Phaneendra Manda

[ONOS-4612]Update SFC flows inline with the Official OVS NSH patch

Change-Id: I4635818ae94be8bd481331329250a119b39d294c
Showing 60 changed files with 3729 additions and 1207 deletions
/*
* 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);
}
/*
* 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());
}
}
}
/*
* 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;
......@@ -23,7 +23,7 @@ import org.onosproject.vtnrsc.PortChain;
/**
* Abstraction of an entity which installs flow classification rules in ovs.
*/
public interface FlowClassifierInstallerService {
public interface SfcFlowRuleInstallerService {
/**
* Install flow classifier.
......@@ -44,24 +44,24 @@ public interface FlowClassifierInstallerService {
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);
}
......
/*
* 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());
}
}
}
/*
* 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.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);
// selector.extension(encapEthTypeSelector, 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();
}
}
......@@ -20,8 +20,9 @@ import static org.slf4j.LoggerFactory.getLogger;
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.OutboundPacket;
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.TenantId;
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 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
@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 class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
@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 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
}
/**
* 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 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
// No need to process other packets received by controller.
return;
}
} else if (ethType == Ethernet.TYPE_IPV6) {
} else {
return;
}
......@@ -587,11 +544,11 @@ public class SfcManager implements SfcService {
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 @@ public class SfcManager implements SfcService {
}
// 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 @@ public class SfcManager implements SfcService {
* @param context packet context
* @param connectPoint connect point of first service function
*/
private void sendPacket(PacketContext context, ConnectPoint connectPoint) {
private void sendPacket(PacketContext context) {
ConnectPoint sourcePoint = context.inPacket().receivedFrom();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
context.inPacket().unparsed());
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 @@ public class SfcManager implements SfcService {
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;
}
}
......
/*
* 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
......@@ -18,48 +18,74 @@ package org.onosproject.sfc.installer.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 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.PortPairGroup;
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.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 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 @@ public class FlowClassifierInstallerImplTest {
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 @@ public class FlowClassifierInstallerImplTest {
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 @@ public class FlowClassifierInstallerImplTest {
return flowClassifier;
}
private VirtualPort createVirtualPort() {
private VirtualPort createVirtualPort(VirtualPortId id) {
Set<FixedIp> fixedIps;
Map<String, String> propertyMap;
Set<AllowedAddressPair> allowedAddressPairs;
......@@ -201,14 +247,13 @@ public class FlowClassifierInstallerImplTest {
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 @@ public class FlowClassifierInstallerImplTest {
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 class FlowClassifierInstallerImplTest {
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 @@ public class FlowClassifierInstallerImplTest {
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 @@ public class FlowClassifierInstallerImplTest {
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));
}
}
}
}
......
......@@ -23,6 +23,12 @@ import org.onosproject.net.flow.instructions.ExtensionPropertyException;
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 @@ public class MockExtensionSelector implements ExtensionSelector {
@Override
public ExtensionSelectorType type() {
return null;
return type;
}
}
\ No newline at end of file
......
......@@ -43,6 +43,6 @@ public class MockExtensionSelectorResolver implements ExtensionSelectorResolver
@Override
public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) {
return new MockExtensionSelector();
return new MockExtensionSelector(type);
}
}
\ No newline at end of file
......
......@@ -23,6 +23,12 @@ import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
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 @@ public class MockExtensionTreatment implements ExtensionTreatment {
@Override
public ExtensionTreatmentType type() {
return null;
return type;
}
}
\ No newline at end of file
......
......@@ -43,7 +43,7 @@ public class MockExtensionTreatmentResolver implements ExtensionTreatmentResolve
@Override
public ExtensionTreatment getExtensionInstruction(ExtensionTreatmentType type) {
return new MockExtensionTreatment();
return new MockExtensionTreatment(type);
}
}
\ No newline at end of file
......
/*
* 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;
}
}
......@@ -43,6 +43,20 @@ public final class VtnConfig {
{
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");
}
};
/**
......
......@@ -48,7 +48,7 @@ public final class DefaultFlowClassifier implements FlowClassifier {
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.
......
......@@ -22,7 +22,6 @@ import java.util.Iterator;
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 @@ public final class DefaultPortChain implements PortChain {
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 @@ public final class DefaultPortChain implements PortChain {
* @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 @@ public final class DefaultPortChain implements PortChain {
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 @@ public final class DefaultPortChain implements PortChain {
@Override
public List<PortPairGroupId> portPairGroups() {
return ImmutableList.copyOf(portPairGroupList);
return ImmutableList.copyOf(portPairGroupList);
}
@Override
......@@ -118,6 +134,11 @@ public final class DefaultPortChain implements PortChain {
}
@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 @@ public final class DefaultPortChain implements PortChain {
@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 @@ public final class DefaultPortChain implements PortChain {
}
@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 @@ public final class DefaultPortChain implements PortChain {
break;
}
}
return Optional.of(id);
return id;
}
@Override
......@@ -267,6 +288,7 @@ public final class DefaultPortChain implements PortChain {
private String description;
private List<PortPairGroupId> portPairGroupList;
private List<FlowClassifierId> flowClassifierList;
private PortChain portChain;
@Override
public Builder setId(PortChainId portChainId) {
......@@ -312,7 +334,7 @@ public final class DefaultPortChain implements PortChain {
checkNotNull(portPairGroupList, "Port pair groups cannot be null");
return new DefaultPortChain(portChainId, tenantId, name, description,
portPairGroupList, flowClassifierList);
portPairGroupList, flowClassifierList, portChain);
}
}
}
......
......@@ -95,6 +95,13 @@ public final class DefaultPortPairGroup implements PortPairGroup {
}
@Override
public void resetLoad() {
for (PortPairId portPairId : portPairList) {
portPairLoadMap.put(portPairId, new Integer(0));
}
}
@Override
public int getLoad(PortPairId portPairId) {
return portPairLoadMap.get(portPairId);
}
......
......@@ -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 @@ public interface PortChain {
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 @@ public interface PortChain {
* @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
......
......@@ -67,6 +67,11 @@ public interface PortPairGroup {
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
......
......@@ -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.Deactivate;
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.EventuallyConsistentMapListener;
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 @@ public class FlowClassifierManager extends AbstractListenerManager<FlowClassifie
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)
......
......@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
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.ReferenceCardinality;
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.EventuallyConsistentMapListener;
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 @@ public class PortChainManager extends AbstractListenerManager<PortChainEvent, Po
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 @@ public class PortChainManager extends AbstractListenerManager<PortChainEvent, Po
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 @@ public class PortChainManager extends AbstractListenerManager<PortChainEvent, Po
@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;
......
......@@ -38,6 +38,7 @@ import org.onosproject.vtnrsc.portpair.PortPairService;
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 @@ public class PortChainSfMapManager implements PortChainSfMapService {
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);
}
}
......
......@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
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.EventuallyConsistentMapListener;
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 @@ public class PortPairManager extends AbstractListenerManager<PortPairEvent, Port
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")
......
......@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
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.EventuallyConsistentMapListener;
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 @@ public class PortPairGroupManager extends AbstractListenerManager<PortPairGroupE
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()
......
/*
* 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;
}
}
/*
* 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();
}
}
......@@ -35,7 +35,9 @@ public class VtnWebApplication extends AbstractWebApplication {
PortPairWebResource.class,
FloatingIpWebResource.class,
RouterWebResource.class,
ClassifierWebResource.class);
ClassifierWebResource.class,
PortChainSfMapWebResource.class,
PortChainDeviceMapWebResource.class);
}
}
......
......@@ -80,8 +80,10 @@ public final class FlowClassifierCodec extends JsonCodec<FlowClassifier> {
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);
......
/*
* Copyright 2015-present Open Networking Laboratory
* Copyright 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.
......@@ -13,8 +13,32 @@
* 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;
/**
* SFC Service manager for interacting with SFC.
* Service function JSON codec.
*/
package org.onosproject.sfc.forwarder.impl;
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;
}
}
......
......@@ -25,6 +25,7 @@ import org.onosproject.vtnrsc.FlowClassifier;
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 @@ public class VtnCodecRegistrator {
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");
}
......
/*
* 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"));
}
}
......@@ -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.TenantId;
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 @@ public class PortChainResourceTest extends VtnResourceTest {
}
@Override
public Optional<LoadBalanceId> matchPath(List<PortPairId> path) {
public LoadBalanceId matchPath(List<PortPairId> path) {
return null;
}
......@@ -204,6 +205,11 @@ public class PortChainResourceTest extends VtnResourceTest {
public Set<LoadBalanceId> getLoadBalancePathMapKeys() {
return null;
}
@Override
public PortChain oldPortChain() {
return null;
}
}
/**
......
/*
* 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"));
}
}
......@@ -136,6 +136,10 @@ public class PortPairGroupResourceTest extends VtnResourceTest {
Objects.equals(this.portPairGroupId, portPairGroup.portPairGroupId()) &&
Objects.equals(this.tenantId, portPairGroup.tenantId());
}
@Override
public void resetLoad() {
}
}
/**
......
......@@ -38,6 +38,7 @@ public class ExtensionSelectorType {
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);
......
......@@ -38,15 +38,30 @@ public final class ExtensionTreatmentType {
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),
BMV2_ACTION(128);
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),
P4_BMV2_ACTION(128);
private ExtensionTreatmentType type;
......
......@@ -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.MastershipRole;
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 @@ public class DeviceServiceAdapter implements DeviceService {
@Override
public List<Port> getPorts(DeviceId deviceId) {
return Collections.emptyList();
return portList;
}
@Override
......
/*
* 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();
}
}
/*
* 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();
}
}
/*
* 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();
}
}
......@@ -18,13 +18,22 @@ package org.onosproject.driver.extensions;
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 @@ public class NiciraExtensionSelectorInterpreter
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 @@ public class NiciraExtensionSelectorInterpreter
@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 @@ public class NiciraExtensionSelectorInterpreter
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())
......
......@@ -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.OFActionExperimenter;
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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
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,51 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
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 +382,37 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
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 +445,27 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
|| 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 +478,32 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
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
......
/*
* 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();
}
}
......@@ -97,4 +97,88 @@ public final class NiciraMoveTreatmentFactory {
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());
}
}
......
/*
* 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();
}
}
/*
* 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();
}
}
/*
* 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;
}
}
/*
* 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;
}
}
......@@ -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.ExtensionTreatment;
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 @@ public class NiciraSetNshContextHeader extends AbstractExtension implements
@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
......
/*
* 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();
}
}
......@@ -70,6 +70,8 @@ public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
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 @@ public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
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) {
......
/*
* 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));
}
}
/*
* 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));
}
}
/*
* 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));
}
}
/*
* 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));
}
}
/*
* 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));
}
}
/*
* 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));
}
}
/*
* 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));
}
}
......@@ -511,6 +511,18 @@ public class FlowEntryBuilder {
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,37 @@ public class FlowEntryBuilder {
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);
......