2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.openflow.internal;
11 import java.nio.charset.Charset;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.HashSet;
16 import java.util.List;
19 import java.util.Timer;
20 import java.util.TimerTask;
21 import java.util.concurrent.BlockingQueue;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
24 import java.util.concurrent.CopyOnWriteArrayList;
25 import java.util.concurrent.LinkedBlockingQueue;
27 import org.eclipse.osgi.framework.console.CommandInterpreter;
28 import org.eclipse.osgi.framework.console.CommandProvider;
29 import org.openflow.protocol.OFPhysicalPort;
30 import org.osgi.framework.BundleContext;
31 import org.osgi.framework.FrameworkUtil;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
36 import org.opendaylight.controller.sal.core.Config;
37 import org.opendaylight.controller.sal.core.ConstructionException;
38 import org.opendaylight.controller.sal.core.Edge;
39 import org.opendaylight.controller.sal.core.ContainerFlow;
40 import org.opendaylight.controller.sal.core.IContainerListener;
41 import org.opendaylight.controller.sal.core.Node;
42 import org.opendaylight.controller.sal.core.NodeConnector;
43 import org.opendaylight.controller.sal.core.Property;
44 import org.opendaylight.controller.sal.core.State;
45 import org.opendaylight.controller.sal.core.UpdateType;
46 import org.opendaylight.controller.sal.packet.Ethernet;
47 import org.opendaylight.controller.sal.packet.LLDP;
48 import org.opendaylight.controller.sal.packet.LLDPTLV;
49 import org.opendaylight.controller.sal.packet.LinkEncap;
50 import org.opendaylight.controller.sal.packet.PacketResult;
51 import org.opendaylight.controller.sal.packet.RawPacket;
52 import org.opendaylight.controller.sal.utils.EtherTypes;
53 import org.opendaylight.controller.sal.utils.HexEncode;
54 import org.opendaylight.controller.sal.utils.NetUtils;
55 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
56 import org.opendaylight.controller.sal.utils.NodeCreator;
57 import org.opendaylight.controller.sal.utils.Status;
58 import org.opendaylight.controller.sal.utils.StatusCode;
59 import org.opendaylight.openflowplugin.openflow.IDataPacketListen;
60 import org.opendaylight.openflowplugin.openflow.IDataPacketMux;
61 import org.opendaylight.openflowplugin.openflow.IDiscoveryListener;
62 import org.opendaylight.openflowplugin.openflow.IInventoryProvider;
63 import org.opendaylight.openflowplugin.openflow.IInventoryShimExternalListener;
64 import org.opendaylight.openflowplugin.openflow.core.IController;
65 import org.opendaylight.openflowplugin.openflow.core.ISwitch;
68 * The class describes neighbor discovery service for an OpenFlow network.
70 public class DiscoveryService implements IInventoryShimExternalListener, IDataPacketListen, IContainerListener,
72 private static Logger logger = LoggerFactory.getLogger(DiscoveryService.class);
73 private IController controller = null;
74 private IDiscoveryListener discoveryListener = null;
75 private IInventoryProvider inventoryProvider = null;
76 private IDataPacketMux iDataPacketMux = null;
77 // High priority list containing newly added ports which will be served first
78 private List<NodeConnector> readyListHi = null;
79 // List containing all the ports which will be served periodically
80 private List<NodeConnector> readyListLo = null;
81 // Staging area during quiet period
82 private List<NodeConnector> stagingList = null;
83 // Wait for next discovery packet. The map contains the time elapsed since
84 // the last received LLDP frame on each node connector
85 private ConcurrentMap<NodeConnector, Integer> holdTime = null;
86 // Allow one more retry for newly added ports. This map contains the time
87 // period elapsed since last discovery pkt transmission on the port.
88 private ConcurrentMap<NodeConnector, Integer> elapsedTime = null;
89 // OpenFlow edges keyed by head connector
90 private ConcurrentMap<NodeConnector, Edge> edgeMap = null;
91 // The map contains aging entry keyed by head connector of Production edge
92 private ConcurrentMap<NodeConnector, Integer> agingMap = null;
93 // Production edges keyed by head connector
94 private ConcurrentMap<NodeConnector, Edge> prodMap = null;
96 private Timer discoveryTimer;
97 private DiscoveryTimerTask discoveryTimerTask;
98 private final static long discoveryTimerTick = 2L * 1000; // per tick in msec
99 private int discoveryTimerTickCount = 0; // main tick counter
100 // Max # of ports handled in one batch
101 private int discoveryBatchMaxPorts;
102 // Periodically restart batching process
103 private int discoveryBatchRestartTicks;
104 private int discoveryBatchPausePeriod = 2;
105 // Pause after this point
106 private int discoveryBatchPauseTicks;
107 private int discoveryTimeoutTicks;
108 private int discoveryThresholdTicks;
109 private int discoveryAgeoutTicks;
110 // multiple of discoveryBatchRestartTicks
111 private int discoveryConsistencyCheckMultiple = 2;
113 private int discoveryConsistencyCheckTickCount;
114 // # of times CC gets called
115 private int discoveryConsistencyCheckCallingTimes = 0;
116 // # of cases CC corrected
117 private int discoveryConsistencyCheckCorrected = 0;
118 // Enable or disable CC
119 private boolean discoveryConsistencyCheckEnabled = true;
120 // Enable or disable aging
121 private boolean discoveryAgingEnabled = true;
122 // Global flag to enable or disable LLDP snooping
123 private boolean discoverySnoopingEnabled = true;
124 // The list of ports that will not do LLDP snooping
125 private List<NodeConnector> discoverySnoopingDisableList;
126 private BlockingQueue<NodeConnector> transmitQ;
127 private Thread transmitThread;
128 private Boolean throttling = false; // if true, no more batching.
129 private volatile Boolean shuttingDown = false;
131 private LLDPTLV chassisIdTlv, portIdTlv, ttlTlv, customTlv;
132 private IPluginOutConnectionService connectionOutService;
134 class DiscoveryTransmit implements Runnable {
135 private final BlockingQueue<NodeConnector> transmitQ;
137 DiscoveryTransmit(BlockingQueue<NodeConnector> transmitQ) {
138 this.transmitQ = transmitQ;
145 NodeConnector nodeConnector = transmitQ.take();
146 RawPacket outPkt = createDiscoveryPacket(nodeConnector);
147 sendDiscoveryPacket(nodeConnector, outPkt);
148 nodeConnector = null;
149 } catch (InterruptedException e1) {
150 logger.warn("DiscoveryTransmit interupted", e1.getMessage());
154 } catch (Exception e2) {
155 logger.error("", e2);
161 class DiscoveryTimerTask extends TimerTask {
166 doConsistencyCheck();
171 public enum DiscoveryPeriod {
176 private int time; // sec
177 private int tick; // tick
179 DiscoveryPeriod(int time) {
181 this.tick = time2Tick(time);
184 public int getTime() {
188 public void setTime(int time) {
190 this.tick = time2Tick(time);
193 public int getTick() {
197 public void setTick(int tick) {
198 this.time = tick2Time(tick);
202 private int time2Tick(int time) {
203 return (int) (time / (discoveryTimerTick / 1000));
206 private int tick2Time(int tick) {
207 return (int) (tick * (discoveryTimerTick / 1000));
211 private RawPacket createDiscoveryPacket(NodeConnector nodeConnector) {
212 String nodeId = HexEncode.longToHexString((Long) nodeConnector.getNode().getID());
214 // Create LLDP ChassisID TLV
215 byte[] cidValue = LLDPTLV.createChassisIDTLVValue(nodeId);
216 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue()).setLength((short) cidValue.length)
219 // Create LLDP PortID TLV
220 String portId = nodeConnector.getNodeConnectorIDString();
221 byte[] pidValue = LLDPTLV.createPortIDTLVValue(portId);
222 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue()).setLength((short) pidValue.length).setValue(pidValue);
224 // Create LLDP Custom TLV
225 byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnector.toString());
226 customTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customValue.length)
227 .setValue(customValue);
229 // Create LLDP Custom Option list
230 List<LLDPTLV> customList = new ArrayList<LLDPTLV>();
231 customList.add(customTlv);
233 // Create discovery pkt
234 LLDP discoveryPkt = new LLDP();
235 discoveryPkt.setChassisId(chassisIdTlv).setPortId(portIdTlv).setTtl(ttlTlv).setOptionalTLVList(customList);
237 RawPacket rawPkt = null;
239 // Create ethernet pkt
240 byte[] sourceMac = getSourceMACFromNodeID(nodeId);
241 Ethernet ethPkt = new Ethernet();
242 ethPkt.setSourceMACAddress(sourceMac).setDestinationMACAddress(LLDP.LLDPMulticastMac)
243 .setEtherType(EtherTypes.LLDP.shortValue()).setPayload(discoveryPkt);
245 byte[] data = ethPkt.serialize();
246 rawPkt = new RawPacket(data);
247 rawPkt.setOutgoingNodeConnector(nodeConnector);
248 } catch (ConstructionException cex) {
249 logger.warn("RawPacket creation caught exception {}", cex.getMessage());
250 } catch (Exception e) {
251 logger.error("Failed to serialize the LLDP packet: " + e);
257 private void sendDiscoveryPacket(NodeConnector nodeConnector, RawPacket outPkt) {
258 if (nodeConnector == null) {
259 logger.debug("Can not send discovery packet out since nodeConnector is null");
263 if (!connectionOutService.isLocal(nodeConnector.getNode())) {
264 logger.debug("Discoery packets will not be sent to {} in a non-master controller", nodeConnector.toString());
268 if (outPkt == null) {
269 logger.debug("Can not send discovery packet out since outPkt is null");
273 long sid = (Long) nodeConnector.getNode().getID();
274 ISwitch sw = controller.getSwitches().get(sid);
277 logger.debug("Can not send discovery packet out since switch {} is null", sid);
281 if (!sw.isOperational()) {
282 logger.debug("Can not send discovery packet out since switch {} is not operational", sw);
286 if (this.iDataPacketMux == null) {
287 logger.debug("Can not send discovery packet out since DataPacket service is not available");
291 logger.trace("Sending topology discovery pkt thru {}", nodeConnector);
292 this.iDataPacketMux.transmitDataPacket(outPkt);
296 public PacketResult receiveDataPacket(RawPacket inPkt) {
298 logger.debug("Ignoring null packet");
299 return PacketResult.IGNORED;
302 byte[] data = inPkt.getPacketData();
303 if (data.length <= 0) {
304 logger.trace("Ignoring zero length packet");
305 return PacketResult.IGNORED;
308 if (!inPkt.getEncap().equals(LinkEncap.ETHERNET)) {
309 logger.trace("Ignoring non ethernet packet");
310 return PacketResult.IGNORED;
313 NodeConnector nodeConnector = inPkt.getIncomingNodeConnector();
314 if (((Short) nodeConnector.getID()).equals(NodeConnector.SPECIALNODECONNECTORID)) {
315 logger.trace("Ignoring ethernet packet received on special port: "
316 + inPkt.getIncomingNodeConnector().toString());
317 return PacketResult.IGNORED;
320 if (!connectionOutService.isLocal(nodeConnector.getNode())) {
321 logger.debug("Discoery packets will not be processed from {} in a non-master controller", nodeConnector.toString());
322 return PacketResult.IGNORED;
325 Ethernet ethPkt = new Ethernet();
327 ethPkt.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
328 } catch (Exception e) {
329 logger.warn("Failed to decode LLDP packet from {}: {}", inPkt.getIncomingNodeConnector(), e);
330 return PacketResult.IGNORED;
333 if (ethPkt.getPayload() instanceof LLDP) {
334 NodeConnector dst = inPkt.getIncomingNodeConnector();
335 if (isEnabled(dst)) {
336 if (!processDiscoveryPacket(dst, ethPkt)) {
337 // Snoop the discovery pkt if not generated from us
338 snoopDiscoveryPacket(dst, ethPkt);
340 return PacketResult.CONSUME;
343 return PacketResult.IGNORED;
347 * Snoop incoming discovery frames generated by the production network
350 private void snoopDiscoveryPacket(NodeConnector dstNodeConnector, Ethernet ethPkt) {
351 if (!this.discoverySnoopingEnabled || discoverySnoopingDisableList.contains(dstNodeConnector)) {
352 logger.trace("Discarded received discovery packet on {} since snooping is turned off", dstNodeConnector);
356 if ((dstNodeConnector == null) || (ethPkt == null)) {
357 logger.trace("Quit snooping discovery packet: Null node connector or packet");
361 LLDP lldp = (LLDP) ethPkt.getPayload();
364 String nodeId = LLDPTLV.getHexStringValue(lldp.getChassisId().getValue(), lldp.getChassisId().getLength());
365 String portId = LLDPTLV.getStringValue(lldp.getPortId().getValue(), lldp.getPortId().getLength());
366 byte[] systemNameBytes = null;
367 // get system name if present in the LLDP pkt
368 for (LLDPTLV lldptlv : lldp.getOptionalTLVList()) {
369 if (lldptlv.getType() == LLDPTLV.TLVType.SystemName.getValue()) {
370 systemNameBytes = lldptlv.getValue();
374 String nodeName = (systemNameBytes == null) ? nodeId
375 : new String(systemNameBytes, Charset.defaultCharset());
376 Node srcNode = new Node(Node.NodeIDType.PRODUCTION, nodeName);
377 NodeConnector srcNodeConnector = NodeConnectorCreator.createNodeConnector(
378 NodeConnector.NodeConnectorIDType.PRODUCTION, portId, srcNode);
381 Set<Property> props = null;
382 edge = new Edge(srcNodeConnector, dstNodeConnector);
383 props = getProps(dstNodeConnector);
385 updateProdEdge(edge, props);
386 } catch (Exception e) {
387 logger.warn("Caught exception ", e);
392 * Handle discovery frames generated by our controller
394 * @return true if it's a success
396 private boolean processDiscoveryPacket(NodeConnector dstNodeConnector, Ethernet ethPkt) {
397 if ((dstNodeConnector == null) || (ethPkt == null)) {
398 logger.trace("Ignoring processing of discovery packet: Null node connector or packet");
402 logger.trace("Handle discovery packet {} from {}", ethPkt, dstNodeConnector);
404 LLDP lldp = (LLDP) ethPkt.getPayload();
406 List<LLDPTLV> optionalTLVList = lldp.getOptionalTLVList();
407 if (optionalTLVList == null) {
408 logger.info("The discovery packet with null custom option from {}", dstNodeConnector);
413 NodeConnector srcNodeConnector = null;
414 for (LLDPTLV lldptlv : lldp.getOptionalTLVList()) {
415 if (lldptlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
416 String ncString = LLDPTLV.getCustomString(lldptlv.getValue(), lldptlv.getLength());
417 srcNodeConnector = NodeConnector.fromString(ncString);
418 if (srcNodeConnector != null) {
419 srcNode = srcNodeConnector.getNode();
424 if ((srcNode == null) || (srcNodeConnector == null)) {
425 logger.trace("Received non-controller generated discovery packet from {}", dstNodeConnector);
429 // push it out to Topology
431 Set<Property> props = null;
433 edge = new Edge(srcNodeConnector, dstNodeConnector);
434 props = getProps(dstNodeConnector);
435 } catch (ConstructionException e) {
436 logger.error("Caught exception ", e);
438 addEdge(edge, props);
440 logger.trace("Received discovery packet for Edge {}", edge);
445 public Map<String, Property> getPropMap(NodeConnector nodeConnector) {
446 if (nodeConnector == null) {
450 if (inventoryProvider == null) {
454 Map<NodeConnector, Map<String, Property>> props = inventoryProvider.getNodeConnectorProps(false);
459 return props.get(nodeConnector);
462 public Property getProp(NodeConnector nodeConnector, String propName) {
463 Map<String, Property> propMap = getPropMap(nodeConnector);
464 if (propMap == null) {
468 Property prop = propMap.get(propName);
472 public Set<Property> getProps(NodeConnector nodeConnector) {
473 Map<String, Property> propMap = getPropMap(nodeConnector);
474 if (propMap == null) {
478 Set<Property> props = new HashSet<Property>(propMap.values());
482 private boolean isEnabled(NodeConnector nodeConnector) {
483 if (nodeConnector == null) {
487 Config config = (Config) getProp(nodeConnector, Config.ConfigPropName);
488 State state = (State) getProp(nodeConnector, State.StatePropName);
489 return ((config != null) && (config.getValue() == Config.ADMIN_UP) && (state != null) && (state.getValue() == State.EDGE_UP));
492 private boolean isTracked(NodeConnector nodeConnector) {
493 if (readyListHi.contains(nodeConnector)) {
497 if (readyListLo.contains(nodeConnector)) {
501 if (holdTime.keySet().contains(nodeConnector)) {
505 if (stagingList.contains(nodeConnector)) {
512 private Set<NodeConnector> getWorkingSet() {
513 Set<NodeConnector> workingSet = new HashSet<NodeConnector>();
514 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
516 for (NodeConnector nodeConnector : readyListHi) {
517 if (isOverLimit(workingSet.size())) {
521 workingSet.add(nodeConnector);
522 removeSet.add(nodeConnector);
524 // Put it in the map and start the timer. It may need retry.
525 elapsedTime.put(nodeConnector, 0);
527 readyListHi.removeAll(removeSet);
530 for (NodeConnector nodeConnector : readyListLo) {
531 if (isOverLimit(workingSet.size())) {
535 workingSet.add(nodeConnector);
536 removeSet.add(nodeConnector);
538 readyListLo.removeAll(removeSet);
543 private Boolean isOverLimit(int size) {
544 return ((size >= discoveryBatchMaxPorts) && !throttling);
547 private void addDiscovery() {
548 Map<Long, ISwitch> switches = controller.getSwitches();
549 Set<Long> sidSet = switches.keySet();
550 if (sidSet == null) {
553 for (Long sid : sidSet) {
554 Node node = NodeCreator.createOFNode(sid);
559 private void addDiscovery(Node node) {
560 Map<Long, ISwitch> switches = controller.getSwitches();
561 ISwitch sw = switches.get(node.getID());
562 List<OFPhysicalPort> ports = sw.getEnabledPorts();
566 for (OFPhysicalPort port : ports) {
567 NodeConnector nodeConnector = NodeConnectorCreator.createOFNodeConnector(port.getPortNumber(), node);
568 if (!readyListHi.contains(nodeConnector)) {
569 readyListHi.add(nodeConnector);
574 private void addDiscovery(NodeConnector nodeConnector) {
575 if (isTracked(nodeConnector)) {
579 readyListHi.add(nodeConnector);
582 private Set<NodeConnector> getRemoveSet(Collection<NodeConnector> c, Node node) {
583 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
587 for (NodeConnector nodeConnector : c) {
588 if (node.equals(nodeConnector.getNode())) {
589 Edge edge1 = edgeMap.get(nodeConnector);
591 removeSet.add(nodeConnector);
593 // check reverse direction
594 Edge edge2 = edgeMap.get(edge1.getTailNodeConnector());
595 if ((edge2 != null) && node.equals(edge2.getTailNodeConnector().getNode())) {
596 removeSet.add(edge2.getHeadNodeConnector());
604 private void removeDiscovery(Node node) {
605 Set<NodeConnector> removeSet;
607 removeSet = getRemoveSet(readyListHi, node);
608 readyListHi.removeAll(removeSet);
610 removeSet = getRemoveSet(readyListLo, node);
611 readyListLo.removeAll(removeSet);
613 removeSet = getRemoveSet(stagingList, node);
614 stagingList.removeAll(removeSet);
616 removeSet = getRemoveSet(holdTime.keySet(), node);
617 for (NodeConnector nodeConnector : removeSet) {
618 holdTime.remove(nodeConnector);
621 removeSet = getRemoveSet(edgeMap.keySet(), node);
622 for (NodeConnector nodeConnector : removeSet) {
623 removeEdge(nodeConnector, false);
626 removeSet = getRemoveSet(prodMap.keySet(), node);
627 for (NodeConnector nodeConnector : removeSet) {
628 removeProdEdge(nodeConnector);
632 private void removeDiscovery(NodeConnector nodeConnector) {
633 readyListHi.remove(nodeConnector);
634 readyListLo.remove(nodeConnector);
635 stagingList.remove(nodeConnector);
636 holdTime.remove(nodeConnector);
637 removeEdge(nodeConnector, false);
638 removeProdEdge(nodeConnector);
641 private void checkTimeout() {
642 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
645 Set<NodeConnector> monitorSet = holdTime.keySet();
646 if (monitorSet != null) {
647 for (NodeConnector nodeConnector : monitorSet) {
648 ticks = holdTime.get(nodeConnector);
649 holdTime.put(nodeConnector, ++ticks);
650 if (ticks >= discoveryTimeoutTicks) {
652 removeSet.add(nodeConnector);
653 logger.trace("Discovery timeout {}", nodeConnector);
658 for (NodeConnector nodeConnector : removeSet) {
659 removeEdge(nodeConnector);
662 Set<NodeConnector> retrySet = new HashSet<NodeConnector>();
663 Set<NodeConnector> ncSet = elapsedTime.keySet();
664 if ((ncSet != null) && (ncSet.size() > 0)) {
665 for (NodeConnector nodeConnector : ncSet) {
666 ticks = elapsedTime.get(nodeConnector);
667 elapsedTime.put(nodeConnector, ++ticks);
668 if (ticks >= discoveryThresholdTicks) {
669 retrySet.add(nodeConnector);
673 for (NodeConnector nodeConnector : retrySet) {
674 // Allow one more retry
675 readyListLo.add(nodeConnector);
676 elapsedTime.remove(nodeConnector);
677 if (connectionOutService.isLocal(nodeConnector.getNode())) {
678 transmitQ.add(nodeConnector);
684 private void checkAging() {
685 if (!discoveryAgingEnabled) {
689 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
692 Set<NodeConnector> agingSet = agingMap.keySet();
693 if (agingSet != null) {
694 for (NodeConnector nodeConnector : agingSet) {
695 ticks = agingMap.get(nodeConnector);
696 agingMap.put(nodeConnector, ++ticks);
697 if (ticks > discoveryAgeoutTicks) {
699 removeSet.add(nodeConnector);
700 logger.trace("Discovery age out {}", nodeConnector);
705 for (NodeConnector nodeConnector : removeSet) {
706 removeProdEdge(nodeConnector);
710 private void doDiscovery() {
711 if (++discoveryTimerTickCount <= discoveryBatchPauseTicks) {
712 for (NodeConnector nodeConnector : getWorkingSet()) {
713 if (connectionOutService.isLocal(nodeConnector.getNode())) {
714 transmitQ.add(nodeConnector);
715 // Move to staging area after it's served
716 if (!stagingList.contains(nodeConnector)) {
717 stagingList.add(nodeConnector);
721 } else if (discoveryTimerTickCount >= discoveryBatchRestartTicks) {
722 discoveryTimerTickCount = 0;
723 for (NodeConnector nodeConnector : stagingList) {
724 if (!readyListLo.contains(nodeConnector)) {
725 readyListLo.add(nodeConnector);
728 stagingList.removeAll(readyListLo);
732 private void doConsistencyCheck() {
733 if (!discoveryConsistencyCheckEnabled) {
737 if (++discoveryConsistencyCheckTickCount % getDiscoveryConsistencyCheckInterval() != 0) {
741 discoveryConsistencyCheckCallingTimes++;
743 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
744 Set<NodeConnector> ncSet = edgeMap.keySet();
748 for (NodeConnector nodeConnector : ncSet) {
749 if (!isEnabled(nodeConnector)) {
750 removeSet.add(nodeConnector);
751 discoveryConsistencyCheckCorrected++;
752 logger.debug("ConsistencyChecker: remove disabled {}", nodeConnector);
756 if (!isTracked(nodeConnector)) {
757 stagingList.add(nodeConnector);
758 discoveryConsistencyCheckCorrected++;
759 logger.debug("ConsistencyChecker: add back untracked {}", nodeConnector);
764 for (NodeConnector nodeConnector : removeSet) {
765 removeEdge(nodeConnector, false);
768 // remove stale entries
770 for (NodeConnector nodeConnector : stagingList) {
771 if (!isEnabled(nodeConnector)) {
772 removeSet.add(nodeConnector);
773 discoveryConsistencyCheckCorrected++;
774 logger.debug("ConsistencyChecker: remove disabled {}", nodeConnector);
777 stagingList.removeAll(removeSet);
779 // Get a snapshot of all the existing switches
780 Map<Long, ISwitch> switches = this.controller.getSwitches();
781 for (ISwitch sw : switches.values()) {
782 for (OFPhysicalPort port : sw.getEnabledPorts()) {
783 Node node = NodeCreator.createOFNode(sw.getId());
784 NodeConnector nodeConnector = NodeConnectorCreator.createOFNodeConnector(port.getPortNumber(), node);
785 if (!isTracked(nodeConnector)) {
786 stagingList.add(nodeConnector);
787 discoveryConsistencyCheckCorrected++;
788 logger.debug("ConsistencyChecker: add back untracked {}", nodeConnector);
794 private void addEdge(Edge edge, Set<Property> props) {
799 NodeConnector src = edge.getTailNodeConnector();
800 NodeConnector dst = edge.getHeadNodeConnector();
801 if (!src.getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
802 holdTime.put(dst, 0);
804 agingMap.put(dst, 0);
806 elapsedTime.remove(src);
809 updateEdge(edge, UpdateType.ADDED, props);
810 logger.trace("Add edge {}", edge);
814 * Update Production Edge
817 * The Production Edge
819 * Properties associated with the edge
821 private void updateProdEdge(Edge edge, Set<Property> props) {
822 NodeConnector edgePort = edge.getHeadNodeConnector();
824 /* Do not update in case there is an existing OpenFlow link */
825 if (edgeMap.get(edgePort) != null) {
826 logger.trace("Discarded edge {} since there is an existing OF link {}", edge, edgeMap.get(edgePort));
830 /* Look for any existing Production Edge */
831 Edge oldEdge = prodMap.get(edgePort);
832 if (oldEdge == null) {
833 /* Let's add a new one */
834 addEdge(edge, props);
835 } else if (!edge.equals(oldEdge)) {
836 /* Remove the old one first */
837 removeProdEdge(oldEdge.getHeadNodeConnector());
838 /* Then add the new one */
839 addEdge(edge, props);
841 /* o/w, just reset the aging timer */
842 NodeConnector dst = edge.getHeadNodeConnector();
843 agingMap.put(dst, 0);
848 * Remove Production Edge for a given edge port
853 private void removeProdEdge(NodeConnector edgePort) {
854 agingMap.remove(edgePort);
857 Set<NodeConnector> prodKeySet = prodMap.keySet();
858 if ((prodKeySet != null) && (prodKeySet.contains(edgePort))) {
859 edge = prodMap.get(edgePort);
860 prodMap.remove(edgePort);
864 if (this.discoveryListener != null) {
865 this.discoveryListener.notifyEdge(edge, UpdateType.REMOVED, null);
867 logger.trace("Remove edge {}", edge);
871 * Remove OpenFlow edge
873 private void removeEdge(NodeConnector nodeConnector, boolean stillEnabled) {
874 holdTime.remove(nodeConnector);
875 readyListLo.remove(nodeConnector);
876 readyListHi.remove(nodeConnector);
880 if (!stagingList.contains(nodeConnector)) {
881 stagingList.add(nodeConnector);
885 stagingList.remove(nodeConnector);
889 Set<NodeConnector> edgeKeySet = edgeMap.keySet();
890 if ((edgeKeySet != null) && (edgeKeySet.contains(nodeConnector))) {
891 edge = edgeMap.get(nodeConnector);
892 edgeMap.remove(nodeConnector);
896 if (this.discoveryListener != null) {
897 this.discoveryListener.notifyEdge(edge, UpdateType.REMOVED, null);
899 logger.trace("Remove {}", nodeConnector);
902 private void removeEdge(NodeConnector nodeConnector) {
903 removeEdge(nodeConnector, isEnabled(nodeConnector));
906 private void updateEdge(Edge edge, UpdateType type, Set<Property> props) {
907 if (discoveryListener == null) {
911 this.discoveryListener.notifyEdge(edge, type, props);
913 NodeConnector src = edge.getTailNodeConnector(), dst = edge.getHeadNodeConnector();
914 if (!src.getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
915 if (type == UpdateType.ADDED) {
916 edgeMap.put(dst, edge);
922 * Save Production edge into different DB keyed by the Edge port
924 if (type == UpdateType.ADDED) {
925 prodMap.put(dst, edge);
932 private void moveToReadyListHi(NodeConnector nodeConnector) {
933 if (readyListLo.contains(nodeConnector)) {
934 readyListLo.remove(nodeConnector);
935 } else if (stagingList.contains(nodeConnector)) {
936 stagingList.remove(nodeConnector);
938 readyListHi.add(nodeConnector);
941 private void registerWithOSGIConsole() {
942 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
943 bundleContext.registerService(CommandProvider.class.getName(), this, null);
946 private int getDiscoveryConsistencyCheckInterval() {
947 return discoveryConsistencyCheckMultiple * discoveryBatchRestartTicks;
951 public String getHelp() {
952 StringBuffer help = new StringBuffer();
953 help.append("---Topology Discovery---\n");
954 help.append("\t prlh - Print readyListHi entries\n");
955 help.append("\t prll - Print readyListLo entries\n");
956 help.append("\t psl - Print stagingList entries\n");
957 help.append("\t pht - Print hold time\n");
958 help.append("\t pet - Print elapsed time\n");
959 help.append("\t ptick - Print tick time in msec\n");
960 help.append("\t pcc - Print CC info\n");
961 help.append("\t psize - Print sizes of all the lists\n");
962 help.append("\t ptm - Print timeout info\n");
963 help.append("\t ecc - Enable CC\n");
964 help.append("\t dcc - Disable CC\n");
965 help.append("\t scc [multiple] - Set/show CC multiple and interval\n");
966 help.append("\t sports [ports] - Set/show max ports per batch\n");
967 help.append("\t spause [ticks] - Set/show pause period\n");
968 help.append("\t sdi [ticks] - Set/show discovery interval in ticks\n");
969 help.append("\t addsw <swid> - Add a switch\n");
970 help.append("\t remsw <swid> - Remove a switch\n");
971 help.append("\t page - Print aging info\n");
972 help.append("\t sage - Set/Show aging time limit\n");
973 help.append("\t eage - Enable aging\n");
974 help.append("\t dage - Disable aging\n");
975 help.append("\t pthrot - Print throttling\n");
976 help.append("\t ethrot - Enable throttling\n");
977 help.append("\t dthrot - Disable throttling\n");
978 help.append("\t psnp - Print LLDP snooping\n");
979 help.append("\t esnp <all|nodeConnector> - Enable LLDP snooping\n");
980 help.append("\t dsnp <all|nodeConnector> - Disable LLDP snooping\n");
981 return help.toString();
984 private List<NodeConnector> sortList(Collection<NodeConnector> ncs) {
985 List<String> ncStrArray = new ArrayList<String>();
986 for (NodeConnector nc : ncs) {
987 ncStrArray.add(nc.toString());
989 Collections.sort(ncStrArray);
991 List<NodeConnector> sortedNodeConnectors = new ArrayList<NodeConnector>();
992 for (String ncStr : ncStrArray) {
993 sortedNodeConnectors.add(NodeConnector.fromString(ncStr));
996 return sortedNodeConnectors;
999 public void _prlh(CommandInterpreter ci) {
1000 ci.println("readyListHi\n");
1001 for (NodeConnector nodeConnector : sortList(readyListHi)) {
1002 if (nodeConnector == null) {
1005 ci.println(nodeConnector);
1007 ci.println("Total number of Node Connectors: " + readyListHi.size());
1010 public void _prll(CommandInterpreter ci) {
1011 ci.println("readyListLo\n");
1012 for (NodeConnector nodeConnector : sortList(readyListLo)) {
1013 if (nodeConnector == null) {
1016 ci.println(nodeConnector);
1018 ci.println("Total number of Node Connectors: " + readyListLo.size());
1021 public void _psl(CommandInterpreter ci) {
1022 ci.println("stagingList\n");
1023 for (NodeConnector nodeConnector : sortList(stagingList)) {
1024 if (nodeConnector == null) {
1027 ci.println(nodeConnector);
1029 ci.println("Total number of Node Connectors: " + stagingList.size());
1032 public void _pht(CommandInterpreter ci) {
1033 ci.println(" NodeConnector Last rx LLDP (sec)");
1034 for (ConcurrentMap.Entry<NodeConnector, Integer> entry: holdTime.entrySet()) {
1035 ci.println(entry.getKey() + "\t\t" + entry.getValue() * (discoveryTimerTick / 1000));
1037 ci.println("\nSize: " + holdTime.size() + "\tTimeout: " + discoveryTimeoutTicks * (discoveryTimerTick / 1000)
1041 public void _pet(CommandInterpreter ci) {
1042 ci.println(" NodeConnector Elapsed Time (sec)");
1043 for (ConcurrentMap.Entry<NodeConnector, Integer> entry: elapsedTime.entrySet()) {
1044 ci.println(entry.getKey() + "\t\t" + entry.getValue() * (discoveryTimerTick / 1000));
1046 ci.println("\nSize: " + elapsedTime.size() + "\tThreshold: " + DiscoveryPeriod.THRESHOLD.getTime() + " sec");
1049 public void _ptick(CommandInterpreter ci) {
1050 ci.println("Current timer is " + discoveryTimerTick + " msec per tick");
1053 public void _pcc(CommandInterpreter ci) {
1054 if (discoveryConsistencyCheckEnabled) {
1055 ci.println("ConsistencyChecker is currently enabled");
1057 ci.println("ConsistencyChecker is currently disabled");
1059 ci.println("Interval " + getDiscoveryConsistencyCheckInterval());
1060 ci.println("Multiple " + discoveryConsistencyCheckMultiple);
1061 ci.println("Number of times called " + discoveryConsistencyCheckCallingTimes);
1062 ci.println("Corrected count " + discoveryConsistencyCheckCorrected);
1065 public void _ptm(CommandInterpreter ci) {
1066 ci.println("Timeout " + discoveryTimeoutTicks + " ticks, " + discoveryTimerTick / 1000 + " sec per tick.");
1069 public void _psize(CommandInterpreter ci) {
1070 ci.println("readyListLo size " + readyListLo.size() + "\n" + "readyListHi size " + readyListHi.size() + "\n"
1071 + "stagingList size " + stagingList.size() + "\n" + "holdTime size " + holdTime.size() + "\n"
1072 + "edgeMap size " + edgeMap.size() + "\n" + "prodMap size " + prodMap.size() + "\n" + "agingMap size "
1073 + agingMap.size() + "\n" + "elapsedTime size " + elapsedTime.size());
1076 public void _page(CommandInterpreter ci) {
1077 if (this.discoveryAgingEnabled) {
1078 ci.println("Aging is enabled");
1080 ci.println("Aging is disabled");
1082 ci.println("Current aging time limit " + this.discoveryAgeoutTicks);
1084 ci.println(" Edge Aging ");
1085 Collection<Edge> prodSet = prodMap.values();
1086 if (prodSet == null) {
1089 for (Edge edge : prodSet) {
1090 Integer aging = agingMap.get(edge.getHeadNodeConnector());
1091 if (aging != null) {
1092 ci.println(edge + " " + aging);
1096 ci.println(" NodeConnector Edge ");
1097 Set<NodeConnector> keySet = prodMap.keySet();
1098 if (keySet == null) {
1101 for (NodeConnector nc : keySet) {
1102 ci.println(nc + " " + prodMap.get(nc));
1107 public void _sage(CommandInterpreter ci) {
1108 String val = ci.nextArgument();
1110 ci.println("Please enter aging time limit. Current value " + this.discoveryAgeoutTicks);
1114 this.discoveryAgeoutTicks = Integer.parseInt(val);
1115 } catch (Exception e) {
1116 ci.println("Please enter a valid number");
1121 public void _eage(CommandInterpreter ci) {
1122 this.discoveryAgingEnabled = true;
1123 ci.println("Aging is enabled");
1127 public void _dage(CommandInterpreter ci) {
1128 this.discoveryAgingEnabled = false;
1129 ci.println("Aging is disabled");
1133 public void _scc(CommandInterpreter ci) {
1134 String val = ci.nextArgument();
1136 ci.println("Please enter CC multiple. Current multiple " + discoveryConsistencyCheckMultiple
1137 + " (interval " + getDiscoveryConsistencyCheckInterval() + ") calling times "
1138 + discoveryConsistencyCheckCallingTimes);
1142 discoveryConsistencyCheckMultiple = Integer.parseInt(val);
1143 } catch (Exception e) {
1144 ci.println("Please enter a valid number");
1149 public void _ecc(CommandInterpreter ci) {
1150 this.discoveryConsistencyCheckEnabled = true;
1151 ci.println("ConsistencyChecker is enabled");
1155 public void _dcc(CommandInterpreter ci) {
1156 this.discoveryConsistencyCheckEnabled = false;
1157 ci.println("ConsistencyChecker is disabled");
1161 public void _psnp(CommandInterpreter ci) {
1162 if (this.discoverySnoopingEnabled) {
1163 ci.println("Discovery snooping is globally enabled");
1165 ci.println("Discovery snooping is globally disabled");
1168 ci.println("\nDiscovery snooping is locally disabled on these ports");
1169 for (NodeConnector nodeConnector : discoverySnoopingDisableList) {
1170 ci.println(nodeConnector);
1175 public void _esnp(CommandInterpreter ci) {
1176 String val = ci.nextArgument();
1179 ci.println("Usage: esnp <all|nodeConnector>");
1180 } else if (val.equalsIgnoreCase("all")) {
1181 this.discoverySnoopingEnabled = true;
1182 ci.println("Discovery snooping is globally enabled");
1184 NodeConnector nodeConnector = NodeConnector.fromString(val);
1185 if (nodeConnector != null) {
1186 discoverySnoopingDisableList.remove(nodeConnector);
1187 ci.println("Discovery snooping is locally enabled on port " + nodeConnector);
1189 ci.println("Entered invalid NodeConnector " + val);
1195 public void _dsnp(CommandInterpreter ci) {
1196 String val = ci.nextArgument();
1199 ci.println("Usage: dsnp <all|nodeConnector>");
1200 } else if (val.equalsIgnoreCase("all")) {
1201 this.discoverySnoopingEnabled = false;
1202 ci.println("Discovery snooping is globally disabled");
1204 NodeConnector nodeConnector = NodeConnector.fromString(val);
1205 if (nodeConnector != null) {
1206 discoverySnoopingDisableList.add(nodeConnector);
1207 ci.println("Discovery snooping is locally disabled on port " + nodeConnector);
1209 ci.println("Entered invalid NodeConnector " + val);
1215 public void _spause(CommandInterpreter ci) {
1216 String val = ci.nextArgument();
1217 String out = "Please enter pause period less than " + discoveryBatchRestartTicks + ". Current pause period is "
1218 + discoveryBatchPausePeriod + " ticks, pause at " + discoveryBatchPauseTicks + " ticks, "
1219 + discoveryTimerTick / 1000 + " sec per tick.";
1223 int pause = Integer.parseInt(val);
1224 if (pause < discoveryBatchRestartTicks) {
1225 discoveryBatchPausePeriod = pause;
1226 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
1229 } catch (Exception e) {
1236 public void _sdi(CommandInterpreter ci) {
1237 String val = ci.nextArgument();
1238 String out = "Please enter discovery interval in ticks. Current value is " + discoveryBatchRestartTicks + " ticks, "
1239 + discoveryTimerTick / 1000 + " sec per tick.";
1243 int ticks = Integer.parseInt(val);
1244 DiscoveryPeriod.INTERVAL.setTick(ticks);
1245 discoveryBatchRestartTicks = getDiscoveryInterval();
1246 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
1247 discoveryTimeoutTicks = getDiscoveryTimeout();
1249 } catch (Exception e) {
1255 public void _sports(CommandInterpreter ci) {
1256 String val = ci.nextArgument();
1258 ci.println("Please enter max ports per batch. Current value is " + discoveryBatchMaxPorts);
1262 discoveryBatchMaxPorts = Integer.parseInt(val);
1263 } catch (Exception e) {
1264 ci.println("Please enter a valid number");
1269 public void _addsw(CommandInterpreter ci) {
1270 String val = ci.nextArgument();
1273 sid = Long.parseLong(val);
1274 Node node = NodeCreator.createOFNode(sid);
1276 } catch (Exception e) {
1277 ci.println("Please enter a valid number");
1282 public void _remsw(CommandInterpreter ci) {
1283 String val = ci.nextArgument();
1286 sid = Long.parseLong(val);
1287 Node node = NodeCreator.createOFNode(sid);
1288 removeDiscovery(node);
1289 } catch (Exception e) {
1290 ci.println("Please enter a valid number");
1295 public void _pthrot(CommandInterpreter ci) {
1296 if (this.throttling) {
1297 ci.println("Throttling is enabled");
1299 ci.println("Throttling is disabled");
1303 public void _ethrot(CommandInterpreter ci) {
1304 this.throttling = true;
1305 ci.println("Throttling is enabled");
1309 public void _dthrot(CommandInterpreter ci) {
1310 this.throttling = false;
1311 ci.println("Throttling is disabled");
1316 public void updateNode(Node node, UpdateType type, Set<Property> props) {
1319 addNode(node, props);
1330 public void updateNodeConnector(NodeConnector nodeConnector, UpdateType type, Set<Property> props) {
1331 Config config = null;
1333 boolean enabled = false;
1335 for (Property prop : props) {
1336 if (prop.getName().equals(Config.ConfigPropName)) {
1337 config = (Config) prop;
1338 } else if (prop.getName().equals(State.StatePropName)) {
1339 state = (State) prop;
1342 enabled = ((config != null) && (config.getValue() == Config.ADMIN_UP) && (state != null) && (state.getValue() == State.EDGE_UP));
1347 addDiscovery(nodeConnector);
1348 logger.trace("ADDED enabled {}", nodeConnector);
1350 logger.trace("ADDED disabled {}", nodeConnector);
1355 addDiscovery(nodeConnector);
1356 logger.trace("CHANGED enabled {}", nodeConnector);
1358 removeDiscovery(nodeConnector);
1359 logger.trace("CHANGED disabled {}", nodeConnector);
1363 removeDiscovery(nodeConnector);
1364 logger.trace("REMOVED enabled {}", nodeConnector);
1371 public void addNode(Node node, Set<Property> props) {
1379 public void removeNode(Node node) {
1384 removeDiscovery(node);
1387 void setController(IController s) {
1388 this.controller = s;
1391 void unsetController(IController s) {
1392 if (this.controller == s) {
1393 this.controller = null;
1397 public void setInventoryProvider(IInventoryProvider service) {
1398 this.inventoryProvider = service;
1401 public void unsetInventoryProvider(IInventoryProvider service) {
1402 this.inventoryProvider = null;
1405 public void setIDataPacketMux(IDataPacketMux service) {
1406 this.iDataPacketMux = service;
1409 public void unsetIDataPacketMux(IDataPacketMux service) {
1410 if (this.iDataPacketMux == service) {
1411 this.iDataPacketMux = null;
1415 void setDiscoveryListener(IDiscoveryListener s) {
1416 this.discoveryListener = s;
1419 void unsetDiscoveryListener(IDiscoveryListener s) {
1420 if (this.discoveryListener == s) {
1421 this.discoveryListener = null;
1425 void setIPluginOutConnectionService(IPluginOutConnectionService s) {
1426 connectionOutService = s;
1429 void unsetIPluginOutConnectionService(IPluginOutConnectionService s) {
1430 if (connectionOutService == s) {
1431 connectionOutService = null;
1435 private void initDiscoveryPacket() {
1436 // Create LLDP ChassisID TLV
1437 chassisIdTlv = new LLDPTLV();
1438 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
1440 // Create LLDP PortID TLV
1441 portIdTlv = new LLDPTLV();
1442 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
1444 // Create LLDP TTL TLV
1445 byte[] ttl = new byte[] { (byte) 0, (byte) 120 };
1446 ttlTlv = new LLDPTLV();
1447 ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue()).setLength((short) ttl.length).setValue(ttl);
1449 customTlv = new LLDPTLV();
1453 * Function called by the dependency manager when all the required
1454 * dependencies are satisfied
1458 logger.trace("Init called");
1460 transmitQ = new LinkedBlockingQueue<NodeConnector>();
1462 readyListHi = new CopyOnWriteArrayList<NodeConnector>();
1463 readyListLo = new CopyOnWriteArrayList<NodeConnector>();
1464 stagingList = new CopyOnWriteArrayList<NodeConnector>();
1465 holdTime = new ConcurrentHashMap<NodeConnector, Integer>();
1466 elapsedTime = new ConcurrentHashMap<NodeConnector, Integer>();
1467 edgeMap = new ConcurrentHashMap<NodeConnector, Edge>();
1468 agingMap = new ConcurrentHashMap<NodeConnector, Integer>();
1469 prodMap = new ConcurrentHashMap<NodeConnector, Edge>();
1470 discoverySnoopingDisableList = new CopyOnWriteArrayList<NodeConnector>();
1472 discoveryBatchRestartTicks = getDiscoveryInterval();
1473 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
1474 discoveryTimeoutTicks = getDiscoveryTimeout();
1475 discoveryThresholdTicks = getDiscoveryThreshold();
1476 discoveryAgeoutTicks = getDiscoveryAgeout();
1477 discoveryConsistencyCheckTickCount = discoveryBatchPauseTicks;
1478 discoveryBatchMaxPorts = getDiscoveryBatchMaxPorts();
1480 discoveryTimer = new Timer("DiscoveryService");
1481 discoveryTimerTask = new DiscoveryTimerTask();
1483 transmitThread = new Thread(new DiscoveryTransmit(transmitQ));
1485 initDiscoveryPacket();
1487 registerWithOSGIConsole();
1491 * Function called by the dependency manager when at least one dependency
1492 * become unsatisfied or when the component is shutting down because for
1493 * example bundle is being stopped.
1505 discoveryTimer = null;
1506 discoveryTimerTask = null;
1507 transmitThread = null;
1511 * Function called by dependency manager after "init ()" is called and after
1512 * the services provided by the class are registered in the service registry
1516 discoveryTimer.schedule(discoveryTimerTask, discoveryTimerTick, discoveryTimerTick);
1517 transmitThread.start();
1521 * Function called after registering the service in OSGi service registry.
1524 /* get a snapshot of all the existing switches */
1529 * Function called by the dependency manager before the services exported by
1530 * the component are unregistered, this will be followed by a "destroy ()"
1535 shuttingDown = true;
1536 discoveryTimer.cancel();
1537 transmitThread.interrupt();
1541 public void tagUpdated(String containerName, Node n, short oldTag, short newTag, UpdateType t) {
1545 public void containerFlowUpdated(String containerName, ContainerFlow previousFlow, ContainerFlow currentFlow,
1550 public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType t) {
1553 moveToReadyListHi(p);
1561 public void containerModeUpdated(UpdateType t) {
1565 private byte[] getSourceMACFromNodeID(String nodeId) {
1566 byte[] cid = HexEncode.bytesFromHexString(nodeId);
1567 byte[] sourceMac = new byte[6];
1568 int pos = cid.length - sourceMac.length;
1571 System.arraycopy(cid, pos, sourceMac, 0, sourceMac.length);
1577 private int getDiscoveryTicks(DiscoveryPeriod dp, String val) {
1584 dp.setTime(Integer.parseInt(val));
1585 } catch (Exception e) {
1589 return dp.getTick();
1593 * This method returns the interval which determines how often the discovery
1594 * packets will be sent.
1596 * @return The discovery interval in ticks
1598 private int getDiscoveryInterval() {
1599 String intvl = System.getProperty("of.discoveryInterval");
1600 return getDiscoveryTicks(DiscoveryPeriod.INTERVAL, intvl);
1604 * This method returns the timeout value in receiving subsequent discovery packets on a port.
1606 * @return The discovery timeout in ticks
1608 private int getDiscoveryTimeout() {
1609 String val = System.getProperty("of.discoveryTimeoutMultiple");
1614 multiple = Integer.parseInt(val);
1615 } catch (Exception e) {
1618 return getDiscoveryInterval() * multiple + 3;
1622 * This method returns the user configurable threshold value
1624 * @return The discovery threshold value in ticks
1626 private int getDiscoveryThreshold() {
1627 String val = System.getProperty("of.discoveryThreshold");
1628 return getDiscoveryTicks(DiscoveryPeriod.THRESHOLD, val);
1632 * This method returns the discovery entry aging time in ticks.
1634 * @return The aging time in ticks
1636 private int getDiscoveryAgeout() {
1637 return getDiscoveryTicks(DiscoveryPeriod.AGEOUT, null);
1641 * This method returns the pause interval
1643 * @return The pause interval in ticks
1645 private int getDiscoveryPauseInterval() {
1646 if (discoveryBatchRestartTicks > discoveryBatchPausePeriod) {
1647 return discoveryBatchRestartTicks - discoveryBatchPausePeriod;
1649 return discoveryBatchRestartTicks - 1;
1654 * This method returns the user configurable maximum number of ports handled
1655 * in one discovery batch.
1657 * @return The maximum number of ports
1659 private int getDiscoveryBatchMaxPorts() {
1660 String val = System.getProperty("of.discoveryBatchMaxPorts");
1665 ports = Integer.parseInt(val);
1666 } catch (Exception e) {