ONOS-1438: Segment Routing rule population optimization fixes
Change-Id: I2cad2cd485282b904e035b209530005b93c90ffd
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 14187c0..7e8cb4c 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -184,21 +184,40 @@
private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) {
rulePopulator.resetCounter();
+ HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> routesBydevice =
+ new HashMap<>();
for (ArrayList<DeviceId> link: routes) {
// When only the source device is defined, reinstall routes to all other devices
if (link.size() == 1) {
log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", link.get(0));
ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager);
if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) {
+ log.debug("Populating flow rules from {} to all is successful",
+ link.get(0));
currentEcmpSpgMap.put(link.get(0), ecmpSpg);
} else {
log.warn("Failed to populate the flow rules from {} to all", link.get(0));
return false;
}
} else {
+ ArrayList<ArrayList<DeviceId>> deviceRoutes =
+ routesBydevice.get(link.get(1));
+ if (deviceRoutes == null) {
+ deviceRoutes = new ArrayList<>();
+ routesBydevice.put(link.get(1), deviceRoutes);
+ }
+ deviceRoutes.add(link);
+ }
+ }
+
+ for (DeviceId impactedDevice : routesBydevice.keySet()) {
+ ArrayList<ArrayList<DeviceId>> deviceRoutes =
+ routesBydevice.get(impactedDevice);
+ for (ArrayList<DeviceId> link: deviceRoutes) {
+ log.debug("repopulate RoutingRules For Routes {} -> {}",
+ link.get(0), link.get(1));
DeviceId src = link.get(0);
DeviceId dst = link.get(1);
- log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", dst);
ECMPShortestPathGraph ecmpSpg = updatedEcmpSpgMap.get(dst);
HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
ecmpSpg.getAllLearnedSwitchesAndVia();
@@ -220,10 +239,18 @@
if (!populateEcmpRoutingRulePartial(targetSw, dst, nextHops)) {
return false;
}
+ log.debug("Populating flow rules from {} to {} is successful",
+ targetSw, dst);
}
}
- currentEcmpSpgMap.put(dst, ecmpSpg);
+ //currentEcmpSpgMap.put(dst, ecmpSpg);
}
+ //Only if all the flows for all impacted routes to a
+ //specific target are pushed successfully, update the
+ //ECMP graph for that target. (Or else the next event
+ //would not see any changes in the ECMP graphs)
+ currentEcmpSpgMap.put(impactedDevice,
+ updatedEcmpSpgMap.get(impactedDevice));
}
return true;
}
@@ -233,13 +260,15 @@
Set<ArrayList<DeviceId>> routes = new HashSet<>();
for (Device sw : srManager.deviceService.getDevices()) {
+ log.debug("Computing the impacted routes for device {} due to link fail",
+ sw.id());
if (srManager.mastershipService.
getLocalRole(sw.id()) != MastershipRole.MASTER) {
continue;
}
ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
if (ecmpSpg == null) {
- log.error("No existing ECMP path for switch {}", sw.id());
+ log.error("No existing ECMP graph for switch {}", sw.id());
continue;
}
HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
@@ -252,8 +281,12 @@
Set<ArrayList<DeviceId>> subLinks =
computeLinks(targetSw, destSw, swViaMap);
for (ArrayList<DeviceId> alink: subLinks) {
- if (alink.get(0).equals(linkFail.src().deviceId()) &&
- alink.get(1).equals(linkFail.dst().deviceId())) {
+ if ((alink.get(0).equals(linkFail.src().deviceId()) &&
+ alink.get(1).equals(linkFail.dst().deviceId()))
+ ||
+ (alink.get(0).equals(linkFail.dst().deviceId()) &&
+ alink.get(1).equals(linkFail.src().deviceId()))) {
+ log.debug("Impacted route:{}->{}", targetSw, destSw);
ArrayList<DeviceId> aRoute = new ArrayList<>();
aRoute.add(targetSw);
aRoute.add(destSw);
@@ -274,9 +307,12 @@
Set<ArrayList<DeviceId>> routes = new HashSet<>();
for (Device sw : srManager.deviceService.getDevices()) {
+ log.debug("Computing the impacted routes for device {}",
+ sw.id());
if (srManager.mastershipService.
getLocalRole(sw.id()) != MastershipRole.MASTER) {
- log.warn("No mastership for {} and skip route optimization");
+ log.debug("No mastership for {} and skip route optimization",
+ sw.id());
continue;
}
@@ -295,7 +331,7 @@
continue;
}
ECMPShortestPathGraph newEcmpSpg = updatedEcmpSpgMap.get(sw.id());
- currentEcmpSpgMap.put(sw.id(), newEcmpSpg);
+ //currentEcmpSpgMap.put(sw.id(), newEcmpSpg);
HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
ecmpSpg.getAllLearnedSwitchesAndVia();
HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchViaUpdated =
@@ -307,7 +343,8 @@
for (DeviceId srcSw : swViaMapUpdated.keySet()) {
ArrayList<ArrayList<DeviceId>> viaUpdated = swViaMapUpdated.get(srcSw);
ArrayList<ArrayList<DeviceId>> via = getVia(switchVia, srcSw);
- if (via.isEmpty() || !viaUpdated.equals(via)) {
+ if ((via == null) || !viaUpdated.equals(via)) {
+ log.debug("Impacted route:{}->{}", srcSw, sw.id());
ArrayList<DeviceId> route = new ArrayList<>();
route.add(srcSw);
route.add(sw.id());
@@ -318,7 +355,7 @@
}
for (ArrayList<DeviceId> link: routes) {
- log.trace("Link changes - ");
+ log.trace("Route changes - ");
if (link.size() == 1) {
log.trace(" : {} - all", link.get(0));
} else {
@@ -341,7 +378,7 @@
}
}
- return new ArrayList<>();
+ return null;
}
private Set<ArrayList<DeviceId>> computeLinks(DeviceId src,