blob: e8c52cccc3cacc24821cc452ee3ae5eff4122e21 [file] [log] [blame]
SureshBR25058b72015-08-13 13:05:06 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
SureshBR25058b72015-08-13 13:05:06 +05303 *
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
17package org.onosproject.pcep.controller.impl;
18
19import java.io.IOException;
20import java.net.InetSocketAddress;
21import java.net.SocketAddress;
22import java.nio.channels.ClosedChannelException;
23import java.util.Collections;
24import java.util.Date;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.ListIterator;
28import java.util.concurrent.RejectedExecutionException;
29
30import org.jboss.netty.channel.Channel;
31import org.jboss.netty.channel.ChannelHandlerContext;
32import org.jboss.netty.channel.ChannelStateEvent;
33import org.jboss.netty.channel.ExceptionEvent;
34import org.jboss.netty.channel.MessageEvent;
35import org.jboss.netty.handler.timeout.IdleState;
36import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
37import org.jboss.netty.handler.timeout.IdleStateEvent;
38import org.jboss.netty.handler.timeout.IdleStateHandler;
39import org.jboss.netty.handler.timeout.ReadTimeoutException;
40import org.onlab.packet.IpAddress;
Priyanka Bd2b28882016-04-04 16:57:04 +053041import org.onosproject.pcep.controller.ClientCapability;
SureshBR25058b72015-08-13 13:05:06 +053042import org.onosproject.pcep.controller.PccId;
43import org.onosproject.pcep.controller.driver.PcepClientDriver;
44import org.onosproject.pcepio.exceptions.PcepParseException;
45import org.onosproject.pcepio.protocol.PcepError;
46import org.onosproject.pcepio.protocol.PcepErrorInfo;
47import org.onosproject.pcepio.protocol.PcepErrorMsg;
48import org.onosproject.pcepio.protocol.PcepErrorObject;
49import org.onosproject.pcepio.protocol.PcepFactory;
50import org.onosproject.pcepio.protocol.PcepMessage;
51import org.onosproject.pcepio.protocol.PcepOpenMsg;
52import org.onosproject.pcepio.protocol.PcepOpenObject;
53import org.onosproject.pcepio.protocol.PcepType;
54import org.onosproject.pcepio.protocol.PcepVersion;
Avantika-Huawei56c11842016-04-28 00:56:56 +053055import org.onosproject.pcepio.types.IPv4RouterIdOfLocalNodeSubTlv;
56import org.onosproject.pcepio.types.NodeAttributesTlv;
SureshBR25058b72015-08-13 13:05:06 +053057import org.onosproject.pcepio.types.PceccCapabilityTlv;
Priyanka B94395bf2016-05-21 18:39:46 +053058import org.onosproject.pcepio.types.SrPceCapabilityTlv;
SureshBR25058b72015-08-13 13:05:06 +053059import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
60import org.onosproject.pcepio.types.PcepErrorDetailInfo;
61import org.onosproject.pcepio.types.PcepValueType;
62import org.slf4j.Logger;
63import org.slf4j.LoggerFactory;
64
65/**
66 * Channel handler deals with the pcc client connection and dispatches
67 * messages from client to the appropriate locations.
68 */
69class PcepChannelHandler extends IdleStateAwareChannelHandler {
70 static final byte DEADTIMER_MAXIMUM_VALUE = (byte) 0xFF;
71 static final byte KEEPALIVE_MULTIPLE_FOR_DEADTIMER = 4;
72 private static final Logger log = LoggerFactory.getLogger(PcepChannelHandler.class);
73 private final Controller controller;
74 private PcepClientDriver pc;
75 private PccId thispccId;
76 private Channel channel;
77 private byte sessionId = 0;
78 private byte keepAliveTime;
79 private byte deadTime;
Priyanka Bd2b28882016-04-04 16:57:04 +053080 private ClientCapability capability;
SureshBR25058b72015-08-13 13:05:06 +053081 private PcepPacketStatsImpl pcepPacketStats;
82 static final int MAX_WRONG_COUNT_PACKET = 5;
83 static final int BYTE_MASK = 0xFF;
84
85 // State needs to be volatile because the HandshakeTimeoutHandler
86 // needs to check if the handshake is complete
87 private volatile ChannelState state;
88
89 // When a pcc client with a ip addresss is found (i.e we already have a
90 // connected client with the same ip), the new client is immediately
91 // disconnected. At that point netty callsback channelDisconnected() which
92 // proceeds to cleaup client state - we need to ensure that it does not cleanup
93 // client state for the older (still connected) client
94 private volatile Boolean duplicatePccIdFound;
95
96 //Indicates the pcep version used by this pcc client
97 protected PcepVersion pcepVersion;
98 protected PcepFactory factory1;
99
100 /**
101 * Create a new unconnected PcepChannelHandler.
102 * @param controller parent controller
103 */
104 PcepChannelHandler(Controller controller) {
105 this.controller = controller;
106 this.state = ChannelState.INIT;
107 factory1 = controller.getPcepMessageFactory1();
108 duplicatePccIdFound = Boolean.FALSE;
109 pcepPacketStats = new PcepPacketStatsImpl();
110 }
111
112 /**
113 * To disconnect a PCC.
114 */
115 public void disconnectClient() {
116 pc.disconnectClient();
117 }
118
119 //*************************
120 // Channel State Machine
121 //*************************
122
123 /**
124 * The state machine for handling the client/channel state. All state
125 * transitions should happen from within the state machine (and not from other
126 * parts of the code)
127 */
128 enum ChannelState {
129 /**
130 * Initial state before channel is connected.
131 */
132 INIT(false) {
133
134 },
135 /**
136 * Once the session is established, wait for open message.
137 */
138 OPENWAIT(false) {
139 @Override
140 void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
141
Avantika-Huawei56c11842016-04-28 00:56:56 +0530142 log.info("Message received in OPEN WAIT State");
SureshBR25058b72015-08-13 13:05:06 +0530143
144 //check for open message
145 if (m.getType() != PcepType.OPEN) {
146 // When the message type is not open message increment the wrong packet statistics
147 h.processUnknownMsg();
148 log.debug("message is not OPEN message");
149 } else {
150
151 h.pcepPacketStats.addInPacket();
152 PcepOpenMsg pOpenmsg = (PcepOpenMsg) m;
Priyanka Bd2b28882016-04-04 16:57:04 +0530153 //Do Capability negotiation.
154 h.capabilityNegotiation(pOpenmsg);
SureshBR25058b72015-08-13 13:05:06 +0530155 log.debug("Sending handshake OPEN message");
156 h.sessionId = pOpenmsg.getPcepOpenObject().getSessionId();
157 h.pcepVersion = pOpenmsg.getPcepOpenObject().getVersion();
158
159 //setting keepalive and deadTimer
160 byte yKeepalive = pOpenmsg.getPcepOpenObject().getKeepAliveTime();
161 byte yDeadTimer = pOpenmsg.getPcepOpenObject().getDeadTime();
162 h.keepAliveTime = yKeepalive;
163 if (yKeepalive < yDeadTimer) {
164 h.deadTime = yDeadTimer;
165 } else {
166 if (DEADTIMER_MAXIMUM_VALUE > (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER)) {
167 h.deadTime = (byte) (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER);
168 } else {
169 h.deadTime = DEADTIMER_MAXIMUM_VALUE;
170 }
171 }
Avantika-Huawei56c11842016-04-28 00:56:56 +0530172
Avantika-Huawei7f7376a2016-05-11 17:07:50 +0530173 /*
174 * If MPLS LSR id and PCEP session socket IP addresses are not same,
175 * the MPLS LSR id will be encoded in separate TLV.
176 * We always maintain session information based on LSR ids.
177 * The socket IP is stored in channel.
178 */
Avantika-Huawei56c11842016-04-28 00:56:56 +0530179 LinkedList<PcepValueType> optionalTlvs = pOpenmsg.getPcepOpenObject().getOptionalTlv();
180 for (PcepValueType optionalTlv : optionalTlvs) {
181 if (optionalTlv instanceof NodeAttributesTlv) {
182 List<PcepValueType> subTlvs = ((NodeAttributesTlv) optionalTlv)
183 .getllNodeAttributesSubTLVs();
184 for (PcepValueType subTlv : subTlvs) {
185 if (subTlv instanceof IPv4RouterIdOfLocalNodeSubTlv) {
186 h.thispccId = PccId.pccId(IpAddress
187 .valueOf(((IPv4RouterIdOfLocalNodeSubTlv) subTlv).getInt()));
188 break;
189 }
190 }
191 break;
192 }
193 }
194
195 if (h.thispccId == null) {
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
201 final InetSocketAddress inetAddress = (InetSocketAddress) address;
202 h.thispccId = PccId.pccId(IpAddress.valueOf(inetAddress.getAddress()));
203 }
204
SureshBR25058b72015-08-13 13:05:06 +0530205 h.sendHandshakeOpenMessage();
206 h.pcepPacketStats.addOutPacket();
207 h.setState(KEEPWAIT);
SureshBR25058b72015-08-13 13:05:06 +0530208 }
209 }
210 },
211 /**
212 * Once the open messages are exchanged, wait for keep alive message.
213 */
214 KEEPWAIT(false) {
215 @Override
216 void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
Avantika-Huawei56c11842016-04-28 00:56:56 +0530217 log.info("message received in KEEPWAIT state");
SureshBR25058b72015-08-13 13:05:06 +0530218 //check for keep alive message
219 if (m.getType() != PcepType.KEEP_ALIVE) {
220 // When the message type is not keep alive message increment the wrong packet statistics
221 h.processUnknownMsg();
Avantika-Huawei56c11842016-04-28 00:56:56 +0530222 log.error("message is not KEEPALIVE message");
SureshBR25058b72015-08-13 13:05:06 +0530223 } else {
224 // Set the client connected status
225 h.pcepPacketStats.addInPacket();
SureshBR25058b72015-08-13 13:05:06 +0530226 log.debug("sending keep alive message in KEEPWAIT state");
SureshBR25058b72015-08-13 13:05:06 +0530227 h.pc = h.controller.getPcepClientInstance(h.thispccId, h.sessionId, h.pcepVersion,
228 h.pcepPacketStats);
Priyanka Bd2b28882016-04-04 16:57:04 +0530229 //Get pc instance and set capabilities
230 h.pc.setCapability(h.capability);
SureshBR25058b72015-08-13 13:05:06 +0530231 // set the status of pcc as connected
232 h.pc.setConnected(true);
233 h.pc.setChannel(h.channel);
234
235 // set any other specific parameters to the pcc
236 h.pc.setPcVersion(h.pcepVersion);
237 h.pc.setPcSessionId(h.sessionId);
238 h.pc.setPcKeepAliveTime(h.keepAliveTime);
239 h.pc.setPcDeadTime(h.deadTime);
240 int keepAliveTimer = h.keepAliveTime & BYTE_MASK;
241 int deadTimer = h.deadTime & BYTE_MASK;
242 if (0 == h.keepAliveTime) {
243 h.deadTime = 0;
244 }
245 // handle keep alive and dead time
246 if (keepAliveTimer != PcepPipelineFactory.DEFAULT_KEEP_ALIVE_TIME
247 || deadTimer != PcepPipelineFactory.DEFAULT_DEAD_TIME) {
248
249 h.channel.getPipeline().replace("idle", "idle",
250 new IdleStateHandler(PcepPipelineFactory.TIMER, deadTimer, keepAliveTimer, 0));
251 }
252 log.debug("Dead timer : " + deadTimer);
253 log.debug("Keep alive time : " + keepAliveTimer);
254
255 //set the state handshake completion.
256 h.sendKeepAliveMessage();
257 h.pcepPacketStats.addOutPacket();
258 h.setHandshakeComplete(true);
259
260 if (!h.pc.connectClient()) {
261 disconnectDuplicate(h);
262 } else {
263 h.setState(ESTABLISHED);
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530264 //Session is established, add a network configuration with LSR id and device capabilities.
Priyanka B94395bf2016-05-21 18:39:46 +0530265 h.addNode();
SureshBR25058b72015-08-13 13:05:06 +0530266 }
267 }
268 }
269 },
270 /**
271 * Once the keep alive messages are exchanged, the state is established.
272 */
273 ESTABLISHED(true) {
274 @Override
275 void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
276
277 //h.channel.getPipeline().remove("waittimeout");
278 log.debug("Message received in established state " + m.getType());
279 //dispatch the message
280 h.dispatchMessage(m);
281 }
282 };
283 private boolean handshakeComplete;
284
285 ChannelState(boolean handshakeComplete) {
286 this.handshakeComplete = handshakeComplete;
287 }
288
289 void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
290 // do nothing
291 }
292
293 /**
294 * Is this a state in which the handshake has completed.
295 *
296 * @return true if the handshake is complete
297 */
298 public boolean isHandshakeComplete() {
299 return this.handshakeComplete;
300 }
301
302 protected void disconnectDuplicate(PcepChannelHandler h) {
303 log.error("Duplicated Pcc IP or incompleted cleanup - " + "disconnecting channel {}",
304 h.getClientInfoString());
305 h.duplicatePccIdFound = Boolean.TRUE;
306 h.channel.disconnect();
307 }
308
309 /**
310 * Sets handshake complete status.
311 *
312 * @param handshakeComplete status of handshake
313 */
314 public void setHandshakeComplete(boolean handshakeComplete) {
315 this.handshakeComplete = handshakeComplete;
316 }
317
318 }
319
320 @Override
321 public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
322 channel = e.getChannel();
323 log.info("PCC connected from {}", channel.getRemoteAddress());
324
325 // Wait for open message from pcc client
326 setState(ChannelState.OPENWAIT);
327 }
328
329 @Override
330 public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
331 log.info("Pcc disconnected callback for pc:{}. Cleaning up ...", getClientInfoString());
332 if (thispccId != null) {
333 if (!duplicatePccIdFound) {
334 // if the disconnected client (on this ChannelHandler)
335 // was not one with a duplicate-dpid, it is safe to remove all
336 // state for it at the controller. Notice that if the disconnected
337 // client was a duplicate-ip, calling the method below would clear
338 // all state for the original client (with the same ip),
339 // which we obviously don't want.
340 log.debug("{}:removal called", getClientInfoString());
341 if (pc != null) {
342 pc.removeConnectedClient();
343 }
344 } else {
345 // A duplicate was disconnected on this ChannelHandler,
346 // this is the same client reconnecting, but the original state was
347 // not cleaned up - XXX check liveness of original ChannelHandler
348 log.debug("{}:duplicate found", getClientInfoString());
349 duplicatePccIdFound = Boolean.FALSE;
350 }
351 } else {
352 log.warn("no pccip in channelHandler registered for " + "disconnected client {}", getClientInfoString());
353 }
354 }
355
356 @Override
357 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
358 PcepErrorMsg errMsg;
359 log.info("exceptionCaught: " + e.toString());
360
361 if (e.getCause() instanceof ReadTimeoutException) {
362 if (ChannelState.OPENWAIT == state) {
363 // When ReadTimeout timer is expired in OPENWAIT state, it is considered
364 // OpenWait timer.
365 errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_2);
366 log.debug("Sending PCEP-ERROR message to PCC.");
367 channel.write(Collections.singletonList(errMsg));
368 channel.close();
369 state = ChannelState.INIT;
370 return;
371 } else if (ChannelState.KEEPWAIT == state) {
372 // When ReadTimeout timer is expired in KEEPWAIT state, is is considered
373 // KeepWait timer.
374 errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_7);
375 log.debug("Sending PCEP-ERROR message to PCC.");
376 channel.write(Collections.singletonList(errMsg));
377 channel.close();
378 state = ChannelState.INIT;
379 return;
380 }
381 } else if (e.getCause() instanceof ClosedChannelException) {
382 log.debug("Channel for pc {} already closed", getClientInfoString());
383 } else if (e.getCause() instanceof IOException) {
384 log.error("Disconnecting client {} due to IO Error: {}", getClientInfoString(), e.getCause().getMessage());
385 if (log.isDebugEnabled()) {
386 // still print stack trace if debug is enabled
387 log.debug("StackTrace for previous Exception: ", e.getCause());
388 }
389 channel.close();
390 } else if (e.getCause() instanceof PcepParseException) {
391 PcepParseException errMsgParse = (PcepParseException) e.getCause();
392 byte errorType = errMsgParse.getErrorType();
393 byte errorValue = errMsgParse.getErrorValue();
394
395 if ((errorType == (byte) 0x0) && (errorValue == (byte) 0x0)) {
396 processUnknownMsg();
397 } else {
398 errMsg = getErrorMsg(errorType, errorValue);
399 log.debug("Sending PCEP-ERROR message to PCC.");
400 channel.write(Collections.singletonList(errMsg));
401 }
402 } else if (e.getCause() instanceof RejectedExecutionException) {
403 log.warn("Could not process message: queue full");
404 } else {
405 log.error("Error while processing message from client " + getClientInfoString() + "state " + this.state);
406 channel.close();
407 }
408 }
409
410 @Override
411 public String toString() {
412 return getClientInfoString();
413 }
414
415 @Override
416 public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
417 if (!isHandshakeComplete()) {
418 return;
419 }
420
421 if (e.getState() == IdleState.READER_IDLE) {
422 // When no message is received on channel for read timeout, then close
423 // the channel
424 log.info("Disconnecting client {} due to read timeout", getClientInfoString());
425 ctx.getChannel().close();
426 } else if (e.getState() == IdleState.WRITER_IDLE) {
427 // Send keep alive message
428 log.debug("Sending keep alive message due to IdleState timeout " + pc.toString());
429 pc.sendMessage(Collections.singletonList(pc.factory().buildKeepaliveMsg().build()));
430 }
431 }
432
433 @Override
434 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
435 if (e.getMessage() instanceof List) {
436 @SuppressWarnings("unchecked")
437 List<PcepMessage> msglist = (List<PcepMessage>) e.getMessage();
438 for (PcepMessage pm : msglist) {
439 // Do the actual packet processing
440 state.processPcepMessage(this, pm);
441 }
442 } else {
443 state.processPcepMessage(this, (PcepMessage) e.getMessage());
444 }
445 }
446
447 /**
448 * To set the handshake status.
449 *
450 * @param handshakeComplete value is handshake status
451 */
452 public void setHandshakeComplete(boolean handshakeComplete) {
453 this.state.setHandshakeComplete(handshakeComplete);
454 }
455
456 /**
457 * Is this a state in which the handshake has completed.
458 *
459 * @return true if the handshake is complete
460 */
461 public boolean isHandshakeComplete() {
462 return this.state.isHandshakeComplete();
463 }
464
465 /**
466 * To handle the pcep message.
467 *
468 * @param m pcep message
469 */
470 private void dispatchMessage(PcepMessage m) {
471 pc.handleMessage(m);
472 }
473
474 /**
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530475 * Adds PCEP device configuration with capabilities once session is established.
Priyanka B94395bf2016-05-21 18:39:46 +0530476 */
477 private void addNode() {
478 pc.addNode(pc);
479 }
480
481 /**
Avantika-Huaweife44ea62016-05-27 19:21:24 +0530482 * Deletes PCEP device configuration when session is disconnected.
Priyanka B94395bf2016-05-21 18:39:46 +0530483 */
484 private void deleteNode() {
485 pc.deleteNode(pc.getPccId());
486 }
487
488 /**
SureshBR25058b72015-08-13 13:05:06 +0530489 * Return a string describing this client based on the already available
490 * information (ip address and/or remote socket).
491 *
492 * @return display string
493 */
494 private String getClientInfoString() {
495 if (pc != null) {
496 return pc.toString();
497 }
498 String channelString;
499 if (channel == null || channel.getRemoteAddress() == null) {
500 channelString = "?";
501 } else {
502 channelString = channel.getRemoteAddress().toString();
503 }
504 String pccIpString;
505 // TODO : implement functionality to get pcc id string
506 pccIpString = "?";
507 return String.format("[%s PCCIP[%s]]", channelString, pccIpString);
508 }
509
510 /**
511 * Update the channels state. Only called from the state machine.
512 *
513 * @param state
514 */
515 private void setState(ChannelState state) {
516 this.state = state;
517 }
518
519 /**
520 * Send handshake open message.
521 *
522 * @throws IOException,PcepParseException
523 */
524 private void sendHandshakeOpenMessage() throws IOException, PcepParseException {
525 PcepOpenObject pcepOpenobj = factory1.buildOpenObject()
526 .setSessionId(sessionId)
527 .setKeepAliveTime(keepAliveTime)
528 .setDeadTime(deadTime)
529 .build();
530 PcepMessage msg = factory1.buildOpenMsg()
531 .setPcepOpenObj(pcepOpenobj)
532 .build();
533 log.debug("Sending OPEN message to {}", channel.getRemoteAddress());
534 channel.write(Collections.singletonList(msg));
535 }
536
Priyanka Bd2b28882016-04-04 16:57:04 +0530537 //Capability negotiation
538 private void capabilityNegotiation(PcepOpenMsg pOpenmsg) {
SureshBR25058b72015-08-13 13:05:06 +0530539 LinkedList<PcepValueType> tlvList = pOpenmsg.getPcepOpenObject().getOptionalTlv();
Priyanka Bd2b28882016-04-04 16:57:04 +0530540 boolean pceccCapability = false;
541 boolean statefulPceCapability = false;
542 boolean pcInstantiationCapability = false;
Priyanka B94395bf2016-05-21 18:39:46 +0530543 boolean labelStackCapability = false;
544 boolean srCapability = false;
SureshBR25058b72015-08-13 13:05:06 +0530545
546 ListIterator<PcepValueType> listIterator = tlvList.listIterator();
547 while (listIterator.hasNext()) {
548 PcepValueType tlv = listIterator.next();
549
550 switch (tlv.getType()) {
551 case PceccCapabilityTlv.TYPE:
Priyanka Bd2b28882016-04-04 16:57:04 +0530552 pceccCapability = true;
Priyanka B94395bf2016-05-21 18:39:46 +0530553 if (((PceccCapabilityTlv) tlv).sBit()) {
554 labelStackCapability = true;
555 }
SureshBR25058b72015-08-13 13:05:06 +0530556 break;
557 case StatefulPceCapabilityTlv.TYPE:
Priyanka Bd2b28882016-04-04 16:57:04 +0530558 statefulPceCapability = true;
SureshBR25058b72015-08-13 13:05:06 +0530559 StatefulPceCapabilityTlv stetefulPcCapTlv = (StatefulPceCapabilityTlv) tlv;
560 if (stetefulPcCapTlv.getIFlag()) {
Priyanka Bd2b28882016-04-04 16:57:04 +0530561 pcInstantiationCapability = true;
SureshBR25058b72015-08-13 13:05:06 +0530562 }
563 break;
Priyanka B94395bf2016-05-21 18:39:46 +0530564 case SrPceCapabilityTlv.TYPE:
565 srCapability = true;
566 break;
SureshBR25058b72015-08-13 13:05:06 +0530567 default:
568 continue;
569 }
570 }
Priyanka B94395bf2016-05-21 18:39:46 +0530571 this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability,
572 labelStackCapability, srCapability);
SureshBR25058b72015-08-13 13:05:06 +0530573 }
574
575 /**
576 * Send keep alive message.
577 *
578 * @throws IOException when channel is disconnected
579 * @throws PcepParseException while building keep alive message
580 */
581 private void sendKeepAliveMessage() throws IOException, PcepParseException {
582 PcepMessage msg = factory1.buildKeepaliveMsg().build();
583 log.debug("Sending KEEPALIVE message to {}", channel.getRemoteAddress());
584 channel.write(Collections.singletonList(msg));
585 }
586
587 /**
588 * Send error message and close channel with pcc.
589 */
590 private void sendErrMsgAndCloseChannel() {
591 // TODO send error message
Priyanka B94395bf2016-05-21 18:39:46 +0530592 //Remove PCEP device from topology
593 deleteNode();
SureshBR25058b72015-08-13 13:05:06 +0530594 channel.close();
595 }
596
597 /**
598 * Send error message when an invalid message is received.
599 *
600 * @throws PcepParseException while building error message
601 */
602 private void sendErrMsgForInvalidMsg() throws PcepParseException {
603 byte errorType = 0x02;
604 byte errorValue = 0x00;
605 PcepErrorMsg errMsg = getErrorMsg(errorType, errorValue);
606 channel.write(Collections.singletonList(errMsg));
607 }
608
609 /**
610 * Builds pcep error message based on error value and error type.
611 *
612 * @param errorType pcep error type
613 * @param errorValue pcep error value
614 * @return pcep error message
615 * @throws PcepParseException while bulding error message
616 */
617 public PcepErrorMsg getErrorMsg(byte errorType, byte errorValue) throws PcepParseException {
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700618 LinkedList<PcepErrorObject> llerrObj = new LinkedList<>();
SureshBR25058b72015-08-13 13:05:06 +0530619 PcepErrorMsg errMsg;
620
621 PcepErrorObject errObj = factory1.buildPcepErrorObject()
622 .setErrorValue(errorValue)
623 .setErrorType(errorType)
624 .build();
625
626 llerrObj.add(errObj);
627
SureshBR25058b72015-08-13 13:05:06 +0530628 //If Error caught in other than Openmessage
Sho SHIMIZU9b8274c2015-09-04 15:54:24 -0700629 LinkedList<PcepError> llPcepErr = new LinkedList<>();
SureshBR25058b72015-08-13 13:05:06 +0530630
631 PcepError pcepErr = factory1.buildPcepError()
632 .setErrorObjList(llerrObj)
633 .build();
634
635 llPcepErr.add(pcepErr);
636
637 PcepErrorInfo errInfo = factory1.buildPcepErrorInfo()
638 .setPcepErrorList(llPcepErr)
639 .build();
640
641 errMsg = factory1.buildPcepErrorMsg()
642 .setPcepErrorInfo(errInfo)
643 .build();
SureshBR25058b72015-08-13 13:05:06 +0530644 return errMsg;
645 }
646
647 /**
648 * Process unknown pcep message received.
649 *
650 * @throws PcepParseException while building pcep error message
651 */
652 public void processUnknownMsg() throws PcepParseException {
653 Date now = null;
654 if (pcepPacketStats.wrongPacketCount() == 0) {
655 now = new Date();
656 pcepPacketStats.setTime(now.getTime());
657 pcepPacketStats.addWrongPacket();
658 sendErrMsgForInvalidMsg();
659 }
660
661 if (pcepPacketStats.wrongPacketCount() > 1) {
662 Date lastest = new Date();
663 pcepPacketStats.addWrongPacket();
664 //converting to seconds
665 if (((lastest.getTime() - pcepPacketStats.getTime()) / 1000) > 60) {
666 now = lastest;
667 pcepPacketStats.setTime(now.getTime());
668 pcepPacketStats.resetWrongPacket();
669 pcepPacketStats.addWrongPacket();
670 } else if (((int) (lastest.getTime() - now.getTime()) / 1000) < 60) {
671 if (MAX_WRONG_COUNT_PACKET <= pcepPacketStats.wrongPacketCount()) {
672 //reset once wrong packet count reaches MAX_WRONG_COUNT_PACKET
673 pcepPacketStats.resetWrongPacket();
674 // max wrong packets received send error message and close the session
675 sendErrMsgAndCloseChannel();
676 }
677 }
678 }
679 }
680}