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 @@
*/
package org.onosproject.sfc.util;
import java.util.List;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
......@@ -55,4 +57,9 @@ public class FlowObjectiveAdapter implements FlowObjectiveService {
public ForwardingObjective forwardingObjective() {
return forwardingObjective;
}
@Override
public List<String> getNextMappings() {
return null;
}
}
......
package org.onosproject.cli.net;
import java.util.List;
//import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.flowobjective.FlowObjectiveService;
/**
* Returns a mapping of FlowObjective next-ids to the groups that get created
* by a device driver.
*/
@Command(scope = "onos", name = "next-ids",
description = "flow-objective next-ids to group-ids mapping")
public class FlowObjectiveNextListCommand extends AbstractShellCommand {
/*@Argument(index = 1, name = "uri", description = "Device ID",
required = false, multiValued = false)
String uri = null;
*/
private static final String FORMAT_MAPPING =
" %s";
@Override
protected void execute() {
FlowObjectiveService service = get(FlowObjectiveService.class);
printNexts(service.getNextMappings());
}
private void printNexts(List<String> nextGroupMappings) {
nextGroupMappings.forEach(str -> print(FORMAT_MAPPING, str));
}
}
......@@ -27,6 +27,10 @@
</command>
<command>
<action class="org.onosproject.cli.net.FlowObjectiveNextListCommand"/>
</command>
<command>
<action class="org.onosproject.cli.net.FlowObjectiveCompositionCommand"/>
</command>
......
......@@ -15,6 +15,8 @@
*/
package org.onosproject.net.behaviour;
import java.util.List;
import org.onosproject.net.DeviceId;
import org.onosproject.net.driver.HandlerBehaviour;
import org.onosproject.net.flowobjective.FilteringObjective;
......@@ -54,4 +56,18 @@ public interface Pipeliner extends HandlerBehaviour {
* @param nextObjective a next objectives
*/
void next(NextObjective nextObjective);
/**
* Retrieves a mapping of the nextObjective to the groups in the dataplane,
* and returns it in a form that can be displayed on the CLI. Typically
* group-ids are returned for groups with multiple buckets, where each list element
* represents a bucket. For nextObjectives that are converted to flow-actions,
* an empty list is returned.
*
* @param nextGroup representation of the nextObjective. This representation
* is stored in the distributed group store
* @return a list of preformatted strings representing group information, or
* an empty list if no groups were created
*/
List<String> getNextMappings(NextGroup nextGroup);
}
......
......@@ -16,6 +16,9 @@
package org.onosproject.net.flowobjective;
import com.google.common.annotations.Beta;
import java.util.List;
import org.onosproject.net.DeviceId;
/**
......@@ -82,4 +85,17 @@ public interface FlowObjectiveService {
throw new UnsupportedOperationException("Unsupported objective of type " + objective.getClass());
}
}
/**
* Retrieve all nextObjective to group mappings known to this onos instance,
* in a format meant for display on the CLI, to help with debugging. Applications
* are only aware of next-Ids, while the group sub-system is only aware of group-ids.
* This method fills in the gap by providing information on the mapping
* between next-ids and group-ids done by device-drivers.
*
* @return a list of strings preformatted by the device-drivers to provide
* information on next-id to group-id mapping. Consumed by the
* "next-ids" command on the CLI.
*/
List<String> getNextMappings();
}
......
......@@ -16,6 +16,9 @@
package org.onosproject.net.flowobjective;
import com.google.common.annotations.Beta;
import java.util.Map;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.store.Store;
......@@ -53,6 +56,13 @@ public interface FlowObjectiveStore
NextGroup removeNextGroup(Integer nextId);
/**
* Fetch all groups from the store and their mapping to nextIds.
*
* @return a map that represents the current snapshot of Next-ids to NextGroups
*/
Map<Integer, NextGroup> getAllGroups();
/**
* Allocates a next objective id. This id is globally unique
*
* @return an integer
......
......@@ -15,6 +15,8 @@
*/
package org.onosproject.net.behaviour;
import java.util.List;
import org.onosproject.net.DeviceId;
import org.onosproject.net.driver.DriverData;
import org.onosproject.net.driver.DriverHandler;
......@@ -65,4 +67,9 @@ public class PipelinerAdapter implements Pipeliner {
public void setData(DriverData data) {
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
return null;
}
}
......
......@@ -30,6 +30,7 @@ import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.device.DeviceEvent;
......@@ -53,7 +54,9 @@ import org.onosproject.net.group.GroupService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
......@@ -123,6 +126,10 @@ public class FlowObjectiveManager implements FlowObjectiveService {
private Map<Integer, Set<PendingNext>> pendingForwards = Maps.newConcurrentMap();
// local store to track which nextObjectives were sent to which device
// for debugging purposes
private Map<Integer, DeviceId> nextToDevice = Maps.newConcurrentMap();
private ExecutorService executorService;
@Activate
......@@ -143,6 +150,7 @@ public class FlowObjectiveManager implements FlowObjectiveService {
executorService.shutdown();
pipeliners.clear();
driverHandlers.clear();
nextToDevice.clear();
log.info("Stopped");
}
......@@ -215,6 +223,7 @@ public class FlowObjectiveManager implements FlowObjectiveService {
@Override
public void next(DeviceId deviceId, NextObjective nextObjective) {
checkPermission(FLOWRULE_WRITE);
nextToDevice.put(nextObjective.id(), deviceId);
executorService.submit(new ObjectiveInstaller(deviceId, nextObjective));
}
......@@ -443,4 +452,33 @@ public class FlowObjectiveManager implements FlowObjectiveService {
return false;
}
}
@Override
public List<String> getNextMappings() {
List<String> mappings = new ArrayList<>();
Map<Integer, NextGroup> allnexts = flowObjectiveStore.getAllGroups();
// XXX if the NextGroup upon decoding stored info of the deviceId
// then info on any nextObj could be retrieved from one controller instance.
// Right now the drivers on one instance can only fetch for next-ids that came
// to them.
// Also, we still need to send the right next-id to the right driver as potentially
// there can be different drivers for different devices. But on that account,
// no instance should be decoding for another instance's nextIds.
for (Map.Entry<Integer, NextGroup> e : allnexts.entrySet()) {
// get the device this next Objective was sent to
DeviceId deviceId = nextToDevice.get(e.getKey());
mappings.add("NextId " + e.getKey() + ": " +
((deviceId != null) ? deviceId : "nextId not in this onos instance"));
if (deviceId != null) {
// this instance of the controller sent the nextObj to a driver
Pipeliner pipeliner = getDevicePipeliner(deviceId);
List<String> nextMappings = pipeliner.getNextMappings(e.getValue());
if (nextMappings != null) {
mappings.addAll(nextMappings);
}
}
}
return mappings;
}
}
......
......@@ -436,4 +436,10 @@ public class FlowObjectiveCompositionManager implements FlowObjectiveService {
str += ")";
return str;
}
@Override
public List<String> getNextMappings() {
// TODO Implementation deferred as this is an experimental component.
return null;
}
}
......
......@@ -15,6 +15,8 @@
*/
package org.onosproject.net.flowobjective.impl;
import java.util.Map;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
......@@ -57,4 +59,9 @@ public class FlowObjectiveStoreAdapter implements FlowObjectiveStore {
public boolean hasDelegate() {
return false;
}
@Override
public Map<Integer, NextGroup> getAllGroups() {
return null;
}
}
......
......@@ -37,6 +37,9 @@ import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.HashMap;
import java.util.Map;
/**
* Manages the inventory of created next groups.
*/
......@@ -106,6 +109,18 @@ public class DistributedFlowObjectiveStore
}
@Override
public Map<Integer, NextGroup> getAllGroups() {
Map<Integer, NextGroup> nextGroupMappings = new HashMap<>();
for (int key : nextGroups.keySet()) {
NextGroup nextGroup = getNextGroup(key);
if (nextGroup != null) {
nextGroupMappings.put(key, nextGroup);
}
}
return nextGroupMappings;
}
@Override
public int allocateNextId() {
return (int) nextIds.incrementAndGet();
}
......
......@@ -74,6 +74,7 @@ import org.slf4j.Logger;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executors;
......@@ -634,4 +635,10 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe
}
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// TODO Implementation deferred to vendor
return null;
}
}
......
......@@ -17,6 +17,7 @@ package org.onosproject.driver.pipeline;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
......@@ -39,6 +40,8 @@ import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.List;
/**
* Simple single table pipeline abstraction.
*/
......@@ -167,4 +170,10 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme
public void next(NextObjective nextObjective) {
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// Default single table pipeline does not use nextObjectives or groups
return null;
}
}
......
......@@ -1029,4 +1029,28 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
protected static void fail(Objective obj, ObjectiveError error) {
obj.context().ifPresent(context -> context.onError(obj, error));
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
List<String> mappings = new ArrayList<>();
List<Deque<GroupKey>> gkeys = appKryo.deserialize(nextGroup.data());
for (Deque<GroupKey> gkd : gkeys) {
Group lastGroup = null;
String gchain = "";
for (GroupKey gk : gkd) {
Group g = groupService.getGroup(deviceId, gk);
gchain += " 0x" + Integer.toHexString(g.id().id()) + " -->";
lastGroup = g;
}
// add port information for last group in group-chain
for (Instruction i: lastGroup.buckets().buckets().get(0).treatment().allInstructions()) {
if (i instanceof OutputInstruction) {
gchain += " port:" + ((OutputInstruction) i).port();
}
}
mappings.add(gchain);
}
return mappings;
}
}
......
......@@ -72,6 +72,7 @@ import org.slf4j.Logger;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executors;
......@@ -857,4 +858,10 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
}
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// TODO Implementation deferred to vendor
return null;
}
}
......
......@@ -702,4 +702,10 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
}
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// TODO Implementation deferred to vendor
return null;
}
}
......
......@@ -537,4 +537,10 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner
return appKryo.serialize(nextActions);
}
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// TODO Implementation deferred to vendor
return null;
}
}
......
......@@ -57,6 +57,7 @@ import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static org.onlab.util.Tools.delay;
......@@ -467,4 +468,10 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// nextObjectives converted to flow-actions not groups
return Collections.emptyList();
}
}
......
......@@ -1126,4 +1126,10 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
}
}
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
// TODO Implementation deferred to vendor
return null;
}
}
......