ONOS-1786: Updates group buckets when link status is changed.
 - Add null check for port map when creating new groups

Change-Id: I92b494d91e908011f2c08be850ccde648e647a09
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 c5bd6ba..cbad910 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -159,6 +159,7 @@
     private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) {
         rulePopulator.resetCounter();
         for (ArrayList<DeviceId> link: routes) {
+            // When only the source device is defined, reinstall routes to all other devices
             if (link.size() == 1) {
                 ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager);
                 if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) {
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 154127e..09bfc50 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -173,6 +173,11 @@
         TrafficTreatment treatment = tbuilder.build();
         TrafficSelector selector = sbuilder.build();
 
+        if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
+            log.warn("No next objective in {} for ns: {}", deviceId, ns);
+            return false;
+        }
+
         ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
                 .builder()
                 .fromApp(srManager.appId)
@@ -183,7 +188,7 @@
                 .withPriority(100)
                 .withFlag(ForwardingObjective.Flag.SPECIFIC);
         log.debug("Installing IPv4 forwarding objective "
-                + "for router IP/subnet {} in switch {}",
+                        + "for router IP/subnet {} in switch {}",
                 ipPrefix,
                 deviceId);
         srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add());
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index b7167c8..9ace6b8 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -304,6 +304,10 @@
 
     private void processLinkRemoved(Link link) {
         log.debug("A link {} was removed", link.toString());
+        DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
+        if (groupHandler != null) {
+            groupHandler.portDown(link.src().port());
+        }
         defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
     }
 
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
index e54f51f..4159d3c 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
@@ -25,7 +25,9 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultNextObjective;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.NextObjective;
 import org.onosproject.net.link.LinkService;
 
 /**
@@ -126,18 +128,18 @@
                         .setMpls(MplsLabel.
                                  mplsLabel(ns.getEdgeLabel()));
             }
-            /*GroupBucket updatedBucket = DefaultGroupBucket.
-                    createSelectGroupBucket(tBuilder.build());
-            GroupBuckets updatedBuckets = new GroupBuckets(
-                                        Arrays.asList(updatedBucket));
-            log.debug("newPortToExistingNeighborAtEdgeRouter: "
-                    + "groupService.addBucketsToGroup for neighborset{}", ns);
-            groupService.addBucketsToGroup(deviceId,
-                                           getGroupKey(ns),
-                                           updatedBuckets,
-                                           getGroupKey(ns),
-                                           appId);*/
-            //TODO: Use nextObjective APIs to update the next objective
+
+            Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
+            if (nextId != null) {
+                NextObjective.Builder nextObjBuilder = DefaultNextObjective
+                        .builder().withId(nextId)
+                        .withType(NextObjective.Type.HASHED).fromApp(appId);
+
+                nextObjBuilder.addTreatment(tBuilder.build());
+
+                NextObjective nextObjective = nextObjBuilder.add();
+                flowObjectiveService.next(deviceId, nextObjective);
+            }
         }
     }
 
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index cb295db..1d9f4ec 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -186,17 +186,19 @@
                 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
                                                     .getEdgeLabel()));
             }
-            /*
-             * GroupBucket removeBucket = DefaultGroupBucket.
-             * createSelectGroupBucket(tBuilder.build()); GroupBuckets
-             * removeBuckets = new GroupBuckets( Arrays.asList(removeBucket));
-             * log.debug("portDown in device{}: " +
-             * "groupService.removeBucketsFromGroup " + "for neighborset{}",
-             * deviceId, ns); groupService.removeBucketsFromGroup(deviceId,
-             * getGroupKey(ns), removeBuckets, getGroupKey(ns), appId);
-             */
-            //TODO: Use next objective API to update the previously created
-            //next objectives.
+
+            Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
+            if (nextId != null) {
+                NextObjective.Builder nextObjBuilder = DefaultNextObjective
+                        .builder().withType(NextObjective.Type.SIMPLE).withId(nextId).fromApp(appId);
+
+                nextObjBuilder.addTreatment(tBuilder.build());
+
+                NextObjective nextObjective = nextObjBuilder.remove();
+
+                flowObjectiveService.next(deviceId, nextObjective);
+            }
+
         }
 
         devicePortMap.get(portDeviceMap.get(port)).remove(port);
@@ -333,6 +335,11 @@
                     .builder().withId(nextId)
                     .withType(NextObjective.Type.HASHED).fromApp(appId);
             for (DeviceId d : ns.getDeviceIds()) {
+                if (devicePortMap.get(d) == null) {
+                    log.warn("Device {} is not in the port map yet", d);
+                    return;
+                }
+
                 for (PortNumber sp : devicePortMap.get(d)) {
                     TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
                             .builder();
@@ -341,7 +348,7 @@
                             .setEthSrc(nodeMacAddr);
                     if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
                         tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
-                                                            .getEdgeLabel()));
+                                .getEdgeLabel()));
                     }
                     nextObjBuilder.addTreatment(tBuilder.build());
                 }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
index 67e9eef..752ee2d 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
@@ -24,7 +24,9 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultNextObjective;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.NextObjective;
 import org.onosproject.net.link.LinkService;
 
 /**
@@ -114,18 +116,19 @@
                         .setMpls(MplsLabel.
                                  mplsLabel(ns.getEdgeLabel()));
             }
-            /*GroupBucket updatedBucket = DefaultGroupBucket.
-                    createSelectGroupBucket(tBuilder.build());
-            GroupBuckets updatedBuckets = new GroupBuckets(
-                                        Arrays.asList(updatedBucket));
-            log.debug("newPortToExistingNeighborAtEdgeRouter: "
-                    + "groupService.addBucketsToGroup for neighborset{}", ns);
-            groupService.addBucketsToGroup(deviceId,
-                                           getGroupKey(ns),
-                                           updatedBuckets,
-                                           getGroupKey(ns),
-                                           appId);*/
-            //TODO: Use nextObjective APIs to update the next objective
+
+
+            Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
+            if (nextId != null) {
+                NextObjective.Builder nextObjBuilder = DefaultNextObjective
+                        .builder().withId(nextId)
+                        .withType(NextObjective.Type.HASHED).fromApp(appId);
+
+                nextObjBuilder.addTreatment(tBuilder.build());
+
+                NextObjective nextObjective = nextObjBuilder.add();
+                flowObjectiveService.next(deviceId, nextObjective);
+            }
         }
     }