diff options
Diffstat (limited to 'framework/src/onos/cli')
12 files changed, 813 insertions, 25 deletions
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java index b0cbbdd6..1df2f049 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java @@ -25,6 +25,8 @@ import org.onosproject.net.ElementId; import org.onosproject.net.Port; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.group.Group; + +import org.onosproject.net.statistic.TypedFlowEntryWithLoad; import org.onosproject.net.topology.TopologyCluster; import java.util.Comparator; @@ -115,4 +117,12 @@ public final class Comparators { public static final Comparator<Interface> INTERFACES_COMPARATOR = (intf1, intf2) -> CONNECT_POINT_COMPARATOR.compare(intf1.connectPoint(), intf2.connectPoint()); + public static final Comparator<TypedFlowEntryWithLoad> TYPEFLOWENTRY_WITHLOAD_COMPARATOR = + new Comparator<TypedFlowEntryWithLoad>() { + @Override + public int compare(TypedFlowEntryWithLoad fe1, TypedFlowEntryWithLoad fe2) { + long delta = fe1.load().rate() - fe2.load().rate(); + return delta == 0 ? 0 : (delta > 0 ? -1 : +1); + } + }; } diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java index d99a1839..7ce56692 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java @@ -35,13 +35,13 @@ import static com.google.common.base.Strings.isNullOrEmpty; description = "Manages network configuration") public class NetworkConfigCommand extends AbstractShellCommand { - @Argument(index = 0, name = "subjectKey", description = "Subject key", + @Argument(index = 0, name = "subjectClassKey", description = "Subject class key", required = false, multiValued = false) - String subjectKey = null; + String subjectClassKey = null; - @Argument(index = 1, name = "subject", description = "Subject", + @Argument(index = 1, name = "subjectKey", description = "Subject key", required = false, multiValued = false) - String subject = null; + String subjectKey = null; @Argument(index = 2, name = "configKey", description = "Config key", required = false, multiValued = false) @@ -54,18 +54,18 @@ public class NetworkConfigCommand extends AbstractShellCommand { protected void execute() { service = get(NetworkConfigService.class); JsonNode root = mapper.createObjectNode(); - if (isNullOrEmpty(subjectKey)) { + if (isNullOrEmpty(subjectClassKey)) { addAll((ObjectNode) root); } else { - SubjectFactory subjectFactory = service.getSubjectFactory(subjectKey); - if (isNullOrEmpty(subject)) { + SubjectFactory subjectFactory = service.getSubjectFactory(subjectClassKey); + if (isNullOrEmpty(subjectKey)) { addSubjectClass((ObjectNode) root, subjectFactory); } else { - Object s = subjectFactory.createSubject(subject); + Object s = subjectFactory.createSubject(subjectKey); if (isNullOrEmpty(configKey)) { addSubject((ObjectNode) root, s); } else { - root = getSubjectConfig(getConfig(s, subjectKey, configKey)); + root = getSubjectConfig(getConfig(s, subjectClassKey, configKey)); } } } @@ -82,14 +82,14 @@ public class NetworkConfigCommand extends AbstractShellCommand { service.getSubjectClasses() .forEach(sc -> { SubjectFactory sf = service.getSubjectFactory(sc); - addSubjectClass(newObject(root, sf.subjectKey()), sf); + addSubjectClass(newObject(root, sf.subjectClassKey()), sf); }); } @SuppressWarnings("unchecked") private void addSubjectClass(ObjectNode root, SubjectFactory sf) { service.getSubjects(sf.subjectClass()) - .forEach(s -> addSubject(newObject(root, s.toString()), s)); + .forEach(s -> addSubject(newObject(root, sf.subjectKey(s)), s)); } private void addSubject(ObjectNode root, Object s) { diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java index f94967e1..cf588770 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java @@ -42,7 +42,7 @@ public class NetworkConfigRegistryCommand extends AbstractShellCommand { private void print(ConfigFactory configFactory) { print(shortOnly ? SHORT_FMT : FMT, - configFactory.subjectFactory().subjectKey(), + configFactory.subjectFactory().subjectClassKey(), configFactory.configKey(), configFactory.subjectFactory().subjectClass().getName(), configFactory.configClass().getName()); diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceControllersCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceControllersCommand.java new file mode 100644 index 00000000..328d4700 --- /dev/null +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceControllersCommand.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cli.net; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.net.DeviceId; +import org.onosproject.net.behaviour.ControllerConfig; +import org.onosproject.net.driver.DriverHandler; +import org.onosproject.net.driver.DriverService; + +/** + * Sets role of the controller node for the given infrastructure device. + */ +@Command(scope = "onos", name = "device-controllers", + description = "gets the list of controllers for the given infrastructure device") +public class DeviceControllersCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "uri", description = "Device ID", + required = true, multiValued = false) + String uri = null; + private DeviceId deviceId; + + @Override + protected void execute() { + DriverService service = get(DriverService.class); + deviceId = DeviceId.deviceId(uri); + DriverHandler h = service.createHandler(deviceId); + ControllerConfig config = h.behaviour(ControllerConfig.class); + config.getControllers().forEach(c -> print(c.target())); + } + +} diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java index 494273cc..e2d3e6d6 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 Open Networking Laboratory + * Copyright 2015 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,12 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.apache.karaf.shell.commands.Option; +import org.onlab.util.Frequency; import org.onosproject.cli.Comparators; import org.onosproject.net.Device; +import org.onosproject.net.OchPort; +import org.onosproject.net.OduCltPort; +import org.onosproject.net.OmsPort; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceService; @@ -41,7 +45,10 @@ import static org.onosproject.net.DeviceId.deviceId; description = "Lists all ports or all ports of a device") public class DevicePortsListCommand extends DevicesListCommand { - private static final String FMT = " port=%s, state=%s, type=%s, speed=%s%s"; + private static final String FMT = " port=%s, state=%s, type=%s, speed=%s %s"; + private static final String FMT_OCH = " port=%s, state=%s, type=%s, signalType=%s, isTunable=%s %s"; + private static final String FMT_ODUCLT = " port=%s, state=%s, type=%s, signalType=%s %s"; + private static final String FMT_OMS = " port=%s, state=%s, type=%s, Freqs= %s / %s / %s GHz, totalChannels=%s %s"; @Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports", required = false, multiValued = false) @@ -137,13 +144,34 @@ public class DevicePortsListCommand extends DevicesListCommand { List<Port> ports = new ArrayList<>(service.getPorts(device.id())); Collections.sort(ports, Comparators.PORT_COMPARATOR); for (Port port : ports) { - if (isIncluded(port)) { - print(FMT, portName(port.number()), - port.isEnabled() ? "enabled" : "disabled", - port.type().toString().toLowerCase(), port.portSpeed(), - annotations(port.annotations())); + if (!isIncluded(port)) { + continue; + } + String portName = portName(port.number()); + Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled"; + String portType = port.type().toString().toLowerCase(); + String annotations = annotations(port.annotations()); + switch (port.type()) { + case OCH: + print(FMT_OCH, portName, portIsEnabled, portType, + ((OchPort) port).signalType().toString(), + ((OchPort) port).isTunable() ? "yes" : "no", annotations); + break; + case ODUCLT: + print(FMT_ODUCLT, portName, portIsEnabled, portType, + ((OduCltPort) port).signalType().toString(), annotations); + break; + case OMS: + print(FMT_OMS, portName, portIsEnabled, portType, + ((OmsPort) port).minFrequency().asHz() / Frequency.ofGHz(1).asHz(), + ((OmsPort) port).maxFrequency().asHz() / Frequency.ofGHz(1).asHz(), + ((OmsPort) port).grid().asHz() / Frequency.ofGHz(1).asHz(), + ((OmsPort) port).totalChannels(), annotations); + break; + default: + print(FMT, portName, portIsEnabled, portType, port.portSpeed(), annotations); + break; } } } - } diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceSetControllersCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceSetControllersCommand.java new file mode 100644 index 00000000..c3693799 --- /dev/null +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceSetControllersCommand.java @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.cli.net; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.net.DeviceId; +import org.onosproject.net.behaviour.ControllerConfig; +import org.onosproject.net.behaviour.ControllerInfo; +import org.onosproject.net.driver.DriverHandler; +import org.onosproject.net.driver.DriverService; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Sets role of the controller node for the given infrastructure device. + */ +@Command(scope = "onos", name = "device-setcontrollers", + description = "sets the list of controllers for the given infrastructure device") +public class DeviceSetControllersCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "uri", description = "Device ID", + required = true, multiValued = false) + String uri = null; + + @Argument(index = 1, name = "controllersListStrings", description = "list of " + + "controllers to set for the specified device", + required = true, multiValued = true) + String[] controllersListStrings = null; + + private DeviceId deviceId; + private List<ControllerInfo> newControllers = new ArrayList<>(); + + @Override + protected void execute() { + + Arrays.asList(controllersListStrings).forEach( + cInfoString -> newControllers.add(new ControllerInfo(cInfoString))); + DriverService service = get(DriverService.class); + deviceId = DeviceId.deviceId(uri); + DriverHandler h = service.createHandler(deviceId); + ControllerConfig config = h.behaviour(ControllerConfig.class); + print("before:"); + config.getControllers().forEach(c -> print(c.target())); + + config.setControllers(newControllers); + print("after:"); + config.getControllers().forEach(c -> print(c.target())); + print("size %d", config.getControllers().size()); + } + +} diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetFlowStatistics.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetFlowStatistics.java new file mode 100644 index 00000000..cafe87f9 --- /dev/null +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetFlowStatistics.java @@ -0,0 +1,323 @@ +/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.TypedStoredFlowEntry;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.statistic.FlowStatisticService;
+import org.onosproject.net.statistic.SummaryFlowEntryWithLoad;
+import org.onosproject.net.statistic.TypedFlowEntryWithLoad;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.PortNumber.portNumber;
+
+/**
+ * Fetches flow statistics with a flow type and instruction type.
+ */
+@Command(scope = "onos", name = "get-flow-stats",
+ description = "Fetches flow stats for a connection point with given flow type and instruction type")
+public class GetFlowStatistics extends AbstractShellCommand {
+ @Argument(index = 0, name = "devicePort",
+ description = "Device[/Port] connectPoint Description",
+ required = true, multiValued = false)
+ String devicePort = null;
+
+ @Option(name = "-s", aliases = "--summary",
+ description = "Show flow stats summary",
+ required = false, multiValued = false)
+ boolean showSummary = true; // default summary
+
+ @Option(name = "-a", aliases = "--all",
+ description = "Show flow stats all",
+ required = false, multiValued = false)
+ boolean showAll = false;
+
+ @Option(name = "-t", aliases = "--topn",
+ description = "Show flow stats topn",
+ required = false, multiValued = false)
+ String showTopn = null;
+
+ @Option(name = "-f", aliases = "--flowType",
+ description = "Flow live type, It includes IMMEDIATE, SHORT, MID, LONG, UNKNOWN"
+ + ", and is valid with -a or -t option only",
+ required = false, multiValued = false)
+ String flowLiveType = null;
+
+ @Option(name = "-i", aliases = "--instructionType",
+ description = "Flow instruction type, It includes DROP, OUTPUT, GROUP, L0MODIFICATION, L2MODIFICATION,"
+ + " TABLE, L3MODIFICATION, METADATA"
+ + ", and is valid with -a or -t option only",
+ required = false, multiValued = false)
+ String instructionType = null;
+
+ @Override
+ protected void execute() {
+ DeviceService deviceService = get(DeviceService.class);
+ FlowStatisticService flowStatsService = get(FlowStatisticService.class);
+
+ String deviceURI = getDeviceId(devicePort);
+ String portURI = getPortNumber(devicePort);
+
+ DeviceId ingressDeviceId = deviceId(deviceURI);
+ PortNumber ingressPortNumber;
+ if (portURI.length() == 0) {
+ ingressPortNumber = null;
+ } else {
+ ingressPortNumber = portNumber(portURI);
+ }
+
+ Device device = deviceService.getDevice(ingressDeviceId);
+ if (device == null) {
+ error("No such device %s", ingressDeviceId.uri());
+ return;
+ }
+
+ if (ingressPortNumber != null) {
+ Port port = deviceService.getPort(ingressDeviceId, ingressPortNumber);
+ if (port == null) {
+ error("No such port %s on device %s", portURI, ingressDeviceId.uri());
+ return;
+ }
+ }
+
+ if (flowLiveType != null) {
+ flowLiveType = flowLiveType.toUpperCase();
+ }
+ if (instructionType != null) {
+ instructionType = instructionType.toUpperCase();
+ }
+
+ // convert String to FlowLiveType and check validity
+ TypedStoredFlowEntry.FlowLiveType inLiveType;
+ if (flowLiveType == null) {
+ inLiveType = null;
+ } else {
+ inLiveType = getFlowLiveType(flowLiveType);
+ if (inLiveType == null) {
+ error("Invalid flow live type [%s] error", flowLiveType);
+ return;
+ }
+ }
+ // convert String to InstructionType and check validity
+ Instruction.Type inInstructionType;
+ if (instructionType == null) {
+ inInstructionType = null;
+ } else {
+ inInstructionType = getInstructionType(instructionType);
+ if (inInstructionType == null) {
+ error("Invalid instruction type [%s] error", instructionType);
+ return;
+ }
+ }
+
+ if (showTopn != null) {
+ int topn = Integer.parseInt(showTopn);
+
+ if (topn <= 0) {
+ topn = 100; //default value
+ } else if (topn > 1000) {
+ topn = 1000; //max value
+ }
+
+ // print show topn head line with type
+ print("deviceId=%s, show TOPN=%s flows, live type=%s, instruction type=%s",
+ deviceURI,
+ Integer.toString(topn),
+ flowLiveType == null ? "ALL" : flowLiveType,
+ instructionType == null ? "ALL" : instructionType);
+ if (ingressPortNumber == null) {
+ Map<ConnectPoint, List<TypedFlowEntryWithLoad>> typedFlowLoadMap =
+ flowStatsService.loadTopnByType(device, inLiveType, inInstructionType, topn);
+ // print all ports topn flows load for a given device
+ for (ConnectPoint cp : typedFlowLoadMap.keySet()) {
+ printPortFlowsLoad(cp, typedFlowLoadMap.get(cp));
+ }
+ } else {
+ List<TypedFlowEntryWithLoad> typedFlowLoad =
+ flowStatsService.loadTopnByType(device, ingressPortNumber, inLiveType, inInstructionType, topn);
+ // print device/port topn flows load
+ ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+ printPortFlowsLoad(cp, typedFlowLoad);
+ }
+ } else if (showAll) { // is true?
+ // print show all head line with type
+ print("deviceId=%s, show ALL flows, live type=%s, instruction type=%s",
+ deviceURI,
+ flowLiveType == null ? "ALL" : flowLiveType,
+ instructionType == null ? "ALL" : instructionType);
+ if (ingressPortNumber == null) {
+ Map<ConnectPoint, List<TypedFlowEntryWithLoad>> typedFlowLoadMap =
+ flowStatsService.loadAllByType(device, inLiveType, inInstructionType);
+ // print all ports all flows load for a given device
+ for (ConnectPoint cp : typedFlowLoadMap.keySet()) {
+ printPortFlowsLoad(cp, typedFlowLoadMap.get(cp));
+ }
+ } else {
+ List<TypedFlowEntryWithLoad> typedFlowLoad =
+ flowStatsService.loadAllByType(device, ingressPortNumber, inLiveType, inInstructionType);
+ // print device/port all flows load
+ ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+ printPortFlowsLoad(cp, typedFlowLoad);
+ }
+ } else { // if (showSummary == true) //always is true
+ // print show summary head line
+ print("deviceId=%s, show SUMMARY flows", deviceURI);
+ if (ingressPortNumber == null) {
+ Map<ConnectPoint, SummaryFlowEntryWithLoad> summaryFlowLoadMap =
+ flowStatsService.loadSummary(device);
+ // print all ports flow load summary for a given device
+ for (ConnectPoint cp : summaryFlowLoadMap.keySet()) {
+ printPortSummaryLoad(cp, summaryFlowLoadMap.get(cp));
+ }
+ } else {
+ SummaryFlowEntryWithLoad summaryFlowLoad =
+ flowStatsService.loadSummary(device, ingressPortNumber);
+ // print device/port flow load summary
+ ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+ printPortSummaryLoad(cp, summaryFlowLoad);
+ }
+ }
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ if (deviceString == null) {
+ return "";
+ }
+
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return ""; // return when no port number
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ if (deviceString == null) {
+ return "";
+ }
+
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return deviceString; // return only included device ID
+ }
+ return deviceString.substring(0, slash);
+ }
+
+ /**
+ * converts string of flow live type to FloeLiveType enum.
+ *
+ * @param liveType string representing the flow live type
+ * @return TypedStoredFlowEntry.FlowLiveType
+ */
+ private TypedStoredFlowEntry.FlowLiveType getFlowLiveType(String liveType) {
+ String liveTypeUC = liveType.toUpperCase();
+
+ if (liveTypeUC.equals("IMMEDIATE")) {
+ return TypedStoredFlowEntry.FlowLiveType.IMMEDIATE_FLOW;
+ } else if (liveTypeUC.equals("SHORT")) {
+ return TypedStoredFlowEntry.FlowLiveType.SHORT_FLOW;
+ } else if (liveTypeUC.equals("MID")) {
+ return TypedStoredFlowEntry.FlowLiveType.MID_FLOW;
+ } else if (liveTypeUC.equals("LONG")) {
+ return TypedStoredFlowEntry.FlowLiveType.LONG_FLOW;
+ } else if (liveTypeUC.equals("UNKNOWN")) {
+ return TypedStoredFlowEntry.FlowLiveType.UNKNOWN_FLOW;
+ } else {
+ return null; // flow live type error
+ }
+ }
+
+ /**
+ * converts string of instruction type to Instruction type enum.
+ *
+ * @param instType string representing the instruction type
+ * @return Instruction.Type
+ */
+ private Instruction.Type getInstructionType(String instType) {
+ String instTypeUC = instType.toUpperCase();
+
+ if (instTypeUC.equals("DROP")) {
+ return Instruction.Type.DROP;
+ } else if (instTypeUC.equals("OUTPUT")) {
+ return Instruction.Type.OUTPUT;
+ } else if (instTypeUC.equals("GROUP")) {
+ return Instruction.Type.GROUP;
+ } else if (instTypeUC.equals("L0MODIFICATION")) {
+ return Instruction.Type.L0MODIFICATION;
+ } else if (instTypeUC.equals("L2MODIFICATION")) {
+ return Instruction.Type.L2MODIFICATION;
+ } else if (instTypeUC.equals("TABLE")) {
+ return Instruction.Type.TABLE;
+ } else if (instTypeUC.equals("L3MODIFICATION")) {
+ return Instruction.Type.L3MODIFICATION;
+ } else if (instTypeUC.equals("METADATA")) {
+ return Instruction.Type.METADATA;
+ } else {
+ return null; // instruction type error
+ }
+ }
+
+ private void printPortFlowsLoad(ConnectPoint cp, List<TypedFlowEntryWithLoad> typedFlowLoad) {
+ print(" deviceId/Port=%s/%s, %s flows", cp.elementId(), cp.port(), typedFlowLoad.size());
+ for (TypedFlowEntryWithLoad tfel: typedFlowLoad) {
+ TypedStoredFlowEntry tfe = tfel.typedStoredFlowEntry();
+ print(" flowId=%s, state=%s, liveType=%s, life=%s -> %s",
+ Long.toHexString(tfe.id().value()),
+ tfe.state(),
+ tfe.flowLiveType(),
+ tfe.life(),
+ tfel.load().isValid() ? tfel.load() : "Load{rate=0, NOT VALID}");
+ }
+ }
+
+ private void printPortSummaryLoad(ConnectPoint cp, SummaryFlowEntryWithLoad summaryFlowLoad) {
+ print(" deviceId/Port=%s/%s, Total=%s, Immediate=%s, Short=%s, Mid=%s, Long=%s, Unknown=%s",
+ cp.elementId(),
+ cp.port(),
+ summaryFlowLoad.totalLoad().isValid() ? summaryFlowLoad.totalLoad() : "Load{rate=0, NOT VALID}",
+ summaryFlowLoad.immediateLoad().isValid() ? summaryFlowLoad.immediateLoad() : "Load{rate=0, NOT VALID}",
+ summaryFlowLoad.shortLoad().isValid() ? summaryFlowLoad.shortLoad() : "Load{rate=0, NOT VALID}",
+ summaryFlowLoad.midLoad().isValid() ? summaryFlowLoad.midLoad() : "Load{rate=0, NOT VALID}",
+ summaryFlowLoad.longLoad().isValid() ? summaryFlowLoad.longLoad() : "Load{rate=0, NOT VALID}",
+ summaryFlowLoad.unknownLoad().isValid() ? summaryFlowLoad.unknownLoad() : "Load{rate=0, NOT VALID}");
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java new file mode 100644 index 00000000..eefb711a --- /dev/null +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.cli.net; + +import com.google.common.collect.Sets; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.incubator.net.intf.InterfaceAdminService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.host.InterfaceIpAddress; + +import java.util.Set; + +/** + * Adds a new interface configuration. + */ +@Command(scope = "onos", name = "add-interface", + description = "Adds a new configured interface") +public class InterfaceAddCommand extends AbstractShellCommand { + + @Option(name = "-c", aliases = "--connectPoint", + description = "Device port that the interface is associated with", + required = true, multiValued = false) + private String connectPoint = null; + + @Option(name = "-m", aliases = "--mac", + description = "MAC address of the interface", + required = true, multiValued = false) + private String mac = null; + + @Option(name = "-i", aliases = "--ip", + description = "IP address configured on the interface\n" + + "(e.g. 10.0.1.1/24). Can be specified multiple times.", + required = false, multiValued = true) + private String[] ips = null; + + @Option(name = "-v", aliases = "--vlan", + description = "VLAN configured on the interface", + required = false, multiValued = false) + private String vlan = null; + + @Override + protected void execute() { + InterfaceAdminService interfaceService = get(InterfaceAdminService.class); + + Set<InterfaceIpAddress> ipAddresses = Sets.newHashSet(); + if (ips != null) { + for (String strIp : ips) { + ipAddresses.add(InterfaceIpAddress.valueOf(strIp)); + } + } + + VlanId vlanId = vlan == null ? VlanId.NONE : VlanId.vlanId(Short.parseShort(vlan)); + + Interface intf = new Interface(ConnectPoint.deviceConnectPoint(connectPoint), + ipAddresses, MacAddress.valueOf(mac), vlanId); + + interfaceService.add(intf); + } + +} diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java new file mode 100644 index 00000000..941a65db --- /dev/null +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.cli.net; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onlab.packet.VlanId; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.intf.InterfaceAdminService; +import org.onosproject.net.ConnectPoint; + +/** + * Removes an interface configuration. + */ +@Command(scope = "onos", name = "remove-interface", + description = "Removes a configured interface") +public class InterfaceRemoveCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "connectPoint", + description = "Connect point of the interface", + required = true, multiValued = false) + private String connectPoint = null; + + @Argument(index = 1, name = "vlan", + description = "Interface vlan", + required = true, multiValued = false) + private String vlan = null; + + @Override + protected void execute() { + InterfaceAdminService interfaceService = get(InterfaceAdminService.class); + + interfaceService.remove(ConnectPoint.deviceConnectPoint(connectPoint), + VlanId.vlanId(Short.parseShort(vlan))); + } + +} diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PacketProcessorsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PacketProcessorsListCommand.java index ff66b803..6b7d9336 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PacketProcessorsListCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PacketProcessorsListCommand.java @@ -17,7 +17,7 @@ package org.onosproject.cli.net; import org.apache.karaf.shell.commands.Command; import org.onosproject.cli.AbstractShellCommand; -import org.onosproject.net.packet.PacketProcessor; +import org.onosproject.net.packet.PacketProcessorEntry; import org.onosproject.net.packet.PacketService; import static org.onosproject.net.packet.PacketProcessor.ADVISOR_MAX; @@ -30,7 +30,7 @@ import static org.onosproject.net.packet.PacketProcessor.DIRECTOR_MAX; description = "Lists packet processors") public class PacketProcessorsListCommand extends AbstractShellCommand { - private static final String FMT = "priority=%s, class=%s"; + private static final String FMT = "priority=%s, class=%s, packets=%d, avgNanos=%d"; @Override protected void execute() { @@ -43,8 +43,10 @@ public class PacketProcessorsListCommand extends AbstractShellCommand { } } - private void print(int priority, PacketProcessor processor) { - print(FMT, priorityFormat(priority), processor.getClass().getName()); + private void print(PacketProcessorEntry entry) { + print(FMT, priorityFormat(entry.priority()), + entry.processor().getClass().getName(), + entry.invocations(), entry.averageNanos()); } private String priorityFormat(int priority) { diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java new file mode 100644 index 00000000..e0cd72fc --- /dev/null +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java @@ -0,0 +1,145 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cli.net; + +import static com.google.common.collect.Lists.newArrayList; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.cli.Comparators; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.flow.FlowRuleService; +import org.onosproject.net.flow.TableStatisticsEntry; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Lists port statistic of all ports in the system. + */ +@Command(scope = "onos", name = "tablestats", + description = "Lists statistics of all tables in the device") +public class TableStatisticsCommand extends AbstractShellCommand { + + @Option(name = "-t", aliases = "--table", description = "Show human readable table format for statistics", + required = false, multiValued = false) + private boolean table = false; + + @Argument(index = 0, name = "uri", description = "Device ID", + required = false, multiValued = false) + String uri = null; + + private static final String FORMAT = + " table=%s, active=%s, lookedup=%s, matched=%s"; + + @Override + protected void execute() { + FlowRuleService flowService = get(FlowRuleService.class); + DeviceService deviceService = get(DeviceService.class); + + SortedMap<Device, List<TableStatisticsEntry>> deviceTableStats = + getSortedTableStats(deviceService, flowService); + + if (outputJson()) { + print("%s", json(deviceTableStats.keySet(), deviceTableStats)); + } else { + deviceTableStats.forEach((device, tableStats) -> printTableStats(device, tableStats)); + } + } + + /** + * Produces a JSON array of table statistics grouped by the each device. + * + * @param devices collection of devices + * @param deviceTableStats collection of table statistics per each device + * @return JSON array + */ + private JsonNode json(Iterable<Device> devices, + Map<Device, List<TableStatisticsEntry>> deviceTableStats) { + ObjectMapper mapper = new ObjectMapper(); + ArrayNode result = mapper.createArrayNode(); + for (Device device : devices) { + result.add(json(mapper, device, deviceTableStats.get(device))); + } + return result; + } + + // Produces JSON object with the table statistics of the given device. + private ObjectNode json(ObjectMapper mapper, + Device device, List<TableStatisticsEntry> tableStats) { + ObjectNode result = mapper.createObjectNode(); + ArrayNode array = mapper.createArrayNode(); + + tableStats.forEach(tableStat -> array.add(jsonForEntity(tableStat, TableStatisticsEntry.class))); + + result.put("device", device.id().toString()) + .put("tableCount", tableStats.size()) + .set("tables", array); + return result; + } + + /** + * Prints flow table statistics. + * + * @param d the device + * @param tableStats the set of flow table statistics for that device + */ + protected void printTableStats(Device d, + List<TableStatisticsEntry> tableStats) { + boolean empty = tableStats == null || tableStats.isEmpty(); + print("deviceId=%s, tableCount=%d", d.id(), empty ? 0 : tableStats.size()); + if (!empty) { + for (TableStatisticsEntry t : tableStats) { + print(FORMAT, t.tableId(), t.activeFlowEntries(), + t.packetsLookedup(), t.packetsMatched()); + } + } + } + + /** + * Returns the list of table statistics sorted using the device ID URIs and table IDs. + * + * @param deviceService device service + * @param flowService flow rule service + * @return sorted table statistics list + */ + protected SortedMap<Device, List<TableStatisticsEntry>> getSortedTableStats(DeviceService deviceService, + FlowRuleService flowService) { + SortedMap<Device, List<TableStatisticsEntry>> deviceTableStats = new TreeMap<>(Comparators.ELEMENT_COMPARATOR); + List<TableStatisticsEntry> tableStatsList; + Iterable<Device> devices = uri == null ? deviceService.getDevices() : + Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri))); + for (Device d : devices) { + tableStatsList = newArrayList(flowService.getFlowTableStatistics(d.id())); + tableStatsList.sort((p1, p2) -> Integer.valueOf(p1.tableId()).compareTo(Integer.valueOf(p2.tableId()))); + deviceTableStats.put(d, tableStatsList); + } + return deviceTableStats; + } + +} diff --git a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml index 459ffa96..28461e27 100644 --- a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -105,6 +105,18 @@ </completers> </command> <command> + <action class="org.onosproject.cli.net.DeviceControllersCommand"/> + <completers> + <ref component-id="deviceIdCompleter"/> + </completers> + </command> + <command> + <action class="org.onosproject.cli.net.DeviceSetControllersCommand"/> + <completers> + <ref component-id="deviceIdCompleter"/> + </completers> + </command> + <command> <action class="org.onosproject.cli.net.DeviceRemoveCommand"/> <completers> <ref component-id="deviceIdCompleter"/> @@ -222,6 +234,12 @@ </completers> </command> <command> + <action class="org.onosproject.cli.net.GetFlowStatistics"/> + <completers> + <ref component-id="deviceIdCompleter"/> + </completers> + </command> + <command> <action class="org.onosproject.cli.net.AddMultiPointToSinglePointIntentCommand"/> <completers> <ref component-id="connectPointCompleter"/> @@ -333,7 +351,19 @@ <command> <action class="org.onosproject.cli.net.InterfacesListCommand"/> </command> - + <command> + <action class="org.onosproject.cli.net.InterfaceAddCommand"/> + <optional-completers> + <entry key="-c" value-ref="connectPointCompleter"/> + <entry key="--connectPoint" value-ref="connectPointCompleter"/> + </optional-completers> + </command> + <command> + <action class="org.onosproject.cli.net.InterfaceRemoveCommand"/> + <completers> + <ref component-id="connectPointCompleter"/> + </completers> + </command> <command> <action class="org.onosproject.cli.net.GroupsListCommand"/> </command> @@ -343,6 +373,10 @@ </command> <command> + <action class="org.onosproject.cli.net.TableStatisticsCommand"/> + </command> + + <command> <action class="org.onosproject.cli.net.FlowsListCommand"/> <completers> <ref component-id="flowRuleStatusCompleter"/> |