[ONOS-4612]Update SFC flows inline with the Official OVS NSH patch
Change-Id: If58517841096a939860d88aa78eca7cae46b9935
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java
deleted file mode 100644
index b270b13..0000000
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2015-present 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.sfc.forwarder;
-
-import java.util.List;
-
-import org.onosproject.net.NshServicePathId;
-import org.onosproject.vtnrsc.PortChain;
-import org.onosproject.vtnrsc.PortPairId;
-
-/**
- * Abstraction of an entity which provides service function forwarder.
- */
-public interface ServiceFunctionForwarderService {
-
- /**
- * Install forwarding rule.
- *
- * @param portChain port-chain
- * @param nshSpi nsh spi
- */
- @Deprecated
- void installForwardingRule(PortChain portChain, NshServicePathId nshSpi);
-
- /**
- * Uninstall forwarding rule.
- *
- * @param portChain port-chain
- * @param nshSpi nsh spi
- */
- @Deprecated
- void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSpi);
-
- /**
- * Install load balanced forwarding rules.
- *
- * @param path load balanced path of port pairs
- * @param nshSpi nsh service path index
- */
- void installLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi);
-
- /**
- * Uninstall load balanced forwarding rules.
- *
- * @param path load balanced path of port pairs
- * @param nshSpi nsh service path index
- */
- void unInstallLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi);
-}
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java
deleted file mode 100644
index 9875e4d..0000000
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright 2015-present 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.sfc.forwarder.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.List;
-import java.util.ListIterator;
-
-import org.onlab.osgi.DefaultServiceDirectory;
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.TpPort;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.NshServicePathId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.ExtensionSelectorResolver;
-import org.onosproject.net.driver.DriverHandler;
-import org.onosproject.net.driver.DriverService;
-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.flow.criteria.ExtensionSelector;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.host.HostService;
-import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService;
-import org.onosproject.vtnrsc.PortChain;
-import org.onosproject.vtnrsc.PortPair;
-import org.onosproject.vtnrsc.PortPairId;
-import org.onosproject.vtnrsc.VirtualPortId;
-import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
-import org.onosproject.vtnrsc.portchain.PortChainService;
-import org.onosproject.vtnrsc.portpair.PortPairService;
-import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
-import org.onosproject.vtnrsc.service.VtnRscService;
-import org.onosproject.vtnrsc.virtualport.VirtualPortService;
-import org.slf4j.Logger;
-
-/**
- * Provides service function forwarder implementation.
- */
-public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService {
-
- private final Logger log = getLogger(getClass());
- protected VirtualPortService virtualPortService;
- protected VtnRscService vtnRscService;
- protected PortPairService portPairService;
- protected PortPairGroupService portPairGroupService;
- protected FlowClassifierService flowClassifierService;
- protected PortChainService portChainService;
- protected DriverService driverService;
- protected FlowObjectiveService flowObjectiveService;
- protected HostService hostService;
- protected ApplicationId appId;
-
- private static final String PATH_NOT_NULL = "Load balanced path cannot be null";
- private static final String APP_ID_NOT_NULL = "Application-Id cannot be null";
-
- /**
- * Default constructor.
- */
- public ServiceFunctionForwarderImpl() {
- }
-
- /**
- * Explicit constructor.
- *
- * @param appId application id
- */
- public ServiceFunctionForwarderImpl(ApplicationId appId) {
- this.appId = checkNotNull(appId, APP_ID_NOT_NULL);
- ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
- this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
- this.driverService = serviceDirectory.get(DriverService.class);
- this.virtualPortService = serviceDirectory.get(VirtualPortService.class);
- this.vtnRscService = serviceDirectory.get(VtnRscService.class);
- this.portPairService = serviceDirectory.get(PortPairService.class);
- this.portPairGroupService = serviceDirectory.get(PortPairGroupService.class);
- this.flowClassifierService = serviceDirectory.get(FlowClassifierService.class);
- this.hostService = serviceDirectory.get(HostService.class);
- this.portChainService = serviceDirectory.get(PortChainService.class);
- }
-
- @Override
- public void installForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
- //TODO this method will be removed
- }
-
- @Override
- public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
- //TODO this method will be removed
- }
-
- @Override
- public void installLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi) {
- checkNotNull(path, PATH_NOT_NULL);
- processForwardingRule(path, nshSpi, Objective.Operation.ADD);
- }
-
- @Override
- public void unInstallLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi) {
- checkNotNull(path, PATH_NOT_NULL);
- processForwardingRule(path, nshSpi, Objective.Operation.REMOVE);
- }
-
- /**
- * Process the required forwarding rules for the given path.
- *
- * @param path list of port pair ids
- * @param nshSpi service path index
- * @param type operation type ADD/REMOVE
- */
- private void processForwardingRule(List<PortPairId> path, NshServicePathId nshSpi,
- Objective.Operation type) {
-
- // Get the first port pair
- ListIterator<PortPairId> portPairListIterator = path.listIterator();
- PortPair currentPortPair = portPairService.getPortPair(portPairListIterator.next());
-
- // Get destination port pair group
- if (!portPairListIterator.hasNext()) {
- log.debug("Path is empty");
- return;
- }
- PortPair nextPortPair = portPairService.getPortPair(portPairListIterator.next());
- DeviceId currentDeviceId = null;
- DeviceId nextDeviceId = null;
-
- // Travel from SF to SF.
- do {
- currentDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(currentPortPair.egress()));
- nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(nextPortPair.ingress()));
- // pack traffic selector
- TrafficSelector.Builder selector = packTrafficSelector(currentDeviceId, currentPortPair, nshSpi);
- // Pack treatment
- if (currentDeviceId.equals(nextDeviceId)) {
- TrafficTreatment.Builder treatment = packTrafficTreatment(nextPortPair, true);
- // Send SFF to SFF
- sendServiceFunctionForwarder(selector, treatment, currentDeviceId, type);
- } else {
- TrafficTreatment.Builder treatment = packTrafficTreatment(nextPortPair, false);
- // Send SFF to OVS
- sendServiceFunctionForwarder(selector, treatment, currentDeviceId, type);
-
- // At the other device get the packet from vlan and send to first port pair
- TrafficSelector.Builder selectorDst = DefaultTrafficSelector.builder();
- selectorDst.matchVlanId((VlanId.vlanId(Short.parseShort((vtnRscService
- .getL3vni(nextPortPair.tenantId()).toString())))));
- TrafficTreatment.Builder treatmentDst = DefaultTrafficTreatment.builder();
- MacAddress macAddr = virtualPortService.getPort(VirtualPortId.portId(nextPortPair.ingress()))
- .macAddress();
- Host host = hostService.getHost(HostId.hostId(macAddr));
- PortNumber port = host.location().port();
- treatmentDst.setOutput(port);
- // Send OVS to SFF
- sendServiceFunctionForwarder(selectorDst, treatmentDst, nextDeviceId, type);
- }
-
- // Move to next service function
- currentPortPair = nextPortPair;
- if (!portPairListIterator.hasNext()) {
- break;
- }
- nextPortPair = portPairService.getPortPair(portPairListIterator.next());
- } while (true);
- }
-
- /**
- * Pack traffic selector.
- *
- * @param deviceId device id
- * @param portPair port-pair
- * @param nshSpi nsh service path index
- * @return traffic selector
- */
- public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId,
- PortPair portPair, NshServicePathId nshSpi) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
-
- MacAddress dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
- Host host = hostService.getHost(HostId.hostId(dstMacAddress));
- PortNumber port = host.location().port();
- selector.matchInPort(port);
-
- DriverHandler handler = driverService.createHandler(deviceId);
- ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
- ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
-
- try {
- nspSpiSelector.setPropertyValue("nshSpi", nshSpi);
- } catch (Exception e) {
- log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
- }
-
- selector.extension(nspSpiSelector, deviceId);
-
- return selector;
- }
-
- /**
- * Pack traffic treatment.
- *
- * @param portPair port pair
- * @param isSameOvs whether the next port pair is in the same ovs
- * @return traffic treatment
- */
- public TrafficTreatment.Builder packTrafficTreatment(PortPair portPair, boolean isSameOvs) {
- MacAddress srcMacAddress = null;
-
- // Check the treatment whether destination SF is on same OVS or in
- // different OVS.
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- if (isSameOvs) {
- srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
- Host host = hostService.getHost(HostId.hostId(srcMacAddress));
- PortNumber port = host.location().port();
- treatment.setOutput(port);
- } else {
- // Vxlan tunnel port for NSH header(Vxlan + NSH).
- TpPort nshDstPort = TpPort.tpPort(6633);
- // TODO check whether this logic is correct
- VlanId vlanId = VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair.tenantId()).toString())));
- treatment.setVlanId(vlanId);
- treatment.setUdpDst(nshDstPort);
- }
-
- return treatment;
- }
-
- /**
- * Send service function forwarder to OVS.
- *
- * @param selector traffic selector
- * @param treatment traffic treatment
- * @param deviceId device id
- * @param type operation type
- */
- public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
- DeviceId deviceId, Objective.Operation type) {
- log.info("Sending flow to serfice-function-forwarder. Selector {}, Treatment {}",
- selector.toString(), treatment.toString());
- ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
- .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE);
- if (type.equals(Objective.Operation.ADD)) {
- log.debug("ADD");
- flowObjectiveService.forward(deviceId, objective.add());
- } else {
- log.debug("REMOVE");
- flowObjectiveService.forward(deviceId, objective.remove());
- }
- }
-}
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java
deleted file mode 100644
index 6dfe007..0000000
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present 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.
- */
-
-/**
- * SFC Service manager for interacting with SFC.
- */
-package org.onosproject.sfc.forwarder.impl;
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java
deleted file mode 100644
index 83ac1dd..0000000
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present 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.
- */
-
-/**
- * Service function forwarder for SFC.
- */
-package org.onosproject.sfc.forwarder;
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstallerService.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/SfcFlowRuleInstallerService.java
similarity index 79%
rename from apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstallerService.java
rename to apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/SfcFlowRuleInstallerService.java
index 58e59be..caff305 100644
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstallerService.java
+++ b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/SfcFlowRuleInstallerService.java
@@ -23,7 +23,7 @@
/**
* Abstraction of an entity which installs flow classification rules in ovs.
*/
-public interface FlowClassifierInstallerService {
+public interface SfcFlowRuleInstallerService {
/**
* Install flow classifier.
@@ -44,24 +44,24 @@
ConnectPoint unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId);
/**
- * Install load balanced flow classifier.
+ * Install load balanced flow rules.
*
* @param portChain port-chain
* @param fiveTuple five tuple packet information
* @param nshSpiId service path index identifier
* @return connectPoint the network identifier
*/
- ConnectPoint installLoadBalancedFlowClassifier(PortChain portChain, FiveTuple fiveTuple,
- NshServicePathId nshSpiId);
+ ConnectPoint installLoadBalancedFlowRules(PortChain portChain, FiveTuple fiveTuple,
+ NshServicePathId nshSpiId);
/**
- * Uninstall load balanced flow classifier.
+ * Uninstall load balanced flow rules.
*
* @param portChain port-chain
* @param fiveTuple five tuple packet information
* @param nshSpiId service path index identifier
* @return connectPoint the network identifier
*/
- ConnectPoint unInstallLoadBalancedFlowClassifier(PortChain portChain, FiveTuple fiveTuple,
- NshServicePathId nshSpiId);
+ ConnectPoint unInstallLoadBalancedFlowRules(PortChain portChain, FiveTuple fiveTuple,
+ NshServicePathId nshSpiId);
}
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/FlowClassifierInstallerImpl.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/FlowClassifierInstallerImpl.java
deleted file mode 100644
index ec12553..0000000
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/FlowClassifierInstallerImpl.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright 2015-present 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.sfc.installer.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI;
-import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-
-import org.onlab.osgi.DefaultServiceDirectory;
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.TpPort;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.NshServiceIndex;
-import org.onosproject.net.NshServicePathId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.DriverHandler;
-import org.onosproject.net.driver.DriverService;
-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.flow.criteria.Criteria;
-import org.onosproject.net.flow.instructions.ExtensionTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.host.HostService;
-import org.onosproject.sfc.installer.FlowClassifierInstallerService;
-import org.onosproject.vtnrsc.FiveTuple;
-import org.onosproject.vtnrsc.FlowClassifier;
-import org.onosproject.vtnrsc.FlowClassifierId;
-import org.onosproject.vtnrsc.PortChain;
-import org.onosproject.vtnrsc.PortPair;
-import org.onosproject.vtnrsc.PortPairGroup;
-import org.onosproject.vtnrsc.PortPairGroupId;
-import org.onosproject.vtnrsc.PortPairId;
-import org.onosproject.vtnrsc.VirtualPortId;
-import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
-import org.onosproject.vtnrsc.portpair.PortPairService;
-import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
-import org.onosproject.vtnrsc.service.VtnRscService;
-import org.onosproject.vtnrsc.virtualport.VirtualPortService;
-import org.slf4j.Logger;
-
-/**
- * Provides flow classifier installer implementation.
- */
-public class FlowClassifierInstallerImpl implements FlowClassifierInstallerService {
- private final Logger log = getLogger(getClass());
-
- protected VirtualPortService virtualPortService;
- protected VtnRscService vtnRscService;
- protected PortPairService portPairService;
- protected PortPairGroupService portPairGroupService;
- protected FlowClassifierService flowClassifierService;
- protected DriverService driverService;
- protected DeviceService deviceService;
- protected HostService hostService;
- protected FlowObjectiveService flowObjectiveService;
- protected ApplicationId appId;
-
- private static final String DRIVER_NAME = "onosfw";
- private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow-Classifier cannot be null";
- private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow-Classifier-Id cannot be null";
- private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
- private static final int NULL = 0;
- private static final int FLOW_CLASSIFIER_PRIORITY = 0x7fff;
- private static final short NSH_SI_ID = 0xff;
-
- /**
- * Default constructor.
- */
- public FlowClassifierInstallerImpl() {
- }
-
- /**
- * Explicit constructor.
- *
- * @param appId application id.
- */
- public FlowClassifierInstallerImpl(ApplicationId appId) {
- this.appId = checkNotNull(appId, "ApplicationId can not be null");
- ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
- this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
- this.driverService = serviceDirectory.get(DriverService.class);
- this.deviceService = serviceDirectory.get(DeviceService.class);
- this.hostService = serviceDirectory.get(HostService.class);
- this.virtualPortService = serviceDirectory.get(VirtualPortService.class);
- this.vtnRscService = serviceDirectory.get(VtnRscService.class);
- this.portPairService = serviceDirectory.get(PortPairService.class);
- this.portPairGroupService = serviceDirectory.get(PortPairGroupService.class);
- this.flowClassifierService = serviceDirectory.get(FlowClassifierService.class);
- }
-
- @Override
- public ConnectPoint installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
- checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
- // Get the portPairGroup
- List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
- ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
- PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
- PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
- List<PortPairId> llPortPairIdList = portPairGroup.portPairs();
-
- // Get port pair
- ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
- PortPairId portPairId = portPairListIterator.next();
- PortPair portPair = portPairService.getPortPair(portPairId);
-
- return processFlowClassifier(portChain, portPair, nshSpiId, null, Objective.Operation.ADD);
- }
-
- @Override
- public ConnectPoint unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
- checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
- // Get the portPairGroup
- List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
- ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
- PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
- PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
- List<PortPairId> llPortPairIdList = portPairGroup.portPairs();
-
- // Get port pair
- ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
- PortPairId portPairId = portPairListIterator.next();
- PortPair portPair = portPairService.getPortPair(portPairId);
-
- return processFlowClassifier(portChain, portPair, nshSpiId, null, Objective.Operation.REMOVE);
- }
-
- @Override
- public ConnectPoint installLoadBalancedFlowClassifier(PortChain portChain, FiveTuple fiveTuple,
- NshServicePathId nshSpiId) {
- checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
-
- // Get the load balanced path
- List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);
-
- // Get the first port pair
- ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
- PortPairId portPairId = portPairListIterator.next();
- PortPair portPair = portPairService.getPortPair(portPairId);
-
- return processFlowClassifier(portChain, portPair, nshSpiId, fiveTuple, Objective.Operation.ADD);
- }
-
- @Override
- public ConnectPoint unInstallLoadBalancedFlowClassifier(PortChain portChain, FiveTuple fiveTuple,
- NshServicePathId nshSpiId) {
- checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
- // Get the load balanced path
- List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);
-
- // Get the first port pair
- ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
- PortPairId portPairId = portPairListIterator.next();
- PortPair portPair = portPairService.getPortPair(portPairId);
-
- return processFlowClassifier(portChain, portPair, nshSpiId, fiveTuple, Objective.Operation.REMOVE);
- }
-
- public ConnectPoint processFlowClassifier(PortChain portChain, PortPair portPair, NshServicePathId nshSpiId,
- FiveTuple fiveTuple, Objective.Operation type) {
-
- DeviceId deviceIdfromPortPair = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
- MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
- Host host = hostService.getHost(HostId.hostId(srcMacAddress));
- PortNumber port = host.location().port();
-
- DeviceId deviceId = deviceIdfromPortPair;
-
- // Vxlan tunnel port for NSH header(Vxlan + NSH).
- TpPort nshDstPort = TpPort.tpPort(6633);
-
- FlowClassifierInstallerService flowclassifierinstallerService;
- // get flow classifiers
- List<FlowClassifierId> llFlowClassifierList = portChain.flowClassifiers();
- ListIterator<FlowClassifierId> flowClassifierListIterator = llFlowClassifierList.listIterator();
-
- while (flowClassifierListIterator.hasNext()) {
- FlowClassifierId flowclassifierId = flowClassifierListIterator.next();
- FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowclassifierId);
-
- if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
- deviceId = vtnRscService.getSfToSffMaping(flowClassifier.srcPort());
- }
-
- // Build Traffic selector.
- TrafficSelector.Builder selector = packTrafficSelector(flowClassifier, fiveTuple);
-
- if (fiveTuple == null) {
- // Send the packet to controller
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.setOutput(PortNumber.CONTROLLER);
- sendServiceFunctionClassifier(selector, treatment, deviceId, type, flowClassifier.priority());
- } else if (deviceId.equals(deviceIdfromPortPair)) {
- // classifier and source device are in the same OVS. So directly send packet to first port pair
- TrafficTreatment.Builder treatment = packTrafficTreatment(deviceId, port, nshDstPort,
- nshSpiId, flowClassifier, true);
- // Build forwarding objective and send to OVS.
- sendServiceFunctionClassifier(selector, treatment, deviceId, type, flowClassifier.priority());
- } else {
- // classifier and source device are not in the same OVS. Send packet on vlan Tunnel
- TrafficTreatment.Builder treatment = packTrafficTreatment(deviceId, port, nshDstPort,
- nshSpiId, flowClassifier, false);
- // Build forwarding objective and send to OVS.
- sendServiceFunctionClassifier(selector, treatment, deviceId, type, flowClassifier.priority());
-
- // At the other device get the packet from vlan and send to first port pair
- TrafficSelector.Builder selectorDst = DefaultTrafficSelector.builder();
- selectorDst.matchVlanId((VlanId.vlanId(Short.parseShort((vtnRscService
- .getL3vni(flowClassifier.tenantId()).toString())))));
- TrafficTreatment.Builder treatmentDst = DefaultTrafficTreatment.builder();
- Host hostDst = hostService.getHost(HostId.hostId(srcMacAddress));
- treatmentDst.setOutput(hostDst.location().port());
- sendServiceFunctionClassifier(selectorDst, treatmentDst, deviceIdfromPortPair, type,
- flowClassifier.priority());
- }
- }
- return host.location();
- }
-
- /**
- * Pack Traffic selector.
- *
- * @param flowClassifier flow-classifier
- * @param fiveTuple five tuple info for the packet
- * @return traffic selector
- */
- public TrafficSelector.Builder packTrafficSelector(FlowClassifier flowClassifier, FiveTuple fiveTuple) {
-
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
-
- if ((flowClassifier.srcIpPrefix() != null) && (flowClassifier.srcIpPrefix().prefixLength() != 0)) {
- selector.matchIPSrc(flowClassifier.srcIpPrefix());
- } else if (fiveTuple != null && fiveTuple.ipSrc() != null) {
- selector.matchIPSrc(IpPrefix.valueOf(fiveTuple.ipSrc(), 24));
- }
-
- if ((flowClassifier.dstIpPrefix() != null) && (flowClassifier.dstIpPrefix().prefixLength() != 0)) {
- selector.matchIPDst(flowClassifier.dstIpPrefix());
- } else if (fiveTuple != null && fiveTuple.ipDst() != null) {
- selector.matchIPDst(IpPrefix.valueOf(fiveTuple.ipDst(), 24));
- }
-
- if ((flowClassifier.protocol() != null) && (!flowClassifier.protocol().isEmpty())) {
- if (flowClassifier.protocol().equalsIgnoreCase("TCP")) {
- selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_TCP));
- } else if (flowClassifier.protocol().equalsIgnoreCase("UDP")) {
- selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP));
- }
- } else if (fiveTuple != null && fiveTuple.protocol() != 0) {
- selector.add(Criteria.matchIPProtocol(fiveTuple.protocol()));
- }
-
- if (((flowClassifier.etherType() != null) && (!flowClassifier.etherType().isEmpty()))
- && (flowClassifier.etherType().equals("IPv4") || flowClassifier.etherType().equals("IPv6"))) {
- if (flowClassifier.etherType().equals("IPv4")) {
- selector.matchEthType(Ethernet.TYPE_IPV4);
- } else {
- selector.matchEthType(Ethernet.TYPE_IPV6);
- }
- }
-
- if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
- VirtualPortId vPortId = VirtualPortId.portId(flowClassifier.srcPort().portId());
- MacAddress macAddress = virtualPortService.getPort(vPortId).macAddress();
- Host host = hostService.getHost(HostId.hostId(macAddress));
- selector.matchInPort(host.location().port());
- }
-
- // Take the port information from five tuple only when the protocol is TCP.
- if (fiveTuple != null && fiveTuple.protocol() == IPv4.PROTOCOL_TCP) {
- selector.matchTcpSrc(TpPort.tpPort((int) fiveTuple.portSrc().toLong()));
- selector.matchTcpDst(TpPort.tpPort((int) fiveTuple.portDst().toLong()));
- } else {
- // For udp packets take the port information from flow classifier
- List<TpPort> srcPortRange = new LinkedList<>();
- List<TpPort> dstPortRange = new LinkedList<>();
- if ((flowClassifier.minSrcPortRange() != 0) && flowClassifier.maxSrcPortRange() != 0
- && flowClassifier.minDstPortRange() != 0 && flowClassifier.maxDstPortRange() != 0) {
-
- for (int port = flowClassifier.minSrcPortRange(); port <= flowClassifier.maxSrcPortRange(); port++) {
- srcPortRange.add(TpPort.tpPort(port));
- }
- for (int port = flowClassifier.minDstPortRange(); port <= flowClassifier.maxDstPortRange(); port++) {
- dstPortRange.add(TpPort.tpPort(port));
- }
- }
-
- for (TpPort inPort : srcPortRange) {
- selector.matchUdpSrc(inPort);
- }
- for (TpPort outPort : dstPortRange) {
- selector.matchUdpDst(outPort);
- }
- }
- return selector;
- }
-
- /**
- * Pack traffic treatment.
- *
- * @param deviceId device id
- * @param port port number
- * @param nshDstPort vxlan tunnel port for nsh header
- * @param nshSpi nsh spi
- * @param flowClassifier flow-classifier
- * @param isSameOvs whether the next service function is in same ovs
- * @return traffic treatment
- */
- public TrafficTreatment.Builder packTrafficTreatment(DeviceId deviceId, PortNumber port,
- TpPort nshDstPort, NshServicePathId nshSpi,
- FlowClassifier flowClassifier, boolean isSameOvs) {
-
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
-
- if (isSameOvs) {
- treatmentBuilder.setOutput(port);
- } else {
- treatmentBuilder.setVlanId((VlanId.vlanId(Short.parseShort((vtnRscService
- .getL3vni(flowClassifier.tenantId()).toString())))));
- treatmentBuilder.setUdpDst(nshDstPort);
- }
-
- // Set NSH
- DriverHandler handler = driverService.createHandler(deviceId);
- ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
- ExtensionTreatment nspIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SPI.type());
- ExtensionTreatment nsiIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SI.type());
-
- treatmentBuilder.extension(nspIdTreatment, deviceId);
- treatmentBuilder.extension(nsiIdTreatment, deviceId);
-
- try {
- nspIdTreatment.setPropertyValue("nshSpi", nshSpi);
- } catch (Exception e) {
- log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
- }
- try {
- nsiIdTreatment.setPropertyValue("nshSi", NshServiceIndex.of(NSH_SI_ID));
- } catch (Exception e) {
- log.error("Failed to get extension instruction to set Nsh Si Id {}", deviceId);
- }
-
- return treatmentBuilder;
- }
-
- /**
- * Send service-function-forwarder to OVS.
- *
- * @param selector traffic selector
- * @param treatment traffic treatment
- * @param deviceId device id
- * @param type operation type
- * @param priority priority of classifier
- */
- public void sendServiceFunctionClassifier(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
- DeviceId deviceId, Objective.Operation type, int priority) {
- log.info("Sending flow to service function classifier. Selector {}, Treatment {}",
- selector.toString(), treatment.toString());
- ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
- .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE)
- .withPriority(priority);
-
- if (type.equals(Objective.Operation.ADD)) {
- log.debug("flowClassifierRules-->ADD");
- flowObjectiveService.forward(deviceId, objective.add());
- } else {
- log.debug("flowClassifierRules-->REMOVE");
- flowObjectiveService.forward(deviceId, objective.remove());
- }
- }
-}
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/SfcFlowRuleInstallerImpl.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/SfcFlowRuleInstallerImpl.java
new file mode 100644
index 0000000..71397a7
--- /dev/null
+++ b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/SfcFlowRuleInstallerImpl.java
@@ -0,0 +1,888 @@
+/*
+ * Copyright 2016-present 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.sfc.installer.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE;
+import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI;
+import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_DST;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_SRC;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_MDTYPE;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_NP;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_POP_NSH;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_PUSH_NSH;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_TUN_GPE_NP;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.NshContextHeader;
+import org.onosproject.net.NshServiceIndex;
+import org.onosproject.net.NshServicePathId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.ExtensionSelectorResolver;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+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.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.host.HostService;
+import org.onosproject.sfc.installer.SfcFlowRuleInstallerService;
+import org.onosproject.vtnrsc.FiveTuple;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.onosproject.vtnrsc.VirtualPort;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
+import org.onosproject.vtnrsc.portpair.PortPairService;
+import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
+import org.onosproject.vtnrsc.service.VtnRscService;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
+import org.onosproject.vtnrsc.virtualport.VirtualPortService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Provides flow classifier installer implementation.
+ */
+public class SfcFlowRuleInstallerImpl implements SfcFlowRuleInstallerService {
+ private final Logger log = getLogger(getClass());
+
+ protected VirtualPortService virtualPortService;
+ protected VtnRscService vtnRscService;
+ protected PortPairService portPairService;
+ protected PortPairGroupService portPairGroupService;
+ protected FlowClassifierService flowClassifierService;
+ protected DriverService driverService;
+ protected DeviceService deviceService;
+ protected HostService hostService;
+ protected TenantNetworkService tenantNetworkService;
+ protected FlowObjectiveService flowObjectiveService;
+ protected ApplicationId appId;
+
+ private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
+ private static final int FLOW_CLASSIFIER_PRIORITY = 0xC738;
+ private static final int DEFAULT_FORWARDER_PRIORITY = 0xD6D8;
+ private static final int ENCAP_OUTPUT_PRIORITY = 0x64;
+ private static final int TUNNEL_SEND_PRIORITY = 0xC8;
+ private static final String SWITCH_CHANNEL_ID = "channelId";
+ private static final int ENCAP_OUTPUT_TABLE = 4;
+ private static final int TUNNEL_SEND_TABLE = 7;
+ private static final short ENCAP_ETH_TYPE = (short) 0x894f;
+ private static final String DEFAULT_IP = "0.0.0.0";
+ private static final String VXLANPORT_HEAD = "vxlan-0.0.0.0";
+
+ /* Port chain params */
+ private short nshSi;
+ List<DeviceId> classifierList;
+ List<DeviceId> forwarderList;
+
+ /**
+ * Default constructor.
+ */
+ public SfcFlowRuleInstallerImpl() {
+ }
+
+ /**
+ * Explicit constructor.
+ *
+ * @param appId application id.
+ */
+ public SfcFlowRuleInstallerImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ this.driverService = serviceDirectory.get(DriverService.class);
+ this.deviceService = serviceDirectory.get(DeviceService.class);
+ this.hostService = serviceDirectory.get(HostService.class);
+ this.virtualPortService = serviceDirectory.get(VirtualPortService.class);
+ this.vtnRscService = serviceDirectory.get(VtnRscService.class);
+ this.portPairService = serviceDirectory.get(PortPairService.class);
+ this.portPairGroupService = serviceDirectory.get(PortPairGroupService.class);
+ this.flowClassifierService = serviceDirectory.get(FlowClassifierService.class);
+ this.tenantNetworkService = serviceDirectory.get(TenantNetworkService.class);
+ nshSi = 0xff;
+ }
+
+ @Override
+ public ConnectPoint installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
+ checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
+ // Get the portPairGroup
+ List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
+ ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
+ PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
+ PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
+ List<PortPairId> llPortPairIdList = portPairGroup.portPairs();
+
+ // Get port pair
+ ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
+ PortPairId portPairId = portPairListIterator.next();
+ PortPair portPair = portPairService.getPortPair(portPairId);
+
+ return installSfcClassifierRules(portChain, portPair, nshSpiId, null, Objective.Operation.ADD);
+ }
+
+ @Override
+ public ConnectPoint unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
+ checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
+ // Get the portPairGroup
+ List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
+ ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
+ PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
+ PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
+ List<PortPairId> llPortPairIdList = portPairGroup.portPairs();
+
+ // Get port pair
+ ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
+ PortPairId portPairId = portPairListIterator.next();
+ PortPair portPair = portPairService.getPortPair(portPairId);
+
+ return installSfcClassifierRules(portChain, portPair, nshSpiId, null, Objective.Operation.REMOVE);
+ }
+
+ @Override
+ public ConnectPoint installLoadBalancedFlowRules(PortChain portChain, FiveTuple fiveTuple,
+ NshServicePathId nshSpiId) {
+ checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
+
+ return installSfcFlowRules(portChain, fiveTuple, nshSpiId, Objective.Operation.ADD);
+ }
+
+ @Override
+ public ConnectPoint unInstallLoadBalancedFlowRules(PortChain portChain, FiveTuple fiveTuple,
+ NshServicePathId nshSpiId) {
+ checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
+ return installSfcFlowRules(portChain, fiveTuple, nshSpiId, Objective.Operation.REMOVE);
+ }
+
+ public ConnectPoint installSfcFlowRules(PortChain portChain, FiveTuple fiveTuple, NshServicePathId nshSpiId,
+ Objective.Operation type) {
+ checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
+
+ classifierList = Lists.newArrayList();
+ forwarderList = Lists.newArrayList();
+
+ // Get the load balanced path
+ List<PortPairId> portPairs = portChain.getLoadBalancePath(fiveTuple);
+
+ // Get the first port pair
+ ListIterator<PortPairId> portPairListIterator = portPairs.listIterator();
+ PortPairId portPairId = portPairListIterator.next();
+ PortPair currentPortPair = portPairService.getPortPair(portPairId);
+
+ ConnectPoint connectPoint = installSfcClassifierRules(portChain, currentPortPair, nshSpiId, fiveTuple, type);
+
+ log.info("Installing encap and output for first port pair");
+
+ installSfcEncapOutputRule(currentPortPair, nshSpiId, type);
+
+ PortPair nextPortPair;
+ while (portPairListIterator.hasNext()) {
+ portPairId = portPairListIterator.next();
+ nextPortPair = portPairService.getPortPair(portPairId);
+ installSfcForwardRule(currentPortPair, nextPortPair, nshSpiId, type);
+ installSfcEncapOutputRule(nextPortPair, nshSpiId, type);
+ currentPortPair = nextPortPair;
+ }
+ installSfcEndRule(currentPortPair, nshSpiId, type);
+
+ if (type.equals(Objective.Operation.ADD)) {
+ portChain.addSfcClassifiers(portChain.getLoadBalanceId(fiveTuple), classifierList);
+ portChain.addSfcForwarders(portChain.getLoadBalanceId(fiveTuple), forwarderList);
+ } else {
+ portChain.removeSfcClassifiers(portChain.getLoadBalanceId(fiveTuple), classifierList);
+ portChain.removeSfcForwarders(portChain.getLoadBalanceId(fiveTuple), forwarderList);
+ }
+ return connectPoint;
+ }
+
+ public void installSfcTunnelReceiveRule(DeviceId deviceId, NshServicePathId nshSpiId, Objective.Operation type) {
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionSelectorResolver selectorResolver = handler.behaviour(ExtensionSelectorResolver.class);
+ ExtensionSelector nshSpiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
+ ExtensionSelector nshSiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
+
+ try {
+ nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Spi Id for end rule {}", e.getMessage());
+ }
+ try {
+ nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Si Id for end rule {}", e.getMessage());
+ }
+
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.extension(nshSpiSelector, deviceId);
+ selector.extension(nshSiSelector, deviceId);
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.transition(ENCAP_OUTPUT_TABLE);
+
+ sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
+ }
+
+ public void installSfcTunnelSendRule(DeviceId deviceId, NshServicePathId nshSpiId, Objective.Operation type) {
+
+ // Prepare selector with nsp, nsi and inport from egress of port pair
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionSelectorResolver selectorResolver = handler.behaviour(ExtensionSelectorResolver.class);
+ ExtensionSelector nshSpiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
+ ExtensionSelector nshSiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
+ ExtensionSelector encapEthTypeSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_ENCAP_ETH_TYPE
+ .type());
+ try {
+ nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Spi Id for end rule {}", e.getMessage());
+ }
+ try {
+ nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Si Id for end rule {}", e.getMessage());
+ }
+ try {
+ encapEthTypeSelector.setPropertyValue("encapEthType", ENCAP_ETH_TYPE);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match encapEthType {}", deviceId);
+ }
+
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.extension(nshSpiSelector, deviceId);
+ selector.extension(nshSiSelector, deviceId);
+
+ ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment tunGpeNpTreatment = treatmentResolver.getExtensionInstruction(NICIRA_TUN_GPE_NP.type());
+ try {
+ tunGpeNpTreatment.setPropertyValue("tunGpeNp", ((byte) 4));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set tunGpeNp {}", deviceId);
+ }
+
+ ExtensionTreatment moveC1ToC1 = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C1_TO_C1.type());
+
+ ExtensionTreatment moveC2ToC2 = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C2_TO_C2.type());
+
+ ExtensionTreatment moveC3ToC3 = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C3_TO_C3.type());
+
+ ExtensionTreatment moveC4ToC4 = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C4_TO_C4.type());
+
+ ExtensionTreatment moveTunIpv4DstToTunIpv4Dst = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST.type());
+
+ ExtensionTreatment moveTunIdToTunId = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_TUN_ID_TO_TUN_ID.type());
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.extension(tunGpeNpTreatment, deviceId);
+ treatment.extension(moveC1ToC1, deviceId);
+ treatment.extension(moveC2ToC2, deviceId);
+ treatment.extension(moveC3ToC3, deviceId);
+ treatment.extension(moveC4ToC4, deviceId);
+ treatment.extension(moveTunIpv4DstToTunIpv4Dst, deviceId);
+ treatment.extension(moveTunIdToTunId, deviceId);
+
+ Iterable<Device> devices = deviceService.getAvailableDevices();
+ DeviceId localControllerId = getControllerId(deviceService.getDevice(deviceId), devices);
+ DriverHandler controllerHandler = driverService.createHandler(localControllerId);
+
+ BridgeConfig bridgeConfig = controllerHandler.behaviour(BridgeConfig.class);
+ Set<PortNumber> ports = bridgeConfig.getPortNumbers();
+ String tunnelName = "vxlan-" + DEFAULT_IP;
+ ports.stream()
+ .filter(p ->p.name().equalsIgnoreCase(tunnelName))
+ .forEach(p -> {
+ treatment.setOutput(p);
+ sendSfcRule(selector, treatment, deviceId, type, TUNNEL_SEND_PRIORITY);
+ });
+ }
+
+ public void installSfcEndRule(PortPair portPair, NshServicePathId nshSpiId, Objective.Operation type) {
+ DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.egress()));
+ MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
+ Host host = hostService.getHost(HostId.hostId(srcMacAddress));
+ PortNumber port = host.location().port();
+
+ // Prepare selector with nsp, nsi and inport from egress of port pair
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionSelectorResolver selectorResolver = handler.behaviour(ExtensionSelectorResolver.class);
+ ExtensionSelector nshSpiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
+ ExtensionSelector nshSiSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
+ ExtensionSelector encapEthTypeSelector = selectorResolver.getExtensionSelector(NICIRA_MATCH_ENCAP_ETH_TYPE
+ .type());
+ try {
+ nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Spi Id for end rule {}", e.getMessage());
+ }
+ // Decrement the SI
+ nshSi = (short) (nshSi - 1);
+ try {
+ nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Si Id for end rule {}", e.getMessage());
+ }
+ try {
+ encapEthTypeSelector.setPropertyValue("encapEthType", ENCAP_ETH_TYPE);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match encapEthType {}", deviceId);
+ }
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.extension(encapEthTypeSelector, deviceId);
+ selector.extension(nshSpiSelector, deviceId);
+ selector.extension(nshSiSelector, deviceId);
+ selector.matchInPort(port);
+
+ // Set treatment to pop nsh header, set tunnel id and resubmit to table
+ // 0.
+ ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment popNshTreatment = treatmentResolver.getExtensionInstruction(NICIRA_POP_NSH.type());
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.extension(popNshTreatment, deviceId);
+
+ VirtualPort virtualPort = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress()));
+ SegmentationId segmentationId = tenantNetworkService.getNetwork(virtualPort.networkId()).segmentationId();
+ treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId.toString())));
+
+ ExtensionTreatment resubmitTableTreatment = treatmentResolver.getExtensionInstruction(NICIRA_RESUBMIT_TABLE
+ .type());
+
+ PortNumber vxlanPortNumber = getVxlanPortNumber(deviceId);
+
+ try {
+ resubmitTableTreatment.setPropertyValue("inPort", vxlanPortNumber);
+ } catch (Exception e) {
+ log.error("Failed to set extension treatment for resubmit table in port {}", deviceId);
+ }
+ try {
+ resubmitTableTreatment.setPropertyValue("table", ((short) 0));
+ } catch (Exception e) {
+ log.error("Failed to set extension treatment for resubmit table {}", deviceId);
+ }
+ treatment.extension(resubmitTableTreatment, deviceId);
+
+ sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
+ }
+
+ public void installSfcForwardRule(PortPair portPair, PortPair nextPortPair, NshServicePathId nshSpiId,
+ Objective.Operation type) {
+ DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.egress()));
+ MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
+ Host host = hostService.getHost(HostId.hostId(srcMacAddress));
+ PortNumber port = host.location().port();
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
+
+ // Prepare selector with nsp, nsi and inport from egress of port pair
+ ExtensionSelector nshSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
+ ExtensionSelector nshSiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
+ try {
+ nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Spi Id for forward rule {}", e.getMessage());
+ }
+ // Decrement the SI
+ nshSi = (short) (nshSi - 1);
+ try {
+ nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Si Id for forward rule {}", e.getMessage());
+ }
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.extension(nshSpiSelector, deviceId);
+ selector.extension(nshSiSelector, deviceId);
+ selector.matchInPort(port);
+
+ DeviceId nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(nextPortPair.ingress()));
+ if (deviceId.equals(nextDeviceId)) {
+
+ // Treatment with transition
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.transition(ENCAP_OUTPUT_TABLE);
+
+ sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
+ } else {
+ // Treatment with with transition to send on tunnel
+ ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment moveC2ToTunId = treatmentResolver
+ .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C2_TO_TUN_ID.type());
+
+ Device remoteDevice = deviceService.getDevice(nextDeviceId);
+ String url = remoteDevice.annotations().value(SWITCH_CHANNEL_ID);
+ String remoteControllerIp = url.substring(0, url.lastIndexOf(":"));
+ if (remoteControllerIp == null) {
+ log.error("Can't find remote controller of device: {}", nextDeviceId.toString());
+ return;
+ }
+
+ ExtensionTreatment tunnelDsttreatment = treatmentResolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST
+ .type());
+ try {
+ tunnelDsttreatment.setPropertyValue("tunnelDst", Ip4Address.valueOf(remoteControllerIp));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
+ }
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.extension(moveC2ToTunId, deviceId);
+ treatment.extension(tunnelDsttreatment, deviceId);
+ treatment.transition(TUNNEL_SEND_TABLE);
+
+ sendSfcRule(selector, treatment, deviceId, type, DEFAULT_FORWARDER_PRIORITY);
+
+ installSfcTunnelSendRule(deviceId, nshSpiId, type);
+ installSfcTunnelReceiveRule(nextDeviceId, nshSpiId, type);
+ }
+ }
+
+ public void installSfcEncapOutputRule(PortPair portPair, NshServicePathId nshSpiId, Objective.Operation type) {
+
+ DeviceId deviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
+ MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
+ Host host = hostService.getHost(HostId.hostId(srcMacAddress));
+ PortNumber port = host.location().port();
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
+
+ // Prepare selector with nsp, nsi and encap eth type
+ ExtensionSelector nshSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
+ ExtensionSelector nshSiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SI.type());
+ ExtensionSelector nshEncapEthTypeSelector = resolver.getExtensionSelector(NICIRA_MATCH_ENCAP_ETH_TYPE.type());
+
+ try {
+ nshSpiSelector.setPropertyValue("nshSpi", nshSpiId);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Spi Id for encap rule {}", e.getMessage());
+ }
+ try {
+ nshSiSelector.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Si Id for encap rule {}", e.getMessage());
+ }
+ try {
+ nshEncapEthTypeSelector.setPropertyValue("encapEthType", ENCAP_ETH_TYPE);
+ } catch (Exception e) {
+ log.error("Failed to set extension selector to match Nsh Si Id {}", deviceId);
+ }
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.extension(nshSpiSelector, deviceId);
+ selector.extension(nshSiSelector, deviceId);
+
+ ExtensionTreatmentResolver treatmentResolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment encapEthSrcTreatment = treatmentResolver
+ .getExtensionInstruction(NICIRA_ENCAP_ETH_SRC.type());
+ ExtensionTreatment encapEthDstTreatment = treatmentResolver
+ .getExtensionInstruction(NICIRA_ENCAP_ETH_DST.type());
+
+ try {
+ encapEthDstTreatment.setPropertyValue("encapEthDst", srcMacAddress);
+ } catch (Exception e) {
+ log.error("Failed to set extension treatment to set encap eth dst {}", deviceId);
+ }
+ // TODO: move from packet source mac address
+ try {
+ encapEthSrcTreatment.setPropertyValue("encapEthSrc", srcMacAddress);
+ } catch (Exception e) {
+ log.error("Failed to set extension treatment to set encap eth src {}", deviceId);
+ }
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.extension(encapEthSrcTreatment, deviceId);
+ treatment.extension(encapEthDstTreatment, deviceId);
+ treatment.setOutput(port);
+
+ sendSfcRule(selector, treatment, deviceId, type, ENCAP_OUTPUT_PRIORITY);
+ forwarderList.add(deviceId);
+ }
+
+ public ConnectPoint installSfcClassifierRules(PortChain portChain, PortPair portPair, NshServicePathId nshSpiId,
+ FiveTuple fiveTuple, Objective.Operation type) {
+
+ DeviceId deviceIdfromPortPair = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
+ MacAddress srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
+ VirtualPort virtualPort = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress()));
+ Host host = hostService.getHost(HostId.hostId(srcMacAddress));
+ PortNumber port = host.location().port();
+
+ DeviceId deviceId = deviceIdfromPortPair;
+
+ // get flow classifiers
+ List<FlowClassifierId> llFlowClassifierList = portChain.flowClassifiers();
+ ListIterator<FlowClassifierId> flowClassifierListIterator = llFlowClassifierList.listIterator();
+
+ while (flowClassifierListIterator.hasNext()) {
+ FlowClassifierId flowclassifierId = flowClassifierListIterator.next();
+ FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowclassifierId);
+
+ if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
+ deviceId = vtnRscService.getSfToSffMaping(flowClassifier.srcPort());
+ }
+
+ // Build Traffic selector.
+ TrafficSelector.Builder selector = packClassifierSelector(flowClassifier, fiveTuple);
+
+ if (fiveTuple == null) {
+ // Send the packet to controller
+ log.info("Downloading rule to send packet to controller");
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.setOutput(PortNumber.CONTROLLER);
+ sendSfcRule(selector, treatment, deviceId, type, FLOW_CLASSIFIER_PRIORITY);
+ continue;
+ }
+
+ if (deviceId != null && !deviceId.equals(deviceIdfromPortPair)) {
+ // First SF is in another device. Set tunnel ipv4 destination to
+ // treatment
+ Device remoteDevice = deviceService.getDevice(deviceIdfromPortPair);
+ String url = remoteDevice.annotations().value(SWITCH_CHANNEL_ID);
+ String remoteControllerIp = url.substring(0, url.lastIndexOf(":"));
+ if (remoteControllerIp == null) {
+ log.error("Can't find remote controller of device: {}", deviceIdfromPortPair.toString());
+ return null;
+ }
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment tunnelDsttreatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ try {
+ tunnelDsttreatment.setPropertyValue("tunnelDst", Ip4Address.valueOf(remoteControllerIp));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
+ }
+
+ TrafficTreatment.Builder treatment = packClassifierTreatment(deviceId, virtualPort, port,
+ nshSpiId, flowClassifier);
+ treatment.extension(tunnelDsttreatment, deviceId);
+ treatment.transition(TUNNEL_SEND_TABLE);
+ sendSfcRule(selector, treatment, deviceId, type, flowClassifier.priority());
+ classifierList.add(deviceIdfromPortPair);
+
+ installSfcTunnelSendRule(deviceId, nshSpiId, type);
+ installSfcTunnelReceiveRule(deviceIdfromPortPair, nshSpiId, type);
+
+ } else {
+ // classifier and port pair are in the same OVS. So directly
+ // send packet to first port pair
+ TrafficTreatment.Builder treatment = packClassifierTreatment(deviceIdfromPortPair, virtualPort, port,
+ nshSpiId, flowClassifier);
+ treatment.transition(ENCAP_OUTPUT_TABLE);
+ sendSfcRule(selector, treatment, deviceIdfromPortPair, type, flowClassifier.priority());
+ classifierList.add(deviceIdfromPortPair);
+ }
+ }
+
+ return host.location();
+ }
+
+ /**
+ * Pack Traffic selector.
+ *
+ * @param flowClassifier flow-classifier
+ * @param fiveTuple five tuple info for the packet
+ * @return traffic selector
+ */
+ public TrafficSelector.Builder packClassifierSelector(FlowClassifier flowClassifier, FiveTuple fiveTuple) {
+
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+
+ if ((flowClassifier.srcIpPrefix() != null) && (flowClassifier.srcIpPrefix().prefixLength() != 0)) {
+ selector.matchIPSrc(flowClassifier.srcIpPrefix());
+ } else if (fiveTuple != null && fiveTuple.ipSrc() != null) {
+ selector.matchIPSrc(IpPrefix.valueOf(fiveTuple.ipSrc(), 24));
+ }
+
+ if ((flowClassifier.dstIpPrefix() != null) && (flowClassifier.dstIpPrefix().prefixLength() != 0)) {
+ selector.matchIPDst(flowClassifier.dstIpPrefix());
+ } else if (fiveTuple != null && fiveTuple.ipDst() != null) {
+ selector.matchIPDst(IpPrefix.valueOf(fiveTuple.ipDst(), 24));
+ }
+
+ if ((flowClassifier.protocol() != null) && (!flowClassifier.protocol().isEmpty())) {
+ if (flowClassifier.protocol().equalsIgnoreCase("TCP")) {
+ selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_TCP));
+ } else if (flowClassifier.protocol().equalsIgnoreCase("UDP")) {
+ selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP));
+ } else if (flowClassifier.protocol().equalsIgnoreCase("ICMP")) {
+ selector.add(Criteria.matchIPProtocol(IPv4.PROTOCOL_ICMP));
+ }
+ } else if (fiveTuple != null && fiveTuple.protocol() != 0) {
+ selector.add(Criteria.matchIPProtocol(fiveTuple.protocol()));
+ }
+
+ if (((flowClassifier.etherType() != null) && (!flowClassifier.etherType().isEmpty()))
+ && (flowClassifier.etherType().equals("IPv4") || flowClassifier.etherType().equals("IPv6"))) {
+ if (flowClassifier.etherType().equals("IPv4")) {
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ } else {
+ selector.matchEthType(Ethernet.TYPE_IPV6);
+ }
+ }
+
+ if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
+ VirtualPortId vPortId = VirtualPortId.portId(flowClassifier.srcPort().portId());
+ MacAddress macAddress = virtualPortService.getPort(vPortId).macAddress();
+ Host host = hostService.getHost(HostId.hostId(macAddress));
+ selector.matchInPort(host.location().port());
+ }
+
+ // Take the port information from five tuple only when the protocol is
+ // TCP.
+ if (fiveTuple != null && fiveTuple.protocol() == IPv4.PROTOCOL_TCP) {
+ selector.matchTcpSrc(TpPort.tpPort((int) fiveTuple.portSrc().toLong()));
+ selector.matchTcpDst(TpPort.tpPort((int) fiveTuple.portDst().toLong()));
+ } else {
+ // For udp packets take the port information from flow classifier
+ List<TpPort> srcPortRange = new LinkedList<>();
+ List<TpPort> dstPortRange = new LinkedList<>();
+ if ((flowClassifier.minSrcPortRange() != 0) && flowClassifier.maxSrcPortRange() != 0
+ && flowClassifier.minDstPortRange() != 0 && flowClassifier.maxDstPortRange() != 0) {
+
+ for (int port = flowClassifier.minSrcPortRange(); port <= flowClassifier.maxSrcPortRange(); port++) {
+ srcPortRange.add(TpPort.tpPort(port));
+ }
+ for (int port = flowClassifier.minDstPortRange(); port <= flowClassifier.maxDstPortRange(); port++) {
+ dstPortRange.add(TpPort.tpPort(port));
+ }
+ }
+
+ for (TpPort inPort : srcPortRange) {
+ selector.matchUdpSrc(inPort);
+ }
+ for (TpPort outPort : dstPortRange) {
+ selector.matchUdpDst(outPort);
+ }
+ }
+ return selector;
+ }
+
+ /**
+ * Pack traffic treatment.
+ *
+ * @param deviceId device id
+ * @param virtualPort virtual port
+ * @param port port number
+ * @param nshSpi nsh spi
+ * @param flowClassifier flow-classifier
+ * @return traffic treatment
+ */
+ public TrafficTreatment.Builder packClassifierTreatment(DeviceId deviceId, VirtualPort virtualPort,
+ PortNumber port, NshServicePathId nshSpi, FlowClassifier flowClassifier) {
+
+ TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+
+ // set tunnel id
+ SegmentationId segmentationId = tenantNetworkService.getNetwork(virtualPort.networkId()).segmentationId();
+ treatmentBuilder.add(Instructions.modTunnelId(Long.parseLong(segmentationId.toString())));
+
+ // Set all NSH header fields
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment nspIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SPI.type());
+ ExtensionTreatment nsiIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SI.type());
+ ExtensionTreatment pushNshTreatment = resolver.getExtensionInstruction(NICIRA_PUSH_NSH.type());
+
+ ExtensionTreatment nshCh1Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH1.type());
+ ExtensionTreatment nshCh2Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH2.type());
+ ExtensionTreatment nshCh3Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH3.type());
+ ExtensionTreatment nshCh4Treatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_CH4.type());
+ ExtensionTreatment nshMdTypeTreatment = resolver.getExtensionInstruction(NICIRA_NSH_MDTYPE.type());
+ ExtensionTreatment nshNpTreatment = resolver.getExtensionInstruction(NICIRA_NSH_NP.type());
+
+ try {
+ nshMdTypeTreatment.setPropertyValue("nshMdType", ((byte) 1));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set nshMdType {}", deviceId);
+ }
+ try {
+ nshNpTreatment.setPropertyValue("nshNp", ((byte) 3));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set nshNp {}", deviceId);
+ }
+ try {
+ nspIdTreatment.setPropertyValue("nshSpi", nshSpi);
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
+ }
+ try {
+ nsiIdTreatment.setPropertyValue("nshSi", NshServiceIndex.of(nshSi));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set Nsh Si Id {}", deviceId);
+ }
+ try {
+ nshCh1Treatment.setPropertyValue("nshCh", NshContextHeader.of(1));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set NshCh1 {}", deviceId);
+ }
+ try {
+ nshCh2Treatment.setPropertyValue("nshCh", NshContextHeader.of(Integer.parseInt(segmentationId.toString())));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set NshCh2 {}", deviceId);
+ }
+ try {
+ nshCh3Treatment.setPropertyValue("nshCh", NshContextHeader.of(3));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set NshCh3 {}", deviceId);
+ }
+ try {
+ nshCh4Treatment.setPropertyValue("nshCh", NshContextHeader.of(4));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set NshCh4 {}", deviceId);
+ }
+ treatmentBuilder.extension(pushNshTreatment, deviceId);
+ treatmentBuilder.extension(nshMdTypeTreatment, deviceId);
+ treatmentBuilder.extension(nshNpTreatment, deviceId);
+ treatmentBuilder.extension(nspIdTreatment, deviceId);
+ treatmentBuilder.extension(nsiIdTreatment, deviceId);
+ treatmentBuilder.extension(nshCh1Treatment, deviceId);
+ treatmentBuilder.extension(nshCh2Treatment, deviceId);
+ treatmentBuilder.extension(nshCh3Treatment, deviceId);
+ treatmentBuilder.extension(nshCh4Treatment, deviceId);
+
+ return treatmentBuilder;
+ }
+
+ /**
+ * Get the ControllerId from the device .
+ *
+ * @param device Device
+ * @param devices Devices
+ * @return Controller Id
+ */
+ public DeviceId getControllerId(Device device, Iterable<Device> devices) {
+ for (Device d : devices) {
+ if (d.type() == Device.Type.CONTROLLER && d.id().toString()
+ .contains(getControllerIpOfSwitch(device))) {
+ return d.id();
+ }
+ }
+ log.info("Can not find controller for device : {}", device.id());
+ return null;
+ }
+
+ /**
+ * Get the ControllerIp from the device .
+ *
+ * @param device Device
+ * @return Controller Ip
+ */
+ public String getControllerIpOfSwitch(Device device) {
+ String url = device.annotations().value(SWITCH_CHANNEL_ID);
+ return url.substring(0, url.lastIndexOf(":"));
+ }
+
+ /**
+ * Send service-function-forwarder to OVS.
+ *
+ * @param selector traffic selector
+ * @param treatment traffic treatment
+ * @param deviceId device id
+ * @param type operation type
+ * @param priority priority of classifier
+ */
+ public void sendSfcRule(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment, DeviceId deviceId,
+ Objective.Operation type, int priority) {
+
+ log.info("Sending sfc flow rule. Selector {}, Treatment {}", selector.toString(),
+ treatment.toString());
+ ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
+ .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE)
+ .withPriority(priority);
+
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("flowClassifierRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("flowClassifierRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+ private PortNumber getVxlanPortNumber(DeviceId deviceId) {
+ Iterable<Port> ports = deviceService.getPorts(deviceId);
+ Port vxlanPort = Sets.newHashSet(ports).stream()
+ .filter(p ->!p.number().equals(PortNumber.LOCAL))
+ .filter(p ->p.annotations().value(AnnotationKeys.PORT_NAME)
+ .startsWith(VXLANPORT_HEAD))
+ .findFirst().get();
+ return vxlanPort.number();
+ }
+}
diff --git a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java
index 0d7702c..3292e23 100644
--- a/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java
+++ b/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java
@@ -20,8 +20,9 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import java.util.Optional;
+import java.util.ListIterator;
import java.util.Set;
+import java.util.UUID;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -50,10 +51,7 @@
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
-import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService;
-import org.onosproject.sfc.forwarder.impl.ServiceFunctionForwarderImpl;
-import org.onosproject.sfc.installer.FlowClassifierInstallerService;
-import org.onosproject.sfc.installer.impl.FlowClassifierInstallerImpl;
+import org.onosproject.sfc.installer.impl.SfcFlowRuleInstallerImpl;
import org.onosproject.sfc.manager.SfcService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.DistributedSet;
@@ -77,7 +75,6 @@
import org.onosproject.vtnrsc.VirtualPort;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.event.VtnRscEvent;
-import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
import org.onosproject.vtnrsc.event.VtnRscListener;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
import org.onosproject.vtnrsc.portchain.PortChainService;
@@ -100,7 +97,6 @@
private String nshSpiIdTopic = "nsh-spi-id";
private static final String APP_ID = "org.onosproject.app.vtn";
private static final int SFC_PRIORITY = 1000;
- private static final int NULL_PORT = 0;
private static final int MAX_NSH_SPI_ID = 0x7FFFF;
private static final int MAX_LOAD_BALANCE_ID = 0x20;
@@ -131,10 +127,9 @@
protected SfcPacketProcessor processor = new SfcPacketProcessor();
protected ApplicationId appId;
- protected ServiceFunctionForwarderService serviceFunctionForwarder;
- protected FlowClassifierInstallerService flowClassifierInstaller;
protected IdGenerator nshSpiIdGenerator;
protected EventuallyConsistentMap<PortChainId, Integer> nshSpiPortChainMap;
+ protected EventuallyConsistentMap<PortChainId, List<FiveTuple>> portChainFiveTupleMap;
protected DistributedSet<Integer> nshSpiIdFreeList;
private final VtnRscListener vtnRscListener = new InnerVtnRscListener();
@@ -142,24 +137,22 @@
@Activate
public void activate() {
appId = coreService.registerApplication(APP_ID);
- serviceFunctionForwarder = new ServiceFunctionForwarderImpl(appId);
- flowClassifierInstaller = new FlowClassifierInstallerImpl(appId);
nshSpiIdGenerator = coreService.getIdGenerator(nshSpiIdTopic);
vtnRscService.addListener(vtnRscListener);
- KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
- .register(TenantId.class)
- .register(PortPairId.class)
- .register(PortPairGroupId.class)
- .register(FlowClassifierId.class)
- .register(PortChainId.class);
+ KryoNamespace.Builder serializer = KryoNamespace
+ .newBuilder()
+ .register(PortChainId.class, UUID.class, FiveTuple.class, IpAddress.class, PortNumber.class,
+ DefaultFiveTuple.class, IpAddress.Version.class, TenantId.class);
nshSpiPortChainMap = storageService.<PortChainId, Integer>eventuallyConsistentMapBuilder()
- .withName("nshSpiPortChainMap")
- .withSerializer(serializer)
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
+ .withName("nshSpiPortChainMap").withSerializer(serializer)
+ .withTimestampProvider((k, v) ->new WallClockTimestamp()).build();
+
+ portChainFiveTupleMap = storageService.<PortChainId, List<FiveTuple>>eventuallyConsistentMapBuilder()
+ .withName("portChainFiveTupleMap").withSerializer(serializer)
+ .withTimestampProvider((k, v) ->new WallClockTimestamp()).build();
nshSpiIdFreeList = storageService.<Integer>setBuilder()
.withName("nshSpiIdDeletedList")
@@ -186,43 +179,47 @@
public void event(VtnRscEvent event) {
if (VtnRscEvent.Type.PORT_PAIR_PUT == event.type()) {
- PortPair portPair = ((VtnRscEventFeedback) event.subject()).portPair();
+ PortPair portPair = event.subject().portPair();
onPortPairCreated(portPair);
} else if (VtnRscEvent.Type.PORT_PAIR_DELETE == event.type()) {
- PortPair portPair = ((VtnRscEventFeedback) event.subject()).portPair();
+ PortPair portPair = event.subject().portPair();
onPortPairDeleted(portPair);
} else if (VtnRscEvent.Type.PORT_PAIR_UPDATE == event.type()) {
- PortPair portPair = ((VtnRscEventFeedback) event.subject()).portPair();
+ PortPair portPair = event.subject().portPair();
onPortPairDeleted(portPair);
onPortPairCreated(portPair);
} else if (VtnRscEvent.Type.PORT_PAIR_GROUP_PUT == event.type()) {
- PortPairGroup portPairGroup = ((VtnRscEventFeedback) event.subject()).portPairGroup();
+ PortPairGroup portPairGroup = event.subject().portPairGroup();
onPortPairGroupCreated(portPairGroup);
} else if (VtnRscEvent.Type.PORT_PAIR_GROUP_DELETE == event.type()) {
- PortPairGroup portPairGroup = ((VtnRscEventFeedback) event.subject()).portPairGroup();
+ PortPairGroup portPairGroup = event.subject().portPairGroup();
onPortPairGroupDeleted(portPairGroup);
} else if (VtnRscEvent.Type.PORT_PAIR_GROUP_UPDATE == event.type()) {
- PortPairGroup portPairGroup = ((VtnRscEventFeedback) event.subject()).portPairGroup();
+ PortPairGroup portPairGroup = event.subject().portPairGroup();
onPortPairGroupDeleted(portPairGroup);
onPortPairGroupCreated(portPairGroup);
} else if (VtnRscEvent.Type.FLOW_CLASSIFIER_PUT == event.type()) {
- FlowClassifier flowClassifier = ((VtnRscEventFeedback) event.subject()).flowClassifier();
+ FlowClassifier flowClassifier = event.subject().flowClassifier();
onFlowClassifierCreated(flowClassifier);
} else if (VtnRscEvent.Type.FLOW_CLASSIFIER_DELETE == event.type()) {
- FlowClassifier flowClassifier = ((VtnRscEventFeedback) event.subject()).flowClassifier();
+ FlowClassifier flowClassifier = event.subject().flowClassifier();
onFlowClassifierDeleted(flowClassifier);
} else if (VtnRscEvent.Type.FLOW_CLASSIFIER_UPDATE == event.type()) {
- FlowClassifier flowClassifier = ((VtnRscEventFeedback) event.subject()).flowClassifier();
+ FlowClassifier flowClassifier = event.subject().flowClassifier();
onFlowClassifierDeleted(flowClassifier);
onFlowClassifierCreated(flowClassifier);
} else if (VtnRscEvent.Type.PORT_CHAIN_PUT == event.type()) {
- PortChain portChain = (PortChain) ((VtnRscEventFeedback) event.subject()).portChain();
+ PortChain portChain = event.subject().portChain();
+ if (portChain.oldPortChain() != null) {
+ onPortChainDeleted(portChain.oldPortChain());
+ }
onPortChainCreated(portChain);
} else if (VtnRscEvent.Type.PORT_CHAIN_DELETE == event.type()) {
- PortChain portChain = (PortChain) ((VtnRscEventFeedback) event.subject()).portChain();
+ PortChain portChain = event.subject().portChain();
onPortChainDeleted(portChain);
+ portChainFiveTupleMap.remove(portChain.portChainId());
} else if (VtnRscEvent.Type.PORT_CHAIN_UPDATE == event.type()) {
- PortChain portChain = (PortChain) ((VtnRscEventFeedback) event.subject()).portChain();
+ PortChain portChain = event.subject().portChain();
onPortChainDeleted(portChain);
onPortChainCreated(portChain);
}
@@ -232,58 +229,69 @@
@Override
public void onPortPairCreated(PortPair portPair) {
log.debug("onPortPairCreated");
- // TODO: Modify forwarding rule on port-pair creation.
+ // Do nothing
}
@Override
public void onPortPairDeleted(PortPair portPair) {
log.debug("onPortPairDeleted");
- // TODO: Modify forwarding rule on port-pair deletion.
+ // Do nothing
}
@Override
public void onPortPairGroupCreated(PortPairGroup portPairGroup) {
log.debug("onPortPairGroupCreated");
- // TODO: Modify forwarding rule on port-pair-group creation.
+ // Do nothing
}
@Override
public void onPortPairGroupDeleted(PortPairGroup portPairGroup) {
log.debug("onPortPairGroupDeleted");
- // TODO: Modify forwarding rule on port-pair-group deletion.
+ // Do nothing
}
@Override
public void onFlowClassifierCreated(FlowClassifier flowClassifier) {
log.debug("onFlowClassifierCreated");
- // TODO: Modify forwarding rule on flow-classifier creation.
+ // Do nothing
}
@Override
public void onFlowClassifierDeleted(FlowClassifier flowClassifier) {
log.debug("onFlowClassifierDeleted");
- // TODO: Modify forwarding rule on flow-classifier deletion.
+ // Do nothing
}
@Override
public void onPortChainCreated(PortChain portChain) {
NshServicePathId nshSpi;
- log.info("onPortChainCreated");
- if (nshSpiPortChainMap.containsKey(portChain.portChainId())) {
- nshSpi = NshServicePathId.of(nshSpiPortChainMap.get(portChain.portChainId()));
- } else {
- int id = getNextNshSpi();
- if (id > MAX_NSH_SPI_ID) {
- log.error("Reached max limit of service path index."
- + "Failed to install SFC for port chain {}", portChain.portChainId().toString());
- return;
- }
- nshSpi = NshServicePathId.of(id);
- nshSpiPortChainMap.put(portChain.portChainId(), new Integer(id));
- }
+ log.info("On port chain created");
+ int spi = getNextNshSpi();
+ if (spi > MAX_NSH_SPI_ID) {
+ log.error("Reached max limit of service path index." + "Failed to install SFC for port chain {}",
+ portChain.portChainId().toString());
+ return;
+ }
+ nshSpi = NshServicePathId.of(spi);
+ nshSpiPortChainMap.put(portChain.portChainId(), new Integer(spi));
+ if (!portChainFiveTupleMap.containsKey(portChain.portChainId())) {
+ portChainFiveTupleMap.put(portChain.portChainId(), Lists.newArrayList());
+ }
// Install classifier rule to send the packet to controller
- flowClassifierInstaller.installFlowClassifier(portChain, nshSpi);
+ SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl(appId);
+ flowRuleInstaller.installFlowClassifier(portChain, nshSpi);
+
+ // Install rules for already identified five tuples.
+ List<FiveTuple> list = portChainFiveTupleMap.get(portChain.portChainId());
+ for (FiveTuple fiveTuple : list) {
+ LoadBalanceId id = loadBalanceSfc(portChain.portChainId(), fiveTuple);
+ // Get nsh service path index
+ nshSpi = NshServicePathId.of(getNshServicePathId(id, spi));
+ // download the required flow rules for classifier and
+ // forwarding
+ flowRuleInstaller.installLoadBalancedFlowRules(portChain, fiveTuple, nshSpi);
+ }
}
@Override
@@ -295,7 +303,8 @@
int nshSpiId = nshSpiPortChainMap.get(portChain.portChainId());
// Uninstall classifier rules
- flowClassifierInstaller.unInstallFlowClassifier(portChain, NshServicePathId.of(nshSpiId));
+ SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl(appId);
+ flowRuleInstaller.unInstallFlowClassifier(portChain, NshServicePathId.of(nshSpiId));
// remove from nshSpiPortChainMap and add to nshSpiIdFreeList
nshSpiPortChainMap.remove(portChain.portChainId());
nshSpiIdFreeList.add(nshSpiId);
@@ -314,9 +323,16 @@
processedIdList.add(id);
}
nshSpi = NshServicePathId.of(getNshServicePathId(id, nshSpiId));
- flowClassifierInstaller.unInstallLoadBalancedFlowClassifier(portChain, fiveTuple, nshSpi);
- serviceFunctionForwarder.unInstallLoadBalancedForwardingRule(portChain.getLoadBalancePath(fiveTuple),
- nshSpi);
+ flowRuleInstaller.unInstallLoadBalancedFlowRules(portChain, fiveTuple, nshSpi);
+ }
+
+ // Reset load for all the port pairs
+ List<PortPairGroupId> ppgIdlist = portChain.portPairGroups();
+ ListIterator<PortPairGroupId> ppgIdListIterator = ppgIdlist.listIterator();
+ while (ppgIdListIterator.hasNext()) {
+ PortPairGroupId portPairGroupId = ppgIdListIterator.next();
+ PortPairGroup ppg = portPairGroupService.getPortPairGroup(portPairGroupId);
+ ppg.resetLoad();
}
}
@@ -388,9 +404,12 @@
boolean match = false;
// Check whether protocol is set in flow classifier
if (flowClassifier.protocol() != null) {
- if ((flowClassifier.protocol().equals("TCP") && fiveTuple.protocol() == IPv4.PROTOCOL_TCP) ||
- (flowClassifier.protocol().equals("UDP") &&
- fiveTuple.protocol() == IPv4.PROTOCOL_UDP)) {
+ if ((flowClassifier.protocol().equalsIgnoreCase("TCP")
+ && fiveTuple.protocol() == IPv4.PROTOCOL_TCP)
+ || (flowClassifier.protocol().equalsIgnoreCase("UDP")
+ && fiveTuple.protocol() == IPv4.PROTOCOL_UDP)
+ || (flowClassifier.protocol().equalsIgnoreCase("ICMP")
+ && fiveTuple.protocol() == IPv4.PROTOCOL_ICMP)) {
match = true;
} else {
continue;
@@ -459,68 +478,6 @@
}
/**
- * Find the load balanced path set it to port chain for the given five tuple.
- *
- * @param portChainId port chain id
- * @param fiveTuple five tuple info
- * @return load balance id
- */
- private LoadBalanceId loadBalanceSfc(PortChainId portChainId, FiveTuple fiveTuple) {
-
- // Get the port chain
- PortChain portChain = portChainService.getPortChain(portChainId);
- List<PortPairId> loadBalancePath = Lists.newArrayList();
- LoadBalanceId id;
- int paths = portChain.getLoadBalancePathSize();
- if (paths >= MAX_LOAD_BALANCE_ID) {
- log.info("Max limit reached for load balance paths. "
- + "Reusing the created path for port chain {} with five tuple {}",
- portChainId, fiveTuple);
- id = LoadBalanceId.of((byte) ((paths + 1) % MAX_LOAD_BALANCE_ID));
- portChain.addLoadBalancePath(fiveTuple, id, portChain.getLoadBalancePath(id));
- }
-
- // Get the list of port pair groups from port chain
- Iterable<PortPairGroupId> portPairGroups = portChain.portPairGroups();
- for (final PortPairGroupId portPairGroupId : portPairGroups) {
- PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
-
- // Get the list of port pair ids from port pair group.
- Iterable<PortPairId> portPairs = portPairGroup.portPairs();
- int minLoad = 0xFFF;
- PortPairId minLoadPortPairId = null;
- for (final PortPairId portPairId : portPairs) {
- int load = portPairGroup.getLoad(portPairId);
- if (load == 0) {
- minLoadPortPairId = portPairId;
- break;
- } else {
- // Check the port pair which has min load.
- if (load < minLoad) {
- minLoad = load;
- minLoadPortPairId = portPairId;
- }
- }
- }
- if (minLoadPortPairId != null) {
- loadBalancePath.add(minLoadPortPairId);
- portPairGroup.addLoad(minLoadPortPairId);
- }
- }
-
- // Check if the path already exists, if not create a new id
- Optional<LoadBalanceId> output = portChain.matchPath(loadBalancePath);
- if (output.isPresent()) {
- id = output.get();
- } else {
- id = LoadBalanceId.of((byte) (paths + 1));
- }
-
- portChain.addLoadBalancePath(fiveTuple, id, loadBalancePath);
- return id;
- }
-
- /**
* Get the tenant id for the given mac address.
*
* @param mac mac address
@@ -561,7 +518,7 @@
TCP tcpPacket = (TCP) ipv4Packet.getPayload();
portSrc = tcpPacket.getSourcePort();
portDst = tcpPacket.getDestinationPort();
- } else if (protocol == IPv4.PROTOCOL_UDP) {
+ } else if (protocol == IPv4.PROTOCOL_UDP) {
UDP udpPacket = (UDP) ipv4Packet.getPayload();
portSrc = udpPacket.getSourcePort();
portDst = udpPacket.getDestinationPort();
@@ -571,7 +528,7 @@
// No need to process other packets received by controller.
return;
}
- } else if (ethType == Ethernet.TYPE_IPV6) {
+ } else {
return;
}
@@ -587,11 +544,11 @@
PortChainId portChainId = findPortChainFromFiveTuple(fiveTuple);
if (portChainId == null) {
- log.error("Packet does not match with any classifier");
return;
}
// Once the 5 tuple and port chain are identified, give this input for load balancing
+ addToPortChainIdFiveTupleMap(portChainId, fiveTuple);
LoadBalanceId id = loadBalanceSfc(portChainId, fiveTuple);
// Get nsh service path index
NshServicePathId nshSpi;
@@ -611,11 +568,9 @@
}
// download the required flow rules for classifier and forwarding
// install in OVS.
- ConnectPoint connectPoint = flowClassifierInstaller.installLoadBalancedFlowClassifier(portChain,
- fiveTuple, nshSpi);
- serviceFunctionForwarder.installLoadBalancedForwardingRule(portChain.getLoadBalancePath(fiveTuple),
- nshSpi);
- sendPacket(context, connectPoint);
+ SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl(appId);
+ flowRuleInstaller.installLoadBalancedFlowRules(portChain, fiveTuple, nshSpi);
+ sendPacket(context);
}
/**
@@ -624,11 +579,13 @@
* @param context packet context
* @param connectPoint connect point of first service function
*/
- private void sendPacket(PacketContext context, ConnectPoint connectPoint) {
+ private void sendPacket(PacketContext context) {
- TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
- OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
- context.inPacket().unparsed());
+ ConnectPoint sourcePoint = context.inPacket().receivedFrom();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(sourcePoint.port()).build();
+ OutboundPacket packet = new DefaultOutboundPacket(sourcePoint.deviceId(), treatment, context.inPacket()
+ .unparsed());
packetService.emit(packet);
log.trace("Sending packet: {}", packet);
}
@@ -646,4 +603,71 @@
nshSpiNew = nshSpiNew | id.loadBalanceId();
return nshSpiNew;
}
+
+ private void addToPortChainIdFiveTupleMap(PortChainId portChainId, FiveTuple fiveTuple) {
+ List<FiveTuple> list = portChainFiveTupleMap.get(portChainId);
+ list.add(fiveTuple);
+ portChainFiveTupleMap.put(portChainId, list);
+ }
+
+ /**
+ * Find the load balanced path set it to port chain for the given five
+ * tuple.
+ *
+ * @param portChainId port chain id
+ * @param fiveTuple five tuple info
+ * @return load balance id
+ */
+ private LoadBalanceId loadBalanceSfc(PortChainId portChainId, FiveTuple fiveTuple) {
+
+ // Get the port chain
+ PortChain portChain = portChainService.getPortChain(portChainId);
+ List<PortPairId> loadBalancePath = Lists.newArrayList();
+ LoadBalanceId id;
+ int paths = portChain.getLoadBalancePathSize();
+ if (paths >= MAX_LOAD_BALANCE_ID) {
+ log.info("Max limit reached for load balance paths. "
+ + "Reusing the created path for port chain {} with five tuple {}", portChainId, fiveTuple);
+ id = LoadBalanceId.of((byte) ((paths + 1) % MAX_LOAD_BALANCE_ID));
+ portChain.addLoadBalancePath(fiveTuple, id, portChain.getLoadBalancePath(id));
+ }
+
+ // Get the list of port pair groups from port chain
+ Iterable<PortPairGroupId> portPairGroups = portChain.portPairGroups();
+ for (final PortPairGroupId portPairGroupId : portPairGroups) {
+ PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
+
+ // Get the list of port pair ids from port pair group.
+ Iterable<PortPairId> portPairs = portPairGroup.portPairs();
+ int minLoad = 0xFFF;
+ PortPairId minLoadPortPairId = null;
+ for (final PortPairId portPairId : portPairs) {
+ int load = portPairGroup.getLoad(portPairId);
+ if (load == 0) {
+ minLoadPortPairId = portPairId;
+ break;
+ } else {
+ // Check the port pair which has min load.
+ if (load < minLoad) {
+ minLoad = load;
+ minLoadPortPairId = portPairId;
+ }
+ }
+ }
+ if (minLoadPortPairId != null) {
+ loadBalancePath.add(minLoadPortPairId);
+ portPairGroup.addLoad(minLoadPortPairId);
+ }
+ }
+
+ // Check if the path already exists, if not create a new id
+ id = portChain.matchPath(loadBalancePath);
+ if (id == null) {
+ id = LoadBalanceId.of((byte) (paths + 1));
+ }
+
+ portChain.addLoadBalancePath(fiveTuple, id, loadBalancePath);
+ return id;
+ }
+
}
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImplTest.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImplTest.java
deleted file mode 100644
index 06b3585..0000000
--- a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImplTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2016-present 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.sfc.forwarder.impl;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.NshServicePathId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.device.DeviceServiceAdapter;
-import org.onosproject.net.driver.DriverHandler;
-import org.onosproject.net.driver.DriverService;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.HostServiceAdapter;
-import org.onosproject.sfc.util.FlowClassifierAdapter;
-import org.onosproject.sfc.util.FlowObjectiveAdapter;
-import org.onosproject.sfc.util.MockDriverHandler;
-import org.onosproject.sfc.util.PortPairAdapter;
-import org.onosproject.sfc.util.PortPairGroupAdapter;
-import org.onosproject.sfc.util.VirtualPortAdapter;
-import org.onosproject.sfc.util.VtnRscAdapter;
-import org.onosproject.vtnrsc.AllowedAddressPair;
-import org.onosproject.vtnrsc.BindingHostId;
-import org.onosproject.vtnrsc.DefaultPortPair;
-import org.onosproject.vtnrsc.DefaultVirtualPort;
-import org.onosproject.vtnrsc.FixedIp;
-import org.onosproject.vtnrsc.PortPair;
-import org.onosproject.vtnrsc.PortPairId;
-import org.onosproject.vtnrsc.SecurityGroup;
-import org.onosproject.vtnrsc.SubnetId;
-import org.onosproject.vtnrsc.TenantId;
-import org.onosproject.vtnrsc.TenantNetworkId;
-import org.onosproject.vtnrsc.VirtualPort;
-import org.onosproject.vtnrsc.VirtualPortId;
-import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
-import org.onosproject.vtnrsc.portpair.PortPairService;
-import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
-import org.onosproject.vtnrsc.service.VtnRscService;
-import org.onosproject.vtnrsc.virtualport.VirtualPortService;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class ServiceFunctionForwarderImplTest {
-
- FlowObjectiveService flowObjectiveService = new FlowObjectiveAdapter();
- DeviceService deviceService = new DeviceServiceAdapter();
- HostService hostService = new HostServiceAdapter();
- VirtualPortService virtualPortService = new VirtualPortAdapter();
- VtnRscService vtnRscService = new VtnRscAdapter();
- PortPairService portPairService = new PortPairAdapter();
- PortPairGroupService portPairGroupService = new PortPairGroupAdapter();
- FlowClassifierService flowClassifierService = new FlowClassifierAdapter();
-
- final DriverService driverService = createMock(DriverService.class);
-
- DeviceId deviceId = DeviceId.deviceId("of:000000000000001");
- final TenantId tenantId = TenantId.tenantId("1");
-
- final DriverHandler driverHandler = new MockDriverHandler();
-
- private VirtualPort createVirtualPort(VirtualPortId id) {
- Set<FixedIp> fixedIps;
- Map<String, String> propertyMap;
- Set<AllowedAddressPair> allowedAddressPairs;
- Set<SecurityGroup> securityGroups = Sets.newHashSet();
-
- String macAddressStr = "fa:12:3e:56:ee:a2";
- String ipAddress = "10.1.1.1";
- String tenantNetworkId = "1234567";
- String subnet = "1212";
- String hostIdStr = "fa:e2:3e:56:ee:a2";
- String deviceOwner = "james";
- propertyMap = Maps.newHashMap();
- propertyMap.putIfAbsent("deviceOwner", deviceOwner);
-
- TenantNetworkId networkId = TenantNetworkId.networkId(tenantNetworkId);
- MacAddress macAddress = MacAddress.valueOf(macAddressStr);
- BindingHostId bindingHostId = BindingHostId.bindingHostId(hostIdStr);
- FixedIp fixedIp = FixedIp.fixedIp(SubnetId.subnetId(subnet),
- IpAddress.valueOf(ipAddress));
- fixedIps = Sets.newHashSet();
- fixedIps.add(fixedIp);
-
- allowedAddressPairs = Sets.newHashSet();
- AllowedAddressPair allowedAddressPair = AllowedAddressPair
- .allowedAddressPair(IpAddress.valueOf(ipAddress),
- MacAddress.valueOf(macAddressStr));
- allowedAddressPairs.add(allowedAddressPair);
-
- VirtualPort d1 = new DefaultVirtualPort(id, networkId, true,
- propertyMap,
- VirtualPort.State.ACTIVE,
- macAddress, tenantId, deviceId,
- fixedIps, bindingHostId,
- allowedAddressPairs,
- securityGroups);
- return d1;
- }
-
- @Test
- public void testInstallFlowClassifier() {
-
- PortPairId portPairId1 = PortPairId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
- PortPairId portPairId2 = PortPairId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
-
- final String ppName1 = "PortPair1";
- final String ppDescription1 = "PortPair1";
- final String ingress1 = "d3333333-24fc-4fae-af4b-321c5e2eb3d1";
- final String egress1 = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345";
- DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder();
- PortPair portPair1 = portPairBuilder.setId(portPairId1).setName(ppName1).setTenantId(tenantId)
- .setDescription(ppDescription1).setIngress(ingress1).setEgress(egress1).build();
-
- final String ppName2 = "PortPair2";
- final String ppDescription2 = "PortPair2";
- final String ingress2 = "d5555555-24fc-4fae-af4b-321c5e2eb3d1";
- final String egress2 = "a6666666-4a56-2a6e-cd3a-9dee4e2ec345";
- PortPair portPair2 = portPairBuilder.setId(portPairId2).setName(ppName2).setTenantId(tenantId)
- .setDescription(ppDescription2).setIngress(ingress2).setEgress(egress2).build();
-
- ApplicationId appId = new DefaultApplicationId(1, "test");
- ServiceFunctionForwarderImpl serviceFunctionForwarder = new ServiceFunctionForwarderImpl();
- serviceFunctionForwarder.virtualPortService = virtualPortService;
- serviceFunctionForwarder.vtnRscService = vtnRscService;
- serviceFunctionForwarder.portPairService = portPairService;
- serviceFunctionForwarder.portPairGroupService = portPairGroupService;
- serviceFunctionForwarder.flowClassifierService = flowClassifierService;
- serviceFunctionForwarder.driverService = driverService;
- serviceFunctionForwarder.hostService = hostService;
- serviceFunctionForwarder.flowObjectiveService = flowObjectiveService;
- serviceFunctionForwarder.appId = appId;
-
- NshServicePathId nshSpiId = NshServicePathId.of(10);
-
- portPairService.createPortPair(portPair1);
- portPairService.createPortPair(portPair2);
-
- List<PortPairId> path = Lists.newArrayList();
- path.add(portPairId1);
- path.add(portPairId2);
-
- List<VirtualPort> virtualPortList = Lists.newArrayList();
- virtualPortList.add(createVirtualPort(VirtualPortId.portId(egress1)));
- virtualPortList.add(createVirtualPort(VirtualPortId.portId(ingress2)));
- virtualPortService.createPorts(virtualPortList);
-
- expect(driverService.createHandler(deviceId)).andReturn(driverHandler).anyTimes();
- replay(driverService);
-
- serviceFunctionForwarder.installLoadBalancedForwardingRule(path, nshSpiId);
-
- ForwardingObjective forObj = ((FlowObjectiveAdapter) flowObjectiveService).forwardingObjective();
-
- // Check for Selector
- assertThat(forObj.selector().getCriterion(Criterion.Type.IN_PORT), instanceOf(PortCriterion.class));
-
- // Check for treatment
- List<Instruction> instructions = forObj.treatment().allInstructions();
- for (Instruction instruction : instructions) {
- if (instruction.type() == Instruction.Type.OUTPUT) {
- assertThat(((OutputInstruction) instruction).port(), is(PortNumber.P0));
- }
- }
- }
-}
\ No newline at end of file
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/installer/impl/FlowClassifierInstallerImplTest.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/installer/impl/SfcFlowRuleInstallerImplTest.java
similarity index 61%
rename from apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/installer/impl/FlowClassifierInstallerImplTest.java
rename to apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/installer/impl/SfcFlowRuleInstallerImplTest.java
index a51ea21..61ad4e8 100644
--- a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/installer/impl/FlowClassifierInstallerImplTest.java
+++ b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/installer/impl/SfcFlowRuleInstallerImplTest.java
@@ -18,48 +18,74 @@
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
+import static org.onosproject.net.Device.Type.SWITCH;
+import static org.onosproject.net.Port.Type.COPPER;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
+import org.onlab.packet.ChassisId;
+import org.onlab.packet.IPv4;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultPort;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.NshServicePathId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.HostServiceAdapter;
+import org.onosproject.net.provider.ProviderId;
import org.onosproject.sfc.util.FlowClassifierAdapter;
import org.onosproject.sfc.util.FlowObjectiveAdapter;
import org.onosproject.sfc.util.MockDriverHandler;
import org.onosproject.sfc.util.PortPairAdapter;
import org.onosproject.sfc.util.PortPairGroupAdapter;
+import org.onosproject.sfc.util.TenantNetworkAdapter;
import org.onosproject.sfc.util.VirtualPortAdapter;
import org.onosproject.sfc.util.VtnRscAdapter;
import org.onosproject.vtnrsc.AllowedAddressPair;
import org.onosproject.vtnrsc.BindingHostId;
+import org.onosproject.vtnrsc.DefaultFiveTuple;
import org.onosproject.vtnrsc.DefaultFlowClassifier;
import org.onosproject.vtnrsc.DefaultPortChain;
import org.onosproject.vtnrsc.DefaultPortPair;
import org.onosproject.vtnrsc.DefaultPortPairGroup;
+import org.onosproject.vtnrsc.DefaultTenantNetwork;
import org.onosproject.vtnrsc.DefaultVirtualPort;
+import org.onosproject.vtnrsc.FiveTuple;
import org.onosproject.vtnrsc.FixedIp;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.LoadBalanceId;
+import org.onosproject.vtnrsc.PhysicalNetwork;
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortChainId;
import org.onosproject.vtnrsc.PortPair;
@@ -67,8 +93,10 @@
import org.onosproject.vtnrsc.PortPairGroupId;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.SecurityGroup;
+import org.onosproject.vtnrsc.SegmentationId;
import org.onosproject.vtnrsc.SubnetId;
import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetwork;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.VirtualPort;
import org.onosproject.vtnrsc.VirtualPortId;
@@ -76,25 +104,30 @@
import org.onosproject.vtnrsc.portpair.PortPairService;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
import org.onosproject.vtnrsc.service.VtnRscService;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-public class FlowClassifierInstallerImplTest {
+public class SfcFlowRuleInstallerImplTest {
FlowObjectiveService flowObjectiveService = new FlowObjectiveAdapter();
- DeviceService deviceService = new DeviceServiceAdapter();
+ DeviceService deviceService = new DeviceServiceAdapter(createPortList());
+
HostService hostService = new HostServiceAdapter();
VirtualPortService virtualPortService = new VirtualPortAdapter();
VtnRscService vtnRscService = new VtnRscAdapter();
PortPairService portPairService = new PortPairAdapter();
PortPairGroupService portPairGroupService = new PortPairGroupAdapter();
FlowClassifierService flowClassifierService = new FlowClassifierAdapter();
+ TenantNetworkService tenantNetworkService = new TenantNetworkAdapter();
final DriverService driverService = createMock(DriverService.class);
+ private final String networkIdStr = "123";
+
final PortChainId portChainId = PortChainId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
final TenantId tenantId = TenantId.tenantId("1");
final String name = "PortChain";
@@ -115,7 +148,6 @@
final String ingress = "d3333333-24fc-4fae-af4b-321c5e2eb3d1";
final String egress = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345";
-
final String ppgName = "PortPairGroup";
final String ppgDescription = "PortPairGroup";
final List<PortPairId> portPairList = new LinkedList<PortPairId>();
@@ -127,7 +159,21 @@
final DriverHandler driverHandler = new MockDriverHandler();
- private PortPair createPortPair(PortPairId ppId) {
+ private List<Port> createPortList() {
+ List<Port> portList = Lists.newArrayList();
+ long sp1 = 1_000_000;
+ ProviderId pid = new ProviderId("of", "foo");
+ ChassisId cid = new ChassisId();
+ Device device = new DefaultDevice(pid, deviceId, SWITCH, "whitebox", "1.1.x", "3.9.1", "43311-12345", cid);
+ Annotations annotations = DefaultAnnotations
+ .builder()
+ .set(AnnotationKeys.PORT_NAME, "vxlan-0.0.0.0").build();
+ Port p1 = new DefaultPort(device, PortNumber.ANY, true, COPPER, sp1, annotations);
+ portList.add(p1);
+ return portList;
+ }
+
+ private PortPair createPortPair(PortPairId ppId) {
DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder();
PortPair portPair = portPairBuilder.setId(ppId).setName(ppName).setTenantId(tenantId)
.setDescription(ppDescription).setIngress(ingress).setEgress(egress).build();
@@ -193,7 +239,7 @@
return flowClassifier;
}
- private VirtualPort createVirtualPort() {
+ private VirtualPort createVirtualPort(VirtualPortId id) {
Set<FixedIp> fixedIps;
Map<String, String> propertyMap;
Set<AllowedAddressPair> allowedAddressPairs;
@@ -201,14 +247,13 @@
String macAddressStr = "fa:12:3e:56:ee:a2";
String ipAddress = "10.1.1.1";
- String tenantNetworkId = "1234567";
String subnet = "1212";
String hostIdStr = "fa:e2:3e:56:ee:a2";
String deviceOwner = "james";
propertyMap = Maps.newHashMap();
propertyMap.putIfAbsent("deviceOwner", deviceOwner);
- TenantNetworkId networkId = TenantNetworkId.networkId(tenantNetworkId);
+ TenantNetworkId networkId = TenantNetworkId.networkId(networkIdStr);
MacAddress macAddress = MacAddress.valueOf(macAddressStr);
BindingHostId bindingHostId = BindingHostId.bindingHostId(hostIdStr);
FixedIp fixedIp = FixedIp.fixedIp(SubnetId.subnetId(subnet),
@@ -222,7 +267,7 @@
MacAddress.valueOf(macAddressStr));
allowedAddressPairs.add(allowedAddressPair);
- VirtualPort d1 = new DefaultVirtualPort(id1, networkId, true,
+ VirtualPort d1 = new DefaultVirtualPort(id, networkId, true,
propertyMap,
VirtualPort.State.ACTIVE,
macAddress, tenantId, deviceId,
@@ -236,7 +281,7 @@
public void testInstallFlowClassifier() {
ApplicationId appId = new DefaultApplicationId(1, "test");
- FlowClassifierInstallerImpl flowClassifierInstaller = new FlowClassifierInstallerImpl();
+ SfcFlowRuleInstallerImpl flowClassifierInstaller = new SfcFlowRuleInstallerImpl();
flowClassifierInstaller.virtualPortService = virtualPortService;
flowClassifierInstaller.vtnRscService = vtnRscService;
flowClassifierInstaller.portPairService = portPairService;
@@ -261,7 +306,7 @@
flowClassifierService.createFlowClassifier(fc2);
List<VirtualPort> virtualPortList = Lists.newArrayList();
- virtualPortList.add(createVirtualPort());
+ virtualPortList.add(createVirtualPort(VirtualPortId.portId(ingress)));
virtualPortService.createPorts(virtualPortList);
expect(driverService.createHandler(deviceId)).andReturn(driverHandler).anyTimes();
@@ -271,4 +316,102 @@
assertThat(connectPoint, is(HostLocation.NONE));
}
-}
\ No newline at end of file
+
+ @Test
+ public void testInstallLoadBalancedFlowRules() {
+ ApplicationId appId = new DefaultApplicationId(1, "test");
+ SfcFlowRuleInstallerImpl flowRuleInstaller = new SfcFlowRuleInstallerImpl();
+ flowRuleInstaller.virtualPortService = virtualPortService;
+ flowRuleInstaller.vtnRscService = vtnRscService;
+ flowRuleInstaller.portPairService = portPairService;
+ flowRuleInstaller.portPairGroupService = portPairGroupService;
+ flowRuleInstaller.flowClassifierService = flowClassifierService;
+ flowRuleInstaller.driverService = driverService;
+ flowRuleInstaller.deviceService = deviceService;
+ flowRuleInstaller.hostService = hostService;
+ flowRuleInstaller.flowObjectiveService = flowObjectiveService;
+ flowRuleInstaller.tenantNetworkService = tenantNetworkService;
+ flowRuleInstaller.appId = appId;
+
+ final PortChain portChain = createPortChain();
+
+ final String ppName1 = "PortPair1";
+ final String ppDescription1 = "PortPair1";
+ final String ingress1 = "d3333333-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress1 = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345";
+ DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder();
+ PortPair portPair1 = portPairBuilder.setId(portPairId1).setName(ppName1).setTenantId(tenantId)
+ .setDescription(ppDescription1).setIngress(ingress1).setEgress(egress1).build();
+
+ final String ppName2 = "PortPair2";
+ final String ppDescription2 = "PortPair2";
+ final String ingress2 = "d5555555-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress2 = "a6666666-4a56-2a6e-cd3a-9dee4e2ec345";
+ PortPair portPair2 = portPairBuilder.setId(portPairId2).setName(ppName2).setTenantId(tenantId)
+ .setDescription(ppDescription2).setIngress(ingress2).setEgress(egress2).build();
+
+ portPairService.createPortPair(portPair1);
+ portPairService.createPortPair(portPair2);
+
+ FlowClassifier fc1 = createFlowClassifier(flowClassifierId1);
+ FlowClassifier fc2 = createFlowClassifier(flowClassifierId2);
+ flowClassifierService.createFlowClassifier(fc1);
+ flowClassifierService.createFlowClassifier(fc2);
+
+ NshServicePathId nshSpiId = NshServicePathId.of(10);
+ FiveTuple fiveTuple = DefaultFiveTuple.builder().setIpSrc(IpAddress.valueOf("3.3.3.3"))
+ .setIpDst(IpAddress.valueOf("4.4.4.4"))
+ .setPortSrc(PortNumber.portNumber(1500))
+ .setPortDst(PortNumber.portNumber(2000))
+ .setProtocol(IPv4.PROTOCOL_UDP)
+ .setTenantId(TenantId.tenantId("bbb"))
+ .build();
+ LoadBalanceId id = LoadBalanceId.of((byte) 1);
+
+ List<PortPairId> path = Lists.newArrayList();
+ path.add(portPairId1);
+ path.add(portPairId2);
+
+ List<VirtualPort> virtualPortList = Lists.newArrayList();
+ virtualPortList.add(createVirtualPort(VirtualPortId.portId(ingress1)));
+ virtualPortList.add(createVirtualPort(VirtualPortId.portId(egress1)));
+ virtualPortList.add(createVirtualPort(VirtualPortId.portId(ingress2)));
+ virtualPortList.add(createVirtualPort(VirtualPortId.portId(egress2)));
+ virtualPortService.createPorts(virtualPortList);
+
+ portChain.addLoadBalancePath(fiveTuple, id, path);
+
+ String physicalNetworkStr = "1234";
+ String segmentationIdStr = "1";
+ SegmentationId segmentationID = SegmentationId
+ .segmentationId(segmentationIdStr);
+ TenantNetworkId networkid1 = TenantNetworkId.networkId(networkIdStr);
+ PhysicalNetwork physicalNetwork = PhysicalNetwork
+ .physicalNetwork(physicalNetworkStr);
+ TenantNetwork p1 = new DefaultTenantNetwork(networkid1, name, false,
+ TenantNetwork.State.ACTIVE,
+ false, tenantId, false,
+ TenantNetwork.Type.LOCAL,
+ physicalNetwork,
+ segmentationID);
+ tenantNetworkService.createNetworks(Collections.singletonList(p1));
+
+ expect(driverService.createHandler(deviceId)).andReturn(driverHandler).anyTimes();
+ replay(driverService);
+
+ flowRuleInstaller.installLoadBalancedFlowRules(portChain, fiveTuple, nshSpiId);
+
+ ForwardingObjective forObj = ((FlowObjectiveAdapter) flowObjectiveService).forwardingObjective();
+
+ // Check for Selector
+ assertThat(forObj.selector().getCriterion(Criterion.Type.IN_PORT), instanceOf(PortCriterion.class));
+
+ // Check for treatment
+ List<Instruction> instructions = forObj.treatment().allInstructions();
+ for (Instruction instruction : instructions) {
+ if (instruction.type() == Instruction.Type.OUTPUT) {
+ assertThat(((OutputInstruction) instruction).port(), is(PortNumber.P0));
+ }
+ }
+ }
+}
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelector.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelector.java
index a59c37b..6b8ca07f 100644
--- a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelector.java
+++ b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelector.java
@@ -23,6 +23,12 @@
public class MockExtensionSelector implements ExtensionSelector {
+ private ExtensionSelectorType type;
+
+ public MockExtensionSelector(ExtensionSelectorType type) {
+ this.type = type;
+ }
+
@Override
public <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException {
}
@@ -48,6 +54,6 @@
@Override
public ExtensionSelectorType type() {
- return null;
+ return type;
}
}
\ No newline at end of file
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelectorResolver.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelectorResolver.java
index f7d90ad..1c2f46c 100644
--- a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelectorResolver.java
+++ b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionSelectorResolver.java
@@ -43,6 +43,6 @@
@Override
public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) {
- return new MockExtensionSelector();
+ return new MockExtensionSelector(type);
}
}
\ No newline at end of file
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatment.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatment.java
index 3106e0f..b782133 100644
--- a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatment.java
+++ b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatment.java
@@ -23,6 +23,12 @@
public class MockExtensionTreatment implements ExtensionTreatment {
+ private ExtensionTreatmentType type;
+
+ public MockExtensionTreatment(ExtensionTreatmentType type) {
+ this.type = type;
+ }
+
@Override
public <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException {
}
@@ -48,7 +54,7 @@
@Override
public ExtensionTreatmentType type() {
- return null;
+ return type;
}
}
\ No newline at end of file
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatmentResolver.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatmentResolver.java
index 6cbb413..c58804c 100644
--- a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatmentResolver.java
+++ b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/MockExtensionTreatmentResolver.java
@@ -43,7 +43,7 @@
@Override
public ExtensionTreatment getExtensionInstruction(ExtensionTreatmentType type) {
- return new MockExtensionTreatment();
+ return new MockExtensionTreatment(type);
}
}
\ No newline at end of file
diff --git a/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/TenantNetworkAdapter.java b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/TenantNetworkAdapter.java
new file mode 100644
index 0000000..f4fa9e8
--- /dev/null
+++ b/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/TenantNetworkAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016-present 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.sfc.util;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.onosproject.vtnrsc.TenantNetwork;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Provides implementation of the VtnRsc service.
+ */
+public class TenantNetworkAdapter implements TenantNetworkService {
+
+ private final ConcurrentMap<TenantNetworkId, TenantNetwork> tenantNetworkStore = new ConcurrentHashMap<>();
+
+ @Override
+ public boolean exists(TenantNetworkId networkId) {
+ return tenantNetworkStore.containsKey(networkId);
+ }
+
+ @Override
+ public int getNetworkCount() {
+ return tenantNetworkStore.size();
+ }
+
+ @Override
+ public Iterable<TenantNetwork> getNetworks() {
+ return ImmutableList.copyOf(tenantNetworkStore.values());
+ }
+
+ @Override
+ public TenantNetwork getNetwork(TenantNetworkId networkId) {
+ return tenantNetworkStore.get(networkId);
+ }
+
+ @Override
+ public boolean createNetworks(Iterable<TenantNetwork> networks) {
+ for (TenantNetwork network : networks) {
+ tenantNetworkStore.put(network.id(), network);
+ if (!tenantNetworkStore.containsKey(network.id())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updateNetworks(Iterable<TenantNetwork> networks) {
+ return false;
+ }
+
+ @Override
+ public boolean removeNetworks(Iterable<TenantNetworkId> networksIds) {
+ return false;
+ }
+
+}
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
index 7301a46..e4b0767 100644
--- a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
@@ -45,6 +45,20 @@
{
put("key", "flow");
put("remote_ip", "flow");
+ put("dst_port", "4790");
+ put("in_nsi", "flow");
+ put("in_nsp", "flow");
+ put("out_nsi", "flow");
+ put("out_nsp", "flow");
+ put("in_nshc1", "flow");
+ put("out_nshc1", "flow");
+ put("in_nshc2", "flow");
+ put("out_nshc2", "flow");
+ put("in_nshc3", "flow");
+ put("out_nshc3", "flow");
+ put("in_nshc4", "flow");
+ put("out_nshc4", "flow");
+ put("exts", "gpe");
}
};
/**
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
index 4f3a5a0..27b3a22 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
@@ -48,7 +48,7 @@
private static final String TENANT_ID_NOT_NULL = "Tenant id can not be null.";
private static final String NAME_NOT_NULL = "Name can not be null.";
private static final String ETHER_TYPE_NOT_NULL = "Ether Type can not be null.";
- private static final int DEFAULT_CLASSIFIER_PRIORITY = 0xFFFF;
+ private static final int DEFAULT_CLASSIFIER_PRIORITY = 0xCB20;
/**
* Constructor to create default flow classifier.
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
index 879c7ea..9d66de3 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
@@ -22,7 +22,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -42,11 +41,13 @@
private final String description;
private final List<PortPairGroupId> portPairGroupList;
private final List<FlowClassifierId> flowClassifierList;
+ private final PortChain oldPortChain;
private final Map<FiveTuple, LoadBalanceId> sfcLoadBalanceIdMap = new ConcurrentHashMap<>();
private final Map<LoadBalanceId, List<PortPairId>> sfcLoadBalancePathMap = new ConcurrentHashMap<>();
private final Map<LoadBalanceId, List<DeviceId>> sfcClassifiersMap = new ConcurrentHashMap<>();
private final Map<LoadBalanceId, List<DeviceId>> sfcForwardersMap = new ConcurrentHashMap<>();
+
/**
* Default constructor to create port chain.
*
@@ -58,9 +59,10 @@
* @param flowClassifierList flow classifier list
*/
private DefaultPortChain(PortChainId portChainId, TenantId tenantId,
- String name, String description,
- List<PortPairGroupId> portPairGroupList,
- List<FlowClassifierId> flowClassifierList) {
+ String name, String description,
+ List<PortPairGroupId> portPairGroupList,
+ List<FlowClassifierId> flowClassifierList,
+ PortChain portChain) {
this.portChainId = portChainId;
this.tenantId = tenantId;
@@ -68,6 +70,20 @@
this.description = description;
this.portPairGroupList = portPairGroupList;
this.flowClassifierList = flowClassifierList;
+ this.oldPortChain = portChain;
+ }
+
+ /**
+ * To create port chain for update with old port chain.
+ *
+ * @param newPortChain updated port chain
+ * @param oldPortChain old port chain
+ * @return port chain
+ */
+ public static PortChain create(PortChain newPortChain, PortChain oldPortChain) {
+ return new DefaultPortChain(newPortChain.portChainId(), newPortChain.tenantId(),
+ newPortChain.name(), newPortChain.description(),
+ newPortChain.portPairGroups(), newPortChain.flowClassifiers(), oldPortChain);
}
/**
@@ -109,7 +125,7 @@
@Override
public List<PortPairGroupId> portPairGroups() {
- return ImmutableList.copyOf(portPairGroupList);
+ return ImmutableList.copyOf(portPairGroupList);
}
@Override
@@ -118,6 +134,11 @@
}
@Override
+ public PortChain oldPortChain() {
+ return oldPortChain;
+ }
+
+ @Override
public void addLoadBalancePath(FiveTuple fiveTuple, LoadBalanceId id,
List<PortPairId> path) {
this.sfcLoadBalanceIdMap.put(fiveTuple, id);
@@ -136,14 +157,14 @@
@Override
public void removeSfcClassifiers(LoadBalanceId id, List<DeviceId> classifierList) {
- List<DeviceId> list = getSfcClassifiers(id);
+ List<DeviceId> list = sfcClassifiersMap.get(id);
list.removeAll(classifierList);
this.sfcForwardersMap.put(id, list);
}
@Override
public void removeSfcForwarders(LoadBalanceId id, List<DeviceId> forwarderList) {
- List<DeviceId> list = getSfcForwarders(id);
+ List<DeviceId> list = sfcForwardersMap.get(id);
list.removeAll(forwarderList);
this.sfcForwardersMap.put(id, list);
}
@@ -192,7 +213,7 @@
}
@Override
- public Optional<LoadBalanceId> matchPath(List<PortPairId> path) {
+ public LoadBalanceId matchPath(List<PortPairId> path) {
LoadBalanceId id = null;
for (Map.Entry<LoadBalanceId, List<PortPairId>> entry : sfcLoadBalancePathMap.entrySet()) {
@@ -202,7 +223,7 @@
break;
}
}
- return Optional.of(id);
+ return id;
}
@Override
@@ -267,6 +288,7 @@
private String description;
private List<PortPairGroupId> portPairGroupList;
private List<FlowClassifierId> flowClassifierList;
+ private PortChain portChain;
@Override
public Builder setId(PortChainId portChainId) {
@@ -312,7 +334,7 @@
checkNotNull(portPairGroupList, "Port pair groups cannot be null");
return new DefaultPortChain(portChainId, tenantId, name, description,
- portPairGroupList, flowClassifierList);
+ portPairGroupList, flowClassifierList, portChain);
}
}
}
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
index 9817b0a..af929dd 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
@@ -95,6 +95,13 @@
}
@Override
+ public void resetLoad() {
+ for (PortPairId portPairId : portPairList) {
+ portPairLoadMap.put(portPairId, new Integer(0));
+ }
+ }
+
+ @Override
public int getLoad(PortPairId portPairId) {
return portPairLoadMap.get(portPairId);
}
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
index 2906411..c431c7a 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
@@ -16,7 +16,6 @@
package org.onosproject.vtnrsc;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import org.onosproject.net.DeviceId;
@@ -74,6 +73,13 @@
List<FlowClassifierId> flowClassifiers();
/**
+ * Returns the old port chain.
+ *
+ * @return old port chain
+ */
+ PortChain oldPortChain();
+
+ /**
* Adds a new load balanced path.
*
* @param fiveTuple five tuple from the packet
@@ -182,7 +188,7 @@
* @param path load balanced path
* @return load balance id if the path matches, null otherwise.
*/
- Optional<LoadBalanceId> matchPath(List<PortPairId> path);
+ LoadBalanceId matchPath(List<PortPairId> path);
/**
* Returns whether this port chain is an exact match to the port chain given
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
index bdcfd1d..0114470 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
@@ -67,6 +67,11 @@
void addLoad(PortPairId portPairId);
/**
+ * Reset the load for all the port pairs in the group.
+ */
+ void resetLoad();
+
+ /**
* Get the load on the given port pair id.
*
* @param portPairId port pair id
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
index 25fca33..5521d2e 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
@@ -15,8 +15,10 @@
*/
package org.onosproject.vtnrsc.flowclassifier.impl;
-import static org.slf4j.LoggerFactory.getLogger;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.UUID;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -24,6 +26,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpPrefix;
import org.onlab.util.KryoNamespace;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.store.serializers.KryoNamespaces;
@@ -33,8 +36,11 @@
import org.onosproject.store.service.MultiValuedTimestamp;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
-import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.DefaultFlowClassifier;
import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierEvent;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierListener;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
@@ -71,7 +77,8 @@
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(MultiValuedTimestamp.class)
- .register(FlowClassifier.class);
+ .register(FlowClassifier.class, FlowClassifierId.class, UUID.class, IpPrefix.class,
+ VirtualPortId.class, DefaultFlowClassifier.class, TenantId.class);
flowClassifierStore = storageService
.<FlowClassifierId, FlowClassifier>eventuallyConsistentMapBuilder()
.withName("flowclassifierstore").withSerializer(serializer)
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
index 21c848b..21a3d2d 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
@@ -19,6 +19,7 @@
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
+import java.util.UUID;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -28,6 +29,7 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.net.DeviceId;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapEvent;
@@ -35,8 +37,15 @@
import org.onosproject.store.service.MultiValuedTimestamp;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultPortChain;
+import org.onosproject.vtnrsc.FiveTuple;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.LoadBalanceId;
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.portchain.PortChainEvent;
import org.onosproject.vtnrsc.portchain.PortChainListener;
import org.onosproject.vtnrsc.portchain.PortChainService;
@@ -71,7 +80,9 @@
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(MultiValuedTimestamp.class)
- .register(PortChain.class);
+ .register(PortChain.class, PortChainId.class, UUID.class, PortPairGroupId.class,
+ FlowClassifierId.class, FiveTuple.class, LoadBalanceId.class, DeviceId.class,
+ DefaultPortChain.class, PortPairId.class, TenantId.class);
portChainStore = storageService
.<PortChainId, PortChain>eventuallyConsistentMapBuilder()
@@ -118,7 +129,7 @@
portChainStore.put(portChain.portChainId(), portChain);
if (!portChainStore.containsKey(portChain.portChainId())) {
- log.debug("The portChain is created failed which identifier was {}", portChain.portChainId()
+ log.error("The portChain created is failed which identifier was {}", portChain.portChainId()
.toString());
return false;
}
@@ -128,18 +139,20 @@
@Override
public boolean updatePortChain(PortChain portChain) {
checkNotNull(portChain, PORT_CHAIN_NULL);
-
+ PortChain oldPortChain = null;
if (!portChainStore.containsKey(portChain.portChainId())) {
- log.debug("The portChain is not exist whose identifier was {} ",
- portChain.portChainId().toString());
+ log.warn("The portChain is not exist whose identifier was {} ",
+ portChain.portChainId().toString());
return false;
+ } else {
+ oldPortChain = portChainStore.get(portChain.portChainId());
}
+ PortChain newPortChain = DefaultPortChain.create(portChain, oldPortChain);
+ portChainStore.put(newPortChain.portChainId(), newPortChain);
- portChainStore.put(portChain.portChainId(), portChain);
-
- if (!portChain.equals(portChainStore.get(portChain.portChainId()))) {
+ if (!newPortChain.equals(portChainStore.get(newPortChain.portChainId()))) {
log.debug("The portChain is updated failed whose identifier was {} ",
- portChain.portChainId().toString());
+ newPortChain.portChainId().toString());
return false;
}
return true;
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java
index 2df0ee6..c769092 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java
@@ -38,6 +38,7 @@
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
import org.slf4j.Logger;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
@@ -86,13 +87,13 @@
List<PortPairGroupId> portPairGrpList = portChain.portPairGroups();
ListIterator<PortPairGroupId> listGrpIterator = portPairGrpList.listIterator();
- while (listGrpIterator.next() != null) {
+ while (listGrpIterator.hasNext()) {
PortPairGroupId portPairGroupId = listGrpIterator.next();
PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
ServiceFunctionGroup sfg = new ServiceFunctionGroup(portPairGroup.name(), portPairGroup.description(),
portPairGroup.portPairLoadMap());
serviceFunctionGroupList.add(sfg);
}
- return serviceFunctionGroupList;
+ return ImmutableList.copyOf(serviceFunctionGroupList);
}
}
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
index 4547764..18105b2 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
@@ -19,6 +19,7 @@
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
+import java.util.UUID;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -35,8 +36,10 @@
import org.onosproject.store.service.MultiValuedTimestamp;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultPortPair;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.portpair.PortPairEvent;
import org.onosproject.vtnrsc.portpair.PortPairListener;
import org.onosproject.vtnrsc.portpair.PortPairService;
@@ -72,7 +75,7 @@
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(MultiValuedTimestamp.class)
- .register(PortPair.class);
+ .register(PortPair.class, PortPairId.class, UUID.class, DefaultPortPair.class, TenantId.class);
portPairStore = storageService.<PortPairId, PortPair>eventuallyConsistentMapBuilder()
.withName("portpairstore")
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
index eca172c..7ef6999 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
@@ -19,6 +19,7 @@
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
+import java.util.UUID;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -35,8 +36,11 @@
import org.onosproject.store.service.MultiValuedTimestamp;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultPortPairGroup;
import org.onosproject.vtnrsc.PortPairGroup;
import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupEvent;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupListener;
import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
@@ -71,7 +75,8 @@
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(MultiValuedTimestamp.class)
- .register(PortPairGroup.class);
+ .register(PortPairGroup.class, PortPairGroupId.class, UUID.class, DefaultPortPairGroup.class,
+ TenantId.class, PortPairId.class);
portPairGroupStore = storageService
.<PortPairGroupId, PortPairGroup>eventuallyConsistentMapBuilder()
diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainDeviceMapWebResource.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainDeviceMapWebResource.java
new file mode 100644
index 0000000..b391ae4
--- /dev/null
+++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainDeviceMapWebResource.java
@@ -0,0 +1,91 @@
+/*
+ * 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.vtnweb.resources;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.LoadBalanceId;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.portchain.PortChainService;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port chain.
+ */
+
+@Path("portChainDeviceMap")
+public class PortChainDeviceMapWebResource extends AbstractWebResource {
+
+ public static final String PORT_CHAIN_NOT_FOUND = "Port chain not found";
+ public static final String PORT_CHAIN_ID_EXIST = "Port chain exists";
+ public static final String PORT_CHAIN_ID_NOT_EXIST = "Port chain does not exist with identifier";
+
+ private static final String NAME = "name";
+ private static final String ID = "id";
+ private static final String CLASSIFIERS = "classifiers";
+ private static final String FORWARDERS = "forwarders";
+ private static final String LOADBALANCEID = "loadBalanceId";
+
+ /**
+ * Get details of a specified port chain id.
+ *
+ * @param id port chain id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{chain_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response getPortChainDeviceMap(@PathParam("chain_id") String id) {
+
+ PortChain portChain = nullIsNotFound(get(PortChainService.class).getPortChain(PortChainId.of(id)),
+ PORT_CHAIN_NOT_FOUND);
+ ObjectNode result = mapper().createObjectNode();
+ result.set("portChainDeviceMap", encode(portChain, this));
+
+ return ok(result.toString()).build();
+ }
+
+ private ObjectNode encode(PortChain portChain, CodecContext context) {
+ checkNotNull(portChain, "portChain cannot be null");
+ ObjectNode result = context.mapper().createObjectNode();
+ result.put(ID, portChain.portChainId().toString())
+ .put(NAME, portChain.name());
+
+ Set<LoadBalanceId> loadBalanceIds = portChain.getLoadBalancePathMapKeys();
+ for (LoadBalanceId id : loadBalanceIds) {
+ result.put(LOADBALANCEID, id.toString())
+ .put(CLASSIFIERS, portChain.getSfcClassifiers(id).toString())
+ .put(FORWARDERS, portChain.getSfcForwarders(id).toString());
+ }
+ return result;
+ }
+}
diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainSfMapWebResource.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainSfMapWebResource.java
new file mode 100644
index 0000000..b644786
--- /dev/null
+++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainSfMapWebResource.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016-present 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.vtnweb.resources;
+
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.ServiceFunctionGroup;
+import org.onosproject.vtnrsc.portchainsfmap.PortChainSfMapService;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query service function and load details by port chain.
+ */
+
+@Path("portChainSfMap")
+public class PortChainSfMapWebResource extends AbstractWebResource {
+
+ public static final String PORT_CHAIN_NOT_FOUND = "Port chain not found";
+ public static final String PORT_CHAIN_ID_EXIST = "Port chain exists";
+ public static final String PORT_CHAIN_ID_NOT_EXIST = "Port chain does not exist with identifier";
+
+ /**
+ * Get service function details of a specified port chain id.
+ *
+ * @param id port chain id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{chainId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response getPortChainSfMap(@PathParam("chainId") String id) {
+
+ Iterable<ServiceFunctionGroup> serviceFunctionGroups = nullIsNotFound(get(PortChainSfMapService.class)
+ .getServiceFunctions(PortChainId.of(id)),
+ PORT_CHAIN_NOT_FOUND);
+ ObjectNode result = mapper().createObjectNode();
+ ArrayNode portChainSfMap = result.putArray("portChainSfMap");
+ if (serviceFunctionGroups != null) {
+ for (final ServiceFunctionGroup serviceFunctionGroup : serviceFunctionGroups) {
+ portChainSfMap.add(codec(ServiceFunctionGroup.class).encode(serviceFunctionGroup, this));
+ }
+ }
+ return ok(result.toString()).build();
+ }
+}
diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VtnWebApplication.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VtnWebApplication.java
index f22f6df..142be79 100644
--- a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VtnWebApplication.java
+++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VtnWebApplication.java
@@ -35,7 +35,9 @@
PortPairWebResource.class,
FloatingIpWebResource.class,
RouterWebResource.class,
- ClassifierWebResource.class);
+ ClassifierWebResource.class,
+ PortChainSfMapWebResource.class,
+ PortChainDeviceMapWebResource.class);
}
}
diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
index 94e02db..e4d4b93 100644
--- a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
+++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
@@ -80,8 +80,10 @@
resultBuilder.setProtocol(protocol);
}
- int priority = (json.get(PRIORITY)).asInt();
- resultBuilder.setPriority(priority);
+ if (json.get(PRIORITY) != null && !(json.get(PRIORITY)).asText().equals("null")) {
+ int priority = (json.get(PRIORITY)).asInt();
+ resultBuilder.setPriority(priority);
+ }
int minSrcPortRange = (json.get(MIN_SRC_PORT_RANGE)).asInt();
resultBuilder.setMinSrcPortRange(minSrcPortRange);
diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/ServiceFunctionCodec.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/ServiceFunctionCodec.java
new file mode 100644
index 0000000..f847b10
--- /dev/null
+++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/ServiceFunctionCodec.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 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.vtnweb.web;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.ServiceFunctionGroup;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Service function JSON codec.
+ */
+public final class ServiceFunctionCodec extends JsonCodec<ServiceFunctionGroup> {
+
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String PORT_PAIR_LOAD = "port_pair_load";
+ @Override
+ public ObjectNode encode(ServiceFunctionGroup serviceFunction, CodecContext context) {
+ checkNotNull(serviceFunction, "service cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(NAME, serviceFunction.name())
+ .put(DESCRIPTION, serviceFunction.description())
+ .put(PORT_PAIR_LOAD, serviceFunction.portPairLoadMap().toString());
+ return result;
+ }
+}
diff --git a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java
index 3330c25..84ac4a8 100644
--- a/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java
+++ b/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java
@@ -25,6 +25,7 @@
import org.onosproject.vtnrsc.PortChain;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.ServiceFunctionGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +46,7 @@
codecService.registerCodec(PortPairGroup.class, new PortPairGroupCodec());
codecService.registerCodec(FlowClassifier.class, new FlowClassifierCodec());
codecService.registerCodec(PortChain.class, new PortChainCodec());
-
+ codecService.registerCodec(ServiceFunctionGroup.class, new ServiceFunctionCodec());
log.info("Started");
}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java
new file mode 100644
index 0000000..e173051
--- /dev/null
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2016-present 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.vtnweb.resources;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
+import org.onosproject.codec.CodecService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.vtnrsc.FiveTuple;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.LoadBalanceId;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.portchain.PortChainService;
+import org.onosproject.vtnweb.web.SfcCodecContext;
+
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Unit tests for port chain device map REST APIs.
+ */
+public class PortChainDeviceMapResourceTest extends VtnResourceTest {
+
+ final PortChainService portChainService = createMock(PortChainService.class);
+
+ PortChainId portChainId1 = PortChainId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ TenantId tenantId1 = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5");
+ private final List<PortPairGroupId> portPairGroupList1 = Lists.newArrayList();
+ private final List<FlowClassifierId> flowClassifierList1 = Lists.newArrayList();
+
+ final MockPortChain portChain1 = new MockPortChain(portChainId1, tenantId1, "portChain1",
+ "Mock port chain", portPairGroupList1,
+ flowClassifierList1);
+
+ /**
+ * Mock class for a port chain.
+ */
+ private static class MockPortChain implements PortChain {
+
+ private final PortChainId portChainId;
+ private final TenantId tenantId;
+ private final String name;
+ private final String description;
+ private final List<PortPairGroupId> portPairGroupList;
+ private final List<FlowClassifierId> flowClassifierList;
+
+ public MockPortChain(PortChainId portChainId, TenantId tenantId,
+ String name, String description,
+ List<PortPairGroupId> portPairGroupList,
+ List<FlowClassifierId> flowClassifierList) {
+
+ this.portChainId = portChainId;
+ this.tenantId = tenantId;
+ this.name = name;
+ this.description = description;
+ this.portPairGroupList = portPairGroupList;
+ this.flowClassifierList = flowClassifierList;
+ }
+
+ @Override
+ public PortChainId portChainId() {
+ return portChainId;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public List<PortPairGroupId> portPairGroups() {
+ return ImmutableList.copyOf(portPairGroupList);
+ }
+
+ @Override
+ public List<FlowClassifierId> flowClassifiers() {
+ return ImmutableList.copyOf(flowClassifierList);
+ }
+
+ @Override
+ public boolean exactMatch(PortChain portChain) {
+ return this.equals(portChain) &&
+ Objects.equals(this.portChainId, portChain.portChainId()) &&
+ Objects.equals(this.tenantId, portChain.tenantId());
+ }
+
+ @Override
+ public void addLoadBalancePath(FiveTuple fiveTuple, LoadBalanceId id, List<PortPairId> path) {
+ }
+
+ @Override
+ public LoadBalanceId getLoadBalanceId(FiveTuple fiveTuple) {
+ return null;
+ }
+
+ @Override
+ public Set<FiveTuple> getLoadBalanceIdMapKeys() {
+ return null;
+ }
+
+ @Override
+ public List<PortPairId> getLoadBalancePath(LoadBalanceId id) {
+ return null;
+ }
+
+ @Override
+ public List<PortPairId> getLoadBalancePath(FiveTuple fiveTuple) {
+ return null;
+ }
+
+ @Override
+ public LoadBalanceId matchPath(List<PortPairId> path) {
+ return null;
+ }
+
+ @Override
+ public int getLoadBalancePathSize() {
+ return 0;
+ }
+
+ @Override
+ public void addSfcClassifiers(LoadBalanceId id, List<DeviceId> classifierList) {
+ }
+
+ @Override
+ public void addSfcForwarders(LoadBalanceId id, List<DeviceId> forwarderList) {
+ }
+
+ @Override
+ public void removeSfcClassifiers(LoadBalanceId id, List<DeviceId> classifierList) {
+ }
+
+ @Override
+ public void removeSfcForwarders(LoadBalanceId id, List<DeviceId> forwarderList) {
+ }
+
+ @Override
+ public List<DeviceId> getSfcClassifiers(LoadBalanceId id) {
+ DeviceId deviceId1 = DeviceId.deviceId("of:000000000000001");
+ List<DeviceId> classifierList = Lists.newArrayList();
+ classifierList.add(deviceId1);
+ return classifierList;
+ }
+
+ @Override
+ public List<DeviceId> getSfcForwarders(LoadBalanceId id) {
+ DeviceId deviceId1 = DeviceId.deviceId("of:000000000000002");
+ DeviceId deviceId2 = DeviceId.deviceId("of:000000000000003");
+ List<DeviceId> forwarderList = Lists.newArrayList();
+ forwarderList.add(deviceId1);
+ forwarderList.add(deviceId2);
+ return forwarderList;
+ }
+
+ @Override
+ public Set<LoadBalanceId> getLoadBalancePathMapKeys() {
+ LoadBalanceId id = LoadBalanceId.of((byte) 1);
+ Set<LoadBalanceId> set = new HashSet<LoadBalanceId>();
+ set.add(id);
+ return set;
+ }
+
+ @Override
+ public PortChain oldPortChain() {
+ return null;
+ }
+ }
+
+ /**
+ * Sets up the global values for all the tests.
+ */
+ @Before
+ public void setUpTest() {
+ SfcCodecContext context = new SfcCodecContext();
+ ServiceDirectory testDirectory = new TestServiceDirectory()
+ .add(PortChainService.class, portChainService)
+ .add(CodecService.class, context.codecManager());
+ BaseResource.setServiceDirectory(testDirectory);
+ }
+
+ /**
+ * Cleans up.
+ */
+ @After
+ public void tearDownTest() {
+ }
+
+ /**
+ * Tests the result of a rest api GET for port chain id.
+ */
+ @Test
+ public void testGetPortChainDeviceMap() {
+
+ expect(portChainService.getPortChain(anyObject())).andReturn(portChain1).anyTimes();
+ replay(portChainService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("portChainDeviceMap/1278dcd4-459f-62ed-754b-87fc5e4a6751").request()
+ .get(String.class);
+ final JsonObject result = Json.parse(response).asObject();
+ assertThat(result, notNullValue());
+ assertThat(result.names().get(0), is("portChainDeviceMap"));
+
+ }
+}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java
index deac05f..8e96a3f 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java
@@ -15,10 +15,29 @@
*/
package org.onosproject.vtnweb.resources;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonObject;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -38,28 +57,10 @@
import org.onosproject.vtnrsc.portchain.PortChainService;
import org.onosproject.vtnweb.web.SfcCodecContext;
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
/**
* Unit tests for port chain REST APIs.
@@ -165,7 +166,7 @@
}
@Override
- public Optional<LoadBalanceId> matchPath(List<PortPairId> path) {
+ public LoadBalanceId matchPath(List<PortPairId> path) {
return null;
}
@@ -204,6 +205,11 @@
public Set<LoadBalanceId> getLoadBalancePathMapKeys() {
return null;
}
+
+ @Override
+ public PortChain oldPortChain() {
+ return null;
+ }
}
/**
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java
new file mode 100644
index 0000000..b95817c
--- /dev/null
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016-present 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.vtnweb.resources;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
+import org.onosproject.codec.CodecService;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.ServiceFunctionGroup;
+import org.onosproject.vtnrsc.portchainsfmap.PortChainSfMapService;
+import org.onosproject.vtnweb.web.SfcCodecContext;
+
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.Lists;
+
+/**
+ * Unit tests for port chain sf map REST APIs.
+ */
+public class PortChainSfMapResourceTest extends VtnResourceTest {
+
+ final PortChainSfMapService portChainSfMapService = createMock(PortChainSfMapService.class);
+
+ String name1 = "Firewall";
+ String description1 = "Firewall service function";
+ Map<PortPairId, Integer> portPairLoadMap1 = new ConcurrentHashMap<>();
+
+ ServiceFunctionGroup serviceFunction1 = new ServiceFunctionGroup(name1, description1,
+ portPairLoadMap1);
+
+ /**
+ * Sets up the global values for all the tests.
+ */
+ @Before
+ public void setUpTest() {
+ SfcCodecContext context = new SfcCodecContext();
+ ServiceDirectory testDirectory = new TestServiceDirectory()
+ .add(PortChainSfMapService.class, portChainSfMapService)
+ .add(CodecService.class, context.codecManager());
+ BaseResource.setServiceDirectory(testDirectory);
+ }
+
+ /**
+ * Cleans up.
+ */
+ @After
+ public void tearDownTest() {
+ }
+
+ /**
+ * Tests the result of a rest api GET for port chain id.
+ */
+ @Test
+ public void testGetPortChainId() {
+
+ final List<ServiceFunctionGroup> serviceFunctions = Lists.newArrayList();
+ serviceFunctions.add(serviceFunction1);
+
+ expect(portChainSfMapService.getServiceFunctions(anyObject())).andReturn(serviceFunctions).anyTimes();
+ replay(portChainSfMapService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("portChainSfMap/1278dcd4-459f-62ed-754b-87fc5e4a6751").request()
+ .get(String.class);
+ final JsonObject result = Json.parse(response).asObject();
+ assertThat(result, notNullValue());
+ assertThat(result.names().get(0), is("portChainSfMap"));
+ }
+}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java
index c33d929..94aab56 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java
@@ -136,6 +136,10 @@
Objects.equals(this.portPairGroupId, portPairGroup.portPairGroupId()) &&
Objects.equals(this.tenantId, portPairGroup.tenantId());
}
+
+ @Override
+ public void resetLoad() {
+ }
}
/**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java
index 6952224..dad75cb 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java
@@ -38,6 +38,7 @@
NICIRA_MATCH_NSH_CH2(3),
NICIRA_MATCH_NSH_CH3(4),
NICIRA_MATCH_NSH_CH4(5),
+ NICIRA_MATCH_ENCAP_ETH_TYPE(6),
OFDPA_MATCH_VLAN_VID(16),
BMV2_MATCH_PARAMS(128);
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
index f87274e..9550597 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
@@ -38,14 +38,29 @@
NICIRA_MOV_ARP_SPA_TO_TPA(3),
NICIRA_MOV_ETH_SRC_TO_DST(4),
NICIRA_MOV_IP_SRC_TO_DST(5),
+ NICIRA_MOV_NSH_C1_TO_C1(6),
+ NICIRA_MOV_NSH_C2_TO_C2(7),
+ NICIRA_MOV_NSH_C3_TO_C3(8),
+ NICIRA_MOV_NSH_C4_TO_C4(9),
+ NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST(10),
+ NICIRA_MOV_TUN_ID_TO_TUN_ID(11),
+ NICIRA_MOV_NSH_C2_TO_TUN_ID(12),
NICIRA_RESUBMIT_TABLE(14),
- NICIRA_SET_NSH_SPI(32),
- NICIRA_SET_NSH_SI(33),
- NICIRA_SET_NSH_CH1(34),
- NICIRA_SET_NSH_CH2(35),
- NICIRA_SET_NSH_CH3(36),
- NICIRA_SET_NSH_CH4(37),
+ NICIRA_PUSH_NSH(38),
+ NICIRA_POP_NSH(39),
OFDPA_SET_VLAN_ID(64),
+ NICIRA_TUN_GPE_NP(111),
+ NICIRA_SET_NSH_SPI(113),
+ NICIRA_SET_NSH_SI(114),
+ NICIRA_SET_NSH_CH1(115),
+ NICIRA_SET_NSH_CH2(116),
+ NICIRA_SET_NSH_CH3(117),
+ NICIRA_SET_NSH_CH4(118),
+ NICIRA_NSH_MDTYPE(119),
+ NICIRA_NSH_NP(120),
+ NICIRA_ENCAP_ETH_SRC(121),
+ NICIRA_ENCAP_ETH_DST(122),
+ NICIRA_ENCAP_ETH_TYPE(123),
BMV2_ACTION(128);
private ExtensionTreatmentType type;
diff --git a/core/api/src/test/java/org/onosproject/net/device/DeviceServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/device/DeviceServiceAdapter.java
index d9ce4e5..9ffa2bd 100644
--- a/core/api/src/test/java/org/onosproject/net/device/DeviceServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/device/DeviceServiceAdapter.java
@@ -15,7 +15,8 @@
*/
package org.onosproject.net.device;
-import com.google.common.collect.FluentIterable;
+import java.util.Collections;
+import java.util.List;
import org.onosproject.net.Device;
import org.onosproject.net.Device.Type;
@@ -24,13 +25,31 @@
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
-import java.util.Collections;
-import java.util.List;
+import com.google.common.collect.FluentIterable;
/**
* Test adapter for device service.
*/
public class DeviceServiceAdapter implements DeviceService {
+
+ private List<Port> portList;
+
+ /**
+ * Constructor with port list.
+ *
+ * @param portList port list
+ */
+ public DeviceServiceAdapter(List<Port> portList) {
+ this.portList = portList;
+ }
+
+ /**
+ * Default constructor.
+ */
+ public DeviceServiceAdapter() {
+
+ }
+
@Override
public int getDeviceCount() {
return 0;
@@ -59,7 +78,7 @@
@Override
public List<Port> getPorts(DeviceId deviceId) {
- return Collections.emptyList();
+ return portList;
}
@Override
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java
index d305e08..b1ba927 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java
@@ -38,7 +38,6 @@
private ExtensionTreatmentType type;
private final KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(byte[].class)
.register(Map.class)
.build("DefaultMoveExtensionTreatment");
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthDst.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthDst.java
new file mode 100644
index 0000000..1f98825
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthDst.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.store.serializers.MacAddressSerializer;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira EncapEthDst extension instruction to set encapsulated eth destination.
+ */
+public class NiciraEncapEthDst extends AbstractExtension implements ExtensionTreatment {
+
+ private MacAddress encapEthDst;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder()
+ .register(new MacAddressSerializer(), MacAddress.class).register(byte[].class).build();;
+
+ /**
+ * Creates a new nshEncapEthDst instruction.
+ */
+ NiciraEncapEthDst() {
+ }
+
+ /**
+ * Creates a new encapEthDst instruction with given mac address.
+ *
+ * @param encapEthDst encapsulated ethernet destination
+ */
+ public NiciraEncapEthDst(MacAddress encapEthDst) {
+ this.encapEthDst = encapEthDst;
+ }
+
+ /**
+ * Gets the encapEthDst.
+ *
+ * @return encapEthDst
+ */
+ public MacAddress encapEthDst() {
+ return encapEthDst;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_DST.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ encapEthDst = appKryo.deserialize(data);
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(encapEthDst);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(encapEthDst);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraEncapEthDst) {
+ NiciraEncapEthDst that = (NiciraEncapEthDst) obj;
+ return Objects.equals(encapEthDst, that.encapEthDst);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("encapEthDst", encapEthDst).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthSrc.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthSrc.java
new file mode 100644
index 0000000..7ecc1e8
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthSrc.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.store.serializers.MacAddressSerializer;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira EncapEthSrc extension instruction to set encapsulated eth source.
+ */
+public class NiciraEncapEthSrc extends AbstractExtension implements ExtensionTreatment {
+
+ private MacAddress encapEthSrc;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder()
+ .register(new MacAddressSerializer(), MacAddress.class).register(byte[].class).build();;
+
+ /**
+ * Creates a new nshEncapEthSrc instruction.
+ */
+ NiciraEncapEthSrc() {
+ }
+
+ /**
+ * Creates a new encapEthSrc instruction with given mac address.
+ *
+ * @param encapEthSrc encapsulated ethernet source
+ */
+ public NiciraEncapEthSrc(MacAddress encapEthSrc) {
+ this.encapEthSrc = encapEthSrc;
+ }
+
+ /**
+ * Gets the encapEthSrc.
+ *
+ * @return encapEthSrc
+ */
+ public MacAddress encapEthSrc() {
+ return encapEthSrc;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_SRC.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ encapEthSrc = appKryo.deserialize(data);
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(encapEthSrc);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(encapEthSrc);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraEncapEthSrc) {
+ NiciraEncapEthSrc that = (NiciraEncapEthSrc) obj;
+ return Objects.equals(encapEthSrc, that.encapEthSrc);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("encapEthSrc", encapEthSrc).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthType.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthType.java
new file mode 100644
index 0000000..8b7f194
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraEncapEthType.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira EncapEthType extension instruction to set encapsulated eth type.
+ */
+public class NiciraEncapEthType extends AbstractExtension implements ExtensionTreatment {
+
+ private short encapEthType;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new nshEncapEthType instruction.
+ */
+ NiciraEncapEthType() {
+ encapEthType = (short) 0;
+ }
+
+ /**
+ * Creates a new nshEncapEthType instruction with given eth type.
+ *
+ * @param encapEthType encapsulated ethernet type
+ */
+ public NiciraEncapEthType(short encapEthType) {
+ this.encapEthType = encapEthType;
+ }
+
+ /**
+ * Gets the encapEthType.
+ *
+ * @return encapEthType
+ */
+ public short encapEthType() {
+ return encapEthType;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_TYPE.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ encapEthType = (short) (appKryo.deserialize(data));
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(encapEthType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(encapEthType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraEncapEthType) {
+ NiciraEncapEthType that = (NiciraEncapEthType) obj;
+ return Objects.equals(encapEthType, that.encapEthType);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("encapEthType", encapEthType).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
index 57f0a67..4bd1aa5 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
@@ -18,13 +18,22 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
+import org.onosproject.net.NshServiceIndex;
+import org.onosproject.net.NshServicePathId;
import org.onosproject.net.behaviour.ExtensionSelectorResolver;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.ExtensionSelectorType;
import org.onosproject.openflow.controller.ExtensionSelectorInterpreter;
import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEncapEthType;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsi;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsp;
+import org.projectfloodlight.openflow.types.U16;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U8;
/**
* Interpreter for Nicira OpenFlow selector extensions.
@@ -53,17 +62,28 @@
if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) {
return true;
}
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE
+ .type())) {
+ return true;
+ }
return false;
}
@Override
public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) {
ExtensionSelectorType type = extensionSelector.type();
+
if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) {
- // TODO
+ NiciraMatchNshSpi niciraNshSpi = (NiciraMatchNshSpi) extensionSelector;
+ return factory.oxms().nsp(U32.of(niciraNshSpi.nshSpi().servicePathId()));
}
if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) {
- // TODO
+ NiciraMatchNshSi niciraNshSi = (NiciraMatchNshSi) extensionSelector;
+ return factory.oxms().nsi(U8.of(niciraNshSi.nshSi().serviceIndex()));
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE.type())) {
+ NiciraMatchEncapEthType niciraEncapEthType = (NiciraMatchEncapEthType) extensionSelector;
+ return factory.oxms().encapEthType(U16.of(niciraEncapEthType.encapEthType()));
}
if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) {
// TODO
@@ -82,6 +102,20 @@
@Override
public ExtensionSelector mapOxm(OFOxm<?> oxm) {
+
+ if (oxm.getMatchField() == MatchField.NSP) {
+ OFOxmNsp oxmField = (OFOxmNsp) oxm;
+ return new NiciraMatchNshSpi(NshServicePathId.of(oxmField.getValue().getRaw()));
+ }
+ if (oxm.getMatchField() == MatchField.NSI) {
+ OFOxmNsi oxmField = (OFOxmNsi) oxm;
+ return new NiciraMatchNshSi(NshServiceIndex.of(oxmField.getValue().getRaw()));
+ }
+ if (oxm.getMatchField() == MatchField.ENCAP_ETH_TYPE) {
+ OFOxmEncapEthType oxmField = (OFOxmEncapEthType) oxm;
+ return new NiciraMatchEncapEthType(oxmField.getValue().getRaw());
+ }
+
return null;
}
@@ -93,6 +127,9 @@
if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) {
return new NiciraMatchNshSi();
}
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE.type())) {
+ return new NiciraMatchEncapEthType();
+ }
if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())
|| type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())
|| type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
index 55f0c3e..3a0778e 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
@@ -16,9 +16,14 @@
package org.onosproject.driver.extensions;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
import org.onlab.packet.Ip4Address;
import org.onosproject.codec.CodecContext;
+import org.onosproject.net.NshContextHeader;
+import org.onosproject.net.NshServiceIndex;
+import org.onosproject.net.NshServicePathId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
@@ -32,13 +37,29 @@
import org.projectfloodlight.openflow.protocol.action.OFActionNicira;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraMove;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmit;
+import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmitTable;
import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEncapEthDst;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEncapEthSrc;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEncapEthType;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNshC1;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNshC2;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNshC3;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNshC4;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNshMdtype;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNshNp;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsi;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsp;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunGpeNp;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.U16;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U8;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.util.Tools.nullIsIllegal;
+import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Interpreter for Nicira OpenFlow treatment extensions.
@@ -52,8 +73,18 @@
private static final int SRC_ETH = 0x00000406;
private static final int SRC_IP = 0x00000e04;
+ private static final int NSH_C1 = 0x0001e604;
+ private static final int NSH_C2 = 0x0001e804;
+ private static final int NSH_C3 = 0x0001ea04;
+ private static final int NSH_C4 = 0x0001ec04;
+ private static final int TUN_IPV4_DST = 0x00014004;
+ private static final int TUN_ID = 0x12008;
+
private static final int SUB_TYPE_RESUBMIT = 1;
+ private static final int SUB_TYPE_RESUBMIT_TABLE = 14;
private static final int SUB_TYPE_MOVE = 6;
+ private static final int SUB_TYPE_PUSH_NSH = 38;
+ private static final int SUB_TYPE_POP_NSH = 39;
private static final String TUNNEL_DST = "tunnelDst";
private static final String RESUBMIT = "resubmit";
@@ -115,6 +146,59 @@
ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
return true;
}
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_MDTYPE.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_NP.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_SRC.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_DST.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_TYPE
+ .type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_PUSH_NSH.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_POP_NSH.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_TUN_GPE_NP.type())) {
+ return true;
+ }
+ if (extensionTreatmentType
+ .equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C1_TO_C1.type())) {
+ return true;
+ }
+ if (extensionTreatmentType
+ .equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_C2.type())) {
+ return true;
+ }
+ if (extensionTreatmentType
+ .equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C3_TO_C3.type())) {
+ return true;
+ }
+ if (extensionTreatmentType
+ .equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C4_TO_C4.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_TUN_ID_TO_TUN_ID
+ .type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_TUN_ID
+ .type())) {
+ return true;
+ }
return false;
}
@@ -136,10 +220,75 @@
return factory.actions().niciraResubmitTable((int) resubmitTable.inPort().toLong(),
resubmitTable.table());
}
+
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
+ NiciraSetNshSpi niciraNshSpi = (NiciraSetNshSpi) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nsp(U32.of(niciraNshSpi.nshSpi().servicePathId())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) {
+ NiciraSetNshSi niciraNshSi = (NiciraSetNshSi) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nsi(U8.of(niciraNshSi.nshSi().serviceIndex())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) {
+ NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nshC1(U32.of(niciraNshch.nshCh().nshContextHeader())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) {
+ NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nshC2(U32.of(niciraNshch.nshCh().nshContextHeader())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) {
+ NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nshC3(U32.of(niciraNshch.nshCh().nshContextHeader())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
+ NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nshC4(U32.of(niciraNshch.nshCh().nshContextHeader())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_MDTYPE.type())) {
+ NiciraNshMdType niciraNshMdType = (NiciraNshMdType) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nshMdtype(U8.of(niciraNshMdType.nshMdType())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_NP.type())) {
+ NiciraNshNp niciraNshNp = (NiciraNshNp) extensionTreatment;
+ return factory.actions().setField(factory.oxms().nshNp(U8.of(niciraNshNp.nshNp())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_SRC.type())) {
+ NiciraEncapEthSrc niciraEncapEthSrc = (NiciraEncapEthSrc) extensionTreatment;
+ return factory.actions().setField(factory.oxms().encapEthSrc(MacAddress.of(niciraEncapEthSrc.encapEthSrc()
+ .toBytes())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_DST.type())) {
+ NiciraEncapEthDst niciraEncapEthDst = (NiciraEncapEthDst) extensionTreatment;
+ return factory.actions().setField(factory.oxms().encapEthDst(MacAddress.of(niciraEncapEthDst.encapEthDst()
+ .toBytes())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_TYPE.type())) {
+ NiciraEncapEthType niciraEncapEthType = (NiciraEncapEthType) extensionTreatment;
+ return factory.actions().setField(factory.oxms().encapEthType(U16.of(niciraEncapEthType.encapEthType())));
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_PUSH_NSH.type())) {
+ return factory.actions().niciraPushNsh();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_POP_NSH.type())) {
+ return factory.actions().niciraPopNsh();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_TUN_GPE_NP.type())) {
+ NiciraTunGpeNp niciraTunGpeNp = (NiciraTunGpeNp) extensionTreatment;
+ return factory.actions().setField(factory.oxms().tunGpeNp(U8.of(niciraTunGpeNp.tunGpeNp())));
+ }
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())
|| type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())
|| type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
- || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C1_TO_C1.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_C2.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C3_TO_C3.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C4_TO_C4.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST
+ .type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_TUN_ID_TO_TUN_ID.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_TUN_ID.type())) {
MoveExtensionTreatment mov = (MoveExtensionTreatment) extensionTreatment;
OFActionNiciraMove.Builder action = factory.actions()
.buildNiciraMove();
@@ -162,6 +311,50 @@
case TUNNEL_IPV4_DST:
OFOxmTunnelIpv4Dst tunnelIpv4Dst = (OFOxmTunnelIpv4Dst) oxm;
return new NiciraSetTunnelDst(Ip4Address.valueOf(tunnelIpv4Dst.getValue().getInt()));
+ case NSP:
+ OFOxmNsp nsp = (OFOxmNsp) oxm;
+ return new NiciraSetNshSpi(NshServicePathId.of((nsp.getValue().getRaw())));
+ case NSI:
+ OFOxmNsi nsi = (OFOxmNsi) oxm;
+ return new NiciraSetNshSi(NshServiceIndex.of((nsi.getValue().getRaw())));
+ case NSH_C1:
+ OFOxmNshC1 nshC1 = (OFOxmNshC1) oxm;
+ return new NiciraSetNshContextHeader(NshContextHeader.of((nshC1.getValue().getRaw())),
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1
+ .type());
+ case NSH_C2:
+ OFOxmNshC2 nshC2 = (OFOxmNshC2) oxm;
+ return new NiciraSetNshContextHeader(NshContextHeader.of((nshC2.getValue().getRaw())),
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2
+ .type());
+ case NSH_C3:
+ OFOxmNshC3 nshC3 = (OFOxmNshC3) oxm;
+ return new NiciraSetNshContextHeader(NshContextHeader.of((nshC3.getValue().getRaw())),
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3
+ .type());
+ case NSH_C4:
+ OFOxmNshC4 nshC4 = (OFOxmNshC4) oxm;
+ return new NiciraSetNshContextHeader(NshContextHeader.of((nshC4.getValue().getRaw())),
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4
+ .type());
+ case NSH_MDTYPE:
+ OFOxmNshMdtype nshMdType = (OFOxmNshMdtype) oxm;
+ return new NiciraNshMdType((nshMdType.getValue().getRaw()));
+ case NSH_NP:
+ OFOxmNshNp nshNp = (OFOxmNshNp) oxm;
+ return new NiciraNshNp((nshNp.getValue().getRaw()));
+ case ENCAP_ETH_SRC:
+ OFOxmEncapEthSrc encapEthSrc = (OFOxmEncapEthSrc) oxm;
+ return new NiciraEncapEthSrc(org.onlab.packet.MacAddress.valueOf((encapEthSrc.getValue().getBytes())));
+ case ENCAP_ETH_DST:
+ OFOxmEncapEthDst encapEthDst = (OFOxmEncapEthDst) oxm;
+ return new NiciraEncapEthDst(org.onlab.packet.MacAddress.valueOf((encapEthDst.getValue().getBytes())));
+ case ENCAP_ETH_TYPE:
+ OFOxmEncapEthType encapEthType = (OFOxmEncapEthType) oxm;
+ return new NiciraEncapEthType((encapEthType.getValue().getRaw()));
+ case TUN_GPE_NP:
+ OFOxmTunGpeNp tunGpeNp = (OFOxmTunGpeNp) oxm;
+ return new NiciraTunGpeNp((tunGpeNp.getValue().getRaw()));
default:
throw new UnsupportedOperationException(
"Driver does not support extension type " + oxm.getMatchField().id);
@@ -188,14 +381,37 @@
case SRC_ARP_SPA:
return NiciraMoveTreatmentFactory
.createNiciraMovArpSpaToTpa();
+ case NSH_C1:
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC1ToC1();
+ case NSH_C2:
+ if (Long.valueOf(moveAction.getDst()).intValue() == TUN_ID) {
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC2ToTunId();
+ }
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC2ToC2();
+ case NSH_C3:
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC3ToC3();
+ case NSH_C4:
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC4ToC4();
+ case TUN_IPV4_DST:
+ return NiciraMoveTreatmentFactory.createNiciraMovTunDstToTunDst();
+ case TUN_ID:
+ return NiciraMoveTreatmentFactory.createNiciraMovTunIdToTunId();
default:
throw new UnsupportedOperationException("Driver does not support move from "
- + moveAction.getSrc() + " to "
- + moveAction.getDst());
+ + moveAction.getSrc() + " to " + moveAction.getDst() + "of length "
+ + moveAction.getNBits());
}
case SUB_TYPE_RESUBMIT:
OFActionNiciraResubmit resubmitAction = (OFActionNiciraResubmit) nicira;
return new NiciraResubmit(PortNumber.portNumber(resubmitAction.getInPort()));
+ case SUB_TYPE_PUSH_NSH:
+ return new NiciraPushNsh();
+ case SUB_TYPE_POP_NSH:
+ return new NiciraPopNsh();
+ case SUB_TYPE_RESUBMIT_TABLE:
+ OFActionNiciraResubmitTable resubmitTable = (OFActionNiciraResubmitTable) nicira;
+ return new NiciraResubmitTable(PortNumber.portNumber(resubmitTable.getInPort()),
+ resubmitTable.getTable());
default:
throw new UnsupportedOperationException("Driver does not support extension subtype "
+ nicira.getSubtype());
@@ -228,6 +444,27 @@
|| type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
return new NiciraSetNshContextHeader(type);
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_PUSH_NSH.type())) {
+ return new NiciraPushNsh();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_POP_NSH.type())) {
+ return new NiciraPopNsh();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_MDTYPE.type())) {
+ return new NiciraNshMdType();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_NP.type())) {
+ return new NiciraNshNp();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_SRC.type())) {
+ return new NiciraEncapEthSrc();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_DST.type())) {
+ return new NiciraEncapEthDst();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_ENCAP_ETH_TYPE.type())) {
+ return new NiciraEncapEthType();
+ }
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) {
return NiciraMoveTreatmentFactory.createNiciraMovArpShaToTha();
}
@@ -240,8 +477,32 @@
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
return NiciraMoveTreatmentFactory.createNiciraMovIpSrcToDst();
}
- throw new UnsupportedOperationException(
- "Driver does not support extension type " + type.toString());
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_TUN_GPE_NP.type())) {
+ return new NiciraTunGpeNp();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C1_TO_C1.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC1ToC1();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_C2.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC2ToC2();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C3_TO_C3.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC3ToC3();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C4_TO_C4.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC4ToC4();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST
+ .type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovTunDstToTunDst();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_TUN_ID_TO_TUN_ID.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovTunIdToTunId();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_TUN_ID.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovNshC2ToTunId();
+ }
+ throw new UnsupportedOperationException("Driver does not support extension type " + type.toString());
}
@Override
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchEncapEthType.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchEncapEthType.java
new file mode 100644
index 0000000..e0ae08a
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchEncapEthType.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira EncapEthType extension selector to set encapsulated eth type.
+ */
+public class NiciraMatchEncapEthType extends AbstractExtension implements ExtensionSelector {
+
+ private short encapEthType;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new nshEncapEthType selector.
+ */
+ NiciraMatchEncapEthType() {
+ encapEthType = (short) 0;
+ }
+
+ /**
+ * Creates a new nshEncapEthType selector with given eth type.
+ *
+ * @param encapEthType encapsulated ethernet type
+ */
+ public NiciraMatchEncapEthType(short encapEthType) {
+ this.encapEthType = encapEthType;
+ }
+
+ /**
+ * Gets the encapEthType.
+ *
+ * @return encapEthType
+ */
+ public short encapEthType() {
+ return encapEthType;
+ }
+
+ @Override
+ public ExtensionSelectorType type() {
+ return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ encapEthType = (short) (appKryo.deserialize(data));
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(encapEthType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(encapEthType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraMatchEncapEthType) {
+ NiciraMatchEncapEthType that = (NiciraMatchEncapEthType) obj;
+ return Objects.equals(encapEthType, that.encapEthType);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("encapEthType", encapEthType).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
index 2b861eb..57f6e8b 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
@@ -97,4 +97,88 @@
ExtensionTreatmentType.ExtensionTreatmentTypes
.NICIRA_MOV_IP_SRC_TO_DST.type());
}
+
+ public static ExtensionTreatment createNiciraMovNshC1ToC1() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcC1 = 0x0001e604;
+ int dstC1 = 0x0001e604;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcC1,
+ dstC1,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C1_TO_C1.type());
+ }
+
+ public static ExtensionTreatment createNiciraMovNshC2ToC2() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcC2 = 0x0001e804;
+ int dstC2 = 0x0001e804;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcC2,
+ dstC2,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C2_TO_C2.type());
+ }
+
+ public static ExtensionTreatment createNiciraMovNshC3ToC3() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcC3 = 0x0001ea04;
+ int dstC3 = 0x0001ea04;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcC3,
+ dstC3,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C3_TO_C3.type());
+ }
+
+ public static ExtensionTreatment createNiciraMovNshC4ToC4() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcC4 = 0x0001ec04;
+ int dstC4 = 0x0001ec04;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcC4,
+ dstC4,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C4_TO_C4.type());
+ }
+
+ public static ExtensionTreatment createNiciraMovTunDstToTunDst() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcTunIpv4Dst = 0x00014004;
+ int dstTunIpv4Dst = 0x00014004;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcTunIpv4Dst,
+ dstTunIpv4Dst,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_TUN_IPV4_DST_TO_TUN_IPV4_DST.type());
+ }
+
+ public static ExtensionTreatment createNiciraMovTunIdToTunId() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 64;
+ int srcTunId = 0x12008;
+ int dstTunId = 0x12008; // 0x80004c08;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcTunId,
+ dstTunId,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_TUN_ID_TO_TUN_ID.type());
+ }
+
+ public static ExtensionTreatment createNiciraMovNshC2ToTunId() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcC2 = 0x0001e804;
+ int dstTunId = 0x80004c08;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcC2,
+ dstTunId,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_NSH_C2_TO_TUN_ID.type());
+ }
}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNshMdType.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNshMdType.java
new file mode 100644
index 0000000..333e470
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNshMdType.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira nshMdType extension instruction.
+ */
+public class NiciraNshMdType extends AbstractExtension implements ExtensionTreatment {
+
+ private byte nshMdType;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new nshMdType instruction.
+ */
+ NiciraNshMdType() {
+ nshMdType = (byte) 0;
+ }
+
+ /**
+ * Creates a new nshMdType instruction with given nsh md type.
+ *
+ * @param nshMdType nsh md type
+ */
+ public NiciraNshMdType(byte nshMdType) {
+ this.nshMdType = nshMdType;
+ }
+
+ /**
+ * Gets the nsh md type.
+ *
+ * @return nshMdType
+ */
+ public byte nshMdType() {
+ return nshMdType;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_MDTYPE.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshMdType = (byte) (appKryo.deserialize(data));
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshMdType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nshMdType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraNshMdType) {
+ NiciraNshMdType that = (NiciraNshMdType) obj;
+ return Objects.equals(nshMdType, that.nshMdType);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("nshMdType", nshMdType).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNshNp.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNshNp.java
new file mode 100644
index 0000000..fc319c5
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNshNp.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira nshNp extension instruction to set next protocol value in nsh header.
+ */
+public class NiciraNshNp extends AbstractExtension implements ExtensionTreatment {
+
+ private byte nshNp;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new nshNp instruction.
+ */
+ NiciraNshNp() {
+ nshNp = (byte) 0;
+ }
+
+ /**
+ * Creates a new nshNp instruction with given nsh np.
+ *
+ * @param nshNp nsh next protocol value
+ */
+ public NiciraNshNp(byte nshNp) {
+ this.nshNp = nshNp;
+ }
+
+ /**
+ * Gets the nsh np.
+ *
+ * @return nshNp
+ */
+ public byte nshNp() {
+ return nshNp;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NSH_NP.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshNp = (byte) (appKryo.deserialize(data));
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshNp);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nshNp);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraNshNp) {
+ NiciraNshNp that = (NiciraNshNp) obj;
+ return Objects.equals(nshNp, that.nshNp);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("nshNp", nshNp).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraPopNsh.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraPopNsh.java
new file mode 100644
index 0000000..2e319f3
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraPopNsh.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+/**
+ * Nicira pop nsh extension instruction.
+ */
+public class NiciraPopNsh extends AbstractExtension implements ExtensionTreatment {
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new pop nsh instruction.
+ */
+ public NiciraPopNsh() {
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_POP_NSH.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(0);
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraPopNsh) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraPushNsh.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraPushNsh.java
new file mode 100644
index 0000000..8d3a96d
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraPushNsh.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+/**
+ * Nicira push nsh extension instruction.
+ */
+public class NiciraPushNsh extends AbstractExtension implements ExtensionTreatment {
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new push nsh instruction.
+ */
+ public NiciraPushNsh() {
+
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_PUSH_NSH.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(0);
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraPushNsh) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
index ebf2382..65ebf28 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
@@ -16,6 +16,7 @@
package org.onosproject.driver.extensions;
+import java.util.Map;
import java.util.Objects;
import org.onlab.util.KryoNamespace;
@@ -25,6 +26,7 @@
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.Maps;
/**
* Nicira set NSH Context header extension instruction.
@@ -74,12 +76,17 @@
@Override
public void deserialize(byte[] data) {
- nshCh = NshContextHeader.of(appKryo.deserialize(data));
+ Map<String, Object> values = appKryo.deserialize(data);
+ nshCh = (NshContextHeader) values.get("nshCh");
+ type = (ExtensionTreatmentType) values.get("type");
}
@Override
public byte[] serialize() {
- return appKryo.serialize(nshCh.nshContextHeader());
+ Map<String, Object> values = Maps.newHashMap();
+ values.put("nshCh", nshCh);
+ values.put("type", type);
+ return appKryo.serialize(values);
}
@Override
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraTunGpeNp.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraTunGpeNp.java
new file mode 100644
index 0000000..de15948
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraTunGpeNp.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira tunnel gpe next protocol extension instruction to tunGpeNp value.
+ */
+public class NiciraTunGpeNp extends AbstractExtension implements ExtensionTreatment {
+
+ private byte tunGpeNp;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new NiciraTunGpeNp instruction.
+ */
+ NiciraTunGpeNp() {
+ tunGpeNp = (byte) 0;
+ }
+
+ /**
+ * Creates a new NiciraTunGpeNp instruction with given value.
+ *
+ * @param tunGpeNp tunnel gpe next protocol value
+ */
+ public NiciraTunGpeNp(byte tunGpeNp) {
+ this.tunGpeNp = tunGpeNp;
+ }
+
+ /**
+ * Gets the tunGpeNp.
+ *
+ * @return tunGpeNp
+ */
+ public byte tunGpeNp() {
+ return tunGpeNp;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_TUN_GPE_NP.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ tunGpeNp = (byte) (appKryo.deserialize(data));
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(tunGpeNp);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(tunGpeNp);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraTunGpeNp) {
+ NiciraTunGpeNp that = (NiciraTunGpeNp) obj;
+ return Objects.equals(tunGpeNp, that.tunGpeNp);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("tunGpeNp", tunGpeNp).toString();
+ }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
index 74cb756..0120e7e 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
@@ -70,6 +70,8 @@
protected DeviceService deviceService;
private static final int TIME_OUT = 0;
private static final int CLASSIFIER_TABLE = 0;
+ private static final int ENCAP_OUTPUT_TABLE = 4;
+ private static final int TUN_SEND_TABLE = 7;
private static final int ARP_TABLE = 10;
private static final int DNAT_TABLE = 20;
private static final int L3FWD_TABLE = 30;
@@ -278,7 +280,23 @@
private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
log.debug("Processing versatile forwarding objective");
- return Collections.emptyList();
+ TrafficSelector selector = fwd.selector();
+ TrafficTreatment tb = fwd.treatment();
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority())
+ .forDevice(deviceId).withSelector(selector).withTreatment(tb).makeTemporary(TIME_OUT);
+ ruleBuilder.withPriority(fwd.priority());
+ if (fwd.priority() == 100) {
+ ruleBuilder.forTable(ENCAP_OUTPUT_TABLE);
+ } else if (fwd.priority() == 200) {
+ ruleBuilder.forTable(TUN_SEND_TABLE);
+ } else {
+ ruleBuilder.forTable(CLASSIFIER_TABLE);
+ }
+
+ if (fwd.permanent()) {
+ ruleBuilder.makePermanent();
+ }
+ return Collections.singletonList(ruleBuilder.build());
}
private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthDstTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthDstTest.java
new file mode 100644
index 0000000..971a700
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthDstTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraEncapEthDstTest class.
+ */
+public class NiciraEncapEthDstTest {
+
+ private final MacAddress mac1 = MacAddress.valueOf("fa:16:3e:da:45:23");
+ private final MacAddress mac2 = MacAddress.valueOf("fa:16:3e:f3:d1:fe");
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraEncapEthDst encapEthDst1 = new NiciraEncapEthDst(mac1);
+ final NiciraEncapEthDst sameAsEncapEthDst1 = new NiciraEncapEthDst(mac1);
+ final NiciraEncapEthDst encapEthDst2 = new NiciraEncapEthDst(mac2);
+
+ new EqualsTester().addEqualityGroup(encapEthDst1, sameAsEncapEthDst1).addEqualityGroup(encapEthDst2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraEncapEthDstTest object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraEncapEthDst encapEthDst1 = new NiciraEncapEthDst(mac1);
+ assertThat(encapEthDst1, is(notNullValue()));
+ assertThat(encapEthDst1.encapEthDst(), is(mac1));
+ }
+}
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthSrcTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthSrcTest.java
new file mode 100644
index 0000000..f54f8b2
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthSrcTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraEncapEthSrcTest class.
+ */
+public class NiciraEncapEthSrcTest {
+
+ private final MacAddress mac1 = MacAddress.valueOf("fa:16:3e:11:00:01");
+ private final MacAddress mac2 = MacAddress.valueOf("fa:16:3e:22:00:02");
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraEncapEthDst encapEthDst1 = new NiciraEncapEthDst(mac1);
+ final NiciraEncapEthDst sameAsEncapEthDst1 = new NiciraEncapEthDst(mac1);
+ final NiciraEncapEthDst encapEthDst2 = new NiciraEncapEthDst(mac2);
+
+ new EqualsTester().addEqualityGroup(encapEthDst1, sameAsEncapEthDst1).addEqualityGroup(encapEthDst2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraEncapEthSrcTest object.
+ */
+ @Test
+ public void testConstruction() {
+
+ final NiciraEncapEthDst encapEthDst1 = new NiciraEncapEthDst(mac1);
+ assertThat(encapEthDst1, is(notNullValue()));
+ assertThat(encapEthDst1.encapEthDst(), is(mac1));
+ }
+}
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthTypeTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthTypeTest.java
new file mode 100644
index 0000000..311c81c
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraEncapEthTypeTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraEncapEthType class.
+ */
+public class NiciraEncapEthTypeTest {
+ final short ethType1 = (short) 0x894f;
+ final short ethType2 = (short) 0x800;
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraEncapEthType encapEthType1 = new NiciraEncapEthType(ethType1);
+ final NiciraEncapEthType sameAsEncapEthType1 = new NiciraEncapEthType(ethType1);
+ final NiciraEncapEthType encapEthType2 = new NiciraEncapEthType(ethType2);
+
+ new EqualsTester().addEqualityGroup(encapEthType1, sameAsEncapEthType1).addEqualityGroup(encapEthType2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraEncapEthType object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraEncapEthType encapEthType = new NiciraEncapEthType(ethType1);
+ assertThat(encapEthType, is(notNullValue()));
+ assertThat(encapEthType.encapEthType(), is(ethType1));
+ }
+}
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraMatchEncapEthTypeTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraMatchEncapEthTypeTest.java
new file mode 100644
index 0000000..b4b38f8
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraMatchEncapEthTypeTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraMatchEncapEthType class.
+ */
+public class NiciraMatchEncapEthTypeTest {
+ final short ethType1 = (short) 0x894f;
+ final short ethType2 = (short) 0x800;
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraMatchEncapEthType encapEthType1 = new NiciraMatchEncapEthType(ethType1);
+ final NiciraMatchEncapEthType sameAsEncapEthType1 = new NiciraMatchEncapEthType(ethType1);
+ final NiciraMatchEncapEthType encapEthType2 = new NiciraMatchEncapEthType(ethType2);
+
+ new EqualsTester().addEqualityGroup(encapEthType1, sameAsEncapEthType1).addEqualityGroup(encapEthType2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraMatchEncapEthType object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraMatchEncapEthType encapEthType = new NiciraMatchEncapEthType(ethType1);
+ assertThat(encapEthType, is(notNullValue()));
+ assertThat(encapEthType.encapEthType(), is(ethType1));
+ }
+}
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraNshMdTypeTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraNshMdTypeTest.java
new file mode 100644
index 0000000..8c299bd
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraNshMdTypeTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraNshMdType class.
+ */
+public class NiciraNshMdTypeTest {
+ final byte mdType1 = (byte) 1;
+ final byte mdType2 = (byte) 2;
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraNshMdType nshMdType1 = new NiciraNshMdType(mdType1);
+ final NiciraNshMdType sameAsnshMdType1 = new NiciraNshMdType(mdType1);
+ final NiciraNshMdType nshMdType2 = new NiciraNshMdType(mdType2);
+
+ new EqualsTester().addEqualityGroup(nshMdType1, sameAsnshMdType1).addEqualityGroup(nshMdType2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraNshMdType object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraNshMdType nshMdType = new NiciraNshMdType(mdType1);
+ assertThat(nshMdType, is(notNullValue()));
+ assertThat(nshMdType.nshMdType(), is(mdType1));
+ }
+}
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraNshNpTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraNshNpTest.java
new file mode 100644
index 0000000..17ed7ae
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraNshNpTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraNshNp class.
+ */
+public class NiciraNshNpTest {
+ final byte np1 = (byte) 1;
+ final byte np2 = (byte) 4;
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraNshNp nshNp1 = new NiciraNshNp(np1);
+ final NiciraNshNp sameAsNshNp1 = new NiciraNshNp(np1);
+ final NiciraNshNp nshNp2 = new NiciraNshNp(np2);
+
+ new EqualsTester().addEqualityGroup(nshNp1, sameAsNshNp1).addEqualityGroup(nshNp2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraNshNp object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraNshNp nshNp1 = new NiciraNshNp(np1);
+ assertThat(nshNp1, is(notNullValue()));
+ assertThat(nshNp1.nshNp(), is(np1));
+ }
+}
diff --git a/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraTunGpeNpTest.java b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraTunGpeNpTest.java
new file mode 100644
index 0000000..259ebb5
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/extensions/NiciraTunGpeNpTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraTunGpeNp class.
+ */
+public class NiciraTunGpeNpTest {
+ final byte np1 = (byte) 1;
+ final byte np2 = (byte) 2;
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ final NiciraTunGpeNp tunGpeNp1 = new NiciraTunGpeNp(np1);
+ final NiciraTunGpeNp sameAsTunGpeNp1 = new NiciraTunGpeNp(np1);
+ final NiciraTunGpeNp tunGpeNp2 = new NiciraTunGpeNp(np2);
+
+ new EqualsTester().addEqualityGroup(tunGpeNp1, sameAsTunGpeNp1).addEqualityGroup(tunGpeNp2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraTunGpeNp object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraTunGpeNp tunGpeNp1 = new NiciraTunGpeNp(np1);
+ assertThat(tunGpeNp1, is(notNullValue()));
+ assertThat(tunGpeNp1.tunGpeNp(), is(np1));
+ }
+}
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
index 3ca0979..8c3cb92 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
@@ -511,6 +511,18 @@
builder.setUdpSrc(TpPort.tpPort(udpsrc.getValue().getPort()));
break;
case TUNNEL_IPV4_DST:
+ case NSP:
+ case NSI:
+ case NSH_C1:
+ case NSH_C2:
+ case NSH_C3:
+ case NSH_C4:
+ case NSH_MDTYPE:
+ case NSH_NP:
+ case ENCAP_ETH_SRC:
+ case ENCAP_ETH_DST:
+ case ENCAP_ETH_TYPE:
+ case TUN_GPE_NP:
if (treatmentInterpreter != null) {
try {
builder.extension(treatmentInterpreter.mapAction(action), deviceId);
@@ -900,6 +912,36 @@
ip = Ip4Address.valueOf(match.get(MatchField.ARP_TPA).getInt());
builder.matchArpTpa(ip);
break;
+ case NSP:
+ if (selectorInterpreter != null) {
+ try {
+ OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.NSP);
+ builder.extension(selectorInterpreter.mapOxm(oxm), deviceId);
+ } catch (UnsupportedOperationException e) {
+ log.debug(e.getMessage());
+ }
+ }
+ break;
+ case NSI:
+ if (selectorInterpreter != null) {
+ try {
+ OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.NSI);
+ builder.extension(selectorInterpreter.mapOxm(oxm), deviceId);
+ } catch (UnsupportedOperationException e) {
+ log.debug(e.getMessage());
+ }
+ }
+ break;
+ case ENCAP_ETH_TYPE:
+ if (selectorInterpreter != null) {
+ try {
+ OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.ENCAP_ETH_TYPE);
+ builder.extension(selectorInterpreter.mapOxm(oxm), deviceId);
+ } catch (UnsupportedOperationException e) {
+ log.debug(e.getMessage());
+ }
+ }
+ break;
case MPLS_TC:
default:
log.warn("Match type {} not yet implemented.", field.id);