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