diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2015-12-01 05:49:27 -0800 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2015-12-01 05:49:27 -0800 |
commit | e63291850fd0795c5700e25e67e5dee89ba54c5f (patch) | |
tree | 9707289536ad95bb739c9856761ad43275e07d8c /framework/src/onos/bgp/ctl | |
parent | 671823e12bc13be9a8b87a5d7de33da1bb7a44e8 (diff) |
onos commit hash c2999f30c69e50df905a9d175ef80b3f23a98514
Change-Id: I2bb8562c4942b6d6a6d60b663db2e17540477b81
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/bgp/ctl')
21 files changed, 2574 insertions, 396 deletions
diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java new file mode 100644 index 00000000..9cbfbf65 --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java @@ -0,0 +1,132 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Map; +import java.util.TreeMap; + +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Adj-RIB-In for each peer. + */ +public class AdjRibIn { + private Map<BgpNodeLSIdentifier, PathAttrNlriDetails> nodeTree = new TreeMap<>(); + private Map<BgpLinkLSIdentifier, PathAttrNlriDetails> linkTree = new TreeMap<>(); + private Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefixTree = new TreeMap<>(); + + /** + * Returns the adjacency node. + * + * @return node adjacency RIB node + */ + public Map<BgpNodeLSIdentifier, PathAttrNlriDetails> nodeTree() { + return nodeTree; + } + + /** + * Returns the adjacency link. + * + * @return link adjacency RIB node + */ + public Map<BgpLinkLSIdentifier, PathAttrNlriDetails> linkTree() { + return linkTree; + } + + /** + * Returns the adjacency prefix. + * + * @return prefix adjacency RIB node + */ + public Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefixTree() { + return prefixTree; + } + + /** + * Update nlri identifier into the tree if nlri identifier exists in tree otherwise add this to the tree. + * + * @param nlri NLRI Info + * @param details has pathattribute , protocolID and identifier + */ + public void add(BgpLSNlri nlri, PathAttrNlriDetails details) { + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.replace(nodeLSIdentifier, details); + } else { + nodeTree.put(nodeLSIdentifier, details); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.replace(linkLSIdentifier, details); + } else { + linkTree.put(linkLSIdentifier, details); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.replace(prefixIdentifier, details); + } else { + prefixTree.put(prefixIdentifier, details); + } + } + } + + /** + * Removes nlri identifier if it exists in the adjacency tree. + * + * @param nlri NLRI Info + */ + public void remove(BgpLSNlri nlri) { + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.remove(nodeLSIdentifier); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.remove(linkLSIdentifier); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.remove(prefixIdentifier); + } + } + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("nodeTree", nodeTree) + .add("linkTree", linkTree) + .add("prefixTree", prefixTree) + .toString(); + } +}
\ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerImpl.java deleted file mode 100755 index 45f74634..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerImpl.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - -import org.jboss.netty.channel.Channel; -import org.onlab.packet.IpAddress; -import org.onosproject.bgp.controller.BGPController; -import org.onosproject.bgp.controller.BGPPeer; -import org.onosproject.bgp.controller.BgpSessionInfo; -import org.onosproject.bgpio.protocol.BGPFactories; -import org.onosproject.bgpio.protocol.BGPFactory; -import org.onosproject.bgpio.protocol.BGPMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * BGPPeerImpl implements BGPPeer, maintains peer information and store updates in RIB . - */ -public class BGPPeerImpl implements BGPPeer { - - protected final Logger log = LoggerFactory.getLogger(BGPPeerImpl.class); - - private static final String SHUTDOWN_MSG = "Worker has already been shutdown"; - - private BGPController bgpController; - private Channel channel; - protected String channelId; - private boolean connected; - protected boolean isHandShakeComplete = false; - private BgpSessionInfo sessionInfo; - private BGPPacketStatsImpl pktStats; - - - @Override - public BgpSessionInfo sessionInfo() { - return sessionInfo; - } - - /** - * Initialize peer. - * - *@param bgpController controller instance - *@param sessionInfo bgp session info - *@param pktStats packet statistics - */ - public BGPPeerImpl(BGPController bgpController, BgpSessionInfo sessionInfo, BGPPacketStatsImpl pktStats) { - this.bgpController = bgpController; - this.sessionInfo = sessionInfo; - this.pktStats = pktStats; - } - - // ************************ - // Channel related - // ************************ - - @Override - public final void disconnectPeer() { - this.channel.close(); - } - - @Override - public final void sendMessage(BGPMessage m) { - log.debug("Sending message to {}", channel.getRemoteAddress()); - try { - channel.write(Collections.singletonList(m)); - this.pktStats.addOutPacket(); - } catch (RejectedExecutionException e) { - log.warn(e.getMessage()); - if (!e.getMessage().contains(SHUTDOWN_MSG)) { - throw e; - } - } - } - - @Override - public final void sendMessage(List<BGPMessage> msgs) { - try { - channel.write(msgs); - this.pktStats.addOutPacket(msgs.size()); - } catch (RejectedExecutionException e) { - log.warn(e.getMessage()); - if (!e.getMessage().contains(SHUTDOWN_MSG)) { - throw e; - } - } - } - - @Override - public final boolean isConnected() { - return this.connected; - } - - @Override - public final void setConnected(boolean connected) { - this.connected = connected; - }; - - @Override - public final void setChannel(Channel channel) { - this.channel = channel; - final SocketAddress address = channel.getRemoteAddress(); - if (address instanceof InetSocketAddress) { - final InetSocketAddress inetAddress = (InetSocketAddress) address; - final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress()); - if (ipAddress.isIp4()) { - channelId = ipAddress.toString() + ':' + inetAddress.getPort(); - } else { - channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort(); - } - } - }; - - @Override - public final Channel getChannel() { - return this.channel; - }; - - @Override - public String channelId() { - return channelId; - } - - @Override - public BGPFactory factory() { - return BGPFactories.getFactory(sessionInfo.remoteBgpVersion()); - } - - @Override - public boolean isHandshakeComplete() { - return isHandShakeComplete; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("channel", channelId()) - .add("bgpId", sessionInfo().remoteBgpId()).toString(); - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPChannelHandler.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java index f21c311c..8754563d 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPChannelHandler.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java @@ -23,8 +23,8 @@ import java.net.SocketAddress; import java.net.UnknownHostException; import java.nio.channels.ClosedChannelException; import java.util.Collections; -import java.util.List; import java.util.LinkedList; +import java.util.List; import java.util.ListIterator; import java.util.concurrent.RejectedExecutionException; @@ -40,20 +40,20 @@ import org.jboss.netty.handler.timeout.ReadTimeoutException; import org.jboss.netty.handler.timeout.ReadTimeoutHandler; import org.onlab.packet.Ip4Address; import org.onlab.packet.IpAddress; -import org.onosproject.bgp.controller.BGPCfg; -import org.onosproject.bgp.controller.BGPController; -import org.onosproject.bgp.controller.BGPId; -import org.onosproject.bgp.controller.BGPPeer; -import org.onosproject.bgp.controller.BGPPeerCfg; -import org.onosproject.bgp.controller.impl.BGPControllerImpl.BGPPeerManagerImpl; -import org.onosproject.bgpio.exceptions.BGPParseException; -import org.onosproject.bgpio.protocol.BGPFactory; -import org.onosproject.bgpio.protocol.BGPMessage; -import org.onosproject.bgpio.protocol.BGPOpenMsg; -import org.onosproject.bgpio.protocol.BGPType; -import org.onosproject.bgpio.protocol.BGPVersion; -import org.onosproject.bgpio.types.BGPErrorType; -import org.onosproject.bgpio.types.BGPValueType; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpPeerCfg; +import org.onosproject.bgp.controller.impl.BgpControllerImpl.BgpPeerManagerImpl; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.BgpOpenMsg; +import org.onosproject.bgpio.protocol.BgpType; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; import org.slf4j.Logger; @@ -62,20 +62,20 @@ import org.slf4j.LoggerFactory; /** * Channel handler deals with the bgp peer connection and dispatches messages from peer to the appropriate locations. */ -class BGPChannelHandler extends IdleStateAwareChannelHandler { +class BgpChannelHandler extends IdleStateAwareChannelHandler { - private static final Logger log = LoggerFactory.getLogger(BGPChannelHandler.class); + private static final Logger log = LoggerFactory.getLogger(BgpChannelHandler.class); static final int BGP_MIN_HOLDTIME = 3; static final int BGP_MAX_KEEPALIVE_INTERVAL = 3; - private BGPPeer bgpPeer; - private BGPId thisbgpId; + private BgpPeer bgpPeer; + private BgpId thisbgpId; private Channel channel; - private BGPKeepAliveTimer keepAliveTimer = null; + private BgpKeepAliveTimer keepAliveTimer = null; private short peerHoldTime = 0; private short negotiatedHoldTime = 0; private long peerAsNum; private int peerIdentifier; - private BGPPacketStatsImpl bgpPacketStats; + private BgpPacketStatsImpl bgpPacketStats; static final int MAX_WRONG_COUNT_PACKET = 5; static final byte MULTI_PROTOCOL_EXTN_CAPA_TYPE = 1; static final byte FOUR_OCTET_AS_NUM_CAPA_TYPE = 65; @@ -97,30 +97,30 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { // peer state for the older (still connected) peer private volatile Boolean duplicateBGPIdFound; // Indicates the bgp version used by this bgp peer - protected BGPVersion bgpVersion; - private BGPController bgpController; - protected BGPFactory factory4; + protected BgpVersion bgpVersion; + private BgpController bgpController; + protected BgpFactory factory4; private boolean isIbgpSession; private BgpSessionInfoImpl sessionInfo; - private BGPPeerManagerImpl peerManager; + private BgpPeerManagerImpl peerManager; private InetSocketAddress inetAddress; private IpAddress ipAddress; private SocketAddress address; private String peerAddr; - private BGPCfg bgpconfig; + private BgpCfg bgpconfig; /** * Create a new unconnected BGPChannelHandler. * * @param bgpController bgp controller */ - BGPChannelHandler(BGPController bgpController) { + BgpChannelHandler(BgpController bgpController) { this.bgpController = bgpController; - this.peerManager = (BGPPeerManagerImpl) bgpController.peerManager(); + this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager(); this.state = ChannelState.IDLE; - this.factory4 = Controller.getBGPMessageFactory4(); + this.factory4 = Controller.getBgpMessageFactory4(); this.duplicateBGPIdFound = Boolean.FALSE; - this.bgpPacketStats = new BGPPacketStatsImpl(); + this.bgpPacketStats = new BgpPacketStatsImpl(); this.bgpconfig = bgpController.getConfig(); } @@ -147,24 +147,29 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { OPENSENT(false) { @Override - void processBGPMessage(BGPChannelHandler h, BGPMessage m) throws IOException, BGPParseException { + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { log.debug("message received in OPENSENT state"); // check for OPEN message - if (m.getType() != BGPType.OPEN) { + if (m.getType() != BgpType.OPEN) { // When the message type is not keep alive message increment the wrong packet statistics - h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, - BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE, m.getType() - .getType()); + h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, + BgpErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE, + m.getType().getType()); log.debug("Message is not OPEN message"); } else { log.debug("Sending keep alive message in OPENSENT state"); h.bgpPacketStats.addInPacket(); - BGPOpenMsg pOpenmsg = (BGPOpenMsg) m; + BgpOpenMsg pOpenmsg = (BgpOpenMsg) m; h.peerIdentifier = pOpenmsg.getBgpId(); // validate capabilities and open msg if (h.openMsgValidation(h, pOpenmsg)) { + if (h.connectionCollisionDetection(BgpPeerCfg.State.OPENCONFIRM, + h.peerIdentifier, h.peerAddr)) { + h.channel.close(); + return; + } log.debug("Sending handshake OPEN message"); /* @@ -176,7 +181,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { if (h.peerHoldTime < h.bgpconfig.getHoldTime()) { h.channel.getPipeline().replace("holdTime", "holdTime", - new ReadTimeoutHandler(BGPPipelineFactory.TIMER, + new ReadTimeoutHandler(BgpPipelineFactory.TIMER, h.peerHoldTime)); } @@ -190,30 +195,35 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { h.sendKeepAliveMessage(); h.bgpPacketStats.addOutPacket(); h.setState(OPENCONFIRM); - h.bgpconfig.setPeerConnState(h.peerAddr, BGPPeerCfg.State.OPENCONFIRM); + h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM); } } }, OPENWAIT(false) { @Override - void processBGPMessage(BGPChannelHandler h, BGPMessage m) throws IOException, BGPParseException { + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { log.debug("Message received in OPEN WAIT State"); // check for open message - if (m.getType() != BGPType.OPEN) { + if (m.getType() != BgpType.OPEN) { // When the message type is not open message increment the wrong packet statistics - h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, BGPErrorType.UNSPECIFIED_ERROR, m - .getType().getType()); + h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, BgpErrorType.UNSPECIFIED_ERROR, + m.getType().getType()); log.debug("Message is not OPEN message"); } else { h.bgpPacketStats.addInPacket(); - BGPOpenMsg pOpenmsg = (BGPOpenMsg) m; + BgpOpenMsg pOpenmsg = (BgpOpenMsg) m; h.peerIdentifier = pOpenmsg.getBgpId(); // Validate open message if (h.openMsgValidation(h, pOpenmsg)) { + if (h.connectionCollisionDetection(BgpPeerCfg.State.OPENSENT, + h.peerIdentifier, h.peerAddr)) { + h.channel.close(); + return; + } log.debug("Sending handshake OPEN message"); /* @@ -225,7 +235,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { if (h.peerHoldTime < h.bgpconfig.getHoldTime()) { h.channel.getPipeline().replace("holdTime", "holdTime", - new ReadTimeoutHandler(BGPPipelineFactory.TIMER, + new ReadTimeoutHandler(BgpPipelineFactory.TIMER, h.peerHoldTime)); } @@ -237,6 +247,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { h.sendHandshakeOpenMessage(); h.bgpPacketStats.addOutPacket(); h.setState(OPENCONFIRM); + h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM); } } } @@ -244,14 +255,14 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { OPENCONFIRM(false) { @Override - void processBGPMessage(BGPChannelHandler h, BGPMessage m) throws IOException, BGPParseException { + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { log.debug("Message received in OPENCONFIRM state"); // check for keep alive message - if (m.getType() != BGPType.KEEP_ALIVE) { + if (m.getType() != BgpType.KEEP_ALIVE) { // When the message type is not keep alive message handle the wrong packet - h.processUnknownMsg(BGPErrorType.FINITE_STATE_MACHINE_ERROR, - BGPErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE, m.getType() - .getType()); + h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, + BgpErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE, + m.getType().getType()); log.debug("Message is not KEEPALIVE message"); } else { @@ -260,7 +271,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { log.debug("Sending keep alive message in OPENCONFIRM state"); final InetSocketAddress inetAddress = (InetSocketAddress) h.address; - h.thisbgpId = BGPId.bgpId(IpAddress.valueOf(inetAddress.getAddress())); + h.thisbgpId = BgpId.bgpId(IpAddress.valueOf(inetAddress.getAddress())); // set session parameters h.negotiatedHoldTime = (h.peerHoldTime < h.bgpconfig.getHoldTime()) ? h.peerHoldTime @@ -268,7 +279,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { h.sessionInfo = new BgpSessionInfoImpl(h.thisbgpId, h.bgpVersion, h.peerAsNum, h.peerHoldTime, h.peerIdentifier, h.negotiatedHoldTime, h.isIbgpSession); - h.bgpPeer = h.peerManager.getBGPPeerInstance(h.bgpController, h.sessionInfo, h.bgpPacketStats); + h.bgpPeer = h.peerManager.getBgpPeerInstance(h.bgpController, h.sessionInfo, h.bgpPacketStats); // set the status of bgp as connected h.bgpPeer.setConnected(true); h.bgpPeer.setChannel(h.channel); @@ -280,8 +291,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { */ if (h.negotiatedHoldTime != 0) { - h.keepAliveTimer = new BGPKeepAliveTimer(h, - (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL)); + h.keepAliveTimer = new BgpKeepAliveTimer(h, + (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL)); } else { h.sendKeepAliveMessage(); } @@ -292,17 +303,10 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { h.setHandshakeComplete(true); if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) { - /* - * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established - * for detecting which BGP connection is to be preserved when a collision occurs. The convention - * is to compare the BGP Identifiers of the peers involved in the collision and to retain only - * the connection initiated by the BGP speaker with the higher-valued BGP Identifier.. - */ - // TODO: Connection collision handling. disconnectDuplicate(h); } else { h.setState(ESTABLISHED); - h.bgpconfig.setPeerConnState(h.peerAddr, BGPPeerCfg.State.ESTABLISHED); + h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.ESTABLISHED); } } } @@ -310,7 +314,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ESTABLISHED(true) { @Override - void processBGPMessage(BGPChannelHandler h, BGPMessage m) throws IOException, BGPParseException { + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { log.debug("Message received in established state " + m.getType()); // dispatch the message h.dispatchMessage(m); @@ -337,7 +341,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * * @param h channel handler */ - protected void disconnectDuplicate(BGPChannelHandler h) { + protected void disconnectDuplicate(BgpChannelHandler h) { log.error("Duplicated BGP IP or incompleted cleanup - " + "" + "disconnecting channel {}", h.getPeerInfoString()); h.duplicateBGPIdFound = Boolean.TRUE; @@ -349,8 +353,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { this.handshakeComplete = handshakeComplete; } - void processBGPMessage(BGPChannelHandler bgpChannelHandler, BGPMessage pm) - throws IOException, BGPParseException { + void processBgpMessage(BgpChannelHandler bgpChannelHandler, BgpMessage pm) + throws IOException, BgpParseException { // TODO Auto-generated method stub log.debug("BGP message stub"); } @@ -373,7 +377,8 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { } // Connection should establish only if local ip and Autonomous system number is configured. - if (bgpconfig.getState() != BGPCfg.State.IP_AS_CONFIGURED) { + if (bgpconfig.getState() != BgpCfg.State.IP_AS_CONFIGURED) { + sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_REJECTED, null); channel.close(); log.info("BGP local AS and router ID not configured"); return; @@ -385,12 +390,13 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { // if peer is not configured disconnect session if (!bgpconfig.isPeerConfigured(peerAddr)) { log.debug("Peer is not configured {}", peerAddr); + sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_REJECTED, null); channel.close(); return; } // if connection is already established close channel - if (peerManager.isPeerConnected(BGPId.bgpId(IpAddress.valueOf(peerAddr)))) { + if (peerManager.isPeerConnected(BgpId.bgpId(IpAddress.valueOf(peerAddr)))) { log.debug("Duplicate connection received, peer {}", peerAddr); channel.close(); return; @@ -406,7 +412,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { sendHandshakeOpenMessage(); bgpPacketStats.addOutPacket(); setState(ChannelState.OPENSENT); - bgpconfig.setPeerConnState(peerAddr, BGPPeerCfg.State.OPENSENT); + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.OPENSENT); } } @@ -436,6 +442,25 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { if (bgpPeer != null) { peerManager.removeConnectedPeer(thisbgpId); } + + // Retry connection if connection is lost to bgp speaker/peer + if ((channel != null) && (null != channel.getPipeline().get("ActiveHandler"))) { + BgpConnectPeerImpl connectPeer; + BgpPeerCfg.State peerCfgState; + + peerCfgState = bgpconfig.getPeerConnState(peerAddr); + // on session disconnect using configuration, do not retry + if (!peerCfgState.equals(BgpPeerCfg.State.IDLE)) { + log.debug("Connection reset by peer, retry, STATE:{}", peerCfgState); + BgpPeerConfig peerConfig = (BgpPeerConfig) bgpconfig.displayPeers(peerAddr); + + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); + connectPeer = new BgpConnectPeerImpl(bgpController, peerAddr, Controller.getBgpPortNum()); + peerConfig.setConnectPeer(connectPeer); + } + } else { + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); + } } else { // A duplicate was disconnected on this ChannelHandler, // this is the same peer reconnecting, but the original state was @@ -448,6 +473,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { keepAliveTimer.getKeepAliveTimer().cancel(); } } else { + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); log.warn("No bgp ip in channelHandler registered for " + "disconnected peer {}", getPeerInfoString()); } } @@ -461,14 +487,14 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { if ((ChannelState.OPENWAIT == state) || (ChannelState.OPENSENT == state)) { // When ReadTimeout timer is expired in OPENWAIT/OPENSENT state, it is considered - sendNotification(BGPErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); + sendNotification(BgpErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); channel.close(); state = ChannelState.IDLE; return; } else if (ChannelState.OPENCONFIRM == state) { // When ReadTimeout timer is expired in OPENCONFIRM state. - sendNotification(BGPErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); + sendNotification(BgpErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); channel.close(); state = ChannelState.IDLE; return; @@ -482,9 +508,9 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { log.debug("StackTrace for previous Exception: ", e.getCause()); } channel.close(); - } else if (e.getCause() instanceof BGPParseException) { + } else if (e.getCause() instanceof BgpParseException) { byte[] data = new byte[] {}; - BGPParseException errMsg = (BGPParseException) e.getCause(); + BgpParseException errMsg = (BgpParseException) e.getCause(); byte errorCode = errMsg.getErrorCode(); byte errorSubCode = errMsg.getErrorSubCode(); ChannelBuffer tempCb = errMsg.getData(); @@ -511,14 +537,47 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (e.getMessage() instanceof List) { @SuppressWarnings("Unchecked") - List<BGPMessage> msglist = (List<BGPMessage>) e.getMessage(); - for (BGPMessage pm : msglist) { + List<BgpMessage> msglist = (List<BgpMessage>) e.getMessage(); + for (BgpMessage pm : msglist) { // Do the actual packet processing - state.processBGPMessage(this, pm); + state.processBgpMessage(this, pm); } } else { - state.processBGPMessage(this, (BGPMessage) e.getMessage()); + state.processBgpMessage(this, (BgpMessage) e.getMessage()); + } + } + + /** + * Check for connection collision. + * + * @param state connection state + * @param peerIdentifier BGP peer identifier + * @param peerAddr BGP peer address + * @return true if bgp spreakers initiated connection + * @throws BgpParseException on error while procession collision detection + * @throws IOException on error while procession collision detection + */ + public boolean connectionCollisionDetection(BgpPeerCfg.State state, int peerIdentifier, String peerAddr) + throws IOException, BgpParseException { + /* + * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established for detecting + * which BGP connection is to be preserved when a collision occurs. The convention is to compare the BGP + * Identifiers of the peers involved in the collision and to retain only the connection initiated by the BGP + * speaker with the higher-valued BGP Identifier.. + */ + BgpPeerCfg.State currentState = bgpconfig.getPeerConnState(peerAddr); + if (currentState.equals(state)) { + if (((Ip4Address.valueOf(bgpconfig.getRouterId())).compareTo(Ip4Address.valueOf(peerIdentifier))) > 0) { + // send notification + sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_COLLISION_RESOLUTION, null); + log.debug("Connection collision detected, local id: {}, peer id: {}, peer state:{}, in state:{}", + (Ip4Address.valueOf(bgpconfig.getRouterId())), (Ip4Address.valueOf(peerIdentifier)), + currentState, state); + return true; + } } + + return false; } // ************************* @@ -546,9 +605,9 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * To handle the BGP message. * * @param m bgp message - * @throws BGPParseException throw exception + * @throws BgpParseException throw exception */ - private void dispatchMessage(BGPMessage m) throws BGPParseException { + private void dispatchMessage(BgpMessage m) throws BgpParseException { bgpPacketStats.addInPacket(); bgpController.processBGPPacket(thisbgpId, m); } @@ -589,24 +648,22 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * * @return packet statistics */ - public BGPPacketStatsImpl getBgpPacketStats() { + public BgpPacketStatsImpl getBgpPacketStats() { return bgpPacketStats; } /** * Send handshake open message to the peer. * - * @throws IOException, BGPParseException + * @throws IOException, BgpParseException */ - private void sendHandshakeOpenMessage() throws IOException, BGPParseException { + private void sendHandshakeOpenMessage() throws IOException, BgpParseException { int bgpId; bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt(); - BGPMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber()) - .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId) - .setLsCapabilityTlv(bgpconfig.getLsCapability()) - .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability()) - .build(); + BgpMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber()) + .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId).setLsCapabilityTlv(bgpconfig.getLsCapability()) + .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability()).build(); log.debug("Sending open message to {}", channel.getRemoteAddress()); channel.write(Collections.singletonList(msg)); @@ -618,12 +675,12 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * @param errorCode error code send in notification * @param errorSubCode sub error code send in notification * @param data data to send in notification - * @throws IOException, BGPParseException while building message + * @throws IOException, BgpParseException while building message */ private void sendNotification(byte errorCode, byte errorSubCode, byte[] data) - throws IOException, BGPParseException { - BGPMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode).setErrorSubCode(errorSubCode) - .setData(data).build(); + throws IOException, BgpParseException { + BgpMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode) + .setErrorSubCode(errorSubCode).setData(data).build(); log.debug("Sending notification message to {}", channel.getRemoteAddress()); channel.write(Collections.singletonList(msg)); } @@ -632,11 +689,11 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * Send keep alive message. * * @throws IOException when channel is disconnected - * @throws BGPParseException while building keep alive message + * @throws BgpParseException while building keep alive message */ - synchronized void sendKeepAliveMessage() throws IOException, BGPParseException { + synchronized void sendKeepAliveMessage() throws IOException, BgpParseException { - BGPMessage msg = factory4.keepaliveMessageBuilder().build(); + BgpMessage msg = factory4.keepaliveMessageBuilder().build(); log.debug("Sending keepalive message to {}", channel.getRemoteAddress()); channel.write(Collections.singletonList(msg)); } @@ -647,10 +704,10 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * @param errorCode error code * @param errorSubCode error sub code * @param data message type - * @throws BGPParseException while processing error messsage + * @throws BgpParseException while processing error messsage * @throws IOException while processing error message */ - public void processUnknownMsg(byte errorCode, byte errorSubCode, byte data) throws BGPParseException, IOException { + public void processUnknownMsg(byte errorCode, byte errorSubCode, byte data) throws BgpParseException, IOException { log.debug("UNKNOWN message received"); byte[] byteArray = new byte[1]; byteArray[0] = data; @@ -664,26 +721,26 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * @param h channel handler * @param openMsg open message * @return true if valid message, otherwise false - * @throws BGPParseException throw exception + * @throws BgpParseException throw exception */ - public boolean openMsgValidation(BGPChannelHandler h, BGPOpenMsg openMsg) throws BGPParseException { + public boolean openMsgValidation(BgpChannelHandler h, BgpOpenMsg openMsg) throws BgpParseException { boolean result; // Validate BGP ID result = bgpIdValidation(openMsg); if (!result) { - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_BGP_IDENTIFIER, null); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_BGP_IDENTIFIER, null); } // Validate AS number result = asNumberValidation(h, openMsg); if (!result) { - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_PEER_AS, null); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); } // Validate hold timer if ((openMsg.getHoldTime() != 0) && (openMsg.getHoldTime() < BGP_MIN_HOLDTIME)) { - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.UNACCEPTABLE_HOLD_TIME, null); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNACCEPTABLE_HOLD_TIME, null); } // Validate capabilities @@ -697,25 +754,25 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * @param h channel handler * @param openmsg open message * @return success or failure - * @throws BGPParseException + * @throws BgpParseException */ - private boolean capabilityValidation(BGPChannelHandler h, BGPOpenMsg openmsg) throws BGPParseException { + private boolean capabilityValidation(BgpChannelHandler h, BgpOpenMsg openmsg) throws BgpParseException { log.debug("capabilityValidation"); boolean isMultiProtocolcapabilityExists = false; boolean isFourOctetCapabilityExits = false; int capAsNum = 0; - List<BGPValueType> capabilityTlv = openmsg.getCapabilityTlv(); - ListIterator<BGPValueType> listIterator = capabilityTlv.listIterator(); - List<BGPValueType> unSupportedCapabilityTlv = new LinkedList<>(); - ListIterator<BGPValueType> unSupportedCaplistIterator = unSupportedCapabilityTlv.listIterator(); - BGPValueType tempTlv; + List<BgpValueType> capabilityTlv = openmsg.getCapabilityTlv(); + ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator(); + List<BgpValueType> unSupportedCapabilityTlv = new LinkedList<>(); + ListIterator<BgpValueType> unSupportedCaplistIterator = unSupportedCapabilityTlv.listIterator(); + BgpValueType tempTlv; boolean isLargeAsCapabilityCfg = h.bgpconfig.getLargeASCapability(); boolean isLsCapabilityCfg = h.bgpconfig.getLsCapability(); while (listIterator.hasNext()) { - BGPValueType tlv = listIterator.next(); + BgpValueType tlv = listIterator.next(); if (tlv.getType() == MULTI_PROTOCOL_EXTN_CAPA_TYPE) { isMultiProtocolcapabilityExists = true; } @@ -728,11 +785,11 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { if (isFourOctetCapabilityExits) { if (capAsNum > MAX_AS2_NUM) { if (openmsg.getAsNumber() != AS_TRANS) { - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_PEER_AS, null); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); } } else { if (capAsNum != openmsg.getAsNumber()) { - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_PEER_AS, null); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); } } } @@ -754,11 +811,10 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { if (unSupportedCaplistIterator.hasNext()) { ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); while (unSupportedCaplistIterator.hasNext()) { - BGPValueType tlv = unSupportedCaplistIterator.next(); + BgpValueType tlv = unSupportedCaplistIterator.next(); tlv.write(buffer); } - throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, - BGPErrorType.UNSUPPORTED_CAPABILITY, buffer); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNSUPPORTED_CAPABILITY, buffer); } else { return true; } @@ -771,18 +827,18 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * @param openMsg open message * @return true or false */ - private boolean asNumberValidation(BGPChannelHandler h, BGPOpenMsg openMsg) { + private boolean asNumberValidation(BgpChannelHandler h, BgpOpenMsg openMsg) { log.debug("AS Num validation"); int capAsNum = 0; boolean isFourOctetCapabilityExits = false; - BGPPeerCfg peerCfg = h.bgpconfig.displayPeers(peerAddr); - List<BGPValueType> capabilityTlv = openMsg.getCapabilityTlv(); - ListIterator<BGPValueType> listIterator = capabilityTlv.listIterator(); + BgpPeerCfg peerCfg = h.bgpconfig.displayPeers(peerAddr); + List<BgpValueType> capabilityTlv = openMsg.getCapabilityTlv(); + ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator(); while (listIterator.hasNext()) { - BGPValueType tlv = listIterator.next(); + BgpValueType tlv = listIterator.next(); if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { isFourOctetCapabilityExits = true; capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); @@ -838,7 +894,7 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { * @param openMsg open message * @return true or false */ - private boolean bgpIdValidation(BGPOpenMsg openMsg) { + private boolean bgpIdValidation(BgpOpenMsg openMsg) { String openMsgBgpId = Ip4Address.valueOf(openMsg.getBgpId()).toString(); InetAddress ipAddress; diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPConfig.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java index 56877a16..716cc0c5 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPConfig.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java @@ -21,17 +21,17 @@ import java.util.Set; import java.util.TreeMap; import org.onlab.packet.Ip4Address; -import org.onosproject.bgp.controller.BGPCfg; -import org.onosproject.bgp.controller.BGPPeerCfg; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpPeerCfg; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Provides BGP configuration of this BGP speaker. */ -public class BGPConfig implements BGPCfg { +public class BgpConfig implements BgpCfg { - protected static final Logger log = LoggerFactory.getLogger(BGPConfig.class); + protected static final Logger log = LoggerFactory.getLogger(BgpConfig.class); private static final short DEFAULT_HOLD_TIMER = 120; private static final short DEFAULT_CONN_RETRY_TIME = 120; @@ -47,12 +47,12 @@ public class BGPConfig implements BGPCfg { private int maxConnRetryCount; private Ip4Address routerId = null; - private TreeMap<String, BGPPeerCfg> bgpPeerTree = new TreeMap<>(); + private TreeMap<String, BgpPeerCfg> bgpPeerTree = new TreeMap<>(); /** * Constructor to initialize the values. */ - public BGPConfig() { + public BgpConfig() { this.holdTime = DEFAULT_HOLD_TIMER; this.maxConnRetryTime = DEFAULT_CONN_RETRY_TIME; @@ -142,13 +142,13 @@ public class BGPConfig implements BGPCfg { @Override public boolean addPeer(String routerid, int remoteAs, short holdTime) { - BGPPeerConfig lspeer = new BGPPeerConfig(); + BgpPeerConfig lspeer = new BgpPeerConfig(); if (this.bgpPeerTree.get(routerid) == null) { lspeer.setPeerRouterId(routerid); lspeer.setAsNumber(remoteAs); lspeer.setHoldtime(holdTime); - lspeer.setState(BGPPeerCfg.State.IDLE); + lspeer.setState(BgpPeerCfg.State.IDLE); lspeer.setSelfInnitConnection(false); if (this.getAsNumber() == remoteAs) { @@ -168,7 +168,7 @@ public class BGPConfig implements BGPCfg { @Override public boolean connectPeer(String routerid) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); if (lspeer != null) { lspeer.setSelfInnitConnection(true); @@ -181,7 +181,7 @@ public class BGPConfig implements BGPCfg { @Override public boolean removePeer(String routerid) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); if (lspeer != null) { @@ -200,12 +200,12 @@ public class BGPConfig implements BGPCfg { @Override public boolean disconnectPeer(String routerid) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); if (lspeer != null) { //TODO DISCONNECT PEER - lspeer.setState(BGPPeerCfg.State.IDLE); + lspeer.setState(BgpPeerCfg.State.IDLE); lspeer.setSelfInnitConnection(false); log.debug("Disconnected : " + routerid + " successfully"); @@ -217,8 +217,8 @@ public class BGPConfig implements BGPCfg { } @Override - public void setPeerConnState(String routerid, BGPPeerCfg.State state) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + public void setPeerConnState(String routerid, BgpPeerCfg.State state) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); if (lspeer != null) { lspeer.setState(state); @@ -232,21 +232,21 @@ public class BGPConfig implements BGPCfg { } @Override - public BGPPeerCfg.State getPeerConnState(String routerid) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + public BgpPeerCfg.State getPeerConnState(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); if (lspeer != null) { return lspeer.getState(); } else { - return BGPPeerCfg.State.INVALID; //No instance + return BgpPeerCfg.State.INVALID; //No instance } } @Override public boolean isPeerConnectable(String routerid) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - if ((lspeer != null) && lspeer.getState().equals(BGPPeerCfg.State.IDLE)) { + if ((lspeer != null) && lspeer.getState().equals(BgpPeerCfg.State.IDLE)) { return true; } @@ -254,21 +254,21 @@ public class BGPConfig implements BGPCfg { } @Override - public TreeMap<String, BGPPeerCfg> getPeerTree() { + public TreeMap<String, BgpPeerCfg> getPeerTree() { return this.bgpPeerTree; } @Override - public TreeMap<String, BGPPeerCfg> displayPeers() { + public TreeMap<String, BgpPeerCfg> displayPeers() { if (this.bgpPeerTree.isEmpty()) { log.debug("There are no BGP peers"); } else { - Set<Entry<String, BGPPeerCfg>> set = this.bgpPeerTree.entrySet(); - Iterator<Entry<String, BGPPeerCfg>> list = set.iterator(); - BGPPeerCfg lspeer; + Set<Entry<String, BgpPeerCfg>> set = this.bgpPeerTree.entrySet(); + Iterator<Entry<String, BgpPeerCfg>> list = set.iterator(); + BgpPeerCfg lspeer; while (list.hasNext()) { - Entry<String, BGPPeerCfg> me = list.next(); + Entry<String, BgpPeerCfg> me = list.next(); lspeer = me.getValue(); log.debug("Peer neighbor IP :" + me.getKey()); log.debug(", AS Number : " + lspeer.getAsNumber()); @@ -280,10 +280,10 @@ public class BGPConfig implements BGPCfg { } @Override - public BGPPeerCfg displayPeers(String routerid) { + public BgpPeerCfg displayPeers(String routerid) { if (this.bgpPeerTree.isEmpty()) { - log.debug("There are no BGP peers"); + log.debug("There are no Bgp peers"); } else { return this.bgpPeerTree.get(routerid); } @@ -312,7 +312,7 @@ public class BGPConfig implements BGPCfg { @Override public boolean isPeerConfigured(String routerid) { - BGPPeerCfg lspeer = this.bgpPeerTree.get(routerid); + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); return (lspeer != null) ? true : false; } diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java new file mode 100755 index 00000000..27db618d --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelFutureListener; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpPeerCfg; +import org.onosproject.bgp.controller.BgpConnectPeer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implements connection initiation to peer on peer configuration and manage channel using netty channel handler. + */ +public class BgpConnectPeerImpl implements BgpConnectPeer { + private static final Logger log = LoggerFactory.getLogger(BgpConnectPeerImpl.class); + + private ScheduledExecutorService connectExecutor = null; + private final String peerHost; + private static final int RETRY_INTERVAL = 4; + private final int peerPort; + private int connectRetryCounter = 0; + private int connectRetryTime; + private ChannelPipelineFactory pfact; + private ClientBootstrap peerBootstrap; + private BgpCfg bgpconfig; + + /** + * Initialize timer and initiate pipeline factory. + * + * @param bgpController parent BGP controller + * @param remoteHost remote host to connect + * @param remotePort remote port to connect + */ + public BgpConnectPeerImpl(BgpController bgpController, String remoteHost, int remotePort) { + + this.bgpconfig = bgpController.getConfig(); + this.pfact = new BgpPipelineFactory(bgpController, false); + this.peerBootstrap = Controller.peerBootstrap(); + this.peerBootstrap.setPipelineFactory(pfact); + this.peerHost = remoteHost; + this.peerPort = remotePort; + this.connectRetryTime = 0; + } + + @Override + public void disconnectPeer() { + if (connectExecutor != null) { + connectExecutor.shutdown(); + connectExecutor = null; + } + } + + @Override + public void connectPeer() { + scheduleConnectionRetry(this.connectRetryTime); + } + + /** + * Retry connection with exponential back-off mechanism. + * + * @param retryDelay retry delay + */ + private void scheduleConnectionRetry(long retryDelay) { + if (this.connectExecutor == null) { + this.connectExecutor = Executors.newSingleThreadScheduledExecutor(); + } + this.connectExecutor.schedule(new ConnectionRetry(), retryDelay, TimeUnit.MINUTES); + } + + /** + * Implements BGP connection and manages connection to peer with back-off mechanism in case of failure. + */ + class ConnectionRetry implements Runnable { + @Override + public void run() { + log.debug("Connect to peer {}", peerHost); + + InetSocketAddress connectToSocket = new InetSocketAddress(peerHost, peerPort); + + try { + bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.CONNECT); + peerBootstrap.connect(connectToSocket).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (!future.isSuccess()) { + bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.ACTIVE); + connectRetryCounter++; + log.error("Connection failed, ConnectRetryCounter {} remote host {}", connectRetryCounter, + peerHost); + /* + * Reconnect to peer on failure is exponential till 4 mins, later on retry after every 4 + * mins. + */ + if (connectRetryTime < RETRY_INTERVAL) { + connectRetryTime = (connectRetryTime != 0) ? connectRetryTime * 2 : 1; + } + scheduleConnectionRetry(connectRetryTime); + } else { + + connectRetryCounter++; + log.info("Connected to remote host {}, Connect Counter {}", peerHost, connectRetryCounter); + disconnectPeer(); + return; + } + } + }); + } catch (Exception e) { + log.info("Connect peer exception : " + e.toString()); + disconnectPeer(); + } + } + } +} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPControllerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java index 35c31ab7..6a14e85c 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPControllerImpl.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java @@ -26,34 +26,32 @@ import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Service; -import org.onosproject.bgp.controller.BGPCfg; -import org.onosproject.bgp.controller.BGPController; -import org.onosproject.bgp.controller.BGPId; -import org.onosproject.bgp.controller.BGPPeer; -import org.onosproject.bgp.controller.BgpLinkListener; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpPeer; import org.onosproject.bgp.controller.BgpNodeListener; import org.onosproject.bgp.controller.BgpPeerManager; -import org.onosproject.bgpio.exceptions.BGPParseException; -import org.onosproject.bgpio.protocol.BGPMessage; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(immediate = true) @Service -public class BGPControllerImpl implements BGPController { +public class BgpControllerImpl implements BgpController { - private static final Logger log = LoggerFactory.getLogger(BGPControllerImpl.class); + private static final Logger log = LoggerFactory.getLogger(BgpControllerImpl.class); - protected ConcurrentHashMap<BGPId, BGPPeer> connectedPeers = new ConcurrentHashMap<BGPId, BGPPeer>(); + protected ConcurrentHashMap<BgpId, BgpPeer> connectedPeers = new ConcurrentHashMap<BgpId, BgpPeer>(); - protected BGPPeerManagerImpl peerManager = new BGPPeerManagerImpl(); + protected BgpPeerManagerImpl peerManager = new BgpPeerManagerImpl(); protected Set<BgpNodeListener> bgpNodeListener = new CopyOnWriteArraySet<>(); - protected Set<BgpLinkListener> bgpLinkListener = new CopyOnWriteArraySet<>(); final Controller ctrl = new Controller(this); - private BGPConfig bgpconfig = new BGPConfig(); + private BgpConfig bgpconfig = new BgpConfig(); @Activate public void activate() { @@ -70,12 +68,12 @@ public class BGPControllerImpl implements BGPController { } @Override - public Iterable<BGPPeer> getPeers() { + public Iterable<BgpPeer> getPeers() { return this.connectedPeers.values(); } @Override - public BGPPeer getPeer(BGPId bgpId) { + public BgpPeer getPeer(BgpId bgpId) { return this.connectedPeers.get(bgpId); } @@ -95,27 +93,12 @@ public class BGPControllerImpl implements BGPController { } @Override - public void addLinkListener(BgpLinkListener listener) { - this.bgpLinkListener.add(listener); - } - - @Override - public void removeLinkListener(BgpLinkListener listener) { - this.bgpLinkListener.remove(listener); - } - - @Override - public Set<BgpLinkListener> linkListener() { - return bgpLinkListener; - } - - @Override - public void writeMsg(BGPId bgpId, BGPMessage msg) { + public void writeMsg(BgpId bgpId, BgpMessage msg) { this.getPeer(bgpId).sendMessage(msg); } @Override - public void processBGPPacket(BGPId bgpId, BGPMessage msg) throws BGPParseException { + public void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException { switch (msg.getType()) { case OPEN: @@ -138,8 +121,8 @@ public class BGPControllerImpl implements BGPController { @Override public void closeConnectedPeers() { - BGPPeer bgpPeer; - for (BGPId id : this.connectedPeers.keySet()) { + BgpPeer bgpPeer; + for (BgpId id : this.connectedPeers.keySet()) { bgpPeer = getPeer(id); bgpPeer.disconnectPeer(); } @@ -149,13 +132,13 @@ public class BGPControllerImpl implements BGPController { * Implementation of an BGP Peer which is responsible for keeping track of connected peers and the state in which * they are. */ - public class BGPPeerManagerImpl implements BgpPeerManager { + public class BgpPeerManagerImpl implements BgpPeerManager { - private final Logger log = LoggerFactory.getLogger(BGPPeerManagerImpl.class); + private final Logger log = LoggerFactory.getLogger(BgpPeerManagerImpl.class); private final Lock peerLock = new ReentrantLock(); @Override - public boolean addConnectedPeer(BGPId bgpId, BGPPeer bgpPeer) { + public boolean addConnectedPeer(BgpId bgpId, BgpPeer bgpPeer) { if (connectedPeers.get(bgpId) != null) { this.log.error("Trying to add connectedPeer but found previous " + "value for bgp ip: {}", @@ -169,7 +152,7 @@ public class BGPControllerImpl implements BGPController { } @Override - public boolean isPeerConnected(BGPId bgpId) { + public boolean isPeerConnected(BgpId bgpId) { if (connectedPeers.get(bgpId) == null) { this.log.error("Is peer connected: bgpIp {}.", bgpId.toString()); return false; @@ -179,12 +162,12 @@ public class BGPControllerImpl implements BGPController { } @Override - public void removeConnectedPeer(BGPId bgpId) { + public void removeConnectedPeer(BgpId bgpId) { connectedPeers.remove(bgpId); } @Override - public BGPPeer getPeer(BGPId bgpId) { + public BgpPeer getPeer(BgpId bgpId) { return connectedPeers.get(bgpId); } @@ -196,26 +179,35 @@ public class BGPControllerImpl implements BGPController { * @param pktStats packet statistics. * @return BGPPeer peer instance. */ - public BGPPeer getBGPPeerInstance(BGPController bgpController, BgpSessionInfoImpl sessionInfo, - BGPPacketStatsImpl pktStats) { - BGPPeer bgpPeer = new BGPPeerImpl(bgpController, sessionInfo, pktStats); + public BgpPeer getBgpPeerInstance(BgpController bgpController, BgpSessionInfoImpl sessionInfo, + BgpPacketStatsImpl pktStats) { + BgpPeer bgpPeer = new BgpPeerImpl(bgpController, sessionInfo, pktStats); return bgpPeer; } } + /** + * Returns controller. + * + * @return controller + */ + public Controller controller() { + return this.ctrl; + } + @Override - public ConcurrentHashMap<BGPId, BGPPeer> connectedPeers() { + public ConcurrentHashMap<BgpId, BgpPeer> connectedPeers() { return connectedPeers; } @Override - public BGPPeerManagerImpl peerManager() { + public BgpPeerManagerImpl peerManager() { return peerManager; } @Override - public BGPCfg getConfig() { + public BgpCfg getConfig() { return this.bgpconfig; } diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPKeepAliveTimer.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java index 1c95804a..524ac4c1 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPKeepAliveTimer.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java @@ -25,11 +25,11 @@ import org.slf4j.LoggerFactory; /** * Implement sending keepalive message to connected peer periodically based on negotiated holdtime. */ -public class BGPKeepAliveTimer { +public class BgpKeepAliveTimer { private Timer keepAliveTimer; - private BGPChannelHandler handler; - private static final Logger log = LoggerFactory.getLogger(BGPKeepAliveTimer.class); + private BgpChannelHandler handler; + private static final Logger log = LoggerFactory.getLogger(BgpKeepAliveTimer.class); /** * Gets keepalive timer object. @@ -46,7 +46,7 @@ public class BGPKeepAliveTimer { * @param h channel handler * @param seconds time interval. */ - public BGPKeepAliveTimer(BGPChannelHandler h, int seconds) { + public BgpKeepAliveTimer(BgpChannelHandler h, int seconds) { this.handler = h; this.keepAliveTimer = new Timer(); this.keepAliveTimer.schedule(new SendKeepAlive(), 0, seconds * 1000); diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPMessageDecoder.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java index 636b78cc..431c6210 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPMessageDecoder.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java @@ -22,20 +22,20 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.frame.FrameDecoder; -import org.onosproject.bgpio.protocol.BGPMessage; +import org.onosproject.bgpio.protocol.BgpMessage; import org.onlab.util.HexDump; -import org.onosproject.bgpio.protocol.BGPFactories; -import org.onosproject.bgpio.protocol.BGPMessageReader; -import org.onosproject.bgpio.types.BGPHeader; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.types.BgpHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Decode an bgp message from a Channel, for use in a netty pipeline. */ -public class BGPMessageDecoder extends FrameDecoder { +public class BgpMessageDecoder extends FrameDecoder { - protected static final Logger log = LoggerFactory.getLogger(BGPMessageDecoder.class); + protected static final Logger log = LoggerFactory.getLogger(BgpMessageDecoder.class); @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { @@ -47,12 +47,12 @@ public class BGPMessageDecoder extends FrameDecoder { HexDump.dump(buffer); - BGPMessageReader<BGPMessage> reader = BGPFactories.getGenericReader(); - List<BGPMessage> msgList = new LinkedList<BGPMessage>(); + BgpMessageReader<BgpMessage> reader = BgpFactories.getGenericReader(); + List<BgpMessage> msgList = new LinkedList<BgpMessage>(); while (buffer.readableBytes() > 0) { - BGPHeader bgpHeader = new BGPHeader(); - BGPMessage message = reader.readFrom(buffer, bgpHeader); + BgpHeader bgpHeader = new BgpHeader(); + BgpMessage message = reader.readFrom(buffer, bgpHeader); msgList.add(message); } return msgList; diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPMessageEncoder.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java index f0d38c3d..3e56d6ff 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPMessageEncoder.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java @@ -22,7 +22,7 @@ import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; -import org.onosproject.bgpio.protocol.BGPMessage; +import org.onosproject.bgpio.protocol.BgpMessage; import org.onlab.util.HexDump; import org.slf4j.Logger; @@ -32,8 +32,8 @@ import org.slf4j.LoggerFactory; * Encode an bgp message for output into a ChannelBuffer, for use in a * netty pipeline. */ -public class BGPMessageEncoder extends OneToOneEncoder { - protected static final Logger log = LoggerFactory.getLogger(BGPMessageEncoder.class); +public class BgpMessageEncoder extends OneToOneEncoder { + protected static final Logger log = LoggerFactory.getLogger(BgpMessageEncoder.class); @Override protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { @@ -44,12 +44,12 @@ public class BGPMessageEncoder extends OneToOneEncoder { } @SuppressWarnings("unchecked") - List<BGPMessage> msglist = (List<BGPMessage>) msg; + List<BgpMessage> msglist = (List<BgpMessage>) msg; ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); log.debug("SENDING MESSAGE"); - for (BGPMessage pm : msglist) { + for (BgpMessage pm : msglist) { pm.writeTo(buf); } diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPacketStatsImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java index 09f4d452..7494c814 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPacketStatsImpl.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java @@ -15,7 +15,7 @@ */ package org.onosproject.bgp.controller.impl; -import org.onosproject.bgp.controller.BGPPacketStats; +import org.onosproject.bgp.controller.BgpPacketStats; /** * A representation of a packet context which allows any provider @@ -23,7 +23,7 @@ import org.onosproject.bgp.controller.BGPPacketStats; * event if blocked has been called. This packet context can be used * to react to the packet in event with a packet out. */ -public class BGPPacketStatsImpl implements BGPPacketStats { +public class BgpPacketStatsImpl implements BgpPacketStats { private int inPacketCount; private int outPacketCount; @@ -33,7 +33,7 @@ public class BGPPacketStatsImpl implements BGPPacketStats { /** * Resets parameter. */ - public BGPPacketStatsImpl() { + public BgpPacketStatsImpl() { this.inPacketCount = 0; this.outPacketCount = 0; this.wrongPacketCount = 0; diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerConfig.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java index 14a68cf6..a8eaee3c 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerConfig.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java @@ -17,12 +17,12 @@ package org.onosproject.bgp.controller.impl; import org.onlab.packet.Ip4Address; import org.onosproject.bgp.controller.BgpConnectPeer; -import org.onosproject.bgp.controller.BGPPeerCfg; +import org.onosproject.bgp.controller.BgpPeerCfg; /** * BGP Peer configuration information. */ -public class BGPPeerConfig implements BGPPeerCfg { +public class BgpPeerConfig implements BgpPeerCfg { private int asNumber; private short holdTime; private boolean isIBgp; @@ -34,7 +34,7 @@ public class BGPPeerConfig implements BGPPeerCfg { /** * Constructor to initialize the values. */ - BGPPeerConfig() { + BgpPeerConfig() { state = State.IDLE; selfInitiated = false; } diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java new file mode 100644 index 00000000..57a924a8 --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java @@ -0,0 +1,297 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Collections; +import java.util.List; +import java.util.ListIterator; +import java.util.concurrent.RejectedExecutionException; + +import org.jboss.netty.channel.Channel; +import org.onlab.packet.IpAddress; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpSessionInfo; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.MpReachNlri; +import org.onosproject.bgpio.types.MpUnReachNlri; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * BGPPeerImpl implements BGPPeer, maintains peer information and store updates in RIB . + */ +public class BgpPeerImpl implements BgpPeer { + + protected final Logger log = LoggerFactory.getLogger(BgpPeerImpl.class); + + private static final String SHUTDOWN_MSG = "Worker has already been shutdown"; + + private BgpController bgpController; + private Channel channel; + protected String channelId; + private boolean connected; + protected boolean isHandShakeComplete = false; + private BgpSessionInfo sessionInfo; + private BgpPacketStatsImpl pktStats; + private AdjRibIn adjRib; + private VpnAdjRibIn vpnAdjRib; + + + @Override + public BgpSessionInfo sessionInfo() { + return sessionInfo; + } + + /** + * Initialize peer. + * + *@param bgpController controller instance + *@param sessionInfo bgp session info + *@param pktStats packet statistics + */ + public BgpPeerImpl(BgpController bgpController, BgpSessionInfo sessionInfo, BgpPacketStatsImpl pktStats) { + this.bgpController = bgpController; + this.sessionInfo = sessionInfo; + this.pktStats = pktStats; + this.adjRib = new AdjRibIn(); + this.vpnAdjRib = new VpnAdjRibIn(); + } + + + @Override + public void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException { + ListIterator<BgpValueType> iterator = pathAttr.listIterator(); + while (iterator.hasNext()) { + BgpValueType attr = iterator.next(); + if (attr instanceof MpReachNlri) { + List<BgpLSNlri> nlri = ((MpReachNlri) attr).mpReachNlri(); + callAdd(this, nlri, pathAttr); + } + if (attr instanceof MpUnReachNlri) { + List<BgpLSNlri> nlri = ((MpUnReachNlri) attr).mpUnReachNlri(); + callRemove(this, nlri); + } + } + } + + /** + * Updates NLRI identifier node in a tree separately based on afi and safi. + * + * @param peerImpl BGP peer instance + * @param nlri MpReachNlri path attribute + * @param pathAttr list of BGP path attributes + * @throws BgpParseException throws exception + */ + public void callAdd(BgpPeerImpl peerImpl, List<BgpLSNlri> nlri, List<BgpValueType> pathAttr) + throws BgpParseException { + ListIterator<BgpLSNlri> listIterator = nlri.listIterator(); + while (listIterator.hasNext()) { + BgpLSNlri nlriInfo = listIterator.next(); + if (nlriInfo instanceof BgpNodeLSNlriVer4) { + PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); + if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.add(nlriInfo, details); + } else { + vpnAdjRib.addVpn(nlriInfo, details, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpLinkLsNlriVer4) { + PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); + if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.add(nlriInfo, details); + } else { + vpnAdjRib.addVpn(nlriInfo, details, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) { + PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); + if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.add(nlriInfo, details); + } else { + vpnAdjRib.addVpn(nlriInfo, details, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } + } + } + + /** + * Sets BGP path attribute and NLRI details. + * + * @param nlriInfo MpReachNlri path attribute + * @param pathAttr list of BGP path attributes + * @return details object of PathAttrNlriDetails + * @throws BgpParseException throw exception + */ + public PathAttrNlriDetails setPathAttrDetails(BgpLSNlri nlriInfo, List<BgpValueType> pathAttr) + throws BgpParseException { + PathAttrNlriDetails details = new PathAttrNlriDetails(); + details.setProtocolID(nlriInfo.getProtocolId()); + details.setIdentifier(nlriInfo.getIdentifier()); + details.setPathAttribute(pathAttr); + return details; + } + + /** + * Removes NLRI identifier node in a tree separately based on afi and safi. + * + * @param peerImpl BGP peer instance + * @param nlri NLRI information + */ + public void callRemove(BgpPeerImpl peerImpl, List<BgpLSNlri> nlri) { + ListIterator<BgpLSNlri> listIterator = nlri.listIterator(); + while (listIterator.hasNext()) { + BgpLSNlri nlriInfo = listIterator.next(); + if (nlriInfo instanceof BgpNodeLSNlriVer4) { + if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.remove(nlriInfo); + } else { + vpnAdjRib.removeVpn(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpLinkLsNlriVer4) { + if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.remove(nlriInfo); + } else { + vpnAdjRib.removeVpn(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) { + if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.remove(nlriInfo); + } else { + vpnAdjRib.removeVpn(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } + } + } + + /** + * Return the adjacency RIB-IN. + * + * @return adjRib the adjacency RIB-IN + */ + public AdjRibIn adjRib() { + return adjRib; + } + + /** + * Return the adjacency RIB-IN with VPN. + * + * @return vpnAdjRib the adjacency RIB-IN with VPN + */ + public VpnAdjRibIn vpnAdjRib() { + return vpnAdjRib; + } + + // ************************ + // Channel related + // ************************ + + @Override + public final void disconnectPeer() { + this.channel.close(); + } + + @Override + public final void sendMessage(BgpMessage m) { + log.debug("Sending message to {}", channel.getRemoteAddress()); + try { + channel.write(Collections.singletonList(m)); + this.pktStats.addOutPacket(); + } catch (RejectedExecutionException e) { + log.warn(e.getMessage()); + if (!e.getMessage().contains(SHUTDOWN_MSG)) { + throw e; + } + } + } + + @Override + public final void sendMessage(List<BgpMessage> msgs) { + try { + channel.write(msgs); + this.pktStats.addOutPacket(msgs.size()); + } catch (RejectedExecutionException e) { + log.warn(e.getMessage()); + if (!e.getMessage().contains(SHUTDOWN_MSG)) { + throw e; + } + } + } + + @Override + public final boolean isConnected() { + return this.connected; + } + + @Override + public final void setConnected(boolean connected) { + this.connected = connected; + }; + + @Override + public final void setChannel(Channel channel) { + this.channel = channel; + final SocketAddress address = channel.getRemoteAddress(); + if (address instanceof InetSocketAddress) { + final InetSocketAddress inetAddress = (InetSocketAddress) address; + final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress()); + if (ipAddress.isIp4()) { + channelId = ipAddress.toString() + ':' + inetAddress.getPort(); + } else { + channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort(); + } + } + }; + + @Override + public final Channel getChannel() { + return this.channel; + }; + + @Override + public String channelId() { + return channelId; + } + + @Override + public BgpFactory factory() { + return BgpFactories.getFactory(sessionInfo.remoteBgpVersion()); + } + + @Override + public boolean isHandshakeComplete() { + return isHandShakeComplete; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("channel", channelId()) + .add("BgpId", sessionInfo().remoteBgpId()).toString(); + } +} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPipelineFactory.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java index e6f09f20..28e1041c 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPipelineFactory.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java @@ -23,18 +23,18 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler; import org.jboss.netty.util.ExternalResourceReleasable; import org.jboss.netty.util.HashedWheelTimer; import org.jboss.netty.util.Timer; -import org.onosproject.bgp.controller.BGPController; +import org.onosproject.bgp.controller.BgpController; /** * Creates a ChannelPipeline for a server-side bgp channel. */ -public class BGPPipelineFactory +public class BgpPipelineFactory implements ChannelPipelineFactory, ExternalResourceReleasable { static final Timer TIMER = new HashedWheelTimer(); protected ReadTimeoutHandler readTimeoutHandler; private boolean isBgpServ; - private BGPController bgpController; + private BgpController bgpController; /** * Constructor to initialize the values. @@ -42,7 +42,7 @@ public class BGPPipelineFactory * @param bgpController parent controller * @param isBgpServ if it is a server or remote peer */ - public BGPPipelineFactory(BGPController bgpController, boolean isBgpServ) { + public BgpPipelineFactory(BgpController bgpController, boolean isBgpServ) { super(); this.isBgpServ = isBgpServ; this.bgpController = bgpController; @@ -52,11 +52,11 @@ public class BGPPipelineFactory @Override public ChannelPipeline getPipeline() throws Exception { - BGPChannelHandler handler = new BGPChannelHandler(bgpController); + BgpChannelHandler handler = new BgpChannelHandler(bgpController); ChannelPipeline pipeline = Channels.pipeline(); - pipeline.addLast("bgpmessagedecoder", new BGPMessageDecoder()); - pipeline.addLast("bgpmessageencoder", new BGPMessageEncoder()); + pipeline.addLast("bgpmessagedecoder", new BgpMessageDecoder()); + pipeline.addLast("bgpmessageencoder", new BgpMessageEncoder()); pipeline.addLast("holdTime", readTimeoutHandler); if (isBgpServ) { pipeline.addLast("PassiveHandler", handler); diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java new file mode 100644 index 00000000..d3065f43 --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java @@ -0,0 +1,242 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.util.Comparator; +import java.util.List; +import java.util.ListIterator; + +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; +import org.onosproject.bgpio.types.AsPath; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.LocalPref; +import org.onosproject.bgpio.types.Med; +import org.onosproject.bgpio.types.Origin; +import org.onosproject.bgpio.types.Origin.ORIGINTYPE; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation of BGP best path Selection process. + */ +public final class BgpSelectionAlgo implements Comparator<PathAttrNlriDetailsLocalRib> { + private static final Logger log = LoggerFactory.getLogger(BgpSelectionAlgo.class); + LocalPref obj1LocPref = null; + AsPath obj1Aspath = null; + Origin obj1Origin = null; + Med obj1Med = null; + LocalPref obj2LocPref = null; + AsPath obj2Aspath = null; + Origin obj2Origin = null; + Med obj2Med = null; + + @Override + public int compare(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { + if (pathNlriDetails1 == null) { + return -1; + } + if (pathNlriDetails2 == null) { + return 1; + } + if (pathNlriDetails1.equals(pathNlriDetails2)) { + return 0; + } + + List<BgpValueType> o1 = pathNlriDetails1.localRibNlridetails().pathAttributes(); + List<BgpValueType> o2 = pathNlriDetails2.localRibNlridetails().pathAttributes(); + ListIterator<BgpValueType> listIteratorObj1 = o1.listIterator(); + ListIterator<BgpValueType> listIteratorObj2 = o2.listIterator(); + storeAttr(listIteratorObj1, listIteratorObj2); + + // prefer attribute with higher local preference + if (obj1LocPref != null || obj2LocPref != null && (obj1LocPref != null && !obj1LocPref.equals(obj2LocPref))) { + return compareLocalPref(obj1LocPref, obj2LocPref); + } + + // prefer attribute with shortest Aspath + if (!obj1Aspath.equals(obj2Aspath)) { + Integer obj1Size = countASSize(obj1Aspath); + Integer obj2Size = countASSize(obj2Aspath); + if (obj1Size != obj2Size) { + return compareAsPath(obj1Size, obj2Size); + } + } + + // prefer attribute with lowest origin type + if (!obj1Origin.equals(obj2Origin)) { + return compareOrigin(obj1Origin, obj2Origin); + } + + // prefer attribute with lowest MED + if (obj1Med != null || obj2Med != null && (obj1Med != null && !obj1Med.equals(obj2Med))) { + return compareMed(obj1Med, obj2Med); + } + + if ((pathNlriDetails1 != null || pathNlriDetails2 != null) && (pathNlriDetails1 != null && !pathNlriDetails1 + .equals(pathNlriDetails2))) { + return comparePeerDetails(pathNlriDetails1, pathNlriDetails2); + } + return 0; + } + + /** + * Compares local preference of two objects and returns object with higher preference. + * + * @param obj1LocPref local preference object1 + * @param obj2LocPref local preference object2 + * @return object with higher preference + */ + int compareLocalPref(LocalPref obj1LocPref, LocalPref obj2LocPref) { + return ((Integer) (obj1LocPref.localPref())).compareTo((Integer) (obj2LocPref.localPref())); + } + + /** + * Compares AsPath of two objects and returns object with shortest AsPath. + * + * @param obj1Size object1 AS count + * @param obj2Size object2 AS count + * @return + */ + int compareAsPath(Integer obj1Size, Integer obj2Size) { + return obj1Size.compareTo(obj2Size); + } + + /** + * Compare Origin of two objects and returns object with lowest origin value. + * + * @param obj1Origin Origin object1 + * @param obj2Origin Origin object1 + * @return object with lowest origin value + */ + int compareOrigin(Origin obj1Origin, Origin obj2Origin) { + if (obj1Origin.origin() == ORIGINTYPE.IGP) { + return 1; + } + if (obj2Origin.origin() == ORIGINTYPE.IGP) { + return -1; + } + if (obj1Origin.origin() == ORIGINTYPE.EGP) { + return 1; + } else { + return -1; + } + } + + /** + * Compare Med of two objects and returns object with lowestMed value. + * + * @param obj1Med Med object1 + * @param obj2Med Med object2 + * @return returns object with lowestMed value + */ + int compareMed(Med obj1Med, Med obj2Med) { + return ((Integer) (obj2Med.med())).compareTo((Integer) (obj1Med.med())); + } + + /** + * Compares EBGP over IBGP, BGP identifier value and peer address. + * + * @param pathNlriDetails1 PathAttrNlriDetailsLocalRib object1 + * @param pathNlriDetails2 PathAttrNlriDetailsLocalRib object2 + * @return object which as EBGP over IBGP, lowest BGP identifier value and lowest peer address + */ + int comparePeerDetails(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { + // consider EBGP over IBGP + if (pathNlriDetails1.isLocalRibIbgpSession() != pathNlriDetails2.isLocalRibIbgpSession()) { + if (pathNlriDetails1 == null || pathNlriDetails1.isLocalRibIbgpSession()) { + return -1; + } + if (pathNlriDetails2 == null || pathNlriDetails2.isLocalRibIbgpSession()) { + return 1; + } + } + // prefer lowest BGP identifier value. + if (pathNlriDetails1.localRibIdentifier() != pathNlriDetails2.localRibIdentifier()) { + return ((Integer) pathNlriDetails2.localRibIdentifier()) + .compareTo(pathNlriDetails1.localRibIdentifier()); + } + //prefer lowest peer address + if (pathNlriDetails1.localRibIpAddress() != pathNlriDetails2.localRibIpAddress()) { + return pathNlriDetails2.localRibIpAddress().compareTo(pathNlriDetails1.localRibIpAddress()); + } + return 0; + } + + /** + * Returns ASes count of AsPath attribute , if AS_SET is present then count as 1. + * + * @param aspath object of AsPath + * @return count of ASes + */ + Integer countASSize(AsPath aspath) { + boolean isASSet = false; + int count = 0; + if (!aspath.asPathSet().isEmpty()) { + isASSet = true; + } + if (!aspath.asPathSeq().isEmpty()) { + count = aspath.asPathSeq().size(); + } + return isASSet ? ++count : count; + } + + /** + * Stores BGP basic attributes of two objects. + * + * @param listIteratorObj1 list iterator of object1 + * @param listIteratorObj2 list iterator of object2 + */ + void storeAttr(ListIterator<BgpValueType> listIteratorObj1, ListIterator<BgpValueType> listIteratorObj2) { + while (listIteratorObj1.hasNext()) { + BgpValueType pathAttributeObj1 = listIteratorObj1.next(); + switch (pathAttributeObj1.getType()) { + case LocalPref.LOCAL_PREF_TYPE: + obj1LocPref = (LocalPref) pathAttributeObj1; + break; + case AsPath.ASPATH_TYPE: + obj1Aspath = (AsPath) pathAttributeObj1; + break; + case Origin.ORIGIN_TYPE: + obj1Origin = (Origin) pathAttributeObj1; + break; + case Med.MED_TYPE: + obj1Med = (Med) pathAttributeObj1; + break; + default: + log.debug("Got other type, Not required: " + pathAttributeObj1.getType()); + } + } + while (listIteratorObj2.hasNext()) { + BgpValueType pathAttributeObj2 = listIteratorObj2.next(); + switch (pathAttributeObj2.getType()) { + case LocalPref.LOCAL_PREF_TYPE: + obj2LocPref = (LocalPref) pathAttributeObj2; + break; + case AsPath.ASPATH_TYPE: + obj2Aspath = (AsPath) pathAttributeObj2; + break; + case Origin.ORIGIN_TYPE: + obj2Origin = (Origin) pathAttributeObj2; + break; + case Med.MED_TYPE: + obj2Med = (Med) pathAttributeObj2; + break; + default: + log.debug("Got other type, Not required: " + pathAttributeObj2.getType()); + } + } + } +}
\ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java new file mode 100755 index 00000000..33623dc2 --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpSessionInfo; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class maintains BGP peer session info. + */ +public class BgpSessionInfoImpl implements BgpSessionInfo { + + protected final Logger log = LoggerFactory.getLogger(BgpSessionInfoImpl.class); + private BgpId remoteBgpId; + private BgpVersion remoteBgpVersion; + private long remoteBgpASNum; + private short remoteBgpholdTime; + private int remoteBgpIdentifier; + private short negotiatedholdTime; + private boolean isIbgpSession; + + /** + * Initialize session info. + * + *@param remoteBgpId remote peer id + *@param remoteBgpVersion remote peer version + *@param remoteBgpASNum remote peer AS number + *@param remoteBgpholdTime remote peer hold time + *@param remoteBgpIdentifier remote peer identifier + *@param negotiatedholdTime negotiated hold time + *@param isIbgpSession session type ibgp/ebgp + */ + public BgpSessionInfoImpl(BgpId remoteBgpId, BgpVersion remoteBgpVersion, long remoteBgpASNum, + short remoteBgpholdTime, int remoteBgpIdentifier, short negotiatedholdTime, + boolean isIbgpSession) { + this.remoteBgpId = remoteBgpId; + this.remoteBgpVersion = remoteBgpVersion; + this.remoteBgpASNum = remoteBgpASNum; + this.remoteBgpholdTime = remoteBgpholdTime; + this.remoteBgpIdentifier = remoteBgpIdentifier; + this.negotiatedholdTime = negotiatedholdTime; + this.isIbgpSession = isIbgpSession; + } + + @Override + public boolean isIbgpSession() { + return isIbgpSession; + } + + @Override + public short negotiatedholdTime() { + return negotiatedholdTime; + } + + @Override + public BgpId remoteBgpId() { + return remoteBgpId; + } + + @Override + public BgpVersion remoteBgpVersion() { + return remoteBgpVersion; + } + + @Override + public long remoteBgpASNum() { + return remoteBgpASNum; + } + + @Override + public short remoteBgpHoldTime() { + return remoteBgpholdTime; + } + + @Override + public int remoteBgpIdentifier() { + return remoteBgpIdentifier; + } +} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java index 017c39e5..f02cee8a 100755 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java @@ -26,15 +26,16 @@ import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; -import org.onosproject.bgp.controller.BGPController; -import org.onosproject.bgpio.protocol.BGPFactories; -import org.onosproject.bgpio.protocol.BGPFactory; -import org.onosproject.bgpio.protocol.BGPVersion; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,12 +47,15 @@ public class Controller { private static final Logger log = LoggerFactory.getLogger(Controller.class); - private static final BGPFactory FACTORY4 = BGPFactories.getFactory(BGPVersion.BGP_4); + private static final BgpFactory FACTORY4 = BgpFactories.getFactory(BgpVersion.BGP_4); private ChannelGroup cg; + public Channel serverChannel; // Configuration options private static final short BGP_PORT_NUM = 179; + private static final short PORT_NUM_ZERO = 0; + private static boolean isPortNumSet = false; private final int workerThreads = 16; private final int peerWorkerThreads = 16; @@ -61,7 +65,7 @@ public class Controller { private NioServerSocketChannelFactory serverExecFactory; private NioClientSocketChannelFactory peerExecFactory; private static ClientBootstrap peerBootstrap; - private BGPController bgpController; + private BgpController bgpController; // Perf. related configuration private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; @@ -71,7 +75,7 @@ public class Controller { * * @param bgpController bgp controller instance */ - public Controller(BGPController bgpController) { + public Controller(BgpController bgpController) { this.bgpController = bgpController; } @@ -80,7 +84,7 @@ public class Controller { * * @return instance of factory version */ - static BGPFactory getBGPMessageFactory4() { + static BgpFactory getBgpMessageFactory4() { return FACTORY4; } @@ -114,12 +118,13 @@ public class Controller { bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); - ChannelPipelineFactory pfact = new BGPPipelineFactory(bgpController, true); + ChannelPipelineFactory pfact = new BgpPipelineFactory(bgpController, true); bootstrap.setPipelineFactory(pfact); InetSocketAddress sa = new InetSocketAddress(getBgpPortNum()); cg = new DefaultChannelGroup(); - cg.add(bootstrap.bind(sa)); + serverChannel = bootstrap.bind(sa); + cg.add(serverChannel); log.info("Listening for Peer connection on {}", sa); } catch (Exception e) { throw new RuntimeException(e); @@ -234,6 +239,16 @@ public class Controller { * @return port number */ public static short getBgpPortNum() { + if (isPortNumSet) { + return PORT_NUM_ZERO; + } return BGP_PORT_NUM; } + + /** + * sets the isPortNumSet as true. + */ + public void setBgpPortNum() { + isPortNumSet = true; + } }
\ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java new file mode 100644 index 00000000..8a9ea91c --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java @@ -0,0 +1,209 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Map; +import java.util.TreeMap; + +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.types.RouteDistinguisher; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Adj-RIB-In with VPN for each peer. + */ +public class VpnAdjRibIn { + private Map<BgpNodeLSIdentifier, PathAttrNlriDetails> nodeTree = new TreeMap<>(); + private Map<BgpLinkLSIdentifier, PathAttrNlriDetails> linkTree = new TreeMap<>(); + private Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefixTree = new TreeMap<>(); + + private Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetails>> vpnNodeTree + = new TreeMap<>(); + private Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetails>> vpnLinkTree + = new TreeMap<>(); + private Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetails>> vpnPrefixTree + = new TreeMap<>(); + /** + * Returns the adjacency node. + * + * @return node adjacency RIB node + */ + public Map<BgpNodeLSIdentifier, PathAttrNlriDetails> nodeTree() { + return nodeTree; + } + + /** + * Returns the adjacency link. + * + * @return link adjacency RIB node + */ + public Map<BgpLinkLSIdentifier, PathAttrNlriDetails> linkTree() { + return linkTree; + } + + /** + * Returns the adjacency prefix. + * + * @return prefix adjacency RIB node + */ + public Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefixTree() { + return prefixTree; + } + + /** + * Returns the adjacency vpnNode. + * + * @return vpnNode adjacency RIB node + */ + public Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetails>> vpnNodeTree() { + return vpnNodeTree; + } + + /** + * Returns the adjacency vpnLink. + * + * @return vpnLink adjacency RIB node + */ + public Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetails>> vpnLinkTree() { + return vpnLinkTree; + } + + /** + * Returns the adjacency vpnPrefix. + * + * @return vpnPrefix adjacency RIB node + */ + public Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetails>> vpnPrefixTree() { + return vpnPrefixTree; + } + + /** + * Update vpn nlri identifier into the tree if nlri identifier exists in tree otherwise add this to the tree. + * + * @param nlri NLRI info + * @param details has pathattribute , protocolID and identifier + */ + public void add(BgpLSNlri nlri, PathAttrNlriDetails details) { + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.replace(nodeLSIdentifier, details); + } else { + nodeTree.put(nodeLSIdentifier, details); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.replace(linkLSIdentifier, details); + } else { + linkTree.put(linkLSIdentifier, details); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.replace(prefixIdentifier, details); + } else { + prefixTree.put(prefixIdentifier, details); + } + } + } + + /** + * Update nlri identifier mapped with route distinguisher if it exists in tree otherwise add nlri infomation mapped + * to respective route distinguisher in tree. + * + * @param nlri NLRI info + * @param details has pathattribute , protocolID and identifier + * @param routeDistinguisher unique for for each vpn + */ + public void addVpn(BgpLSNlri nlri, PathAttrNlriDetails details, RouteDistinguisher routeDistinguisher) { + add(nlri, details); + if (nlri instanceof BgpNodeLSNlriVer4) { + if (!vpnNodeTree.containsKey(routeDistinguisher)) { + vpnNodeTree.put(routeDistinguisher, nodeTree); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + if (!vpnLinkTree.containsKey(routeDistinguisher)) { + vpnLinkTree.put(routeDistinguisher, linkTree); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + if (!vpnPrefixTree.containsKey(routeDistinguisher)) { + vpnPrefixTree.put(routeDistinguisher, prefixTree); + } + } + } + + /** + * Removes vpn nlri identifier mapped to route distinguisher if it exists in tree. + * + * @param nlri NLRI Info + * @param routeDistinguisher unique for for each vpn + */ + public void removeVpn(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) { + if (nlri instanceof BgpNodeLSNlriVer4) { + if (vpnNodeTree.containsKey(routeDistinguisher)) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.remove(nodeLSIdentifier); + } + if ((vpnNodeTree.get(routeDistinguisher)).isEmpty()) { + vpnNodeTree.remove(routeDistinguisher); + } + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + if (vpnLinkTree.containsKey(routeDistinguisher)) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.remove(linkLSIdentifier); + } + if ((vpnLinkTree.get(routeDistinguisher)).isEmpty()) { + vpnLinkTree.remove(routeDistinguisher); + } + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + if (vpnPrefixTree.containsKey(routeDistinguisher)) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.remove(prefixIdentifier); + } + if ((vpnPrefixTree.get(routeDistinguisher)).isEmpty()) { + vpnPrefixTree.remove(routeDistinguisher); + } + } + } + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues().add("nodeTree", nodeTree) + .add("linkTree", linkTree) + .add("prefixTree", prefixTree) + .add("vpnNodeTree", vpnNodeTree) + .add("vpnLinkTree", vpnLinkTree) + .add("vpnPrefixTree", vpnPrefixTree) + .toString(); + } +}
\ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java new file mode 100755 index 00000000..36b1d6fc --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java @@ -0,0 +1,300 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import com.google.common.net.InetAddresses; +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.Channels; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import org.onlab.junit.TestUtils; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.LinkedList; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.impl.BgpControllerImpl; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; +import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; + +/** + * Test case for BGPControllerImpl. + */ +public class BgpControllerImplTest { + + protected static final Logger log = LoggerFactory + .getLogger(BgpControllerImplTest.class); + + private static final String IP_LOOPBACK_ID1 = "127.0.0.1"; + + private static final int MESSAGE_TIMEOUT_MS = 3000; + public byte version; + public short asNumber; + public short holdTime; + public int bgpId = InetAddresses.coerceToInteger(InetAddresses.forString(IP_LOOPBACK_ID1)); + public boolean isLargeAsCapabilitySet = false; + public LinkedList<BgpValueType> capabilityTlv = new LinkedList<>(); + + @Before + public void setUp() throws Exception { + peer1 = new BgpPeerTest(version, asNumber, + holdTime, bgpId, isLargeAsCapabilitySet, + capabilityTlv); + + bgpControllerImpl = new BgpControllerImpl(); + + // NOTE: We use port 0 to bind on any available port + bgpControllerImpl.controller().setBgpPortNum(); + bgpControllerImpl.activate(); + + Channel serverChannel = TestUtils.getField(bgpControllerImpl.controller(), + "serverChannel"); + SocketAddress socketAddress = serverChannel.getLocalAddress(); + InetSocketAddress inetSocketAddress = + (InetSocketAddress) socketAddress; + InetAddress connectToAddress = InetAddresses.forString("127.0.0.1"); + connectToSocket = new InetSocketAddress(connectToAddress, + inetSocketAddress.getPort()); + + bgpControllerImpl.getConfig().setRouterId("1.1.1.1"); + bgpControllerImpl.getConfig().setAsNumber(200); + bgpControllerImpl.getConfig().setHoldTime((short) 120); + bgpControllerImpl.getConfig().setState(BgpCfg.State.IP_AS_CONFIGURED); + + bgpControllerImpl.getConfig().addPeer("127.0.0.1", 200); + } + + @After + public void tearDown() throws Exception { + bgpControllerImpl.deactivate(); + bgpControllerImpl = null; + } + + private BgpControllerImpl bgpControllerImpl; + + BgpPeerTest peer1; + + // The socket that the remote peers should connect to + private InetSocketAddress connectToSocket; + + @Test + public void bgpOpenMessageTest1() throws InterruptedException { + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + peer1.connect(connectToSocket); + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest2() throws InterruptedException { + // Open message with as number which is not configured at peer + peer1.peerChannelHandler.asNumber = 500; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest3() throws InterruptedException { + // Open message with invalid hold time value + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 1; + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest4() throws InterruptedException { + // Open message with invalid as number + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + peer1.peerChannelHandler.isLargeAsCapabilitySet = true; + BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(766545); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest5() throws InterruptedException { + // Open message with LS capability + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest6() throws InterruptedException { + // Open message with as4 capability + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + peer1.peerChannelHandler.isLargeAsCapabilitySet = true; + bgpControllerImpl.getConfig().setLargeASCapability(true); + BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest7() throws InterruptedException { + // Open message with both LS capability and as4 capability + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + + peer1.peerChannelHandler.isLargeAsCapabilitySet = true; + bgpControllerImpl.getConfig().setLargeASCapability(true); + BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv); + + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + /** + * A class to capture the state for a BGP peer. + */ + private final class BgpPeerTest { + private ClientBootstrap peerBootstrap; + private BgpPeerFrameDecoderTest peerFrameDecoder = + new BgpPeerFrameDecoderTest(); + private BgpPeerChannelHandlerTest peerChannelHandler; + + private BgpPeerTest(byte version, short asNumber, + short holdTime, int bgpId, boolean isLargeAsCapabilitySet, + LinkedList<BgpValueType> capabilityTlv) { + peerChannelHandler = new BgpPeerChannelHandlerTest(version, + asNumber, holdTime, bgpId, isLargeAsCapabilitySet, capabilityTlv); + } + + /** + * Starts the BGP peer. + * + * @param connectToSocket the socket to connect to + */ + private void connect(InetSocketAddress connectToSocket) + throws InterruptedException { + + ChannelFactory channelFactory = + new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + ChannelPipelineFactory pipelineFactory = () -> { + ChannelPipeline pipeline = Channels.pipeline(); + pipeline.addLast("BgpPeerFrameDecoderTest", + peerFrameDecoder); + pipeline.addLast("BgpPeerChannelHandlerTest", + peerChannelHandler); + return pipeline; + }; + + peerBootstrap = new ClientBootstrap(channelFactory); + peerBootstrap.setOption("child.keepAlive", true); + peerBootstrap.setOption("child.tcpNoDelay", true); + peerBootstrap.setPipelineFactory(pipelineFactory); + peerBootstrap.connect(connectToSocket); + } + } +}
\ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java new file mode 100755 index 00000000..26ed36d8 --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java @@ -0,0 +1,107 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import java.util.LinkedList; +import java.util.concurrent.TimeUnit; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.onosproject.bgpio.protocol.ver4.BgpKeepaliveMsgVer4; +import org.onosproject.bgpio.protocol.ver4.BgpOpenMsgVer4; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.types.BgpValueType; + +public class BgpPeerChannelHandlerTest extends SimpleChannelHandler { + public static final int OPEN_MSG_MINIMUM_LENGTH = 29; + public static final byte[] MARKER = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff}; + public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER, + (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01); + LinkedList<BgpValueType> capabilityTlv = new LinkedList<>(); + public byte version; + public short asNumber; + public short holdTime; + public int bgpId; + public boolean isLargeAsCapabilitySet; + + final BgpOpenMsgVer4 openMessage = new BgpOpenMsgVer4(); + ChannelHandlerContext savedCtx; + + /** + * Constructor to initialize all variables of BGP Open message. + * + * @param version BGP version in open message + * @param asNumber AS number in open message + * @param holdTime hold time in open message + * @param bgpId BGP identifier in open message + * @param capabilityTlv capabilities in open message + */ + public BgpPeerChannelHandlerTest(byte version, + short asNumber, + short holdTime, + int bgpId, + boolean isLargeAsCapabilitySet, + LinkedList<BgpValueType> capabilityTlv) { + this.version = version; + this.asNumber = asNumber; + this.holdTime = holdTime; + this.bgpId = bgpId; + this.isLargeAsCapabilitySet = isLargeAsCapabilitySet; + this.capabilityTlv = capabilityTlv; + } + + /** + * closes the channel. + */ + void closeChannel() { + savedCtx.getChannel().close(); + } + + @Override + public void channelConnected(ChannelHandlerContext ctx, + ChannelStateEvent channelEvent) throws InterruptedException { + this.savedCtx = ctx; + + BgpOpenMsgVer4 openMsg = new BgpOpenMsgVer4(DEFAULT_OPEN_HEADER, + this.version, + this.asNumber, + this.holdTime, + this.bgpId, + this.capabilityTlv); + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + openMsg.writeTo(buffer); + ctx.getChannel().write(buffer); + + TimeUnit.MILLISECONDS.sleep(100); + + BgpKeepaliveMsgVer4 keepaliveMsg = new BgpKeepaliveMsgVer4(); + ChannelBuffer buffer1 = ChannelBuffers.dynamicBuffer(); + keepaliveMsg.writeTo(buffer1); + ctx.getChannel().write(buffer1); + } + + @Override + public void channelDisconnected(ChannelHandlerContext ctx, + ChannelStateEvent channelEvent) { + //Do Nothing + } +} diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java new file mode 100755 index 00000000..7767053f --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java @@ -0,0 +1,168 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.frame.FrameDecoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.concurrent.CountDownLatch; + +/** + * Class to decode the message received. + */ +public class BgpPeerFrameDecoderTest extends FrameDecoder { + static final byte OPEN_MSG_TYPE = 0x1; + static final byte KEEPALIVE_MSG_TYPE = 0x4; + static final byte UPDATE_MSG_TYPE = 0x2; + static final byte NOTIFICATION_MSG_TYPE = 0x3; + static final int MINIMUM_COMMON_HEADER_LENGTH = 19; + static final int MINIMUM_OPEN_MSG_LENGTH = 29; + static final int MINIMUM_HEADER_MARKER_LENGTH = 16; + static final int HEADER_AND_MSG_LEN = 18; + + protected static final Logger log = LoggerFactory + .getLogger(BgpPeerFrameDecoderTest.class); + final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1); + final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1); + final CountDownLatch receivedNotificationMessageLatch = new CountDownLatch(1); + + @Override + protected Object decode(ChannelHandlerContext ctx, + Channel channel, + ChannelBuffer cb) throws Exception { + + if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { + log.debug("Error: Packet length is less then minimum length"); + return null; + } + + byte[] marker = new byte[MINIMUM_HEADER_MARKER_LENGTH]; + cb.readBytes(marker); + for (int i = 0; i < marker.length; i++) { + if (marker[i] != (byte) 0xff) { + log.debug("Error: Marker must be set all ones"); + ctx.getChannel().close(); + return null; + } + } + + short length = cb.readShort(); + if (length < MINIMUM_COMMON_HEADER_LENGTH) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return null; + } + + if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return null; + } + + byte type = cb.readByte(); + int len = length - MINIMUM_COMMON_HEADER_LENGTH; + + ChannelBuffer message = cb.readBytes(len); + + switch (type) { + case OPEN_MSG_TYPE: + processBgpOpen(ctx, message); + break; + case UPDATE_MSG_TYPE: + break; + case NOTIFICATION_MSG_TYPE: + processBgpNotification(ctx, message); + break; + case KEEPALIVE_MSG_TYPE: + processBgpKeepalive(ctx, message); + break; + default: + ctx.getChannel().close(); + return null; + } + + return null; + } + + /** + * Processes BGP open message. + * + * @param ctx Channel handler context + * @param message open message + */ + private void processBgpOpen(ChannelHandlerContext ctx, + ChannelBuffer message) { + int minLength = + MINIMUM_OPEN_MSG_LENGTH - MINIMUM_COMMON_HEADER_LENGTH; + if (message.readableBytes() < minLength) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return; + } + + message.readByte(); // read version + message.readShort(); // read AS number + message.readShort(); // read Hold timer + message.readInt(); // read BGP Identifier + // Optional Parameters + int optParamLen = message.readUnsignedByte(); + if (message.readableBytes() < optParamLen) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return; + } + message.readBytes(optParamLen); + + // Open message received + receivedOpenMessageLatch.countDown(); + } + + /** + * Processes BGP keepalive message. + * + * @param ctx Channel handler context + * @param message keepalive message + */ + private void processBgpKeepalive(ChannelHandlerContext ctx, + ChannelBuffer message) { + + // Keepalive message received + receivedKeepaliveMessageLatch.countDown(); + } + + /** + * Processes BGP notification message. + * + * @param ctx Channel handler context + * @param message notification message + */ + private void processBgpNotification(ChannelHandlerContext ctx, + ChannelBuffer message) { + byte[] data; + message.readByte(); //read error code + message.readByte(); // read error sub code + if (message.readableBytes() > 0) { + data = new byte[message.readableBytes()]; + message.readBytes(data, 0, message.readableBytes()); + } + + // Notification message received + receivedNotificationMessageLatch.countDown(); + } +}
\ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java new file mode 100644 index 00000000..7c0fa417 --- /dev/null +++ b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java @@ -0,0 +1,595 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.controller.impl; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import java.util.LinkedList; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpAddress.Version; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; +import org.onosproject.bgpio.types.AsPath; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.LocalPref; +import org.onosproject.bgpio.types.Med; +import org.onosproject.bgpio.types.Origin; +import org.onosproject.bgp.controller.impl.BgpSelectionAlgo; + +/** + * Test cases for BGP Selection Algorithm. + */ +public class BgpSelectionAlgoTest { + + /** + * firstPathAttribute and secondPathAttribute has same AS count and firstPathAttribute + * has shortest Origin value than secondPathAttribute. + */ + @Test + public void selectionAlgoTest1() throws BgpParseException { + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + //origin with IGP + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + //AsPath with AS_SEQ with one AS + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xea }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + //origin with INCOMPLETE + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + //AsPath with AS_SEQ with one AS + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * firstPathAttribute has 1 AS count and secondPathAttribute has 2 AS count + * and firstPathAttribute has shortest Origin value than secondPathAttribute. + */ + @Test + public void selectionAlgoTest2() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x08, 0x02, 0x01, (byte) 0xfd, + (byte) 0xea, 0x02, 0x01, (byte) 0xfd, (byte) 0xea }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * firstPathAttribute and secondPathAttribute has same AS value + * and firstPathAttribute has shortest Origin value than secondPathAttribute. + */ + @Test + public void selectionAlgoTest3() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * firstPathAttribute has lowest med than secondPathAttribute. + */ + @Test + public void selectionAlgoTest4() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] med = new byte[] {(byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, + 0x00 }; + buffer.writeBytes(med); + pathAttribute1 = Med.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + med = new byte[] {(byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01 }; + buffer.writeBytes(med); + pathAttribute2 = Med.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * secondPathAttribute has higher local preference than firstPathAttribute. + */ + @Test + public void selectionAlgoTest5() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] locPref = new byte[] {(byte) 0x00, 0x05, 0x04, 0x00, 0x00, + 0x00, 0x01 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(locPref); + pathAttribute1 = LocalPref.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + locPref = new byte[] {(byte) 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x0a }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(locPref); + pathAttribute2 = LocalPref.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * secondPathAttribute is EBGP than firstPathAttribute is IBGP. + */ + @Test + public void selectionAlgoTest6() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = true; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, false, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * firstPathAttribute has lower BGPID than secondPathAttribute. + */ + @Test + public void selectionAlgoTest7() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + Integer bgpId = 168430080; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //B0A0A00 + bgpId = 185207296; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * secondPathAttribute has lowest peer address than firstPathAttribute. + */ + @Test + public void selectionAlgoTest8() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + Integer bgpId = 168430080; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + bgpId = 168430080; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * firstPathAttribute and secondPathAttribute are same. + */ + @Test + public void selectionAlgoTest9() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + Integer bgpId = 168430080; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList<BgpValueType> pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + bgpId = 168430080; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(0)); + } +} |