/**
- * Copyright (c) 2014 Ericsson Inc. and others. All rights reserved.
- *
+ * Copyright (c) 2014 Ericsson Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
- *
*/
package org.opendaylight.sfc.l2renderer;
//
// Table 2, NextHop
//
- public void configureNextHopFlow(
- final String sffNodeName, final long sfpId, final String srcMac, final String dstMac, final boolean isAddFlow);
+ public void configureNextHopFlow(final String sffNodeName, final long sfpId, final String srcMac,
+ final String dstMac, final boolean isAddFlow);
public void configureGroupNextHopFlow(
final String sffNodeName, final long sfpId, final String srcMac, final long groupId, final String groupName, final boolean isAddFlow);
final String port,
final long pathId,
final boolean setDscp,
+ final boolean isLastHop,
final boolean isAddFlow);
public void configureVlanTransportEgressFlow(
final String port,
final long pathId,
final boolean setDscp,
+ final boolean isLastHop,
final boolean isAddFlow);
public void configureVxlanGpeTransportEgressFlow(
final long nshNsp,
final short nshNsi,
final String port,
+ final boolean isLastHop,
final boolean isAddFlow);
public void configureMplsTransportEgressFlow(
final String port,
final long pathId,
boolean setDscp,
+ final boolean isLastHop,
+ final boolean isAddFlow);
+
+ public void configureNshNscTransportEgressFlow(
+ String sffNodeName,
+ final long nshNsp,
+ final short nshNsi,
+ String switchPort,
final boolean isAddFlow);
//
public void configureTransportIngressTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
public void configurePathMapperTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
public void configureNextHopTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
- public void configureTransportEgressTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
+
+ public void configureTransportEgressTableMatchAny(final String sffNodeName, final boolean doDrop,
+ final boolean isAddFlow);
// group configuration
- public void configureGroup(final String sffNodeName, final String openflowNodeId, final String sfgName, final long sfgId, int groupType, List<GroupBucketInfo> bucketInfos, final boolean isAddGroup);
+ public void configureGroup(final String sffNodeName, final String openflowNodeId, final String sfgName,
+ final long sfgId, int groupType, List<GroupBucketInfo> bucketInfos, final boolean isAddGroup);
}
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Mpls;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.MplsBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
import org.opendaylight.yangtools.yang.binding.DataContainer;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
null,
sffGraph.getPathEgressDpl(entry.getPathId()),
entry.getPathId(),
- entry.getServiceIndex());
+ entry.getServiceIndex(),
+ true);
// Nothing else to be done for the egress tables
return;
sffDstIngressDpl,
dstHopIngressDpl,
entry.getPathId(),
- entry.getServiceIndex());
+ entry.getServiceIndex(),
+ false);
}
null,
sffGraph.getPathEgressDpl(entry.getPathId()),
entry.getPathId(),
- entry.getServiceIndex());
+ entry.getServiceIndex(),
+ true);
// Nothing else to be done for the egress tables
return;
sffDstIngressDpl,
dstHopIngressDpl,
entry.getPathId(),
- entry.getServiceIndex());
+ entry.getServiceIndex(),
+ false);
}
private void initializeSff(final String sffName, final long pathId) {
private void configureGroupNextHopFlow(final String sffName, SffDataPlaneLocator srcSffDpl, long groupId, String groupName,
final long pathId, final short serviceIndex) {
- DataPlaneLocator srcDpl = null;
+ //DataPlaneLocator srcDpl = null;
// currently support only mac
String srcMac = null;
if (srcSffDpl != null) {
- srcDpl = srcSffDpl.getDataPlaneLocator();
+ //srcDpl = srcSffDpl.getDataPlaneLocator();
srcMac = sfcL2ProviderUtils.getDplPortInfoMac(srcSffDpl);
}
String sffNodeName = sfcL2ProviderUtils.getSffOpenFlowNodeName(sffName, pathId);
this.sfcL2FlowProgrammer.configureGroupNextHopFlow(sffName, pathId, srcMac, groupId, groupName, addFlow);
}
- // TODO I think isSf can be removed from this one, and just pass true to the final signature
// Simple pass-through method that calculates the srcOfsPort
// and srcMac from the srcSffSfDict, and the dstMac from the dstDpl
private void configureSffTransportEgressFlow(final String sffName,
String srcMac = sfcL2ProviderUtils.getDictPortInfoMac(srcSffSfDict);
String dstMac = sfcL2ProviderUtils.getSfDplMac(dstSfDpl);
configureSffTransportEgressFlow(
- sffName, srcDpl, dstSfDpl, hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, true);
+ sffName, srcDpl, dstSfDpl, hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, true, false);
}
// Simple pass-through method that calculates the srcOfsPort
SffDataPlaneLocator dstDpl,
DataPlaneLocator hopDpl,
long pathId,
- short serviceIndex) {
+ short serviceIndex,
+ boolean isLastServiceIndex) {
String srcOfsPortStr = sfcL2ProviderUtils.getDplPortInfoPort(srcDpl);
if(srcOfsPortStr == null) {
throw new RuntimeException(
configureSffTransportEgressFlow(sffName,
srcDpl.getDataPlaneLocator(),
((dstDpl == null) ? null : dstDpl.getDataPlaneLocator()),
- hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, false);
+ hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, false, isLastServiceIndex);
}
// This version is only used by the previous 2 configureSffTransportEgressFlow() signatures
String dstMac,
long pathId,
short serviceIndex,
- boolean isSf) {
+ boolean isSf,
+ boolean isLastServiceIndex) {
if(hopDpl == null) {
throw new RuntimeException(
"configureSffTransportEgressFlow SFF [" + sffName + "] hopDpl is null");
Integer vlanTag = ((MacAddressLocator) hopLocatorType).getVlanId();
if(vlanTag == null) {
this.sfcL2FlowProgrammer.configureMacTransportEgressFlow(
- sffNodeName, srcMac, dstMac, srcOfsPort, pathId, isSf, this.addFlow);
+ sffNodeName, srcMac, dstMac, srcOfsPort, pathId, isSf, isLastServiceIndex, this.addFlow);
} else {
this.sfcL2FlowProgrammer.configureVlanTransportEgressFlow(
- sffNodeName, srcMac, dstMac, vlanTag, srcOfsPort, pathId, isSf, this.addFlow);
+ sffNodeName, srcMac, dstMac, vlanTag, srcOfsPort, pathId, isSf, isLastServiceIndex, this.addFlow);
}
} else if (implementedInterface.equals(Mpls.class)) {
// MPLS
long mplsLabel = ((MplsLocator) hopLocatorType).getMplsLabel();
this.sfcL2FlowProgrammer.configureMplsTransportEgressFlow(
- sffNodeName, srcMac, dstMac, mplsLabel, srcOfsPort, pathId, isSf, this.addFlow);
+ sffNodeName, srcMac, dstMac, mplsLabel, srcOfsPort, pathId, isSf, isLastServiceIndex, this.addFlow);
} else if (implementedInterface.equals(Ip.class)) {
//VxLAN-gpe, it is IP/UDP flow with VLAN tag
if (hopDpl.getTransport().equals(VxlanGpe.class)) {
long nsp = pathId;
short nsi = serviceIndex;
this.sfcL2FlowProgrammer.configureVxlanGpeTransportEgressFlow(
- sffNodeName, nsp, nsi, srcOfsPort, this.addFlow);
+ sffNodeName, nsp, nsi, srcOfsPort, isLastServiceIndex, this.addFlow);
+ if(isLastServiceIndex) {
+ this.sfcL2FlowProgrammer.configureNshNscTransportEgressFlow(
+ sffNodeName, nsp, nsi, OutputPortValues.INPORT.toString(), this.addFlow);
+ }
}
}
}
//
public void configureMacTransportEgressFlow(
final String sffNodeName, final String srcMac, final String dstMac,
- String port, final long pathId, boolean setDscp, final boolean isAddFlow) {
+ String port, final long pathId, boolean setDscp, final boolean isLastHop, final boolean isAddFlow) {
ConfigureTransportEgressThread configureEgressTransportThread =
- new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isAddFlow);
+ new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isLastHop, isAddFlow);
try {
threadPoolExecutorService.execute(configureEgressTransportThread);
} catch (Exception ex) {
public void configureVlanTransportEgressFlow(
final String sffNodeName, final String srcMac, final String dstMac,
- final int dstVlan, String port, final long pathId, boolean setDscp, final boolean isAddFlow) {
+ final int dstVlan, String port, final long pathId, boolean setDscp,
+ final boolean isLastHop, final boolean isAddFlow) {
ConfigureTransportEgressThread configureEgressTransportThread =
- new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isAddFlow);
+ new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isLastHop, isAddFlow);
configureEgressTransportThread.setDstVlan(dstVlan);
try {
threadPoolExecutorService.execute(configureEgressTransportThread);
}
public void configureVxlanGpeTransportEgressFlow(
- final String sffNodeName, final long nshNsp, final short nshNsi, String port, final boolean isAddFlow) {
+ final String sffNodeName, final long nshNsp, final short nshNsi, String port,
+ final boolean isLastHop, final boolean isAddFlow) {
ConfigureTransportEgressThread configureEgressTransportThread =
- new ConfigureTransportEgressThread(sffNodeName, null, null, port, nshNsp, false, isAddFlow);
+ new ConfigureTransportEgressThread(sffNodeName, null, null, port, nshNsp, false, isLastHop, isAddFlow);
configureEgressTransportThread.setNshNsp(nshNsp);
configureEgressTransportThread.setNshNsi(nshNsi);
try {
public void configureMplsTransportEgressFlow(
final String sffNodeName, final String srcMac, final String dstMac,
- final long mplsLabel, String port, final long pathId, boolean setDscp, final boolean isAddFlow) {
+ final long mplsLabel, String port, final long pathId, boolean setDscp,
+ final boolean isLastHop, final boolean isAddFlow) {
ConfigureTransportEgressThread configureEgressTransportThread =
- new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isAddFlow);
+ new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isLastHop, isAddFlow);
configureEgressTransportThread.setMplsLabel(mplsLabel);
try {
threadPoolExecutorService.execute(configureEgressTransportThread);
String port;
long pathId;
boolean setDscp;
+ boolean isLastHop;
boolean isAddFlow;
public ConfigureTransportEgressThread(
final String sffNodeName, String srcMac, String dstMac, String port,
- final long pathId, boolean setDscp, boolean isAddFlow) {
+ final long pathId, boolean setDscp, final boolean isLastHop, boolean isAddFlow) {
super();
this.sffNodeName = sffNodeName;
this.srcMac = srcMac;
this.port = port;
this.pathId = pathId;
this.setDscp = setDscp;
+ this.isLastHop = isLastHop;
this.isAddFlow = isAddFlow;
}
public void setDstVlan(final int dstVlan) { this.dstVlan = dstVlan; }
int flowPriority = FLOW_PRIORITY_TRANSPORT_EGRESS;
- int order = 0;
- List<Action> actionList = new ArrayList<Action>();
+ //
+ // Matches
MatchBuilder match = new MatchBuilder();
if (this.nshNsp >=0 && this.nshNsi >= 0) {
- // If its NSH, then we dont need the metadata
+ // If its NSH, then we dont need the metadata, match on Nsp/Nsi instead
SfcOpenflowUtils.addMatchNshNsp(match, this.nshNsp);
SfcOpenflowUtils.addMatchNshNsi(match, this.nshNsi);
- actionList.add(SfcOpenflowUtils.createActionNxMoveTunIdRegister(order++));
} else {
// Match on the metadata pathId
SfcOpenflowUtils.addMatchMetada(match, getMetadataSFP(this.pathId), METADATA_MASK_SFP_MATCH);
flowPriority -= 10;
}
- // Set the macSrc
+
+ //
+ // Actions
+ int order = 0;
+ List<Action> actionList = new ArrayList<Action>();
+
+ // Set the macSrc, if present
if(this.srcMac != null) {
actionList.add(SfcOpenflowUtils.createActionSetDlSrc(this.srcMac, order++));
}
+ // Nsh stuff, if present
+ if (this.nshNsp >=0 && this.nshNsi >= 0) {
+ Action mvNsc1;
+ Action mvNsc2;
+ if(this.isLastHop) {
+ // On the last hop Copy/Move Nsi, Nsp, Nsc1=>TunIpv4Dst, and Nsc2=>TunId (Vnid)
+ actionList.add(SfcOpenflowUtils.createActionNxMoveNsi(order++));
+ actionList.add(SfcOpenflowUtils.createActionNxMoveNsp(order++));
+ mvNsc1 = SfcOpenflowUtils.createActionNxMoveNsc1ToTunIpv4DstRegister(order++);
+ mvNsc2 = SfcOpenflowUtils.createActionNxMoveNsc2ToTunIdRegister(order++);
+ } else {
+ // If its not the last hop, Copy/Move Nsc1/Nsc2 to the next hop
+ mvNsc1 = SfcOpenflowUtils.createActionNxMoveNsc1(order++);
+ mvNsc2 = SfcOpenflowUtils.createActionNxMoveNsc2(order++);
+ }
+ actionList.add(SfcOpenflowUtils.createActionNxMoveTunIdRegister(order++));
+ actionList.add(mvNsc1);
+ actionList.add(mvNsc2);
+ }
+
// Optionally write the DSCP with the pathId
if(this.setDscp) {
// In order to set the IP DSCP, we need to match IPv4
}
}
+ // For NSH, Return the packet to INPORT if the NSH Nsc1 Register is not present (==0)
+ // If it is present, it will be handled in ConfigureTransportEgressFlowThread()
+ // This flow will have a higher priority than the flow created in ConfigureTransportEgressFlowThread()
+ public void configureNshNscTransportEgressFlow(final String sffNodeName, final long nshNsp, final short nshNsi,String port, final boolean isAddFlow) {
+ // This is the last table, cant set next table AND doDrop should be false
+ ConfigureNshNscTransportEgressFlowThread configureNshNscTransportEgressFlowThread =
+ new ConfigureNshNscTransportEgressFlowThread(sffNodeName, nshNsp, nshNsi, port, isAddFlow);
+ try {
+ threadPoolExecutorService.execute(configureNshNscTransportEgressFlowThread);
+ } catch (Exception ex) {
+ LOG.error(LOGSTR_THREAD_QUEUE_FULL, ex.toString());
+ }
+ }
+
+ private class ConfigureNshNscTransportEgressFlowThread implements Runnable {
+ private String sffNodeName;
+ private final long nshNsp;
+ private final short nshNsi;
+ private String port;
+ private boolean isAddFlow;
+
+ public ConfigureNshNscTransportEgressFlowThread(
+ final String sffNodeName, final long nshNsp, final short nshNsi,String port, final boolean isAddFlow) {
+ this.sffNodeName = sffNodeName;
+ this.nshNsp = nshNsp;
+ this.nshNsi = nshNsi;
+ this.port = port;
+ this.isAddFlow = isAddFlow;
+ }
+
+ @Override
+ public void run() {
+ try {
+ LOG.debug("SfcProviderSffFlowWriter.ConfigureNshNscTransportEgressFlowThread, sff [{}]", this.sffNodeName);
+
+
+ //
+ // Match any
+ MatchBuilder match = new MatchBuilder();
+ SfcOpenflowUtils.addMatchNshNsp(match, this.nshNsp);
+ SfcOpenflowUtils.addMatchNshNsi(match, this.nshNsi);
+ SfcOpenflowUtils.addMatchNshNsc1(match, 0l);
+
+ //
+ // Create the actions
+ int order = 0;
+ Action outPortBuilder = SfcOpenflowUtils.createActionOutPort(this.port, order++);
+
+ List<Action> actionList = new ArrayList<Action>();
+ actionList.add(outPortBuilder);
+
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+
+ // Put our Instruction in a list of Instructions
+ InstructionsBuilder isb = SfcOpenflowUtils.createInstructionsBuilder(ib);
+
+ //
+ // Create and configure the FlowBuilder
+ FlowBuilder transportIngressFlow =
+ SfcOpenflowUtils.createFlowBuilder(
+ TABLE_INDEX_TRANSPORT_EGRESS,
+ FLOW_PRIORITY_TRANSPORT_EGRESS+10,
+ "MatchAny",
+ match,
+ isb);
+
+ if (isAddFlow) {
+ writeFlowToConfig(sffNodeName, transportIngressFlow);
+ } else {
+ removeFlowFromConfig(sffNodeName, transportIngressFlow);
+ }
+ } catch (Exception e) {
+ LOG.error("ConfigureNshNscTransportEgressFlowThread writer caught an Exception: ", e);
+ }
+ }
+ }
+
+
@Override
public void configureGroup(String sffNodeName, String openflowNodeId, String sfgName, long sfgId, int groupType,
List<GroupBucketInfo> bucketInfos, boolean isAddGroup) {
// 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.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.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
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.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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nshc._1.grouping.NxmNxNshc1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsi.grouping.NxmNxNsiBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNshc1Key;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder;
public static void addMatchIpProtocol(MatchBuilder match, final short ipProtocol) {
IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
- ipMatch.setIpProtocol((short) ipProtocol);
+ ipMatch.setIpProtocol(ipProtocol);
match.setIpMatch(ipMatch.build());
}
match.setEthernetMatch(eth.build());
ProtocolMatchFieldsBuilder protomatch = new ProtocolMatchFieldsBuilder();
- protomatch.setMplsLabel((long) label);
+ protomatch.setMplsLabel(label);
match.setProtocolMatchFields(protomatch.build());
}
public static void addMatchNshNsp(MatchBuilder match, long nsp) {
NxAugMatchNodesNodeTableFlow am =
- new NxAugMatchNodesNodeTableFlowBuilder()
+ new NxAugMatchNodesNodeTableFlowBuilder()
.setNxmNxNsp(new NxmNxNspBuilder()
- .setValue(nsp)
- .build())
+ .setValue(nsp)
+ .build())
.build();
addExtension(match, NxmNxNspKey.class, am);
}
public static void addMatchNshNsi(MatchBuilder match, short nsi) {
NxAugMatchNodesNodeTableFlow am =
- new NxAugMatchNodesNodeTableFlowBuilder()
+ new NxAugMatchNodesNodeTableFlowBuilder()
.setNxmNxNsi(new NxmNxNsiBuilder()
- .setNsi(nsi)
- .build())
+ .setNsi(nsi)
+ .build())
.build();
addExtension(match, NxmNxNsiKey.class, am);
}
+ public static void addMatchNshNsc1(MatchBuilder match, long nsc) {
+ NxAugMatchNodesNodeTableFlow am =
+ new NxAugMatchNodesNodeTableFlowBuilder()
+ .setNxmNxNshc1(new NxmNxNshc1Builder()
+ .setValue(nsc)
+ .build())
+ .build();
+ addExtension(match, NxmNxNshc1Key.class, am);
+ }
+
//
// Create Action methods
}
}
- public static org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nxMoveRegAction(
+ public static org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
+ nxMoveRegAction(
SrcChoice srcChoice, DstChoice dstChoice, int endOffset, boolean groupBucket) {
NxRegMove r = new NxRegMoveBuilder()
.setSrc(new SrcBuilder()
return ab.build();
}
+ public static Action createActionNxMoveNsc1(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(nxMoveRegAction(
+ new SrcNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+ new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+ 31,
+ false));
+
+ return ab.build();
+ }
+
+ public static Action createActionNxMoveNsc2(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(nxMoveRegAction(
+ new SrcNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+ new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+ 31,
+ false));
+
+ return ab.build();
+ }
+
+ public static Action createActionNxMoveNsi(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(nxMoveRegAction(
+ new SrcNxNsiCaseBuilder().setNxNsiDst(Boolean.TRUE).build(),
+ new DstNxNsiCaseBuilder().setNxNsiDst(Boolean.TRUE).build(),
+ 7, // Service Index is 8 bits, moving bits 0-7
+ false));
+
+ return ab.build();
+ }
+
+ public static Action createActionNxMoveNsp(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(nxMoveRegAction(
+ new SrcNxNspCaseBuilder().setNxNspDst(Boolean.TRUE).build(),
+ new DstNxNspCaseBuilder().setNxNspDst(Boolean.TRUE).build(),
+ 23, // Service Index is 24 bits, moving bits 0-23
+ false));
+
+ return ab.build();
+ }
+
+ // Used by NSH to move one of the NSH Context registers (NSC) to
+ // the Tunnel Id (VNID) Register. This is for the RSP NSH egress tunnel.
+ // GBP will set the Tunnel ID (VNID) in NSC2 and pass it along the
+ // chain, and in the last SFF, we will use it to set the VNID
+ // This will only work with this patch: https://git.opendaylight.org/gerrit/#/c/19478
+ public static Action createActionNxMoveNsc2ToTunIdRegister(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(nxMoveRegAction(
+ new SrcNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+ new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+ 31,
+ false));
+
+ return ab.build();
+ }
+
+ // This will only work with this patch: https://git.opendaylight.org/gerrit/#/c/19478
+ public static Action createActionNxMoveNsc1ToTunIpv4DstRegister(int order) {
+ ActionBuilder ab = createActionBuilder(order);
+ ab.setAction(nxMoveRegAction(
+ new SrcNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+ new DstNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+ 31,
+ false));
+
+ return ab.build();
+ }
+
public static WriteMetadataCase createInstructionMetadata(int order, BigInteger metadataVal, BigInteger metadataMask) {
WriteMetadataBuilder wmb = new WriteMetadataBuilder();
wmb.setMetadata(metadataVal);
configureVlanTransportEgressFlowMethodIndex,
configureVxlanGpeTransportEgressFlowMethodIndex,
configureMplsTransportEgressFlowMethodIndex,
+ configureNshNscTransportEgressFlowMethodIndex,
configureTransportIngressTableMatchAnyMethodIndex,
configurePathMapperTableMatchAnyMethodIndex,
String port,
long pathId,
boolean setDscp,
+ final boolean isLastHop,
boolean isAddFlow) {
incrementMethodCalled(MethodIndeces.configureMacTransportEgressFlowMethodIndex);
}
String port,
long pathId,
boolean setDscp,
+ final boolean isLastHop,
boolean isAddFlow) {
incrementMethodCalled(MethodIndeces.configureVlanTransportEgressFlowMethodIndex);
}
long nshNsp,
short nshNsi,
String port,
+ final boolean isLastHop,
boolean isAddFlow) {
incrementMethodCalled(MethodIndeces.configureVxlanGpeTransportEgressFlowMethodIndex);
}
String port,
long pathId,
boolean setDscp,
+ final boolean isLastHop,
boolean isAddFlow) {
incrementMethodCalled(MethodIndeces.configureMplsTransportEgressFlowMethodIndex);
}
+ @Override
+ public void configureNshNscTransportEgressFlow(
+ String sffNodeName,
+ final long nshNsp,
+ final short nshNsi,
+ String switchPort,
+ final boolean isAddFlow) {
+ incrementMethodCalled(MethodIndeces.configureNshNscTransportEgressFlowMethodIndex);
+ }
+
//---------------------------------------------
//
// Match Any methods
}
private void assertMethodCallCount(SfcL2FlowProgrammerTestMoc.MethodIndeces methodIndex, int count) {
- LOG.info("assertMethodCallCount [{}] comparing [{}] to expected count [{}]", methodIndex, flowProgrammerTestMoc.getMethodCalledCount(methodIndex), count);
- assertTrue(flowProgrammerTestMoc.getMethodCalledCount(methodIndex) == count);
+ assertEquals(count, flowProgrammerTestMoc.getMethodCalledCount(methodIndex));
}
private void assertMatchAnyMethodsCalled() {
+ // Default values
+ assertMatchAnyMethodsCalled(2, 2, 2, 2);
+ }
+
+ private void assertMatchAnyMethodsCalled(
+ int transportIngressCount, int pathMapperCount, int nextHopCount, int transportEgressCount) {
// Each of these is called once per SFF, and there are 2 SFFs
assertMethodCallCount(
- SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportIngressTableMatchAnyMethodIndex, 2);
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportIngressTableMatchAnyMethodIndex,
+ transportIngressCount);
assertMethodCallCount(
- SfcL2FlowProgrammerTestMoc.MethodIndeces.configurePathMapperTableMatchAnyMethodIndex, 2);
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configurePathMapperTableMatchAnyMethodIndex,
+ pathMapperCount);
assertMethodCallCount(
- SfcL2FlowProgrammerTestMoc.MethodIndeces.configureNextHopTableMatchAnyMethodIndex, 2);
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureNextHopTableMatchAnyMethodIndex,
+ nextHopCount);
assertMethodCallCount(
- SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportEgressTableMatchAnyMethodIndex, 2);
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportEgressTableMatchAnyMethodIndex,
+ transportEgressCount);
}
@Before
sfcUtilsTestMock.resetCache();
}
+ // TODO tests to add:
+ // - An SFF with > 1 SF
+ // - An SF of type TCP Proxy
+
@Test
public void testVlanFlowCreation() {
LOG.info("SfcL2RspProcessorTest testVlanFlowCreation");
assertMethodCallCount(
SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeTransportEgressFlowMethodIndex, 4);
}
+
+ @Test
+ public void testNshOneHopFlowCreation() {
+ LOG.info("SfcL2RspProcessorTest testNshOneHopFlowCreation");
+
+ List<Class<? extends ServiceFunctionTypeIdentity>> sfOneHopTypes;
+ sfOneHopTypes = new ArrayList<Class<? extends ServiceFunctionTypeIdentity>>();
+ sfOneHopTypes.add(Firewall.class);
+
+ RenderedServicePath nshRsp = rspBuilder.createRspFromSfTypes(sfOneHopTypes, VxlanGpe.class);
+ this.sfcL2RspProcessor.processRenderedServicePath(nshRsp, true);
+
+ assertMatchAnyMethodsCalled(1, 1, 1, 1);
+ assertMethodCallCount(
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeTransportIngressFlowMethodIndex, 2);
+ assertMethodCallCount(
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpePathMapperFlowMethodIndex, 0);
+ assertMethodCallCount(
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeNextHopFlowMethodIndex, 1);
+ assertMethodCallCount(
+ SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeTransportEgressFlowMethodIndex, 2);
+ }
}