<Embed-Transitive>true</Embed-Transitive>
<Export-Package>
org.opendaylight.ovsdb.openstack.netvirt.providers,
- org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13
+ org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109
</Export-Package>
</instructions>
</configuration>
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "TableOffset_" + getTable();
FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable())
- .setPriority(0);
+ .setPriority(6);
MatchBuilder matchBuilder = new MatchBuilder();
flowBuilder.setMatch(matchBuilder.build());
container classifiers {
description "Classifier container which represents the ACL being applied,
- atachment point and the associated chain";
+ attachment point and the associated chain";
list classifier {
description "A list of SFC classifiers";
package org.opendaylight.ovsdb.openstack.netvirt.sfc;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
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;
void addClassifierRules(Acl acl);
void removeClassifierRules(Acl acl);
-
void setSfcClassifierService(ISfcClassifierService sfcClassifierService);
public void setDependencies(ServiceReference serviceReference);
+ void updateRsp(RenderedServicePath change);
+ void removeRsp(RenderedServicePath change);
}
private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcProvider.class);
private NetvirtSfcAclListener aclListener;
private NetvirtSfcClassifierListener classifierListener;
+ private RspListener rspListener;
public void setOf13Provider(String of13Provider) {
LOG.info("of13Provider is: {}", of13Provider);
}
aclListener = new NetvirtSfcAclListener(provider, dataBroker);
classifierListener = new NetvirtSfcClassifierListener(provider, dataBroker);
+ rspListener = new RspListener(provider, dataBroker);
addToPipeline(provider);
provider.setDependencies(null);
--- /dev/null
+/*
+ * Copyright © 2015 Red Hat, 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.ovsdb.openstack.netvirt.sfc;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Data tree listener for {@link RenderedServicePath}
+ */
+public class RspListener extends AbstractDataTreeListener<RenderedServicePath> {
+ private static final Logger LOG = LoggerFactory.getLogger(RspListener.class);
+
+ public RspListener(final INetvirtSfcOF13Provider provider, final DataBroker db) {
+ super(provider, RenderedServicePath.class);
+ Preconditions.checkNotNull(db, "DataBroker can not be null!");
+
+ registrationListener(db);
+ }
+
+ public InstanceIdentifier<RenderedServicePath> getRspIid() {
+ return InstanceIdentifier.create(RenderedServicePaths.class).child(RenderedServicePath.class);
+ }
+
+ private void registrationListener(final DataBroker db) {
+ final DataTreeIdentifier<RenderedServicePath> treeId =
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getRspIid());
+ try {
+ LOG.info("Registering Data Change Listener for NetvirtSfc RenderedServicePath configuration.");
+ ListenerRegistration<RspListener> listenerRegistration = db.registerDataTreeChangeListener(treeId, this);
+ } catch (final Exception e) {
+ LOG.warn("Netvirt RenderedServicePath DataChange listener registration failed!");
+ throw new IllegalStateException("NetvirtSfcAccessListListener startup failed! System needs restart.", e);
+ }
+ }
+
+ @Override
+ public void remove(InstanceIdentifier<RenderedServicePath> identifier, RenderedServicePath change) {
+ Preconditions.checkNotNull(change, "Object can not be null!");
+ LOG.debug("remove RenderedServicePath iid = {}, change = {}", identifier, change);
+ provider.removeRsp(change);
+ }
+
+ @Override
+ public void update(InstanceIdentifier<RenderedServicePath> identifier, RenderedServicePath original,
+ RenderedServicePath change) {
+ Preconditions.checkNotNull(change, "Object can not be null!");
+ LOG.debug("Update RenderedServicePath iid = {}, change = {}", identifier, change);
+ //provider.addClassifierRules(update);
+ }
+
+ @Override
+ public void add(InstanceIdentifier<RenderedServicePath> identifier, RenderedServicePath change) {
+ Preconditions.checkNotNull(change, "Object can not be null!");
+ LOG.debug("Add RenderedServicePath iid = {}, change = {}", identifier, change);
+ }
+
+ @Override
+ public void close() throws Exception {
+
+ }
+}
package org.opendaylight.ovsdb.openstack.netvirt.sfc;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.sfc.provider.api.SfcProviderAclAPI;
import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
+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.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntries;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.Ace;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+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;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
return rspFound;
}
- public ServiceFunctionPath getSfp(String redirectSfc) {
+ public ServiceFunctionPath getSfp(String sfcName) {
ServiceFunctionPath sfpFound = null;
ServiceFunctionPaths sfps = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
if (sfps != null) {
for (ServiceFunctionPath sfp: sfps.getServiceFunctionPath()) {
- if (sfp.getServiceChainName().getValue().equalsIgnoreCase(redirectSfc)) {
+ if (sfp.getServiceChainName().getValue().equalsIgnoreCase(sfcName)) {
sfpFound = sfp;
}
}
return sfpFound;
}
+ private AccessLists readAccessLists() {
+ InstanceIdentifier<AccessLists> path = InstanceIdentifier.create(AccessLists.class);
+ return mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
+ }
+
+ public Ace getAce(String name) {
+ Ace aceFound = null;
+ AccessLists accessLists = readAccessLists();
+ if (accessLists != null) {
+ List<Acl> acls = accessLists.getAcl();
+ if (acls != null) {
+ for (Acl acl :acls) {
+ AccessListEntries accessListEntries = acl.getAccessListEntries();
+ if (accessListEntries != null) {
+ List<Ace> aces = accessListEntries.getAce();
+ for (Ace ace : aces) {
+ RedirectToSfc sfcRedirect = ace.getActions().getAugmentation(RedirectToSfc.class);
+ if ((sfcRedirect != null && sfcRedirect.getRspName().equals(name)) ||
+ (sfcRedirect != null && sfcRedirect.getSfcName().equals(name)) ||
+ (sfcRedirect != null && sfcRedirect.getSfpName().equals(name))) {
+ aceFound = ace;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ LOG.info("getAce: {}", aceFound);
+ return aceFound;
+ }
+
public IpAddress getSfIpAddress(String sfname) {
ServiceFunction serviceFunction =
SfcProviderServiceFunctionAPI.readServiceFunction(SfName.getDefaultInstance(sfname));
nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
}
+
+ @Override
+ public void removeRsp(RenderedServicePath change) {
+
+ }
+ @Override
+ public void updateRsp(RenderedServicePath change) {
+
+ }
}
private void processAclEntry(Ace entry) {
Matches matches = entry.getMatches();
- Preconditions.checkNotNull(matches, "Input bridges cannot be NULL!");
+ Preconditions.checkNotNull(matches, "ACL Entry cannot be null!");
RenderedServicePath rsp = getRenderedServicePath(entry);
if (rsp == null) {
handleRenderedServicePath(rsp, entry);
}
- private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+ private void handleRenderedServicePath(RenderedServicePath rsp) {
LOG.info("handleRenderedServicePath: RSP: {}", rsp);
+ Ace entry = getAceFromRenderedServicePath(rsp);
+ if (entry == null) {
+ LOG.warn("handleRenderedServicePath: failed to get acl entry");
+ return;
+ }
+
+ handleRenderedServicePath(rsp, entry);
+ }
+
+ private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+ LOG.info("handleRenderedServicePath: RSP: {}, Ace: {}", rsp, entry);
Matches matches = entry.getMatches();
if (matches == null) {
if (hop == firstHop) {
LOG.info("handleSff: first hop processing {} - {}",
- bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+ bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
NshUtils nshHeader = new NshUtils();
nshHeader.setNshNsp(rsp.getPathId());
nshHeader.setNshNsi(firstHop.getServiceIndex());
if (isSffOnBridge(bridgeNode, serviceFunctionForwarder)) {
LOG.info("handleSff: sff and bridge are the same: {} - {}, skipping first sff",
- bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+ bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
Ip ip = sfcUtils.getSfIp(serviceFunction);
nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
nshHeader.setNshTunUdpPort(ip.getPort());
} else {
LOG.info("handleSff: sff and bridge are not the same: {} - {}, sending to first sff",
- bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+ bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
nshHeader.setNshTunUdpPort(ip.getPort());
nshHeader, vxGpeOfPort, true);
} else if (hop == lastHop) {
LOG.info("handleSff: last hop processing {} - {}",
- bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+ bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
String sfDplName = sfcUtils.getSfDplName(serviceFunction);
long sfOfPort = getSfPort(bridgeNode, sfDplName);
+ // TODO: Coexistence: SFC flows should take this using new egressTable REST
sfcClassifierService.programEgressClassifier(dataPathId, vxGpeOfPort, rsp.getPathId(),
lastServiceindex, sfOfPort, 0, true);
+ // TODO: Coexistence: This flow should like like one above, change port, add reg0=1, resubmit
sfcClassifierService.programEgressClassifierBypass(dataPathId, vxGpeOfPort, rsp.getPathId(),
lastServiceindex, sfOfPort, 0, true);
} else {
// add typical sff flows
}
- sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
+ // TODO: Coexistence: SFC flows should take this using new tableOffset REST
+ //sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
}
void handleSf(Node bridgeNode, ServiceFunction serviceFunction) {
if (isSfOnBridge(bridgeNode, serviceFunction)) {
LOG.info("handleSf: sf and bridge are on the same node: {} - {}, adding workaround and arp",
- bridgeNode.getNodeId(), serviceFunction.getName());
+ bridgeNode.getNodeId().getValue(), serviceFunction.getName().getValue());
long dataPathId = southbound.getDataPathId(bridgeNode);
Ip ip = sfcUtils.getSfIp(serviceFunction);
String sfIpAddr = String.valueOf(ip.getIp().getValue());
return;
}
//should be sffdplport, but they should all be the same 6633/4790
- sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
- sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
+ // TODO: Coexistence: SFC flows should take this using new sf dpl augmentation
+ //sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
+ //sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
} else {
LOG.info("handleSf: sf and bridge are not on the same node: {} - {}, do nothing",
- bridgeNode.getNodeId(), serviceFunction.getName());
+ bridgeNode.getNodeId().getValue(), serviceFunction.getName().getValue());
}
}
if (ovsdbNode != null) {
localIp = getLocalip(ovsdbNode);
}
+ LOG.info("isSffOnBridge: {}: {}, localIp: {}, sff ip: {}",
+ bridgeNode.getNodeId().getValue(),
+ localIp.equals(String.valueOf(ip.getIp().getValue())),
+ localIp, ip.getIp().getValue());
return localIp.equals(String.valueOf(ip.getIp().getValue()));
}
private String getLocalip(Node ovsdbNode) {
- Preconditions.checkNotNull("The ovsdbNode was null", ovsdbNode);
+ Preconditions.checkNotNull(ovsdbNode, "The ovsdbNode was null");
String localIp = null;
if (ovsdbNode != null) {
OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
String sfDplName = sfcUtils.getSfDplName(serviceFunction);
long sfOfPort = getSfPort(bridgeNode, sfDplName);
+ LOG.info("isSfOnBridge: {}: {}, sfOfPort: {}", bridgeNode.getNodeId().getValue(), sfOfPort != 0L, sfOfPort);
return sfOfPort != 0L;
}
+ private Ace getAceFromRenderedServicePath(RenderedServicePath rsp) {
+ Preconditions.checkNotNull(rsp, "RSP cannot be null");
+ Ace ace = null;
+ String rspName = rsp.getName().getValue();
+ String rspNameSuffix = "_rsp";
+ String sfcName = rspName.substring(0, rspName.length() - rspNameSuffix.length());
+ ace = sfcUtils.getAce(sfcName);
+
+ return ace;
+ }
+
private RenderedServicePath getRenderedServicePath (Ace entry) {
RenderedServicePath rsp = null;
RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
return mac;
}
+ @Override
+ public void removeRsp(RenderedServicePath change) {
+ LOG.info("removeRsp not implemented yet");
+ }
+
+ @Override
+ public void updateRsp(RenderedServicePath change) {
+ LOG.info("updateRsp not implemented yet");
+ }
+
@Override
public void setDependencies(ServiceReference serviceReference) {
nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
return new BigInteger(cookieString, 16);
}
+ private BigInteger getCookie(FlowID flowID, short nsp, short nsi) {
+ String cookieString = String.format("1110%02d%03d%03d0%03d", flowID.value, 0, nsp, nsi);
+ return new BigInteger(cookieString, 16);
+ }
+
public SfcClassifierService(Service service) {
super(service);
}
@Override
public void setDependencies(Object impl) {}
+ private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID) {
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
+ .setCookie(new FlowCookie(getCookie(flowID)))
+ .setCookieMask(new FlowCookie(getCookie(flowID)));
+ return flowBuilder;
+ }
+
+ private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID,
+ short nsp, short nsi) {
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
+ .setCookie(new FlowCookie(getCookie(flowID, nsp, nsi)))
+ .setCookieMask(new FlowCookie(getCookie(flowID, nsp, nsi)));
+ return flowBuilder;
+ }
+
@Override
public void programIngressClassifier(long dataPathId, String ruleName, Matches matches,
NshUtils nshHeader, long vxGpeOfPort, boolean write) {
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
+ initFlowBuilder(flowBuilder, flowName, getTable(), FlowID.FLOW_INGRESSCLASS,
+ (short)nshHeader.getNshNsp(), nshHeader.getNshNsi());
MatchBuilder matchBuilder = buildMatch(matches);
- MatchUtils.addNxRegMatch(matchBuilder,
- MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
MatchUtils.addNxRegMatch(matchBuilder,
MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
flowBuilder.setMatch(matchBuilder.build());
- String flowId = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setBarrier(true);
- flowBuilder.setTableId(getTable());
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_INGRESSCLASS)));
-
if (write) {
ActionBuilder ab = new ActionBuilder();
List<Action> actionList = new ArrayList<>();
public void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write) {
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "sfcTable_" + vxGpeOfPort;
+ initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER), FlowID.FLOW_SFCTABLE)
+ .setPriority(1000);
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
flowBuilder.setMatch(matchBuilder.build());
- String flowId = "sfcTable_" + vxGpeOfPort;
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setBarrier(true);
- flowBuilder.setTableId(getTable(Service.CLASSIFIER));
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- flowBuilder.setPriority(1000);
- flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
- flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
-
if (write) {
InstructionsBuilder isb = new InstructionsBuilder();
List<Instruction> instructions = Lists.newArrayList();
int tunnelOfPort, int tunnelId, short gotoTableId, boolean write) {
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "sfcEgressClass1_" + vxGpeOfPort;
+ initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER), FlowID.FLOW_EGRESSCLASSUNUSED,
+ (short)nsp, nsi);
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
MatchUtils.addNxNsiMatch(matchBuilder, nsi);
flowBuilder.setMatch(matchBuilder.build());
- String flowId = "sfcEgressClass1_" + vxGpeOfPort;
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setBarrier(true);
- flowBuilder.setTableId(getTable(Service.CLASSIFIER));
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
- flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
-
if (write) {
InstructionsBuilder isb = new InstructionsBuilder();
List<Instruction> instructions = Lists.newArrayList();
long sfOfPort, int tunnelId, boolean write) {
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
+ String flowName = "sfcEgressClass_" + nsp + "_" + + nsi + "_" + vxGpeOfPort;
+ initFlowBuilder(flowBuilder, flowName, getTable(Service.SFC_CLASSIFIER), FlowID.FLOW_EGRESSCLASS,
+ (short)nsp, nsi);
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
MatchUtils.addNxNsiMatch(matchBuilder, nsi);
flowBuilder.setMatch(matchBuilder.build());
- String flowId = "sfcEgressClass_" + nsp + "_" + + nsi + "_" + vxGpeOfPort;
- flowBuilder.setId(new FlowId(flowId));
- FlowKey key = new FlowKey(new FlowId(flowId));
- flowBuilder.setBarrier(true);
- flowBuilder.setTableId(getTable(Service.CLASSIFIER));
- flowBuilder.setKey(key);
- flowBuilder.setFlowName(flowId);
- flowBuilder.setHardTimeout(0);
- flowBuilder.setIdleTimeout(0);
- flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
- flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
-
if (write) {
InstructionsBuilder isb = new InstructionsBuilder();
List<Instruction> instructions = Lists.newArrayList();
ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
- ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, Service.CLASSIFIER.getTable()));
+ ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, getTable(Service.CLASSIFIER)));
ab.setOrder(actionList.size());
ab.setKey(new ActionKey(actionList.size()));
actionList.add(ab.build());
}
}
- private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID) {
- FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
- .setCookie(new FlowCookie(getCookie(flowID)))
- .setCookieMask(new FlowCookie(getCookie(flowID)));
- return flowBuilder;
- }
-
@Override
public void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
long sfOfPort, int tunnelId, boolean write) {
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "sfcEgressClassBypass_" + nsp + "_" + + nsi + "_" + sfOfPort;
- initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(),
- FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000);
+ initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER),
+ FlowID.FLOW_EGRESSCLASSBYPASS, (short)nsp, nsi)
+ .setPriority(40000);
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort);
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
FlowBuilder flowBuilder = new FlowBuilder();
String flowName = "ArpResponder_" + ipAddress;
- initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFARP).setPriority(1024);
+ initFlowBuilder(flowBuilder, flowName, getTable(Service.ARP_RESPONDER), FlowID.FLOW_SFARP)
+ .setPriority(1024);
MacAddress macAddress = new MacAddress(macAddressStr);
import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.NetvirtConfigUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionChainUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionForwarderUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionPathUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcConfigUtils;
import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
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.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SftType;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfig;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfigBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
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.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.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfigBuilder;
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 static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
private static ServiceFunctionChainUtils serviceFunctionChainUtils = new ServiceFunctionChainUtils();
private static ServiceFunctionPathUtils serviceFunctionPathUtils = new ServiceFunctionPathUtils();
+ private static SfcConfigUtils sfcConfigUtils = new SfcConfigUtils();
+ private static NetvirtConfigUtils netvirtConfigUtils = new NetvirtConfigUtils();
private static MdsalUtils mdsalUtils;
private static AtomicBoolean setup = new AtomicBoolean(false);
private static SouthboundUtils southboundUtils;
private static final String SF2NAME = "dpi-72";
private static final String SF1IP = "10.2.1.1";//"192.168.50.70";//"192.168.120.31";
private static final String SF2IP = "10.2.1.2";
- private static final String SF1DPLNAME = "sf1Dpl";
- private static final String SF2DPLNAME = "sf2Dpl";
- private static final String SFF1IP = "127.0.0.1"; //"192.168.1.129"
+ private static final String SF1DPLNAME = "sf1";
+ private static final String SF2DPLNAME = "sf2";
+ // Use 192.168.50.70 when running against vagrant vm for workaround testing
+ // "192.168.50.70"; "127.0.0.1"; "192.168.1.129";
+ private static final String SFF1IP = "192.168.1.129";
private static final String SFF2IP = "192.168.1.129";//"127.0.0.1";
private static final String SFF1NAME = "sff1";
private static final String SFF2NAME = "sff2";
//editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
// "log4j.logger.org.opendaylight.ovsdb",
// LogLevelOption.LogLevel.TRACE.name()),
+ editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+ "log4j.logger.org.opendaylight.ovsdb.library",
+ LogLevel.INFO.name()),
editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
logConfiguration(NetvirtSfcIT.class),
LogLevel.INFO.name()),
SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
"classifierName", ACLNAME, sffsBuilder);
- ClassifiersBuilder classifiersBuilder = classifierUtils.ClassifiersBuilder(new ClassifiersBuilder(),
+ ClassifiersBuilder classifiersBuilder = classifierUtils.classifiersBuilder(new ClassifiersBuilder(),
classifierBuilder);
LOG.info("Classifiers: {}", classifiersBuilder.build());
return classifiersBuilder;
return serviceFunctionPathsBuilder;
}
+ private SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder(short tableOffset, short egressTable) {
+ SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder =
+ sfcConfigUtils.sfcOfRendererConfigBuilder(new SfcOfRendererConfigBuilder(), tableOffset, egressTable);
+ LOG.info("SfcOfRendererConfig: {}", sfcOfRendererConfigBuilder.build());
+ return sfcOfRendererConfigBuilder;
+ }
+
+ private NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder(short tableOffset) {
+ NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder =
+ netvirtConfigUtils.netvirtProvidersConfigBuilder(new NetvirtProvidersConfigBuilder(), tableOffset);
+ LOG.info("NetvirtProvidersConfig: {}", netvirtProvidersConfigBuilder.build());
+ return netvirtProvidersConfigBuilder;
+ }
+
@Test
public void testSfcModel() throws InterruptedException {
int timeout = 1000;
String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable();
verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
+ readwait();
+
assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
Thread.sleep(1000);
assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
LOG.info("testNetvirtSfcAll: skipping test because userSpaceEnabled {}", userSpaceEnabled);
return;
}
+
+ short netvirtTableOffset = 1;
+ testModelPut(netvirtProvidersConfigBuilder(netvirtTableOffset), NetvirtProvidersConfig.class);
+ short sfcTableoffset = 150;
+ short egressTable = pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
+ testModelPut(sfcOfRendererConfigBuilder(sfcTableoffset, egressTable), SfcOfRendererConfig.class);
+
String bridgeName = INTEGRATION_BRIDGE_NAME;
ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
assertNotEquals("datapathId was not found", datapathId, 0);
- String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable();
+ String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
Map<String, String> externalIds = Maps.newHashMap();
externalIds.put("attached-mac", "f6:00:00:0f:00:01");
southboundUtils.addTerminationPoint(bridgeNode, SF1DPLNAME, "internal", null, externalIds);
+ externalIds.clear();
+ externalIds.put("attached-mac", "f6:00:00:0c:00:01");
southboundUtils.addTerminationPoint(bridgeNode, "vm1", "internal");
+ externalIds.clear();
+ externalIds.put("attached-mac", "f6:00:00:0c:00:02");
southboundUtils.addTerminationPoint(bridgeNode, "vm2", "internal");
- Map<String, String> options = Maps.newHashMap();
+ // SFC will add the SFF dpl port when creating the RSP
+ /*Map<String, String> options = Maps.newHashMap();
options.put("key", "flow");
options.put("dst_port", String.valueOf(GPEUDPPORT));
options.put("remote_ip", "flow");
options.clear();
options.put("key", "flow");
options.put("remote_ip", "192.168.120.32");
- southboundUtils.addTerminationPoint(bridgeNode, "vx", "vxlan", options, null);
- long vxGpeOfPort = getOFPort(bridgeNode, "vxgpe");
+ southboundUtils.addTerminationPoint(bridgeNode, "vx", "vxlan", options, null);*/
testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
testModelPut(accessListsBuilder(), AccessLists.class);
testModelPut(classifiersBuilder(), Classifiers.class);
+ long vxGpeOfPort = getOFPort(bridgeNode, "vxgpe");
+ assertNotEquals("vxGpePort was not found", 0, vxGpeOfPort);
+
readwait();
flowId = "sfcIngressClass_" + "httpRule";
verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
- flowId = "sfcTable_" + vxGpeOfPort;
- verifyFlow(datapathId, flowId, Service.CLASSIFIER);
- flowId = "sfEgress_" + GPEUDPPORT;
- verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
- flowId = "sfIngress_" + GPEUDPPORT + "_" + SF1IP;
- verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+ // SFC is adding these flows now
+ //flowId = "sfcTable_" + vxGpeOfPort;
+ //verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+ //flowId = "sfEgress_" + GPEUDPPORT;
+ //verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
+ //flowId = "sfIngress_" + GPEUDPPORT + "_" + SF1IP;
+ //verifyFlow(datapathId, flowId, Service.CLASSIFIER);
flowId = "ArpResponder_" + SF1IP;
- verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+ verifyFlow(datapathId, flowId, Service.ARP_RESPONDER);
+
+ readwait();
assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
Thread.sleep(1000);
assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
}
+ // Not used yet
+ private void getSffDplPort(String rspName) {
+ long ofPort = 0;
+ RenderedServicePathKey renderedServicePathKey =
+ new RenderedServicePathKey(RspName.getDefaultInstance(rspName));
+ InstanceIdentifier<RenderedServicePath> path =
+ InstanceIdentifier.create(RenderedServicePaths.class)
+ .child(RenderedServicePath.class, renderedServicePathKey);
+ RenderedServicePath rsp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
+ if (rsp == null) {
+ LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+ return;
+ }
+ List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+ if (pathHopList.isEmpty()) {
+ LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+ return;
+ }
+
+ for (RenderedServicePathHop hop : pathHopList) {
+ }
+ }
+
/**
* Test the standalone NetvirtSfc implementation
* NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
return flow;
}
- private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
+ private void verifyFlow(long datapathId, String flowId, short table) throws InterruptedException {
org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
FlowUtils.createNodeBuilder(datapathId);
FlowBuilder flowBuilder =
- FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, pipelineOrchestrator.getTable(service));
+ FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, table);
Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
- assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+ assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(),
+ flow);
+ }
+
+ private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
+ verifyFlow(datapathId, flowId, pipelineOrchestrator.getTable(service));
}
private void readwait() {
+/*
+ * Copyright © 2015 Red Hat, 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.ovsdb.openstack.netvirt.sfc.utils;
import java.util.List;
.setAcl(aclName);
}
- public ClassifiersBuilder ClassifiersBuilder(ClassifiersBuilder classifiersBuilder,
+ public ClassifiersBuilder classifiersBuilder(ClassifiersBuilder classifiersBuilder,
ClassifierBuilder classifierBuilder) {
List<Classifier> classifierList = new ArrayList<>();
classifierList.add(classifierBuilder.build());
--- /dev/null
+/*
+ * Copyright © 2015 Red Hat, 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.ovsdb.openstack.netvirt.sfc.utils;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfigBuilder;
+
+public class NetvirtConfigUtils {
+ public NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder(
+ NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder, short tableOffset) {
+ return netvirtProvidersConfigBuilder.setTableOffset(tableOffset);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2016 Red Hat, 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.ovsdb.openstack.netvirt.sfc.utils;
+
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfig;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfigBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SfcConfigUtils {
+ public SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder(SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder,
+ short tableOffset, short egressTable) {
+ return sfcOfRendererConfigBuilder
+ .setSfcOfTableOffset(tableOffset)
+ .setSfcOfAppEgressTableOffset(egressTable);
+ }
+
+ public InstanceIdentifier<SfcOfRendererConfig> getPath() {
+ return InstanceIdentifier.create(SfcOfRendererConfig.class);
+ }
+}