[Emu] [ONOS-2591,ONOS-2594] Implementation of BGP channel handler to manage each BGP peer connection.

Change-Id: I14e90c9437f676698f89da79e736a81035689492
diff --git a/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPController.java b/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPController.java
index 6d75812..49432aa 100755
--- a/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPController.java
+++ b/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPController.java
@@ -25,6 +25,21 @@
 public interface BGPController {
 
     /**
+     * Returns list of bgp peers connected to this BGP controller.
+     *
+     * @return Iterable of BGPPeer elements
+     */
+    Iterable<BGPPeer> getPeers();
+
+    /**
+     * Returns the actual bgp peer for the given ip address.
+     *
+     * @param bgpId the id of the bgp peer to fetch
+     * @return the interface to this bgp peer
+     */
+    BGPPeer getPeer(BGPId bgpId);
+
+    /**
      * Send a message to a particular bgp peer.
      *
      * @param bgpId the id of the peer to send message.
@@ -41,9 +56,22 @@
     void processBGPPacket(BGPId bgpId, BGPMessage msg);
 
     /**
+     * Close all connected BGP peers.
+     *
+     */
+    void closeConnectedPeers();
+
+    /**
      * Get the BGPConfig class to the caller.
      *
      * @return configuration object
      */
     BGPCfg getConfig();
+
+    /**
+     * Get the BGP connected peers to this controller.
+     *
+     * @return the integer number
+     */
+    int getBGPConnNumber();
 }
