Saurav Das
Committed by Ray Milkey

CLI command to help debug the mapping of next-Objectives to the

groups that are created by device drivers.

Change-Id: Iff9e04e5e96b2cabbdb40e83215315d2e27791a6
Showing 19 changed files with 231 additions and 0 deletions
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.sfc.util; 16 package org.onosproject.sfc.util;
17 17
18 +import java.util.List;
19 +
18 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
19 import org.onosproject.net.flowobjective.FilteringObjective; 21 import org.onosproject.net.flowobjective.FilteringObjective;
20 import org.onosproject.net.flowobjective.FlowObjectiveService; 22 import org.onosproject.net.flowobjective.FlowObjectiveService;
...@@ -55,4 +57,9 @@ public class FlowObjectiveAdapter implements FlowObjectiveService { ...@@ -55,4 +57,9 @@ public class FlowObjectiveAdapter implements FlowObjectiveService {
55 public ForwardingObjective forwardingObjective() { 57 public ForwardingObjective forwardingObjective() {
56 return forwardingObjective; 58 return forwardingObjective;
57 } 59 }
60 +
61 + @Override
62 + public List<String> getNextMappings() {
63 + return null;
64 + }
58 } 65 }
......
1 +package org.onosproject.cli.net;
2 +
3 +import java.util.List;
4 +
5 +//import org.apache.karaf.shell.commands.Argument;
6 +import org.apache.karaf.shell.commands.Command;
7 +import org.onosproject.cli.AbstractShellCommand;
8 +import org.onosproject.net.flowobjective.FlowObjectiveService;
9 +
10 +/**
11 + * Returns a mapping of FlowObjective next-ids to the groups that get created
12 + * by a device driver.
13 + */
14 +@Command(scope = "onos", name = "next-ids",
15 + description = "flow-objective next-ids to group-ids mapping")
16 +public class FlowObjectiveNextListCommand extends AbstractShellCommand {
17 +
18 + /*@Argument(index = 1, name = "uri", description = "Device ID",
19 + required = false, multiValued = false)
20 + String uri = null;
21 + */
22 + private static final String FORMAT_MAPPING =
23 + " %s";
24 + @Override
25 + protected void execute() {
26 + FlowObjectiveService service = get(FlowObjectiveService.class);
27 + printNexts(service.getNextMappings());
28 + }
29 +
30 + private void printNexts(List<String> nextGroupMappings) {
31 + nextGroupMappings.forEach(str -> print(FORMAT_MAPPING, str));
32 + }
33 +}
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
27 </command> 27 </command>
28 28
29 <command> 29 <command>
30 + <action class="org.onosproject.cli.net.FlowObjectiveNextListCommand"/>
31 + </command>
32 +
33 + <command>
30 <action class="org.onosproject.cli.net.FlowObjectiveCompositionCommand"/> 34 <action class="org.onosproject.cli.net.FlowObjectiveCompositionCommand"/>
31 </command> 35 </command>
32 36
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.net.behaviour; 16 package org.onosproject.net.behaviour;
17 17
18 +import java.util.List;
19 +
18 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
19 import org.onosproject.net.driver.HandlerBehaviour; 21 import org.onosproject.net.driver.HandlerBehaviour;
20 import org.onosproject.net.flowobjective.FilteringObjective; 22 import org.onosproject.net.flowobjective.FilteringObjective;
...@@ -54,4 +56,18 @@ public interface Pipeliner extends HandlerBehaviour { ...@@ -54,4 +56,18 @@ public interface Pipeliner extends HandlerBehaviour {
54 * @param nextObjective a next objectives 56 * @param nextObjective a next objectives
55 */ 57 */
56 void next(NextObjective nextObjective); 58 void next(NextObjective nextObjective);
59 +
60 + /**
61 + * Retrieves a mapping of the nextObjective to the groups in the dataplane,
62 + * and returns it in a form that can be displayed on the CLI. Typically
63 + * group-ids are returned for groups with multiple buckets, where each list element
64 + * represents a bucket. For nextObjectives that are converted to flow-actions,
65 + * an empty list is returned.
66 + *
67 + * @param nextGroup representation of the nextObjective. This representation
68 + * is stored in the distributed group store
69 + * @return a list of preformatted strings representing group information, or
70 + * an empty list if no groups were created
71 + */
72 + List<String> getNextMappings(NextGroup nextGroup);
57 } 73 }
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
16 package org.onosproject.net.flowobjective; 16 package org.onosproject.net.flowobjective;
17 17
18 import com.google.common.annotations.Beta; 18 import com.google.common.annotations.Beta;
19 +
20 +import java.util.List;
21 +
19 import org.onosproject.net.DeviceId; 22 import org.onosproject.net.DeviceId;
20 23
21 /** 24 /**
...@@ -82,4 +85,17 @@ public interface FlowObjectiveService { ...@@ -82,4 +85,17 @@ public interface FlowObjectiveService {
82 throw new UnsupportedOperationException("Unsupported objective of type " + objective.getClass()); 85 throw new UnsupportedOperationException("Unsupported objective of type " + objective.getClass());
83 } 86 }
84 } 87 }
88 +
89 + /**
90 + * Retrieve all nextObjective to group mappings known to this onos instance,
91 + * in a format meant for display on the CLI, to help with debugging. Applications
92 + * are only aware of next-Ids, while the group sub-system is only aware of group-ids.
93 + * This method fills in the gap by providing information on the mapping
94 + * between next-ids and group-ids done by device-drivers.
95 + *
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
98 + * "next-ids" command on the CLI.
99 + */
100 + List<String> getNextMappings();
85 } 101 }
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
16 package org.onosproject.net.flowobjective; 16 package org.onosproject.net.flowobjective;
17 17
18 import com.google.common.annotations.Beta; 18 import com.google.common.annotations.Beta;
19 +
20 +import java.util.Map;
21 +
19 import org.onosproject.net.behaviour.NextGroup; 22 import org.onosproject.net.behaviour.NextGroup;
20 import org.onosproject.store.Store; 23 import org.onosproject.store.Store;
21 24
...@@ -53,6 +56,13 @@ public interface FlowObjectiveStore ...@@ -53,6 +56,13 @@ public interface FlowObjectiveStore
53 NextGroup removeNextGroup(Integer nextId); 56 NextGroup removeNextGroup(Integer nextId);
54 57
55 /** 58 /**
59 + * Fetch all groups from the store and their mapping to nextIds.
60 + *
61 + * @return a map that represents the current snapshot of Next-ids to NextGroups
62 + */
63 + Map<Integer, NextGroup> getAllGroups();
64 +
65 + /**
56 * Allocates a next objective id. This id is globally unique 66 * Allocates a next objective id. This id is globally unique
57 * 67 *
58 * @return an integer 68 * @return an integer
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.net.behaviour; 16 package org.onosproject.net.behaviour;
17 17
18 +import java.util.List;
19 +
18 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
19 import org.onosproject.net.driver.DriverData; 21 import org.onosproject.net.driver.DriverData;
20 import org.onosproject.net.driver.DriverHandler; 22 import org.onosproject.net.driver.DriverHandler;
...@@ -65,4 +67,9 @@ public class PipelinerAdapter implements Pipeliner { ...@@ -65,4 +67,9 @@ public class PipelinerAdapter implements Pipeliner {
65 public void setData(DriverData data) { 67 public void setData(DriverData data) {
66 68
67 } 69 }
70 +
71 + @Override
72 + public List<String> getNextMappings(NextGroup nextGroup) {
73 + return null;
74 + }
68 } 75 }
......
...@@ -30,6 +30,7 @@ import org.onosproject.mastership.MastershipEvent; ...@@ -30,6 +30,7 @@ import org.onosproject.mastership.MastershipEvent;
30 import org.onosproject.mastership.MastershipListener; 30 import org.onosproject.mastership.MastershipListener;
31 import org.onosproject.mastership.MastershipService; 31 import org.onosproject.mastership.MastershipService;
32 import org.onosproject.net.DeviceId; 32 import org.onosproject.net.DeviceId;
33 +import org.onosproject.net.behaviour.NextGroup;
33 import org.onosproject.net.behaviour.Pipeliner; 34 import org.onosproject.net.behaviour.Pipeliner;
34 import org.onosproject.net.behaviour.PipelinerContext; 35 import org.onosproject.net.behaviour.PipelinerContext;
35 import org.onosproject.net.device.DeviceEvent; 36 import org.onosproject.net.device.DeviceEvent;
...@@ -53,7 +54,9 @@ import org.onosproject.net.group.GroupService; ...@@ -53,7 +54,9 @@ import org.onosproject.net.group.GroupService;
53 import org.slf4j.Logger; 54 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory; 55 import org.slf4j.LoggerFactory;
55 56
57 +import java.util.ArrayList;
56 import java.util.Collections; 58 import java.util.Collections;
59 +import java.util.List;
57 import java.util.Map; 60 import java.util.Map;
58 import java.util.Objects; 61 import java.util.Objects;
59 import java.util.Set; 62 import java.util.Set;
...@@ -123,6 +126,10 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -123,6 +126,10 @@ public class FlowObjectiveManager implements FlowObjectiveService {
123 126
124 private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap(); 127 private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap();
125 128
129 + // local store to track which nextObjectives were sent to which device
130 + // for debugging purposes
131 + private Map<Integer, DeviceId> nextToDevice = Maps.newConcurrentMap();
132 +
126 private ExecutorService executorService; 133 private ExecutorService executorService;
127 134
128 @Activate 135 @Activate
...@@ -143,6 +150,7 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -143,6 +150,7 @@ public class FlowObjectiveManager implements FlowObjectiveService {
143 executorService.shutdown(); 150 executorService.shutdown();
144 pipeliners.clear(); 151 pipeliners.clear();
145 driverHandlers.clear(); 152 driverHandlers.clear();
153 + nextToDevice.clear();
146 log.info("Stopped"); 154 log.info("Stopped");
147 } 155 }
148 156
...@@ -215,6 +223,7 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -215,6 +223,7 @@ public class FlowObjectiveManager implements FlowObjectiveService {
215 @Override 223 @Override
216 public void next(DeviceId deviceId, NextObjective nextObjective) { 224 public void next(DeviceId deviceId, NextObjective nextObjective) {
217 checkPermission(FLOWRULE_WRITE); 225 checkPermission(FLOWRULE_WRITE);
226 + nextToDevice.put(nextObjective.id(), deviceId);
218 executorService.submit(new ObjectiveInstaller(deviceId, nextObjective)); 227 executorService.submit(new ObjectiveInstaller(deviceId, nextObjective));
219 } 228 }
220 229
...@@ -443,4 +452,33 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -443,4 +452,33 @@ public class FlowObjectiveManager implements FlowObjectiveService {
443 return false; 452 return false;
444 } 453 }
445 } 454 }
455 +
456 + @Override
457 + public List<String> getNextMappings() {
458 + List<String> mappings = new ArrayList<>();
459 + Map<Integer, NextGroup> allnexts = flowObjectiveStore.getAllGroups();
460 + // XXX if the NextGroup upon decoding stored info of the deviceId
461 + // then info on any nextObj could be retrieved from one controller instance.
462 + // Right now the drivers on one instance can only fetch for next-ids that came
463 + // to them.
464 + // Also, we still need to send the right next-id to the right driver as potentially
465 + // there can be different drivers for different devices. But on that account,
466 + // no instance should be decoding for another instance's nextIds.
467 +
468 + for (Map.Entry<Integer, NextGroup> e : allnexts.entrySet()) {
469 + // get the device this next Objective was sent to
470 + DeviceId deviceId = nextToDevice.get(e.getKey());
471 + mappings.add("NextId " + e.getKey() + ": " +
472 + ((deviceId != null) ? deviceId : "nextId not in this onos instance"));
473 + if (deviceId != null) {
474 + // this instance of the controller sent the nextObj to a driver
475 + Pipeliner pipeliner = getDevicePipeliner(deviceId);
476 + List<String> nextMappings = pipeliner.getNextMappings(e.getValue());
477 + if (nextMappings != null) {
478 + mappings.addAll(nextMappings);
479 + }
480 + }
481 + }
482 + return mappings;
483 + }
446 } 484 }
......
...@@ -436,4 +436,10 @@ public class FlowObjectiveCompositionManager implements FlowObjectiveService { ...@@ -436,4 +436,10 @@ public class FlowObjectiveCompositionManager implements FlowObjectiveService {
436 str += ")"; 436 str += ")";
437 return str; 437 return str;
438 } 438 }
439 +
440 + @Override
441 + public List<String> getNextMappings() {
442 + // TODO Implementation deferred as this is an experimental component.
443 + return null;
444 + }
439 } 445 }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.net.flowobjective.impl; 16 package org.onosproject.net.flowobjective.impl;
17 17
18 +import java.util.Map;
19 +
18 import org.onosproject.net.behaviour.NextGroup; 20 import org.onosproject.net.behaviour.NextGroup;
19 import org.onosproject.net.flowobjective.FlowObjectiveStore; 21 import org.onosproject.net.flowobjective.FlowObjectiveStore;
20 import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate; 22 import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
...@@ -57,4 +59,9 @@ public class FlowObjectiveStoreAdapter implements FlowObjectiveStore { ...@@ -57,4 +59,9 @@ public class FlowObjectiveStoreAdapter implements FlowObjectiveStore {
57 public boolean hasDelegate() { 59 public boolean hasDelegate() {
58 return false; 60 return false;
59 } 61 }
62 +
63 + @Override
64 + public Map<Integer, NextGroup> getAllGroups() {
65 + return null;
66 + }
60 } 67 }
......
...@@ -37,6 +37,9 @@ import org.slf4j.Logger; ...@@ -37,6 +37,9 @@ import org.slf4j.Logger;
37 37
38 import static org.slf4j.LoggerFactory.getLogger; 38 import static org.slf4j.LoggerFactory.getLogger;
39 39
40 +import java.util.HashMap;
41 +import java.util.Map;
42 +
40 /** 43 /**
41 * Manages the inventory of created next groups. 44 * Manages the inventory of created next groups.
42 */ 45 */
...@@ -106,6 +109,18 @@ public class DistributedFlowObjectiveStore ...@@ -106,6 +109,18 @@ public class DistributedFlowObjectiveStore
106 } 109 }
107 110
108 @Override 111 @Override
112 + public Map<Integer, NextGroup> getAllGroups() {
113 + Map<Integer, NextGroup> nextGroupMappings = new HashMap<>();
114 + for (int key : nextGroups.keySet()) {
115 + NextGroup nextGroup = getNextGroup(key);
116 + if (nextGroup != null) {
117 + nextGroupMappings.put(key, nextGroup);
118 + }
119 + }
120 + return nextGroupMappings;
121 + }
122 +
123 + @Override
109 public int allocateNextId() { 124 public int allocateNextId() {
110 return (int) nextIds.incrementAndGet(); 125 return (int) nextIds.incrementAndGet();
111 } 126 }
......
...@@ -74,6 +74,7 @@ import org.slf4j.Logger; ...@@ -74,6 +74,7 @@ import org.slf4j.Logger;
74 74
75 import java.util.Collection; 75 import java.util.Collection;
76 import java.util.Collections; 76 import java.util.Collections;
77 +import java.util.List;
77 import java.util.Objects; 78 import java.util.Objects;
78 import java.util.Set; 79 import java.util.Set;
79 import java.util.concurrent.Executors; 80 import java.util.concurrent.Executors;
...@@ -634,4 +635,10 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe ...@@ -634,4 +635,10 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe
634 } 635 }
635 636
636 } 637 }
638 +
639 + @Override
640 + public List<String> getNextMappings(NextGroup nextGroup) {
641 + // TODO Implementation deferred to vendor
642 + return null;
643 + }
637 } 644 }
......
...@@ -17,6 +17,7 @@ package org.onosproject.driver.pipeline; ...@@ -17,6 +17,7 @@ package org.onosproject.driver.pipeline;
17 17
18 import org.onlab.osgi.ServiceDirectory; 18 import org.onlab.osgi.ServiceDirectory;
19 import org.onosproject.net.DeviceId; 19 import org.onosproject.net.DeviceId;
20 +import org.onosproject.net.behaviour.NextGroup;
20 import org.onosproject.net.behaviour.Pipeliner; 21 import org.onosproject.net.behaviour.Pipeliner;
21 import org.onosproject.net.behaviour.PipelinerContext; 22 import org.onosproject.net.behaviour.PipelinerContext;
22 import org.onosproject.net.driver.AbstractHandlerBehaviour; 23 import org.onosproject.net.driver.AbstractHandlerBehaviour;
...@@ -39,6 +40,8 @@ import org.slf4j.Logger; ...@@ -39,6 +40,8 @@ import org.slf4j.Logger;
39 40
40 import static org.slf4j.LoggerFactory.getLogger; 41 import static org.slf4j.LoggerFactory.getLogger;
41 42
43 +import java.util.List;
44 +
42 /** 45 /**
43 * Simple single table pipeline abstraction. 46 * Simple single table pipeline abstraction.
44 */ 47 */
...@@ -167,4 +170,10 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme ...@@ -167,4 +170,10 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme
167 public void next(NextObjective nextObjective) { 170 public void next(NextObjective nextObjective) {
168 } 171 }
169 172
173 + @Override
174 + public List<String> getNextMappings(NextGroup nextGroup) {
175 + // Default single table pipeline does not use nextObjectives or groups
176 + return null;
177 + }
178 +
170 } 179 }
......
...@@ -1029,4 +1029,28 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -1029,4 +1029,28 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
1029 protected static void fail(Objective obj, ObjectiveError error) { 1029 protected static void fail(Objective obj, ObjectiveError error) {
1030 obj.context().ifPresent(context -> context.onError(obj, error)); 1030 obj.context().ifPresent(context -> context.onError(obj, error));
1031 } 1031 }
1032 +
1033 +
1034 + @Override
1035 + public List<String> getNextMappings(NextGroup nextGroup) {
1036 + List<String> mappings = new ArrayList<>();
1037 + List<Deque<GroupKey>> gkeys = appKryo.deserialize(nextGroup.data());
1038 + for (Deque<GroupKey> gkd : gkeys) {
1039 + Group lastGroup = null;
1040 + String gchain = "";
1041 + for (GroupKey gk : gkd) {
1042 + Group g = groupService.getGroup(deviceId, gk);
1043 + gchain += " 0x" + Integer.toHexString(g.id().id()) + " -->";
1044 + lastGroup = g;
1045 + }
1046 + // add port information for last group in group-chain
1047 + for (Instruction i: lastGroup.buckets().buckets().get(0).treatment().allInstructions()) {
1048 + if (i instanceof OutputInstruction) {
1049 + gchain += " port:" + ((OutputInstruction) i).port();
1050 + }
1051 + }
1052 + mappings.add(gchain);
1053 + }
1054 + return mappings;
1055 + }
1032 } 1056 }
......
...@@ -72,6 +72,7 @@ import org.slf4j.Logger; ...@@ -72,6 +72,7 @@ import org.slf4j.Logger;
72 72
73 import java.util.Collection; 73 import java.util.Collection;
74 import java.util.Collections; 74 import java.util.Collections;
75 +import java.util.List;
75 import java.util.Objects; 76 import java.util.Objects;
76 import java.util.Set; 77 import java.util.Set;
77 import java.util.concurrent.Executors; 78 import java.util.concurrent.Executors;
...@@ -857,4 +858,10 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli ...@@ -857,4 +858,10 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
857 } 858 }
858 859
859 } 860 }
861 +
862 + @Override
863 + public List<String> getNextMappings(NextGroup nextGroup) {
864 + // TODO Implementation deferred to vendor
865 + return null;
866 + }
860 } 867 }
......
...@@ -702,4 +702,10 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { ...@@ -702,4 +702,10 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
702 } 702 }
703 703
704 } 704 }
705 +
706 + @Override
707 + public List<String> getNextMappings(NextGroup nextGroup) {
708 + // TODO Implementation deferred to vendor
709 + return null;
710 + }
705 } 711 }
......
...@@ -537,4 +537,10 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner ...@@ -537,4 +537,10 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner
537 return appKryo.serialize(nextActions); 537 return appKryo.serialize(nextActions);
538 } 538 }
539 } 539 }
540 +
541 + @Override
542 + public List<String> getNextMappings(NextGroup nextGroup) {
543 + // TODO Implementation deferred to vendor
544 + return null;
545 + }
540 } 546 }
......
...@@ -57,6 +57,7 @@ import org.slf4j.Logger; ...@@ -57,6 +57,7 @@ import org.slf4j.Logger;
57 import java.util.ArrayList; 57 import java.util.ArrayList;
58 import java.util.Collection; 58 import java.util.Collection;
59 import java.util.Collections; 59 import java.util.Collections;
60 +import java.util.List;
60 import java.util.Objects; 61 import java.util.Objects;
61 62
62 import static org.onlab.util.Tools.delay; 63 import static org.onlab.util.Tools.delay;
...@@ -467,4 +468,10 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe ...@@ -467,4 +468,10 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe
467 468
468 } 469 }
469 470
471 + @Override
472 + public List<String> getNextMappings(NextGroup nextGroup) {
473 + // nextObjectives converted to flow-actions not groups
474 + return Collections.emptyList();
475 + }
476 +
470 } 477 }
......
...@@ -1126,4 +1126,10 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -1126,4 +1126,10 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
1126 } 1126 }
1127 1127
1128 } 1128 }
1129 +
1130 + @Override
1131 + public List<String> getNextMappings(NextGroup nextGroup) {
1132 + // TODO Implementation deferred to vendor
1133 + return null;
1134 + }
1129 } 1135 }
......