blob: 369b1ae7fab8a3b6e9d4f94bb485503c85d6c311 [file] [log] [blame]
Andreas Papazois25a98e72016-07-28 10:57:15 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Andreas Papazois25a98e72016-07-28 10:57:15 +05303 *
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 */
16package org.onosproject.cli.net;
17
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import org.apache.karaf.shell.api.action.Argument;
19import org.apache.karaf.shell.api.action.Command;
Ray Milkey0068fd02018-10-11 15:45:39 -070020import org.apache.karaf.shell.api.action.Completion;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070021import org.apache.karaf.shell.api.action.lifecycle.Service;
Andreas Papazois25a98e72016-07-28 10:57:15 +053022import org.onlab.packet.VlanId;
23import org.onosproject.cli.AbstractShellCommand;
24import org.onosproject.net.ConnectPoint;
25import org.onosproject.net.Device;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.Port;
28import org.onosproject.net.PortNumber;
29import org.onosproject.net.behaviour.VlanQuery;
30import org.onosproject.net.device.DeviceService;
31import org.onosproject.net.driver.DriverHandler;
32import org.onosproject.net.driver.DriverService;
33
34import java.util.ArrayList;
35import java.util.Arrays;
36import java.util.Set;
37
38/**
39 * Command to show the list of unused vlan-ids.
40 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070041@Service
Andreas Papazois25a98e72016-07-28 10:57:15 +053042@Command(scope = "onos", name = "port-query-vlans",
43 description = "Lists all unused VLAN-IDs on port")
44public class PortQueryVlansCommand extends AbstractShellCommand {
45
46 private static final String AVAIL_VLANS = "VLAN-ID: %s";
47 private static final String VLAN_NOT_AVAILABLE = "No unused VLAN-ID";
48 private static final String FMT = "port=%s, state=%s, type=%s, speed=%s%s";
49 private static final String NO_SUPPORT = "Device not supporting VLAN-ID retrieval";
50 private static final String FAILURE = "Failed to retrieve VLAN information: ";
51
52 @Argument(index = 0, name = "port",
53 description = "Port Description",
54 required = true, multiValued = true)
Ray Milkey0068fd02018-10-11 15:45:39 -070055 @Completion(ConnectPointCompleter.class)
Andreas Papazois25a98e72016-07-28 10:57:15 +053056 private String[] ports;
57
58
59 @Override
Ray Milkeyd84f89b2018-08-17 14:54:17 -070060 protected void doExecute() {
Andreas Papazois25a98e72016-07-28 10:57:15 +053061 DeviceService service = get(DeviceService.class);
62 for (String portStr : ports) {
63 ConnectPoint connectPoint = ConnectPoint.deviceConnectPoint(portStr);
64 Port port = service.getPort(connectPoint.deviceId(), connectPoint.port());
65 printPort(port);
66 printVlans(port);
67 }
68 }
69
70 private void printPort(Port port) {
71 String portName = portName(port.number());
72 Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled";
73 String portType = port.type().toString().toLowerCase();
74 String annotations = annotations(port.annotations());
75 print(FMT, portName, portIsEnabled, portType, port.portSpeed(), annotations);
76 }
77
78 private String portName(PortNumber port) {
79 return port.equals(PortNumber.LOCAL) ? "local" : port.toString();
80 }
81
82 private void printVlans(Port port) {
83 DeviceService deviceService = get(DeviceService.class);
84 DriverService driverService = get(DriverService.class);
85
86 DeviceId deviceId = (DeviceId) port.element().id();
87 Device device = deviceService.getDevice(deviceId);
88
89 if (!device.is(VlanQuery.class)) {
90 // The relevant behavior is not supported by the device.
91 print(NO_SUPPORT);
92 return;
93 }
94
95 DriverHandler h = driverService.createHandler(deviceId);
96 VlanQuery vlanQuery = h.behaviour(VlanQuery.class);
97
98 try {
99 Set<VlanId> vlanIds = vlanQuery.queryVlanIds(port.number());
100
101 if (vlanIds.isEmpty()) {
102 print(VLAN_NOT_AVAILABLE);
103 } else {
104 print(AVAIL_VLANS, getRanges(vlanIds).toString());
105 }
106 } catch (Exception e) {
107 print(FAILURE + e.getMessage());
108 }
109 }
110
111 private static ArrayList getRanges(Set<VlanId> vlans) {
112 short i = 0;
113 short[] vlanArray = new short[vlans.size()];
114 for (VlanId vlanId : vlans) {
115 vlanArray[i++] = vlanId.toShort();
116 }
117 Arrays.sort(vlanArray);
118
119 ArrayList ranges = new ArrayList();
120 short rStart = 0;
121 short rEnd = 0;
122
123 for (i = 2; i < vlanArray.length; i++) {
124 if (vlanArray[i] == vlanArray[i - 1] + 1 &&
125 vlanArray[i] == vlanArray[i - 2] + 2) {
126 // Three consecutive VLAN-IDs found, so range exists.
127 if (rEnd == vlanArray[i - 1]) {
128 // Range already exists, so step the end.
129 rEnd = vlanArray[i];
130 } else {
131 // Setup a new range.
132 rStart = vlanArray[i - 2];
133 rEnd = vlanArray[i];
134 }
135 } else {
136 // Not in a range.
137 if (rEnd == vlanArray[i - 1]) {
138 // Previous range is discontinued and is stored.
139 ranges.add(rStart + "-" + rEnd);
140 } else {
141 // No previous range.
142 if (vlanArray[i] != vlanArray[i - 1] + 1) {
143 // Current VLAN-ID is not 2nd consecutive.
144 if (vlanArray[i - 1] == vlanArray[i - 2] + 1) {
145 // The 2 previous VLAN-IDs were consequetive, so 2nd
146 // last is stored separately.
147 ranges.add(vlanArray[i - 2]);
148 }
149 // Previous is stored, when current is not consequetive.
150 ranges.add(vlanArray[i - 1]);
151 }
152 }
153 }
154 }
155 if (rEnd == vlanArray[vlanArray.length - 1]) {
156 // Array finished with a range.
157 ranges.add(rStart + "-" + rEnd);
158 } else {
159 if (vlanArray[vlanArray.length - 1] == vlanArray[vlanArray.length - 2] + 1) {
160 // Previous is stored, when current is consequetive.
161 ranges.add(vlanArray[vlanArray.length - 2]);
162 }
163 // Last item is stored
164 ranges.add(vlanArray[vlanArray.length - 1]);
165 }
166 return ranges;
167 }
168}