\ No newline at end of file
diff --git a/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPPeer.java b/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPPeer.java
new file mode 100755
index 0000000..1b022c7
--- /dev/null
+++ b/bgp/api/src/main/java/org/onosproject/bgp/controller/BGPPeer.java
@@ -0,0 +1,161 @@
+/*
+ * 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;
+import java.util.List;
+import org.jboss.netty.channel.Channel;
+import org.onosproject.bgpio.protocol.BGPMessage;
+import org.onosproject.bgpio.protocol.BGPVersion;
+
+/**
+ * Represents the peer side of an bgp peer.
+ *
+ */
+public interface BGPPeer {
+
+    /**
+     * Sets the BGP version for this bgp peer.
+     *
+     * @param bgpVersion the version to set.
+     */
+    void setBgpPeerVersion(BGPVersion bgpVersion);
+
+    /**
+     * Gets the BGP version for this bgp peer.
+     *
+     * @return bgp identifier.
+     */
+    int getBgpPeerIdentifier();
+
+    /**
+     * Sets the associated Netty channel for this bgp peer.
+     *
+     * @param channel the Netty channel
+     */
+    void setChannel(Channel channel);
+
+    /**
+     * Gets the associated Netty channel handler for this bgp peer.
+     *
+     * @return Channel channel connected.
+     */
+    Channel getChannel();
+
+    /**
+     * Sets the AS Number for this bgp peer.
+     *
+     * @param peerASNum the autonomous system number value to set.
+     */
+    void setBgpPeerASNum(short peerASNum);
+
+    /**
+     * Sets the hold time for this bgp peer.
+     *
+     * @param peerHoldTime the hold timer value to set.
+     */
+    void setBgpPeerHoldTime(short peerHoldTime);
+
+    /**
+     * Sets the peer identifier value.
+     *
+     * @param peerIdentifier the bgp peer identifier value.
+     */
+    void setBgpPeerIdentifier(int peerIdentifier);
+
+    /**
+     * Sets whether the bgp peer is connected.
+     *
+     * @param connected whether the bgp peer is connected
+     */
+    void setConnected(boolean connected);
+
+    /**
+     * Initialises the behaviour.
+     *
+     * @param bgpId id of bgp peer
+     * @param bgpVersion BGP version
+     * @param pktStats packet statistics
+     */
+    void init(BGPId bgpId, BGPVersion bgpVersion, BGPPacketStats pktStats);
+
+    /**
+     * Checks whether the handshake is complete.
+     *
+     * @return true is finished, false if not.
+     */
+    boolean isHandshakeComplete();
+
+    /**
+     * Writes the message to the peer.
+     *
+     * @param msg the message to write
+     */
+    void sendMessage(BGPMessage msg);
+
+    /**
+     * Writes the BGPMessage list to the peer.
+     *
+     * @param msgs the messages to be written
+     */
+    void sendMessage(List<BGPMessage> msgs);
+
+    /**
+     * Gets a string version of the ID for this bgp peer.
+     *
+     * @return string version of the ID
+     */
+    String getStringId();
+
+    /**
+     * Gets the ipAddress of the peer.
+     *
+     * @return the peer bgpId in IPAddress format
+     */
+    BGPId getBGPId();
+
+    /**
+     * Checks if the bgp peer is still connected.
+     *
+     * @return whether the bgp peer is still connected
+     */
+    boolean isConnected();
+
+    /**
+     * Disconnects the bgp peer by closing the TCP connection. Results in a call to the channel handler's
+     * channelDisconnected method for cleanup
+     */
+    void disconnectPeer();
+
+    /**
+     * Identifies the channel used to communicate with the bgp peer.
+     *
+     * @return string representation of the connection to the peer
+     */
+    String channelId();
+
+    /**
+     * Gets the negotiated hold time.
+     *
+     * @return the negotiated hold time
+     */
+    int getNegotiatedHoldTime();
+
+    /**
+     * Sets negotiated hold time for the peer.
+     *
+     * @param negotiatedHoldTime negotiated hold time
+     */
+    void setNegotiatedHoldTime(short negotiatedHoldTime);
+}
diff --git a/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPMessage.java b/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPMessage.java
index a5d8154..309ef43 100644
--- a/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPMessage.java
+++ b/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPMessage.java
@@ -61,27 +61,6 @@
         BGPMessage build() throws BGPParseException;
 
         /**
-         * Returns BGP Version of BGP Message.
-         *
-         * @return BGP Version of BGP Message
-         */
-        BGPVersion getVersion();
-
-        /**
-         * Returns BGP Type of BGP Message.
-         *
-         * @return BGP Type of BGP Message
-         */
-        BGPType getType();
-
-        /**
-         * Returns BGP Header of BGP Message.
-         *
-         * @return BGP Header of BGP Message
-         */
-        BGPHeader getHeader();
-
-        /**
          * Sets BgpHeader and return its builder.
          *
          * @param bgpMsgHeader BGP Message Header
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPChannelHandler.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPChannelHandler.java
index 942d365..c17736e 100755
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPChannelHandler.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPChannelHandler.java
@@ -16,19 +16,616 @@
 
 package org.onosproject.bgp.controller.impl;
 
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.ClosedChannelException;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+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.IpAddress;
+import org.onosproject.bgp.controller.BGPCfg;
+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.BGPPeerManager;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+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.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 {
 
-    // TODO: implement FSM and session handling mechanism
+    private static final Logger log = LoggerFactory.getLogger(BGPChannelHandler.class);
+
+    static final int BGP_MAX_KEEPALIVE_INTERVAL = 3;
+    private BGPPeer bgpPeer;
+    private BGPId thisbgpId;
+    Channel channel;
+    private BGPKeepAliveTimer keepAliveTimer = null;
+    private short peerHoldTime = 0;
+    private short negotiatedHoldTime = 0;
+    private short peerAsNum;
+    private int peerIdentifier;
+    private BGPPacketStatsImpl bgpPacketStats;
+    static final int MAX_WRONG_COUNT_PACKET = 5;
+
+    // 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 BGPControllerImpl bgpControllerImpl;
+    private BGPPeerManager peerManager;
+    private InetSocketAddress inetAddress;
+    private IpAddress ipAddress;
+    private SocketAddress address;
+    private String peerAddr;
+    private BGPCfg bgpconfig;
+
     /**
      * Create a new unconnected BGPChannelHandler.
      *
      * @param bgpCtrlImpl bgp controller implementation object
      */
     BGPChannelHandler(BGPControllerImpl bgpCtrlImpl) {
+        this.bgpControllerImpl = bgpCtrlImpl;
+        this.peerManager = bgpCtrlImpl.getPeerManager();
+        this.state = ChannelState.IDLE;
+        this.duplicateBGPIdFound = Boolean.FALSE;
+        this.bgpPacketStats = new BGPPacketStatsImpl();
+        this.bgpconfig = bgpCtrlImpl.getConfig();
     }
