Shashikanth VH
Committed by Gerrit Code Review

BGP connection collision detection.

Change-Id: I124674b79170450409df5d0f4b5fea5f9e11f1d9
...@@ -151,7 +151,9 @@ class BGPNotificationMsgVer4 implements BGPNotificationMsg { ...@@ -151,7 +151,9 @@ class BGPNotificationMsgVer4 implements BGPNotificationMsg {
151 151
152 @Override 152 @Override
153 public Builder setData(byte[] data) { 153 public Builder setData(byte[] data) {
154 + if (data != null) {
154 this.data = data; 155 this.data = data;
156 + }
155 return this; 157 return this;
156 } 158 }
157 159
......
...@@ -23,8 +23,8 @@ import java.net.SocketAddress; ...@@ -23,8 +23,8 @@ 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.List;
27 import java.util.LinkedList; 26 import java.util.LinkedList;
27 +import java.util.List;
28 import java.util.ListIterator; 28 import java.util.ListIterator;
29 import java.util.concurrent.RejectedExecutionException; 29 import java.util.concurrent.RejectedExecutionException;
30 30
...@@ -153,8 +153,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -153,8 +153,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
153 if (m.getType() != BGPType.OPEN) { 153 if (m.getType() != BGPType.OPEN) {
154 // 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
155 h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, 155 h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR,
156 - BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE, m.getType() 156 + BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE,
157 - .getType()); 157 + m.getType().getType());
158 log.debug("Message is not OPEN message"); 158 log.debug("Message is not OPEN message");
159 } else { 159 } else {
160 log.debug("Sending keep alive message in OPENSENT state"); 160 log.debug("Sending keep alive message in OPENSENT state");
...@@ -165,6 +165,11 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -165,6 +165,11 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
165 165
166 // validate capabilities and open msg 166 // validate capabilities and open msg
167 if (h.openMsgValidation(h, pOpenmsg)) { 167 if (h.openMsgValidation(h, pOpenmsg)) {
168 + if (h.connectionCollisionDetection(BGPPeerCfg.State.OPENCONFIRM,
169 + h.peerIdentifier, h.peerAddr)) {
170 + h.channel.close();
171 + return;
172 + }
168 log.debug("Sending handshake OPEN message"); 173 log.debug("Sending handshake OPEN message");
169 174
170 /* 175 /*
...@@ -203,8 +208,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -203,8 +208,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
203 // check for open message 208 // check for open message
204 if (m.getType() != BGPType.OPEN) { 209 if (m.getType() != BGPType.OPEN) {
205 // When the message type is not open message increment the wrong packet statistics 210 // When the message type is not open message increment the wrong packet statistics
206 - h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, BGPErrorType.UNSPECIFIED_ERROR, m 211 + h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, BGPErrorType.UNSPECIFIED_ERROR,
207 - .getType().getType()); 212 + m.getType().getType());
208 log.debug("Message is not OPEN message"); 213 log.debug("Message is not OPEN message");
209 } else { 214 } else {
210 h.bgpPacketStats.addInPacket(); 215 h.bgpPacketStats.addInPacket();
...@@ -214,6 +219,11 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -214,6 +219,11 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
214 219
215 // Validate open message 220 // Validate open message
216 if (h.openMsgValidation(h, pOpenmsg)) { 221 if (h.openMsgValidation(h, pOpenmsg)) {
222 + if (h.connectionCollisionDetection(BGPPeerCfg.State.OPENSENT,
223 + h.peerIdentifier, h.peerAddr)) {
224 + h.channel.close();
225 + return;
226 + }
217 log.debug("Sending handshake OPEN message"); 227 log.debug("Sending handshake OPEN message");
218 228
219 /* 229 /*
...@@ -237,6 +247,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -237,6 +247,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
237 h.sendHandshakeOpenMessage(); 247 h.sendHandshakeOpenMessage();
238 h.bgpPacketStats.addOutPacket(); 248 h.bgpPacketStats.addOutPacket();
239 h.setState(OPENCONFIRM); 249 h.setState(OPENCONFIRM);
250 + h.bgpconfig.setPeerConnState(h.peerAddr, BGPPeerCfg.State.OPENCONFIRM);
240 } 251 }
241 } 252 }
242 } 253 }
...@@ -250,8 +261,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -250,8 +261,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
250 if (m.getType() != BGPType.KEEP_ALIVE) { 261 if (m.getType() != BGPType.KEEP_ALIVE) {
251 // When the message type is not keep alive message handle the wrong packet 262 // When the message type is not keep alive message handle the wrong packet
252 h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, 263 h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR,
253 - BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE, m.getType() 264 + BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE,
254 - .getType()); 265 + m.getType().getType());
255 log.debug("Message is not KEEPALIVE message"); 266 log.debug("Message is not KEEPALIVE message");
256 } else { 267 } else {
257 268
...@@ -292,13 +303,6 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -292,13 +303,6 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
292 h.setHandshakeComplete(true); 303 h.setHandshakeComplete(true);
293 304
294 if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) { 305 if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) {
295 - /*
296 - * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established
297 - * for detecting which BGP connection is to be preserved when a collision occurs. The convention
298 - * is to compare the BGP Identifiers of the peers involved in the collision and to retain only
299 - * the connection initiated by the BGP speaker with the higher-valued BGP Identifier..
300 - */
301 - // TODO: Connection collision handling.
302 disconnectDuplicate(h); 306 disconnectDuplicate(h);
303 } else { 307 } else {
304 h.setState(ESTABLISHED); 308 h.setState(ESTABLISHED);
...@@ -374,6 +378,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -374,6 +378,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
374 378
375 // Connection should establish only if local ip and Autonomous system number is configured. 379 // Connection should establish only if local ip and Autonomous system number is configured.
376 if (bgpconfig.getState() != BGPCfg.State.IP_AS_CONFIGURED) { 380 if (bgpconfig.getState() != BGPCfg.State.IP_AS_CONFIGURED) {
381 + sendNotification(BGPErrorType.CEASE, BGPErrorType.CONNECTION_REJECTED, null);
377 channel.close(); 382 channel.close();
378 log.info("BGP local AS and router ID not configured"); 383 log.info("BGP local AS and router ID not configured");
379 return; 384 return;
...@@ -385,6 +390,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -385,6 +390,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
385 // if peer is not configured disconnect session 390 // if peer is not configured disconnect session
386 if (!bgpconfig.isPeerConfigured(peerAddr)) { 391 if (!bgpconfig.isPeerConfigured(peerAddr)) {
387 log.debug("Peer is not configured {}", peerAddr); 392 log.debug("Peer is not configured {}", peerAddr);
393 + sendNotification(BGPErrorType.CEASE, BGPErrorType.CONNECTION_REJECTED, null);
388 channel.close(); 394 channel.close();
389 return; 395 return;
390 } 396 }
...@@ -436,6 +442,25 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -436,6 +442,25 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
436 if (bgpPeer != null) { 442 if (bgpPeer != null) {
437 peerManager.removeConnectedPeer(thisbgpId); 443 peerManager.removeConnectedPeer(thisbgpId);
438 } 444 }
445 +
446 + // Retry connection if connection is lost to bgp speaker/peer
447 + if ((channel != null) && (null != channel.getPipeline().get("ActiveHandler"))) {
448 + BgpConnectPeerImpl connectPeer;
449 + BGPPeerCfg.State peerCfgState;
450 +
451 + peerCfgState = bgpconfig.getPeerConnState(peerAddr);
452 + // on session disconnect using configuration, do not retry
453 + if (!peerCfgState.equals(BGPPeerCfg.State.IDLE)) {
454 + log.debug("Connection reset by peer, retry, STATE:{}", peerCfgState);
455 + BGPPeerConfig peerConfig = (BGPPeerConfig) bgpconfig.displayPeers(peerAddr);
456 +
457 + bgpconfig.setPeerConnState(peerAddr, BGPPeerCfg.State.IDLE);
458 + connectPeer = new BgpConnectPeerImpl(bgpController, peerAddr, Controller.getBgpPortNum());
459 + peerConfig.setConnectPeer(connectPeer);
460 + }
461 + } else {
462 + bgpconfig.setPeerConnState(peerAddr, BGPPeerCfg.State.IDLE);
463 + }
439 } else { 464 } else {
440 // A duplicate was disconnected on this ChannelHandler, 465 // A duplicate was disconnected on this ChannelHandler,
441 // this is the same peer reconnecting, but the original state was 466 // this is the same peer reconnecting, but the original state was
...@@ -448,6 +473,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -448,6 +473,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
448 keepAliveTimer.getKeepAliveTimer().cancel(); 473 keepAliveTimer.getKeepAliveTimer().cancel();
449 } 474 }
450 } else { 475 } else {
476 + bgpconfig.setPeerConnState(peerAddr, BGPPeerCfg.State.IDLE);
451 log.warn("No bgp ip in channelHandler registered for " + "disconnected peer {}", getPeerInfoString()); 477 log.warn("No bgp ip in channelHandler registered for " + "disconnected peer {}", getPeerInfoString());
452 } 478 }
453 } 479 }
...@@ -521,6 +547,39 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -521,6 +547,39 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
521 } 547 }
522 } 548 }
523 549
550 + /**
551 + * Check for connection collision.
552 + *
553 + * @param state connection state
554 + * @param peerIdentifier BGP peer identifier
555 + * @param peerAddr BGP peer address
556 + * @return true if bgp spreakers initiated connection
557 + * @throws BGPParseException on error while procession collision detection
558 + * @throws IOException on error while procession collision detection
559 + */
560 + public boolean connectionCollisionDetection(BGPPeerCfg.State state, int peerIdentifier, String peerAddr)
561 + throws IOException, BGPParseException {
562 + /*
563 + * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established for detecting
564 + * which BGP connection is to be preserved when a collision occurs. The convention is to compare the BGP
565 + * Identifiers of the peers involved in the collision and to retain only the connection initiated by the BGP
566 + * speaker with the higher-valued BGP Identifier..
567 + */
568 + BGPPeerCfg.State currentState = bgpconfig.getPeerConnState(peerAddr);
569 + if (currentState.equals(state)) {
570 + if (((Ip4Address.valueOf(bgpconfig.getRouterId())).compareTo(Ip4Address.valueOf(peerIdentifier))) > 0) {
571 + // send notification
572 + sendNotification(BGPErrorType.CEASE, BGPErrorType.CONNECTION_COLLISION_RESOLUTION, null);
573 + log.debug("Connection collision detected, local id: {}, peer id: {}, peer state:{}, in state:{}",
574 + (Ip4Address.valueOf(bgpconfig.getRouterId())), (Ip4Address.valueOf(peerIdentifier)),
575 + currentState, state);
576 + return true;
577 + }
578 + }
579 +
580 + return false;
581 + }
582 +
524 // ************************* 583 // *************************
525 // Channel utility methods 584 // Channel utility methods
526 // ************************* 585 // *************************
...@@ -603,10 +662,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -603,10 +662,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
603 662
604 bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt(); 663 bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt();
605 BGPMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber()) 664 BGPMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber())
606 - .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId) 665 + .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId).setLsCapabilityTlv(bgpconfig.getLsCapability())
607 - .setLsCapabilityTlv(bgpconfig.getLsCapability()) 666 + .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability()).build();
608 - .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability())
609 - .build();
610 log.debug("Sending open message to {}", channel.getRemoteAddress()); 667 log.debug("Sending open message to {}", channel.getRemoteAddress());
611 channel.write(Collections.singletonList(msg)); 668 channel.write(Collections.singletonList(msg));
612 669
...@@ -622,8 +679,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -622,8 +679,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
622 */ 679 */
623 private void sendNotification(byte errorCode, byte errorSubCode, byte[] data) 680 private void sendNotification(byte errorCode, byte errorSubCode, byte[] data)
624 throws IOException, BGPParseException { 681 throws IOException, BGPParseException {
625 - BGPMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode).setErrorSubCode(errorSubCode) 682 + BGPMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode)
626 - .setData(data).build(); 683 + .setErrorSubCode(errorSubCode).setData(data).build();
627 log.debug("Sending notification message to {}", channel.getRemoteAddress()); 684 log.debug("Sending notification message to {}", channel.getRemoteAddress());
628 channel.write(Collections.singletonList(msg)); 685 channel.write(Collections.singletonList(msg));
629 } 686 }
...@@ -757,8 +814,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -757,8 +814,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
757 BGPValueType tlv = unSupportedCaplistIterator.next(); 814 BGPValueType tlv = unSupportedCaplistIterator.next();
758 tlv.write(buffer); 815 tlv.write(buffer);
759 } 816 }
760 - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, 817 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.UNSUPPORTED_CAPABILITY, buffer);
761 - BGPErrorType.UNSUPPORTED_CAPABILITY, buffer);
762 } else { 818 } else {
763 return true; 819 return true;
764 } 820 }
......