/* * Copyright 2014-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.Option; import org.onlab.packet.Ip6Address; import org.onlab.packet.IpAddress; import org.onlab.packet.IpPrefix; import org.onlab.packet.MacAddress; import org.onlab.packet.TpPort; import org.onlab.packet.VlanId; import org.onlab.util.Bandwidth; import org.onosproject.cli.AbstractShellCommand; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.net.Link; import org.onosproject.net.PortNumber; import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.intent.Constraint; import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.Key; import org.onosproject.net.intent.constraint.BandwidthConstraint; import org.onosproject.net.intent.constraint.LambdaConstraint; import org.onosproject.net.intent.constraint.LinkTypeConstraint; import org.onosproject.net.intent.constraint.PartialFailureConstraint; import org.onosproject.net.resource.link.BandwidthResource; import java.util.LinkedList; import java.util.List; import static com.google.common.base.Strings.isNullOrEmpty; import static org.onosproject.net.flow.DefaultTrafficTreatment.builder; /** * Base class for command line operations for connectivity based intents. */ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { // Selectors @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 extHdrStringList = null; @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth", required = false, multiValued = false) private String bandwidthString = null; @Option(name = "-l", aliases = "--lambda", description = "Lambda", required = false, multiValued = false) private boolean lambda = false; @Option(name = "-a", aliases = "--appId", description = "Application Id", required = false, multiValued = false) private String appId = null; @Option(name = "-k", aliases = "--key", description = "Intent Key", required = false, multiValued = false) private String intentKey = null; @Option(name = "--partial", description = "Allow partial installation", required = false, multiValued = false) private boolean partial = false; // Treatments @Option(name = "--setEthSrc", description = "Rewrite Source MAC Address", required = false, multiValued = false) private String setEthSrcString = null; @Option(name = "--setEthDst", description = "Rewrite Destination MAC Address", required = false, multiValued = false) private String setEthDstString = null; @Option(name = "--setIpSrc", description = "Rewrite Source IP Address", required = false, multiValued = false) private String setIpSrcString = null; @Option(name = "--setIpDst", description = "Rewrite Destination IP Address", required = false, multiValued = false) private String setIpDstString = null; @Option(name = "--setVlan", description = "Rewrite VLAN ID", required = false, multiValued = false) private String setVlan = null; @Option(name = "--popVlan", description = "Pop VLAN Tag", required = false, multiValued = false) private boolean popVlan = false; @Option(name = "--pushVlan", description = "Push VLAN ID", required = false, multiValued = false) private String pushVlan = null; @Option(name = "--setQueue", description = "Set Queue ID (for OpenFlow 1.0, " + "also the port has to be specified, i.e., /", required = false, multiValued = false) private String setQueue = null; // Priorities @Option(name = "-p", aliases = "--priority", description = "Priority", required = false, multiValued = false) private int priority = Intent.DEFAULT_INTENT_PRIORITY; /** * Constructs a traffic selector based on the command line arguments * presented to the command. * @return traffic selector */ protected 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(); } /** * Generates a traffic treatment for this intent based on command line * arguments presented to the command. * * @return traffic treatment */ protected TrafficTreatment buildTrafficTreatment() { final TrafficTreatment.Builder treatmentBuilder = builder(); boolean emptyTreatment = true; if (!isNullOrEmpty(setEthSrcString)) { treatmentBuilder.setEthSrc(MacAddress.valueOf(setEthSrcString)); emptyTreatment = false; } if (!isNullOrEmpty(setEthDstString)) { treatmentBuilder.setEthDst(MacAddress.valueOf(setEthDstString)); emptyTreatment = false; } if (!isNullOrEmpty(setIpSrcString)) { treatmentBuilder.setIpSrc(IpAddress.valueOf(setIpSrcString)); emptyTreatment = false; } if (!isNullOrEmpty(setIpDstString)) { treatmentBuilder.setIpSrc(IpAddress.valueOf(setIpDstString)); emptyTreatment = false; } if (!isNullOrEmpty(setVlan)) { treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(setVlan))); emptyTreatment = false; } if (popVlan) { treatmentBuilder.popVlan(); emptyTreatment = false; } if (!isNullOrEmpty(pushVlan)) { treatmentBuilder.pushVlan(); treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(pushVlan))); emptyTreatment = false; } if (!isNullOrEmpty(setQueue)) { // OpenFlow 1.0 notation (for ENQUEUE): / if (setQueue.contains("/")) { String[] queueConfig = setQueue.split("/"); PortNumber port = PortNumber.portNumber(Long.parseLong(queueConfig[0])); long queueId = Long.parseLong(queueConfig[1]); treatmentBuilder.setQueue(queueId, port); } else { treatmentBuilder.setQueue(Long.parseLong(setQueue)); } emptyTreatment = false; } if (emptyTreatment) { return DefaultTrafficTreatment.emptyTreatment(); } else { return treatmentBuilder.build(); } } /** * Builds the constraint list for this command based on the command line * parameters. * * @return List of constraint objects describing the constraints requested */ protected List buildConstraints() { final List constraints = new LinkedList<>(); // Check for a bandwidth specification if (!isNullOrEmpty(bandwidthString)) { final Bandwidth bandwidth = Bandwidth.bps(Double.parseDouble(bandwidthString)); constraints.add(new BandwidthConstraint(new BandwidthResource(bandwidth))); } // Check for a lambda specification if (lambda) { constraints.add(new LambdaConstraint(null)); } constraints.add(new LinkTypeConstraint(lambda, Link.Type.OPTICAL)); if (partial) { constraints.add(new PartialFailureConstraint()); } return constraints; } @Override protected ApplicationId appId() { ApplicationId appIdForIntent; if (appId == null) { appIdForIntent = super.appId(); } else { CoreService service = get(CoreService.class); appIdForIntent = service.getAppId(appId); } return appIdForIntent; } /** * Creates a key for an intent based on command line arguments. If a key * has been specified, it is returned. If no key is specified, null * is returned. * * @return intent key if specified, null otherwise */ protected Key key() { Key key = null; ApplicationId appIdForIntent; if (intentKey != null) { key = Key.of(intentKey, appId()); } return key; } /** * Gets the priority to use for the intent. * * @return priority */ protected int priority() { return priority; } }