-}
\ No newline at end of file
+
+    // 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();
+                    log.debug("Message is not OPEN message");
+                } else {
+                    log.debug("Sending keep alive message in OPENSENT state");
+                    h.bgpPacketStats.addInPacket();
+
+                    // TODO: initialize openmessage BGPOpenMsg pOpenmsg = (BGPOpenMsg) m;
+                    // TODO: initialize identifier from open messgae h.peerIdentifier = pOpenmsg.getBgpId();
+
+                    // validate capabilities and open msg
+                    if (h.openMsgValidation(h)) {
+                        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
+                         */
+                        // TODO: initialize holdtime from 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);
+
+                        // TODO: get AS number for open message update AS number
+                    }
+
+                    // 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();
+                    log.debug("Message is not OPEN message");
+                } else {
+                    h.bgpPacketStats.addInPacket();
+
+                    // TODO: initialize open message BGPOpenMsg pOpenmsg = (BGPOpenMsg) m;
+
+                    // Validate open message
+                    if (h.openMsgValidation(h)) {
+                        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
+                         */
+                        // TODO: get hold time from 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);
+
+                        //TODO: update AS number form open messsage update AS number
+
+                        h.sendHandshakeOpenMessage();
+                        h.bgpPacketStats.addOutPacket();
+                        h.setState(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();
+                    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()));
+
+                    h.bgpPeer = h.peerManager.getBGPPeerInstance(h.thisbgpId, h.bgpVersion, h.bgpPacketStats);
+                    // set the status fo bgp as connected
+                    h.bgpPeer.setConnected(true);
+                    h.bgpPeer.setChannel(h.channel);
+
+                    // set specific parameters to bgp peer
+                    h.bgpPeer.setBgpPeerVersion(h.bgpVersion);
+                    h.bgpPeer.setBgpPeerASNum(h.peerAsNum);
+                    h.bgpPeer.setBgpPeerHoldTime(h.peerHoldTime);
+                    h.bgpPeer.setBgpPeerIdentifier(h.peerIdentifier);
+
+                    h.negotiatedHoldTime = (h.peerHoldTime < h.bgpconfig.getHoldTime()) ? h.peerHoldTime : h.bgpconfig
+                            .getHoldTime();
+                    h.bgpPeer.setNegotiatedHoldTime(h.negotiatedHoldTime);
+                    /*
+                     * 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.
+                     */
+                    h.sendKeepAliveMessage();
+
+                    if (h.negotiatedHoldTime != 0) {
+                        h.keepAliveTimer
+                            = new BGPKeepAliveTimer(h, (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL));
+                    }
+
+                    h.bgpPacketStats.addOutPacket();
+
+                    // set the state handshake completion.
+                    h.setHandshakeComplete(true);
+
+                    if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) {
+                        /*
+                         * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established
+                         * for detecting which BGP connection is to be preserved when a collision occurs. The convention
+                         * is to compare the BGP Identifiers of the peers involved in the collision and to retain only
+                         * the connection initiated by the BGP speaker with the higher-valued BGP Identifier..
+                         */
+                        // TODO: Connection collision handling.
+                        disconnectDuplicate(h);
+                    } else {
+                        h.setState(ESTABLISHED);
+                        h.bgpconfig.setPeerConnState(h.peerAddr, BGPPeerCfg.State.ESTABLISHED);
+                    }
+                }
+            }
+        },
+
+        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.");
+        }
+
+        // Connection should establish only if local ip and Autonomous system number is configured.
+        if (bgpconfig.getState() != BGPCfg.State.IP_AS_CONFIGURED) {
+            channel.close();
+            log.info("BGP local AS and router ID not configured");
+            return;
+        }
+
+        inetAddress = (InetSocketAddress) address;
+        ipAddress = IpAddress.valueOf(inetAddress.getAddress());
+        peerAddr = ipAddress.toString();
+
+        // if peer is not configured disconnect session
+        if (!bgpconfig.isPeerConfigured(peerAddr)) {
+            log.debug("Peer is not configured {}", peerAddr);
+            channel.close();
+            return;
+        }
+
+        // if connection is already established close channel
+        if (peerManager.isPeerConnected(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;
+        ipAddress = IpAddress.valueOf(inetAddress.getAddress());
+        peerAddr = ipAddress.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) {
+                    peerManager.removeConnectedPeer(thisbgpId);
+                }
+            } 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 {
+            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
+                // TODO: Send notification
+                channel.close();
+                state = ChannelState.IDLE;
+                return;
+            } else if (ChannelState.OPENCONFIRM == state) {
+
+                // When ReadTimeout timer is expired in OPENCONFIRM state.
+                // TODO: Send Notification
+                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) {
+            // TODO: SEND NOTIFICATION
+            log.debug("BGP Parse Exception: ", e.getCause());
+        } 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());
+        }
+    }
+
+    // *************************
+    // 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
+     */
+    private void dispatchMessage(BGPMessage m) throws BGPParseException {
+        bgpPacketStats.addInPacket();
+        bgpControllerImpl.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 {
+        // TODO: send open message.
+
+    }
+
+    /**
+     * Send keep alive message.
+     *
+     * @throws IOException when channel is disconnected
+     * @throws BGPParseException while building keep alive message
+     */
+    synchronized void sendKeepAliveMessage() throws IOException, BGPParseException {
+
+        // TODO: send keep alive message.
+    }
+
+    /**
+     * Send notification and close channel with peer.
+     */
+    private void sendErrNotificationAndCloseChannel() {
+        // TODO: send notification
+        channel.close();
+    }
+
+    /**
+     * Process unknown BGP message received.
+     *
+     * @throws BGPParseException when received invalid message
+     */
+    public void processUnknownMsg() throws BGPParseException {
+        log.debug("UNKNOWN message received");
+        Date now = null;
+        if (bgpPacketStats.wrongPacketCount() == 0) {
+            now = new Date();
+            bgpPacketStats.setTime(now.getTime());
+            bgpPacketStats.addWrongPacket();
+            sendErrNotificationAndCloseChannel();
+        }
+        if (bgpPacketStats.wrongPacketCount() > 1) {
+            Date lastest = new Date();
+            bgpPacketStats.addWrongPacket();
+            // converting to seconds
+            if (((lastest.getTime() - bgpPacketStats.getTime()) / 1000) > 60) {
+                now = lastest;
+                bgpPacketStats.setTime(now.getTime());
+                bgpPacketStats.resetWrongPacket();
+                bgpPacketStats.addWrongPacket();
+            } else if (((int) (lastest.getTime() - now.getTime()) / 1000) < 60) {
+                if (MAX_WRONG_COUNT_PACKET <= bgpPacketStats.wrongPacketCount()) {
+                    // reset once wrong packet count reaches MAX_WRONG_COUNT_PACKET
+                    bgpPacketStats.resetWrongPacket();
+                    // max wrong packets received send error message and close the session
+                    sendErrNotificationAndCloseChannel();
+                }
+            }
+        }
+    }
+
+    /**
+     * Open message validation.
+     *
+     * @param h channel handler
+     * @return true if validation succeed, otherwise false
+     * @throws BGPParseException when received invalid message
+     */
+    public boolean openMsgValidation(BGPChannelHandler h) throws BGPParseException {
+        // TODO: Open message validation.
+        return true;
+    }
+}
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPControllerImpl.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPControllerImpl.java
index 95eafdb..d8378e3 100755
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPControllerImpl.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPControllerImpl.java
@@ -17,16 +17,24 @@
 package org.onosproject.bgp.controller.impl;
 
 import static org.onlab.util.Tools.groupedThreads;
