bc8721d73ecc8d54bddcae8c9d5ccd9ab23bbc06
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onosproject.pcep.controller.impl;
18
19 import java.io.IOException;
20 import java.net.InetSocketAddress;
21 import java.net.SocketAddress;
22 import java.nio.channels.ClosedChannelException;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.ListIterator;
28 import java.util.concurrent.RejectedExecutionException;
29
30 import org.jboss.netty.channel.Channel;
31 import org.jboss.netty.channel.ChannelHandlerContext;
32 import org.jboss.netty.channel.ChannelStateEvent;
33 import org.jboss.netty.channel.ExceptionEvent;
34 import org.jboss.netty.channel.MessageEvent;
35 import org.jboss.netty.handler.timeout.IdleState;
36 import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
37 import org.jboss.netty.handler.timeout.IdleStateEvent;
38 import org.jboss.netty.handler.timeout.IdleStateHandler;
39 import org.jboss.netty.handler.timeout.ReadTimeoutException;
40 import org.onlab.packet.IpAddress;
41 import org.onosproject.pcep.controller.PccId;
42 import org.onosproject.pcep.controller.driver.PcepClientDriver;
43 import org.onosproject.pcepio.exceptions.PcepParseException;
44 import org.onosproject.pcepio.protocol.PcepError;
45 import org.onosproject.pcepio.protocol.PcepErrorInfo;
46 import org.onosproject.pcepio.protocol.PcepErrorMsg;
47 import org.onosproject.pcepio.protocol.PcepErrorObject;
48 import org.onosproject.pcepio.protocol.PcepFactory;
49 import org.onosproject.pcepio.protocol.PcepMessage;
50 import org.onosproject.pcepio.protocol.PcepOpenMsg;
51 import org.onosproject.pcepio.protocol.PcepOpenObject;
52 import org.onosproject.pcepio.protocol.PcepType;
53 import org.onosproject.pcepio.protocol.PcepVersion;
54 import org.onosproject.pcepio.types.ErrorObjListWithOpen;
55 import org.onosproject.pcepio.types.PceccCapabilityTlv;
56 import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
57 import org.onosproject.pcepio.types.PcepErrorDetailInfo;
58 import org.onosproject.pcepio.types.PcepValueType;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 /**
63  * Channel handler deals with the pcc client connection and dispatches
64  * messages from client to the appropriate locations.
65  */
66 class PcepChannelHandler extends IdleStateAwareChannelHandler {
67     static final byte DEADTIMER_MAXIMUM_VALUE = (byte) 0xFF;
68     static final byte KEEPALIVE_MULTIPLE_FOR_DEADTIMER = 4;
69     private static final Logger log = LoggerFactory.getLogger(PcepChannelHandler.class);
70     private final Controller controller;
71     private PcepClientDriver pc;
72     private PccId thispccId;
73     private Channel channel;
74     private byte sessionId = 0;
75     private byte keepAliveTime;
76     private byte deadTime;
77     private PcepPacketStatsImpl pcepPacketStats;
78     static final int MAX_WRONG_COUNT_PACKET = 5;
79     static final int BYTE_MASK = 0xFF;
80
81     // State needs to be volatile because the HandshakeTimeoutHandler
82     // needs to check if the handshake is complete
83     private volatile ChannelState state;
84
85     // When a pcc client with a ip addresss is found (i.e we already have a
86     // connected client with the same ip), the new client is immediately
87     // disconnected. At that point netty callsback channelDisconnected() which
88     // proceeds to cleaup client state - we need to ensure that it does not cleanup
89     // client state for the older (still connected) client
90     private volatile Boolean duplicatePccIdFound;
91
92     //Indicates the pcep version used by this pcc client
93     protected PcepVersion pcepVersion;
94     protected PcepFactory factory1;
95
96     /**
97      * Create a new unconnected PcepChannelHandler.
98      * @param controller parent controller
99      */
100     PcepChannelHandler(Controller controller) {
101         this.controller = controller;
102         this.state = ChannelState.INIT;
103         factory1 = controller.getPcepMessageFactory1();
104         duplicatePccIdFound = Boolean.FALSE;
105         pcepPacketStats = new PcepPacketStatsImpl();
106     }
107
108     /**
109      * To disconnect a PCC.
110      */
111     public void disconnectClient() {
112         pc.disconnectClient();
113     }
114
115     //*************************
116     //  Channel State Machine
117     //*************************
118
119     /**
120      * The state machine for handling the client/channel state. All state
121      * transitions should happen from within the state machine (and not from other
122      * parts of the code)
123      */
124     enum ChannelState {
125         /**
126          * Initial state before channel is connected.
127          */
128         INIT(false) {
129
130         },
131         /**
132          * Once the session is established, wait for open message.
133          */
134         OPENWAIT(false) {
135             @Override
136             void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
137
138                 log.debug("Message received in OPEN WAIT State");
139
140                 //check for open message
141                 if (m.getType() != PcepType.OPEN) {
142                     // When the message type is not open message increment the wrong packet statistics
143                     h.processUnknownMsg();
144                     log.debug("message is not OPEN message");
145                 } else {
146
147                     h.pcepPacketStats.addInPacket();
148                     PcepOpenMsg pOpenmsg = (PcepOpenMsg) m;
149                     // do Capability validation.
150                     if (h.capabilityValidation(pOpenmsg)) {
151                         log.debug("Sending handshake OPEN message");
152                         h.sessionId = pOpenmsg.getPcepOpenObject().getSessionId();
153                         h.pcepVersion = pOpenmsg.getPcepOpenObject().getVersion();
154
155                         //setting keepalive and deadTimer
156                         byte yKeepalive = pOpenmsg.getPcepOpenObject().getKeepAliveTime();
157                         byte yDeadTimer = pOpenmsg.getPcepOpenObject().getDeadTime();
158                         h.keepAliveTime = yKeepalive;
159                         if (yKeepalive < yDeadTimer) {
160                             h.deadTime = yDeadTimer;
161                         } else {
162                             if (DEADTIMER_MAXIMUM_VALUE > (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER)) {
163                                 h.deadTime = (byte) (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER);
164                             } else {
165                                 h.deadTime = DEADTIMER_MAXIMUM_VALUE;
166                             }
167                         }
168                         h.sendHandshakeOpenMessage();
169                         h.pcepPacketStats.addOutPacket();
170                         h.setState(KEEPWAIT);
171                     } else {
172                         log.debug("Capability validation failed. Sending PCEP-ERROR message to PCC.");
173                         // Send PCEP-ERROR message.
174                         PcepErrorMsg errMsg = h.getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_2,
175                                 PcepErrorDetailInfo.ERROR_VALUE_2);
176                         h.channel.write(Collections.singletonList(errMsg));
177                     }
178                 }
179             }
180         },
181         /**
182          * Once the open messages are exchanged, wait for keep alive message.
183          */
184         KEEPWAIT(false) {
185             @Override
186             void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
187                 log.debug("message received in KEEPWAIT state");
188                 //check for keep alive message
189                 if (m.getType() != PcepType.KEEP_ALIVE) {
190                     // When the message type is not keep alive message increment the wrong packet statistics
191                     h.processUnknownMsg();
192                     log.debug("message is not KEEPALIVE message");
193                 } else {
194                     // Set the client connected status
195                     h.pcepPacketStats.addInPacket();
196                     final SocketAddress address = h.channel.getRemoteAddress();
197                     if (!(address instanceof InetSocketAddress)) {
198                         throw new IOException("Invalid client connection. Pcc is indentifed based on IP");
199                     }
200                     log.debug("sending keep alive message in KEEPWAIT state");
201
202                     final InetSocketAddress inetAddress = (InetSocketAddress) address;
203                     h.thispccId = PccId.pccId(IpAddress.valueOf(inetAddress.getAddress()));
204                     h.pc = h.controller.getPcepClientInstance(h.thispccId, h.sessionId, h.pcepVersion,
205                             h.pcepPacketStats);
206                     // set the status of pcc as connected
207                     h.pc.setConnected(true);
208                     h.pc.setChannel(h.channel);
209
210                     // set any other specific parameters to the pcc
211                     h.pc.setPcVersion(h.pcepVersion);
212                     h.pc.setPcSessionId(h.sessionId);
213                     h.pc.setPcKeepAliveTime(h.keepAliveTime);
214                     h.pc.setPcDeadTime(h.deadTime);
215                     int keepAliveTimer = h.keepAliveTime & BYTE_MASK;
216                     int deadTimer = h.deadTime & BYTE_MASK;
217                     if (0 == h.keepAliveTime) {
218                         h.deadTime = 0;
219                     }
220                     // handle keep alive and dead time
221                     if (keepAliveTimer != PcepPipelineFactory.DEFAULT_KEEP_ALIVE_TIME
222                             || deadTimer != PcepPipelineFactory.DEFAULT_DEAD_TIME) {
223
224                         h.channel.getPipeline().replace("idle", "idle",
225                                 new IdleStateHandler(PcepPipelineFactory.TIMER, deadTimer, keepAliveTimer, 0));
226                     }
227                     log.debug("Dead timer : " + deadTimer);
228                     log.debug("Keep alive time : " + keepAliveTimer);
229
230                     //set the state handshake completion.
231                     h.sendKeepAliveMessage();
232                     h.pcepPacketStats.addOutPacket();
233                     h.setHandshakeComplete(true);
234
235                     if (!h.pc.connectClient()) {
236                         disconnectDuplicate(h);
237                     } else {
238                         h.setState(ESTABLISHED);
239                     }
240                 }
241             }
242         },
243         /**
244          * Once the keep alive messages are exchanged, the state is established.
245          */
246         ESTABLISHED(true) {
247             @Override
248             void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
249
250                 //h.channel.getPipeline().remove("waittimeout");
251                 log.debug("Message received in established state " + m.getType());
252                 //dispatch the message
253                 h.dispatchMessage(m);
254             }
255         };
256         private boolean handshakeComplete;
257
258         ChannelState(boolean handshakeComplete) {
259             this.handshakeComplete = handshakeComplete;
260         }
261
262         void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
263             // do nothing
264         }
265
266         /**
267          * Is this a state in which the handshake has completed.
268          *
269          * @return true if the handshake is complete
270          */
271         public boolean isHandshakeComplete() {
272             return this.handshakeComplete;
273         }
274
275         protected void disconnectDuplicate(PcepChannelHandler h) {
276             log.error("Duplicated Pcc IP or incompleted cleanup - " + "disconnecting channel {}",
277                     h.getClientInfoString());
278             h.duplicatePccIdFound = Boolean.TRUE;
279             h.channel.disconnect();
280         }
281
282         /**
283          * Sets handshake complete status.
284          *
285          * @param handshakeComplete status of handshake
286          */
287         public void setHandshakeComplete(boolean handshakeComplete) {
288             this.handshakeComplete = handshakeComplete;
289         }
290
291     }
292
293     @Override
294     public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
295         channel = e.getChannel();
296         log.info("PCC connected from {}", channel.getRemoteAddress());
297
298         // Wait for open message from pcc client
299         setState(ChannelState.OPENWAIT);
300     }
301
302     @Override
303     public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
304         log.info("Pcc disconnected callback for pc:{}. Cleaning up ...", getClientInfoString());
305         if (thispccId != null) {
306             if (!duplicatePccIdFound) {
307                 // if the disconnected client (on this ChannelHandler)
308                 // was not one with a duplicate-dpid, it is safe to remove all
309                 // state for it at the controller. Notice that if the disconnected
310                 // client was a duplicate-ip, calling the method below would clear
311                 // all state for the original client (with the same ip),
312                 // which we obviously don't want.
313                 log.debug("{}:removal called", getClientInfoString());
314                 if (pc != null) {
315                     pc.removeConnectedClient();
316                 }
317             } else {
318                 // A duplicate was disconnected on this ChannelHandler,
319                 // this is the same client reconnecting, but the original state was
320                 // not cleaned up - XXX check liveness of original ChannelHandler
321                 log.debug("{}:duplicate found", getClientInfoString());
322                 duplicatePccIdFound = Boolean.FALSE;
323             }
324         } else {
325             log.warn("no pccip in channelHandler registered for " + "disconnected client {}", getClientInfoString());
326         }
327     }
328
329     @Override
330     public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
331         PcepErrorMsg errMsg;
332         log.info("exceptionCaught: " + e.toString());
333
334         if (e.getCause() instanceof ReadTimeoutException) {
335             if (ChannelState.OPENWAIT == state) {
336                 // When ReadTimeout timer is expired in OPENWAIT state, it is considered
337                 // OpenWait timer.
338                 errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_2);
339                 log.debug("Sending PCEP-ERROR message to PCC.");
340                 channel.write(Collections.singletonList(errMsg));
341                 channel.close();
342                 state = ChannelState.INIT;
343                 return;
344             } else if (ChannelState.KEEPWAIT == state) {
345                 // When ReadTimeout timer is expired in KEEPWAIT state, is is considered
346                 // KeepWait timer.
347                 errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_7);
348                 log.debug("Sending PCEP-ERROR message to PCC.");
349                 channel.write(Collections.singletonList(errMsg));
350                 channel.close();
351                 state = ChannelState.INIT;
352                 return;
353             }
354         } else if (e.getCause() instanceof ClosedChannelException) {
355             log.debug("Channel for pc {} already closed", getClientInfoString());
356         } else if (e.getCause() instanceof IOException) {
357             log.error("Disconnecting client {} due to IO Error: {}", getClientInfoString(), e.getCause().getMessage());
358             if (log.isDebugEnabled()) {
359                 // still print stack trace if debug is enabled
360                 log.debug("StackTrace for previous Exception: ", e.getCause());
361             }
362             channel.close();
363         } else if (e.getCause() instanceof PcepParseException) {
364             PcepParseException errMsgParse = (PcepParseException) e.getCause();
365             byte errorType = errMsgParse.getErrorType();
366             byte errorValue = errMsgParse.getErrorValue();
367
368             if ((errorType == (byte) 0x0) && (errorValue == (byte) 0x0)) {
369                 processUnknownMsg();
370             } else {
371                 errMsg = getErrorMsg(errorType, errorValue);
372                 log.debug("Sending PCEP-ERROR message to PCC.");
373                 channel.write(Collections.singletonList(errMsg));
374             }
375         } else if (e.getCause() instanceof RejectedExecutionException) {
376             log.warn("Could not process message: queue full");
377         } else {
378             log.error("Error while processing message from client " + getClientInfoString() + "state " + this.state);
379             channel.close();
380         }
381     }
382
383     @Override
384     public String toString() {
385         return getClientInfoString();
386     }
387
388     @Override
389     public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
390         if (!isHandshakeComplete()) {
391             return;
392         }
393
394         if (e.getState() == IdleState.READER_IDLE) {
395             // When no message is received on channel for read timeout, then close
396             // the channel
397             log.info("Disconnecting client {} due to read timeout", getClientInfoString());
398             ctx.getChannel().close();
399         } else if (e.getState() == IdleState.WRITER_IDLE) {
400             // Send keep alive message
401             log.debug("Sending keep alive message due to IdleState timeout " + pc.toString());
402             pc.sendMessage(Collections.singletonList(pc.factory().buildKeepaliveMsg().build()));
403         }
404     }
405
406     @Override
407     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
408         if (e.getMessage() instanceof List) {
409             @SuppressWarnings("unchecked")
410             List<PcepMessage> msglist = (List<PcepMessage>) e.getMessage();
411             for (PcepMessage pm : msglist) {
412                 // Do the actual packet processing
413                 state.processPcepMessage(this, pm);
414             }
415         } else {
416             state.processPcepMessage(this, (PcepMessage) e.getMessage());
417         }
418     }
419
420     /**
421      * To set the handshake status.
422      *
423      * @param handshakeComplete value is handshake status
424      */
425     public void setHandshakeComplete(boolean handshakeComplete) {
426         this.state.setHandshakeComplete(handshakeComplete);
427     }
428
429     /**
430      * Is this a state in which the handshake has completed.
431      *
432      * @return true if the handshake is complete
433      */
434     public boolean isHandshakeComplete() {
435         return this.state.isHandshakeComplete();
436     }
437
438     /**
439      * To handle the pcep message.
440      *
441      * @param m pcep message
442      */
443     private void dispatchMessage(PcepMessage m) {
444         pc.handleMessage(m);
445     }
446
447     /**
448      * Return a string describing this client based on the already available
449      * information (ip address and/or remote socket).
450      *
451      * @return display string
452      */
453     private String getClientInfoString() {
454         if (pc != null) {
455             return pc.toString();
456         }
457         String channelString;
458         if (channel == null || channel.getRemoteAddress() == null) {
459             channelString = "?";
460         } else {
461             channelString = channel.getRemoteAddress().toString();
462         }
463         String pccIpString;
464         // TODO : implement functionality to get pcc id string
465         pccIpString = "?";
466         return String.format("[%s PCCIP[%s]]", channelString, pccIpString);
467     }
468
469     /**
470      * Update the channels state. Only called from the state machine.
471      *
472      * @param state
473      */
474     private void setState(ChannelState state) {
475         this.state = state;
476     }
477
478     /**
479      * Send handshake open message.
480      *
481      * @throws IOException,PcepParseException
482      */
483     private void sendHandshakeOpenMessage() throws IOException, PcepParseException {
484         PcepOpenObject pcepOpenobj = factory1.buildOpenObject()
485                 .setSessionId(sessionId)
486                 .setKeepAliveTime(keepAliveTime)
487                 .setDeadTime(deadTime)
488                 .build();
489         PcepMessage msg = factory1.buildOpenMsg()
490                 .setPcepOpenObj(pcepOpenobj)
491                 .build();
492         log.debug("Sending OPEN message to {}", channel.getRemoteAddress());
493         channel.write(Collections.singletonList(msg));
494     }
495
496     /**
497      * Capability Validation.
498      *
499      * @param pOpenmsg pcep open message
500      * @return success or failure
501      */
502     private boolean capabilityValidation(PcepOpenMsg pOpenmsg) {
503         LinkedList<PcepValueType> tlvList = pOpenmsg.getPcepOpenObject().getOptionalTlv();
504         boolean bFoundPceccCapability = false;
505         boolean bFoundStatefulPceCapability = false;
506         boolean bFoundPcInstantiationCapability = false;
507
508         ListIterator<PcepValueType> listIterator = tlvList.listIterator();
509         while (listIterator.hasNext()) {
510             PcepValueType tlv = listIterator.next();
511
512             switch (tlv.getType()) {
513             case PceccCapabilityTlv.TYPE:
514                 bFoundPceccCapability = true;
515                 break;
516             case StatefulPceCapabilityTlv.TYPE:
517                 bFoundStatefulPceCapability = true;
518                 StatefulPceCapabilityTlv stetefulPcCapTlv = (StatefulPceCapabilityTlv) tlv;
519                 if (stetefulPcCapTlv.getIFlag()) {
520                     bFoundPcInstantiationCapability = true;
521                 }
522                 break;
523             default:
524                 continue;
525             }
526         }
527
528         return (bFoundPceccCapability && bFoundStatefulPceCapability && bFoundPcInstantiationCapability);
529     }
530
531     /**
532      * Send keep alive message.
533      *
534      * @throws IOException when channel is disconnected
535      * @throws PcepParseException while building keep alive message
536      */
537     private void sendKeepAliveMessage() throws IOException, PcepParseException {
538         PcepMessage msg = factory1.buildKeepaliveMsg().build();
539         log.debug("Sending KEEPALIVE message to {}", channel.getRemoteAddress());
540         channel.write(Collections.singletonList(msg));
541     }
542
543     /**
544      * Send error message and close channel with pcc.
545      */
546     private void sendErrMsgAndCloseChannel() {
547         // TODO send error message
548         channel.close();
549     }
550
551     /**
552      * Send error message when an invalid message is received.
553      *
554      * @throws PcepParseException while building error message
555      */
556     private void sendErrMsgForInvalidMsg() throws PcepParseException {
557         byte errorType = 0x02;
558         byte errorValue = 0x00;
559         PcepErrorMsg errMsg = getErrorMsg(errorType, errorValue);
560         channel.write(Collections.singletonList(errMsg));
561     }
562
563     /**
564      * Builds pcep error message based on error value and error type.
565      *
566      * @param errorType  pcep error type
567      * @param errorValue pcep error value
568      * @return pcep error message
569      * @throws PcepParseException while bulding error message
570      */
571     public PcepErrorMsg getErrorMsg(byte errorType, byte errorValue) throws PcepParseException {
572         LinkedList<PcepErrorObject> llerrObj = new LinkedList<>();
573         PcepErrorMsg errMsg;
574
575         PcepErrorObject errObj = factory1.buildPcepErrorObject()
576                 .setErrorValue(errorValue)
577                 .setErrorType(errorType)
578                 .build();
579
580         llerrObj.add(errObj);
581
582         if (state == ChannelState.OPENWAIT) {
583             //If Error caught in Openmessage
584             PcepOpenObject openObj = null;
585             ErrorObjListWithOpen errorObjListWithOpen = null;
586
587             if (0 != sessionId) {
588                 openObj = factory1.buildOpenObject().setSessionId(sessionId).build();
589                 errorObjListWithOpen = new ErrorObjListWithOpen(llerrObj, openObj);
590             } else {
591                 errorObjListWithOpen = new ErrorObjListWithOpen(llerrObj, null);
592             }
593
594             errMsg = factory1.buildPcepErrorMsg()
595                     .setErrorObjListWithOpen(errorObjListWithOpen)
596                     .build();
597         } else {
598
599             //If Error caught in other than Openmessage
600             LinkedList<PcepError> llPcepErr = new LinkedList<>();
601
602             PcepError pcepErr = factory1.buildPcepError()
603                     .setErrorObjList(llerrObj)
604                     .build();
605
606             llPcepErr.add(pcepErr);
607
608             PcepErrorInfo errInfo = factory1.buildPcepErrorInfo()
609                     .setPcepErrorList(llPcepErr)
610                     .build();
611
612             errMsg = factory1.buildPcepErrorMsg()
613                     .setPcepErrorInfo(errInfo)
614                     .build();
615         }
616         return errMsg;
617     }
618
619     /**
620      * Process unknown pcep message received.
621      *
622      * @throws PcepParseException while building pcep error message
623      */
624     public void processUnknownMsg() throws PcepParseException {
625         Date now = null;
626         if (pcepPacketStats.wrongPacketCount() == 0) {
627             now = new Date();
628             pcepPacketStats.setTime(now.getTime());
629             pcepPacketStats.addWrongPacket();
630             sendErrMsgForInvalidMsg();
631         }
632
633         if (pcepPacketStats.wrongPacketCount() > 1) {
634             Date lastest = new Date();
635             pcepPacketStats.addWrongPacket();
636             //converting to seconds
637             if (((lastest.getTime() - pcepPacketStats.getTime()) / 1000) > 60) {
638                 now = lastest;
639                 pcepPacketStats.setTime(now.getTime());
640                 pcepPacketStats.resetWrongPacket();
641                 pcepPacketStats.addWrongPacket();
642             } else if (((int) (lastest.getTime() - now.getTime()) / 1000) < 60) {
643                 if (MAX_WRONG_COUNT_PACKET <= pcepPacketStats.wrongPacketCount()) {
644                     //reset once wrong packet count reaches MAX_WRONG_COUNT_PACKET
645                     pcepPacketStats.resetWrongPacket();
646                     // max wrong packets received send error message and close the session
647                     sendErrMsgAndCloseChannel();
648                 }
649             }
650         }
651     }
652 }