leaf name {
type string;
}
+ leaf direction {
+ type enumeration {
+ enum ingress;
+ enum egress;
+ }
+ }
}
}
}
return;
}
- if (addDataObj.getBridges() != null) {
- for (Bridge bridge : addDataObj.getBridges().getBridge()) {
- provider.addClassifierRules(bridge, acl);
- }
- }
+ //if (addDataObj.getBridges() != null) {
+ // for (Bridge bridge : addDataObj.getBridges().getBridge()) {
+ provider.addClassifierRules(addDataObj.getBridges(), acl);
+ // }
+ //}
}
public InstanceIdentifier<Classifier> getClassifierIid() {
package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
* @param acl - Access list includes rules that need to be installed in a SFF.
*/
void addClassifierRules(Bridge bridge, Acl acl);
+ void addClassifierRules(Bridges bridges, Acl acl);
/**
* Method removes the OF rules corresponding to rules within ACL
import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
import java.util.List;
import java.util.StringTokenizer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.Bridges;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
* Open vSwitch OpenFlow 1.3 Networking Provider for Netvirt SFC
* @author Arun Yerra
*/
-public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
+public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider {
private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcOF13Provider.class);
private static final short TABLE_0_CLASSIFIER = 0;
- //private static final short TABLE_1_L2FORWARD = 30;
- //private static final short TABLE_2_L3FORWARD = 40;
private static final short TABLE_3_INGR_ACL = 50;
- public static final long REG_VALUE_FROM_LOCAL = 0x1L;
- public static final long REG_VALUE_FROM_REMOTE = 0x2L;
- public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
private volatile NodeCacheManager nodeCacheManager;
private volatile Southbound southbound;
private MdsalUtils mdsalUtils;
- private DataBroker dataBroker;
private SfcClassifier sfcClassifier;
// TBD:: Remove these constants after integrating with openstack.
*/
public NetvirtSfcOF13Provider(final DataBroker dataBroker) {
Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
- this.dataBroker = dataBroker;
mdsalUtils = new MdsalUtils(dataBroker);
this.setDependencies(null);
sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
@Override
public void addClassifierRules(Bridge bridge, Acl acl) {
- Preconditions.checkNotNull(bridge, "Input bridge cannot be NULL!");
+
+ }
+
+ @Override
+ public void addClassifierRules(Bridges bridges, Acl acl) {
+ Preconditions.checkNotNull(bridges, "Input bridge cannot be NULL!");
Preconditions.checkNotNull(acl, "Input accesslist cannot be NULL!");
- Node bridgeNode = getBridgeNode(bridge.getName());
- if (bridgeNode == null) {
- LOG.debug("bridge {} not yet configured. Skip processing !!", bridge.getName());
- return;
- }
+ //Node bridgeNode = getBridgeNode(bridge.getName());
+ //if (bridgeNode == null) {
+ // LOG.debug("bridge {} not yet configured. Skip processing !!", bridge.getName());
+ // return;
+ //}
// TODO: Find all nodes needing the classifier and add classifier to them
for (Ace ace : acl.getAccessListEntries().getAce()) {
- processAclEntry(ace, bridgeNode, true);
+ processAclEntry(ace, bridges, true);
}
}
- private void processAclEntry(Ace entry, Node srcNode, boolean write) {
+ private void processAclEntry(Ace entry, Bridges bridges, boolean write) {
Matches matches = entry.getMatches();
if (matches == null) {
LOG.warn("processAclEntry: matches not found");
}
RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
- LOG.debug("Processing ACL entry = {} on Node = {} sfcRedirect = {}", entry.getRuleName(),
- srcNode.getNodeId(), sfcRedirect);
+ LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
if (sfcRedirect == null) {
LOG.warn("processAClEntry: sfcRedirect is null");
return;
}
LOG.info("processAclEntry: RSP: {}", rsp);
-
- // Find the first Hop within an RSP.
- // The classifier flow needs to send all matched traffic to this first hop SFF.
List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
if (pathHopList.isEmpty()) {
LOG.warn("Service Path = {} has empty hops!!", sfpName);
return;
}
- RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
- .readRenderedServicePathFirstHop(new RspName(rspName));
+ for (Bridge bridge : bridges.getBridge()) {
+ if (bridge.getDirection().getIntValue() == 0) {
+ Node bridgeNode = getBridgeNode(bridge.getName());
+ if (bridgeNode == null) {
+ LOG.debug("processAclEntry: bridge {} not yet configured. Skip processing !!", bridge.getName());
+ continue;
+ }
- LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
- firstRspHop.getPort().getValue().intValue());
- long tunnelOfPort = southbound.getOFPort(srcNode, CLIENT_GPE_PORT_NAME);
- if (tunnelOfPort == 0L) {
- LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
- CLIENT_GPE_PORT_NAME, tunnelOfPort, srcNode);
- return;
- }
+ long tunnelOfPort = southbound.getOFPort(bridgeNode, CLIENT_GPE_PORT_NAME);
+ if (tunnelOfPort == 0L) {
+ LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
+ CLIENT_GPE_PORT_NAME, tunnelOfPort, bridgeNode);
+ return;
+ }
- long localOfPort = southbound.getOFPort(srcNode, CLIENT_PORT_NAME);
- if (localOfPort == 0L) {
- LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
- CLIENT_GPE_PORT_NAME, localOfPort, srcNode);
- return;
- }
+ long localOfPort = southbound.getOFPort(bridgeNode, CLIENT_PORT_NAME);
+ if (localOfPort == 0L) {
+ LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
+ CLIENT_GPE_PORT_NAME, localOfPort, bridgeNode);
+ return;
+ }
- NshUtils nshHeader = new NshUtils();
- // C1 is the normal overlay dest ip and c2 is the vnid
- // Hardcoded for now, netvirt integration will have those values
- nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
- nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
- nshHeader.setNshNsp(rsp.getPathId());
+ // Find the first Hop within an RSP.
+ // The classifier flow needs to send all matched traffic to this first hop SFF.
+ RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+ .readRenderedServicePathFirstHop(new RspName(rspName));
+
+ LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
+ firstRspHop.getPort().getValue().intValue());
+
+ NshUtils nshHeader = new NshUtils();
+ // C1 is the normal overlay dest ip and c2 is the vnid
+ // Hardcoded for now, netvirt integration will have those values
+ nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
+ nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
+ nshHeader.setNshNsp(rsp.getPathId());
+
+ RenderedServicePathHop firstHop = pathHopList.get(0);
+ nshHeader.setNshNsi(firstHop.getServiceIndex());
+ nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
+ nshHeader.setNshTunUdpPort(firstRspHop.getPort());
+ LOG.debug("The Nsh Header = {}", nshHeader);
+
+ handleLocalInPort(southbound.getDataPathId(bridgeNode), rsp.getPathId().toString(), localOfPort,
+ TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, matches, true);
+
+ handleSfcClassiferFlows(southbound.getDataPathId(bridgeNode), TABLE_3_INGR_ACL, entry.getRuleName(),
+ matches, nshHeader, tunnelOfPort, true);
+ } else {
+ Node bridgeNode = getBridgeNode(bridge.getName());
+ if (bridgeNode == null) {
+ LOG.debug("processAclEntry: bridge {} not yet configured. Skip processing !!", bridge.getName());
+ continue;
+ }
+
+ long tunnelOfPort = southbound.getOFPort(bridgeNode, SERVER_GPE_PORT_NAME);
+ if (tunnelOfPort == 0L) {
+ LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
+ CLIENT_GPE_PORT_NAME, tunnelOfPort, bridgeNode);
+ return;
+ }
+
+ long localOfPort = southbound.getOFPort(bridgeNode, SERVER_PORT_NAME);
+ if (localOfPort == 0L) {
+ LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
+ CLIENT_GPE_PORT_NAME, localOfPort, bridgeNode);
+ return;
+ }
+
+ RenderedServicePathHop lastRspHop = Iterables.getLast(rsp.getRenderedServicePathHop());
+
+ LOG.debug("programAclEntry: Last Hop #: {}, nsi: {}", lastRspHop.getHopNumber().intValue(),
+ lastRspHop.getServiceIndex().intValue() - 1);
- RenderedServicePathHop firstHop = pathHopList.get(0);
- nshHeader.setNshNsi(firstHop.getServiceIndex());
- nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
- nshHeader.setNshTunUdpPort(firstRspHop.getPort());
- LOG.debug("The Nsh Header = {}", nshHeader);
+ NshUtils nshHeader = new NshUtils();
+ nshHeader.setNshNsp(rsp.getPathId());
+ nshHeader.setNshNsi((short)(lastRspHop.getServiceIndex().intValue() - 1));
+ nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
+ LOG.debug("programAclEntry: The Nsh Header = {}", nshHeader);
- handleLocalInPort(southbound.getDataPathId(srcNode), rsp.getPathId().toString(), localOfPort,
- TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, true);
+ //handleLocalEgressPort(southbound.getDataPathId(bridgeNode), rsp.getPathId().toString(), localOfPort,
+ // TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, true);
+
+ handleEgressSfcClassiferFlows(southbound.getDataPathId(bridgeNode),
+ TABLE_0_CLASSIFIER, entry.getRuleName(), matches, nshHeader, tunnelOfPort, localOfPort, true);
+ }
+ }
+ }
+
+ private void handleLocalEgressPort(long dataPathId, String s, long localOfPort, short writeTable,
+ short gotoTable, boolean write) {
+
+ }
- handleSfcClassiferFlows(southbound.getDataPathId(srcNode), TABLE_3_INGR_ACL, entry.getRuleName(),
- matches, nshHeader, tunnelOfPort, true);
+ private void handleEgressSfcClassiferFlows(long dataPathId, short writeTable, String ruleName,
+ Matches matches, NshUtils nshHeader, long tunnelOfPort,
+ long outOfPort, boolean write) {
+ sfcClassifier.programEgressSfcClassiferFlows(dataPathId, writeTable, ruleName, matches, nshHeader,
+ tunnelOfPort, outOfPort, write);
}
private void handleSfcClassiferFlows(long dataPathId, short writeTable, String ruleName,
}
public void handleLocalInPort(long dpidLong, String segmentationId, Long inPort,
- short writeTable, short goToTableId, boolean write) {
- sfcClassifier.programLocalInPort(dpidLong, segmentationId, inPort, writeTable, goToTableId, write);
+ short writeTable, short goToTableId, Matches matches, boolean write) {
+ sfcClassifier.programLocalInPort(dpidLong, segmentationId, inPort, writeTable, goToTableId, matches, write);
}
private void setDependencies(ServiceReference serviceReference) {
import com.google.common.collect.Lists;
import java.math.BigInteger;
+import java.util.ArrayList;
import java.util.List;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public void programSfcClassiferFlows(Long dpidLong, short writeTable, String ruleName, Matches match,
NshUtils nshHeader, long tunnelOfPort, boolean write) {
String nodeName = OPENFLOW + dpidLong;
- NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
FlowBuilder flowBuilder = new FlowBuilder();
MatchBuilder matchBuilder = buildMatch(match);
List<Action> actionList = getNshAction(nshHeader);
ActionBuilder ab = new ActionBuilder();
- ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + tunnelOfPort)));
+ ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(tunnelOfPort, nodeName)));
ab.setOrder(actionList.size());
ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
}
}
+ public void programEgressSfcClassiferFlows(Long dpidLong, short writeTable, String ruleName,
+ Matches match, NshUtils nshHeader,
+ long tunnelOfPort, long outOfPort, boolean write) {
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
+ flowBuilder.setMatch(
+ MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshMetaC2())).build());
+ flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
+ flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
+
+ String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(writeTable);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+
+ if (write) {
+ List<Action> actionList = new ArrayList<>();
+ ActionBuilder ab = new ActionBuilder();
+
+ ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD).build(),
+ BigInteger.valueOf(REG_VALUE_FROM_REMOTE)));
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ actionList.add(ab.build());
+
+ ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(dpidLong, outOfPort)));
+ ab.setOrder(1);
+ ab.setKey(new ActionKey(1));
+ actionList.add(ab.build());
+
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ List<Instruction> instructions = new ArrayList<>();
+ instructions.add(ib.build());
+
+ InstructionsBuilder isb = new InstructionsBuilder();
+ isb.setInstruction(instructions);
+
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
private List<Action> getNshAction(NshUtils header) {
// Build the Actions to Add the NSH Header
org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
}
public void programLocalInPort(Long dpidLong, String segmentationId, Long inPort,
- short writeTable, short goToTableId, boolean write) {
+ short writeTable, short goToTableId, Matches match, boolean write) {
String nodeName = OPENFLOW + dpidLong;
- MatchBuilder matchBuilder = new MatchBuilder();
- NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(nodeName);
FlowBuilder flowBuilder = new FlowBuilder();
+ MatchBuilder matchBuilder = buildMatch(match);
+ flowBuilder.setMatch(matchBuilder.build());
flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
flowBuilder.setId(new FlowId(flowId));
}
}
-/*
- public InstructionsBuilder buildActions(String ruleName, Actions actions, String datapathId) {
- InstructionBuilder ib = new InstructionBuilder();
-
- if (actions.getPacketHandling() instanceof Deny) {
- InstructionUtils.createDropInstructions(ib);
- } else if (actions.getPacketHandling() instanceof Permit) {
- //Permit actPermit = (Permit) actions.getPacketHandling();
- } else {
- InstructionUtils.createDropInstructions(ib);
- }
-
- ib.setOrder(0);
- ib.setKey(new InstructionKey(0));
- // Instructions List Stores Individual Instructions
- List<Instruction> instructions = Lists.newArrayList();
- instructions.add(ib.build());
-
- // Call the InstructionBuilder Methods Containing Actions
- ib = this.getMutablePipelineInstructionBuilder();
- ib.setOrder(1);
- ib.setKey(new InstructionKey(1));
- instructions.add(ib.build());
-
- // Add InstructionBuilder to the Instruction(s)Builder List
- InstructionsBuilder isb = new InstructionsBuilder();
- isb.setInstruction(instructions);
- return isb;
- }*/
-
public MatchBuilder buildMatch(Matches matches) {
MatchBuilder matchBuilder = new MatchBuilder();
//AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion();
//MatchUtils.createSrcL3IPv4Match(matchBuilder, aceIpv4.getSourceIpv4Network());
//MatchUtils.createDstL3IPv4Match(matchBuilder, aceIpv4.getDestinationIpv4Network());
- //MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
+ MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
}
new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
}
+ LOG.info("buildMatch: {}", matchBuilder.build());
return matchBuilder;
}
protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}", flowBuilder.build(), nodeBuilder.build());
- mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder), nodeBuilder.build());
- mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
+ mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, FlowUtils.createNodePath(nodeBuilder),
+ nodeBuilder.build());
+ mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, FlowUtils.createFlowPath(flowBuilder, nodeBuilder),
flowBuilder.build());
}
- /*private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
- LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}",
- flowBuilder.build(), nodeBuilder.build());
- WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
- modification.put(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder),
- nodeBuilder.build(), true);
- modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
- flowBuilder.build(), true);
-
- CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
- try {
- commitFuture.get(); // TODO: Make it async (See bug 1362)
- LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
- } catch (Exception e) {
- LOG.error(e.getMessage(), e);
- modification.cancel();
- }
- }*/
-
protected void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
- mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
- }
-
- private NodeBuilder createNodeBuilder(String nodeId) {
- NodeBuilder builder = new NodeBuilder();
- builder.setId(new NodeId(nodeId));
- builder.setKey(new NodeKey(builder.getId()));
- return builder;
- }
-
- private static InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
- return InstanceIdentifier.builder(Nodes.class)
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
- nodeBuilder.getKey())
- .augmentation(FlowCapableNode.class)
- .child(Table.class, new TableKey(flowBuilder.getTableId()))
- .child(Flow.class, flowBuilder.getKey()).build();
- }
-
- private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
- createNodePath(NodeBuilder nodeBuilder) {
- return InstanceIdentifier.builder(Nodes.class)
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
- nodeBuilder.getKey()).build();
+ mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, FlowUtils.createFlowPath(flowBuilder, nodeBuilder));
}
}
<artifactId>openstack.net-virt-sfc-features-test</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>utils.mdsal-openflow</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>utils.mdsal-utils</artifactId>
import static org.junit.Assert.fail;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties;
import static org.ops4j.pax.exam.CoreOptions.vmOption;
+import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
+import static org.ops4j.pax.exam.MavenUtils.asInProject;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
-import java.io.IOException;
+import java.math.BigInteger;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
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.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.Nshc1CaseValue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
private Option[] getOtherOptions() {
return new Option[] {
+ wrappedBundle(
+ mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
+ .version(asInProject())
+ .type("jar")),
configureConsole().startLocalConsole(),
vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
- keepRuntimeFolder()
+ keepRuntimeFolder()
};
}
Thread.sleep(1000);
}
- SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
long datapathId = southbound.getDataPathId(bridgeNode);
- //sfcClassifier.programSfcClassiferFlows();
- sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
+
+ SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
+ //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
(long)10, (short)255, (long)4096, (long)4096);
MatchesBuilder matchesBuilder = aclUtils.createMatches(new MatchesBuilder(), 80);
- sfcClassifier.programSfcClassiferFlows(datapathId, (short)50, "test", matchesBuilder.build(),
+ sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
nshUtils, (long)2, true);
+ nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
+ //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
+ // nshUtils, (long)2, (long)3, true);
+
//try {
// System.in.read();
//} catch (IOException e) {
// e.printStackTrace();
//}
- Thread.sleep(15000);
+ /*NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+ FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0);
+ Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+ assertNotNull("Could not find flow in config", flow);
+ flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+ assertNotNull("Could not find flow in operational", flow);*/
+
+ MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
+ NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+ FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null,
+ nshUtils, (long) 2, matchBuilder);
+ Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+ assertNotNull("Could not find flow in config", flow);
+ flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+ assertNotNull("Could not find flow in operational", flow);
+
+ //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
+ //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2);
+ //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
+ //assertNotNull("Could not find flow in config", flow);
+ //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
+ //assertNotNull("Could not find flow in operational", flow);
+
+ LOG.info("***** Go look for flows *****");
+ Thread.sleep(30000);
assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
Thread.sleep(1000);
assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
Thread.sleep(1000);
assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
}
+
+ private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
+ String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(true);
+ flowBuilder.setBarrier(false);
+ flowBuilder.setTableId(writeTable);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ return flowBuilder;
+ }
+
+ public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match,
+ NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) {
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ flowBuilder.setMatch(matchBuilder.build());
+
+ String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setBarrier(true);
+ flowBuilder.setTableId(writeTable);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ return flowBuilder;
+ }
+
+ private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName,
+ NshUtils nshHeader, long tunnelOfPort) {
+ FlowBuilder flowBuilder = new FlowBuilder();
+
+ MatchBuilder matchBuilder = new MatchBuilder();
+ flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
+ flowBuilder.setMatch(
+ MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build());
+ flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
+ flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
+
+ String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
+ flowBuilder.setId(new FlowId(flowId));
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ flowBuilder.setStrict(true);
+ flowBuilder.setBarrier(false);
+ flowBuilder.setTableId(writeTable);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(flowId);
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ return flowBuilder;
+ }
+
+ private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
+ throws InterruptedException {
+ Flow flow = null;
+ for (int i = 0; i < 10; i++) {
+ flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
+ if (flow != null) {
+ LOG.info("flow({}): {}", store, flow);
+ break;
+ }
+ Thread.sleep(1000);
+ }
+ return flow;
+ }
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
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.packet.fields.rev150611.acl.transport.header.fields.DestinationPortRangeBuilder;
AceIpBuilder aceIpBuilder = new AceIpBuilder();
aceIpBuilder.setDestinationPortRange(destinationPortRangeBuilder.build());
+ aceIpBuilder.setProtocol((short)6);
+ aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
matchesBuilder.setAceType(aceIpBuilder.build());
return matchesBuilder;