Committed by
Gerrit Code Review
[ONOS-2587] BGP send notification to peer on error
Change-Id: I5ff970e4da0d27f062e004c034b4325f0d5ec898
Showing
2 changed files
with
71 additions
and
49 deletions
... | @@ -55,4 +55,20 @@ public final class BGPErrorType { | ... | @@ -55,4 +55,20 @@ public final class BGPErrorType { |
55 | public static final byte OPTIONAL_ATTRIBUTE_ERROR = 9; | 55 | public static final byte OPTIONAL_ATTRIBUTE_ERROR = 9; |
56 | public static final byte INVALID_NETWORK_FIELD = 10; | 56 | public static final byte INVALID_NETWORK_FIELD = 10; |
57 | public static final byte MALFORMED_ASPATH = 11; | 57 | public static final byte MALFORMED_ASPATH = 11; |
58 | + | ||
59 | + //FSM Error subcodes | ||
60 | + public static final byte UNSPECIFIED_ERROR = 0; | ||
61 | + public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE = 1; | ||
62 | + public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE = 2; | ||
63 | + public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_ESTABLISHED_STATE = 3; | ||
64 | + | ||
65 | + //Cease Error subcodes | ||
66 | + public static final byte MAXIMUM_NUMBER_OF_PREFIXES_REACHED = 1; | ||
67 | + public static final byte ADMINISTRATIVE_SHUTDOWN = 2; | ||
68 | + public static final byte PEER_DECONFIGURED = 3; | ||
69 | + public static final byte ADMINISTRATIVE_RESET = 4; | ||
70 | + public static final byte CONNECTION_REJECTED = 5; | ||
71 | + public static final byte OTHER_CONFIGURATION_CHANGE = 6; | ||
72 | + public static final byte CONNECTION_COLLISION_RESOLUTION = 7; | ||
73 | + public static final byte OUT_OF_RESOURCES = 8; | ||
58 | } | 74 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -23,7 +23,6 @@ import java.net.SocketAddress; | ... | @@ -23,7 +23,6 @@ import java.net.SocketAddress; |
23 | import java.net.UnknownHostException; | 23 | import java.net.UnknownHostException; |
24 | import java.nio.channels.ClosedChannelException; | 24 | import java.nio.channels.ClosedChannelException; |
25 | import java.util.Collections; | 25 | import java.util.Collections; |
26 | -import java.util.Date; | ||
27 | import java.util.List; | 26 | import java.util.List; |
28 | import java.util.LinkedList; | 27 | import java.util.LinkedList; |
29 | import java.util.ListIterator; | 28 | import java.util.ListIterator; |
... | @@ -153,7 +152,9 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -153,7 +152,9 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
153 | // check for OPEN message | 152 | // check for OPEN message |
154 | if (m.getType() != BGPType.OPEN) { | 153 | if (m.getType() != BGPType.OPEN) { |
155 | // When the message type is not keep alive message increment the wrong packet statistics | 154 | // When the message type is not keep alive message increment the wrong packet statistics |
156 | - h.processUnknownMsg(); | 155 | + h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, |
156 | + BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE, m.getType() | ||
157 | + .getType()); | ||
157 | log.debug("Message is not OPEN message"); | 158 | log.debug("Message is not OPEN message"); |
158 | } else { | 159 | } else { |
159 | log.debug("Sending keep alive message in OPENSENT state"); | 160 | log.debug("Sending keep alive message in OPENSENT state"); |
... | @@ -202,7 +203,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -202,7 +203,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
202 | // check for open message | 203 | // check for open message |
203 | if (m.getType() != BGPType.OPEN) { | 204 | if (m.getType() != BGPType.OPEN) { |
204 | // When the message type is not open message increment the wrong packet statistics | 205 | // When the message type is not open message increment the wrong packet statistics |
205 | - h.processUnknownMsg(); | 206 | + h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, BGPErrorType.UNSPECIFIED_ERROR, m |
207 | + .getType().getType()); | ||
206 | log.debug("Message is not OPEN message"); | 208 | log.debug("Message is not OPEN message"); |
207 | } else { | 209 | } else { |
208 | h.bgpPacketStats.addInPacket(); | 210 | h.bgpPacketStats.addInPacket(); |
... | @@ -247,7 +249,9 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -247,7 +249,9 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
247 | // check for keep alive message | 249 | // check for keep alive message |
248 | if (m.getType() != BGPType.KEEP_ALIVE) { | 250 | if (m.getType() != BGPType.KEEP_ALIVE) { |
249 | // When the message type is not keep alive message handle the wrong packet | 251 | // When the message type is not keep alive message handle the wrong packet |
250 | - h.processUnknownMsg(); | 252 | + h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, |
253 | + BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE, m.getType() | ||
254 | + .getType()); | ||
251 | log.debug("Message is not KEEPALIVE message"); | 255 | log.debug("Message is not KEEPALIVE message"); |
252 | } else { | 256 | } else { |
253 | 257 | ||
... | @@ -274,11 +278,12 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -274,11 +278,12 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
274 | * time value is zero, then the HoldTimer and KeepaliveTimer are not started. A reasonable maximum | 278 | * time value is zero, then the HoldTimer and KeepaliveTimer are not started. A reasonable maximum |
275 | * time between KEEPALIVE messages would be one third of the Hold Time interval. | 279 | * time between KEEPALIVE messages would be one third of the Hold Time interval. |
276 | */ | 280 | */ |
277 | - h.sendKeepAliveMessage(); | ||
278 | 281 | ||
279 | if (h.negotiatedHoldTime != 0) { | 282 | if (h.negotiatedHoldTime != 0) { |
280 | h.keepAliveTimer = new BGPKeepAliveTimer(h, | 283 | h.keepAliveTimer = new BGPKeepAliveTimer(h, |
281 | (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL)); | 284 | (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL)); |
285 | + } else { | ||
286 | + h.sendKeepAliveMessage(); | ||
282 | } | 287 | } |
283 | 288 | ||
284 | h.bgpPacketStats.addOutPacket(); | 289 | h.bgpPacketStats.addOutPacket(); |
... | @@ -375,8 +380,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -375,8 +380,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
375 | } | 380 | } |
376 | 381 | ||
377 | inetAddress = (InetSocketAddress) address; | 382 | inetAddress = (InetSocketAddress) address; |
378 | - ipAddress = IpAddress.valueOf(inetAddress.getAddress()); | 383 | + peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString(); |
379 | - peerAddr = ipAddress.toString(); | ||
380 | 384 | ||
381 | // if peer is not configured disconnect session | 385 | // if peer is not configured disconnect session |
382 | if (!bgpconfig.isPeerConfigured(peerAddr)) { | 386 | if (!bgpconfig.isPeerConfigured(peerAddr)) { |
... | @@ -418,8 +422,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -418,8 +422,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
418 | } | 422 | } |
419 | 423 | ||
420 | inetAddress = (InetSocketAddress) address; | 424 | inetAddress = (InetSocketAddress) address; |
421 | - ipAddress = IpAddress.valueOf(inetAddress.getAddress()); | 425 | + peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString(); |
422 | - peerAddr = ipAddress.toString(); | ||
423 | 426 | ||
424 | if (thisbgpId != null) { | 427 | if (thisbgpId != null) { |
425 | if (!duplicateBGPIdFound) { | 428 | if (!duplicateBGPIdFound) { |
... | @@ -458,14 +461,14 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -458,14 +461,14 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
458 | if ((ChannelState.OPENWAIT == state) || (ChannelState.OPENSENT == state)) { | 461 | if ((ChannelState.OPENWAIT == state) || (ChannelState.OPENSENT == state)) { |
459 | 462 | ||
460 | // When ReadTimeout timer is expired in OPENWAIT/OPENSENT state, it is considered | 463 | // When ReadTimeout timer is expired in OPENWAIT/OPENSENT state, it is considered |
461 | - // TODO: Send notification | 464 | + sendNotification(BGPErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); |
462 | channel.close(); | 465 | channel.close(); |
463 | state = ChannelState.IDLE; | 466 | state = ChannelState.IDLE; |
464 | return; | 467 | return; |
465 | } else if (ChannelState.OPENCONFIRM == state) { | 468 | } else if (ChannelState.OPENCONFIRM == state) { |
466 | 469 | ||
467 | // When ReadTimeout timer is expired in OPENCONFIRM state. | 470 | // When ReadTimeout timer is expired in OPENCONFIRM state. |
468 | - // TODO: Send Notification | 471 | + sendNotification(BGPErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); |
469 | channel.close(); | 472 | channel.close(); |
470 | state = ChannelState.IDLE; | 473 | state = ChannelState.IDLE; |
471 | return; | 474 | return; |
... | @@ -480,8 +483,17 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -480,8 +483,17 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
480 | } | 483 | } |
481 | channel.close(); | 484 | channel.close(); |
482 | } else if (e.getCause() instanceof BGPParseException) { | 485 | } else if (e.getCause() instanceof BGPParseException) { |
483 | - // TODO: SEND NOTIFICATION | 486 | + byte[] data = new byte[] {}; |
484 | - log.debug("BGP Parse Exception: ", e.getCause()); | 487 | + BGPParseException errMsg = (BGPParseException) e.getCause(); |
488 | + byte errorCode = errMsg.getErrorCode(); | ||
489 | + byte errorSubCode = errMsg.getErrorSubCode(); | ||
490 | + ChannelBuffer tempCb = errMsg.getData(); | ||
491 | + if (tempCb != null) { | ||
492 | + int dataLength = tempCb.capacity(); | ||
493 | + data = new byte[dataLength]; | ||
494 | + tempCb.readBytes(data, 0, dataLength); | ||
495 | + } | ||
496 | + sendNotification(errorCode, errorSubCode, data); | ||
485 | } else if (e.getCause() instanceof RejectedExecutionException) { | 497 | } else if (e.getCause() instanceof RejectedExecutionException) { |
486 | log.warn("Could not process message: queue full"); | 498 | log.warn("Could not process message: queue full"); |
487 | } else { | 499 | } else { |
... | @@ -591,13 +603,32 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -591,13 +603,32 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
591 | 603 | ||
592 | bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt(); | 604 | bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt(); |
593 | BGPMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber()) | 605 | BGPMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber()) |
594 | - .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId).build(); | 606 | + .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId) |
607 | + .setLsCapabilityTlv(bgpconfig.getLsCapability()) | ||
608 | + .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability()) | ||
609 | + .build(); | ||
595 | log.debug("Sending open message to {}", channel.getRemoteAddress()); | 610 | log.debug("Sending open message to {}", channel.getRemoteAddress()); |
596 | channel.write(Collections.singletonList(msg)); | 611 | channel.write(Collections.singletonList(msg)); |
597 | 612 | ||
598 | } | 613 | } |
599 | 614 | ||
600 | /** | 615 | /** |
616 | + * Send notification message to peer. | ||
617 | + * | ||
618 | + * @param errorCode error code send in notification | ||
619 | + * @param errorSubCode sub error code send in notification | ||
620 | + * @param data data to send in notification | ||
621 | + * @throws IOException, BGPParseException while building message | ||
622 | + */ | ||
623 | + private void sendNotification(byte errorCode, byte errorSubCode, byte[] data) | ||
624 | + throws IOException, BGPParseException { | ||
625 | + BGPMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode).setErrorSubCode(errorSubCode) | ||
626 | + .setData(data).build(); | ||
627 | + log.debug("Sending notification message to {}", channel.getRemoteAddress()); | ||
628 | + channel.write(Collections.singletonList(msg)); | ||
629 | + } | ||
630 | + | ||
631 | + /** | ||
601 | * Send keep alive message. | 632 | * Send keep alive message. |
602 | * | 633 | * |
603 | * @throws IOException when channel is disconnected | 634 | * @throws IOException when channel is disconnected |
... | @@ -611,45 +642,20 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { | ... | @@ -611,45 +642,20 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { |
611 | } | 642 | } |
612 | 643 | ||
613 | /** | 644 | /** |
614 | - * Send notification and close channel with peer. | ||
615 | - */ | ||
616 | - private void sendErrNotificationAndCloseChannel() { | ||
617 | - // TODO: send notification | ||
618 | - channel.close(); | ||
619 | - } | ||
620 | - | ||
621 | - /** | ||
622 | * Process unknown BGP message received. | 645 | * Process unknown BGP message received. |
623 | * | 646 | * |
624 | - * @throws BGPParseException when received invalid message | 647 | + * @param errorCode error code |
648 | + * @param errorSubCode error sub code | ||
649 | + * @param data message type | ||
650 | + * @throws BGPParseException while processing error messsage | ||
651 | + * @throws IOException while processing error message | ||
625 | */ | 652 | */ |
626 | - public void processUnknownMsg() throws BGPParseException { | 653 | + public void processUnknownMsg(byte errorCode, byte errorSubCode, byte data) throws BGPParseException, IOException { |
627 | log.debug("UNKNOWN message received"); | 654 | log.debug("UNKNOWN message received"); |
628 | - Date now = null; | 655 | + byte[] byteArray = new byte[1]; |
629 | - if (bgpPacketStats.wrongPacketCount() == 0) { | 656 | + byteArray[0] = data; |
630 | - now = new Date(); | 657 | + sendNotification(errorCode, errorSubCode, byteArray); |
631 | - bgpPacketStats.setTime(now.getTime()); | 658 | + channel.close(); |
632 | - bgpPacketStats.addWrongPacket(); | ||
633 | - sendErrNotificationAndCloseChannel(); | ||
634 | - } | ||
635 | - if (bgpPacketStats.wrongPacketCount() > 1) { | ||
636 | - Date lastest = new Date(); | ||
637 | - bgpPacketStats.addWrongPacket(); | ||
638 | - // converting to seconds | ||
639 | - if (((lastest.getTime() - bgpPacketStats.getTime()) / 1000) > 60) { | ||
640 | - now = lastest; | ||
641 | - bgpPacketStats.setTime(now.getTime()); | ||
642 | - bgpPacketStats.resetWrongPacket(); | ||
643 | - bgpPacketStats.addWrongPacket(); | ||
644 | - } else if (((int) (lastest.getTime() - now.getTime()) / 1000) < 60) { | ||
645 | - if (MAX_WRONG_COUNT_PACKET <= bgpPacketStats.wrongPacketCount()) { | ||
646 | - // reset once wrong packet count reaches MAX_WRONG_COUNT_PACKET | ||
647 | - bgpPacketStats.resetWrongPacket(); | ||
648 | - // max wrong packets received send error message and close the session | ||
649 | - sendErrNotificationAndCloseChannel(); | ||
650 | - } | ||
651 | - } | ||
652 | - } | ||
653 | } | 659 | } |
654 | 660 | ||
655 | /** | 661 | /** | ... | ... |
-
Please register or login to post a comment