public void configureMplsTransportIngressFlow(final String sffNodeName, final boolean isAddFlow);
+ public void configureArpTransportIngressFlow(final String sffNodeName, final String mac, final boolean isAddFlow);
+
//
// Configure Table 1, Path Mapper
//
public void configureVxlanGpePathMapperFlow(final String sffNodeName, long nsp, short nsi, long pathId, final boolean isAddFlow);
+
//
// Table 2, NextHop
//
}
}
+ //ARP flows for TcpProxy type of SFFasd
+ ServiceFunction sf = sfcL2ProviderUtils.getServiceFunction(entry.getSf(), entry.getPathId());
+ if(sf.getType() == TcpProxy.class){
+ ServiceFunctionDictionary sffSfDict = sfcL2ProviderUtils.getSffSfDictionary(sffDst, entry.getSf());
+ String sffMac = sfcL2ProviderUtils.getDictPortInfoMac(sffSfDict);
+ // If the SF is a TCP Proxy, then we need to reply to the ARP Request messages
+ if (sffMac != null){
+ this.sfcL2FlowProgrammer.configureArpTransportIngressFlow(
+ sfcL2ProviderUtils.getSffOpenFlowNodeName(sffDstName, entry.getPathId()),
+ sffMac,
+ this.addFlow);
+ }
+ }
// Configure the Service Chain Ingress flow(s)
if(entry.getSrcSff().equals(SffGraph.INGRESS)) {
// configure the SFF Transport Ingress Flow using the dstHopIngressDpl
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
}
}
+ //Thread to create ARP flows
+ public void configureArpTransportIngressFlow(final String sffNodeName, final String mac, final boolean isAddFlow) {
+
+ ConfigureTransportArpIngressThread configureArpIngressTransportThread =
+ new ConfigureTransportArpIngressThread(sffNodeName, mac, isAddFlow);
+ try {
+ threadPoolExecutorService.execute(configureArpIngressTransportThread);
+ } catch (Exception ex) {
+ LOG.error(LOGSTR_THREAD_QUEUE_FULL, ex.toString());
+ }
+ }
+
+ private class ConfigureTransportArpIngressThread implements Runnable {
+ String sffNodeName;
+ String mac;
+ boolean isAddFlow;
+
+ public ConfigureTransportArpIngressThread(final String sffNodeName, final String mac, final boolean isAddFlow) {
+ this.sffNodeName = sffNodeName;
+ this.mac = mac;
+ this.isAddFlow = isAddFlow;
+ }
+
+ @Override
+ public void run() {
+ try {
+ LOG.info("SfcProviderSffFlowWriter.ConfigureTransportArpIngressThread, sff [{}] mac [{}]",
+ this.sffNodeName, this.mac);
+
+ // Create the matching criteria
+ MatchBuilder match = new MatchBuilder();
+ SfcOpenflowUtils.addMatchEtherType(match, SfcOpenflowUtils.ETHERTYPE_ARP);
+ SfcOpenflowUtils.addMatchArpRequest(match);
+
+ int order = 0;
+ List<Action> actionList = new ArrayList<Action>();
+ actionList.add(SfcOpenflowUtils.createActionNxMoveEthSrcToEthDstAction(order++));
+ actionList.add(SfcOpenflowUtils.createActionSetDlSrc(mac, order++));
+ actionList.add(SfcOpenflowUtils.createActionNxLoadArpOpAction(SfcOpenflowUtils.ARP_REPLY, order++));
+ actionList.add(SfcOpenflowUtils.createActionNxMoveArpShaToArpThaAction(order++));
+ actionList.add(SfcOpenflowUtils.createActionOutPort(OutputPortValues.INPORT.toString(), order++));
+
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ int ibOrder = 0;
+ InstructionBuilder actionsIb = new InstructionBuilder();
+ actionsIb.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ actionsIb.setKey(new InstructionKey(ibOrder));
+ actionsIb.setOrder(ibOrder++);
+
+ // Put our Instruction in a list of Instructions
+ InstructionsBuilder isb = SfcOpenflowUtils.createInstructionsBuilder(actionsIb);
+
+ // Create and configure the FlowBuilder
+ FlowBuilder transportIngressFlow =
+ SfcOpenflowUtils.createFlowBuilder(
+ TABLE_INDEX_INGRESS_TRANSPORT_TABLE,
+ FLOW_PRIORITY_TRANSPORT_INGRESS,
+ "ingress_Transport_Default_Flow",
+ match,
+ isb);
+
+ if (isAddFlow) {
+ writeFlowToConfig(sffNodeName, transportIngressFlow);
+ } else {
+ removeFlowFromConfig(sffNodeName, transportIngressFlow);
+ }
+ } catch (Exception e) {
+ LOG.error("ConfigureTransportArpIngress writer caught an Exception: ", e);
+ }
+ }
+ }
//
// Configure Table 1, PathMapper
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
// Import Nicira extension
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc2CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNsiCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNspCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpOpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.SrcChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNspCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc2CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNsiCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNspKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsp.grouping.NxmNxNspBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNsiKey;
public static final int ETHERTYPE_IPV4 = 0x0800;
public static final int ETHERTYPE_VLAN = 0x8100;
public static final int ETHERTYPE_MPLS_UCAST = 0x8847;
+ public static final int ETHERTYPE_ARP = 0x0806;
public static final short IP_PROTOCOL_TCP = (short) 6;
public static final short IP_PROTOCOL_UDP = (short) 17;
public static final int PKT_LENGTH_IP_HEADER = 20+14; // ether + IP header
public static final int TCP_FLAG_SYN = 0x0002;
+ public static final int ARP_REQUEST = 1;
+ public static final int ARP_REPLY = 2;
private static final int COOKIE_BIGINT_INT_RADIX = 10;
private static AtomicLong flowIdInc = new AtomicLong();
match.setVlanMatch(vlanMatchBuilder.build());
}
+ public static void addMatchArpRequest(MatchBuilder match){
+ ArpMatchBuilder arpmatch = new ArpMatchBuilder();
+ arpmatch.setArpOp(ARP_REQUEST);
+ match.setLayer3Match(arpmatch.build());
+ }
+
// If we call multiple Layer3 match methods, the MatchBuilder
// Ipv4Match object gets overwritten each time, when we actually
// want to set additional fields on the existing Ipv4Match object
return ab.build();
}
+ public static Action createActionNxLoadArpOpAction(int value, int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(
+ nxLoadRegAction(
+ new DstOfArpOpCaseBuilder().setOfArpOp(Boolean.TRUE).build(),
+ BigInteger.valueOf(value),
+ 15,
+ false));
+
+ return ab.build();
+ }
+
+ // Used for ARP to move the Source HW Address (Sha) to the Target HW address (Tha)
+ public static Action createActionNxMoveArpShaToArpThaAction(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(
+ nxMoveRegAction(
+ new SrcNxArpShaCaseBuilder().setNxArpSha(Boolean.TRUE).build(),
+ new DstNxArpThaCaseBuilder().setNxArpTha(Boolean.TRUE).build(),
+ 47,
+ false));
+
+ return ab.build();
+ }
+
+ public static Action createActionNxMoveEthSrcToEthDstAction(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(
+ nxMoveRegAction(
+ new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
+ new DstOfEthDstCaseBuilder().setOfEthDst(Boolean.TRUE).build(),
+ 47,
+ false));
+
+ return ab.build();
+ }
+
public static WriteMetadataCase createInstructionMetadata(int order, BigInteger metadataVal, BigInteger metadataMask) {
WriteMetadataBuilder wmb = new WriteMetadataBuilder();
wmb.setMetadata(metadataVal);
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.ServiceFunctionDictionary1Builder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.ServiceFunctionDictionary1;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.SffDataPlaneLocator1;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.SffDataPlaneLocator1Builder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.port.details.OfsPortBuilder;
public class RspBuilder {
private static int VLAN_BASE = 1;
private static int MPLS_BASE = 1;
private static int VXLAN_UDP_PORT = 6633;
+ private static String SWITCH_PORT_STR = "1";
private long RSP_PATHID_INDEX = 0;
private int SF_NAME_INDEX = 0;
dplBuilder.setTransport(transportType);
sffDplBuilder.setDataPlaneLocator(dplBuilder.build());
+ // Augment the SFF DPL if its not VxLan
+ if(!transportType.equals(VxlanGpe.class)) {
+
+ SffDataPlaneLocator1Builder ofsSffDplBuilder = new SffDataPlaneLocator1Builder();
+ OfsPortBuilder ofsPortBuilder = new OfsPortBuilder();
+ ofsPortBuilder.setMacAddress(new MacAddress(getNextMacAddress()));
+ ofsPortBuilder.setPortId(SWITCH_PORT_STR);
+ ofsSffDplBuilder.setOfsPort(ofsPortBuilder.build());
+ sffDplBuilder.addAugmentation(SffDataPlaneLocator1.class, ofsSffDplBuilder.build());
+ }
+
sffDpls.add(sffDplBuilder.build());
}
Class<? extends SlTransportType> sfTransportType =
(transportType.equals(VxlanGpe.class) ? transportType : Mac.class);
- // TODO this needs to be an augmented SFF-OFS DPL
SffSfDataPlaneLocatorBuilder sffSfDplBuilder = new SffSfDataPlaneLocatorBuilder();
// TODO the vlanId needs to be the same as on the SF
sffSfDplBuilder.setLocatorType(buildSfLocatorType(sfTransportType));
sfDictBuilder.setSffSfDataPlaneLocator(sffSfDplBuilder.build());
sfDictBuilder.setKey(new ServiceFunctionDictionaryKey(sf.getName()));
+ // Augment the dictionary with an OfsPortBuilder if its not VxLan
+ if(!transportType.equals(VxlanGpe.class)) {
+ ServiceFunctionDictionary1Builder ofsSfDictBuilder = new ServiceFunctionDictionary1Builder();
+ OfsPortBuilder ofsPortBuilder = new OfsPortBuilder();
+ ofsPortBuilder.setMacAddress(new MacAddress(getNextMacAddress()));
+ ofsPortBuilder.setPortId(SWITCH_PORT_STR);
+ ofsSfDictBuilder.setOfsPort(ofsPortBuilder.build());
+ sfDictBuilder.addAugmentation(ServiceFunctionDictionary1.class, ofsSfDictBuilder.build());
+ }
+
List<ServiceFunctionDictionary> sfDictList = new ArrayList<ServiceFunctionDictionary>();
sfDictList.add(sfDictBuilder.build());
+
return sfDictList;
}
configureVlanTransportIngressFlowMethodIndex,
configureVxlanGpeTransportIngressFlowMethodIndex,
configureMplsTransportIngressFlowMethodIndex,
+ configureArpTransportIngressFlowMethodIndex,
configureMacPathMapperFlowMethodIndex,
configureMplsPathMapperFlowMethodIndex,
String groupName, boolean isAddFlow) {
incrementMethodCalled(MethodIndeces.configureGroupNextHopFlow);
}
+
+ @Override
+ public void configureArpTransportIngressFlow(String sffNodeName,
+ String mac, boolean isAddFlow) {
+ incrementMethodCalled(MethodIndeces.configureArpTransportIngressFlowMethodIndex);
+ }
}
assertMatchAnyMethodsCalled();
assertMethodCallCount(
SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVlanTransportIngressFlowMethodIndex, 3);
+ assertMethodCallCount(
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureArpTransportIngressFlowMethodIndex, 2);
assertMethodCallCount(
SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVlanPathMapperFlowMethodIndex, 5);
assertMethodCallCount(