+
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+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.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.BGPPacketStats;
+import org.onosproject.bgp.controller.BGPPeer;
 import org.onosproject.bgpio.protocol.BGPMessage;
+import org.onosproject.bgpio.protocol.BGPVersion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,8 +50,10 @@
 
     private final ExecutorService executorBarrier = Executors.newFixedThreadPool(4,
                                                                                  groupedThreads("onos/bgp",
-                                                                                         "event-barrier-%d"));
+                                                                                                "event-barrier-%d"));
+    protected ConcurrentHashMap<BGPId, BGPPeer> connectedPeers = new ConcurrentHashMap<BGPId, BGPPeer>();
 
+    protected BGPPeerManager peerManager = new BGPPeerManager();
     final Controller ctrl = new Controller(this);
 
     private BGPConfig bgpconfig = new BGPConfig();
@@ -57,11 +67,22 @@
     @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 writeMsg(BGPId bgpId, BGPMessage msg) {
         // TODO: Send message
     }
@@ -88,17 +109,167 @@
         }
     }
 
+    @Override
+    public void closeConnectedPeers() {
+        BGPPeer bgpPeer;
+        for (BGPId id : this.connectedPeers.keySet()) {
+            bgpPeer = getPeer(id);
+            bgpPeer.disconnectPeer();
+        }
+    }
+
     /**
-     * Get controller instance.
-     *
-     * @return ctrl the controller.
+     * Implementation of an BGP Peer which is responsible for keeping track of connected peers and the state in which
+     * they are.
      */
