blob: 2a88198f1a24353b70d99615eda53b2f0154c8b3 [file] [log] [blame]
Claudine Chiu1f036b82017-03-09 16:45:56 -05001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Claudine Chiu1f036b82017-03-09 16:45:56 -05003 *
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
17package org.onosproject.cli.net.vnet;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
21import com.fasterxml.jackson.databind.node.ArrayNode;
22import org.apache.karaf.shell.commands.Argument;
23import org.apache.karaf.shell.commands.Command;
24import org.apache.karaf.shell.commands.Option;
25import org.onlab.packet.Ip6Address;
26import org.onlab.packet.IpPrefix;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.TpPort;
29import org.onlab.packet.VlanId;
30import org.onosproject.cli.AbstractShellCommand;
31import org.onosproject.cli.net.EthType;
32import org.onosproject.cli.net.ExtHeader;
33import org.onosproject.cli.net.Icmp6Code;
34import org.onosproject.cli.net.Icmp6Type;
35import org.onosproject.cli.net.IpProtocol;
36import org.onosproject.incubator.net.virtual.NetworkId;
37import org.onosproject.incubator.net.virtual.VirtualNetworkService;
38import org.onosproject.net.DeviceId;
39import org.onosproject.net.flow.DefaultTrafficSelector;
40import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.packet.PacketPriority;
42import org.onosproject.net.packet.PacketRequest;
43import org.onosproject.net.packet.PacketService;
44
45import java.util.List;
46import java.util.Optional;
47
48import static com.google.common.base.Strings.isNullOrEmpty;
49
50/**
51 * Tests virtual network packet requests.
52 */
53@Command(scope = "onos", name = "vnet-packet",
54 description = "Tests virtual network packet requests")
55public class VirtualNetworkPacketRequestCommand extends AbstractShellCommand {
56
57 @Argument(index = 0, name = "command",
58 description = "Command name (requestPackets|getRequests|cancelPackets)",
59 required = true, multiValued = false)
60 private String command = null;
61
62 @Argument(index = 1, name = "networkId", description = "Network ID",
63 required = true, multiValued = false)
64 private Long networkId = null;
65
66 @Option(name = "--deviceId", description = "Device ID",
67 required = false, multiValued = false)
68 private String deviceIdString = null;
69
70 // Traffic selector
71 @Option(name = "-s", aliases = "--ethSrc", description = "Source MAC Address",
72 required = false, multiValued = false)
73 private String srcMacString = null;
74
75 @Option(name = "-d", aliases = "--ethDst", description = "Destination MAC Address",
76 required = false, multiValued = false)
77 private String dstMacString = null;
78
79 @Option(name = "-t", aliases = "--ethType", description = "Ethernet Type",
80 required = false, multiValued = false)
81 private String ethTypeString = null;
82
83 @Option(name = "-v", aliases = "--vlan", description = "VLAN ID",
84 required = false, multiValued = false)
85 private String vlanString = null;
86
87 @Option(name = "--ipProto", description = "IP Protocol",
88 required = false, multiValued = false)
89 private String ipProtoString = null;
90
91 @Option(name = "--ipSrc", description = "Source IP Prefix",
92 required = false, multiValued = false)
93 private String srcIpString = null;
94
95 @Option(name = "--ipDst", description = "Destination IP Prefix",
96 required = false, multiValued = false)
97 private String dstIpString = null;
98
99 @Option(name = "--fLabel", description = "IPv6 Flow Label",
100 required = false, multiValued = false)
101 private String fLabelString = null;
102
103 @Option(name = "--icmp6Type", description = "ICMPv6 Type",
104 required = false, multiValued = false)
105 private String icmp6TypeString = null;
106
107 @Option(name = "--icmp6Code", description = "ICMPv6 Code",
108 required = false, multiValued = false)
109 private String icmp6CodeString = null;
110
111 @Option(name = "--ndTarget", description = "IPv6 Neighbor Discovery Target Address",
112 required = false, multiValued = false)
113 private String ndTargetString = null;
114
115 @Option(name = "--ndSLL", description = "IPv6 Neighbor Discovery Source Link-Layer",
116 required = false, multiValued = false)
117 private String ndSllString = null;
118
119 @Option(name = "--ndTLL", description = "IPv6 Neighbor Discovery Target Link-Layer",
120 required = false, multiValued = false)
121 private String ndTllString = null;
122
123 @Option(name = "--tcpSrc", description = "Source TCP Port",
124 required = false, multiValued = false)
125 private String srcTcpString = null;
126
127 @Option(name = "--tcpDst", description = "Destination TCP Port",
128 required = false, multiValued = false)
129 private String dstTcpString = null;
130
131 @Option(name = "--extHdr", description = "IPv6 Extension Header Pseudo-field",
132 required = false, multiValued = true)
133 private List<String> extHdrStringList = null;
134
135 @Override
136 protected void execute() {
137 VirtualNetworkService service = get(VirtualNetworkService.class);
138 PacketService virtualPacketService = service.get(NetworkId.networkId(networkId), PacketService.class);
139
140 if (command == null) {
141 print("Command is not defined");
142 return;
143 }
144
145 if (command.equals("getRequests")) {
146 getRequests(virtualPacketService);
147 return;
148 }
149
150 TrafficSelector selector = buildTrafficSelector();
151 PacketPriority packetPriority = PacketPriority.CONTROL; //TODO allow user to specify
152 Optional<DeviceId> optionalDeviceId = null;
153 if (!isNullOrEmpty(deviceIdString)) {
154 optionalDeviceId = Optional.of(DeviceId.deviceId(deviceIdString));
155 }
156
157 if (command.equals("requestPackets")) {
158 if (optionalDeviceId != null) {
159 virtualPacketService.requestPackets(selector, packetPriority, appId(), optionalDeviceId);
160 } else {
161 virtualPacketService.requestPackets(selector, packetPriority, appId());
162 }
163 print("Virtual packet requested:\n%s", selector);
164 return;
165 }
166
167 if (command.equals("cancelPackets")) {
168 if (optionalDeviceId != null) {
169 virtualPacketService.cancelPackets(selector, packetPriority, appId(), optionalDeviceId);
170 } else {
171 virtualPacketService.cancelPackets(selector, packetPriority, appId());
172 }
173 print("Virtual packet cancelled:\n%s", selector);
174 return;
175 }
176
177 print("Unsupported command %s", command);
178 }
179
180 private void getRequests(PacketService packetService) {
181 List<PacketRequest> packetRequests = packetService.getRequests();
182 if (outputJson()) {
183 print("%s", json(packetRequests));
184 } else {
185 packetRequests.forEach(packetRequest -> print(packetRequest.toString()));
186 }
187 }
188
189 private JsonNode json(List<PacketRequest> packetRequests) {
190 ObjectMapper mapper = new ObjectMapper();
191 ArrayNode result = mapper.createArrayNode();
192 packetRequests.forEach(packetRequest ->
193 result.add(jsonForEntity(packetRequest, PacketRequest.class)));
194 return result;
195 }
196
197 /**
198 * Constructs a traffic selector based on the command line arguments
199 * presented to the command.
200 * @return traffic selector
201 */
202 private TrafficSelector buildTrafficSelector() {
203 IpPrefix srcIpPrefix = null;
204 IpPrefix dstIpPrefix = null;
205
206 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
207
208 if (!isNullOrEmpty(srcIpString)) {
209 srcIpPrefix = IpPrefix.valueOf(srcIpString);
210 if (srcIpPrefix.isIp4()) {
211 selectorBuilder.matchIPSrc(srcIpPrefix);
212 } else {
213 selectorBuilder.matchIPv6Src(srcIpPrefix);
214 }
215 }
216
217 if (!isNullOrEmpty(dstIpString)) {
218 dstIpPrefix = IpPrefix.valueOf(dstIpString);
219 if (dstIpPrefix.isIp4()) {
220 selectorBuilder.matchIPDst(dstIpPrefix);
221 } else {
222 selectorBuilder.matchIPv6Dst(dstIpPrefix);
223 }
224 }
225
226 if ((srcIpPrefix != null) && (dstIpPrefix != null) &&
227 (srcIpPrefix.version() != dstIpPrefix.version())) {
228 // ERROR: IP src/dst version mismatch
229 throw new IllegalArgumentException(
230 "IP source and destination version mismatch");
231 }
232
233 //
234 // Set the default EthType based on the IP version if the matching
235 // source or destination IP prefixes.
236 //
237 Short ethType = null;
238 if ((srcIpPrefix != null) && srcIpPrefix.isIp6()) {
239 ethType = EthType.IPV6.value();
240 }
241 if ((dstIpPrefix != null) && dstIpPrefix.isIp6()) {
242 ethType = EthType.IPV6.value();
243 }
244 if (!isNullOrEmpty(ethTypeString)) {
245 ethType = EthType.parseFromString(ethTypeString);
246 }
247 if (ethType != null) {
248 selectorBuilder.matchEthType(ethType);
249 }
250 if (!isNullOrEmpty(vlanString)) {
251 selectorBuilder.matchVlanId(VlanId.vlanId(Short.parseShort(vlanString)));
252 }
253 if (!isNullOrEmpty(srcMacString)) {
254 selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMacString));
255 }
256
257 if (!isNullOrEmpty(dstMacString)) {
258 selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString));
259 }
260
261 if (!isNullOrEmpty(ipProtoString)) {
262 short ipProtoShort = IpProtocol.parseFromString(ipProtoString);
263 selectorBuilder.matchIPProtocol((byte) ipProtoShort);
264 }
265
266 if (!isNullOrEmpty(fLabelString)) {
267 selectorBuilder.matchIPv6FlowLabel(Integer.parseInt(fLabelString));
268 }
269
270 if (!isNullOrEmpty(icmp6TypeString)) {
271 byte icmp6Type = Icmp6Type.parseFromString(icmp6TypeString);
272 selectorBuilder.matchIcmpv6Type(icmp6Type);
273 }
274
275 if (!isNullOrEmpty(icmp6CodeString)) {
276 byte icmp6Code = Icmp6Code.parseFromString(icmp6CodeString);
277 selectorBuilder.matchIcmpv6Code(icmp6Code);
278 }
279
280 if (!isNullOrEmpty(ndTargetString)) {
281 selectorBuilder.matchIPv6NDTargetAddress(Ip6Address.valueOf(ndTargetString));
282 }
283
284 if (!isNullOrEmpty(ndSllString)) {
285 selectorBuilder.matchIPv6NDSourceLinkLayerAddress(MacAddress.valueOf(ndSllString));
286 }
287
288 if (!isNullOrEmpty(ndTllString)) {
289 selectorBuilder.matchIPv6NDTargetLinkLayerAddress(MacAddress.valueOf(ndTllString));
290 }
291
292 if (!isNullOrEmpty(srcTcpString)) {
293 selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpString)));
294 }
295
296 if (!isNullOrEmpty(dstTcpString)) {
297 selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpString)));
298 }
299
300 if (extHdrStringList != null) {
301 short extHdr = 0;
302 for (String extHdrString : extHdrStringList) {
303 extHdr = (short) (extHdr | ExtHeader.parseFromString(extHdrString));
304 }
305 selectorBuilder.matchIPv6ExthdrFlags(extHdr);
306 }
307
308 return selectorBuilder.build();
309 }
310}