Saurav Das
Committed by Ray Milkey

In this commit:

   Bug fix when optimized SR re-routing fails, do full re-route
   Bug fix filtering objectives should be called for new device even if there is an existing grouphandler
   Bug fix NPE in ofdpa driver due to null check on the wrong variable
   New cli command for debugging flow-objectives for pending next-objectives
   Flow objective cli commands now start with "obj-"

Change-Id: I819f82d1d67769cb9fbbde60f099d29b8e7f7c9e
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
16 package org.onosproject.pce.util; 16 package org.onosproject.pce.util;
17 17
18 import java.util.List; 18 import java.util.List;
19 - 19 +import com.google.common.collect.ImmutableList;
20 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
21 import org.onosproject.net.flowobjective.FilteringObjective; 21 import org.onosproject.net.flowobjective.FilteringObjective;
22 import org.onosproject.net.flowobjective.FlowObjectiveService; 22 import org.onosproject.net.flowobjective.FlowObjectiveService;
...@@ -60,6 +60,11 @@ public class FlowObjServiceAdapter implements FlowObjectiveService { ...@@ -60,6 +60,11 @@ public class FlowObjServiceAdapter implements FlowObjectiveService {
60 60
61 @Override 61 @Override
62 public List<String> getNextMappings() { 62 public List<String> getNextMappings() {
63 - return null; 63 + return ImmutableList.of();
64 + }
65 +
66 + @Override
67 + public List<String> getPendingNexts() {
68 + return ImmutableList.of();
64 } 69 }
65 } 70 }
......
...@@ -170,6 +170,7 @@ public class DefaultRoutingHandler { ...@@ -170,6 +170,7 @@ public class DefaultRoutingHandler {
170 log.trace("populateRoutingRulesForLinkStatusChange: " 170 log.trace("populateRoutingRulesForLinkStatusChange: "
171 + "populationStatus is STARTED"); 171 + "populationStatus is STARTED");
172 populationStatus = Status.STARTED; 172 populationStatus = Status.STARTED;
173 + // optimized re-routing
173 if (linkFail == null) { 174 if (linkFail == null) {
174 // Compare all routes of existing ECMP SPG with the new ones 175 // Compare all routes of existing ECMP SPG with the new ones
175 routeChanges = computeRouteChange(); 176 routeChanges = computeRouteChange();
...@@ -178,6 +179,11 @@ public class DefaultRoutingHandler { ...@@ -178,6 +179,11 @@ public class DefaultRoutingHandler {
178 routeChanges = computeDamagedRoutes(linkFail); 179 routeChanges = computeDamagedRoutes(linkFail);
179 } 180 }
180 181
182 + // null routeChanges indicates that full re-routing is required
183 + if (routeChanges == null) {
184 + return populateAllRoutingRules();
185 + }
186 +
181 if (routeChanges.isEmpty()) { 187 if (routeChanges.isEmpty()) {
182 log.info("No route changes for the link status change"); 188 log.info("No route changes for the link status change");
183 log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED"); 189 log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
...@@ -276,6 +282,15 @@ public class DefaultRoutingHandler { ...@@ -276,6 +282,15 @@ public class DefaultRoutingHandler {
276 return true; 282 return true;
277 } 283 }
278 284
285 + /**
286 + * Computes set of affected ECMP routes due to failed link. Assumes
287 + * previous ecmp shortest-path graph exists for a switch in order to compute
288 + * affected routes. If such a graph does not exist, the method returns null.
289 + *
290 + * @param linkFail the failed link
291 + * @return the set of affected routes which may be empty if no routes were
292 + * affected, or null if no previous ecmp spg was found for comparison
293 + */
279 private Set<ArrayList<DeviceId>> computeDamagedRoutes(Link linkFail) { 294 private Set<ArrayList<DeviceId>> computeDamagedRoutes(Link linkFail) {
280 295
281 Set<ArrayList<DeviceId>> routes = new HashSet<>(); 296 Set<ArrayList<DeviceId>> routes = new HashSet<>();
...@@ -284,20 +299,31 @@ public class DefaultRoutingHandler { ...@@ -284,20 +299,31 @@ public class DefaultRoutingHandler {
284 log.debug("Computing the impacted routes for device {} due to link fail", 299 log.debug("Computing the impacted routes for device {} due to link fail",
285 sw.id()); 300 sw.id());
286 if (!srManager.mastershipService.isLocalMaster(sw.id())) { 301 if (!srManager.mastershipService.isLocalMaster(sw.id())) {
302 + log.debug("No mastership for {} .. skipping route optimization",
303 + sw.id());
287 continue; 304 continue;
288 } 305 }
289 EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id()); 306 EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
290 if (ecmpSpg == null) { 307 if (ecmpSpg == null) {
291 - log.error("No existing ECMP graph for switch {}", sw.id()); 308 + log.warn("No existing ECMP graph for switch {}. Aborting optimized"
292 - continue; 309 + + " rerouting and opting for full-reroute", sw.id());
310 + return null;
293 } 311 }
294 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = 312 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
295 ecmpSpg.getAllLearnedSwitchesAndVia(); 313 ecmpSpg.getAllLearnedSwitchesAndVia();
296 for (Integer itrIdx : switchVia.keySet()) { 314 for (Integer itrIdx : switchVia.keySet()) {
315 + log.trace("Iterindex# {}", itrIdx);
297 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap = 316 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
298 switchVia.get(itrIdx); 317 switchVia.get(itrIdx);
299 for (DeviceId targetSw : swViaMap.keySet()) { 318 for (DeviceId targetSw : swViaMap.keySet()) {
300 DeviceId destSw = sw.id(); 319 DeviceId destSw = sw.id();
320 + if (log.isTraceEnabled()) {
321 + log.trace("TargetSwitch {} --> RootSwitch {}", targetSw, destSw);
322 + for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
323 + log.trace(" Via:");
324 + via.forEach(e -> { log.trace(" {}", e); });
325 + }
326 + }
301 Set<ArrayList<DeviceId>> subLinks = 327 Set<ArrayList<DeviceId>> subLinks =
302 computeLinks(targetSw, destSw, swViaMap); 328 computeLinks(targetSw, destSw, swViaMap);
303 for (ArrayList<DeviceId> alink: subLinks) { 329 for (ArrayList<DeviceId> alink: subLinks) {
...@@ -327,20 +353,18 @@ public class DefaultRoutingHandler { ...@@ -327,20 +353,18 @@ public class DefaultRoutingHandler {
327 Set<ArrayList<DeviceId>> routes = new HashSet<>(); 353 Set<ArrayList<DeviceId>> routes = new HashSet<>();
328 354
329 for (Device sw : srManager.deviceService.getDevices()) { 355 for (Device sw : srManager.deviceService.getDevices()) {
330 - log.debug("Computing the impacted routes for device {}", 356 + log.debug("Computing the impacted routes for device {}", sw.id());
331 - sw.id());
332 if (!srManager.mastershipService.isLocalMaster(sw.id())) { 357 if (!srManager.mastershipService.isLocalMaster(sw.id())) {
333 - log.debug("No mastership for {} and skip route optimization", 358 + log.debug("No mastership for {} ... skipping route optimization",
334 sw.id()); 359 sw.id());
335 continue; 360 continue;
336 } 361 }
337 - 362 + if (log.isTraceEnabled()) {
338 log.trace("link of {} - ", sw.id()); 363 log.trace("link of {} - ", sw.id());
339 for (Link link: srManager.linkService.getDeviceLinks(sw.id())) { 364 for (Link link: srManager.linkService.getDeviceLinks(sw.id())) {
340 log.trace("{} -> {} ", link.src().deviceId(), link.dst().deviceId()); 365 log.trace("{} -> {} ", link.src().deviceId(), link.dst().deviceId());
341 } 366 }
342 - 367 + }
343 - log.debug("Checking route change for switch {}", sw.id());
344 EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id()); 368 EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
345 if (ecmpSpg == null) { 369 if (ecmpSpg == null) {
346 log.debug("No existing ECMP graph for device {}", sw.id()); 370 log.debug("No existing ECMP graph for device {}", sw.id());
...@@ -363,7 +387,7 @@ public class DefaultRoutingHandler { ...@@ -363,7 +387,7 @@ public class DefaultRoutingHandler {
363 ArrayList<ArrayList<DeviceId>> viaUpdated = swViaMapUpdated.get(srcSw); 387 ArrayList<ArrayList<DeviceId>> viaUpdated = swViaMapUpdated.get(srcSw);
364 ArrayList<ArrayList<DeviceId>> via = getVia(switchVia, srcSw); 388 ArrayList<ArrayList<DeviceId>> via = getVia(switchVia, srcSw);
365 if ((via == null) || !viaUpdated.equals(via)) { 389 if ((via == null) || !viaUpdated.equals(via)) {
366 - log.debug("Impacted route:{}->{}", srcSw, sw.id()); 390 + log.debug("Impacted route:{} -> {}", srcSw, sw.id());
367 ArrayList<DeviceId> route = new ArrayList<>(); 391 ArrayList<DeviceId> route = new ArrayList<>();
368 route.add(srcSw); 392 route.add(srcSw);
369 route.add(sw.id()); 393 route.add(sw.id());
...@@ -373,15 +397,16 @@ public class DefaultRoutingHandler { ...@@ -373,15 +397,16 @@ public class DefaultRoutingHandler {
373 } 397 }
374 } 398 }
375 399
400 + if (log.isTraceEnabled()) {
376 for (ArrayList<DeviceId> link: routes) { 401 for (ArrayList<DeviceId> link: routes) {
377 log.trace("Route changes - "); 402 log.trace("Route changes - ");
378 if (link.size() == 1) { 403 if (link.size() == 1) {
379 - log.trace(" : {} - all", link.get(0)); 404 + log.trace(" : all -> {}", link.get(0));
380 } else { 405 } else {
381 - log.trace(" : {} - {}", link.get(0), link.get(1)); 406 + log.trace(" : {} -> {}", link.get(0), link.get(1));
407 + }
382 } 408 }
383 } 409 }
384 -
385 return routes; 410 return routes;
386 } 411 }
387 412
......
...@@ -718,6 +718,17 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -718,6 +718,17 @@ public class SegmentRoutingManager implements SegmentRoutingService {
718 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) { 718 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
719 processPortRemoved((Device) event.subject(), 719 processPortRemoved((Device) event.subject(),
720 ((DeviceEvent) event).port()); 720 ((DeviceEvent) event).port());
721 + } else if (event.type() == DeviceEvent.Type.PORT_ADDED ||
722 + event.type() == DeviceEvent.Type.PORT_UPDATED) {
723 + log.info("** PORT ADDED OR UPDATED {}/{} -> {}",
724 + (Device) event.subject(),
725 + ((DeviceEvent) event).port(),
726 + event.type());
727 + /* XXX create method for single port filtering rules
728 + if (defaultRoutingHandler != null) {
729 + defaultRoutingHandler.populatePortAddressingRules(
730 + ((Device) event.subject()).id());
731 + }*/
721 } else { 732 } else {
722 log.warn("Unhandled event type: {}", event.type()); 733 log.warn("Unhandled event type: {}", event.type());
723 } 734 }
...@@ -730,7 +741,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -730,7 +741,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
730 } 741 }
731 742
732 private void processLinkAdded(Link link) { 743 private void processLinkAdded(Link link) {
733 - log.debug("A new link {} was added", link.toString()); 744 + log.info("** LINK ADDED {}", link.toString());
734 if (!deviceConfiguration.isConfigured(link.src().deviceId())) { 745 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
735 log.warn("Source device of this link is not configured."); 746 log.warn("Source device of this link is not configured.");
736 return; 747 return;
...@@ -767,7 +778,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -767,7 +778,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
767 } 778 }
768 779
769 private void processLinkRemoved(Link link) { 780 private void processLinkRemoved(Link link) {
770 - log.debug("A link {} was removed", link.toString()); 781 + log.info("** LINK REMOVED {}", link.toString());
771 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId()); 782 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
772 if (groupHandler != null) { 783 if (groupHandler != null) {
773 groupHandler.portDown(link.src().port(), 784 groupHandler.portDown(link.src().port(),
...@@ -782,7 +793,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -782,7 +793,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
782 } 793 }
783 794
784 private void processDeviceAdded(Device device) { 795 private void processDeviceAdded(Device device) {
785 - log.debug("A new device with ID {} was added", device.id()); 796 + log.info("** DEVICE ADDED with ID {}", device.id());
786 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) { 797 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
787 log.warn("Device configuration uploading. Device {} will be " 798 log.warn("Device configuration uploading. Device {} will be "
788 + "processed after config completes.", device.id()); 799 + "processed after config completes.", device.id());
...@@ -816,12 +827,13 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -816,12 +827,13 @@ public class SegmentRoutingManager implements SegmentRoutingService {
816 log.debug("updating groupHandlerMap with new config for device: {}", 827 log.debug("updating groupHandlerMap with new config for device: {}",
817 deviceId); 828 deviceId);
818 groupHandlerMap.put(deviceId, groupHandler); 829 groupHandlerMap.put(deviceId, groupHandler);
830 + }
819 // Also, in some cases, drivers may need extra 831 // Also, in some cases, drivers may need extra
820 // information to process rules (eg. Router IP/MAC); and so, we send 832 // information to process rules (eg. Router IP/MAC); and so, we send
821 // port addressing rules to the driver as well irrespective of whether 833 // port addressing rules to the driver as well irrespective of whether
822 // this instance is the master or not. 834 // this instance is the master or not.
823 defaultRoutingHandler.populatePortAddressingRules(deviceId); 835 defaultRoutingHandler.populatePortAddressingRules(deviceId);
824 - } 836 +
825 if (mastershipService.isLocalMaster(deviceId)) { 837 if (mastershipService.isLocalMaster(deviceId)) {
826 hostHandler.readInitialHosts(deviceId); 838 hostHandler.readInitialHosts(deviceId);
827 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId); 839 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
...@@ -866,7 +878,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -866,7 +878,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
866 } 878 }
867 879
868 private void processPortRemoved(Device device, Port port) { 880 private void processPortRemoved(Device device, Port port) {
869 - log.debug("Port {} was removed", port.toString()); 881 + log.info("Port {} was removed", port.toString());
870 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 882 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
871 if (groupHandler != null) { 883 if (groupHandler != null) {
872 groupHandler.portDown(port.number(), 884 groupHandler.portDown(port.number(),
......
...@@ -23,6 +23,8 @@ import org.onosproject.net.flowobjective.FlowObjectiveService; ...@@ -23,6 +23,8 @@ import org.onosproject.net.flowobjective.FlowObjectiveService;
23 import org.onosproject.net.flowobjective.ForwardingObjective; 23 import org.onosproject.net.flowobjective.ForwardingObjective;
24 import org.onosproject.net.flowobjective.NextObjective; 24 import org.onosproject.net.flowobjective.NextObjective;
25 25
26 +import com.google.common.collect.ImmutableList;
27 +
26 /** 28 /**
27 * Testing version of implementation on FlowObjectiveService. 29 * Testing version of implementation on FlowObjectiveService.
28 */ 30 */
...@@ -60,6 +62,11 @@ public class FlowObjectiveAdapter implements FlowObjectiveService { ...@@ -60,6 +62,11 @@ public class FlowObjectiveAdapter implements FlowObjectiveService {
60 62
61 @Override 63 @Override
62 public List<String> getNextMappings() { 64 public List<String> getNextMappings() {
63 - return null; 65 + return ImmutableList.of();
66 + }
67 +
68 + @Override
69 + public List<String> getPendingNexts() {
70 + return ImmutableList.of();
64 } 71 }
65 } 72 }
......
...@@ -16,30 +16,30 @@ ...@@ -16,30 +16,30 @@
16 package org.onosproject.cli.net; 16 package org.onosproject.cli.net;
17 17
18 import java.util.List; 18 import java.util.List;
19 +import org.onlab.osgi.ServiceNotFoundException;
19 20
20 -//import org.apache.karaf.shell.commands.Argument;
21 import org.apache.karaf.shell.commands.Command; 21 import org.apache.karaf.shell.commands.Command;
22 import org.onosproject.cli.AbstractShellCommand; 22 import org.onosproject.cli.AbstractShellCommand;
23 import org.onosproject.net.flowobjective.FlowObjectiveService; 23 import org.onosproject.net.flowobjective.FlowObjectiveService;
24 24
25 /** 25 /**
26 * Returns a mapping of FlowObjective next-ids to the groups that get created 26 * Returns a mapping of FlowObjective next-ids to the groups that get created
27 - * by a device driver. 27 + * by a device driver. These mappings are controller instance specific.
28 */ 28 */
29 -@Command(scope = "onos", name = "next-ids", 29 +@Command(scope = "onos", name = "obj-next-ids",
30 - description = "flow-objective next-ids to group-ids mapping") 30 + description = "flow-objectives next-ids to group-ids mapping")
31 public class FlowObjectiveNextListCommand extends AbstractShellCommand { 31 public class FlowObjectiveNextListCommand extends AbstractShellCommand {
32 32
33 - /*@Argument(index = 1, name = "uri", description = "Device ID", 33 + private static final String FORMAT_MAPPING = " %s";
34 - required = false, multiValued = false) 34 +
35 - String uri = null;
36 - */
37 - private static final String FORMAT_MAPPING =
38 - " %s";
39 @Override 35 @Override
40 protected void execute() { 36 protected void execute() {
37 + try {
41 FlowObjectiveService service = get(FlowObjectiveService.class); 38 FlowObjectiveService service = get(FlowObjectiveService.class);
42 printNexts(service.getNextMappings()); 39 printNexts(service.getNextMappings());
40 + } catch (ServiceNotFoundException e) {
41 + print(FORMAT_MAPPING, "FlowObjectiveService unavailable");
42 + }
43 } 43 }
44 44
45 private void printNexts(List<String> nextGroupMappings) { 45 private void printNexts(List<String> nextGroupMappings) {
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.cli.net;
17 +
18 +import java.util.List;
19 +
20 +import org.apache.karaf.shell.commands.Command;
21 +import org.onlab.osgi.ServiceNotFoundException;
22 +import org.onosproject.cli.AbstractShellCommand;
23 +import org.onosproject.net.flowobjective.FlowObjectiveService;
24 +
25 +/**
26 + * Returns a list of FlowObjective next-ids waiting to get created by device-drivers.
27 + * Also returns the forwarding objectives waiting on the pending next-objectives.
28 + * These lists are controller instance specific.
29 + */
30 +@Command(scope = "onos", name = "obj-pending-nexts",
31 + description = "flow-objectives pending next-objectives")
32 +public class FlowObjectivePendingNextCommand extends AbstractShellCommand {
33 +
34 + private static final String FORMAT_MAPPING = " %s";
35 +
36 + @Override
37 + protected void execute() {
38 + try {
39 + FlowObjectiveService service = get(FlowObjectiveService.class);
40 + printNexts(service.getPendingNexts());
41 + } catch (ServiceNotFoundException e) {
42 + print(FORMAT_MAPPING, "FlowObjectiveService unavailable");
43 + }
44 + }
45 +
46 + private void printNexts(List<String> pendingNexts) {
47 + pendingNexts.forEach(str -> print(FORMAT_MAPPING, str));
48 + }
49 +
50 +}
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
31 </command> 31 </command>
32 32
33 <command> 33 <command>
34 + <action class="org.onosproject.cli.net.FlowObjectivePendingNextCommand"/>
35 + </command>
36 +
37 + <command>
34 <action class="org.onosproject.cli.net.FlowObjectiveCompositionCommand"/> 38 <action class="org.onosproject.cli.net.FlowObjectiveCompositionCommand"/>
35 </command> 39 </command>
36 40
......
...@@ -95,7 +95,18 @@ public interface FlowObjectiveService { ...@@ -95,7 +95,18 @@ public interface FlowObjectiveService {
95 * 95 *
96 * @return a list of strings preformatted by the device-drivers to provide 96 * @return a list of strings preformatted by the device-drivers to provide
97 * information on next-id to group-id mapping. Consumed by the 97 * information on next-id to group-id mapping. Consumed by the
98 - * "next-ids" command on the CLI. 98 + * "obj-next-ids" command on the CLI.
99 */ 99 */
100 List<String> getNextMappings(); 100 List<String> getNextMappings();
101 +
102 + /**
103 + * Retrieve all nextObjectives that are waiting to hear back from device
104 + * drivers, and the forwarding-objectives that are waiting on the
105 + * successful completion of the next-objectives. Consumed by the
106 + * "obj-pending-nexts" command on the CLI.
107 + *
108 + * @return a list of strings preformatted to provide information on the
109 + * next-ids awaiting confirmation from the device-drivers.
110 + */
111 + List<String> getPendingNexts();
101 } 112 }
......
...@@ -482,4 +482,21 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -482,4 +482,21 @@ public class FlowObjectiveManager implements FlowObjectiveService {
482 } 482 }
483 return mappings; 483 return mappings;
484 } 484 }
485 +
486 + @Override
487 + public List<String> getPendingNexts() {
488 + List<String> pendingNexts = new ArrayList<>();
489 + for (Integer nextId : pendingForwards.keySet()) {
490 + Set<PendingNext> pnext = pendingForwards.get(nextId);
491 + StringBuffer pend = new StringBuffer();
492 + pend.append("Next Id: ").append(Integer.toString(nextId))
493 + .append(" :: ");
494 + for (PendingNext pn : pnext) {
495 + pend.append(Integer.toString(pn.forwardingObjective().id()))
496 + .append(" ");
497 + }
498 + pendingNexts.add(pend.toString());
499 + }
500 + return pendingNexts;
501 + }
485 } 502 }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.flowobjective.impl.composition; 16 package org.onosproject.net.flowobjective.impl.composition;
17 17
18 +import com.google.common.collect.ImmutableList;
18 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
19 import com.google.common.collect.Sets; 20 import com.google.common.collect.Sets;
20 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
...@@ -440,6 +441,12 @@ public class FlowObjectiveCompositionManager implements FlowObjectiveService { ...@@ -440,6 +441,12 @@ public class FlowObjectiveCompositionManager implements FlowObjectiveService {
440 @Override 441 @Override
441 public List<String> getNextMappings() { 442 public List<String> getNextMappings() {
442 // TODO Implementation deferred as this is an experimental component. 443 // TODO Implementation deferred as this is an experimental component.
443 - return null; 444 + return ImmutableList.of();
445 + }
446 +
447 + @Override
448 + public List<String> getPendingNexts() {
449 + // TODO Implementation deferred as this is an experimental component.
450 + return ImmutableList.of();
444 } 451 }
445 } 452 }
......
...@@ -1083,7 +1083,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -1083,7 +1083,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
1083 } 1083 }
1084 // add port information for last group in group-chain 1084 // add port information for last group in group-chain
1085 List<Instruction> lastGroupIns = new ArrayList<Instruction>(); 1085 List<Instruction> lastGroupIns = new ArrayList<Instruction>();
1086 - if (gchain != null) { 1086 + if (lastGroup != null) {
1087 lastGroupIns = lastGroup.buckets().buckets().get(0) 1087 lastGroupIns = lastGroup.buckets().buckets().get(0)
1088 .treatment().allInstructions(); 1088 .treatment().allInstructions();
1089 } 1089 }
......