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.controller.protocol_plugin.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.opendaylight.controller.protocol_plugin.openflow.IDataPacketListen;
30 import org.opendaylight.controller.protocol_plugin.openflow.IDataPacketMux;
31 import org.opendaylight.controller.protocol_plugin.openflow.IDiscoveryListener;
32 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryProvider;
33 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExternalListener;
34 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
35 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
36 import org.openflow.protocol.OFPhysicalPort;
37 import org.osgi.framework.BundleContext;
38 import org.osgi.framework.FrameworkUtil;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
43 import org.opendaylight.controller.sal.core.Config;
44 import org.opendaylight.controller.sal.core.ConstructionException;
45 import org.opendaylight.controller.sal.core.Edge;
46 import org.opendaylight.controller.sal.core.ContainerFlow;
47 import org.opendaylight.controller.sal.core.IContainerListener;
48 import org.opendaylight.controller.sal.core.Node;
49 import org.opendaylight.controller.sal.core.NodeConnector;
50 import org.opendaylight.controller.sal.core.Property;
51 import org.opendaylight.controller.sal.core.State;
52 import org.opendaylight.controller.sal.core.UpdateType;
53 import org.opendaylight.controller.sal.packet.Ethernet;
54 import org.opendaylight.controller.sal.packet.LLDP;
55 import org.opendaylight.controller.sal.packet.LLDPTLV;
56 import org.opendaylight.controller.sal.packet.LinkEncap;
57 import org.opendaylight.controller.sal.packet.PacketResult;
58 import org.opendaylight.controller.sal.packet.RawPacket;
59 import org.opendaylight.controller.sal.utils.EtherTypes;
60 import org.opendaylight.controller.sal.utils.HexEncode;
61 import org.opendaylight.controller.sal.utils.NetUtils;
62 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
63 import org.opendaylight.controller.sal.utils.NodeCreator;
66 * The class describes neighbor discovery service for an OpenFlow network.
68 public class DiscoveryService implements IInventoryShimExternalListener, IDataPacketListen, IContainerListener,
70 private static Logger logger = LoggerFactory.getLogger(DiscoveryService.class);
71 private IController controller = null;
72 private IDiscoveryListener discoveryListener = null;
73 private IInventoryProvider inventoryProvider = null;
74 private IDataPacketMux iDataPacketMux = null;
75 // High priority list containing newly added ports which will be served first
76 private List<NodeConnector> readyListHi = null;
77 // List containing all the ports which will be served periodically
78 private List<NodeConnector> readyListLo = null;
79 // Staging area during quiet period
80 private List<NodeConnector> stagingList = null;
81 // Wait for next discovery packet. The map contains the time elapsed since
82 // the last received LLDP frame on each node connector
83 private ConcurrentMap<NodeConnector, Integer> holdTime = null;
84 // Allow one more retry for newly added ports. This map contains the time
85 // period elapsed since last discovery pkt transmission on the port.
86 private ConcurrentMap<NodeConnector, Integer> elapsedTime = null;
87 // OpenFlow edges keyed by head connector
88 private ConcurrentMap<NodeConnector, Edge> edgeMap = null;
89 // The map contains aging entry keyed by head connector of Production edge
90 private ConcurrentMap<NodeConnector, Integer> agingMap = null;
91 // Production edges keyed by head connector
92 private ConcurrentMap<NodeConnector, Edge> prodMap = null;
94 private Timer discoveryTimer;
95 private DiscoveryTimerTask discoveryTimerTask;
96 private final static long discoveryTimerTick = 2L * 1000; // per tick in msec
97 private int discoveryTimerTickCount = 0; // main tick counter
98 // Max # of ports handled in one batch
99 private int discoveryBatchMaxPorts;
100 // Periodically restart batching process
101 private int discoveryBatchRestartTicks;
102 private int discoveryBatchPausePeriod = 2;
103 // Pause after this point
104 private int discoveryBatchPauseTicks;
105 private int discoveryTimeoutTicks;
106 private int discoveryThresholdTicks;
107 private int discoveryAgeoutTicks;
108 // multiple of discoveryBatchRestartTicks
109 private int discoveryConsistencyCheckMultiple = 2;
111 private int discoveryConsistencyCheckTickCount;
112 // # of times CC gets called
113 private int discoveryConsistencyCheckCallingTimes = 0;
114 // # of cases CC corrected
115 private int discoveryConsistencyCheckCorrected = 0;
116 // Enable or disable CC
117 private boolean discoveryConsistencyCheckEnabled = true;
118 // Enable or disable aging
119 private boolean discoveryAgingEnabled = true;
120 // Global flag to enable or disable LLDP snooping
121 private boolean discoverySnoopingEnabled = true;
122 // The list of ports that will not do LLDP snooping
123 private List<NodeConnector> discoverySnoopingDisableList;
124 private BlockingQueue<NodeConnector> transmitQ;
125 private Thread transmitThread;
126 private Boolean throttling = false; // if true, no more batching.
127 private volatile Boolean shuttingDown = false;
129 private LLDPTLV chassisIdTlv, portIdTlv, ttlTlv, customTlv;
130 private IPluginOutConnectionService connectionOutService;
132 class DiscoveryTransmit implements Runnable {
133 private final BlockingQueue<NodeConnector> transmitQ;
135 DiscoveryTransmit(BlockingQueue<NodeConnector> transmitQ) {
136 this.transmitQ = transmitQ;
143 NodeConnector nodeConnector = transmitQ.take();
144 RawPacket outPkt = createDiscoveryPacket(nodeConnector);
145 sendDiscoveryPacket(nodeConnector, outPkt);
146 nodeConnector = null;
147 } catch (InterruptedException e1) {
148 logger.warn("DiscoveryTransmit interupted", e1.getMessage());
152 } catch (Exception e2) {
153 logger.error("", e2);
159 class DiscoveryTimerTask extends TimerTask {
164 doConsistencyCheck();
169 public enum DiscoveryPeriod {
174 private int time; // sec
175 private int tick; // tick
177 DiscoveryPeriod(int time) {
179 this.tick = time2Tick(time);
182 public int getTime() {
186 public void setTime(int time) {
188 this.tick = time2Tick(time);
191 public int getTick() {
195 public void setTick(int tick) {
196 this.time = tick2Time(tick);
200 private int time2Tick(int time) {
201 return (int) (time / (discoveryTimerTick / 1000));
204 private int tick2Time(int tick) {
205 return (int) (tick * (discoveryTimerTick / 1000));
209 private RawPacket createDiscoveryPacket(NodeConnector nodeConnector) {
210 String nodeId = HexEncode.longToHexString((Long) nodeConnector.getNode().getID());
212 // Create LLDP ChassisID TLV
213 byte[] cidValue = LLDPTLV.createChassisIDTLVValue(nodeId);
214 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue()).setLength((short) cidValue.length)
217 // Create LLDP PortID TLV
218 String portId = nodeConnector.getNodeConnectorIDString();
219 byte[] pidValue = LLDPTLV.createPortIDTLVValue(portId);
220 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue()).setLength((short) pidValue.length).setValue(pidValue);
222 // Create LLDP Custom TLV
223 byte[] customValue = LLDPTLV.createCustomTLVValue(nodeConnector.toString());
224 customTlv.setType(LLDPTLV.TLVType.Custom.getValue()).setLength((short) customValue.length)
225 .setValue(customValue);
227 // Create LLDP Custom Option list
228 List<LLDPTLV> customList = new ArrayList<LLDPTLV>();
229 customList.add(customTlv);
231 // Create discovery pkt
232 LLDP discoveryPkt = new LLDP();
233 discoveryPkt.setChassisId(chassisIdTlv).setPortId(portIdTlv).setTtl(ttlTlv).setOptionalTLVList(customList);
235 RawPacket rawPkt = null;
237 // Create ethernet pkt
238 byte[] sourceMac = getSourceMACFromNodeID(nodeId);
239 Ethernet ethPkt = new Ethernet();
240 ethPkt.setSourceMACAddress(sourceMac).setDestinationMACAddress(LLDP.LLDPMulticastMac)
241 .setEtherType(EtherTypes.LLDP.shortValue()).setPayload(discoveryPkt);
243 byte[] data = ethPkt.serialize();
244 rawPkt = new RawPacket(data);
245 rawPkt.setOutgoingNodeConnector(nodeConnector);
246 } catch (ConstructionException cex) {
247 logger.warn("RawPacket creation caught exception {}", cex.getMessage());
248 } catch (Exception e) {
249 logger.error("Failed to serialize the LLDP packet: " + e);
255 private void sendDiscoveryPacket(NodeConnector nodeConnector, RawPacket outPkt) {
256 if (nodeConnector == null) {
257 logger.debug("Can not send discovery packet out since nodeConnector is null");
261 if (!connectionOutService.isLocal(nodeConnector.getNode())) {
262 logger.debug("Discoery packets will not be sent to {} in a non-master controller", nodeConnector.toString());
266 if (outPkt == null) {
267 logger.debug("Can not send discovery packet out since outPkt is null");
271 long sid = (Long) nodeConnector.getNode().getID();
272 ISwitch sw = controller.getSwitches().get(sid);
275 logger.debug("Can not send discovery packet out since switch {} is null", sid);
279 if (!sw.isOperational()) {
280 logger.debug("Can not send discovery packet out since switch {} is not operational", sw);
284 if (this.iDataPacketMux == null) {
285 logger.debug("Can not send discovery packet out since DataPacket service is not available");
289 logger.trace("Sending topology discovery pkt thru {}", nodeConnector);
290 this.iDataPacketMux.transmitDataPacket(outPkt);
294 public PacketResult receiveDataPacket(RawPacket inPkt) {
296 logger.debug("Ignoring null packet");
297 return PacketResult.IGNORED;
300 byte[] data = inPkt.getPacketData();
301 if (data.length <= 0) {
302 logger.trace("Ignoring zero length packet");
303 return PacketResult.IGNORED;
306 if (!inPkt.getEncap().equals(LinkEncap.ETHERNET)) {
307 logger.trace("Ignoring non ethernet packet");
308 return PacketResult.IGNORED;
311 NodeConnector nodeConnector = inPkt.getIncomingNodeConnector();
312 if (((Short) nodeConnector.getID()).equals(NodeConnector.SPECIALNODECONNECTORID)) {
313 logger.trace("Ignoring ethernet packet received on special port: "
314 + inPkt.getIncomingNodeConnector().toString());
315 return PacketResult.IGNORED;
318 if (!connectionOutService.isLocal(nodeConnector.getNode())) {
319 logger.debug("Discoery packets will not be processed from {} in a non-master controller", nodeConnector.toString());
320 return PacketResult.IGNORED;
323 Ethernet ethPkt = new Ethernet();
325 ethPkt.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
326 } catch (Exception e) {
327 logger.warn("Failed to decode LLDP packet from {}: {}", inPkt.getIncomingNodeConnector(), e);
328 return PacketResult.IGNORED;
331 if (ethPkt.getPayload() instanceof LLDP) {
332 NodeConnector dst = inPkt.getIncomingNodeConnector();
333 if (isEnabled(dst)) {
334 if (!processDiscoveryPacket(dst, ethPkt)) {
335 // Snoop the discovery pkt if not generated from us
336 snoopDiscoveryPacket(dst, ethPkt);
338 return PacketResult.CONSUME;
341 return PacketResult.IGNORED;
345 * Snoop incoming discovery frames generated by the production network
348 private void snoopDiscoveryPacket(NodeConnector dstNodeConnector, Ethernet ethPkt) {
349 if (!this.discoverySnoopingEnabled || discoverySnoopingDisableList.contains(dstNodeConnector)) {
350 logger.trace("Discarded received discovery packet on {} since snooping is turned off", dstNodeConnector);
354 if ((dstNodeConnector == null) || (ethPkt == null)) {
355 logger.trace("Quit snooping discovery packet: Null node connector or packet");
359 LLDP lldp = (LLDP) ethPkt.getPayload();
362 String nodeId = LLDPTLV.getHexStringValue(lldp.getChassisId().getValue(), lldp.getChassisId().getLength());
363 String portId = LLDPTLV.getStringValue(lldp.getPortId().getValue(), lldp.getPortId().getLength());
364 byte[] systemNameBytes = null;
365 // get system name if present in the LLDP pkt
366 for (LLDPTLV lldptlv : lldp.getOptionalTLVList()) {
367 if (lldptlv.getType() == LLDPTLV.TLVType.SystemName.getValue()) {
368 systemNameBytes = lldptlv.getValue();
372 String nodeName = (systemNameBytes == null) ? nodeId
373 : new String(systemNameBytes, Charset.defaultCharset());
374 Node srcNode = new Node(Node.NodeIDType.PRODUCTION, nodeName);
375 NodeConnector srcNodeConnector = NodeConnectorCreator.createNodeConnector(
376 NodeConnector.NodeConnectorIDType.PRODUCTION, portId, srcNode);
379 Set<Property> props = null;
380 edge = new Edge(srcNodeConnector, dstNodeConnector);
381 props = getProps(dstNodeConnector);
383 updateProdEdge(edge, props);
384 } catch (Exception e) {
385 logger.warn("Caught exception ", e);
390 * Handle discovery frames generated by our controller
392 * @return true if it's a success
394 private boolean processDiscoveryPacket(NodeConnector dstNodeConnector, Ethernet ethPkt) {
395 if ((dstNodeConnector == null) || (ethPkt == null)) {
396 logger.trace("Ignoring processing of discovery packet: Null node connector or packet");
400 logger.trace("Handle discovery packet {} from {}", ethPkt, dstNodeConnector);
402 LLDP lldp = (LLDP) ethPkt.getPayload();
404 List<LLDPTLV> optionalTLVList = lldp.getOptionalTLVList();
405 if (optionalTLVList == null) {
406 logger.info("The discovery packet with null custom option from {}", dstNodeConnector);
411 NodeConnector srcNodeConnector = null;
412 for (LLDPTLV lldptlv : lldp.getOptionalTLVList()) {
413 if (lldptlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
414 String ncString = LLDPTLV.getCustomString(lldptlv.getValue(), lldptlv.getLength());
415 srcNodeConnector = NodeConnector.fromString(ncString);
416 if (srcNodeConnector != null) {
417 srcNode = srcNodeConnector.getNode();
422 if ((srcNode == null) || (srcNodeConnector == null)) {
423 logger.trace("Received non-controller generated discovery packet from {}", dstNodeConnector);
427 // push it out to Topology
429 Set<Property> props = null;
431 edge = new Edge(srcNodeConnector, dstNodeConnector);
432 props = getProps(dstNodeConnector);
433 } catch (ConstructionException e) {
434 logger.error("Caught exception ", e);
436 addEdge(edge, props);
438 logger.trace("Received discovery packet for Edge {}", edge);
443 public Map<String, Property> getPropMap(NodeConnector nodeConnector) {
444 if (nodeConnector == null) {
448 if (inventoryProvider == null) {
452 Map<NodeConnector, Map<String, Property>> props = inventoryProvider.getNodeConnectorProps(false);
457 return props.get(nodeConnector);
460 public Property getProp(NodeConnector nodeConnector, String propName) {
461 Map<String, Property> propMap = getPropMap(nodeConnector);
462 if (propMap == null) {
466 Property prop = propMap.get(propName);
470 public Set<Property> getProps(NodeConnector nodeConnector) {
471 Map<String, Property> propMap = getPropMap(nodeConnector);
472 if (propMap == null) {
476 Set<Property> props = new HashSet<Property>(propMap.values());
480 private boolean isEnabled(NodeConnector nodeConnector) {
481 if (nodeConnector == null) {
485 Config config = (Config) getProp(nodeConnector, Config.ConfigPropName);
486 State state = (State) getProp(nodeConnector, State.StatePropName);
487 return ((config != null) && (config.getValue() == Config.ADMIN_UP) && (state != null) && (state.getValue() == State.EDGE_UP));
490 private boolean isTracked(NodeConnector nodeConnector) {
491 if (readyListHi.contains(nodeConnector)) {
495 if (readyListLo.contains(nodeConnector)) {
499 if (holdTime.keySet().contains(nodeConnector)) {
503 if (stagingList.contains(nodeConnector)) {
510 private Set<NodeConnector> getWorkingSet() {
511 Set<NodeConnector> workingSet = new HashSet<NodeConnector>();
512 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
514 for (NodeConnector nodeConnector : readyListHi) {
515 if (isOverLimit(workingSet.size())) {
519 workingSet.add(nodeConnector);
520 removeSet.add(nodeConnector);
522 // Put it in the map and start the timer. It may need retry.
523 elapsedTime.put(nodeConnector, 0);
525 readyListHi.removeAll(removeSet);
528 for (NodeConnector nodeConnector : readyListLo) {
529 if (isOverLimit(workingSet.size())) {
533 workingSet.add(nodeConnector);
534 removeSet.add(nodeConnector);
536 readyListLo.removeAll(removeSet);
541 private Boolean isOverLimit(int size) {
542 return ((size >= discoveryBatchMaxPorts) && !throttling);
545 private void addDiscovery() {
546 Map<Long, ISwitch> switches = controller.getSwitches();
547 Set<Long> sidSet = switches.keySet();
548 if (sidSet == null) {
551 for (Long sid : sidSet) {
552 Node node = NodeCreator.createOFNode(sid);
557 private void addDiscovery(Node node) {
558 Map<Long, ISwitch> switches = controller.getSwitches();
559 ISwitch sw = switches.get(node.getID());
560 List<OFPhysicalPort> ports = sw.getEnabledPorts();
564 for (OFPhysicalPort port : ports) {
565 NodeConnector nodeConnector = NodeConnectorCreator.createOFNodeConnector(port.getPortNumber(), node);
566 if (!readyListHi.contains(nodeConnector)) {
567 readyListHi.add(nodeConnector);
572 private void addDiscovery(NodeConnector nodeConnector) {
573 if (isTracked(nodeConnector)) {
577 readyListHi.add(nodeConnector);
580 private void removeNodeConnector(NodeConnector nodeConnector) {
581 readyListLo.remove(nodeConnector);
582 readyListHi.remove(nodeConnector);
583 stagingList.remove(nodeConnector);
584 holdTime.remove(nodeConnector);
585 elapsedTime.remove(nodeConnector);
588 private Set<NodeConnector> getRemoveSet(Collection<NodeConnector> c, Node node) {
589 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
593 for (NodeConnector nodeConnector : c) {
594 if (node.equals(nodeConnector.getNode())) {
595 removeSet.add(nodeConnector);
601 private void removeDiscovery(Node node) {
602 Set<NodeConnector> removeSet;
604 removeSet = getRemoveSet(edgeMap.keySet(), node);
605 NodeConnector peerConnector;
607 for (NodeConnector nodeConnector : removeSet) {
608 // get the peer for fast removal of the edge in reverse direction
609 peerConnector = null;
610 edge1 = edgeMap.get(nodeConnector);
612 edge2 = edgeMap.get(edge1.getTailNodeConnector());
613 if ((edge2 != null) && node.equals(edge2.getTailNodeConnector().getNode())) {
614 peerConnector = edge2.getHeadNodeConnector();
618 removeEdge(nodeConnector, false);
619 removeEdge(peerConnector, isEnabled(peerConnector));
622 removeSet = getRemoveSet(prodMap.keySet(), node);
623 for (NodeConnector nodeConnector : removeSet) {
624 removeProdEdge(nodeConnector);
627 removeSet = getRemoveSet(readyListHi, node);
628 readyListHi.removeAll(removeSet);
630 removeSet = getRemoveSet(readyListLo, node);
631 readyListLo.removeAll(removeSet);
633 removeSet = getRemoveSet(stagingList, node);
634 stagingList.removeAll(removeSet);
636 removeSet = getRemoveSet(holdTime.keySet(), node);
637 for (NodeConnector nodeConnector : removeSet) {
638 holdTime.remove(nodeConnector);
641 removeSet = getRemoveSet(elapsedTime.keySet(), node);
642 for (NodeConnector nodeConnector : removeSet) {
643 elapsedTime.remove(nodeConnector);
647 private void removeDiscovery(NodeConnector nodeConnector) {
648 removeNodeConnector(nodeConnector);
649 removeEdge(nodeConnector, false);
650 removeProdEdge(nodeConnector);
653 private void checkTimeout() {
654 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
657 Set<NodeConnector> monitorSet = holdTime.keySet();
658 if (monitorSet != null) {
659 for (NodeConnector nodeConnector : monitorSet) {
660 ticks = holdTime.get(nodeConnector);
661 holdTime.put(nodeConnector, ++ticks);
662 if (ticks >= discoveryTimeoutTicks) {
664 removeSet.add(nodeConnector);
665 logger.trace("Discovery timeout {}", nodeConnector);
670 for (NodeConnector nodeConnector : removeSet) {
671 removeEdge(nodeConnector);
674 Set<NodeConnector> retrySet = new HashSet<NodeConnector>();
675 Set<NodeConnector> ncSet = elapsedTime.keySet();
676 if ((ncSet != null) && (ncSet.size() > 0)) {
677 for (NodeConnector nodeConnector : ncSet) {
678 ticks = elapsedTime.get(nodeConnector);
679 elapsedTime.put(nodeConnector, ++ticks);
680 if (ticks >= discoveryThresholdTicks) {
681 retrySet.add(nodeConnector);
685 for (NodeConnector nodeConnector : retrySet) {
686 // Allow one more retry
687 elapsedTime.remove(nodeConnector);
688 if (connectionOutService.isLocal(nodeConnector.getNode())) {
689 transmitQ.add(nodeConnector);
695 private void checkAging() {
696 if (!discoveryAgingEnabled) {
700 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
703 Set<NodeConnector> agingSet = agingMap.keySet();
704 if (agingSet != null) {
705 for (NodeConnector nodeConnector : agingSet) {
706 ticks = agingMap.get(nodeConnector);
707 agingMap.put(nodeConnector, ++ticks);
708 if (ticks > discoveryAgeoutTicks) {
710 removeSet.add(nodeConnector);
711 logger.trace("Discovery age out {}", nodeConnector);
716 for (NodeConnector nodeConnector : removeSet) {
717 removeProdEdge(nodeConnector);
721 private void doDiscovery() {
722 if (++discoveryTimerTickCount <= discoveryBatchPauseTicks) {
723 for (NodeConnector nodeConnector : getWorkingSet()) {
724 if (connectionOutService.isLocal(nodeConnector.getNode())) {
725 transmitQ.add(nodeConnector);
726 // Move to staging area after it's served
727 if (!stagingList.contains(nodeConnector)) {
728 stagingList.add(nodeConnector);
732 } else if (discoveryTimerTickCount >= discoveryBatchRestartTicks) {
733 discoveryTimerTickCount = 0;
734 for (NodeConnector nodeConnector : stagingList) {
735 if (!readyListLo.contains(nodeConnector)) {
736 readyListLo.add(nodeConnector);
739 stagingList.removeAll(readyListLo);
743 private void doConsistencyCheck() {
744 if (!discoveryConsistencyCheckEnabled) {
748 if (++discoveryConsistencyCheckTickCount % getDiscoveryConsistencyCheckInterval() != 0) {
752 discoveryConsistencyCheckCallingTimes++;
754 Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
755 Set<NodeConnector> ncSet = edgeMap.keySet();
759 for (NodeConnector nodeConnector : ncSet) {
760 if (!isEnabled(nodeConnector)) {
761 removeSet.add(nodeConnector);
762 discoveryConsistencyCheckCorrected++;
763 logger.debug("ConsistencyChecker: remove disabled {}", nodeConnector);
767 if (!isTracked(nodeConnector)) {
768 stagingList.add(nodeConnector);
769 discoveryConsistencyCheckCorrected++;
770 logger.debug("ConsistencyChecker: add back untracked {}", nodeConnector);
775 for (NodeConnector nodeConnector : removeSet) {
776 removeEdge(nodeConnector, false);
779 // remove stale entries
781 for (NodeConnector nodeConnector : stagingList) {
782 if (!isEnabled(nodeConnector)) {
783 removeSet.add(nodeConnector);
784 discoveryConsistencyCheckCorrected++;
785 logger.debug("ConsistencyChecker: remove disabled {}", nodeConnector);
788 stagingList.removeAll(removeSet);
790 // Get a snapshot of all the existing switches
791 Map<Long, ISwitch> switches = this.controller.getSwitches();
792 for (ISwitch sw : switches.values()) {
793 for (OFPhysicalPort port : sw.getEnabledPorts()) {
794 Node node = NodeCreator.createOFNode(sw.getId());
795 NodeConnector nodeConnector = NodeConnectorCreator.createOFNodeConnector(port.getPortNumber(), node);
796 if (!isTracked(nodeConnector)) {
797 stagingList.add(nodeConnector);
798 discoveryConsistencyCheckCorrected++;
799 logger.debug("ConsistencyChecker: add back untracked {}", nodeConnector);
805 private void addEdge(Edge edge, Set<Property> props) {
810 NodeConnector src = edge.getTailNodeConnector();
811 NodeConnector dst = edge.getHeadNodeConnector();
812 if (!src.getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
813 holdTime.put(dst, 0);
815 agingMap.put(dst, 0);
817 elapsedTime.remove(src);
819 // fast discovery of the edge in reverse direction
820 if (!edgeMap.containsKey(dst) && !readyListHi.contains(dst) && !elapsedTime.keySet().contains(dst)) {
821 moveToReadyListHi(dst);
825 updateEdge(edge, UpdateType.ADDED, props);
826 logger.trace("Add edge {}", edge);
830 * Update Production Edge
833 * The Production Edge
835 * Properties associated with the edge
837 private void updateProdEdge(Edge edge, Set<Property> props) {
838 NodeConnector edgePort = edge.getHeadNodeConnector();
840 /* Do not update in case there is an existing OpenFlow link */
841 if (edgeMap.get(edgePort) != null) {
842 logger.trace("Discarded edge {} since there is an existing OF link {}", edge, edgeMap.get(edgePort));
846 /* Look for any existing Production Edge */
847 Edge oldEdge = prodMap.get(edgePort);
848 if (oldEdge == null) {
849 /* Let's add a new one */
850 addEdge(edge, props);
851 } else if (!edge.equals(oldEdge)) {
852 /* Remove the old one first */
853 removeProdEdge(oldEdge.getHeadNodeConnector());
854 /* Then add the new one */
855 addEdge(edge, props);
857 /* o/w, just reset the aging timer */
858 NodeConnector dst = edge.getHeadNodeConnector();
859 agingMap.put(dst, 0);
864 * Remove Production Edge for a given edge port
869 private void removeProdEdge(NodeConnector edgePort) {
870 agingMap.remove(edgePort);
873 Set<NodeConnector> prodKeySet = prodMap.keySet();
874 if ((prodKeySet != null) && (prodKeySet.contains(edgePort))) {
875 edge = prodMap.get(edgePort);
876 prodMap.remove(edgePort);
880 if (this.discoveryListener != null) {
881 this.discoveryListener.notifyEdge(edge, UpdateType.REMOVED, null);
883 logger.trace("Remove edge {}", edge);
887 * Remove OpenFlow edge
889 private void removeEdge(NodeConnector nodeConnector, boolean stillEnabled) {
890 if (nodeConnector == null) {
894 removeNodeConnector(nodeConnector);
898 stagingList.add(nodeConnector);
902 Set<NodeConnector> edgeKeySet = edgeMap.keySet();
903 if ((edgeKeySet != null) && (edgeKeySet.contains(nodeConnector))) {
904 edge = edgeMap.get(nodeConnector);
905 edgeMap.remove(nodeConnector);
909 if (this.discoveryListener != null) {
910 this.discoveryListener.notifyEdge(edge, UpdateType.REMOVED, null);
912 logger.trace("Remove {}", nodeConnector);
915 private void removeEdge(NodeConnector nodeConnector) {
916 removeEdge(nodeConnector, isEnabled(nodeConnector));
919 private void updateEdge(Edge edge, UpdateType type, Set<Property> props) {
920 if (discoveryListener == null) {
924 this.discoveryListener.notifyEdge(edge, type, props);
926 NodeConnector src = edge.getTailNodeConnector(), dst = edge.getHeadNodeConnector();
927 if (!src.getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
928 if (type == UpdateType.ADDED) {
929 edgeMap.put(dst, edge);
935 * Save Production edge into different DB keyed by the Edge port
937 if (type == UpdateType.ADDED) {
938 prodMap.put(dst, edge);
945 private void moveToReadyListHi(NodeConnector nodeConnector) {
946 if (readyListLo.contains(nodeConnector)) {
947 readyListLo.remove(nodeConnector);
948 } else if (stagingList.contains(nodeConnector)) {
949 stagingList.remove(nodeConnector);
951 readyListHi.add(nodeConnector);
954 private void registerWithOSGIConsole() {
955 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
956 bundleContext.registerService(CommandProvider.class.getName(), this, null);
959 private int getDiscoveryConsistencyCheckInterval() {
960 return discoveryConsistencyCheckMultiple * discoveryBatchRestartTicks;
964 public String getHelp() {
965 StringBuffer help = new StringBuffer();
966 help.append("---Topology Discovery---\n");
967 help.append("\t prlh - Print readyListHi entries\n");
968 help.append("\t prll - Print readyListLo entries\n");
969 help.append("\t psl - Print stagingList entries\n");
970 help.append("\t pht - Print hold time\n");
971 help.append("\t pet - Print elapsed time\n");
972 help.append("\t ptick - Print tick time in msec\n");
973 help.append("\t pcc - Print CC info\n");
974 help.append("\t psize - Print sizes of all the lists\n");
975 help.append("\t ptm - Print timeout info\n");
976 help.append("\t ecc - Enable CC\n");
977 help.append("\t dcc - Disable CC\n");
978 help.append("\t scc [multiple] - Set/show CC multiple and interval\n");
979 help.append("\t sports [ports] - Set/show max ports per batch\n");
980 help.append("\t spause [ticks] - Set/show pause period\n");
981 help.append("\t sdi [ticks] - Set/show discovery interval in ticks\n");
982 help.append("\t addsw <swid> - Add a switch\n");
983 help.append("\t remsw <swid> - Remove a switch\n");
984 help.append("\t page - Print aging info\n");
985 help.append("\t sage - Set/Show aging time limit\n");
986 help.append("\t eage - Enable aging\n");
987 help.append("\t dage - Disable aging\n");
988 help.append("\t pthrot - Print throttling\n");
989 help.append("\t ethrot - Enable throttling\n");
990 help.append("\t dthrot - Disable throttling\n");
991 help.append("\t psnp - Print LLDP snooping\n");
992 help.append("\t esnp <all|nodeConnector> - Enable LLDP snooping\n");
993 help.append("\t dsnp <all|nodeConnector> - Disable LLDP snooping\n");
994 return help.toString();
997 private List<NodeConnector> sortList(Collection<NodeConnector> ncs) {
998 List<String> ncStrArray = new ArrayList<String>();
999 for (NodeConnector nc : ncs) {
1000 ncStrArray.add(nc.toString());
1002 Collections.sort(ncStrArray);
1004 List<NodeConnector> sortedNodeConnectors = new ArrayList<NodeConnector>();
1005 for (String ncStr : ncStrArray) {
1006 sortedNodeConnectors.add(NodeConnector.fromString(ncStr));
1009 return sortedNodeConnectors;
1012 public void _prlh(CommandInterpreter ci) {
1013 ci.println("readyListHi\n");
1014 for (NodeConnector nodeConnector : sortList(readyListHi)) {
1015 if (nodeConnector == null) {
1018 ci.println(nodeConnector);
1020 ci.println("Total number of Node Connectors: " + readyListHi.size());
1023 public void _prll(CommandInterpreter ci) {
1024 ci.println("readyListLo\n");
1025 for (NodeConnector nodeConnector : sortList(readyListLo)) {
1026 if (nodeConnector == null) {
1029 ci.println(nodeConnector);
1031 ci.println("Total number of Node Connectors: " + readyListLo.size());
1034 public void _psl(CommandInterpreter ci) {
1035 ci.println("stagingList\n");
1036 for (NodeConnector nodeConnector : sortList(stagingList)) {
1037 if (nodeConnector == null) {
1040 ci.println(nodeConnector);
1042 ci.println("Total number of Node Connectors: " + stagingList.size());
1045 public void _pht(CommandInterpreter ci) {
1046 ci.println(" NodeConnector Last rx LLDP (sec)");
1047 for (ConcurrentMap.Entry<NodeConnector, Integer> entry: holdTime.entrySet()) {
1048 ci.println(entry.getKey() + "\t\t" + entry.getValue() * (discoveryTimerTick / 1000));
1050 ci.println("\nSize: " + holdTime.size() + "\tTimeout: " + discoveryTimeoutTicks * (discoveryTimerTick / 1000)
1054 public void _pet(CommandInterpreter ci) {
1055 ci.println(" NodeConnector Elapsed Time (sec)");
1056 for (ConcurrentMap.Entry<NodeConnector, Integer> entry: elapsedTime.entrySet()) {
1057 ci.println(entry.getKey() + "\t\t" + entry.getValue() * (discoveryTimerTick / 1000));
1059 ci.println("\nSize: " + elapsedTime.size() + "\tThreshold: " + DiscoveryPeriod.THRESHOLD.getTime() + " sec");
1062 public void _ptick(CommandInterpreter ci) {
1063 ci.println("Current timer is " + discoveryTimerTick + " msec per tick");
1066 public void _pcc(CommandInterpreter ci) {
1067 if (discoveryConsistencyCheckEnabled) {
1068 ci.println("ConsistencyChecker is currently enabled");
1070 ci.println("ConsistencyChecker is currently disabled");
1072 ci.println("Interval " + getDiscoveryConsistencyCheckInterval());
1073 ci.println("Multiple " + discoveryConsistencyCheckMultiple);
1074 ci.println("Number of times called " + discoveryConsistencyCheckCallingTimes);
1075 ci.println("Corrected count " + discoveryConsistencyCheckCorrected);
1078 public void _ptm(CommandInterpreter ci) {
1079 ci.println("Timeout " + discoveryTimeoutTicks + " ticks, " + discoveryTimerTick / 1000 + " sec per tick.");
1082 public void _psize(CommandInterpreter ci) {
1083 ci.println("readyListLo size " + readyListLo.size() + "\n" + "readyListHi size " + readyListHi.size() + "\n"
1084 + "stagingList size " + stagingList.size() + "\n" + "holdTime size " + holdTime.size() + "\n"
1085 + "edgeMap size " + edgeMap.size() + "\n" + "prodMap size " + prodMap.size() + "\n" + "agingMap size "
1086 + agingMap.size() + "\n" + "elapsedTime size " + elapsedTime.size());
1089 public void _page(CommandInterpreter ci) {
1090 if (this.discoveryAgingEnabled) {
1091 ci.println("Aging is enabled");
1093 ci.println("Aging is disabled");
1095 ci.println("Current aging time limit " + this.discoveryAgeoutTicks);
1097 ci.println(" Edge Aging ");
1098 Collection<Edge> prodSet = prodMap.values();
1099 if (prodSet == null) {
1102 for (Edge edge : prodSet) {
1103 Integer aging = agingMap.get(edge.getHeadNodeConnector());
1104 if (aging != null) {
1105 ci.println(edge + " " + aging);
1109 ci.println(" NodeConnector Edge ");
1110 Set<NodeConnector> keySet = prodMap.keySet();
1111 if (keySet == null) {
1114 for (NodeConnector nc : keySet) {
1115 ci.println(nc + " " + prodMap.get(nc));
1120 public void _sage(CommandInterpreter ci) {
1121 String val = ci.nextArgument();
1123 ci.println("Please enter aging time limit. Current value " + this.discoveryAgeoutTicks);
1127 this.discoveryAgeoutTicks = Integer.parseInt(val);
1128 } catch (Exception e) {
1129 ci.println("Please enter a valid number");
1134 public void _eage(CommandInterpreter ci) {
1135 this.discoveryAgingEnabled = true;
1136 ci.println("Aging is enabled");
1140 public void _dage(CommandInterpreter ci) {
1141 this.discoveryAgingEnabled = false;
1142 ci.println("Aging is disabled");
1146 public void _scc(CommandInterpreter ci) {
1147 String val = ci.nextArgument();
1149 ci.println("Please enter CC multiple. Current multiple " + discoveryConsistencyCheckMultiple
1150 + " (interval " + getDiscoveryConsistencyCheckInterval() + ") calling times "
1151 + discoveryConsistencyCheckCallingTimes);
1155 discoveryConsistencyCheckMultiple = Integer.parseInt(val);
1156 } catch (Exception e) {
1157 ci.println("Please enter a valid number");
1162 public void _ecc(CommandInterpreter ci) {
1163 this.discoveryConsistencyCheckEnabled = true;
1164 ci.println("ConsistencyChecker is enabled");
1168 public void _dcc(CommandInterpreter ci) {
1169 this.discoveryConsistencyCheckEnabled = false;
1170 ci.println("ConsistencyChecker is disabled");
1174 public void _psnp(CommandInterpreter ci) {
1175 if (this.discoverySnoopingEnabled) {
1176 ci.println("Discovery snooping is globally enabled");
1178 ci.println("Discovery snooping is globally disabled");
1181 ci.println("\nDiscovery snooping is locally disabled on these ports");
1182 for (NodeConnector nodeConnector : discoverySnoopingDisableList) {
1183 ci.println(nodeConnector);
1188 public void _esnp(CommandInterpreter ci) {
1189 String val = ci.nextArgument();
1192 ci.println("Usage: esnp <all|nodeConnector>");
1193 } else if (val.equalsIgnoreCase("all")) {
1194 this.discoverySnoopingEnabled = true;
1195 ci.println("Discovery snooping is globally enabled");
1197 NodeConnector nodeConnector = NodeConnector.fromString(val);
1198 if (nodeConnector != null) {
1199 discoverySnoopingDisableList.remove(nodeConnector);
1200 ci.println("Discovery snooping is locally enabled on port " + nodeConnector);
1202 ci.println("Entered invalid NodeConnector " + val);
1208 public void _dsnp(CommandInterpreter ci) {
1209 String val = ci.nextArgument();
1212 ci.println("Usage: dsnp <all|nodeConnector>");
1213 } else if (val.equalsIgnoreCase("all")) {
1214 this.discoverySnoopingEnabled = false;
1215 ci.println("Discovery snooping is globally disabled");
1217 NodeConnector nodeConnector = NodeConnector.fromString(val);
1218 if (nodeConnector != null) {
1219 discoverySnoopingDisableList.add(nodeConnector);
1220 ci.println("Discovery snooping is locally disabled on port " + nodeConnector);
1222 ci.println("Entered invalid NodeConnector " + val);
1228 public void _spause(CommandInterpreter ci) {
1229 String val = ci.nextArgument();
1230 String out = "Please enter pause period less than " + discoveryBatchRestartTicks + ". Current pause period is "
1231 + discoveryBatchPausePeriod + " ticks, pause at " + discoveryBatchPauseTicks + " ticks, "
1232 + discoveryTimerTick / 1000 + " sec per tick.";
1236 int pause = Integer.parseInt(val);
1237 if (pause < discoveryBatchRestartTicks) {
1238 discoveryBatchPausePeriod = pause;
1239 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
1242 } catch (Exception e) {
1249 public void _sdi(CommandInterpreter ci) {
1250 String val = ci.nextArgument();
1251 String out = "Please enter discovery interval in ticks. Current value is " + discoveryBatchRestartTicks + " ticks, "
1252 + discoveryTimerTick / 1000 + " sec per tick.";
1257 Set<NodeConnector> monitorSet = holdTime.keySet();
1258 if (monitorSet != null) {
1259 for (NodeConnector nodeConnector : monitorSet) {
1260 holdTime.put(nodeConnector, 0);
1264 ticks = Integer.parseInt(val);
1265 DiscoveryPeriod.INTERVAL.setTick(ticks);
1266 discoveryBatchRestartTicks = getDiscoveryInterval();
1267 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
1268 discoveryTimeoutTicks = getDiscoveryTimeout();
1270 } catch (Exception e) {
1276 public void _sports(CommandInterpreter ci) {
1277 String val = ci.nextArgument();
1279 ci.println("Please enter max ports per batch. Current value is " + discoveryBatchMaxPorts);
1283 discoveryBatchMaxPorts = Integer.parseInt(val);
1284 } catch (Exception e) {
1285 ci.println("Please enter a valid number");
1290 public void _addsw(CommandInterpreter ci) {
1291 String val = ci.nextArgument();
1294 sid = Long.parseLong(val);
1295 Node node = NodeCreator.createOFNode(sid);
1297 } catch (Exception e) {
1298 ci.println("Please enter a valid number");
1303 public void _remsw(CommandInterpreter ci) {
1304 String val = ci.nextArgument();
1307 sid = Long.parseLong(val);
1308 Node node = NodeCreator.createOFNode(sid);
1309 removeDiscovery(node);
1310 } catch (Exception e) {
1311 ci.println("Please enter a valid number");
1316 public void _pthrot(CommandInterpreter ci) {
1317 if (this.throttling) {
1318 ci.println("Throttling is enabled");
1320 ci.println("Throttling is disabled");
1324 public void _ethrot(CommandInterpreter ci) {
1325 this.throttling = true;
1326 ci.println("Throttling is enabled");
1330 public void _dthrot(CommandInterpreter ci) {
1331 this.throttling = false;
1332 ci.println("Throttling is disabled");
1337 public void updateNode(Node node, UpdateType type, Set<Property> props) {
1340 addNode(node, props);
1351 public void updateNodeConnector(NodeConnector nodeConnector, UpdateType type, Set<Property> props) {
1352 Config config = null;
1354 boolean enabled = false;
1356 for (Property prop : props) {
1357 if (prop.getName().equals(Config.ConfigPropName)) {
1358 config = (Config) prop;
1359 } else if (prop.getName().equals(State.StatePropName)) {
1360 state = (State) prop;
1363 enabled = ((config != null) && (config.getValue() == Config.ADMIN_UP) && (state != null) && (state.getValue() == State.EDGE_UP));
1368 addDiscovery(nodeConnector);
1369 logger.trace("ADDED enabled {}", nodeConnector);
1371 logger.trace("ADDED disabled {}", nodeConnector);
1376 addDiscovery(nodeConnector);
1377 logger.trace("CHANGED enabled {}", nodeConnector);
1379 removeDiscovery(nodeConnector);
1380 logger.trace("CHANGED disabled {}", nodeConnector);
1384 removeDiscovery(nodeConnector);
1385 logger.trace("REMOVED enabled {}", nodeConnector);
1392 public void addNode(Node node, Set<Property> props) {
1400 public void removeNode(Node node) {
1405 removeDiscovery(node);
1408 void setController(IController s) {
1409 this.controller = s;
1412 void unsetController(IController s) {
1413 if (this.controller == s) {
1414 this.controller = null;
1418 public void setInventoryProvider(IInventoryProvider service) {
1419 this.inventoryProvider = service;
1422 public void unsetInventoryProvider(IInventoryProvider service) {
1423 this.inventoryProvider = null;
1426 public void setIDataPacketMux(IDataPacketMux service) {
1427 this.iDataPacketMux = service;
1430 public void unsetIDataPacketMux(IDataPacketMux service) {
1431 if (this.iDataPacketMux == service) {
1432 this.iDataPacketMux = null;
1436 void setDiscoveryListener(IDiscoveryListener s) {
1437 this.discoveryListener = s;
1440 void unsetDiscoveryListener(IDiscoveryListener s) {
1441 if (this.discoveryListener == s) {
1442 this.discoveryListener = null;
1446 void setIPluginOutConnectionService(IPluginOutConnectionService s) {
1447 connectionOutService = s;
1450 void unsetIPluginOutConnectionService(IPluginOutConnectionService s) {
1451 if (connectionOutService == s) {
1452 connectionOutService = null;
1456 private void initDiscoveryPacket() {
1457 // Create LLDP ChassisID TLV
1458 chassisIdTlv = new LLDPTLV();
1459 chassisIdTlv.setType(LLDPTLV.TLVType.ChassisID.getValue());
1461 // Create LLDP PortID TLV
1462 portIdTlv = new LLDPTLV();
1463 portIdTlv.setType(LLDPTLV.TLVType.PortID.getValue());
1465 // Create LLDP TTL TLV
1466 byte[] ttl = new byte[] { (byte) 0, (byte) 120 };
1467 ttlTlv = new LLDPTLV();
1468 ttlTlv.setType(LLDPTLV.TLVType.TTL.getValue()).setLength((short) ttl.length).setValue(ttl);
1470 customTlv = new LLDPTLV();
1474 * Function called by the dependency manager when all the required
1475 * dependencies are satisfied
1479 logger.trace("Init called");
1481 transmitQ = new LinkedBlockingQueue<NodeConnector>();
1483 readyListHi = new CopyOnWriteArrayList<NodeConnector>();
1484 readyListLo = new CopyOnWriteArrayList<NodeConnector>();
1485 stagingList = new CopyOnWriteArrayList<NodeConnector>();
1486 holdTime = new ConcurrentHashMap<NodeConnector, Integer>();
1487 elapsedTime = new ConcurrentHashMap<NodeConnector, Integer>();
1488 edgeMap = new ConcurrentHashMap<NodeConnector, Edge>();
1489 agingMap = new ConcurrentHashMap<NodeConnector, Integer>();
1490 prodMap = new ConcurrentHashMap<NodeConnector, Edge>();
1491 discoverySnoopingDisableList = new CopyOnWriteArrayList<NodeConnector>();
1493 discoveryBatchRestartTicks = getDiscoveryInterval();
1494 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
1495 discoveryTimeoutTicks = getDiscoveryTimeout();
1496 discoveryThresholdTicks = getDiscoveryThreshold();
1497 discoveryAgeoutTicks = getDiscoveryAgeout();
1498 discoveryConsistencyCheckTickCount = discoveryBatchPauseTicks;
1499 discoveryBatchMaxPorts = getDiscoveryBatchMaxPorts();
1501 discoveryTimer = new Timer("DiscoveryService");
1502 discoveryTimerTask = new DiscoveryTimerTask();
1504 transmitThread = new Thread(new DiscoveryTransmit(transmitQ));
1506 initDiscoveryPacket();
1508 registerWithOSGIConsole();
1512 * Function called by the dependency manager when at least one dependency
1513 * become unsatisfied or when the component is shutting down because for
1514 * example bundle is being stopped.
1526 discoveryTimer = null;
1527 discoveryTimerTask = null;
1528 transmitThread = null;
1532 * Function called by dependency manager after "init ()" is called and after
1533 * the services provided by the class are registered in the service registry
1537 discoveryTimer.schedule(discoveryTimerTask, discoveryTimerTick, discoveryTimerTick);
1538 transmitThread.start();
1542 * Function called after registering the service in OSGi service registry.
1545 /* get a snapshot of all the existing switches */
1550 * Function called by the dependency manager before the services exported by
1551 * the component are unregistered, this will be followed by a "destroy ()"
1556 shuttingDown = true;
1557 discoveryTimer.cancel();
1558 transmitThread.interrupt();
1562 public void tagUpdated(String containerName, Node n, short oldTag, short newTag, UpdateType t) {
1566 public void containerFlowUpdated(String containerName, ContainerFlow previousFlow, ContainerFlow currentFlow,
1571 public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType t) {
1574 moveToReadyListHi(p);
1582 public void containerModeUpdated(UpdateType t) {
1586 private byte[] getSourceMACFromNodeID(String nodeId) {
1587 byte[] cid = HexEncode.bytesFromHexString(nodeId);
1588 byte[] sourceMac = new byte[6];
1589 int pos = cid.length - sourceMac.length;
1592 System.arraycopy(cid, pos, sourceMac, 0, sourceMac.length);
1598 private int getDiscoveryTicks(DiscoveryPeriod dp, String val) {
1605 dp.setTime(Integer.parseInt(val));
1606 } catch (Exception e) {
1610 return dp.getTick();
1614 * This method returns the interval which determines how often the discovery
1615 * packets will be sent.
1617 * @return The discovery interval in ticks
1619 private int getDiscoveryInterval() {
1620 String intvl = System.getProperty("of.discoveryInterval");
1621 return getDiscoveryTicks(DiscoveryPeriod.INTERVAL, intvl);
1625 * This method returns the timeout value in receiving subsequent discovery packets on a port.
1627 * @return The discovery timeout in ticks
1629 private int getDiscoveryTimeout() {
1630 String val = System.getProperty("of.discoveryTimeoutMultiple");
1635 multiple = Integer.parseInt(val);
1636 } catch (Exception e) {
1639 return getDiscoveryInterval() * multiple + 3;
1643 * This method returns the user configurable threshold value
1645 * @return The discovery threshold value in ticks
1647 private int getDiscoveryThreshold() {
1648 String val = System.getProperty("of.discoveryThreshold");
1649 return getDiscoveryTicks(DiscoveryPeriod.THRESHOLD, val);
1653 * This method returns the discovery entry aging time in ticks.
1655 * @return The aging time in ticks
1657 private int getDiscoveryAgeout() {
1658 return getDiscoveryTicks(DiscoveryPeriod.AGEOUT, null);
1662 * This method returns the pause interval
1664 * @return The pause interval in ticks
1666 private int getDiscoveryPauseInterval() {
1667 if (discoveryBatchRestartTicks > discoveryBatchPausePeriod) {
1668 return discoveryBatchRestartTicks - discoveryBatchPausePeriod;
1670 return discoveryBatchRestartTicks - 1;
1675 * This method returns the user configurable maximum number of ports handled
1676 * in one discovery batch.
1678 * @return The maximum number of ports
1680 private int getDiscoveryBatchMaxPorts() {
1681 String val = System.getProperty("of.discoveryBatchMaxPorts");
1686 ports = Integer.parseInt(val);
1687 } catch (Exception e) {