Phaneendra Manda
Committed by Gerrit Code Review

[ONOS-3834] Install load balanced forwarding rules

Change-Id: I681d0b047feb332543307eac1a54ed20114993ef
......@@ -15,37 +15,48 @@
*/
package org.onosproject.sfc.forwarder;
import org.onosproject.net.flowobjective.Objective;
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.
* Abstraction of an entity which provides service function forwarder.
*/
public interface ServiceFunctionForwarderService {
/**
* Install Forwarding rule.
* Install forwarding rule.
*
* @param portChain port-chain
* @param nshSpi nsh spi
*/
@Deprecated
void installForwardingRule(PortChain portChain, NshServicePathId nshSpi);
/**
* Uninstall Forwarding rule.
* Uninstall forwarding rule.
*
* @param portChain port-chain
* @param nshSpi nsh spi
*/
@Deprecated
void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSpi);
/**
* Prepare forwarding object for Service Function.
* Install load balanced forwarding rules.
*
* @param portChain port-chain
* @param nshSpi nsh spi
* @param type forwarding objective operation type
* @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 prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSpi, Objective.Operation type);
void unInstallLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi);
}
......
......@@ -15,13 +15,17 @@
*/
package org.onosproject.sfc.forwarder.impl;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
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;
......@@ -46,8 +50,6 @@ 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.PortPairGroup;
import org.onosproject.vtnrsc.PortPairGroupId;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
......@@ -58,46 +60,25 @@ import org.onosproject.vtnrsc.service.VtnRscService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;
import java.util.List;
import java.util.ListIterator;
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;
/**
* Provides Service Function Forwarder implementation.
* Provides service function forwarder implementation.
*/
@Component(immediate = true)
@Service
public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DriverService driverService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private final Logger log = getLogger(getClass());
protected VirtualPortService virtualPortService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected VtnRscService vtnRscService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PortPairService portPairService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PortPairGroupService portPairGroupService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowClassifierService flowClassifierService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PortChainService portChainService;
private final Logger log = getLogger(getClass());
protected ApplicationId appId;
protected DriverService driverService;
protected FlowObjectiveService flowObjectiveService;
protected HostService hostService;
protected ApplicationId appId;
private static final String DRIVER_NAME = "onosfw";
private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
private static final String PORT_CHAIN_ID_NOT_NULL = "Port-Chain-Id cannot be null";
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";
private static final int NULL = 0;
/**
* Default constructor.
......@@ -108,129 +89,118 @@ public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderSer
/**
* Explicit constructor.
*
* @param appId Application id
* @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) {
checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
prepareServiceFunctionForwarder(portChain, nshSpi, Objective.Operation.ADD);
//TODO this method will be removed
}
@Override
public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
prepareServiceFunctionForwarder(portChain, nshSpi, Objective.Operation.REMOVE);
//TODO this method will be removed
}
@Override
public void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSpi,
Objective.Operation type) {
// Go through the port pair group list
List<PortPairGroupId> portPairGrpList = portChain.portPairGroups();
ListIterator<PortPairGroupId> listGrpIterator = portPairGrpList.listIterator();
// Get source port pair group
if (!listGrpIterator.hasNext()) {
return;
}
PortPairGroupId portPairGrpId = listGrpIterator.next();
PortPairGroup currentPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
// Get destination port pair group
if (!listGrpIterator.hasNext()) {
return;
}
portPairGrpId = listGrpIterator.next();
PortPairGroup nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
public void installLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi) {
checkNotNull(path, PATH_NOT_NULL);
processForwardingRule(path, nshSpi, Objective.Operation.ADD);
}
// push SFF to OVS
pushServiceFunctionForwarder(currentPortPairGroup, nextPortPairGroup, listGrpIterator, nshSpi, type);
@Override
public void unInstallLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi) {
checkNotNull(path, PATH_NOT_NULL);
processForwardingRule(path, nshSpi, Objective.Operation.REMOVE);
}
/**
* Push service-function-forwarder to OVS.
* Process the required forwarding rules for the given path.
*
* @param currentPortPairGroup current port-pair-group
* @param nextPortPairGroup next port-pair-group
* @param listGrpIterator pointer to port-pair-group list
* @param nshSpi nsh service path id
* @param type objective type
* @param path list of port pair ids
* @param nshSpi service path index
* @param type operation type ADD/REMOVE
*/
public void pushServiceFunctionForwarder(PortPairGroup currentPortPairGroup, PortPairGroup nextPortPairGroup,
ListIterator<PortPairGroupId> listGrpIterator, NshServicePathId nshSpi, Objective.Operation type) {
DeviceId deviceId = null;
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;
PortPairGroupId portPairGrpId = null;
// Travel from SF to SF.
do {
// Get the required information on port pairs from source port pair
// group
List<PortPairId> portPairList = currentPortPairGroup.portPairs();
ListIterator<PortPairId> portPLIterator = portPairList.listIterator();
if (!portPLIterator.hasNext()) {
break;
}
PortPairId portPairId = portPLIterator.next();
PortPair portPair = portPairService.getPortPair(portPairId);
currentDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
if (deviceId == null) {
deviceId = currentDeviceId;
}
currentDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(currentPortPair.egress()));
nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(nextPortPair.ingress()));
// pack traffic selector
TrafficSelector.Builder selector = packTrafficSelector(deviceId, portPair, nshSpi);
// Get the required information on port pairs from destination port
// pair group
portPairList = nextPortPairGroup.portPairs();
portPLIterator = portPairList.listIterator();
if (!portPLIterator.hasNext()) {
break;
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);
}
portPairId = portPLIterator.next();
portPair = portPairService.getPortPair(portPairId);
nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
// pack traffic treatment
TrafficTreatment.Builder treatment = packTrafficTreatment(currentDeviceId, nextDeviceId, portPair);
// Send SFF to OVS
sendServiceFunctionForwarder(selector, treatment, deviceId, type);
// Replace source port pair group with destination port pair group
// for moving to next SFF processing.
currentPortPairGroup = nextPortPairGroup;
if (!listGrpIterator.hasNext()) {
// Move to next service function
currentPortPair = nextPortPair;
if (!portPairListIterator.hasNext()) {
break;
}
portPairGrpId = listGrpIterator.next();
nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
nextPortPair = portPairService.getPortPair(portPairListIterator.next());
} while (true);
}
/**
* Pack Traffic selector.
* Pack traffic selector.
*
* @param deviceId device id
* @param portPair port-pair
* @param nshSpi nsh spi
* @return traffic treatment
* @param nshSpi nsh service path index
* @return traffic selector
*/
public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId, PortPair portPair, NshServicePathId nshSpi) {
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();
......@@ -252,29 +222,30 @@ public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderSer
}
/**
* Pack Traffic treatment.
* Pack traffic treatment.
*
* @param currentDeviceId current device id
* @param nextDeviceId next device id
* @param portPair port-pair
* @param portPair port pair
* @param isSameOvs whether the next port pair is in the same ovs
* @return traffic treatment
*/
public TrafficTreatment.Builder packTrafficTreatment(DeviceId currentDeviceId, DeviceId nextDeviceId,
PortPair portPair) {
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 (currentDeviceId.equals(nextDeviceId)) {
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;
......@@ -289,7 +260,9 @@ public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderSer
* @param type operation type
*/
public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
DeviceId deviceId, Objective.Operation type) {
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)) {
......
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.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