blob: 134a48b9bc4bb4b4204cdcc9cb690ebbec3ea571 [file] [log] [blame]
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301/*
2 * Copyright 2016-present 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 */
16package org.onosproject.isis.controller.impl;
17
18import org.jboss.netty.channel.Channel;
19import org.onlab.packet.Ip4Address;
20import org.onlab.packet.MacAddress;
21import org.onosproject.isis.controller.IsisInterface;
22import org.onosproject.isis.controller.IsisInterfaceState;
23import org.onosproject.isis.controller.IsisLsdb;
24import org.onosproject.isis.controller.IsisMessage;
25import org.onosproject.isis.controller.IsisNeighbor;
26import org.onosproject.isis.controller.IsisNetworkType;
27import org.onosproject.isis.controller.IsisPduType;
28import org.onosproject.isis.controller.IsisRouterType;
29import org.onosproject.isis.controller.LspWrapper;
30import org.onosproject.isis.io.isispacket.IsisHeader;
31import org.onosproject.isis.io.isispacket.pdu.Csnp;
32import org.onosproject.isis.io.isispacket.pdu.HelloPdu;
33import org.onosproject.isis.io.isispacket.pdu.L1L2HelloPdu;
34import org.onosproject.isis.io.isispacket.pdu.LsPdu;
35import org.onosproject.isis.io.isispacket.pdu.P2PHelloPdu;
36import org.onosproject.isis.io.isispacket.pdu.Psnp;
37import org.onosproject.isis.io.isispacket.tlv.AdjacencyStateTlv;
38import org.onosproject.isis.io.isispacket.tlv.IsisTlv;
39import org.onosproject.isis.io.isispacket.tlv.LspEntriesTlv;
40import org.onosproject.isis.io.isispacket.tlv.LspEntry;
41import org.onosproject.isis.io.isispacket.tlv.TlvHeader;
42import org.onosproject.isis.io.isispacket.tlv.TlvType;
43import org.onosproject.isis.io.util.IsisConstants;
44import org.onosproject.isis.io.util.IsisUtil;
45import org.onosproject.isis.io.util.LspGenerator;
46import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
49import java.util.ArrayList;
50import java.util.Iterator;
51import java.util.List;
52import java.util.Map;
53import java.util.Set;
54import java.util.concurrent.ConcurrentHashMap;
55import java.util.concurrent.Executors;
56import java.util.concurrent.ScheduledExecutorService;
57import java.util.concurrent.ScheduledFuture;
58import java.util.concurrent.TimeUnit;
59
60/**
61 * Representation of an ISIS interface.
62 */
63public class DefaultIsisInterface implements IsisInterface {
64 private static final Logger log = LoggerFactory.getLogger(DefaultIsisInterface.class);
65 boolean flagValue = false;
66 private int interfaceIndex;
67 private Ip4Address interfaceIpAddress;
68 private byte[] networkMask;
69 private MacAddress interfaceMacAddress;
70 private String intermediateSystemName;
71 private String systemId;
sunish vk4b5ce002016-05-09 20:18:35 +053072 private String l1LanId = IsisConstants.DEFAULTLANID;
73 private String l2LanId = IsisConstants.DEFAULTLANID;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +053074 private int idLength;
75 private int maxAreaAddresses;
76 private int reservedPacketCircuitType;
77 private IsisNetworkType networkType;
78 private String areaAddress;
79 private int areaLength;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +053080 private int holdingTime;
81 private int priority;
82 private String circuitId;
83 private int helloInterval;
84 private Map<MacAddress, IsisNeighbor> neighborList = new ConcurrentHashMap<>();
85 private IsisHelloPduSender isisHelloPduSender = null;
86 private ScheduledExecutorService exServiceHello = null;
87 private IsisInterfaceState interfaceState = IsisInterfaceState.DOWN;
88 private IsisLsdb isisLsdb = null;
89 private List<Ip4Address> allConfiguredInterfaceIps = null;
90 private Channel channel;
91
92 /**
93 * Returns ISIS LSDB instance.
94 *
95 * @return ISIS LSDB instance
96 */
97 public IsisLsdb isisLsdb() {
98 return isisLsdb;
99 }
100
101 /**
102 * Sets all configured interface IPs.
103 *
104 * @param allConfiguredInterfaces all configured interface IPs
105 */
106 public void setAllConfiguredInterfaceIps(List<Ip4Address> allConfiguredInterfaces) {
107 allConfiguredInterfaceIps = allConfiguredInterfaces;
108 }
109
110 /**
111 * Removes neighbor from the interface neighbor map.
112 *
113 * @param isisNeighbor ISIS neighbor instance
114 */
115 public void removeNeighbor(IsisNeighbor isisNeighbor) {
sunish vk4b5ce002016-05-09 20:18:35 +0530116 log.debug("Neighbor removed - {}", isisNeighbor.neighborMacAddress());
117 isisNeighbor.stopHoldingTimeCheck();
118 isisNeighbor.stopInactivityTimeCheck();
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530119 neighborList.remove(isisNeighbor.neighborMacAddress());
120 }
121
122 /**
sunish vk4b5ce002016-05-09 20:18:35 +0530123 * Removes all the neighbors.
124 */
125 public void removeNeighbors() {
126 Set<MacAddress> neighbors = neighbors();
127 for (MacAddress mac : neighbors) {
128 removeNeighbor(lookup(mac));
129 log.debug("Neighbor removed - {}", mac);
130 }
131 neighborList.clear();
132 }
133
134 /**
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530135 * Returns the ISIS neighbor instance if exists.
136 *
137 * @param isisNeighborMac mac address of the neighbor router
138 * @return ISIS neighbor instance if exists else null
139 */
140 public IsisNeighbor lookup(MacAddress isisNeighborMac) {
141 return neighborList.get(isisNeighborMac);
142 }
143
144 /**
145 * Returns the neighbors list.
146 *
147 * @return neighbors list
148 */
149 public Set<MacAddress> neighbors() {
150 return neighborList.keySet();
151 }
152
153 /**
154 * Returns channel instance.
155 *
156 * @return channel instance
157 */
158 public Channel channel() {
159 return channel;
160 }
161
162 /**
163 * Returns interface index.
164 *
165 * @return interface index
166 */
167 public int interfaceIndex() {
168 return interfaceIndex;
169 }
170
171 /**
172 * Set interface index.
173 *
174 * @param interfaceIndex interface index
175 */
176 public void setInterfaceIndex(int interfaceIndex) {
177 this.interfaceIndex = interfaceIndex;
178 }
179
180 /**
181 * Returns the interface IP address.
182 *
183 * @return interface IP address
184 */
185 public Ip4Address interfaceIpAddress() {
186 return interfaceIpAddress;
187 }
188
189 /**
190 * Sets the interface IP address.
191 *
192 * @param interfaceIpAddress interfaceIpAddress interface IP address
193 */
194 public void setInterfaceIpAddress(Ip4Address interfaceIpAddress) {
195 this.interfaceIpAddress = interfaceIpAddress;
196 }
197
198 /**
199 * Returns the network mask.
200 *
201 * @return network mask
202 */
203 public byte[] networkMask() {
204 return networkMask;
205 }
206
207 /**
208 * Sets the network mask.
209 *
210 * @param networkMask network mask
211 */
212 public void setNetworkMask(byte[] networkMask) {
213 this.networkMask = networkMask;
214 }
215
216 /**
217 * Returns the interface mac address.
218 *
219 * @return interface mac address
220 */
221 public MacAddress getInterfaceMacAddress() {
222 return interfaceMacAddress;
223 }
224
225 /**
226 * Sets the interface mac address.
227 *
228 * @param interfaceMacAddress interface mac address
229 */
230 public void setInterfaceMacAddress(MacAddress interfaceMacAddress) {
231 this.interfaceMacAddress = interfaceMacAddress;
232 }
233
234 /**
235 * Returns intermediate system name.
236 *
237 * @return intermediate system name
238 */
239 public String intermediateSystemName() {
240 return intermediateSystemName;
241 }
242
243 /**
244 * Sets intermediate system name.
245 *
246 * @param intermediateSystemName intermediate system name
247 */
248 public void setIntermediateSystemName(String intermediateSystemName) {
249 this.intermediateSystemName = intermediateSystemName;
250 }
251
252 /**
253 * Returns system ID.
254 *
255 * @return system ID
256 */
257 public String systemId() {
258 return systemId;
259 }
260
261 /**
262 * Sets system ID.
263 *
264 * @param systemId system ID
265 */
266 public void setSystemId(String systemId) {
267 this.systemId = systemId;
268 }
269
270 /**
271 * Returns LAN ID.
272 *
273 * @return LAN ID
274 */
275 public String l1LanId() {
276 return l1LanId;
277 }
278
279 /**
280 * Sets LAN ID.
281 *
282 * @param l1LanId LAN ID
283 */
284 public void setL1LanId(String l1LanId) {
285 this.l1LanId = l1LanId;
286 }
287
288 /**
289 * Returns LAN ID.
290 *
291 * @return LAN ID
292 */
293 public String l2LanId() {
294 return l2LanId;
295 }
296
297 /**
298 * Sets LAN ID.
299 *
300 * @param l2LanId LAN ID
301 */
302 public void setL2LanId(String l2LanId) {
303 this.l2LanId = l2LanId;
304 }
305
306 /**
307 * Returns ID length.
308 *
309 * @return ID length
310 */
311 public int getIdLength() {
312
313 return ((idLength == 0) ? 6 : idLength);
314 }
315
316 /**
317 * Sets ID length.
318 *
319 * @param idLength ID length
320 */
321 public void setIdLength(int idLength) {
322 this.idLength = idLength;
323 }
324
325 /**
326 * Returns max area addresses.
327 *
328 * @return max area addresses
329 */
330 public int getMaxAreaAddresses() {
331
332 return maxAreaAddresses;
333 }
334
335 /**
336 * Sets area max addresses.
337 *
338 * @param maxAreaAddresses max area addresses
339 */
340 public void setMaxAreaAddresses(int maxAreaAddresses) {
341 this.maxAreaAddresses = maxAreaAddresses;
342 }
343
344 /**
345 * Returns reserved packet circuit type.
346 *
347 * @return reserved packet circuit type
348 */
349 public int reservedPacketCircuitType() {
350 return reservedPacketCircuitType;
351 }
352
353 /**
354 * Sets reserved packet circuit type.
355 *
356 * @param reservedPacketCircuitType reserved packet circuit type
357 */
358 public void setReservedPacketCircuitType(int reservedPacketCircuitType) {
359 this.reservedPacketCircuitType = reservedPacketCircuitType;
360 }
361
362 /**
363 * Returns point to point.
364 *
365 * @return point to point
366 */
367 public IsisNetworkType networkType() {
368 return networkType;
369 }
370
371 /**
372 * Sets point to point or broadcast.
373 *
374 * @param networkType point to point or broadcast
375 */
376 public void setNetworkType(IsisNetworkType networkType) {
377 this.networkType = networkType;
378 }
379
380 /**
381 * Returns area address.
382 *
383 * @return area address
384 */
385 public String areaAddress() {
386 return areaAddress;
387 }
388
389 /**
390 * Sets area address.
391 *
392 * @param areaAddress area address
393 */
394 public void setAreaAddress(String areaAddress) {
395 this.areaAddress = areaAddress;
396 }
397
398 /**
399 * Returns area length.
400 *
401 * @return area length
402 */
403 public int getAreaLength() {
404 return areaLength;
405 }
406
407 /**
408 * Sets area length.
409 *
410 * @param areaLength area length
411 */
412 public void setAreaLength(int areaLength) {
413 this.areaLength = areaLength;
414 }
415
416 /**
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530417 * Returns holding time.
418 *
419 * @return holding time
420 */
421 public int holdingTime() {
422 return holdingTime;
423 }
424
425 /**
426 * Sets holding time.
427 *
428 * @param holdingTime holding time
429 */
430 public void setHoldingTime(int holdingTime) {
431 this.holdingTime = holdingTime;
432 }
433
434 /**
435 * Returns priority.
436 *
437 * @return priority
438 */
439 public int priority() {
440 return priority;
441 }
442
443 /**
444 * Sets priority.
445 *
446 * @param priority priority
447 */
448 public void setPriority(int priority) {
449 this.priority = priority;
450 }
451
452 /**
453 * Returns hello interval.
454 *
455 * @return hello interval
456 */
457 public int helloInterval() {
458 return helloInterval;
459 }
460
461 /**
462 * Sets hello interval.
463 *
464 * @param helloInterval hello interval
465 */
466 public void setHelloInterval(int helloInterval) {
467 this.helloInterval = helloInterval;
468 }
469
470 /**
471 * Returns the interface state.
472 *
473 * @return interface state
474 */
475 public IsisInterfaceState interfaceState() {
476 return interfaceState;
477 }
478
479 /**
480 * Sets the interface state.
481 *
482 * @param interfaceState the interface state
483 */
484 public void setInterfaceState(IsisInterfaceState interfaceState) {
485 this.interfaceState = interfaceState;
486 }
487
488 /**
489 * Returns the circuit ID.
490 *
491 * @return circuit ID
492 */
493 public String circuitId() {
494 return circuitId;
495 }
496
497 /**
498 * Sets the circuit ID.
499 *
500 * @param circuitId circuit ID
501 */
502 public void setCircuitId(String circuitId) {
503 this.circuitId = circuitId;
504 }
505
506 /**
507 * Processes received ISIS message.
508 * When an ISIS message received it is handed over to this method.
509 * Based on the type of the ISIS message received it will be handed over
510 * to corresponding message handler methods.
511 *
512 * @param isisMessage received ISIS message
513 * @param isisLsdb ISIS LSDB instance
514 */
515 public void processIsisMessage(IsisMessage isisMessage, IsisLsdb isisLsdb, Channel channel) {
516 log.debug("IsisInterfaceImpl::processIsisMessage...!!!");
sunish vk4b5ce002016-05-09 20:18:35 +0530517 this.channel = channel;
518
519 if (isisMessage.sourceMac().equals(interfaceMacAddress)) {
520 log.debug("Received our own message {}...!!!", isisMessage.isisPduType());
521 return;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530522 }
sunish vk4b5ce002016-05-09 20:18:35 +0530523
524 if (isisMessage.isisPduType() == IsisPduType.P2PHELLOPDU && networkType.equals(IsisNetworkType.BROADCAST)) {
525 return;
526 } else if ((isisMessage.isisPduType() == IsisPduType.L1HELLOPDU ||
527 isisMessage.isisPduType() == IsisPduType.L2HELLOPDU)
528 && networkType.equals(IsisNetworkType.P2P)) {
529 return;
530 }
531
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530532 if (this.isisLsdb == null) {
533 this.isisLsdb = isisLsdb;
534 }
535
536 switch (isisMessage.isisPduType()) {
537 case L1HELLOPDU:
538 case L2HELLOPDU:
539 processL1L2HelloPduMessage(isisMessage, channel);
540 break;
541 case P2PHELLOPDU:
542 processP2pHelloPduMessage(isisMessage, channel);
543 break;
544 case L1LSPDU:
545 case L2LSPDU:
546 processLsPduMessage(isisMessage, channel);
547 break;
548 case L1CSNP:
549 case L2CSNP:
550 processCsnPduMessage(isisMessage, channel);
551 break;
552 case L1PSNP:
553 case L2PSNP:
sunish vk4b5ce002016-05-09 20:18:35 +0530554 processPsnPduMessage(isisMessage, channel);
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530555 break;
556 default:
557 log.debug("Unknown packet to process...!!!");
558 break;
559 }
560 }
561
562 /**
563 * Validates the received message.
564 *
565 * @param helloPdu ISIS message instance
566 * @return true if valid ISIS message else false
567 */
568 public boolean validateHelloMessage(HelloPdu helloPdu) {
569 boolean isValid = false;
570
sunish vk4b5ce002016-05-09 20:18:35 +0530571 if ((helloPdu.circuitType() == IsisRouterType.L1.value() &&
572 reservedPacketCircuitType == IsisRouterType.L2.value()) ||
573 (helloPdu.circuitType() == IsisRouterType.L2.value() &&
574 reservedPacketCircuitType == IsisRouterType.L1.value())) {
575 return false;
576 }
577
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530578 //Local InterfaceAddress TLV and compare with the IP Interface address and check if they are in same subnet
579 List<Ip4Address> interfaceIpAddresses = helloPdu.interfaceIpAddresses();
580 Ip4Address neighborIp = (helloPdu.interfaceIpAddresses() != null) ?
581 interfaceIpAddresses.get(0) : Ip4Address.valueOf("0.0.0.0");
582 if (!IsisUtil.sameNetwork(interfaceIpAddress, neighborIp, networkMask)) {
583 return false;
584 }
585
586 //Verify if it's in same area, Areas which the router belongs to
sunish vk4b5ce002016-05-09 20:18:35 +0530587 if (helloPdu.circuitType() == IsisRouterType.L1.value()) {
588 List<String> areas = helloPdu.areaAddress();
589 for (String area : areas) {
590 if (areaAddress.equals(area)) {
591 isValid = true;
592 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530593 }
sunish vk4b5ce002016-05-09 20:18:35 +0530594 } else if (helloPdu.circuitType() == IsisRouterType.L2.value() ||
595 helloPdu.circuitType() == IsisRouterType.L1L2.value()) {
596 isValid = true;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530597 }
598
599 return isValid;
600 }
601
602 /**
603 * Checks neighbor presents in the list or not.
604 *
605 * @param neighborMac neighbor MAc address
606 * @return true if neighbor exist else false
607 */
sunish vk4b5ce002016-05-09 20:18:35 +0530608
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530609 private boolean isNeighborInList(MacAddress neighborMac) {
610 return neighborList.containsKey(neighborMac);
611 }
612
613 /**
614 * Adds neighbor in the list.
615 *
616 * @param neighbor neighbor MAC address
617 * @return true if neighbor exist else false
618 */
619 private void addNeighbouringRouter(IsisNeighbor neighbor) {
620 neighborList.put(neighbor.neighborMacAddress(), neighbor);
621 }
622
623 /**
624 * Returns neighbor presents in the list.
625 *
626 * @param neighborMac neighbor MAc address
627 * @return neighbor instance
628 */
629 private IsisNeighbor neighbouringRouter(MacAddress neighborMac) {
630 return neighborList.get(neighborMac);
631 }
632
633 /**
634 * Processes the L1 or L2 hello message.
635 *
636 * @param isisMessage hello message instance
637 * @param channel channel instance
638 */
639 public void processL1L2HelloPduMessage(IsisMessage isisMessage, Channel channel) {
640 log.debug("Enters processL1L2HelloPduMessage ...!!!");
641 log.debug("IsisInterfaceImpl::processHelloMessage...!!!");
642
643 L1L2HelloPdu helloPacket = (L1L2HelloPdu) isisMessage;
644 log.debug("IsisInterfaceImpl::processHelloMessage::Interface Type {} ISISInterfaceState {} ",
645 networkType, interfaceState);
646
sunish vk4b5ce002016-05-09 20:18:35 +0530647 //If validate the area, network and max address
648 if (!validateHelloMessage(helloPacket)) {
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530649 return;
650 }
651
652 //Get the neighbor
653 IsisNeighbor neighbor = neighbouringRouter(isisMessage.sourceMac());
654 //Neighbor is not in list
655 if (!isNeighborInList(isisMessage.sourceMac())) {
656 neighbor = new DefaultIsisNeighbor(helloPacket, this);
657 addNeighbouringRouter(neighbor);
658 }
659
sunish vk4b5ce002016-05-09 20:18:35 +0530660 neighbor.setHoldingTime(helloPacket.holdingTime());
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530661 neighbor.stopInactivityTimeCheck();
662 neighbor.startInactivityTimeCheck();
663
664 //Assign the DIS
665 String lanId = helloPacket.lanId();
666
667 if (IsisPduType.L1HELLOPDU == helloPacket.isisPduType()) {
sunish vk4b5ce002016-05-09 20:18:35 +0530668 buildUpdateAndSendSelfGeneratedLspIfDisChange(l1LanId, lanId, channel,
669 IsisRouterType.get(helloPacket.circuitType()));
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530670 l1LanId = lanId;
671 neighbor.setL1LanId(lanId);
672 //if a change in lanid
673 } else if (IsisPduType.L2HELLOPDU == helloPacket.isisPduType()) {
sunish vk4b5ce002016-05-09 20:18:35 +0530674 buildUpdateAndSendSelfGeneratedLspIfDisChange(l2LanId, lanId, channel,
675 IsisRouterType.get(helloPacket.circuitType()));
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530676 l2LanId = lanId;
677 neighbor.setL2LanId(lanId);
678 }
679
680 //Check in neighbors list our MAC address present
681 List<MacAddress> neighbors = helloPacket.neighborList();
sunish vk4b5ce002016-05-09 20:18:35 +0530682 if (neighbors != null) {
683 for (MacAddress macAddress : neighbors) {
684 if (interfaceMacAddress.equals(macAddress)) {
685 neighbor.setNeighborState(IsisInterfaceState.UP);
686 //Build Self LSP add in LSDB and sent it.
687 buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel,
688 IsisRouterType.get(helloPacket.circuitType()));
689 break;
690 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530691 }
692 }
693 }
694
695 /**
696 * Builds and store and send self generated LSP.
697 *
698 * @param channel netty channel instance
699 */
sunish vk4b5ce002016-05-09 20:18:35 +0530700 private void buildStoreAndSendSelfGeneratedLspIfNotExistInDb(Channel channel, IsisRouterType neighborRouterType) {
701 this.channel = channel;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530702 //Check our LSP is present in DB. else create a self LSP and store it and sent it
703 String lspKey = isisLsdb.lspKey(systemId);
704 LspWrapper wrapper = null;
705 if (reservedPacketCircuitType == IsisRouterType.L1.value()) {
706 wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey);
707 if (wrapper == null) {
708 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
709 isisLsdb.addLsp(lsp, true, this);
710 sendLsp(lsp, channel);
711 }
712 } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) {
713 wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey);
714 if (wrapper == null) {
715 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
716 isisLsdb.addLsp(lsp, true, this);
717 sendLsp(lsp, channel);
718 }
719 } else if (reservedPacketCircuitType == IsisRouterType.L1L2.value()) {
sunish vk4b5ce002016-05-09 20:18:35 +0530720 if ((neighborRouterType == IsisRouterType.L1 || neighborRouterType == IsisRouterType.L1L2)) {
721
722 wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey);
723 if (wrapper == null) {
724 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU,
725 allConfiguredInterfaceIps);
726 isisLsdb.addLsp(lsp, true, this);
727 sendLsp(lsp, channel);
728 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530729 }
730
sunish vk4b5ce002016-05-09 20:18:35 +0530731 if ((neighborRouterType == IsisRouterType.L2 || neighborRouterType == IsisRouterType.L1L2)) {
732 wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey);
733 if (wrapper == null) {
734 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU,
735 allConfiguredInterfaceIps);
736 isisLsdb.addLsp(lsp, true, this);
737 sendLsp(lsp, channel);
738 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530739 }
740 }
741 }
742
743 /**
744 * Builds and update in DB and send self generated LSP.
745 *
746 * @param previousLanId previous DIS ID
747 * @param latestLanId latest DIS ID
748 * @param channel netty channel instance
749 */
750 private void buildUpdateAndSendSelfGeneratedLspIfDisChange(String previousLanId,
sunish vk4b5ce002016-05-09 20:18:35 +0530751 String latestLanId, Channel channel,
752 IsisRouterType neighborRouterType) {
753 this.channel = channel;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530754 //If DIS change then build and sent LSP
sunish vk4b5ce002016-05-09 20:18:35 +0530755 if (!previousLanId.equals(latestLanId)) {
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530756 //Create a self LSP and Update it in DB and sent it
757 String lspKey = isisLsdb.lspKey(systemId);
758 if (reservedPacketCircuitType == IsisRouterType.L1.value()) {
759 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
760 isisLsdb.addLsp(lsp, true, this);
761 sendLsp(lsp, channel);
sunish vk4b5ce002016-05-09 20:18:35 +0530762 } else if (reservedPacketCircuitType == IsisRouterType.L2.value() &&
763 (neighborRouterType == IsisRouterType.L2 || neighborRouterType == IsisRouterType.L1L2)) {
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530764 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
765 isisLsdb.addLsp(lsp, true, this);
766 sendLsp(lsp, channel);
767 } else if (reservedPacketCircuitType == IsisRouterType.L1L2.value()) {
768 //L1 LSPDU
sunish vk4b5ce002016-05-09 20:18:35 +0530769 if (neighborRouterType == IsisRouterType.L1 || neighborRouterType == IsisRouterType.L1L2) {
770 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
771 isisLsdb.addLsp(lsp, true, this);
772 sendLsp(lsp, channel);
773 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530774 //L1 LSPDU
sunish vk4b5ce002016-05-09 20:18:35 +0530775 if (neighborRouterType == IsisRouterType.L2 || neighborRouterType == IsisRouterType.L1L2) {
776 LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
777 isisLsdb.addLsp(lsp, true, this);
778 sendLsp(lsp, channel);
779 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530780 }
781 }
782
783 }
784
785 /**
786 * Sends LS PDU message to channel.
787 *
788 * @param lsp LS PDU message instance
789 * @param channel channel instance
790 */
791 private void sendLsp(LsPdu lsp, Channel channel) {
792 byte[] lspBytes = lsp.asBytes();
793 lspBytes = IsisUtil.addLengthAndMarkItInReserved(lspBytes, IsisConstants.LENGTHPOSITION,
794 IsisConstants.LENGTHPOSITION + 1,
795 IsisConstants.RESERVEDPOSITION);
796 lspBytes = IsisUtil.addChecksum(lspBytes, IsisConstants.CHECKSUMPOSITION,
797 IsisConstants.CHECKSUMPOSITION + 1);
798 //write to the channel
sunish vk4b5ce002016-05-09 20:18:35 +0530799 if (channel != null && channel.isConnected() && channel.isOpen()) {
800 channel.write(IsisUtil.framePacket(lspBytes, interfaceIndex));
801 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530802 }
803
804 /**
805 * Processes P2P hello message.
806 *
807 * @param isisMessage hello message instance
808 * @param channel channel instance
809 */
810 public void processP2pHelloPduMessage(IsisMessage isisMessage, Channel channel) {
811 log.debug("Enters processP2pHelloPduMessage ...!!!");
812 P2PHelloPdu helloPacket = (P2PHelloPdu) isisMessage;
813
814 log.debug("IsisInterfaceImpl::processHelloMessage::Interface Type {} OSPFInterfaceState {} ",
815 networkType, interfaceState);
816
817 //validate the area, network and max address
818 if (!validateHelloMessage(helloPacket)) {
819 return;
820 }
821
822 IsisNeighbor neighbor = null;
823 List<IsisTlv> tlvs = ((P2PHelloPdu) isisMessage).tlvs();
824 AdjacencyStateTlv stateTlv = null;
825 for (IsisTlv tlv : tlvs) {
826 if (tlv instanceof AdjacencyStateTlv) {
827 stateTlv = (AdjacencyStateTlv) tlv;
828 break;
829 }
830 }
831
832 if (stateTlv == null) {
833 neighbor = neighbouringRouter(isisMessage.sourceMac());
834 if (neighbor == null) {
835 neighbor = new DefaultIsisNeighbor(helloPacket, this);
836 addNeighbouringRouter(neighbor);
837 }
838 neighbor.setNeighborState(IsisInterfaceState.DOWN);
sunish vk4b5ce002016-05-09 20:18:35 +0530839 buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel, IsisRouterType.get(helloPacket.circuitType()));
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530840 } else if (stateTlv.adjacencyType() == IsisInterfaceState.DOWN.value()) {
841 neighbor = neighbouringRouter(isisMessage.sourceMac());
842 if (neighbor == null) {
843 neighbor = new DefaultIsisNeighbor(helloPacket, this);
844 addNeighbouringRouter(neighbor);
845 }
846 neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId());
847 } else if (stateTlv.adjacencyType() == IsisInterfaceState.INITIAL.value()) {
848 //Neighbor already present in the list
849 neighbor = neighbouringRouter(isisMessage.sourceMac());
sunish vk4b5ce002016-05-09 20:18:35 +0530850 if (neighbor == null) {
851 neighbor = new DefaultIsisNeighbor(helloPacket, this);
852 addNeighbouringRouter(neighbor);
853 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530854 neighbor.setNeighborState(IsisInterfaceState.INITIAL);
855 neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId());
856 //interfaceState = IsisInterfaceState.UP;
857 } else if (stateTlv.adjacencyType() == IsisInterfaceState.UP.value()) {
858 //Build Self LSP add in LSDB and sent it.
859 neighbor = neighbouringRouter(isisMessage.sourceMac());
860 neighbor.setNeighborState(IsisInterfaceState.UP);
861 neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId());
sunish vk4b5ce002016-05-09 20:18:35 +0530862 buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel, IsisRouterType.get(helloPacket.circuitType()));
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530863 }
864
sunish vk4b5ce002016-05-09 20:18:35 +0530865 neighbor.setHoldingTime(helloPacket.holdingTime());
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530866 neighbor.stopInactivityTimeCheck();
867 neighbor.startInactivityTimeCheck();
868 }
869
870 /**
871 * Processes LS PDU message.
872 *
873 * @param isisMessage LS pdu message instance
874 * @param channel channel instance
875 */
876 public void processLsPduMessage(IsisMessage isisMessage, Channel channel) {
877 log.debug("Enters processLsPduMessage ...!!!");
sunish vk4b5ce002016-05-09 20:18:35 +0530878 IsisNeighbor neighbor = neighbouringRouter(isisMessage.sourceMac());
879 if (networkType == IsisNetworkType.BROADCAST && neighbor == null) {
880 return;
881 }
882
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530883 LsPdu lsPdu = (LsPdu) isisMessage;
884 LspWrapper wrapper = isisLsdb.findLsp(lsPdu.isisPduType(), lsPdu.lspId());
885 if (wrapper == null || isisLsdb.isNewerOrSameLsp(lsPdu, wrapper.lsPdu()).equalsIgnoreCase("latest")) {
sunish vk4b5ce002016-05-09 20:18:35 +0530886 if (wrapper != null) { // verify if the LSA - is your own LSA - get system ID and compare LSP
887 String lspKey = isisLsdb.lspKey(systemId);
888 if (lsPdu.lspId().equals(lspKey)) {
889 lsPdu.setSequenceNumber(lsPdu.sequenceNumber() + 1);
890 if (lsPdu.pduType() == IsisPduType.L1LSPDU.value()) {
891 // setting the ls sequence number
892 isisLsdb.setL1LspSeqNo(lsPdu.sequenceNumber());
893 } else if (lsPdu.pduType() == IsisPduType.L2LSPDU.value()) {
894 // setting the ls sequence number
895 isisLsdb.setL2LspSeqNo(lsPdu.sequenceNumber());
896 }
897 isisLsdb.addLsp(lsPdu, true, this);
898 sendLsp(lsPdu, channel);
899 } else {
900 isisLsdb.addLsp(lsPdu, false, this);
901 }
902
903
904 } else {
905 //not exist in the database or latest, then add it in database
906 isisLsdb.addLsp(lsPdu, false, this);
907 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530908 }
909
910 //If network type is P2P, acknowledge with a PSNP
911 if (networkType() == IsisNetworkType.P2P) {
912 IsisPduType psnpType = null;
913 if (IsisPduType.get(lsPdu.pduType()) == IsisPduType.L1LSPDU) {
914 psnpType = IsisPduType.L1PSNP;
915 } else if (IsisPduType.get(lsPdu.pduType()) == IsisPduType.L2LSPDU) {
916 psnpType = IsisPduType.L2PSNP;
917 }
918 IsisHeader isisHeader = new LspGenerator().getHeader(psnpType);
919 Psnp psnp = new Psnp(isisHeader);
920 psnp.setSourceId(lspKeyP2P(this.systemId));
921 TlvHeader tlvHeader = new TlvHeader();
922 tlvHeader.setTlvType(TlvType.LSPENTRY.value());
923 tlvHeader.setTlvLength(0);
924 LspEntriesTlv lspEntriesTlv = new LspEntriesTlv(tlvHeader);
925 LspEntry lspEntry = new LspEntry();
926 lspEntry.setLspChecksum(lsPdu.checkSum());
927 lspEntry.setLspId(lsPdu.lspId());
928 lspEntry.setLspSequenceNumber(lsPdu.sequenceNumber());
929 lspEntry.setRemainingTime(lsPdu.remainingLifeTime());
930 lspEntriesTlv.addLspEntry(lspEntry);
931 psnp.addTlv(lspEntriesTlv);
932
933 //write it to channel buffer.
934 byte[] psnpBytes = psnp.asBytes();
935 psnpBytes = IsisUtil.addLengthAndMarkItInReserved(psnpBytes, IsisConstants.LENGTHPOSITION,
936 IsisConstants.LENGTHPOSITION + 1,
937 IsisConstants.RESERVEDPOSITION);
938 flagValue = false;
939 //write to the channel
sunish vk4b5ce002016-05-09 20:18:35 +0530940 if (channel != null && channel.isConnected() && channel.isOpen()) {
941 channel.write(IsisUtil.framePacket(psnpBytes, interfaceIndex));
942 }
943 }
944 }
945
946 /**
947 * Processes PSN PDU message.
948 * Checks for self originated LSP entries in PSNP message and sends the missing LSP.
949 *
950 * @param isisMessage PSN PDU message instance
951 * @param channel channel instance
952 */
953 public void processPsnPduMessage(IsisMessage isisMessage, Channel channel) {
954 log.debug("Enters processPsnPduMessage ...!!!");
955 //If adjacency not formed don't process.
956 IsisNeighbor neighbor = neighbouringRouter(isisMessage.sourceMac());
957 if (networkType == IsisNetworkType.BROADCAST && neighbor == null) {
958 return;
959 }
960
961 Psnp psnPacket = (Psnp) isisMessage;
962 List<IsisTlv> isisTlvs = psnPacket.getAllTlv();
963 Iterator iterator = isisTlvs.iterator();
964 while (iterator.hasNext()) {
965 IsisTlv isisTlv = (IsisTlv) iterator.next();
966 if (isisTlv instanceof LspEntriesTlv) {
967 LspEntriesTlv lspEntriesTlv = (LspEntriesTlv) isisTlv;
968 List<LspEntry> lspEntryList = lspEntriesTlv.lspEntry();
969 Iterator lspEntryListIterator = lspEntryList.iterator();
970 while (lspEntryListIterator.hasNext()) {
971 LspEntry lspEntry = (LspEntry) lspEntryListIterator.next();
972 String lspKey = lspEntry.lspId();
973 LspWrapper lspWrapper = isisLsdb.findLsp(psnPacket.isisPduType(), lspKey);
974 if (lspWrapper != null) {
975 if (lspWrapper.isSelfOriginated()) {
976 //Sent the LSP
977 sendLsp((LsPdu) lspWrapper.lsPdu(), channel);
978 }
979 }
980 }
981 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530982 }
983 }
984
985 /**
986 * Processes CSN PDU message.
987 *
988 * @param isisMessage CSN PDU message instance
989 * @param channel channel instance
990 */
991 public void processCsnPduMessage(IsisMessage isisMessage, Channel channel) {
992 log.debug("Enters processCsnPduMessage ...!!!");
sunish vk4b5ce002016-05-09 20:18:35 +0530993 IsisNeighbor neighbor = neighbouringRouter(isisMessage.sourceMac());
994 if (networkType == IsisNetworkType.BROADCAST && neighbor == null) {
995 return;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530996 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530997
tejeshwer degala3fe1ed52016-04-22 17:04:01 +0530998 Csnp csnPacket = (Csnp) isisMessage;
sunish vk4b5ce002016-05-09 20:18:35 +0530999 IsisPduType psnPduType = (IsisPduType.L2CSNP.equals(csnPacket.isisPduType())) ?
1000 IsisPduType.L2PSNP : IsisPduType.L1PSNP;
1001 IsisPduType lsPduType = (IsisPduType.L2CSNP.equals(csnPacket.isisPduType())) ?
1002 IsisPduType.L2LSPDU : IsisPduType.L1LSPDU;
1003
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301004 List<LspEntry> lspEntryRequestList = new ArrayList<>();
1005 boolean selfOriginatedFound = false;
sunish vk4b5ce002016-05-09 20:18:35 +05301006 List<IsisTlv> isisTlvs = csnPacket.getAllTlv();
1007 Iterator iterator = isisTlvs.iterator();
1008 while (iterator.hasNext()) {
1009 IsisTlv isisTlv = (IsisTlv) iterator.next();
1010 if (isisTlv instanceof LspEntriesTlv) {
1011 LspEntriesTlv lspEntriesTlv = (LspEntriesTlv) isisTlv;
1012 List<LspEntry> lspEntryList = lspEntriesTlv.lspEntry();
1013 Iterator lspEntryListIterator = lspEntryList.iterator();
1014 while (lspEntryListIterator.hasNext()) {
1015 LspEntry lspEntry = (LspEntry) lspEntryListIterator.next();
1016 String lspKey = lspEntry.lspId();
1017 LspWrapper lspWrapper = isisLsdb.findLsp(lsPduType, lspKey);
1018 if (lspWrapper != null) {
1019 LsPdu lsPdu = (LsPdu) lspWrapper.lsPdu();
1020 if (lspWrapper.isSelfOriginated()) {
1021 selfOriginatedFound = true;
1022 if (lspEntry.lspSequenceNumber() < lsPdu.sequenceNumber()) {
1023 sendLsp(lsPdu, channel);
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301024 }
1025 } else {
sunish vk4b5ce002016-05-09 20:18:35 +05301026 if (lsPdu.sequenceNumber() < lspEntry.lspSequenceNumber()) {
1027 lspEntryRequestList.add(lspEntry);
1028 flagValue = true;
1029 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301030 }
sunish vk4b5ce002016-05-09 20:18:35 +05301031 } else {
1032 lspEntryRequestList.add(lspEntry);
1033 flagValue = true;
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301034 }
1035 }
1036 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301037 }
sunish vk4b5ce002016-05-09 20:18:35 +05301038 if (flagValue) {
1039 sendPsnPduMessage(lspEntryRequestList, psnPduType, channel);
1040 lspEntryRequestList.clear();
1041 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301042
sunish vk4b5ce002016-05-09 20:18:35 +05301043 if (!selfOriginatedFound) {
1044 String lspKey = isisLsdb.lspKey(systemId);
1045 LspWrapper wrapper = isisLsdb.findLsp(lsPduType, lspKey);
1046 if (wrapper != null) {
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301047 sendLsp((LsPdu) wrapper.lsPdu(), channel);
1048 }
1049 }
1050 }
1051
1052 /**
1053 * Sends the partial sequence number PDU.
1054 *
1055 * @param lspEntryRequestList list of lsp entry request
1056 * @param isisPduType intermediate system PDU type
1057 * @param channel netty channel instance
1058 */
1059 private void sendPsnPduMessage(List<LspEntry> lspEntryRequestList, IsisPduType isisPduType, Channel channel) {
sunish vk4b5ce002016-05-09 20:18:35 +05301060 IsisHeader isisHeader = new LspGenerator().getHeader(isisPduType);
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301061 Psnp psnp = new Psnp(isisHeader);
1062 psnp.setSourceId(lspKeyP2P(this.systemId));
1063 TlvHeader tlvHeader = new TlvHeader();
1064 tlvHeader.setTlvType(TlvType.LSPENTRY.value());
1065 tlvHeader.setTlvLength(0);
1066 LspEntriesTlv lspEntriesTlv = new LspEntriesTlv(tlvHeader);
1067 for (LspEntry lspEntry : lspEntryRequestList) {
sunish vk4b5ce002016-05-09 20:18:35 +05301068 lspEntry.setLspChecksum(0);
1069 lspEntry.setLspSequenceNumber(0);
1070 lspEntry.setRemainingTime(0);
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301071 lspEntriesTlv.addLspEntry(lspEntry);
1072 }
1073 psnp.addTlv(lspEntriesTlv);
1074 //write it to channel buffer.
1075 byte[] psnpBytes = psnp.asBytes();
1076 psnpBytes = IsisUtil.addLengthAndMarkItInReserved(psnpBytes, IsisConstants.LENGTHPOSITION,
1077 IsisConstants.LENGTHPOSITION + 1,
1078 IsisConstants.RESERVEDPOSITION);
1079 flagValue = false;
1080 //write to the channel
sunish vk4b5ce002016-05-09 20:18:35 +05301081 if (channel != null && channel.isConnected() && channel.isOpen()) {
1082 channel.write(IsisUtil.framePacket(psnpBytes, interfaceIndex));
1083 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301084 }
1085
1086 /**
1087 * Gets the LSP key.
1088 *
1089 * @param systemId system ID
1090 * @return key
1091 */
1092 public String lspKeyP2P(String systemId) {
1093 StringBuilder lspKey = new StringBuilder();
1094 lspKey.append(systemId);
1095 lspKey.append(".00");
1096 return lspKey.toString();
1097 }
1098
1099 /**
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301100 * Starts the hello timer which sends hello packet every configured seconds.
1101 *
1102 * @param channel netty channel instance
1103 */
1104 public void startHelloSender(Channel channel) {
1105 log.debug("IsisInterfaceImpl::startHelloSender");
1106
1107 isisHelloPduSender = new IsisHelloPduSender(channel, this);
1108 exServiceHello = Executors.newSingleThreadScheduledExecutor();
1109 final ScheduledFuture<?> helloHandle =
1110 exServiceHello.scheduleAtFixedRate(isisHelloPduSender, 0,
1111 helloInterval, TimeUnit.SECONDS);
1112 }
sunish vk4b5ce002016-05-09 20:18:35 +05301113
1114 /**
1115 * Stops the hello timer which sends hello packet every configured seconds.
1116 */
1117 public void stopHelloSender() {
1118 log.debug("IsisInterfaceImpl::stopHelloSender");
1119 exServiceHello.shutdown();
1120 }
tejeshwer degala3fe1ed52016-04-22 17:04:01 +05301121}