aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl')
-rw-r--r--framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java132
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java896
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java364
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java133
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java266
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java72
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java603
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java60
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java60
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java124
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java121
-rw-r--r--framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java346
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java74
-rw-r--r--framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java242
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java93
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java254
-rw-r--r--framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java209
-rwxr-xr-xframework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java20
18 files changed, 4069 insertions, 0 deletions
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java b/framework/src/onos/protocols/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/protocols/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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
new file mode 100755
index 00000000..0c55eadc
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
@@ -0,0 +1,896 @@
+/*
+ * 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.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.nio.channels.ClosedChannelException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
+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.bgpio.types.FourOctetAsNumCapabilityTlv;
+import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
+import org.slf4j.Logger;
+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 {
+
+ 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 Channel channel;
+ private BgpKeepAliveTimer keepAliveTimer = null;
+ private short peerHoldTime = 0;
+ private short negotiatedHoldTime = 0;
+ private long peerAsNum;
+ private int peerIdentifier;
+ 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;
+ static final int AS_TRANS = 23456;
+ static final int MAX_AS2_NUM = 65535;
+ static final short AFI = 16388;
+ static final byte RES = 0;
+ static final byte SAFI = 71;
+
+ // State needs to be volatile because the HandshakeTimeoutHandler
+ // needs to check if the handshake is complete
+ private volatile ChannelState state;
+
+ // When a bgp peer with a ip addresss is found (i.e we already have a
+ // connected peer with the same ip), the new peer is immediately
+ // disconnected. At that point netty callsback channelDisconnected() which
+ // proceeds to cleaup peer state - we need to ensure that it does not
+ // cleanup
+ // 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;
+ private boolean isIbgpSession;
+ private BgpSessionInfoImpl sessionInfo;
+ private BgpPeerManagerImpl peerManager;
+ private InetSocketAddress inetAddress;
+ private IpAddress ipAddress;
+ private SocketAddress address;
+ private String peerAddr;
+ private BgpCfg bgpconfig;
+
+ /**
+ * Create a new unconnected BGPChannelHandler.
+ *
+ * @param bgpController bgp controller
+ */
+ BgpChannelHandler(BgpController bgpController) {
+ this.bgpController = bgpController;
+ this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager();
+ this.state = ChannelState.IDLE;
+ this.factory4 = Controller.getBgpMessageFactory4();
+ this.duplicateBGPIdFound = Boolean.FALSE;
+ this.bgpPacketStats = new BgpPacketStatsImpl();
+ this.bgpconfig = bgpController.getConfig();
+ }
+
+ // To disconnect peer session.
+ public void disconnectPeer() {
+ bgpPeer.disconnectPeer();
+ }
+
+ // *************************
+ // Channel State Machine
+ // *************************
+
+ /**
+ * The state machine for handling the peer/channel state. All state transitions should happen from within the state
+ * machine (and not from other parts of the code)
+ */
+ enum ChannelState {
+ /**
+ * Initial state before channel is connected.
+ */
+ IDLE(false) {
+
+ },
+
+ OPENSENT(false) {
+ @Override
+ 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) {
+ // 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());
+ log.debug("Message is not OPEN message");
+ } else {
+ log.debug("Sending keep alive message in OPENSENT state");
+ h.bgpPacketStats.addInPacket();
+
+ 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");
+
+ /*
+ * RFC 4271, section 4.2: Upon receipt of an OPEN message, a BGP speaker MUST calculate the
+ * value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time
+ * received in the OPEN message
+ */
+ h.peerHoldTime = pOpenmsg.getHoldTime();
+ if (h.peerHoldTime < h.bgpconfig.getHoldTime()) {
+ h.channel.getPipeline().replace("holdTime",
+ "holdTime",
+ new ReadTimeoutHandler(BgpPipelineFactory.TIMER,
+ h.peerHoldTime));
+ }
+
+ log.info("Hold Time : " + h.peerHoldTime);
+
+ // update AS number
+ h.peerAsNum = pOpenmsg.getAsNumber();
+ }
+
+ // Send keepalive message to peer.
+ h.sendKeepAliveMessage();
+ h.bgpPacketStats.addOutPacket();
+ h.setState(OPENCONFIRM);
+ h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM);
+ }
+ }
+ },
+
+ OPENWAIT(false) {
+ @Override
+ 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) {
+ // 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());
+ log.debug("Message is not OPEN message");
+ } else {
+ h.bgpPacketStats.addInPacket();
+
+ 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");
+
+ /*
+ * RFC 4271, section 4.2: Upon receipt of an OPEN message, a BGP speaker MUST calculate the
+ * value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time
+ * received in the OPEN message
+ */
+ h.peerHoldTime = pOpenmsg.getHoldTime();
+ if (h.peerHoldTime < h.bgpconfig.getHoldTime()) {
+ h.channel.getPipeline().replace("holdTime",
+ "holdTime",
+ new ReadTimeoutHandler(BgpPipelineFactory.TIMER,
+ h.peerHoldTime));
+ }
+
+ log.debug("Hold Time : " + h.peerHoldTime);
+
+ // update AS number
+ h.peerAsNum = pOpenmsg.getAsNumber();
+
+ h.sendHandshakeOpenMessage();
+ h.bgpPacketStats.addOutPacket();
+ h.setState(OPENCONFIRM);
+ h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM);
+ }
+ }
+ }
+ },
+
+ OPENCONFIRM(false) {
+ @Override
+ 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) {
+ // 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());
+ log.debug("Message is not KEEPALIVE message");
+ } else {
+
+ // Set the peer connected status
+ h.bgpPacketStats.addInPacket();
+ log.debug("Sending keep alive message in OPENCONFIRM state");
+
+ final InetSocketAddress inetAddress = (InetSocketAddress) h.address;
+ h.thisbgpId = BgpId.bgpId(IpAddress.valueOf(inetAddress.getAddress()));
+
+ // set session parameters
+ h.negotiatedHoldTime = (h.peerHoldTime < h.bgpconfig.getHoldTime()) ? h.peerHoldTime
+ : h.bgpconfig.getHoldTime();
+ 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);
+ // set the status of bgp as connected
+ h.bgpPeer.setConnected(true);
+ h.bgpPeer.setChannel(h.channel);
+
+ /*
+ * RFC 4271, When an OPEN message is received, sends a KEEPALIVE message, If the negotiated hold
+ * time value is zero, then the HoldTimer and KeepaliveTimer are not started. A reasonable maximum
+ * time between KEEPALIVE messages would be one third of the Hold Time interval.
+ */
+
+ if (h.negotiatedHoldTime != 0) {
+ h.keepAliveTimer = new BgpKeepAliveTimer(h,
+ (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL));
+ } else {
+ h.sendKeepAliveMessage();
+ }
+
+ h.bgpPacketStats.addOutPacket();
+
+ // set the state handshake completion.
+ h.setHandshakeComplete(true);
+
+ if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) {
+ disconnectDuplicate(h);
+ } else {
+ h.setState(ESTABLISHED);
+ h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.ESTABLISHED);
+ }
+ }
+ }
+ },
+
+ ESTABLISHED(true) {
+ @Override
+ void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException {
+ log.debug("Message received in established state " + m.getType());
+ // dispatch the message
+ h.dispatchMessage(m);
+ }
+ };
+
+ private boolean handshakeComplete;
+
+ ChannelState(boolean handshakeComplete) {
+ this.handshakeComplete = handshakeComplete;
+ }
+
+ /**
+ * Is this a state in which the handshake has completed?
+ *
+ * @return true if the handshake is complete
+ */
+ public boolean isHandshakeComplete() {
+ return this.handshakeComplete;
+ }
+
+ /**
+ * Disconnect duplicate peer connection.
+ *
+ * @param h channel handler
+ */
+ protected void disconnectDuplicate(BgpChannelHandler h) {
+ log.error("Duplicated BGP IP or incompleted cleanup - " + "" + "disconnecting channel {}",
+ h.getPeerInfoString());
+ h.duplicateBGPIdFound = Boolean.TRUE;
+ h.channel.disconnect();
+ }
+
+ // set handshake completion status
+ public void setHandshakeComplete(boolean handshakeComplete) {
+ this.handshakeComplete = handshakeComplete;
+ }
+
+ void processBgpMessage(BgpChannelHandler bgpChannelHandler, BgpMessage pm)
+ throws IOException, BgpParseException {
+ // TODO Auto-generated method stub
+ log.debug("BGP message stub");
+ }
+
+ }
+
+ // *************************
+ // Channel handler methods
+ // *************************
+
+ @Override
+ public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+
+ channel = e.getChannel();
+ log.info("BGP connected from {}", channel.getRemoteAddress());
+
+ address = channel.getRemoteAddress();
+ if (!(address instanceof InetSocketAddress)) {
+ throw new IOException("Invalid peer connection.");
+ }
+
+
+ inetAddress = (InetSocketAddress) address;
+ peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString();
+
+
+ // if connection is already established close channel
+ if (peerManager.isPeerConnected(BgpId.bgpId(IpAddress.valueOf(peerAddr)))) {
+ log.debug("Duplicate connection received, peer {}", peerAddr);
+ channel.close();
+ return;
+ }
+
+ if (null != channel.getPipeline().get("PassiveHandler")) {
+ log.info("BGP handle connection request from peer");
+ // Wait for open message from bgp peer
+ setState(ChannelState.OPENWAIT);
+ } else if (null != channel.getPipeline().get("ActiveHandler")) {
+ log.info("BGP handle connection response from peer");
+
+ sendHandshakeOpenMessage();
+ bgpPacketStats.addOutPacket();
+ setState(ChannelState.OPENSENT);
+ bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.OPENSENT);
+ }
+ }
+
+ @Override
+ public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+
+ channel = e.getChannel();
+ log.info("BGP disconnected callback for bgp:{}. Cleaning up ...", getPeerInfoString());
+
+ address = channel.getRemoteAddress();
+ if (!(address instanceof InetSocketAddress)) {
+ throw new IOException("Invalid peer connection.");
+ }
+
+ inetAddress = (InetSocketAddress) address;
+ peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString();
+
+ if (thisbgpId != null) {
+ if (!duplicateBGPIdFound) {
+ // if the disconnected peer (on this ChannelHandler)
+ // was not one with a duplicate, it is safe to remove all
+ // state for it at the controller. Notice that if the disconnected
+ // peer was a duplicate-ip, calling the method below would clear
+ // all state for the original peer (with the same ip),
+ // which we obviously don't want.
+ log.debug("{}:removal called", getPeerInfoString());
+ if (bgpPeer != null) {
+ BgpPeerImpl peer = (BgpPeerImpl) bgpPeer;
+ peerManager.removeConnectedPeer(thisbgpId);
+ peer.updateLocalRIBOnPeerDisconnect();
+ }
+
+ // 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
+ // not cleaned up - XXX check liveness of original ChannelHandler
+ log.debug("{}:duplicate found", getPeerInfoString());
+ duplicateBGPIdFound = Boolean.FALSE;
+ }
+
+ if (null != keepAliveTimer) {
+ keepAliveTimer.getKeepAliveTimer().cancel();
+ }
+ } else {
+ bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE);
+ log.warn("No bgp ip in channelHandler registered for " + "disconnected peer {}", getPeerInfoString());
+ }
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
+
+ log.info("[exceptionCaught]: " + e.toString());
+
+ if (e.getCause() instanceof ReadTimeoutException) {
+ 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);
+ 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);
+ channel.close();
+ state = ChannelState.IDLE;
+ return;
+ }
+ } else if (e.getCause() instanceof ClosedChannelException) {
+ log.debug("Channel for bgp {} already closed", getPeerInfoString());
+ } else if (e.getCause() instanceof IOException) {
+ log.error("Disconnecting peer {} due to IO Error: {}", getPeerInfoString(), e.getCause().getMessage());
+ if (log.isDebugEnabled()) {
+ // still print stack trace if debug is enabled
+ log.debug("StackTrace for previous Exception: ", e.getCause());
+ }
+ channel.close();
+ } else if (e.getCause() instanceof BgpParseException) {
+ byte[] data = new byte[] {};
+ BgpParseException errMsg = (BgpParseException) e.getCause();
+ byte errorCode = errMsg.getErrorCode();
+ byte errorSubCode = errMsg.getErrorSubCode();
+ ChannelBuffer tempCb = errMsg.getData();
+ if (tempCb != null) {
+ int dataLength = tempCb.capacity();
+ data = new byte[dataLength];
+ tempCb.readBytes(data, 0, dataLength);
+ }
+ sendNotification(errorCode, errorSubCode, data);
+ } else if (e.getCause() instanceof RejectedExecutionException) {
+ log.warn("Could not process message: queue full");
+ } else {
+ log.error("Error while processing message from peer " + getPeerInfoString() + "state " + this.state);
+ channel.close();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getPeerInfoString();
+ }
+
+ @Override
+ 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) {
+ // Do the actual packet processing
+ state.processBgpMessage(this, pm);
+ }
+ } else {
+ 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;
+ }
+
+ // *************************
+ // Channel utility methods
+ // *************************
+ /**
+ * Set handshake status.
+ *
+ * @param handshakeComplete handshake complete status
+ */
+ public void setHandshakeComplete(boolean handshakeComplete) {
+ this.state.setHandshakeComplete(handshakeComplete);
+ }
+
+ /**
+ * Is this a state in which the handshake has completed?
+ *
+ * @return true if the handshake is complete
+ */
+ public boolean isHandshakeComplete() {
+ return state.isHandshakeComplete();
+ }
+
+ /**
+ * To handle the BGP message.
+ *
+ * @param m bgp message
+ * @throws BgpParseException throw exception
+ */
+ private void dispatchMessage(BgpMessage m) throws BgpParseException {
+ bgpPacketStats.addInPacket();
+ bgpController.processBGPPacket(thisbgpId, m);
+ }
+
+ /**
+ * Return a string describing this peer based on the already available information (ip address and/or remote
+ * socket).
+ *
+ * @return display string
+ */
+ private String getPeerInfoString() {
+ if (bgpPeer != null) {
+ return bgpPeer.toString();
+ }
+ String channelString;
+ if (channel == null || channel.getRemoteAddress() == null) {
+ channelString = "?";
+ } else {
+ channelString = channel.getRemoteAddress().toString();
+ }
+ String bgpIpString;
+ // TODO: implement functionality to get bgp id string
+ bgpIpString = "?";
+ return String.format("[%s BGP-IP[%s]]", channelString, bgpIpString);
+ }
+
+ /**
+ * Update the channels state. Only called from the state machine. TODO: enforce restricted state transitions
+ *
+ * @param state
+ */
+ private void setState(ChannelState state) {
+ this.state = state;
+ }
+
+ /**
+ * get packet statistics.
+ *
+ * @return packet statistics
+ */
+ public BgpPacketStatsImpl getBgpPacketStats() {
+ return bgpPacketStats;
+ }
+
+ /**
+ * Send handshake open message to the peer.
+ *
+ * @throws IOException, BgpParseException
+ */
+ private void sendHandshakeOpenMessage() throws IOException, BgpParseException {
+ int bgpId;
+
+ InetSocketAddress localAddress = (InetSocketAddress) channel.getLocalAddress();
+
+ bgpId = Ip4Address.valueOf(IpAddress.valueOf(localAddress.getAddress()).toString()).toInt();
+ BgpMessage msg = factory4.openMessageBuilder().setAsNumber((short) peerAsNum)
+ .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));
+
+ }
+
+ /**
+ * Send notification message to peer.
+ *
+ * @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
+ */
+ private void sendNotification(byte errorCode, byte errorSubCode, byte[] data)
+ 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));
+ }
+
+ /**
+ * Send keep alive message.
+ *
+ * @throws IOException when channel is disconnected
+ * @throws BgpParseException while building keep alive message
+ */
+ synchronized void sendKeepAliveMessage() throws IOException, BgpParseException {
+
+ BgpMessage msg = factory4.keepaliveMessageBuilder().build();
+ log.debug("Sending keepalive message to {}", channel.getRemoteAddress());
+ channel.write(Collections.singletonList(msg));
+ }
+
+ /**
+ * Process unknown BGP message received.
+ *
+ * @param errorCode error code
+ * @param errorSubCode error sub code
+ * @param data message type
+ * @throws BgpParseException while processing error messsage
+ * @throws IOException while processing error message
+ */
+ 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;
+ sendNotification(errorCode, errorSubCode, byteArray);
+ channel.close();
+ }
+
+ /**
+ * BGP open message validation.
+ *
+ * @param h channel handler
+ * @param openMsg open message
+ * @return true if valid message, otherwise false
+ * @throws BgpParseException throw exception
+ */
+ 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);
+ }
+
+
+ // Validate hold timer
+ if ((openMsg.getHoldTime() != 0) && (openMsg.getHoldTime() < BGP_MIN_HOLDTIME)) {
+ throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNACCEPTABLE_HOLD_TIME, null);
+ }
+
+ // Validate capabilities
+ result = capabilityValidation(h, openMsg);
+ return result;
+ }
+
+ /**
+ * Capability Validation.
+ *
+ * @param h channel handler
+ * @param openmsg open message
+ * @return success or failure
+ * @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;
+ boolean isLargeAsCapabilityCfg = h.bgpconfig.getLargeASCapability();
+ boolean isLsCapabilityCfg = h.bgpconfig.getLsCapability();
+
+ while (listIterator.hasNext()) {
+ BgpValueType tlv = listIterator.next();
+ if (tlv.getType() == MULTI_PROTOCOL_EXTN_CAPA_TYPE) {
+ isMultiProtocolcapabilityExists = true;
+ }
+ if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
+ isFourOctetCapabilityExits = true;
+ capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
+ }
+ }
+
+ if (isFourOctetCapabilityExits) {
+ if (capAsNum > MAX_AS2_NUM) {
+ if (openmsg.getAsNumber() != AS_TRANS) {
+ 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);
+ }
+ }
+ }
+
+ if ((isLsCapabilityCfg)) {
+ if (!isMultiProtocolcapabilityExists) {
+ tempTlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
+ unSupportedCapabilityTlv.add(tempTlv);
+ }
+ }
+
+ if ((isLargeAsCapabilityCfg)) {
+ if (!isFourOctetCapabilityExits) {
+ tempTlv = new FourOctetAsNumCapabilityTlv(h.bgpconfig.getAsNumber());
+ unSupportedCapabilityTlv.add(tempTlv);
+ }
+ }
+
+ if (unSupportedCaplistIterator.hasNext()) {
+ ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
+ while (unSupportedCaplistIterator.hasNext()) {
+ BgpValueType tlv = unSupportedCaplistIterator.next();
+ tlv.write(buffer);
+ }
+ throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNSUPPORTED_CAPABILITY, buffer);
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * AS Number Validation.
+ *
+ * @param h channel Handler
+ * @param openMsg open message
+ * @return true or false
+ */
+ 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();
+
+ while (listIterator.hasNext()) {
+ BgpValueType tlv = listIterator.next();
+ if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
+ isFourOctetCapabilityExits = true;
+ capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
+ }
+ }
+
+ if (peerCfg.getAsNumber() > MAX_AS2_NUM) {
+ if (openMsg.getAsNumber() != AS_TRANS) {
+ return false;
+ }
+
+ if (!isFourOctetCapabilityExits) {
+ return false;
+ }
+
+ if (peerCfg.getAsNumber() != capAsNum) {
+ return false;
+ }
+
+ isIbgpSession = peerCfg.getIsIBgp();
+ if (isIbgpSession) {
+ // IBGP - AS number should be same for Peer and local if it is IBGP
+ if (h.bgpconfig.getAsNumber() != capAsNum) {
+ return false;
+ }
+ }
+ } else {
+
+ if (openMsg.getAsNumber() != peerCfg.getAsNumber()) {
+ return false;
+ }
+
+ if (isFourOctetCapabilityExits) {
+ if (capAsNum != peerCfg.getAsNumber()) {
+ return false;
+ }
+ }
+
+ isIbgpSession = peerCfg.getIsIBgp();
+ if (isIbgpSession) {
+ // IBGP - AS number should be same for Peer and local if it is IBGP
+ if (openMsg.getAsNumber() != h.bgpconfig.getAsNumber()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Validates BGP ID.
+ *
+ * @param openMsg open message
+ * @return true or false
+ */
+ private boolean bgpIdValidation(BgpOpenMsg openMsg) {
+ String openMsgBgpId = Ip4Address.valueOf(openMsg.getBgpId()).toString();
+
+ InetAddress ipAddress;
+ try {
+ ipAddress = InetAddress.getByName(openMsgBgpId);
+ if (ipAddress.isMulticastAddress()) {
+ return false;
+ }
+ } catch (UnknownHostException e) {
+ log.debug("InetAddress convertion failed");
+ }
+ return true;
+ }
+}
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
new file mode 100755
index 00000000..95a07ad5
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
@@ -0,0 +1,364 @@
+/*
+ * 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.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onosproject.bgp.controller.BgpCfg;
+import org.onosproject.bgp.controller.BgpConnectPeer;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides BGP configuration of this BGP speaker.
+ */
+public class BgpConfig implements BgpCfg {
+
+ 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;
+ private static final short DEFAULT_CONN_RETRY_COUNT = 5;
+
+ private State state = State.INIT;
+ private int localAs;
+ private int maxSession;
+ private boolean lsCapability;
+ private short holdTime;
+ private boolean largeAs = false;
+ private int maxConnRetryTime;
+ private int maxConnRetryCount;
+
+ private Ip4Address routerId = null;
+ private TreeMap<String, BgpPeerCfg> bgpPeerTree = new TreeMap<>();
+ private BgpConnectPeer connectPeer;
+ private BgpPeerManagerImpl peerManager;
+ private BgpController bgpController;
+
+ /*
+ * Constructor to initialize the values.
+ */
+ public BgpConfig(BgpController bgpController) {
+ this.bgpController = bgpController;
+ this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager();
+ this.holdTime = DEFAULT_HOLD_TIMER;
+ this.maxConnRetryTime = DEFAULT_CONN_RETRY_TIME;
+ this.maxConnRetryCount = DEFAULT_CONN_RETRY_COUNT;
+ this.lsCapability = true;
+ }
+
+ @Override
+ public State getState() {
+ return state;
+ }
+
+ @Override
+ public void setState(State state) {
+ this.state = state;
+ }
+
+ @Override
+ public int getAsNumber() {
+ return this.localAs;
+ }
+
+ @Override
+ public void setAsNumber(int localAs) {
+
+ State localState = getState();
+ this.localAs = localAs;
+
+ /* Set configuration state */
+ if (localState == State.IP_CONFIGURED) {
+ setState(State.IP_AS_CONFIGURED);
+ } else {
+ setState(State.AS_CONFIGURED);
+ }
+ }
+
+ @Override
+ public int getMaxSession() {
+ return this.maxSession;
+ }
+
+ @Override
+ public void setMaxSession(int maxSession) {
+ this.maxSession = maxSession;
+ }
+
+ @Override
+ public boolean getLsCapability() {
+ return this.lsCapability;
+ }
+
+ @Override
+ public void setLsCapability(boolean lsCapability) {
+ this.lsCapability = lsCapability;
+ }
+
+ @Override
+ public String getRouterId() {
+ if (this.routerId != null) {
+ return this.routerId.toString();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void setRouterId(String routerId) {
+ State localState = getState();
+ this.routerId = Ip4Address.valueOf(routerId);
+
+ /* Set configuration state */
+ if (localState == State.AS_CONFIGURED) {
+ setState(State.IP_AS_CONFIGURED);
+ } else {
+ setState(State.IP_CONFIGURED);
+ }
+ }
+
+ @Override
+ public boolean addPeer(String routerid, int remoteAs) {
+ return addPeer(routerid, remoteAs, DEFAULT_HOLD_TIMER);
+ }
+
+ @Override
+ public boolean addPeer(String routerid, short holdTime) {
+ return addPeer(routerid, this.getAsNumber(), holdTime);
+ }
+
+ @Override
+ public boolean addPeer(String routerid, int remoteAs, short holdTime) {
+ 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.setSelfInnitConnection(false);
+
+ if (this.getAsNumber() == remoteAs) {
+ lspeer.setIsIBgp(true);
+ } else {
+ lspeer.setIsIBgp(false);
+ }
+
+ this.bgpPeerTree.put(routerid, lspeer);
+ log.debug("added successfully");
+ return true;
+ } else {
+ log.debug("already exists");
+ return false;
+ }
+ }
+
+ @Override
+ public boolean connectPeer(String routerid) {
+ BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid);
+
+ if (lspeer != null) {
+ lspeer.setSelfInnitConnection(true);
+
+ if (lspeer.connectPeer() == null) {
+ connectPeer = new BgpConnectPeerImpl(bgpController, routerid, Controller.getBgpPortNum());
+ lspeer.setConnectPeer(connectPeer);
+ connectPeer.connectPeer();
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean removePeer(String routerid) {
+ BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid);
+
+ if (lspeer != null) {
+
+ disconnectPeer(routerid);
+ lspeer.setSelfInnitConnection(false);
+ lspeer = this.bgpPeerTree.remove(routerid);
+ log.debug("Deleted : " + routerid + " successfully");
+
+ return true;
+ } else {
+ log.debug("Did not find : " + routerid);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean disconnectPeer(String routerid) {
+ BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid);
+
+ if (lspeer != null) {
+
+ BgpPeer disconnPeer = peerManager.getPeer(BgpId.bgpId(IpAddress.valueOf(routerid)));
+ if (disconnPeer != null) {
+ // TODO: send notification peer deconfigured
+ disconnPeer.disconnectPeer();
+ }
+ lspeer.connectPeer().disconnectPeer();
+ lspeer.setState(BgpPeerCfg.State.IDLE);
+ lspeer.setSelfInnitConnection(false);
+ log.debug("Disconnected : " + routerid + " successfully");
+
+ return true;
+ } else {
+ log.debug("Did not find : " + routerid);
+ return false;
+ }
+ }
+
+ @Override
+ public void setPeerConnState(String routerid, BgpPeerCfg.State state) {
+ BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid);
+
+ if (lspeer != null) {
+ lspeer.setState(state);
+ log.debug("Peer : " + routerid + " is not available");
+
+ return;
+ } else {
+ log.debug("Did not find : " + routerid);
+ return;
+ }
+ }
+
+ @Override
+ 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
+ }
+ }
+
+ @Override
+ public boolean isPeerConnectable(String routerid) {
+ BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid);
+
+ if ((lspeer != null) && lspeer.getState().equals(BgpPeerCfg.State.IDLE)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public TreeMap<String, BgpPeerCfg> getPeerTree() {
+ return this.bgpPeerTree;
+ }
+
+ @Override
+ 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;
+
+ while (list.hasNext()) {
+ Entry<String, BgpPeerCfg> me = list.next();
+ lspeer = me.getValue();
+ log.debug("Peer neighbor IP :" + me.getKey());
+ log.debug(", AS Number : " + lspeer.getAsNumber());
+ log.debug(", Hold Timer : " + lspeer.getHoldtime());
+ log.debug(", Is iBGP : " + lspeer.getIsIBgp());
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public BgpPeerCfg displayPeers(String routerid) {
+
+ if (this.bgpPeerTree.isEmpty()) {
+ log.debug("There are no Bgp peers");
+ } else {
+ return this.bgpPeerTree.get(routerid);
+ }
+ return null;
+ }
+
+ @Override
+ public void setHoldTime(short holdTime) {
+ this.holdTime = holdTime;
+ }
+
+ @Override
+ public short getHoldTime() {
+ return this.holdTime;
+ }
+
+ @Override
+ public boolean getLargeASCapability() {
+ return this.largeAs;
+ }
+
+ @Override
+ public void setLargeASCapability(boolean largeAs) {
+ this.largeAs = largeAs;
+ }
+
+ @Override
+ public boolean isPeerConfigured(String routerid) {
+ BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid);
+ return (lspeer != null) ? true : false;
+ }
+
+ @Override
+ public boolean isPeerConnected(String routerid) {
+ // TODO: is peer connected
+ return true;
+ }
+
+ @Override
+ public int getMaxConnRetryCount() {
+ return this.maxConnRetryCount;
+ }
+
+ @Override
+ public void setMaxConnRetryCout(int retryCount) {
+ this.maxConnRetryCount = retryCount;
+ }
+
+ @Override
+ public int getMaxConnRetryTime() {
+ return this.maxConnRetryTime;
+ }
+
+ @Override
+ public void setMaxConnRetryTime(int retryTime) {
+ this.maxConnRetryTime = retryTime;
+ }
+}
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java b/framework/src/onos/protocols/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/protocols/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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
new file mode 100755
index 00000000..51ab68be
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
@@ -0,0 +1,266 @@
+/*
+ * 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.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+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.BgpLocalRib;
+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.protocol.BgpUpdateMsg;
+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;
+
+@Component(immediate = true)
+@Service
+public class BgpControllerImpl implements BgpController {
+
+ private static final Logger log = LoggerFactory.getLogger(BgpControllerImpl.class);
+
+ protected ConcurrentHashMap<BgpId, BgpPeer> connectedPeers = new ConcurrentHashMap<BgpId, BgpPeer>();
+
+ protected BgpPeerManagerImpl peerManager = new BgpPeerManagerImpl();
+
+ private BgpLocalRib bgplocalRIB = new BgpLocalRibImpl(this);
+ private BgpLocalRib bgplocalRIBVpn = new BgpLocalRibImpl(this);
+
+ protected Set<BgpNodeListener> bgpNodeListener = new CopyOnWriteArraySet<>();
+
+ final Controller ctrl = new Controller(this);
+
+ private BgpConfig bgpconfig = new BgpConfig(this);
+
+ @Activate
+ public void activate() {
+ this.ctrl.start();
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ // Close all connected peers
+ closeConnectedPeers();
+ this.ctrl.stop();
+ log.info("Stopped");
+ }
+
+ @Override
+ public Iterable<BgpPeer> getPeers() {
+ return this.connectedPeers.values();
+ }
+
+ @Override
+ public BgpPeer getPeer(BgpId bgpId) {
+ return this.connectedPeers.get(bgpId);
+ }
+
+ @Override
+ public void addListener(BgpNodeListener listener) {
+ this.bgpNodeListener.add(listener);
+ }
+
+ @Override
+ public void removeListener(BgpNodeListener listener) {
+ this.bgpNodeListener.remove(listener);
+ }
+
+ @Override
+ public Set<BgpNodeListener> listener() {
+ return bgpNodeListener;
+ }
+
+ @Override
+ public void writeMsg(BgpId bgpId, BgpMessage msg) {
+ this.getPeer(bgpId).sendMessage(msg);
+ }
+
+ @Override
+ public void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException {
+
+ BgpPeer peer = getPeer(bgpId);
+
+ switch (msg.getType()) {
+ case OPEN:
+ // TODO: Process Open message
+ break;
+ case KEEP_ALIVE:
+ // TODO: Process keepalive message
+ break;
+ case NOTIFICATION:
+ // TODO: Process notificatoin message
+ break;
+ case UPDATE:
+ BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
+ List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
+ if (pathAttr == null) {
+ log.debug("llPathAttr is null, cannot process update message");
+ break;
+ }
+ Iterator<BgpValueType> listIterator = pathAttr.iterator();
+ boolean isLinkstate = false;
+ while (listIterator.hasNext()) {
+ BgpValueType attr = listIterator.next();
+ if ((attr instanceof MpReachNlri) || (attr instanceof MpUnReachNlri)) {
+ isLinkstate = true;
+ }
+ }
+ if (isLinkstate) {
+ peer.buildAdjRibIn(pathAttr);
+ }
+ break;
+ default:
+ // TODO: Process other message
+ break;
+ }
+ }
+
+ @Override
+ public void closeConnectedPeers() {
+ BgpPeer bgpPeer;
+ for (BgpId id : this.connectedPeers.keySet()) {
+ bgpPeer = getPeer(id);
+ bgpPeer.disconnectPeer();
+ }
+ }
+
+ /**
+ * 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 {
+
+ private final Logger log = LoggerFactory.getLogger(BgpPeerManagerImpl.class);
+ private final Lock peerLock = new ReentrantLock();
+
+ @Override
+ 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: {}",
+ bgpId.toString());
+ return false;
+ } else {
+ this.log.debug("Added Peer {}", bgpId.toString());
+ connectedPeers.put(bgpId, bgpPeer);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean isPeerConnected(BgpId bgpId) {
+ if (connectedPeers.get(bgpId) == null) {
+ this.log.error("Is peer connected: bgpIp {}.", bgpId.toString());
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void removeConnectedPeer(BgpId bgpId) {
+ connectedPeers.remove(bgpId);
+ }
+
+ @Override
+ public BgpPeer getPeer(BgpId bgpId) {
+ return connectedPeers.get(bgpId);
+ }
+
+ /**
+ * Gets bgp peer instance.
+ *
+ * @param bgpController controller instance.
+ * @param sessionInfo bgp session info.
+ * @param pktStats packet statistics.
+ * @return BGPPeer peer instance.
+ */
+ 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() {
+ return connectedPeers;
+ }
+
+ @Override
+ public BgpPeerManagerImpl peerManager() {
+ return peerManager;
+ }
+
+ @Override
+ public BgpCfg getConfig() {
+ return this.bgpconfig;
+ }
+
+ @Override
+ public int connectedPeerCount() {
+ return connectedPeers.size();
+ }
+
+ /**
+ * Gets the BGP local RIB.
+ *
+ * @return bgplocalRIB BGP local RIB.
+ */
+ @Override
+ public BgpLocalRib bgpLocalRib() {
+ return bgplocalRIB;
+ }
+
+ /**
+ * Gets the BGP local RIB with VPN.
+ *
+ * @return bgplocalRIBVpn BGP VPN local RIB .
+ */
+ @Override
+ public BgpLocalRib bgpLocalRibVpn() {
+ return bgplocalRIBVpn;
+ }
+}
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java
new file mode 100755
index 00000000..524ac4c1
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java
@@ -0,0 +1,72 @@
+/*
+ * 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.Timer;
+import java.util.TimerTask;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implement sending keepalive message to connected peer periodically based on negotiated holdtime.
+ */
+public class BgpKeepAliveTimer {
+
+ private Timer keepAliveTimer;
+ private BgpChannelHandler handler;
+ private static final Logger log = LoggerFactory.getLogger(BgpKeepAliveTimer.class);
+
+ /**
+ * Gets keepalive timer object.
+ *
+ * @return keepAliveTimer keepalive timer.
+ */
+ public Timer getKeepAliveTimer() {
+ return keepAliveTimer;
+ }
+
+ /**
+ * Initialize timer to send keepalive message periodically.
+ *
+ * @param h channel handler
+ * @param seconds time interval.
+ */
+ public BgpKeepAliveTimer(BgpChannelHandler h, int seconds) {
+ this.handler = h;
+ this.keepAliveTimer = new Timer();
+ this.keepAliveTimer.schedule(new SendKeepAlive(), 0, seconds * 1000);
+ }
+
+ /**
+ * Send keepalive message to connected peer on schedule.
+ */
+ class SendKeepAlive extends TimerTask {
+ @Override
+ public void run() {
+ log.debug("Sending periodic KeepAlive");
+
+ try {
+ // Send keep alive message
+ handler.sendKeepAliveMessage();
+ handler.getBgpPacketStats().addOutPacket();
+ } catch (Exception e) {
+ log.info("Exception occured while sending keepAlive message" + e.toString());
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
new file mode 100755
index 00000000..44b19057
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java
@@ -0,0 +1,603 @@
+/*
+ * 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.Set;
+import java.util.TreeMap;
+
+import org.onosproject.bgp.controller.BgpController;
+import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpLocalRib;
+import org.onosproject.bgp.controller.BgpNodeListener;
+import org.onosproject.bgp.controller.BgpSessionInfo;
+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.protocol.linkstate.PathAttrNlriDetailsLocalRib;
+import org.onosproject.bgpio.types.RouteDistinguisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implementation of local RIB.
+ */
+public class BgpLocalRibImpl implements BgpLocalRib {
+
+ private static final Logger log = LoggerFactory.getLogger(BgpLocalRibImpl.class);
+ private BgpController bgpController;
+
+ private Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> nodeTree = new TreeMap<>();
+ private Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib> linkTree = new TreeMap<>();
+ private Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib> prefixTree = new TreeMap<>();
+
+ private Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnNodeTree
+ = new TreeMap<>();
+ private Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnLinkTree
+ = new TreeMap<>();
+ private Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnPrefixTree
+ = new TreeMap<>();
+
+ public BgpLocalRibImpl(BgpController bgpController) {
+ this.bgpController = bgpController;
+ }
+
+ /**
+ * Gets node NLRI tree.
+ *
+ * @return node tree
+ */
+ public Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> nodeTree() {
+ return nodeTree;
+ }
+
+ /**
+ * Gets link NLRI tree.
+ *
+ * @return link tree
+ */
+ public Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib> linkTree() {
+ return linkTree;
+ }
+
+ /**
+ * Gets prefix NLRI tree.
+ *
+ * @return prefix tree
+ */
+ public Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib> prefixTree() {
+ return prefixTree;
+ }
+
+ /**
+ * Gets VPN node NLRI tree.
+ *
+ * @return vpn node NLRI tree
+ */
+ public Map<RouteDistinguisher, Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnNodeTree() {
+ return vpnNodeTree;
+ }
+
+ /**
+ * Gets VPN link NLRI tree.
+ *
+ * @return vpn link NLRI Tree
+ */
+ public Map<RouteDistinguisher, Map<BgpLinkLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnLinkTree() {
+ return vpnLinkTree;
+ }
+
+ /**
+ * Gets VPN prefix NLRI tree.
+ *
+ * @return vpn prefix NLRI Tree
+ */
+ public Map<RouteDistinguisher, Map<BgpPrefixLSIdentifier, PathAttrNlriDetailsLocalRib>> vpnPrefixTree() {
+ return vpnPrefixTree;
+ }
+
+ @Override
+ public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) {
+ int decisionResult;
+
+ log.debug("Add to local RIB {}", details.toString());
+
+ PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+ sessionInfo.remoteBgpId().ipAddress(),
+ sessionInfo.remoteBgpIdentifier(),
+ sessionInfo.remoteBgpASNum(),
+ sessionInfo.isIbgpSession(), details);
+ if (nlri instanceof BgpNodeLSNlriVer4) {
+ BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors();
+ if (nodeTree.containsKey(nodeLsIdentifier)) {
+ BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+ // Compare local RIB entry with the current attribute
+ decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
+ if (decisionResult < 0) {
+ nodeTree.replace(nodeLsIdentifier, detailsLocRib);
+ log.debug("Local RIB update node: {}", detailsLocRib.toString());
+ }
+ } else {
+ nodeTree.put(nodeLsIdentifier, detailsLocRib);
+ for (BgpNodeListener l : bgpController.listener()) {
+ l.addNode((BgpNodeLSNlriVer4) nlri);
+ }
+ log.debug("Local RIB ad node: {}", detailsLocRib.toString());
+ }
+ } else if (nlri instanceof BgpLinkLsNlriVer4) {
+ BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier();
+ if (linkTree.containsKey(linkLsIdentifier)) {
+ BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+ // Compare local RIB entry with the current attribute
+ decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
+ if (decisionResult < 0) {
+ linkTree.replace(linkLsIdentifier, detailsLocRib);
+ log.debug("Local RIB update link: {}", detailsLocRib.toString());
+ }
+ } else {
+ linkTree.put(linkLsIdentifier, detailsLocRib);
+ log.debug("Local RIB add link: {}", detailsLocRib.toString());
+ }
+ } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+ BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier();
+ if (prefixTree.containsKey(prefixIdentifier)) {
+ BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+ // Compare local RIB entry with the current attribute
+ decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib);
+ if (decisionResult < 0) {
+ prefixTree.replace(prefixIdentifier, detailsLocRib);
+ log.debug("Local RIB update prefix: {}", detailsLocRib.toString());
+ }
+ } else {
+ prefixTree.put(prefixIdentifier, detailsLocRib);
+ log.debug("Local RIB add prefix: {}", detailsLocRib.toString());
+ }
+ }
+ }
+
+ @Override
+ public void delete(BgpLSNlri nlri) {
+ log.debug("Delete from local RIB.");
+
+ // Update local RIB
+ decisionProcess(nlri);
+ }
+
+ /**
+ * Update local RIB based on selection algorithm.
+ *
+ * @param nlri NLRI to update
+ */
+ public void decisionProcess(BgpLSNlri nlri) {
+ checkNotNull(nlri);
+ if (nlri instanceof BgpNodeLSNlriVer4) {
+ selectionProcessNode(nlri, false);
+ } else if (nlri instanceof BgpLinkLsNlriVer4) {
+ selectionProcessLink(nlri, false);
+ } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+ selectionProcessPrefix(nlri, false);
+ }
+ }
+
+ /**
+ * Update VPN local RIB .
+ *
+ * @param nlri NLRI to update
+ * @param routeDistinguisher VPN id to update
+ */
+ public void decisionProcess(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
+ checkNotNull(nlri);
+ if (nlri instanceof BgpNodeLSNlriVer4) {
+ if (vpnNodeTree.containsKey(routeDistinguisher)) {
+ selectionProcessNode(nlri, true);
+ if (nodeTree.size() == 0) {
+ vpnNodeTree.remove(routeDistinguisher);
+ }
+ }
+ } else if (nlri instanceof BgpLinkLsNlriVer4) {
+ if (vpnLinkTree.containsKey(routeDistinguisher)) {
+ selectionProcessLink(nlri, true);
+ if (linkTree.size() == 0) {
+ vpnLinkTree.remove(routeDistinguisher);
+ }
+ }
+ } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) {
+ if (vpnPrefixTree.containsKey(routeDistinguisher)) {
+ selectionProcessPrefix(nlri, true);
+ if (prefixTree.size() == 0) {
+ vpnPrefixTree.remove(routeDistinguisher);
+ }
+ }
+ }
+ }
+
+ /**
+ * Selection process for local RIB node.
+ *
+ * @param nlri NLRI to update
+ * @param isVpnRib true if VPN local RIB, otherwise false
+ */
+ public void selectionProcessNode(BgpLSNlri nlri, boolean isVpnRib) {
+ BgpPeerImpl peer;
+ BgpSessionInfo sessionInfo;
+ int decisionResult;
+ boolean containsKey;
+
+ BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors();
+
+ if (nodeTree.containsKey(nodeLsIdentifier)) {
+ for (BgpNodeListener l : bgpController.listener()) {
+ l.deleteNode((BgpNodeLSNlriVer4) nlri);
+ }
+ log.debug("Local RIB delete node: {}", nodeLsIdentifier.toString());
+ nodeTree.remove(nodeLsIdentifier);
+ }
+
+ for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
+ peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));
+
+ if (nodeTree.containsKey(nodeLsIdentifier)) {
+ containsKey = (!isVpnRib) ? (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) :
+ (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier));
+
+ if (!containsKey) {
+ continue;
+ }
+ sessionInfo = peer.sessionInfo();
+ PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+ sessionInfo.remoteBgpId().ipAddress(),
+ sessionInfo.remoteBgpIdentifier(),
+ sessionInfo.remoteBgpASNum(),
+ sessionInfo.isIbgpSession(),
+ (!isVpnRib) ?
+ (peer.adjacencyRib().nodeTree()
+ .get(nodeLsIdentifier)) :
+ (peer.vpnAdjacencyRib().nodeTree()
+ .get(nodeLsIdentifier)));
+ BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+ decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib);
+ if (decisionResult < 0) {
+ nodeTree.replace(nodeLsIdentifier, detailsLocRib);
+ log.debug("Local RIB node updated: {}", detailsLocRib.toString());
+ }
+ } else {
+ if (!isVpnRib) {
+ if (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) {
+ add(peer.sessionInfo(), nlri, peer.adjacencyRib().nodeTree().get(nodeLsIdentifier));
+ }
+ } else {
+ if (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) {
+ add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().nodeTree().get(nodeLsIdentifier));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Selection process for local RIB link.
+ *
+ * @param nlri NLRI to update
+ * @param isVpnRib true if VPN local RIB, otherwise false
+ */
+ public void selectionProcessLink(BgpLSNlri nlri, boolean isVpnRib) {
+ BgpPeerImpl peer;
+ BgpSessionInfo sessionInfo;
+ int decisionResult;
+ boolean containsKey;
+
+ BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier();
+
+ if (linkTree.containsKey(linkLsIdentifier)) {
+ log.debug("Local RIB remove link: {}", linkLsIdentifier.toString());
+ linkTree.remove(linkLsIdentifier);
+ }
+
+ for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
+ peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));
+
+ if (linkTree.containsKey(linkLsIdentifier)) {
+
+ containsKey = (!isVpnRib) ? (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) :
+ (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier));
+
+ if (!containsKey) {
+ continue;
+ }
+
+ sessionInfo = peer.sessionInfo();
+
+ PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+ sessionInfo.remoteBgpId().ipAddress(),
+ sessionInfo.remoteBgpIdentifier(),
+ sessionInfo.remoteBgpASNum(),
+ sessionInfo.isIbgpSession(),
+ ((!isVpnRib) ?
+ (peer.adjacencyRib().linkTree().get(linkLsIdentifier)) :
+ (peer.vpnAdjacencyRib().linkTree()
+ .get(linkLsIdentifier))));
+
+ BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+ decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib);
+ if (decisionResult < 0) {
+ linkTree.replace(linkLsIdentifier, detailsLocRib);
+ log.debug("Local RIB link updated: {}", detailsLocRib.toString());
+ }
+ } else {
+ if (!isVpnRib) {
+ if (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) {
+ add(peer.sessionInfo(), nlri, peer.adjacencyRib().linkTree().get(linkLsIdentifier));
+ }
+ } else {
+ if (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier)) {
+ add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().linkTree().get(linkLsIdentifier));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Selection process for local RIB prefix.
+ *
+ * @param nlri NLRI to update
+ * @param isVpnRib true if VPN local RIB, otherwise false
+ */
+ public void selectionProcessPrefix(BgpLSNlri nlri, boolean isVpnRib) {
+ BgpPeerImpl peer;
+ BgpSessionInfo sessionInfo;
+ int decisionResult;
+ boolean containsKey;
+
+ BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier();
+ if (prefixTree.containsKey(prefixIdentifier)) {
+ log.debug("Local RIB remove prefix: {}", prefixIdentifier.toString());
+ prefixTree.remove(prefixIdentifier);
+ }
+
+ for (BgpId bgpId : bgpController.connectedPeers().keySet()) {
+ peer = (BgpPeerImpl) (bgpController.getPeer(bgpId));
+
+ if (prefixTree.containsKey(prefixIdentifier)) {
+
+ containsKey = (!isVpnRib) ? (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) :
+ (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier));
+ if (!containsKey) {
+ continue;
+ }
+ sessionInfo = peer.sessionInfo();
+
+ PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib(
+ sessionInfo.remoteBgpId().ipAddress(),
+ sessionInfo.remoteBgpIdentifier(),
+ sessionInfo.remoteBgpASNum(),
+ sessionInfo.isIbgpSession(),
+ ((!isVpnRib) ?
+ (peer.adjacencyRib().prefixTree()
+ .get(prefixIdentifier)) :
+ (peer.vpnAdjacencyRib().prefixTree()
+ .get(prefixIdentifier))));
+
+ BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo();
+ decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib);
+ if (decisionResult < 0) {
+ prefixTree.replace(prefixIdentifier, detailsLocRib);
+ log.debug("local RIB prefix updated: {}", detailsLocRib.toString());
+ }
+ } else {
+ if (!isVpnRib) {
+ if (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) {
+ add(peer.sessionInfo(), nlri, peer.adjacencyRib().prefixTree().get(prefixIdentifier));
+ } else {
+ if (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier)) {
+ add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().prefixTree().get(prefixIdentifier));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details,
+ RouteDistinguisher routeDistinguisher) {
+ add(sessionInfo, 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);
+ }
+ }
+ }
+
+ @Override
+ public void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) {
+ // Update local RIB
+ decisionProcess(nlri, routeDistinguisher);
+ }
+
+ /**
+ * Update local RIB node based on avaliable peer adjacency RIB.
+ *
+ * @param o adjacency-in/VPN adjacency-in
+ */
+ public void localRIBUpdateNode(Object o) {
+
+ if (o instanceof AdjRibIn) {
+ AdjRibIn adjRib = (AdjRibIn) o;
+ log.debug("Update local RIB node.");
+
+ Set<BgpNodeLSIdentifier> nodeKeys = adjRib.nodeTree().keySet();
+ for (BgpNodeLSIdentifier key : nodeKeys) {
+ PathAttrNlriDetails pathAttrNlri = adjRib.nodeTree().get(key);
+
+ BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(), pathAttrNlri
+ .protocolID().getType(), key, false, null);
+ decisionProcess(nodeNlri);
+ }
+ }
+
+ if (o instanceof VpnAdjRibIn) {
+ VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
+ log.debug("Update local RIB VPN node.");
+ Set<RouteDistinguisher> nodeKeysVpn = vpnAdjRib.vpnNodeTree().keySet();
+ Map<BgpNodeLSIdentifier, PathAttrNlriDetails> node;
+ for (RouteDistinguisher keyVpnNode : nodeKeysVpn) {
+ node = vpnAdjRib.vpnNodeTree().get(keyVpnNode);
+
+ Set<BgpNodeLSIdentifier> vpnNodeKeys = node.keySet();
+ for (BgpNodeLSIdentifier key : vpnNodeKeys) {
+ PathAttrNlriDetails pathAttrNlri = vpnAdjRib.nodeTree().get(key);
+ BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(),
+ pathAttrNlri.protocolID().getType(),
+ key, true, keyVpnNode);
+ decisionProcess(nodeNlri, keyVpnNode);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update localRIB link based on avaliable peer adjacency RIB.
+ *
+ * @param o adjacency-in/VPN adjacency-in
+ */
+ public void localRIBUpdateLink(Object o) {
+
+ if (o instanceof AdjRibIn) {
+ AdjRibIn adjRib = (AdjRibIn) o;
+ log.debug("Update local RIB link.");
+
+ Set<BgpLinkLSIdentifier> linkKeys = adjRib.linkTree().keySet();
+ for (BgpLinkLSIdentifier key : linkKeys) {
+ PathAttrNlriDetails pathAttrNlri = adjRib.linkTree().get(key);
+ BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(),
+ pathAttrNlri.identifier(), key, null, false);
+ decisionProcess(linkNlri);
+ }
+ }
+
+ if (o instanceof VpnAdjRibIn) {
+ VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
+ log.debug("Update local RIB VPN link");
+
+ Set<RouteDistinguisher> linkKeysVpn = vpnAdjRib.vpnLinkTree().keySet();
+ Map<BgpLinkLSIdentifier, PathAttrNlriDetails> link;
+ for (RouteDistinguisher keyVpnLink : linkKeysVpn) {
+ link = vpnAdjRib.vpnLinkTree().get(keyVpnLink);
+
+ Set<BgpLinkLSIdentifier> vpnLinkKeys = link.keySet();
+ for (BgpLinkLSIdentifier key : vpnLinkKeys) {
+ PathAttrNlriDetails pathAttrNlri = vpnAdjRib.linkTree().get(key);
+ BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(),
+ pathAttrNlri.identifier(), key, keyVpnLink,
+ true);
+ decisionProcess(linkNlri, keyVpnLink);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update localRIB prefix based on avaliable peer adjacency RIB.
+ *
+ * @param o instance of adjacency-in/VPN adjacency-in
+ */
+ public void localRIBUpdatePrefix(Object o) {
+
+ if (o instanceof AdjRibIn) {
+ AdjRibIn adjRib = (AdjRibIn) o;
+ log.debug("Update local RIB prefix.");
+
+ Set<BgpPrefixLSIdentifier> prefixKeys = adjRib.prefixTree().keySet();
+ for (BgpPrefixLSIdentifier key : prefixKeys) {
+ PathAttrNlriDetails pathAttrNlri = adjRib.prefixTree().get(key);
+ BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(
+ pathAttrNlri.identifier(),
+ pathAttrNlri.protocolID().getType(),
+ key, null, false);
+ decisionProcess(prefixNlri);
+ }
+ }
+
+ if (o instanceof VpnAdjRibIn) {
+ VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o;
+ log.debug("Update local RIB VPN prefix.");
+
+ Set<RouteDistinguisher> prefixKeysVpn = vpnAdjRib.vpnPrefixTree().keySet();
+ Map<BgpPrefixLSIdentifier, PathAttrNlriDetails> prefix;
+ for (RouteDistinguisher keyVpnPrefix : prefixKeysVpn) {
+ prefix = vpnAdjRib.vpnPrefixTree().get(keyVpnPrefix);
+
+ Set<BgpPrefixLSIdentifier> vpnPrefixKeys = prefix.keySet();
+ for (BgpPrefixLSIdentifier key : vpnPrefixKeys) {
+ PathAttrNlriDetails pathAttrNlri = vpnAdjRib.prefixTree().get(key);
+ BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(pathAttrNlri.identifier(),
+ pathAttrNlri.protocolID()
+ .getType(), key,
+ keyVpnPrefix, true);
+ decisionProcess(prefixNlri, keyVpnPrefix);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update localRIB.
+ *
+ * @param adjRibIn adjacency RIB-in
+ */
+ public void localRIBUpdate(AdjRibIn adjRibIn) {
+ log.debug("Update local RIB.");
+
+ localRIBUpdateNode(adjRibIn);
+ localRIBUpdateLink(adjRibIn);
+ localRIBUpdatePrefix(adjRibIn);
+ }
+
+ /**
+ * Update localRIB.
+ *
+ * @param vpnAdjRibIn VPN adjacency RIB-in
+ */
+ public void localRIBUpdate(VpnAdjRibIn vpnAdjRibIn) {
+ log.debug("Update VPN local RIB.");
+
+ localRIBUpdateNode(vpnAdjRibIn);
+ localRIBUpdateLink(vpnAdjRibIn);
+ localRIBUpdatePrefix(vpnAdjRibIn);
+ }
+
+ @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();
+ }
+}
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java
new file mode 100755
index 00000000..431c6210
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java
@@ -0,0 +1,60 @@
+/*
+ * 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.LinkedList;
+import java.util.List;
+
+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.onlab.util.HexDump;
+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 {
+
+ protected static final Logger log = LoggerFactory.getLogger(BgpMessageDecoder.class);
+
+ @Override
+ protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
+ log.debug("MESSAGE IS RECEIVED.");
+ if (!channel.isConnected()) {
+ log.info("Channel is not connected.");
+ return null;
+ }
+
+ HexDump.dump(buffer);
+
+ 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);
+ msgList.add(message);
+ }
+ return msgList;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java
new file mode 100755
index 00000000..3e56d6ff
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java
@@ -0,0 +1,60 @@
+/*
+ * 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.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+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.onlab.util.HexDump;
+
+import org.slf4j.Logger;
+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);
+
+ @Override
+ protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
+ log.debug("BGPMessageEncoder::encode");
+ if (!(msg instanceof List)) {
+ log.debug("Invalid msg.");
+ return msg;
+ }
+
+ @SuppressWarnings("unchecked")
+ List<BgpMessage> msglist = (List<BgpMessage>) msg;
+
+ ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
+
+ log.debug("SENDING MESSAGE");
+ for (BgpMessage pm : msglist) {
+ pm.writeTo(buf);
+ }
+
+ HexDump.dump(buf);
+
+ return buf;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java
new file mode 100755
index 00000000..7494c814
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java
@@ -0,0 +1,124 @@
+/*
+ * 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.BgpPacketStats;
+
+/**
+ * A representation of a packet context which allows any provider
+ * to view a packet in event, but may block the response to the
+ * 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 {
+
+ private int inPacketCount;
+ private int outPacketCount;
+ private int wrongPacketCount;
+ private long time;
+
+ /**
+ * Resets parameter.
+ */
+ public BgpPacketStatsImpl() {
+ this.inPacketCount = 0;
+ this.outPacketCount = 0;
+ this.wrongPacketCount = 0;
+ this.time = 0;
+ }
+
+ /**
+ * Get the outgoing packet count number.
+ *
+ * @return packet count
+ */
+ public int outPacketCount() {
+ return outPacketCount;
+ }
+
+ /**
+ * Get the incoming packet count number.
+ *
+ * @return packet count
+ */
+ public int inPacketCount() {
+ return inPacketCount;
+ }
+
+ /**
+ * Get the wrong packet count number.
+ *
+ * @return packet count
+ */
+ public int wrongPacketCount() {
+ return wrongPacketCount;
+ }
+
+ /**
+ * Increments the received packet counter.
+ */
+ public void addInPacket() {
+ this.inPacketCount++;
+ }
+
+ /**
+ * Increments the sent packet counter.
+ */
+ public void addOutPacket() {
+ this.outPacketCount++;
+ }
+
+ /**
+ * Increments the sent packet counter by specified value.
+ *
+ * @param value of no of packets sent
+ */
+ public void addOutPacket(int value) {
+ this.outPacketCount = this.outPacketCount + value;
+ }
+
+ /**
+ * Increments the wrong packet counter.
+ */
+ public void addWrongPacket() {
+ this.wrongPacketCount++;
+ }
+
+ /**
+ * Resets wrong packet count.
+ */
+ public void resetWrongPacket() {
+ this.wrongPacketCount = 0;
+ }
+
+ /**
+ * Get the time.
+ *
+ * @return time
+ */
+ public long getTime() {
+ return this.time;
+ }
+
+ /**
+ * Sets the time.
+ *
+ * @param time value to set
+ */
+ public void setTime(long time) {
+ this.time = time;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java
new file mode 100755
index 00000000..a8eaee3c
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java
@@ -0,0 +1,121 @@
+/*
+ * 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.onlab.packet.Ip4Address;
+import org.onosproject.bgp.controller.BgpConnectPeer;
+import org.onosproject.bgp.controller.BgpPeerCfg;
+
+/**
+ * BGP Peer configuration information.
+ */
+public class BgpPeerConfig implements BgpPeerCfg {
+ private int asNumber;
+ private short holdTime;
+ private boolean isIBgp;
+ private Ip4Address peerId = null;
+ private State state;
+ private boolean selfInitiated;
+ private BgpConnectPeer connectPeer;
+
+ /**
+ * Constructor to initialize the values.
+ */
+ BgpPeerConfig() {
+ state = State.IDLE;
+ selfInitiated = false;
+ }
+
+ @Override
+ public int getAsNumber() {
+ return this.asNumber;
+ }
+
+ @Override
+ public void setAsNumber(int asNumber) {
+ this.asNumber = asNumber;
+ }
+
+ @Override
+ public short getHoldtime() {
+ return this.holdTime;
+ }
+
+ @Override
+ public void setHoldtime(short holdTime) {
+ this.holdTime = holdTime;
+ }
+
+ @Override
+ public boolean getIsIBgp() {
+ return this.isIBgp;
+ }
+
+ @Override
+ public void setIsIBgp(boolean isIBgp) {
+ this.isIBgp = isIBgp;
+ }
+
+ @Override
+ public String getPeerRouterId() {
+ if (this.peerId != null) {
+ return this.peerId.toString();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void setPeerRouterId(String peerId) {
+ this.peerId = Ip4Address.valueOf(peerId);
+ }
+
+ @Override
+ public void setPeerRouterId(String peerId, int asNumber) {
+ this.peerId = Ip4Address.valueOf(peerId);
+ this.asNumber = asNumber;
+ }
+
+ @Override
+ public State getState() {
+ return this.state;
+ }
+
+ @Override
+ public void setState(State state) {
+ this.state = state;
+ }
+
+ @Override
+ public boolean getSelfInnitConnection() {
+ return this.selfInitiated;
+ }
+
+ @Override
+ public void setSelfInnitConnection(boolean selfInit) {
+ this.selfInitiated = selfInit;
+ }
+
+ @Override
+ public BgpConnectPeer connectPeer() {
+ return this.connectPeer;
+ }
+
+ @Override
+ public void setConnectPeer(BgpConnectPeer connectPeer) {
+ this.connectPeer = connectPeer;
+ }
+}
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
new file mode 100644
index 00000000..e3f09f30
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
@@ -0,0 +1,346 @@
+/*
+ * 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.bgp.controller.BgpLocalRib;
+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 BgpLocalRib bgplocalRIB;
+ private BgpLocalRib bgplocalRIBVpn;
+ private AdjRibIn adjRib;
+ private VpnAdjRibIn vpnAdjRib;
+
+ /**
+ * Return the adjacency RIB-IN.
+ *
+ * @return adjRib the adjacency RIB-IN
+ */
+ public AdjRibIn adjacencyRib() {
+ return adjRib;
+ }
+
+ /**
+ * Return the adjacency RIB-IN with VPN.
+ *
+ * @return vpnAdjRib the adjacency RIB-IN with VPN
+ */
+ public VpnAdjRibIn vpnAdjacencyRib() {
+ return 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.bgplocalRIB = bgpController.bgpLocalRib();
+ this.bgplocalRIBVpn = bgpController.bgpLocalRibVpn();
+ 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);
+ bgplocalRIB.add(sessionInfo(), nlriInfo, details);
+ } else {
+ vpnAdjRib.addVpn(nlriInfo, details, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
+ bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details,
+ ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
+ }
+ } else if (nlriInfo instanceof BgpLinkLsNlriVer4) {
+ PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr);
+ if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) {
+ adjRib.add(nlriInfo, details);
+ bgplocalRIB.add(sessionInfo(), nlriInfo, details);
+ } else {
+ vpnAdjRib.addVpn(nlriInfo, details, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
+ bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details,
+ ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
+ }
+ } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) {
+ PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr);
+ if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) {
+ adjRib.add(nlriInfo, details);
+ bgplocalRIB.add(sessionInfo(), nlriInfo, details);
+ } else {
+ vpnAdjRib.addVpn(nlriInfo, details, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher());
+ bgplocalRIBVpn.add(sessionInfo(), 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);
+ bgplocalRIB.delete(nlriInfo);
+ } else {
+ vpnAdjRib.removeVpn(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
+ bgplocalRIBVpn.delete(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher());
+ }
+ } else if (nlriInfo instanceof BgpLinkLsNlriVer4) {
+ if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) {
+ adjRib.remove(nlriInfo);
+ bgplocalRIB.delete(nlriInfo);
+ } else {
+ vpnAdjRib.removeVpn(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
+ bgplocalRIBVpn.delete(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher());
+ }
+ } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) {
+ if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) {
+ adjRib.remove(nlriInfo);
+ bgplocalRIB.delete(nlriInfo);
+ } else {
+ vpnAdjRib.removeVpn(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher());
+ bgplocalRIBVpn.delete(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;
+ }
+
+ /**
+ * Update localRIB on peer disconnect.
+ *
+ */
+ public void updateLocalRIBOnPeerDisconnect() {
+ BgpLocalRibImpl localRib = (BgpLocalRibImpl) bgplocalRIB;
+ BgpLocalRibImpl localRibVpn = (BgpLocalRibImpl) bgplocalRIBVpn;
+
+ localRib.localRIBUpdate(adjacencyRib());
+ localRibVpn.localRIBUpdate(vpnAdjacencyRib());
+ }
+
+ // ************************
+ // 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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java
new file mode 100755
index 00000000..28e1041c
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+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;
+
+/**
+ * Creates a ChannelPipeline for a server-side bgp channel.
+ */
+public class BgpPipelineFactory
+ implements ChannelPipelineFactory, ExternalResourceReleasable {
+
+ static final Timer TIMER = new HashedWheelTimer();
+ protected ReadTimeoutHandler readTimeoutHandler;
+ private boolean isBgpServ;
+ private BgpController bgpController;
+
+ /**
+ * Constructor to initialize the values.
+ *
+ * @param bgpController parent controller
+ * @param isBgpServ if it is a server or remote peer
+ */
+ public BgpPipelineFactory(BgpController bgpController, boolean isBgpServ) {
+ super();
+ this.isBgpServ = isBgpServ;
+ this.bgpController = bgpController;
+ /* hold time */
+ this.readTimeoutHandler = new ReadTimeoutHandler(TIMER, bgpController.getConfig().getHoldTime());
+ }
+
+ @Override
+ public ChannelPipeline getPipeline() throws Exception {
+ BgpChannelHandler handler = new BgpChannelHandler(bgpController);
+
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("bgpmessagedecoder", new BgpMessageDecoder());
+ pipeline.addLast("bgpmessageencoder", new BgpMessageEncoder());
+ pipeline.addLast("holdTime", readTimeoutHandler);
+ if (isBgpServ) {
+ pipeline.addLast("PassiveHandler", handler);
+ } else {
+ pipeline.addLast("ActiveHandler", handler);
+ }
+
+ return pipeline;
+ }
+
+ @Override
+ public void releaseExternalResources() {
+ TIMER.stop();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java b/framework/src/onos/protocols/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/protocols/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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java b/framework/src/onos/protocols/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/protocols/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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java
new file mode 100755
index 00000000..f02cee8a
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java
@@ -0,0 +1,254 @@
+/*
+ * 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 static org.onlab.util.Tools.groupedThreads;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The main controller class. Handles all setup and network listeners - Distributed ownership control of bgp peer
+ * through IControllerRegistryService
+ */
+public class Controller {
+
+ private static final Logger log = LoggerFactory.getLogger(Controller.class);
+
+ 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;
+
+ // Start time of the controller
+ private long systemStartTime;
+
+ private NioServerSocketChannelFactory serverExecFactory;
+ private NioClientSocketChannelFactory peerExecFactory;
+ private static ClientBootstrap peerBootstrap;
+ private BgpController bgpController;
+
+ // Perf. related configuration
+ private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
+
+ /**
+ * Constructor to initialize the values.
+ *
+ * @param bgpController bgp controller instance
+ */
+ public Controller(BgpController bgpController) {
+ this.bgpController = bgpController;
+ }
+
+ /**
+ * Returns factory version for processing BGP messages.
+ *
+ * @return instance of factory version
+ */
+ static BgpFactory getBgpMessageFactory4() {
+ return FACTORY4;
+ }
+
+ /**
+ * To get system start time.
+ *
+ * @return system start time in milliseconds
+ */
+ public long getSystemStartTime() {
+ return (this.systemStartTime);
+ }
+
+ /**
+ * Tell controller that we're ready to accept bgp peer connections.
+ */
+ public void run() {
+
+ try {
+
+ peerBootstrap = createPeerBootStrap();
+
+ peerBootstrap.setOption("reuseAddr", true);
+ peerBootstrap.setOption("child.keepAlive", true);
+ peerBootstrap.setOption("child.tcpNoDelay", true);
+ peerBootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
+
+ final ServerBootstrap bootstrap = createServerBootStrap();
+
+ bootstrap.setOption("reuseAddr", true);
+ bootstrap.setOption("child.keepAlive", true);
+ bootstrap.setOption("child.tcpNoDelay", true);
+ bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
+
+ ChannelPipelineFactory pfact = new BgpPipelineFactory(bgpController, true);
+
+ bootstrap.setPipelineFactory(pfact);
+ InetSocketAddress sa = new InetSocketAddress(getBgpPortNum());
+ cg = new DefaultChannelGroup();
+ serverChannel = bootstrap.bind(sa);
+ cg.add(serverChannel);
+ log.info("Listening for Peer connection on {}", sa);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Creates server boot strap.
+ *
+ * @return ServerBootStrap
+ */
+ private ServerBootstrap createServerBootStrap() {
+
+ if (workerThreads == 0) {
+ serverExecFactory = new NioServerSocketChannelFactory(
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")),
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")));
+ return new ServerBootstrap(serverExecFactory);
+ } else {
+ serverExecFactory = new NioServerSocketChannelFactory(
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")),
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")),
+ workerThreads);
+ return new ServerBootstrap(serverExecFactory);
+ }
+ }
+
+ /**
+ * Creates peer boot strap.
+ *
+ * @return ClientBootstrap
+ */
+ private ClientBootstrap createPeerBootStrap() {
+
+ if (peerWorkerThreads == 0) {
+ peerExecFactory = new NioClientSocketChannelFactory(
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")),
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")));
+ return new ClientBootstrap(peerExecFactory);
+ } else {
+ peerExecFactory = new NioClientSocketChannelFactory(
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")),
+ Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")),
+ peerWorkerThreads);
+ return new ClientBootstrap(peerExecFactory);
+ }
+ }
+
+ /**
+ * Gets peer bootstrap.
+ *
+ * @return peer bootstrap
+ */
+ public static ClientBootstrap peerBootstrap() {
+ return peerBootstrap;
+ }
+
+ /**
+ * Initialize internal data structures.
+ */
+ public void init() {
+ // These data structures are initialized here because other
+ // module's startUp() might be called before ours
+ this.systemStartTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Gets run time memory.
+ *
+ * @return m run time memory
+ */
+ public Map<String, Long> getMemory() {
+ Map<String, Long> m = new HashMap<>();
+ Runtime runtime = Runtime.getRuntime();
+ m.put("total", runtime.totalMemory());
+ m.put("free", runtime.freeMemory());
+ return m;
+ }
+
+ /**
+ * Gets UP time.
+ *
+ * @return UP time
+ */
+ public Long getUptime() {
+ RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
+ return rb.getUptime();
+ }
+
+ /**
+ * Starts the BGP controller.
+ */
+ public void start() {
+ log.info("Started");
+ this.init();
+ this.run();
+ }
+
+ /**
+ * Stops the BGP controller.
+ */
+ public void stop() {
+ log.info("Stopped");
+ serverExecFactory.shutdown();
+ peerExecFactory.shutdown();
+ cg.close();
+ }
+
+ /**
+ * Returns port number.
+ *
+ * @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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java b/framework/src/onos/protocols/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/protocols/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/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java
new file mode 100755
index 00000000..fd4e9506
--- /dev/null
+++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of the BGP controller IO subsystem.
+ */
+package org.onosproject.bgp.controller.impl;