+    public class BGPPeerManager {
+
+        private final Logger log = LoggerFactory.getLogger(BGPPeerManager.class);
+        private final Lock peerLock = new ReentrantLock();
+
+        /**
+         * Add a BGP peer that has just connected to the system.
+         *
+         * @param bgpId the id of bgp peer to add
+         * @param bgpPeer the actual bgp peer object.
+         * @return true if added, false otherwise.
+         */
+        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;
+            }
+        }
+
+        /**
+         * Checks if the activation for this bgp peer is valid.
+         *
+         * @param bgpId the id of bgp peer to check
+         * @return true if valid, false otherwise
+         */
+        public boolean isPeerConnected(BGPId bgpId) {
+            if (connectedPeers.get(bgpId) == null) {
+                this.log.error("Trying to activate peer but is not in " + "connected peer: bgpIp {}. Aborting ..",
+                               bgpId.toString());
+                return false;
+            }
+
+            return true;
+        }
+
+        /**
+         * Checks if the activation for this bgp peer is valid.
+         *
+         * @param routerid the routerid of bgp peer to check
+         * @return true if valid, false otherwise
+         */
+        public boolean isPeerConnected(String routerid) {
+
+            final BGPId bgpId;
+            bgpId = BGPId.bgpId(IpAddress.valueOf(routerid));
+
+            if (connectedPeers.get(bgpId) != null) {
+                this.log.info("Peer connection exist ");
+                return true;
+            }
+            this.log.info("Initiate connect request to " + "peer: bgpIp {}", bgpId.toString());
+
+            return false;
+        }
+
+        /**
+         * Clear all state in controller peer maps for a bgp peer that has
+         * disconnected from the local controller.
+         *
+         * @param bgpId the id of bgp peer to remove.
+         */
+        public void removeConnectedPeer(BGPId bgpId) {
+            connectedPeers.remove(bgpId);
+        }
+
+        /**
+         * Clear all state in controller peer maps for a bgp peer that has
+         * disconnected from the local controller.
+         *
+         * @param routerid the router id of bgp peer to remove.
+         */
+        public void removeConnectedPeer(String routerid) {
+            final BGPId bgpId;
+
+            bgpId = BGPId.bgpId(IpAddress.valueOf(routerid));
+
+            connectedPeers.remove(bgpId);
+        }
+
+        /**
+          * Gets bgp peer for connected peer map.
+          *
+          * @param routerid router id
+          * @return peer if available, null otherwise
+          */
+        public BGPPeer getPeer(String routerid) {
+            final BGPId bgpId;
+            bgpId = BGPId.bgpId(IpAddress.valueOf(routerid));
+
+            return connectedPeers.get(bgpId);
+        }
+
+        /**
+          * Gets bgp peer instance.
+          *
+          * @param bgpId bgp identifier.
+          * @param pv bgp version.
+          * @param pktStats packet statistics.
+          * @return BGPPeer peer instance.
+          */
+        public BGPPeer getBGPPeerInstance(BGPId bgpId, BGPVersion pv, BGPPacketStats pktStats) {
+            BGPPeer bgpPeer = new BGPPeerImpl();
+            bgpPeer.init(bgpId, pv, pktStats);
+            return bgpPeer;
+        }
+
+    }
+
+    /**
+      * Gets controller instance.
+      *
+      * @return Controller instance.
+      */
     public Controller getController() {
         return ctrl;
     }
 
+    /**
+      * Gets connected peers.
+      *
+      * @return connectedPeers from connected Peers Map.
+      */
+    public ConcurrentHashMap<BGPId, BGPPeer> getConnectedPeers() {
+        return connectedPeers;
+    }
+
+    /**
+      * Gets peer manager.
+      *
+      * @return peerManager.
+      */
+    public BGPPeerManager getPeerManager() {
+        return peerManager;
+    }
+
     @Override
     public BGPCfg getConfig() {
         return this.bgpconfig;
     }
