- Add the link with delay if the link was down before
- Process switch remove events only if the switch is really down (checking the port_removed events)
Change-Id: Id77669b1efc246d50eaf7879bd4036bb9667170f
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
index 0f49148..0a90a89 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -79,7 +79,8 @@
private static final Logger log = LoggerFactory
.getLogger(SegmentRoutingManager.class);
- private ITopologyService topologyService;
+
+ private ITopologyService topologyService;
private IPacketService packetService;
private MutableTopology mutableTopology;
private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
@@ -90,16 +91,19 @@
private IcmpHandler icmpHandler;
private IThreadPoolService threadPool;
private SingletonTask discoveryTask;
+ private SingletonTask linkAddTask;
private IFloodlightProviderService floodlightProvider;
private HashMap<Switch, ECMPShortestPathGraph> graphs;
- //private HashSet<LinkData> topologyLinks;
+ private HashMap<String, LinkData> linksDown;
+ private HashMap<String, LinkData> linksToAdd;
private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
private int numOfEvents = 0;
private int numOfEventProcess = 0;
private int numOfPopulation = 0;
private long matchActionId = 0L;
+ private final int DELAY_TO_ADD_LINK = 10;
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
@@ -141,7 +145,8 @@
topologyService.addListener(this, false);
ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
graphs = new HashMap<Switch, ECMPShortestPathGraph>();
- //topologyLinks = new HashSet<LinkData>();
+ linksDown = new HashMap<String, LinkData>();
+ linksToAdd = new HashMap<String, LinkData>();
topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
this.packetService = context.getServiceImpl(IPacketService.class);
@@ -160,6 +165,14 @@
handleTopologyChangeEvents();
}
});
+
+ linkAddTask = new SingletonTask(ses, new Runnable() {
+ @Override
+ public void run() {
+ delayedAddLink();
+ }
+ });
+
}
@Override
@@ -263,7 +276,10 @@
discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
}
-
+ /**
+ * Process the multiple topology events with some delay (100MS at most for now)
+ *
+ */
private void handleTopologyChangeEvents() {
numOfEventProcess ++;
@@ -306,11 +322,11 @@
}
if (!mastershipRemoved.isEmpty()) {
- processMastershipRemoved(mastershipRemoved);
+ log.debug("Mastership is removed. Check if ports are down also.");
}
if (!linkEntriesAdded.isEmpty()) {
- processLinkAdd(linkEntriesAdded);
+ processLinkAdd(linkEntriesAdded, false);
}
if (!portEntriesAdded.isEmpty()) {
@@ -322,12 +338,45 @@
}
}
+ // TODO: 100ms is enough to check both mastership removed events
+ // and the port removed events? What if the PORT_STATUS packets comes late?
+ if (!mastershipRemoved.isEmpty()) {
+ if (portEntriesRemoved.isEmpty()) {
+ log.debug("Just mastership is removed. Do not anthing.");
+ }
+ else {
+ HashMap<String, MastershipData> mastershipToRemove =
+ new HashMap<String, MastershipData>();
+ for (MastershipData ms: mastershipRemoved) {
+ for (PortData port: portEntriesRemoved) {
+ // TODO: check ALL ports of the switch are dead ..
+ if (port.getDpid().equals(ms.getDpid())) {
+ mastershipToRemove.put(ms.getDpid().toString(), ms);
+ }
+ }
+ log.debug("Swtich {} is really down.", ms.getDpid());
+ }
+ processMastershipRemoved(mastershipToRemove.values());
+ }
+ }
+
log.debug("num events {}, num of process {}, "
+ "num of Population {}", numOfEvents, numOfEventProcess,
numOfPopulation);
}
/**
+ * Add the link immediately
+ * The function is scheduled when link add event happens and called
+ * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
+ */
+ private void delayedAddLink() {
+
+ processLinkAdd(linksToAdd.values(), true);
+
+ }
+
+ /**
* Process the SwitchAdded events from topologyMananger.
* It does nothing. When a switch is added, then link will be added too.
* LinkAdded event will handle process all re-computation.
@@ -357,6 +406,9 @@
}
}
}
+
+ linksToAdd.clear();
+ linksDown.clear();
}
/**
@@ -365,20 +417,7 @@
* @param switchRemoved Switch removed
*/
private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
- //topologyLinks.clear();
-
- for (SwitchData switchData: switchRemoved) {
- Switch sw = mutableTopology.getSwitch(switchData.getDpid());
- for (Link link: sw.getOutgoingLinks()) {
- Port dstPort = link.getDstPort();
- IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
- getSwId(dstPort.getDpid().toString()));
- if (dstSw != null) {
- dstSw.removePortFromGroups(dstPort.getNumber());
- log.debug("Switch {} is gone: remove port {}", sw.getDpid(), dstPort);
- }
- }
- }
+ log.debug("SwitchRemoved event occurred !!!");
}
/**
@@ -402,52 +441,58 @@
/**
* Reports ports of new links to driver and recalculate ECMP SPG
+ * If the link to add was removed before, then we just schedule the add link
+ * event and do not recompute the path now.
*
* @param linkEntries
*/
- private void processLinkAdd(Collection<LinkData> linkEntries) {
+ private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
- //boolean linkRecovered = false;
-
- // TODO: How to determine this link was broken before and back now?
- // We should go stateless as possible.
- // If the link broken is up, we need to add the link with delay.
for (LinkData link : linkEntries) {
SwitchPort srcPort = link.getSrc();
SwitchPort dstPort = link.getDst();
+ String key = srcPort.getDpid().toString() +
+ dstPort.getDpid().toString();
+ if (!delayed) {
+ if (linksDown.containsKey(key)) {
+ linksToAdd.put(key, link);
+ linksDown.remove(key);
+ linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
+ log.debug("Add link {} with 5 sec delay", link);
+ // TODO: What if we have multiple events of add link:
+ // one is new link add, the other one is link up for
+ // broken link? ECMPSPG function cannot deal with it for now
+ return;
+ }
+ }
+ else {
+ if (linksDown.containsKey(key)) {
+ linksToAdd.remove(key);
+ log.debug("Do not add the link {}: it is down again!", link);
+ return;
+ }
+ }
+
IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
getSwId(srcPort.getDpid().toString()));
IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
getSwId(dstPort.getDpid().toString()));
if ((srcSw == null) || (dstSw == null))
- /* If this link is not between two switches, ignore it */
continue;
srcSw.addPortToGroups(srcPort.getPortNumber());
dstSw.addPortToGroups(dstPort.getPortNumber());
- log.debug("Add port {} to switch {}", srcPort, srcSw);
- log.debug("Add port {} to switch {}", dstPort, dstSw);
+ log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
+ link);
+ log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
+ link);
- /*
- if (!topologyLinks.contains(link)) {
- topologyLinks.add(link);
- }
- else {
- linkRecovered = true;
- }
- */
}
-
- //if (linkRecovered) {
- // populateEcmpRoutingRules(false);
- //}
- //else {
populateEcmpRoutingRules(false);
- //}
}
/**
@@ -471,6 +516,7 @@
if ((srcSw == null) || (dstSw == null))
/* If this link is not between two switches, ignore it */
continue;
+
srcSw.removePortFromGroups(srcPort.getPortNumber());
dstSw.removePortFromGroups(dstPort.getPortNumber());
log.debug("Remove port {} from switch {}", srcPort, srcSw);
@@ -484,6 +530,12 @@
log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
dstPort.getDpid());
}
+
+ String key = link.getSrc().getDpid().toString()+
+ link.getDst().getDpid().toString();
+ if (!linksDown.containsKey(key)) {
+ linksDown.put(key, link);
+ }
}
if (recomputationRequired)
@@ -960,7 +1012,7 @@
maEntries.add(maEntry);
// One rule for Bos = 0
- MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), true);
+ MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
List<Action> actionsBos = new ArrayList<Action>();
actionsBos.add(popAction);
actionsBos.add(groupAction);