Shashikanth VH
Committed by Gerrit Code Review

[ONOS-2587] BGP send notification to peer on error

Change-Id: I5ff970e4da0d27f062e004c034b4325f0d5ec898
...@@ -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 /**
......