| /* |
| * Copyright 2016-present Open Networking Foundation |
| * |
| * 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.vnet; |
| |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import com.fasterxml.jackson.databind.node.ArrayNode; |
| import org.apache.karaf.shell.commands.Argument; |
| import org.apache.karaf.shell.commands.Command; |
| import org.apache.karaf.shell.commands.Option; |
| import org.onlab.packet.Ip6Address; |
| import org.onlab.packet.IpPrefix; |
| import org.onlab.packet.MacAddress; |
| import org.onlab.packet.TpPort; |
| import org.onlab.packet.VlanId; |
| import org.onosproject.cli.AbstractShellCommand; |
| import org.onosproject.cli.net.EthType; |
| import org.onosproject.cli.net.ExtHeader; |
| import org.onosproject.cli.net.Icmp6Code; |
| import org.onosproject.cli.net.Icmp6Type; |
| import org.onosproject.cli.net.IpProtocol; |
| import org.onosproject.incubator.net.virtual.NetworkId; |
| import org.onosproject.incubator.net.virtual.VirtualNetworkService; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.flow.DefaultTrafficSelector; |
| import org.onosproject.net.flow.TrafficSelector; |
| import org.onosproject.net.packet.PacketPriority; |
| import org.onosproject.net.packet.PacketRequest; |
| import org.onosproject.net.packet.PacketService; |
| |
| import java.util.List; |
| import java.util.Optional; |
| |
| import static com.google.common.base.Strings.isNullOrEmpty; |
| |
| /** |
| * Tests virtual network packet requests. |
| */ |
| @Command(scope = "onos", name = "vnet-packet", |
| description = "Tests virtual network packet requests") |
| public class VirtualNetworkPacketRequestCommand extends AbstractShellCommand { |
| |
| @Argument(index = 0, name = "command", |
| description = "Command name (requestPackets|getRequests|cancelPackets)", |
| required = true, multiValued = false) |
| private String command = null; |
| |
| @Argument(index = 1, name = "networkId", description = "Network ID", |
| required = true, multiValued = false) |
| private Long networkId = null; |
| |
| @Option(name = "--deviceId", description = "Device ID", |
| required = false, multiValued = false) |
| private String deviceIdString = null; |
| |
| // Traffic selector |
| @Option(name = "-s", aliases = "--ethSrc", description = "Source MAC Address", |
| required = false, multiValued = false) |
| private String srcMacString = null; |
| |
| @Option(name = "-d", aliases = "--ethDst", description = "Destination MAC Address", |
| required = false, multiValued = false) |
| private String dstMacString = null; |
| |
| @Option(name = "-t", aliases = "--ethType", description = "Ethernet Type", |
| required = false, multiValued = false) |
| private String ethTypeString = null; |
| |
| @Option(name = "-v", aliases = "--vlan", description = "VLAN ID", |
| required = false, multiValued = false) |
| private String vlanString = null; |
| |
| @Option(name = "--ipProto", description = "IP Protocol", |
| required = false, multiValued = false) |
| private String ipProtoString = null; |
| |
| @Option(name = "--ipSrc", description = "Source IP Prefix", |
| required = false, multiValued = false) |
| private String srcIpString = null; |
| |
| @Option(name = "--ipDst", description = "Destination IP Prefix", |
| required = false, multiValued = false) |
| private String dstIpString = null; |
| |
| @Option(name = "--fLabel", description = "IPv6 Flow Label", |
| required = false, multiValued = false) |
| private String fLabelString = null; |
| |
| @Option(name = "--icmp6Type", description = "ICMPv6 Type", |
| required = false, multiValued = false) |
| private String icmp6TypeString = null; |
| |
| @Option(name = "--icmp6Code", description = "ICMPv6 Code", |
| required = false, multiValued = false) |
| private String icmp6CodeString = null; |
| |
| @Option(name = "--ndTarget", description = "IPv6 Neighbor Discovery Target Address", |
| required = false, multiValued = false) |
| private String ndTargetString = null; |
| |
| @Option(name = "--ndSLL", description = "IPv6 Neighbor Discovery Source Link-Layer", |
| required = false, multiValued = false) |
| private String ndSllString = null; |
| |
| @Option(name = "--ndTLL", description = "IPv6 Neighbor Discovery Target Link-Layer", |
| required = false, multiValued = false) |
| private String ndTllString = null; |
| |
| @Option(name = "--tcpSrc", description = "Source TCP Port", |
| required = false, multiValued = false) |
| private String srcTcpString = null; |
| |
| @Option(name = "--tcpDst", description = "Destination TCP Port", |
| required = false, multiValued = false) |
| private String dstTcpString = null; |
| |
| @Option(name = "--extHdr", description = "IPv6 Extension Header Pseudo-field", |
| required = false, multiValued = true) |
| private List<String> extHdrStringList = null; |
| |
| @Override |
| protected void execute() { |
| VirtualNetworkService service = get(VirtualNetworkService.class); |
| PacketService virtualPacketService = service.get(NetworkId.networkId(networkId), PacketService.class); |
| |
| if (command == null) { |
| print("Command is not defined"); |
| return; |
| } |
| |
| if (command.equals("getRequests")) { |
| getRequests(virtualPacketService); |
| return; |
| } |
| |
| TrafficSelector selector = buildTrafficSelector(); |
| PacketPriority packetPriority = PacketPriority.CONTROL; //TODO allow user to specify |
| Optional<DeviceId> optionalDeviceId = null; |
| if (!isNullOrEmpty(deviceIdString)) { |
| optionalDeviceId = Optional.of(DeviceId.deviceId(deviceIdString)); |
| } |
| |
| if (command.equals("requestPackets")) { |
| if (optionalDeviceId != null) { |
| virtualPacketService.requestPackets(selector, packetPriority, appId(), optionalDeviceId); |
| } else { |
| virtualPacketService.requestPackets(selector, packetPriority, appId()); |
| } |
| print("Virtual packet requested:\n%s", selector); |
| return; |
| } |
| |
| if (command.equals("cancelPackets")) { |
| if (optionalDeviceId != null) { |
| virtualPacketService.cancelPackets(selector, packetPriority, appId(), optionalDeviceId); |
| } else { |
| virtualPacketService.cancelPackets(selector, packetPriority, appId()); |
| } |
| print("Virtual packet cancelled:\n%s", selector); |
| return; |
| } |
| |
| print("Unsupported command %s", command); |
| } |
| |
| private void getRequests(PacketService packetService) { |
| List<PacketRequest> packetRequests = packetService.getRequests(); |
| if (outputJson()) { |
| print("%s", json(packetRequests)); |
| } else { |
| packetRequests.forEach(packetRequest -> print(packetRequest.toString())); |
| } |
| } |
| |
| private JsonNode json(List<PacketRequest> packetRequests) { |
| ObjectMapper mapper = new ObjectMapper(); |
| ArrayNode result = mapper.createArrayNode(); |
| packetRequests.forEach(packetRequest -> |
| result.add(jsonForEntity(packetRequest, PacketRequest.class))); |
| return result; |
| } |
| |
| /** |
| * Constructs a traffic selector based on the command line arguments |
| * presented to the command. |
| * @return traffic selector |
| */ |
| private TrafficSelector buildTrafficSelector() { |
| IpPrefix srcIpPrefix = null; |
| IpPrefix dstIpPrefix = null; |
| |
| TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); |
| |
| if (!isNullOrEmpty(srcIpString)) { |
| srcIpPrefix = IpPrefix.valueOf(srcIpString); |
| if (srcIpPrefix.isIp4()) { |
| selectorBuilder.matchIPSrc(srcIpPrefix); |
| } else { |
| selectorBuilder.matchIPv6Src(srcIpPrefix); |
| } |
| } |
| |
| if (!isNullOrEmpty(dstIpString)) { |
| dstIpPrefix = IpPrefix.valueOf(dstIpString); |
| if (dstIpPrefix.isIp4()) { |
| selectorBuilder.matchIPDst(dstIpPrefix); |
| } else { |
| selectorBuilder.matchIPv6Dst(dstIpPrefix); |
| } |
| } |
| |
| if ((srcIpPrefix != null) && (dstIpPrefix != null) && |
| (srcIpPrefix.version() != dstIpPrefix.version())) { |
| // ERROR: IP src/dst version mismatch |
| throw new IllegalArgumentException( |
| "IP source and destination version mismatch"); |
| } |
| |
| // |
| // Set the default EthType based on the IP version if the matching |
| // source or destination IP prefixes. |
| // |
| Short ethType = null; |
| if ((srcIpPrefix != null) && srcIpPrefix.isIp6()) { |
| ethType = EthType.IPV6.value(); |
| } |
| if ((dstIpPrefix != null) && dstIpPrefix.isIp6()) { |
| ethType = EthType.IPV6.value(); |
| } |
| if (!isNullOrEmpty(ethTypeString)) { |
| ethType = EthType.parseFromString(ethTypeString); |
| } |
| if (ethType != null) { |
| selectorBuilder.matchEthType(ethType); |
| } |
| if (!isNullOrEmpty(vlanString)) { |
| selectorBuilder.matchVlanId(VlanId.vlanId(Short.parseShort(vlanString))); |
| } |
| if (!isNullOrEmpty(srcMacString)) { |
| selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMacString)); |
| } |
| |
| if (!isNullOrEmpty(dstMacString)) { |
| selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString)); |
| } |
| |
| if (!isNullOrEmpty(ipProtoString)) { |
| short ipProtoShort = IpProtocol.parseFromString(ipProtoString); |
| selectorBuilder.matchIPProtocol((byte) ipProtoShort); |
| } |
| |
| if (!isNullOrEmpty(fLabelString)) { |
| selectorBuilder.matchIPv6FlowLabel(Integer.parseInt(fLabelString)); |
| } |
| |
| if (!isNullOrEmpty(icmp6TypeString)) { |
| byte icmp6Type = Icmp6Type.parseFromString(icmp6TypeString); |
| selectorBuilder.matchIcmpv6Type(icmp6Type); |
| } |
| |
| if (!isNullOrEmpty(icmp6CodeString)) { |
| byte icmp6Code = Icmp6Code.parseFromString(icmp6CodeString); |
| selectorBuilder.matchIcmpv6Code(icmp6Code); |
| } |
| |
| if (!isNullOrEmpty(ndTargetString)) { |
| selectorBuilder.matchIPv6NDTargetAddress(Ip6Address.valueOf(ndTargetString)); |
| } |
| |
| if (!isNullOrEmpty(ndSllString)) { |
| selectorBuilder.matchIPv6NDSourceLinkLayerAddress(MacAddress.valueOf(ndSllString)); |
| } |
| |
| if (!isNullOrEmpty(ndTllString)) { |
| selectorBuilder.matchIPv6NDTargetLinkLayerAddress(MacAddress.valueOf(ndTllString)); |
| } |
| |
| if (!isNullOrEmpty(srcTcpString)) { |
| selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpString))); |
| } |
| |
| if (!isNullOrEmpty(dstTcpString)) { |
| selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpString))); |
| } |
| |
| if (extHdrStringList != null) { |
| short extHdr = 0; |
| for (String extHdrString : extHdrStringList) { |
| extHdr = (short) (extHdr | ExtHeader.parseFromString(extHdrString)); |
| } |
| selectorBuilder.matchIPv6ExthdrFlags(extHdr); |
| } |
| |
| return selectorBuilder.build(); |
| } |
| } |