+
+    @Override
+    public int getBGPConnNumber() {
+        return connectedPeers.size();
+    }
 }
\ No newline at end of file
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPKeepAliveTimer.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPKeepAliveTimer.java
new file mode 100755
index 0000000..1c95804
--- /dev/null
+++ b/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/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPacketStatsImpl.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPacketStatsImpl.java
index 41407dc..09f4d45 100755
--- a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPacketStatsImpl.java
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPacketStatsImpl.java
@@ -43,8 +43,7 @@
     /**
      * Get the outgoing packet count number.
      *
-     * @return
-     *          packet count
+     * @return packet count
      */
     public int outPacketCount() {
         return outPacketCount;
@@ -53,8 +52,7 @@
     /**
      * Get the incoming packet count number.
      *
-     * @return
-     *          packet count
+     * @return packet count
      */
     public int inPacketCount() {
         return inPacketCount;
@@ -63,8 +61,7 @@
     /**
      * Get the wrong packet count number.
      *
-     * @return
-     *          packet count
+     * @return packet count
      */
     public int wrongPacketCount() {
         return wrongPacketCount;
@@ -110,8 +107,7 @@
     /**
      * Get the time.
      *
-     * @return
-     *          time
+     * @return time
      */
     public long getTime() {
         return this.time;
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerImpl.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerImpl.java
new file mode 100755
index 0000000..212b24d
--- /dev/null
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPPeerImpl.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgp.controller.impl;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.jboss.netty.channel.Channel;
+import org.onlab.packet.IpAddress;
+import org.onosproject.bgp.controller.BGPId;
+import org.onosproject.bgp.controller.BGPPacketStats;
+import org.onosproject.bgp.controller.BGPPeer;
+import org.onosproject.bgpio.protocol.BGPMessage;
+import org.onosproject.bgpio.protocol.BGPVersion;
+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 Channel channel;
+    protected String channelId;
+    private boolean connected;
+    protected boolean isHandShakeComplete = false;
+    public BGPSessionInfo sessionInfo;
+    private BGPPacketStatsImpl pktStats;
+
+    @Override
+    public void init(BGPId bgpId, BGPVersion bgpVersion, BGPPacketStats pktStats) {
+        this.sessionInfo.setRemoteBgpId(bgpId);
+        this.sessionInfo.setRemoteBgpVersion(bgpVersion);
+        this.pktStats = (BGPPacketStatsImpl) pktStats;
+        this.sessionInfo = new BGPSessionInfo();
+    }
+
+    // ************************
+    // 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;
+    }
+
+    // ************************
+    // BGP Peer features related
+    // ************************
+
+    @Override
+    public final BGPId getBGPId() {
+        return this.sessionInfo.getRemoteBgpId();
+    };
+
+    @Override
+    public final String getStringId() {
+        return this.sessionInfo.getRemoteBgpId().toString();
+    }
+
+    @Override
+    public final void setBgpPeerVersion(BGPVersion peerVersion) {
+        this.sessionInfo.setRemoteBgpVersion(peerVersion);
+    }
+
+    @Override
+    public void setBgpPeerASNum(short peerASNum) {
+        this.sessionInfo.setRemoteBgpASNum(peerASNum);
+    }
+
+    @Override
+    public void setBgpPeerHoldTime(short peerHoldTime) {
+        this.sessionInfo.setRemoteBgpHoldTime(peerHoldTime);
+    }
+
+    @Override
+    public void setBgpPeerIdentifier(int peerIdentifier) {
+        this.sessionInfo.setRemoteBgpIdentifier(peerIdentifier);
+    }
+
+    @Override
+    public int getBgpPeerIdentifier() {
+        return this.sessionInfo.getRemoteBgpIdentifier();
+    }
+
+    @Override
+    public int getNegotiatedHoldTime() {
+        return this.sessionInfo.getNegotiatedholdTime();
+    }
+
+    @Override
+    public void setNegotiatedHoldTime(short negotiatedHoldTime) {
+        this.sessionInfo.setNegotiatedholdTime(negotiatedHoldTime);
+    }
+
+    @Override
+    public boolean isHandshakeComplete() {
+        return isHandShakeComplete;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).omitNullValues().add("channel", channelId())
+                .add("bgpId", getBGPId()).toString();
+    }
+}
diff --git a/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPSessionInfo.java b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPSessionInfo.java
new file mode 100755
index 0000000..207d783
--- /dev/null
+++ b/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BGPSessionInfo.java
@@ -0,0 +1,149 @@
+/*
+ * 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.bgpio.protocol.BGPVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class maintains BGP peer session info.
+ */
+public class BGPSessionInfo {
+
+    protected final Logger log = LoggerFactory.getLogger(BGPSessionInfo.class);
+    private BGPId remoteBgpId;
+    private BGPVersion remoteBgpVersion;
+    private short remoteBgpASNum;
+    private short remoteBgpholdTime;
+    private int remoteBgpIdentifier;
+    private short negotiatedholdTime;
+
+    /**
+     * Gets the negotiated hold time for the session.
+     *
+     * @return negotiated hold time.
+     */
+    public short getNegotiatedholdTime() {
+        return negotiatedholdTime;
+    }
+
+    /**
+     * Sets the negotiated hold time for the session.
+     *
+     * @param negotiatedholdTime negotiated hold time.
+     */
+    public void setNegotiatedholdTime(short negotiatedholdTime) {
+        this.negotiatedholdTime = negotiatedholdTime;
+    }
+
+    /**
+     * Gets the BGP ID of BGP peer.
+     *
+     * @return bgp ID.
+     */
+    public BGPId getRemoteBgpId() {
+        return remoteBgpId;
+    }
+
+    /**
+     * Sets the BGP ID of bgp peer.
+     *
+     * @param bgpId BGP ID to set.
+     */
+    public void setRemoteBgpId(BGPId bgpId) {
+        log.debug("Remote BGP ID {}", bgpId);
+        this.remoteBgpId = bgpId;
+    }
+
+    /**
+     * Gets the BGP version of peer.
+     *
+     * @return bgp version.
+     */
+    public BGPVersion getRemoteBgpVersion() {
+        return remoteBgpVersion;
+    }
+
+    /**
+     * Sets the BGP version for this bgp peer.
+     *
+     * @param bgpVersion bgp version to set.
+     */
+    public void setRemoteBgpVersion(BGPVersion bgpVersion) {
+        log.debug("Remote BGP version {}", bgpVersion);
+        this.remoteBgpVersion = bgpVersion;
+    }
+
+    /**
+     * Gets the BGP remote bgp AS number.
+     *
+     * @return remoteBgpASNum peer AS number.
+     */
+    public short getRemoteBgpASNum() {
+        return remoteBgpASNum;
+    }
+
+    /**
+     * Sets the AS Number for this bgp peer.
+     *
+     * @param bgpASNum the autonomous system number value to set.
+     */
+    public void setRemoteBgpASNum(short bgpASNum) {
+        log.debug("Remote BGP AS number {}", bgpASNum);
+        this.remoteBgpASNum = bgpASNum;
+    }
+
+    /**
+     * Gets the BGP peer hold time.
+     *
+     * @return bgp hold time.
+     */
+    public short getRemoteBgpHoldTime() {
+        return remoteBgpholdTime;
+    }
+
+    /**
+     * Sets the hold time for this bgp peer.
+     *
+     * @param holdTime the hold timer value to set.
+     */
+    public void setRemoteBgpHoldTime(short holdTime) {
+        log.debug("Remote BGP HoldTime {}", holdTime);
+        this.remoteBgpholdTime = holdTime;
+    }
+
+    /**
+     * Gets the BGP version for this bgp peer.
+     *
+     * @return bgp identifier.
+     */
+    public int getRemoteBgpIdentifier() {
+        return remoteBgpIdentifier;
+    }
+
+    /**
+     * Sets the peer identifier value.
+     *
+     * @param bgpIdentifier the bgp peer identifier value.
+     */
+    public void setRemoteBgpIdentifier(int bgpIdentifier) {
+        log.debug("Remote BGP Identifier {}", bgpIdentifier);
+        this.remoteBgpIdentifier = bgpIdentifier;
+    }
+}