Committed by
Gerrit Code Review
Command using VlanQuery behavior on device.
Change-Id: Ifef86810d1f8bf8b59a1e9ba2735cd79bfb890f7
Showing
2 changed files
with
171 additions
and
0 deletions
| 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 org.apache.karaf.shell.commands.Argument; | ||
| 19 | +import org.apache.karaf.shell.commands.Command; | ||
| 20 | +import org.onlab.packet.VlanId; | ||
| 21 | +import org.onosproject.cli.AbstractShellCommand; | ||
| 22 | +import org.onosproject.net.ConnectPoint; | ||
| 23 | +import org.onosproject.net.Device; | ||
| 24 | +import org.onosproject.net.DeviceId; | ||
| 25 | +import org.onosproject.net.Port; | ||
| 26 | +import org.onosproject.net.PortNumber; | ||
| 27 | +import org.onosproject.net.behaviour.VlanQuery; | ||
| 28 | +import org.onosproject.net.device.DeviceService; | ||
| 29 | +import org.onosproject.net.driver.DriverHandler; | ||
| 30 | +import org.onosproject.net.driver.DriverService; | ||
| 31 | + | ||
| 32 | +import java.util.ArrayList; | ||
| 33 | +import java.util.Arrays; | ||
| 34 | +import java.util.Set; | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * Command to show the list of unused vlan-ids. | ||
| 38 | + */ | ||
| 39 | +@Command(scope = "onos", name = "port-query-vlans", | ||
| 40 | + description = "Lists all unused VLAN-IDs on port") | ||
| 41 | +public class PortQueryVlansCommand extends AbstractShellCommand { | ||
| 42 | + | ||
| 43 | + private static final String AVAIL_VLANS = "VLAN-ID: %s"; | ||
| 44 | + private static final String VLAN_NOT_AVAILABLE = "No unused VLAN-ID"; | ||
| 45 | + private static final String FMT = "port=%s, state=%s, type=%s, speed=%s%s"; | ||
| 46 | + private static final String NO_SUPPORT = "Device not supporting VLAN-ID retrieval"; | ||
| 47 | + private static final String FAILURE = "Failed to retrieve VLAN information: "; | ||
| 48 | + | ||
| 49 | + @Argument(index = 0, name = "port", | ||
| 50 | + description = "Port Description", | ||
| 51 | + required = true, multiValued = true) | ||
| 52 | + private String[] ports; | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + @Override | ||
| 56 | + protected void execute() { | ||
| 57 | + DeviceService service = get(DeviceService.class); | ||
| 58 | + for (String portStr : ports) { | ||
| 59 | + ConnectPoint connectPoint = ConnectPoint.deviceConnectPoint(portStr); | ||
| 60 | + Port port = service.getPort(connectPoint.deviceId(), connectPoint.port()); | ||
| 61 | + printPort(port); | ||
| 62 | + printVlans(port); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + private void printPort(Port port) { | ||
| 67 | + String portName = portName(port.number()); | ||
| 68 | + Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled"; | ||
| 69 | + String portType = port.type().toString().toLowerCase(); | ||
| 70 | + String annotations = annotations(port.annotations()); | ||
| 71 | + print(FMT, portName, portIsEnabled, portType, port.portSpeed(), annotations); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + private String portName(PortNumber port) { | ||
| 75 | + return port.equals(PortNumber.LOCAL) ? "local" : port.toString(); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + private void printVlans(Port port) { | ||
| 79 | + DeviceService deviceService = get(DeviceService.class); | ||
| 80 | + DriverService driverService = get(DriverService.class); | ||
| 81 | + | ||
| 82 | + DeviceId deviceId = (DeviceId) port.element().id(); | ||
| 83 | + Device device = deviceService.getDevice(deviceId); | ||
| 84 | + | ||
| 85 | + if (!device.is(VlanQuery.class)) { | ||
| 86 | + // The relevant behavior is not supported by the device. | ||
| 87 | + print(NO_SUPPORT); | ||
| 88 | + return; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + DriverHandler h = driverService.createHandler(deviceId); | ||
| 92 | + VlanQuery vlanQuery = h.behaviour(VlanQuery.class); | ||
| 93 | + | ||
| 94 | + try { | ||
| 95 | + Set<VlanId> vlanIds = vlanQuery.queryVlanIds(port.number()); | ||
| 96 | + | ||
| 97 | + if (vlanIds.isEmpty()) { | ||
| 98 | + print(VLAN_NOT_AVAILABLE); | ||
| 99 | + } else { | ||
| 100 | + print(AVAIL_VLANS, getRanges(vlanIds).toString()); | ||
| 101 | + } | ||
| 102 | + } catch (Exception e) { | ||
| 103 | + print(FAILURE + e.getMessage()); | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + private static ArrayList getRanges(Set<VlanId> vlans) { | ||
| 108 | + short i = 0; | ||
| 109 | + short[] vlanArray = new short[vlans.size()]; | ||
| 110 | + for (VlanId vlanId : vlans) { | ||
| 111 | + vlanArray[i++] = vlanId.toShort(); | ||
| 112 | + } | ||
| 113 | + Arrays.sort(vlanArray); | ||
| 114 | + | ||
| 115 | + ArrayList ranges = new ArrayList(); | ||
| 116 | + short rStart = 0; | ||
| 117 | + short rEnd = 0; | ||
| 118 | + | ||
| 119 | + for (i = 2; i < vlanArray.length; i++) { | ||
| 120 | + if (vlanArray[i] == vlanArray[i - 1] + 1 && | ||
| 121 | + vlanArray[i] == vlanArray[i - 2] + 2) { | ||
| 122 | + // Three consecutive VLAN-IDs found, so range exists. | ||
| 123 | + if (rEnd == vlanArray[i - 1]) { | ||
| 124 | + // Range already exists, so step the end. | ||
| 125 | + rEnd = vlanArray[i]; | ||
| 126 | + } else { | ||
| 127 | + // Setup a new range. | ||
| 128 | + rStart = vlanArray[i - 2]; | ||
| 129 | + rEnd = vlanArray[i]; | ||
| 130 | + } | ||
| 131 | + } else { | ||
| 132 | + // Not in a range. | ||
| 133 | + if (rEnd == vlanArray[i - 1]) { | ||
| 134 | + // Previous range is discontinued and is stored. | ||
| 135 | + ranges.add(rStart + "-" + rEnd); | ||
| 136 | + } else { | ||
| 137 | + // No previous range. | ||
| 138 | + if (vlanArray[i] != vlanArray[i - 1] + 1) { | ||
| 139 | + // Current VLAN-ID is not 2nd consecutive. | ||
| 140 | + if (vlanArray[i - 1] == vlanArray[i - 2] + 1) { | ||
| 141 | + // The 2 previous VLAN-IDs were consequetive, so 2nd | ||
| 142 | + // last is stored separately. | ||
| 143 | + ranges.add(vlanArray[i - 2]); | ||
| 144 | + } | ||
| 145 | + // Previous is stored, when current is not consequetive. | ||
| 146 | + ranges.add(vlanArray[i - 1]); | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + if (rEnd == vlanArray[vlanArray.length - 1]) { | ||
| 152 | + // Array finished with a range. | ||
| 153 | + ranges.add(rStart + "-" + rEnd); | ||
| 154 | + } else { | ||
| 155 | + if (vlanArray[vlanArray.length - 1] == vlanArray[vlanArray.length - 2] + 1) { | ||
| 156 | + // Previous is stored, when current is consequetive. | ||
| 157 | + ranges.add(vlanArray[vlanArray.length - 2]); | ||
| 158 | + } | ||
| 159 | + // Last item is stored | ||
| 160 | + ranges.add(vlanArray[vlanArray.length - 1]); | ||
| 161 | + } | ||
| 162 | + return ranges; | ||
| 163 | + } | ||
| 164 | +} |
| ... | @@ -463,6 +463,13 @@ | ... | @@ -463,6 +463,13 @@ |
| 463 | </command> | 463 | </command> |
| 464 | 464 | ||
| 465 | <command> | 465 | <command> |
| 466 | + <action class="org.onosproject.cli.net.PortQueryVlansCommand"/> | ||
| 467 | + <completers> | ||
| 468 | + <ref component-id="connectPointCompleter"/> | ||
| 469 | + </completers> | ||
| 470 | + </command> | ||
| 471 | + | ||
| 472 | + <command> | ||
| 466 | <action class="org.onosproject.cli.net.TableStatisticsCommand"/> | 473 | <action class="org.onosproject.cli.net.TableStatisticsCommand"/> |
| 467 | </command> | 474 | </command> |
| 468 | 475 | ... | ... |
-
Please register or login to post a comment