Committed by
Gerrit Code Review
BGP connection collision detection.
Change-Id: I124674b79170450409df5d0f4b5fea5f9e11f1d9
Showing
2 changed files
with
80 additions
and
22 deletions
... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment