Bgp and Pcep maintaiability

Change-Id: I2c14cc29d4900ef2f0fbffd4761b0d78e282910f
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/Controller.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/Controller.java
index b7d1d52..92ea93a 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/Controller.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/Controller.java
@@ -20,8 +20,11 @@
 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.LinkedList;
+import java.util.TreeMap;
+import java.util.List;
+import java.util.HashMap;
 import java.util.concurrent.Executors;
 
 import org.jboss.netty.bootstrap.ServerBootstrap;
@@ -30,6 +33,7 @@
 import org.jboss.netty.channel.group.DefaultChannelGroup;
 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
 import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepCfg;
 import org.onosproject.pcep.controller.PcepPacketStats;
 import org.onosproject.pcep.controller.driver.PcepAgent;
 import org.onosproject.pcep.controller.driver.PcepClientDriver;
@@ -48,7 +52,7 @@
     private static final Logger log = LoggerFactory.getLogger(Controller.class);
 
     private static final PcepFactory FACTORY1 = PcepFactories.getFactory(PcepVersion.PCEP_1);
-
+    private PcepCfg pcepConfig = new PcepConfig();
     private ChannelGroup cg;
 
     // Configuration options
@@ -60,12 +64,83 @@
 
     private PcepAgent agent;
 
+    private Map<String, String> peerMap = new TreeMap<>();
+    private Map<String, List<String>> pcepExceptionMap = new TreeMap<>();
+    private Map<Integer, Integer> pcepErrorMsg = new TreeMap<>();
+    private Map<String, Byte> sessionMap = new TreeMap<>();
+    private LinkedList<String> pcepExceptionList = new LinkedList<String>();
+
     private NioServerSocketChannelFactory execFactory;
 
     // Perf. related configuration
     private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
 
     /**
+     * pcep session information.
+     *
+     * @param peerId id of the peer with which the session is being formed
+     * @param status pcep session status
+     * @param sessionId pcep session id
+     */
+    public void peerStatus(String peerId, String status, byte sessionId) {
+        if (peerId != null) {
+            peerMap.put(peerId, status);
+            sessionMap.put(peerId, sessionId);
+        } else {
+            log.debug("Peer Id is null");
+        }
+    }
+
+    /**
+     * Pcep session exceptions information.
+     *
+     * @param peerId id of the peer which has generated the exception
+     * @param exception pcep session exception
+     */
+    public void peerExceptions(String peerId, String exception) {
+        if (peerId != null) {
+            pcepExceptionList.add(exception);
+            pcepExceptionMap.put(peerId, pcepExceptionList);
+        } else {
+            log.debug("Peer Id is null");
+        }
+        if (pcepExceptionList.size() > 10) {
+            pcepExceptionList.clear();
+            pcepExceptionList.add(exception);
+            pcepExceptionMap.put(peerId, pcepExceptionList);
+        }
+    }
+
+    /**
+     * Create a map of pcep error messages received.
+     *
+     * @param peerId id of the peer which has sent the error message
+     * @param errorType error type of pcep error messgae
+     * @param errValue error value of pcep error messgae
+     */
+    public void peerErrorMsg(String peerId, Integer errorType, Integer errValue) {
+        if (peerId == null) {
+            pcepErrorMsg.put(errorType, errValue);
+        } else {
+            if (pcepErrorMsg.size() > 10) {
+                pcepErrorMsg.clear();
+            }
+            pcepErrorMsg.put(errorType, errValue);
+        }
+    }
+
+    /**
+     * Returns the pcep session details.
+     *
+     * @return pcep session details
+     */
+    public Map<String, Byte> mapSession() {
+        return this.sessionMap;
+    }
+
+
+
+    /**
      * Returns factory version for processing pcep messages.
      *
      * @return instance of factory version
@@ -84,6 +159,33 @@
     }
 
     /**
+     * Returns the list of pcep peers with session information.
+     *
+     * @return pcep peer information
+     */
+    public  Map<String, String> mapPeer() {
+        return this.peerMap;
+    }
+
+    /**
+     * Returns the list of pcep exceptions per peer.
+     *
+     * @return pcep exceptions
+     */
+    public  Map<String, List<String>> exceptionsMap() {
+        return this.pcepExceptionMap;
+    }
+
+    /**
+     * Returns the type and value of pcep error messages.
+     *
+     * @return pcep error message
+     */
+    public Map<Integer, Integer> mapErrorMsg() {
+        return this.pcepErrorMsg;
+    }
+
+    /**
      * Tell controller that we're ready to accept pcc connections.
      */
     public void run() {
@@ -101,7 +203,7 @@
             InetSocketAddress sa = new InetSocketAddress(pcepPort);
             cg = new DefaultChannelGroup();
             cg.add(bootstrap.bind(sa));
-            log.info("Listening for PCC connection on {}", sa);
+            log.debug("Listening for PCC connection on {}", sa);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
index d2523f5..d557116 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
@@ -40,6 +40,7 @@
 import org.onlab.packet.IpAddress;
 import org.onosproject.pcep.controller.ClientCapability;
 import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepCfg;
 import org.onosproject.pcep.controller.driver.PcepClientDriver;
 import org.onosproject.pcepio.exceptions.PcepParseException;
 import org.onosproject.pcepio.protocol.PcepError;
@@ -87,7 +88,9 @@
     // State needs to be volatile because the HandshakeTimeoutHandler
     // needs to check if the handshake is complete
     private volatile ChannelState state;
-
+    private String peerAddr;
+    private SocketAddress address;
+    private InetSocketAddress inetAddress;
     // When a pcc client with a ip addresss is found (i.e we already have a
     // connected client with the same ip), the new client is immediately
     // disconnected. At that point netty callsback channelDisconnected() which
@@ -122,226 +125,38 @@
     //  Channel State Machine
     //*************************
 
-    /**
-     * The state machine for handling the client/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.
-         */
-        INIT(false) {
-
-        },
-        /**
-         * Once the session is established, wait for open message.
-         */
-        OPENWAIT(false) {
-            @Override
-            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
-
-                log.info("Message received in OPEN WAIT State");
-
-                //check for open message
-                if (m.getType() != PcepType.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.pcepPacketStats.addInPacket();
-                    PcepOpenMsg pOpenmsg = (PcepOpenMsg) m;
-                        //Do Capability negotiation.
-                        h.capabilityNegotiation(pOpenmsg);
-                        log.debug("Sending handshake OPEN message");
-                        h.sessionId = pOpenmsg.getPcepOpenObject().getSessionId();
-                        h.pcepVersion = pOpenmsg.getPcepOpenObject().getVersion();
-
-                        //setting keepalive and deadTimer
-                        byte yKeepalive = pOpenmsg.getPcepOpenObject().getKeepAliveTime();
-                        byte yDeadTimer = pOpenmsg.getPcepOpenObject().getDeadTime();
-                        h.keepAliveTime = yKeepalive;
-                        if (yKeepalive < yDeadTimer) {
-                            h.deadTime = yDeadTimer;
-                        } else {
-                            if (DEADTIMER_MAXIMUM_VALUE > (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER)) {
-                                h.deadTime = (byte) (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER);
-                            } else {
-                                h.deadTime = DEADTIMER_MAXIMUM_VALUE;
-                            }
-                        }
-
-                        /*
-                         * If MPLS LSR id and PCEP session socket IP addresses are not same,
-                         * the MPLS LSR id will be encoded in separate TLV.
-                         * We always maintain session information based on LSR ids.
-                         * The socket IP is stored in channel.
-                         */
-                        LinkedList<PcepValueType> optionalTlvs = pOpenmsg.getPcepOpenObject().getOptionalTlv();
-                        if (optionalTlvs != null) {
-                            for (PcepValueType optionalTlv : optionalTlvs) {
-                                if (optionalTlv instanceof NodeAttributesTlv) {
-                                    List<PcepValueType> subTlvs = ((NodeAttributesTlv) optionalTlv)
-                                            .getllNodeAttributesSubTLVs();
-                                    if (subTlvs == null) {
-                                        break;
-                                    }
-                                    for (PcepValueType subTlv : subTlvs) {
-                                        if (subTlv instanceof IPv4RouterIdOfLocalNodeSubTlv) {
-                                            h.thispccId = PccId.pccId(IpAddress
-                                                    .valueOf(((IPv4RouterIdOfLocalNodeSubTlv) subTlv).getInt()));
-                                            break;
-                                        }
-                                    }
-                                    break;
-                                }
-                            }
-                        }
-
-                        if (h.thispccId == null) {
-                            final SocketAddress address = h.channel.getRemoteAddress();
-                            if (!(address instanceof InetSocketAddress)) {
-                                throw new IOException("Invalid client connection. Pcc is indentifed based on IP");
-                            }
-
-                            final InetSocketAddress inetAddress = (InetSocketAddress) address;
-                            h.thispccId = PccId.pccId(IpAddress.valueOf(inetAddress.getAddress()));
-                        }
-
-                        h.sendHandshakeOpenMessage();
-                        h.pcepPacketStats.addOutPacket();
-                        h.setState(KEEPWAIT);
-                }
-            }
-        },
-        /**
-         * Once the open messages are exchanged, wait for keep alive message.
-         */
-        KEEPWAIT(false) {
-            @Override
-            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
-                log.info("message received in KEEPWAIT state");
-                //check for keep alive message
-                if (m.getType() != PcepType.KEEP_ALIVE) {
-                    // When the message type is not keep alive message increment the wrong packet statistics
-                    h.processUnknownMsg();
-                    log.error("message is not KEEPALIVE message");
-                } else {
-                    // Set the client connected status
-                    h.pcepPacketStats.addInPacket();
-                    log.debug("sending keep alive message in KEEPWAIT state");
-                    h.pc = h.controller.getPcepClientInstance(h.thispccId, h.sessionId, h.pcepVersion,
-                            h.pcepPacketStats);
-                    //Get pc instance and set capabilities
-                    h.pc.setCapability(h.capability);
-
-                    // Initilialize DB sync status.
-                    h.pc.setLspDbSyncStatus(NOT_SYNCED);
-                    h.pc.setLabelDbSyncStatus(NOT_SYNCED);
-
-                    // set the status of pcc as connected
-                    h.pc.setConnected(true);
-                    h.pc.setChannel(h.channel);
-
-                    // set any other specific parameters to the pcc
-                    h.pc.setPcVersion(h.pcepVersion);
-                    h.pc.setPcSessionId(h.sessionId);
-                    h.pc.setPcKeepAliveTime(h.keepAliveTime);
-                    h.pc.setPcDeadTime(h.deadTime);
-                    int keepAliveTimer = h.keepAliveTime & BYTE_MASK;
-                    int deadTimer = h.deadTime & BYTE_MASK;
-                    if (0 == h.keepAliveTime) {
-                        h.deadTime = 0;
-                    }
-                    // handle keep alive and dead time
-                    if (keepAliveTimer != PcepPipelineFactory.DEFAULT_KEEP_ALIVE_TIME
-                            || deadTimer != PcepPipelineFactory.DEFAULT_DEAD_TIME) {
-
-                        h.channel.getPipeline().replace("idle", "idle",
-                                new IdleStateHandler(PcepPipelineFactory.TIMER, deadTimer, keepAliveTimer, 0));
-                    }
-                    log.debug("Dead timer : " + deadTimer);
-                    log.debug("Keep alive time : " + keepAliveTimer);
-
-                    //set the state handshake completion.
-
-                    h.sendKeepAliveMessage();
-                    h.pcepPacketStats.addOutPacket();
-                    h.setHandshakeComplete(true);
-
-                    if (!h.pc.connectClient()) {
-                        disconnectDuplicate(h);
-                    } else {
-                        h.setState(ESTABLISHED);
-                        //Session is established, add a network configuration with LSR id and device capabilities.
-                        h.addNode();
-                    }
-                }
-            }
-        },
-        /**
-         * Once the keep alive messages are exchanged, the state is established.
-         */
-        ESTABLISHED(true) {
-            @Override
-            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
-
-                //h.channel.getPipeline().remove("waittimeout");
-                log.debug("Message received in established state " + m.getType());
-                //dispatch the message
-                h.dispatchMessage(m);
-            }
-        };
-        private boolean handshakeComplete;
-
-        ChannelState(boolean handshakeComplete) {
-            this.handshakeComplete = handshakeComplete;
-        }
-
-        void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
-            // do nothing
-        }
-
-        /**
-         * Is this a state in which the handshake has completed.
-         *
-         * @return true if the handshake is complete
-         */
-        public boolean isHandshakeComplete() {
-            return this.handshakeComplete;
-        }
-
-        protected void disconnectDuplicate(PcepChannelHandler h) {
-            log.error("Duplicated Pcc IP or incompleted cleanup - " + "disconnecting channel {}",
-                    h.getClientInfoString());
-            h.duplicatePccIdFound = Boolean.TRUE;
-            h.channel.disconnect();
-        }
-
-        /**
-         * Sets handshake complete status.
-         *
-         * @param handshakeComplete status of handshake
-         */
-        public void setHandshakeComplete(boolean handshakeComplete) {
-            this.handshakeComplete = handshakeComplete;
-        }
-
-    }
-
     @Override
     public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
         channel = e.getChannel();
         log.info("PCC 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();
+
         // Wait for open message from pcc client
         setState(ChannelState.OPENWAIT);
+        controller.peerStatus(peerAddr, PcepCfg.State.OPENWAIT.toString(), sessionId);
     }
 
     @Override
     public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
         log.info("Pcc disconnected callback for pc:{}. Cleaning up ...", getClientInfoString());
+        controller.peerStatus(peerAddr, PcepCfg.State.DOWN.toString(), sessionId);
+
+        channel = e.getChannel();
+        address = channel.getRemoteAddress();
+        if (!(address instanceof InetSocketAddress)) {
+            throw new IOException("Invalid peer connection.");
+        }
+
+        inetAddress = (InetSocketAddress) address;
+        peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString();
+
         if (thispccId != null) {
             if (!duplicatePccIdFound) {
                 // if the disconnected client (on this ChannelHandler)
@@ -377,6 +192,7 @@
                 // OpenWait timer.
                 errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_2);
                 log.debug("Sending PCEP-ERROR message to PCC.");
+                controller.peerExceptions(peerAddr, e.getCause().toString());
                 channel.write(Collections.singletonList(errMsg));
                 channel.close();
                 state = ChannelState.INIT;
@@ -386,14 +202,17 @@
                 // KeepWait timer.
                 errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_7);
                 log.debug("Sending PCEP-ERROR message to PCC.");
+                controller.peerExceptions(peerAddr, e.getCause().toString());
                 channel.write(Collections.singletonList(errMsg));
                 channel.close();
                 state = ChannelState.INIT;
                 return;
             }
         } else if (e.getCause() instanceof ClosedChannelException) {
+            controller.peerExceptions(peerAddr, e.getCause().toString());
             log.debug("Channel for pc {} already closed", getClientInfoString());
         } else if (e.getCause() instanceof IOException) {
+            controller.peerExceptions(peerAddr, e.getCause().toString());
             log.error("Disconnecting client {} due to IO Error: {}", getClientInfoString(), e.getCause().getMessage());
             if (log.isDebugEnabled()) {
                 // still print stack trace if debug is enabled
@@ -401,6 +220,7 @@
             }
             channel.close();
         } else if (e.getCause() instanceof PcepParseException) {
+            controller.peerExceptions(peerAddr, e.getCause().toString());
             PcepParseException errMsgParse = (PcepParseException) e.getCause();
             byte errorType = errMsgParse.getErrorType();
             byte errorValue = errMsgParse.getErrorValue();
@@ -414,8 +234,10 @@
             }
         } else if (e.getCause() instanceof RejectedExecutionException) {
             log.warn("Could not process message: queue full");
+            controller.peerExceptions(peerAddr, e.getCause().toString());
         } else {
             log.error("Error while processing message from client " + getClientInfoString() + "state " + this.state);
+            controller.peerExceptions(peerAddr, e.getCause().toString());
             channel.close();
         }
     }
@@ -458,15 +280,6 @@
     }
 
     /**
-     * To set the handshake status.
-     *
-     * @param handshakeComplete value is handshake 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
@@ -476,6 +289,15 @@
     }
 
     /**
+     * To set the handshake status.
+     *
+     * @param handshakeComplete value is handshake status
+     */
+    public void setHandshakeComplete(boolean handshakeComplete) {
+        this.state.setHandshakeComplete(handshakeComplete);
+    }
+
+    /**
      * To handle the pcep message.
      *
      * @param m pcep message
@@ -561,24 +383,24 @@
             PcepValueType tlv = listIterator.next();
 
             switch (tlv.getType()) {
-            case PceccCapabilityTlv.TYPE:
-                pceccCapability = true;
-                if (((PceccCapabilityTlv) tlv).sBit()) {
-                    labelStackCapability = true;
-                }
-                break;
-            case StatefulPceCapabilityTlv.TYPE:
-                statefulPceCapability = true;
-                StatefulPceCapabilityTlv stetefulPcCapTlv = (StatefulPceCapabilityTlv) tlv;
-                if (stetefulPcCapTlv.getIFlag()) {
-                    pcInstantiationCapability = true;
-                }
-                break;
-            case SrPceCapabilityTlv.TYPE:
-                srCapability = true;
-                break;
-            default:
-                continue;
+                case PceccCapabilityTlv.TYPE:
+                    pceccCapability = true;
+                    if (((PceccCapabilityTlv) tlv).sBit()) {
+                        labelStackCapability = true;
+                    }
+                    break;
+                case StatefulPceCapabilityTlv.TYPE:
+                    statefulPceCapability = true;
+                    StatefulPceCapabilityTlv stetefulPcCapTlv = (StatefulPceCapabilityTlv) tlv;
+                    if (stetefulPcCapTlv.getIFlag()) {
+                        pcInstantiationCapability = true;
+                    }
+                    break;
+                case SrPceCapabilityTlv.TYPE:
+                    srCapability = true;
+                    break;
+                default:
+                    continue;
             }
         }
         this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability,
@@ -588,7 +410,7 @@
     /**
      * Send keep alive message.
      *
-     * @throws IOException when channel is disconnected
+     * @throws IOException        when channel is disconnected
      * @throws PcepParseException while building keep alive message
      */
     private void sendKeepAliveMessage() throws IOException, PcepParseException {
@@ -638,22 +460,22 @@
 
         llerrObj.add(errObj);
 
-            //If Error caught in other than Openmessage
-            LinkedList<PcepError> llPcepErr = new LinkedList<>();
+        //If Error caught in other than Openmessage
+        LinkedList<PcepError> llPcepErr = new LinkedList<>();
 
-            PcepError pcepErr = factory1.buildPcepError()
-                    .setErrorObjList(llerrObj)
-                    .build();
+        PcepError pcepErr = factory1.buildPcepError()
+                .setErrorObjList(llerrObj)
+                .build();
 
-            llPcepErr.add(pcepErr);
+        llPcepErr.add(pcepErr);
 
-            PcepErrorInfo errInfo = factory1.buildPcepErrorInfo()
-                    .setPcepErrorList(llPcepErr)
-                    .build();
+        PcepErrorInfo errInfo = factory1.buildPcepErrorInfo()
+                .setPcepErrorList(llPcepErr)
+                .build();
 
-            errMsg = factory1.buildPcepErrorMsg()
-                    .setPcepErrorInfo(errInfo)
-                    .build();
+        errMsg = factory1.buildPcepErrorMsg()
+                .setPcepErrorInfo(errInfo)
+                .build();
         return errMsg;
     }
 
@@ -690,4 +512,214 @@
             }
         }
     }
+
+    /**
+     * The state machine for handling the client/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.
+         */
+        INIT(false) {
+
+        },
+        /**
+         * Once the session is established, wait for open message.
+         */
+        OPENWAIT(false) {
+            @Override
+            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+
+                log.info("Message received in OPEN WAIT State");
+
+                //check for open message
+                if (m.getType() != PcepType.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.pcepPacketStats.addInPacket();
+                    PcepOpenMsg pOpenmsg = (PcepOpenMsg) m;
+                    //Do Capability negotiation.
+                    h.capabilityNegotiation(pOpenmsg);
+                    log.debug("Sending handshake OPEN message");
+                    h.sessionId = pOpenmsg.getPcepOpenObject().getSessionId();
+                    h.pcepVersion = pOpenmsg.getPcepOpenObject().getVersion();
+
+                    //setting keepalive and deadTimer
+                    byte yKeepalive = pOpenmsg.getPcepOpenObject().getKeepAliveTime();
+                    byte yDeadTimer = pOpenmsg.getPcepOpenObject().getDeadTime();
+                    h.keepAliveTime = yKeepalive;
+                    if (yKeepalive < yDeadTimer) {
+                        h.deadTime = yDeadTimer;
+                    } else {
+                        if (DEADTIMER_MAXIMUM_VALUE > (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER)) {
+                            h.deadTime = (byte) (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER);
+                        } else {
+                            h.deadTime = DEADTIMER_MAXIMUM_VALUE;
+                        }
+                    }
+
+                        /*
+                         * If MPLS LSR id and PCEP session socket IP addresses are not same,
+                         * the MPLS LSR id will be encoded in separate TLV.
+                         * We always maintain session information based on LSR ids.
+                         * The socket IP is stored in channel.
+                         */
+                    LinkedList<PcepValueType> optionalTlvs = pOpenmsg.getPcepOpenObject().getOptionalTlv();
+                    if (optionalTlvs != null) {
+                        for (PcepValueType optionalTlv : optionalTlvs) {
+                            if (optionalTlv instanceof NodeAttributesTlv) {
+                                List<PcepValueType> subTlvs = ((NodeAttributesTlv) optionalTlv)
+                                        .getllNodeAttributesSubTLVs();
+                                if (subTlvs == null) {
+                                    break;
+                                }
+                                for (PcepValueType subTlv : subTlvs) {
+                                    if (subTlv instanceof IPv4RouterIdOfLocalNodeSubTlv) {
+                                        h.thispccId = PccId.pccId(IpAddress
+                                                .valueOf(((IPv4RouterIdOfLocalNodeSubTlv) subTlv).getInt()));
+                                        break;
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                    }
+
+                    if (h.thispccId == null) {
+                        final SocketAddress address = h.channel.getRemoteAddress();
+                        if (!(address instanceof InetSocketAddress)) {
+                            throw new IOException("Invalid client connection. Pcc is indentifed based on IP");
+                        }
+
+                        final InetSocketAddress inetAddress = (InetSocketAddress) address;
+                        h.thispccId = PccId.pccId(IpAddress.valueOf(inetAddress.getAddress()));
+                    }
+
+                    h.sendHandshakeOpenMessage();
+                    h.pcepPacketStats.addOutPacket();
+                    h.setState(KEEPWAIT);
+                    h.controller.peerStatus(h.peerAddr.toString(), PcepCfg.State.KEEPWAIT.toString(), h.sessionId);
+                }
+            }
+        },
+        /**
+         * Once the open messages are exchanged, wait for keep alive message.
+         */
+        KEEPWAIT(false) {
+            @Override
+            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+                log.info("Message received in KEEPWAIT state");
+                //check for keep alive message
+                if (m.getType() != PcepType.KEEP_ALIVE) {
+                    // When the message type is not keep alive message increment the wrong packet statistics
+                    h.processUnknownMsg();
+                    log.error("Message is not KEEPALIVE message");
+                } else {
+                    // Set the client connected status
+                    h.pcepPacketStats.addInPacket();
+                    log.debug("sending keep alive message in KEEPWAIT state");
+                    h.pc = h.controller.getPcepClientInstance(h.thispccId, h.sessionId, h.pcepVersion,
+                            h.pcepPacketStats);
+                    //Get pc instance and set capabilities
+                    h.pc.setCapability(h.capability);
+
+                    // Initilialize DB sync status.
+                    h.pc.setLspDbSyncStatus(NOT_SYNCED);
+                    h.pc.setLabelDbSyncStatus(NOT_SYNCED);
+
+                    // set the status of pcc as connected
+                    h.pc.setConnected(true);
+                    h.pc.setChannel(h.channel);
+
+                    // set any other specific parameters to the pcc
+                    h.pc.setPcVersion(h.pcepVersion);
+                    h.pc.setPcSessionId(h.sessionId);
+                    h.pc.setPcKeepAliveTime(h.keepAliveTime);
+                    h.pc.setPcDeadTime(h.deadTime);
+                    int keepAliveTimer = h.keepAliveTime & BYTE_MASK;
+                    int deadTimer = h.deadTime & BYTE_MASK;
+                    if (0 == h.keepAliveTime) {
+                        h.deadTime = 0;
+                    }
+                    // handle keep alive and dead time
+                    if (keepAliveTimer != PcepPipelineFactory.DEFAULT_KEEP_ALIVE_TIME
+                            || deadTimer != PcepPipelineFactory.DEFAULT_DEAD_TIME) {
+
+                        h.channel.getPipeline().replace("idle", "idle",
+                                new IdleStateHandler(PcepPipelineFactory.TIMER, deadTimer, keepAliveTimer, 0));
+                    }
+                    log.debug("Dead timer : " + deadTimer);
+                    log.debug("Keep alive time : " + keepAliveTimer);
+
+                    //set the state handshake completion.
+
+                    h.sendKeepAliveMessage();
+                    h.pcepPacketStats.addOutPacket();
+                    h.setHandshakeComplete(true);
+
+                    if (!h.pc.connectClient()) {
+                        disconnectDuplicate(h);
+                    } else {
+                        h.setState(ESTABLISHED);
+                     h.controller.peerStatus(h.peerAddr.toString(), PcepCfg.State.ESTABLISHED.toString(), h.sessionId);
+                        //Session is established, add a network configuration with LSR id and device capabilities.
+                        h.addNode();
+                    }
+                }
+            }
+        },
+        /**
+         * Once the keep alive messages are exchanged, the state is established.
+         */
+        ESTABLISHED(true) {
+            @Override
+            void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+
+                //h.channel.getPipeline().remove("waittimeout");
+                log.debug("Message received in established state " + m.getType());
+                //dispatch the message
+                h.dispatchMessage(m);
+            }
+        };
+        private boolean handshakeComplete;
+
+        ChannelState(boolean handshakeComplete) {
+            this.handshakeComplete = handshakeComplete;
+        }
+
+        void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
+            // do nothing
+        }
+
+        /**
+         * Is this a state in which the handshake has completed.
+         *
+         * @return true if the handshake is complete
+         */
+        public boolean isHandshakeComplete() {
+            return this.handshakeComplete;
+        }
+
+        /**
+         * Sets handshake complete status.
+         *
+         * @param handshakeComplete status of handshake
+         */
+        public void setHandshakeComplete(boolean handshakeComplete) {
+            this.handshakeComplete = handshakeComplete;
+        }
+
+        protected void disconnectDuplicate(PcepChannelHandler h) {
+            log.error("Duplicated Pcc IP or incompleted cleanup - " + "disconnecting channel {}",
+                    h.getClientInfoString());
+            h.duplicatePccIdFound = Boolean.TRUE;
+            h.channel.disconnect();
+        }
+
+    }
 }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
index 999dd40..8ffc707 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
@@ -15,17 +15,18 @@
  */
 package org.onosproject.pcep.controller.impl;
 
-import java.util.Arrays;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -185,6 +186,7 @@
     private DeviceListener deviceListener = new InternalDeviceListener();
     private LinkListener linkListener = new InternalLinkListener();
     private InternalConfigListener cfgListener = new InternalConfigListener();
+    private Map<Integer, Integer> pcepErrorMsg = new TreeMap<>();
 
     @Activate
     public void activate() {
@@ -220,6 +222,39 @@
     }
 
     @Override
+    public void peerErrorMsg(String peerId, Integer errorType, Integer errValue) {
+        if (peerId == null) {
+            pcepErrorMsg.put(errorType, errValue);
+        } else {
+            if (pcepErrorMsg.size() > 10) {
+                pcepErrorMsg.clear();
+            }
+            pcepErrorMsg.put(errorType, errValue);
+        }
+    }
+
+    @Override
+    public Map<String, List<String>> getPcepExceptions() {
+        return this.ctrl.exceptionsMap();
+    }
+
+    @Override
+    public Map<Integer, Integer> getPcepErrorMsg() {
+        return pcepErrorMsg;
+    }
+
+
+    @Override
+    public Map<String, String> getPcepSessionMap() {
+        return this.ctrl.mapPeer();
+    }
+
+    @Override
+    public Map<String, Byte> getPcepSessionIdMap() {
+        return this.ctrl.mapSession();
+    }
+
+    @Override
     public Collection<PcepClient> getClients() {
         return connectedClients.values();
     }
@@ -879,7 +914,7 @@
 
             connectedClients.remove(pccId);
             for (PcepClientListener l : pcepClientListener) {
-                log.warn("removal for {}", pccId.toString());
+                log.warn("Removal for {}", pccId.toString());
                 l.clientDisconnected(pccId);
             }
         }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepConfig.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepConfig.java
new file mode 100644
index 0000000..2c8c162
--- /dev/null
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepConfig.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-present 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.pcep.controller.impl;
+
+import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepCfg;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.TreeMap;
+
+
+public class PcepConfig implements PcepCfg {
+
+    protected static final Logger log = LoggerFactory.getLogger(PcepConfig.class);
+
+    private State state = State.INIT;
+    private PccId pccId;
+    private TreeMap<String, PcepCfg> bgpPeerTree = new TreeMap<>();
+
+    @Override
+    public State getState() {
+        return state;
+    }
+
+    @Override
+    public void setState(State state) {
+        this.state = state;
+    }
+
+}