Committed by
Gerrit Code Review
ONOS-1438: Segment Routing rule population optimization fixes
Change-Id: I2cad2cd485282b904e035b209530005b93c90ffd
Showing
6 changed files
with
113 additions
and
37 deletions
| ... | @@ -184,21 +184,40 @@ public class DefaultRoutingHandler { | ... | @@ -184,21 +184,40 @@ public class DefaultRoutingHandler { |
| 184 | 184 | ||
| 185 | private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) { | 185 | private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) { |
| 186 | rulePopulator.resetCounter(); | 186 | rulePopulator.resetCounter(); |
| 187 | + HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> routesBydevice = | ||
| 188 | + new HashMap<>(); | ||
| 187 | for (ArrayList<DeviceId> link: routes) { | 189 | for (ArrayList<DeviceId> link: routes) { |
| 188 | // When only the source device is defined, reinstall routes to all other devices | 190 | // When only the source device is defined, reinstall routes to all other devices |
| 189 | if (link.size() == 1) { | 191 | if (link.size() == 1) { |
| 190 | log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", link.get(0)); | 192 | log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", link.get(0)); |
| 191 | ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager); | 193 | ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager); |
| 192 | if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) { | 194 | if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) { |
| 195 | + log.debug("Populating flow rules from {} to all is successful", | ||
| 196 | + link.get(0)); | ||
| 193 | currentEcmpSpgMap.put(link.get(0), ecmpSpg); | 197 | currentEcmpSpgMap.put(link.get(0), ecmpSpg); |
| 194 | } else { | 198 | } else { |
| 195 | log.warn("Failed to populate the flow rules from {} to all", link.get(0)); | 199 | log.warn("Failed to populate the flow rules from {} to all", link.get(0)); |
| 196 | return false; | 200 | return false; |
| 197 | } | 201 | } |
| 198 | } else { | 202 | } else { |
| 203 | + ArrayList<ArrayList<DeviceId>> deviceRoutes = | ||
| 204 | + routesBydevice.get(link.get(1)); | ||
| 205 | + if (deviceRoutes == null) { | ||
| 206 | + deviceRoutes = new ArrayList<>(); | ||
| 207 | + routesBydevice.put(link.get(1), deviceRoutes); | ||
| 208 | + } | ||
| 209 | + deviceRoutes.add(link); | ||
| 210 | + } | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + for (DeviceId impactedDevice : routesBydevice.keySet()) { | ||
| 214 | + ArrayList<ArrayList<DeviceId>> deviceRoutes = | ||
| 215 | + routesBydevice.get(impactedDevice); | ||
| 216 | + for (ArrayList<DeviceId> link: deviceRoutes) { | ||
| 217 | + log.debug("repopulate RoutingRules For Routes {} -> {}", | ||
| 218 | + link.get(0), link.get(1)); | ||
| 199 | DeviceId src = link.get(0); | 219 | DeviceId src = link.get(0); |
| 200 | DeviceId dst = link.get(1); | 220 | DeviceId dst = link.get(1); |
| 201 | - log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", dst); | ||
| 202 | ECMPShortestPathGraph ecmpSpg = updatedEcmpSpgMap.get(dst); | 221 | ECMPShortestPathGraph ecmpSpg = updatedEcmpSpgMap.get(dst); |
| 203 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = | 222 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = |
| 204 | ecmpSpg.getAllLearnedSwitchesAndVia(); | 223 | ecmpSpg.getAllLearnedSwitchesAndVia(); |
| ... | @@ -220,10 +239,18 @@ public class DefaultRoutingHandler { | ... | @@ -220,10 +239,18 @@ public class DefaultRoutingHandler { |
| 220 | if (!populateEcmpRoutingRulePartial(targetSw, dst, nextHops)) { | 239 | if (!populateEcmpRoutingRulePartial(targetSw, dst, nextHops)) { |
| 221 | return false; | 240 | return false; |
| 222 | } | 241 | } |
| 242 | + log.debug("Populating flow rules from {} to {} is successful", | ||
| 243 | + targetSw, dst); | ||
| 223 | } | 244 | } |
| 224 | } | 245 | } |
| 225 | - currentEcmpSpgMap.put(dst, ecmpSpg); | 246 | + //currentEcmpSpgMap.put(dst, ecmpSpg); |
| 226 | } | 247 | } |
| 248 | + //Only if all the flows for all impacted routes to a | ||
| 249 | + //specific target are pushed successfully, update the | ||
| 250 | + //ECMP graph for that target. (Or else the next event | ||
| 251 | + //would not see any changes in the ECMP graphs) | ||
| 252 | + currentEcmpSpgMap.put(impactedDevice, | ||
| 253 | + updatedEcmpSpgMap.get(impactedDevice)); | ||
| 227 | } | 254 | } |
| 228 | return true; | 255 | return true; |
| 229 | } | 256 | } |
| ... | @@ -233,13 +260,15 @@ public class DefaultRoutingHandler { | ... | @@ -233,13 +260,15 @@ public class DefaultRoutingHandler { |
| 233 | Set<ArrayList<DeviceId>> routes = new HashSet<>(); | 260 | Set<ArrayList<DeviceId>> routes = new HashSet<>(); |
| 234 | 261 | ||
| 235 | for (Device sw : srManager.deviceService.getDevices()) { | 262 | for (Device sw : srManager.deviceService.getDevices()) { |
| 263 | + log.debug("Computing the impacted routes for device {} due to link fail", | ||
| 264 | + sw.id()); | ||
| 236 | if (srManager.mastershipService. | 265 | if (srManager.mastershipService. |
| 237 | getLocalRole(sw.id()) != MastershipRole.MASTER) { | 266 | getLocalRole(sw.id()) != MastershipRole.MASTER) { |
| 238 | continue; | 267 | continue; |
| 239 | } | 268 | } |
| 240 | ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id()); | 269 | ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id()); |
| 241 | if (ecmpSpg == null) { | 270 | if (ecmpSpg == null) { |
| 242 | - log.error("No existing ECMP path for switch {}", sw.id()); | 271 | + log.error("No existing ECMP graph for switch {}", sw.id()); |
| 243 | continue; | 272 | continue; |
| 244 | } | 273 | } |
| 245 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = | 274 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = |
| ... | @@ -252,8 +281,12 @@ public class DefaultRoutingHandler { | ... | @@ -252,8 +281,12 @@ public class DefaultRoutingHandler { |
| 252 | Set<ArrayList<DeviceId>> subLinks = | 281 | Set<ArrayList<DeviceId>> subLinks = |
| 253 | computeLinks(targetSw, destSw, swViaMap); | 282 | computeLinks(targetSw, destSw, swViaMap); |
| 254 | for (ArrayList<DeviceId> alink: subLinks) { | 283 | for (ArrayList<DeviceId> alink: subLinks) { |
| 255 | - if (alink.get(0).equals(linkFail.src().deviceId()) && | 284 | + if ((alink.get(0).equals(linkFail.src().deviceId()) && |
| 256 | - alink.get(1).equals(linkFail.dst().deviceId())) { | 285 | + alink.get(1).equals(linkFail.dst().deviceId())) |
| 286 | + || | ||
| 287 | + (alink.get(0).equals(linkFail.dst().deviceId()) && | ||
| 288 | + alink.get(1).equals(linkFail.src().deviceId()))) { | ||
| 289 | + log.debug("Impacted route:{}->{}", targetSw, destSw); | ||
| 257 | ArrayList<DeviceId> aRoute = new ArrayList<>(); | 290 | ArrayList<DeviceId> aRoute = new ArrayList<>(); |
| 258 | aRoute.add(targetSw); | 291 | aRoute.add(targetSw); |
| 259 | aRoute.add(destSw); | 292 | aRoute.add(destSw); |
| ... | @@ -274,9 +307,12 @@ public class DefaultRoutingHandler { | ... | @@ -274,9 +307,12 @@ public class DefaultRoutingHandler { |
| 274 | Set<ArrayList<DeviceId>> routes = new HashSet<>(); | 307 | Set<ArrayList<DeviceId>> routes = new HashSet<>(); |
| 275 | 308 | ||
| 276 | for (Device sw : srManager.deviceService.getDevices()) { | 309 | for (Device sw : srManager.deviceService.getDevices()) { |
| 310 | + log.debug("Computing the impacted routes for device {}", | ||
| 311 | + sw.id()); | ||
| 277 | if (srManager.mastershipService. | 312 | if (srManager.mastershipService. |
| 278 | getLocalRole(sw.id()) != MastershipRole.MASTER) { | 313 | getLocalRole(sw.id()) != MastershipRole.MASTER) { |
| 279 | - log.warn("No mastership for {} and skip route optimization"); | 314 | + log.debug("No mastership for {} and skip route optimization", |
| 315 | + sw.id()); | ||
| 280 | continue; | 316 | continue; |
| 281 | } | 317 | } |
| 282 | 318 | ||
| ... | @@ -295,7 +331,7 @@ public class DefaultRoutingHandler { | ... | @@ -295,7 +331,7 @@ public class DefaultRoutingHandler { |
| 295 | continue; | 331 | continue; |
| 296 | } | 332 | } |
| 297 | ECMPShortestPathGraph newEcmpSpg = updatedEcmpSpgMap.get(sw.id()); | 333 | ECMPShortestPathGraph newEcmpSpg = updatedEcmpSpgMap.get(sw.id()); |
| 298 | - currentEcmpSpgMap.put(sw.id(), newEcmpSpg); | 334 | + //currentEcmpSpgMap.put(sw.id(), newEcmpSpg); |
| 299 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = | 335 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = |
| 300 | ecmpSpg.getAllLearnedSwitchesAndVia(); | 336 | ecmpSpg.getAllLearnedSwitchesAndVia(); |
| 301 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchViaUpdated = | 337 | HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchViaUpdated = |
| ... | @@ -307,7 +343,8 @@ public class DefaultRoutingHandler { | ... | @@ -307,7 +343,8 @@ public class DefaultRoutingHandler { |
| 307 | for (DeviceId srcSw : swViaMapUpdated.keySet()) { | 343 | for (DeviceId srcSw : swViaMapUpdated.keySet()) { |
| 308 | ArrayList<ArrayList<DeviceId>> viaUpdated = swViaMapUpdated.get(srcSw); | 344 | ArrayList<ArrayList<DeviceId>> viaUpdated = swViaMapUpdated.get(srcSw); |
| 309 | ArrayList<ArrayList<DeviceId>> via = getVia(switchVia, srcSw); | 345 | ArrayList<ArrayList<DeviceId>> via = getVia(switchVia, srcSw); |
| 310 | - if (via.isEmpty() || !viaUpdated.equals(via)) { | 346 | + if ((via == null) || !viaUpdated.equals(via)) { |
| 347 | + log.debug("Impacted route:{}->{}", srcSw, sw.id()); | ||
| 311 | ArrayList<DeviceId> route = new ArrayList<>(); | 348 | ArrayList<DeviceId> route = new ArrayList<>(); |
| 312 | route.add(srcSw); | 349 | route.add(srcSw); |
| 313 | route.add(sw.id()); | 350 | route.add(sw.id()); |
| ... | @@ -318,7 +355,7 @@ public class DefaultRoutingHandler { | ... | @@ -318,7 +355,7 @@ public class DefaultRoutingHandler { |
| 318 | } | 355 | } |
| 319 | 356 | ||
| 320 | for (ArrayList<DeviceId> link: routes) { | 357 | for (ArrayList<DeviceId> link: routes) { |
| 321 | - log.trace("Link changes - "); | 358 | + log.trace("Route changes - "); |
| 322 | if (link.size() == 1) { | 359 | if (link.size() == 1) { |
| 323 | log.trace(" : {} - all", link.get(0)); | 360 | log.trace(" : {} - all", link.get(0)); |
| 324 | } else { | 361 | } else { |
| ... | @@ -341,7 +378,7 @@ public class DefaultRoutingHandler { | ... | @@ -341,7 +378,7 @@ public class DefaultRoutingHandler { |
| 341 | } | 378 | } |
| 342 | } | 379 | } |
| 343 | 380 | ||
| 344 | - return new ArrayList<>(); | 381 | + return null; |
| 345 | } | 382 | } |
| 346 | 383 | ||
| 347 | private Set<ArrayList<DeviceId>> computeLinks(DeviceId src, | 384 | private Set<ArrayList<DeviceId>> computeLinks(DeviceId src, | ... | ... |
| ... | @@ -133,7 +133,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -133,7 +133,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 133 | 133 | ||
| 134 | private NetworkConfigManager networkConfigService = new NetworkConfigManager();; | 134 | private NetworkConfigManager networkConfigService = new NetworkConfigManager();; |
| 135 | 135 | ||
| 136 | - private static int numOfEvents = 0; | 136 | + private Object threadSchedulerLock = new Object(); |
| 137 | + private static int numOfEventsQueued = 0; | ||
| 138 | + private static int numOfEventsExecuted = 0; | ||
| 137 | private static int numOfHandlerExecution = 0; | 139 | private static int numOfHandlerExecution = 0; |
| 138 | private static int numOfHandlerScheduled = 0; | 140 | private static int numOfHandlerScheduled = 0; |
| 139 | 141 | ||
| ... | @@ -325,6 +327,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -325,6 +327,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 325 | public void event(LinkEvent event) { | 327 | public void event(LinkEvent event) { |
| 326 | if (event.type() == LinkEvent.Type.LINK_ADDED | 328 | if (event.type() == LinkEvent.Type.LINK_ADDED |
| 327 | || event.type() == LinkEvent.Type.LINK_REMOVED) { | 329 | || event.type() == LinkEvent.Type.LINK_REMOVED) { |
| 330 | + log.debug("Event {} received from Link Service", event.type()); | ||
| 328 | scheduleEventHandlerIfNotScheduled(event); | 331 | scheduleEventHandlerIfNotScheduled(event); |
| 329 | } | 332 | } |
| 330 | } | 333 | } |
| ... | @@ -346,6 +349,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -346,6 +349,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 346 | case PORT_REMOVED: | 349 | case PORT_REMOVED: |
| 347 | case DEVICE_UPDATED: | 350 | case DEVICE_UPDATED: |
| 348 | case DEVICE_AVAILABILITY_CHANGED: | 351 | case DEVICE_AVAILABILITY_CHANGED: |
| 352 | + log.debug("Event {} received from Device Service", event.type()); | ||
| 349 | scheduleEventHandlerIfNotScheduled(event); | 353 | scheduleEventHandlerIfNotScheduled(event); |
| 350 | break; | 354 | break; |
| 351 | default: | 355 | default: |
| ... | @@ -355,19 +359,20 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -355,19 +359,20 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 355 | 359 | ||
| 356 | private void scheduleEventHandlerIfNotScheduled(Event event) { | 360 | private void scheduleEventHandlerIfNotScheduled(Event event) { |
| 357 | 361 | ||
| 358 | - synchronized (eventQueue) { | 362 | + synchronized (threadSchedulerLock) { |
| 359 | eventQueue.add(event); | 363 | eventQueue.add(event); |
| 360 | - numOfEvents++; | 364 | + numOfEventsQueued++; |
| 361 | - if (eventHandlerFuture == null || eventHandlerFuture.isDone()) { | 365 | + |
| 366 | + if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) { | ||
| 367 | + //No pending scheduled event handling threads. So start a new one. | ||
| 362 | eventHandlerFuture = executorService | 368 | eventHandlerFuture = executorService |
| 363 | .schedule(eventHandler, 100, TimeUnit.MILLISECONDS); | 369 | .schedule(eventHandler, 100, TimeUnit.MILLISECONDS); |
| 364 | numOfHandlerScheduled++; | 370 | numOfHandlerScheduled++; |
| 365 | } | 371 | } |
| 366 | - } | 372 | + log.trace("numOfEventsQueued {}, numOfEventHanlderScheduled {}", |
| 367 | - | 373 | + numOfEventsQueued, |
| 368 | - log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents, | ||
| 369 | numOfHandlerScheduled); | 374 | numOfHandlerScheduled); |
| 370 | - | 375 | + } |
| 371 | } | 376 | } |
| 372 | 377 | ||
| 373 | private class InternalEventHandler implements Runnable { | 378 | private class InternalEventHandler implements Runnable { |
| ... | @@ -375,10 +380,19 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -375,10 +380,19 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 375 | @Override | 380 | @Override |
| 376 | public void run() { | 381 | public void run() { |
| 377 | try { | 382 | try { |
| 378 | - synchronized (eventQueue) { | 383 | + while (true) { |
| 384 | + Event event = null; | ||
| 385 | + synchronized (threadSchedulerLock) { | ||
| 386 | + if (!eventQueue.isEmpty()) { | ||
| 387 | + event = eventQueue.poll(); | ||
| 388 | + numOfEventsExecuted++; | ||
| 389 | + } else { | ||
| 379 | numOfHandlerExecution++; | 390 | numOfHandlerExecution++; |
| 380 | - while (!eventQueue.isEmpty()) { | 391 | + log.debug("numOfHandlerExecution {} numOfEventsExecuted {}", |
| 381 | - Event event = eventQueue.poll(); | 392 | + numOfHandlerExecution, numOfEventsExecuted); |
| 393 | + break; | ||
| 394 | + } | ||
| 395 | + } | ||
| 382 | if (event.type() == LinkEvent.Type.LINK_ADDED) { | 396 | if (event.type() == LinkEvent.Type.LINK_ADDED) { |
| 383 | processLinkAdded((Link) event.subject()); | 397 | processLinkAdded((Link) event.subject()); |
| 384 | } else if (event.type() == LinkEvent.Type.LINK_REMOVED) { | 398 | } else if (event.type() == LinkEvent.Type.LINK_REMOVED) { |
| ... | @@ -398,9 +412,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -398,9 +412,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 398 | log.warn("Unhandled event type: {}", event.type()); | 412 | log.warn("Unhandled event type: {}", event.type()); |
| 399 | } | 413 | } |
| 400 | } | 414 | } |
| 401 | - } | ||
| 402 | - log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}", | ||
| 403 | - numOfHandlerExecution, numOfHandlerScheduled, numOfEvents); | ||
| 404 | } catch (Exception e) { | 415 | } catch (Exception e) { |
| 405 | log.error("SegmentRouting event handler " | 416 | log.error("SegmentRouting event handler " |
| 406 | + "thread thrown an exception: {}", e); | 417 | + "thread thrown an exception: {}", e); |
| ... | @@ -433,9 +444,10 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -433,9 +444,10 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 433 | } | 444 | } |
| 434 | } | 445 | } |
| 435 | 446 | ||
| 436 | - //defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null); | 447 | + log.trace("Starting optimized route population process"); |
| 437 | - log.trace("processLinkAdded: re-starting route population process"); | 448 | + defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null); |
| 438 | - defaultRoutingHandler.startPopulationProcess(); | 449 | + //log.trace("processLinkAdded: re-starting route population process"); |
| 450 | + //defaultRoutingHandler.startPopulationProcess(); | ||
| 439 | } | 451 | } |
| 440 | 452 | ||
| 441 | private void processLinkRemoved(Link link) { | 453 | private void processLinkRemoved(Link link) { |
| ... | @@ -444,9 +456,10 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -444,9 +456,10 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 444 | if (groupHandler != null) { | 456 | if (groupHandler != null) { |
| 445 | groupHandler.portDown(link.src().port()); | 457 | groupHandler.portDown(link.src().port()); |
| 446 | } | 458 | } |
| 447 | - //defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link); | 459 | + log.trace("Starting optimized route population process"); |
| 448 | - log.trace("processLinkRemoved: re-starting route population process"); | 460 | + defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link); |
| 449 | - defaultRoutingHandler.startPopulationProcess(); | 461 | + //log.trace("processLinkRemoved: re-starting route population process"); |
| 462 | + //defaultRoutingHandler.startPopulationProcess(); | ||
| 450 | } | 463 | } |
| 451 | 464 | ||
| 452 | private void processDeviceAdded(Device device) { | 465 | private void processDeviceAdded(Device device) { | ... | ... |
| ... | @@ -35,6 +35,10 @@ public interface Group extends GroupDescription { | ... | @@ -35,6 +35,10 @@ public interface Group extends GroupDescription { |
| 35 | */ | 35 | */ |
| 36 | PENDING_ADD, | 36 | PENDING_ADD, |
| 37 | /** | 37 | /** |
| 38 | + * Group is missing in data plane and retrying GROUP ADD request. | ||
| 39 | + */ | ||
| 40 | + PENDING_ADD_RETRY, | ||
| 41 | + /** | ||
| 38 | * Group is created in the data plane. | 42 | * Group is created in the data plane. |
| 39 | */ | 43 | */ |
| 40 | ADDED, | 44 | ADDED, | ... | ... |
| ... | @@ -715,11 +715,12 @@ public class DistributedGroupStore | ... | @@ -715,11 +715,12 @@ public class DistributedGroupStore |
| 715 | existing.setLife(group.life()); | 715 | existing.setLife(group.life()); |
| 716 | existing.setPackets(group.packets()); | 716 | existing.setPackets(group.packets()); |
| 717 | existing.setBytes(group.bytes()); | 717 | existing.setBytes(group.bytes()); |
| 718 | - if (existing.state() == GroupState.PENDING_ADD) { | 718 | + if ((existing.state() == GroupState.PENDING_ADD) || |
| 719 | + (existing.state() == GroupState.PENDING_ADD_RETRY)) { | ||
| 719 | log.debug("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED", | 720 | log.debug("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED", |
| 720 | existing.id(), | 721 | existing.id(), |
| 721 | existing.deviceId(), | 722 | existing.deviceId(), |
| 722 | - GroupState.PENDING_ADD); | 723 | + existing.state()); |
| 723 | existing.setState(GroupState.ADDED); | 724 | existing.setState(GroupState.ADDED); |
| 724 | existing.setIsGroupStateAddedFirstTime(true); | 725 | existing.setIsGroupStateAddedFirstTime(true); |
| 725 | event = new GroupEvent(Type.GROUP_ADDED, existing); | 726 | event = new GroupEvent(Type.GROUP_ADDED, existing); |
| ... | @@ -839,6 +840,12 @@ public class DistributedGroupStore | ... | @@ -839,6 +840,12 @@ public class DistributedGroupStore |
| 839 | existing.deviceId()); | 840 | existing.deviceId()); |
| 840 | switch (operation.opType()) { | 841 | switch (operation.opType()) { |
| 841 | case ADD: | 842 | case ADD: |
| 843 | + if (existing.state() == GroupState.PENDING_ADD) { | ||
| 844 | + //TODO: Need to add support for passing the group | ||
| 845 | + //operation failure reason from group provider. | ||
| 846 | + //If the error type is anything other than GROUP_EXISTS, | ||
| 847 | + //then the GROUP_ADD_FAILED event should be raised even | ||
| 848 | + //in PENDING_ADD_RETRY state also. | ||
| 842 | notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing)); | 849 | notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing)); |
| 843 | log.warn("groupOperationFailed: cleaningup " | 850 | log.warn("groupOperationFailed: cleaningup " |
| 844 | + "group {} from store in device {}....", | 851 | + "group {} from store in device {}....", |
| ... | @@ -848,6 +855,7 @@ public class DistributedGroupStore | ... | @@ -848,6 +855,7 @@ public class DistributedGroupStore |
| 848 | //map update listener | 855 | //map update listener |
| 849 | getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), | 856 | getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), |
| 850 | existing.appCookie())); | 857 | existing.appCookie())); |
| 858 | + } | ||
| 851 | break; | 859 | break; |
| 852 | case MODIFY: | 860 | case MODIFY: |
| 853 | notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_FAILED, existing)); | 861 | notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_FAILED, existing)); |
| ... | @@ -1196,16 +1204,17 @@ public class DistributedGroupStore | ... | @@ -1196,16 +1204,17 @@ public class DistributedGroupStore |
| 1196 | break; | 1204 | break; |
| 1197 | case ADDED: | 1205 | case ADDED: |
| 1198 | case PENDING_ADD: | 1206 | case PENDING_ADD: |
| 1207 | + case PENDING_ADD_RETRY: | ||
| 1199 | case PENDING_UPDATE: | 1208 | case PENDING_UPDATE: |
| 1200 | log.debug("Group {} is in store but not on device {}", | 1209 | log.debug("Group {} is in store but not on device {}", |
| 1201 | group, group.deviceId()); | 1210 | group, group.deviceId()); |
| 1202 | StoredGroupEntry existing = | 1211 | StoredGroupEntry existing = |
| 1203 | getStoredGroupEntry(group.deviceId(), group.id()); | 1212 | getStoredGroupEntry(group.deviceId(), group.id()); |
| 1204 | - log.debug("groupMissing: group entry {} in device {} moving from {} to PENDING_ADD", | 1213 | + log.debug("groupMissing: group entry {} in device {} moving from {} to PENDING_ADD_RETRY", |
| 1205 | existing.id(), | 1214 | existing.id(), |
| 1206 | existing.deviceId(), | 1215 | existing.deviceId(), |
| 1207 | existing.state()); | 1216 | existing.state()); |
| 1208 | - existing.setState(Group.GroupState.PENDING_ADD); | 1217 | + existing.setState(Group.GroupState.PENDING_ADD_RETRY); |
| 1209 | //Re-PUT map entries to trigger map update events | 1218 | //Re-PUT map entries to trigger map update events |
| 1210 | getGroupStoreKeyMap(). | 1219 | getGroupStoreKeyMap(). |
| 1211 | put(new GroupStoreKeyMapKey(existing.deviceId(), | 1220 | put(new GroupStoreKeyMapKey(existing.deviceId(), | ... | ... |
| ... | @@ -215,6 +215,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -215,6 +215,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 215 | @Override | 215 | @Override |
| 216 | public void next(NextObjective nextObjective) { | 216 | public void next(NextObjective nextObjective) { |
| 217 | 217 | ||
| 218 | + log.debug("Processing NextObjective id{} op{}", nextObjective.id(), | ||
| 219 | + nextObjective.op()); | ||
| 218 | if (nextObjective.op() == Objective.Operation.REMOVE) { | 220 | if (nextObjective.op() == Objective.Operation.REMOVE) { |
| 219 | if (nextObjective.next().isEmpty()) { | 221 | if (nextObjective.next().isEmpty()) { |
| 220 | removeGroup(nextObjective); | 222 | removeGroup(nextObjective); |
| ... | @@ -243,6 +245,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -243,6 +245,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | private void addGroup(NextObjective nextObjective) { | 247 | private void addGroup(NextObjective nextObjective) { |
| 248 | + log.debug("addGroup with type{} for nextObjective id {}", | ||
| 249 | + nextObjective.type(), nextObjective.id()); | ||
| 246 | switch (nextObjective.type()) { | 250 | switch (nextObjective.type()) { |
| 247 | case SIMPLE: | 251 | case SIMPLE: |
| 248 | log.debug("processing SIMPLE next objective"); | 252 | log.debug("processing SIMPLE next objective"); |
| ... | @@ -262,6 +266,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -262,6 +266,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 262 | key, | 266 | key, |
| 263 | null, | 267 | null, |
| 264 | nextObjective.appId()); | 268 | nextObjective.appId()); |
| 269 | + log.debug("Creating SIMPLE group for next objective id {}", | ||
| 270 | + nextObjective.id()); | ||
| 265 | groupService.addGroup(groupDescription); | 271 | groupService.addGroup(groupDescription); |
| 266 | pendingGroups.put(key, nextObjective); | 272 | pendingGroups.put(key, nextObjective); |
| 267 | } | 273 | } |
| ... | @@ -285,6 +291,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -285,6 +291,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 285 | key, | 291 | key, |
| 286 | null, | 292 | null, |
| 287 | nextObjective.appId()); | 293 | nextObjective.appId()); |
| 294 | + log.debug("Creating HASHED group for next objective id {}", | ||
| 295 | + nextObjective.id()); | ||
| 288 | groupService.addGroup(groupDescription); | 296 | groupService.addGroup(groupDescription); |
| 289 | pendingGroups.put(key, nextObjective); | 297 | pendingGroups.put(key, nextObjective); |
| 290 | } | 298 | } |
| ... | @@ -324,6 +332,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -324,6 +332,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 324 | return; | 332 | return; |
| 325 | } | 333 | } |
| 326 | GroupBuckets bucketsToAdd = new GroupBuckets(Collections.singletonList(bucket)); | 334 | GroupBuckets bucketsToAdd = new GroupBuckets(Collections.singletonList(bucket)); |
| 335 | + log.debug("Adding buckets to group id {} of next objective id {} in device {}", | ||
| 336 | + group.id(), nextObjective.id(), deviceId); | ||
| 327 | groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId); | 337 | groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId); |
| 328 | } | 338 | } |
| 329 | 339 | ||
| ... | @@ -352,6 +362,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -352,6 +362,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
| 352 | return; | 362 | return; |
| 353 | } | 363 | } |
| 354 | GroupBuckets removeBuckets = new GroupBuckets(Collections.singletonList(bucket)); | 364 | GroupBuckets removeBuckets = new GroupBuckets(Collections.singletonList(bucket)); |
| 365 | + log.debug("Removing buckets from group id {} of next objective id {} in device {}", | ||
| 366 | + group.id(), nextObjective.id(), deviceId); | ||
| 355 | groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId); | 367 | groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId); |
| 356 | } | 368 | } |
| 357 | } | 369 | } | ... | ... |
| ... | @@ -40,9 +40,10 @@ | ... | @@ -40,9 +40,10 @@ |
| 40 | "load": { | 40 | "load": { |
| 41 | "alpha": 0.9, | 41 | "alpha": 0.9, |
| 42 | "sprites": [ | 42 | "sprites": [ |
| 43 | - { "id": "rack", "pos":[300,600], "class":"blue1" }, | 43 | + { "id": "rack", "pos":[200,600], "class":"blue1" }, |
| 44 | - { "id": "rack", "pos":[500,600], "class":"blue1" }, | 44 | + { "id": "rack", "pos":[400,600], "class":"blue1" }, |
| 45 | - { "id": "rack", "pos":[700,600], "class":"blue1" } | 45 | + { "id": "rack", "pos":[600,600], "class":"blue1" }, |
| 46 | + { "id": "rack", "pos":[800,600], "class":"blue1" } | ||
| 46 | ], | 47 | ], |
| 47 | "labels": [ | 48 | "labels": [ |
| 48 | { "pos":[550,80], "text":"Segment Routing Demo", "class":"blue1", "size":1.4 } | 49 | { "pos":[550,80], "text":"Segment Routing Demo", "class":"blue1", "size":1.4 } | ... | ... |
-
Please register or login to post a comment