<classifier>features</classifier>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>openstack.net-virt-sfc-features</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
<dependency>
<groupId>org.opendaylight.sfc</groupId>
<artifactId>features-sfc</artifactId>
<repository>mvn:org.opendaylight.neutron/features-neutron/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.sfc/features-sfc/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.netvirt/features-netvirt/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.netvirt/openstack.net-virt-sfc-features/{{VERSION}}/xml/features</repository>
<feature name='odl-netvirt-openstack-sfc-translator' version='${project.version}'
description='OpenStack SFC to OpenDaylight SFC API data translator'>
<feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
<feature version="${neutron.version}">odl-neutron-service</feature>
<feature version='${sfc.version}'>odl-sfc-model</feature>
+ <feature version='${project.version}'>odl-ovsdb-sfc-api</feature>
<bundle>mvn:org.opendaylight.netvirt/utils.mdsal-utils/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.netvirt/openstack.sfc-translator-impl/{{VERSION}}</bundle>
</feature>
<feature version="${project.version}">odl-netvirt-openstack-sfc-translator</feature>
<feature version="${restconf.version}">odl-restconf</feature>
</feature>
- <feature name='odl-netvirt-openstack-sfc-translator-ui' version='${project.version}'
- description='OpenStack SFC to OpenDaylight SFC API data translator with dlux UI'>
- <feature version="${project.version}">odl-netvirt-openstack-sfc-translator-rest</feature>
- <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
- <feature version="${controller.mdsal.version}">odl-mdsal-xsql</feature>
- <feature version="${dlux.version}">odl-dlux-yangui</feature>
- </feature>
</features>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>openstack.net-virt-sfc-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>utils.mdsal-utils</artifactId>
/**
* Data-tree listener which delegates data processing to a {@link INeutronSfcDataProcessor}.
*/
-public class DelegatingDataTreeListener<T extends DataObject> implements AutoCloseable, DataTreeChangeListener<T> {
+public abstract class DelegatingDataTreeListener<T extends DataObject> implements AutoCloseable,
+ DataTreeChangeListener<T>,
+ INeutronSfcDataProcessor<T> {
private static final Logger LOG = LoggerFactory.getLogger(DelegatingDataTreeListener.class);
private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("NeutronSfcListener-%d").build();
private final INeutronSfcDataProcessor<T> dataProcessor;
private ListenerRegistration<DelegatingDataTreeListener<T>> listenerRegistration;
- public DelegatingDataTreeListener(INeutronSfcDataProcessor<T> dataProcessor,
- DataBroker db, DataTreeIdentifier<T> treeId) {
- this.dataProcessor = Preconditions.checkNotNull(dataProcessor, "Data processor can not be null!");
+ public DelegatingDataTreeListener(DataBroker db, DataTreeIdentifier<T> treeId) {
+ this.dataProcessor = Preconditions.checkNotNull(this, "Data processor can not be null!");
registerListener(Preconditions.checkNotNull(db, "Data broker can not be null!"),
Preconditions.checkNotNull(treeId, "Tree identifier can not be null!"));
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.SfcFlowClassifiers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifierKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortPairGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortPairs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPairKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
public class NeutronMdsalHelper {
private static final Logger LOG = LoggerFactory.getLogger(NeutronMdsalHelper.class);
- private static final InstanceIdentifier<Ports> portsPairIid =
+ private static final InstanceIdentifier<SfcFlowClassifiers> fcIid =
+ InstanceIdentifier.create(Neutron.class).child(SfcFlowClassifiers.class);
+ private static final InstanceIdentifier<Ports> portsIid =
InstanceIdentifier.create(Neutron.class).child(Ports.class);
-
+ private static final InstanceIdentifier<PortPairs> portPairsIid =
+ InstanceIdentifier.create(Neutron.class).child(PortPairs.class);
+ private static final InstanceIdentifier<PortPairGroups> portPairGroupsIid =
+ InstanceIdentifier.create(Neutron.class).child(PortPairGroups.class);
private final DataBroker dataBroker;
private final MdsalUtils mdsalUtils;
return neutronPort;
}
+ public PortPair getNeutronPortPair(Uuid portPairId) {
+ PortPair neutronPortPair
+ = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION , getNeutronPortPairPath(portPairId));
+ return neutronPortPair;
+ }
+
+ public PortPairGroup getNeutronPortPairGroup(Uuid portPairGroupId) {
+ PortPairGroup neutronPortPairGroup
+ = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION , getNeutronPortPairGroupPath(portPairGroupId));
+ return neutronPortPairGroup;
+ }
+
+ public SfcFlowClassifier getNeutronFlowClassifier(Uuid flowClassifierId) {
+ SfcFlowClassifier sfcFlowClassifier
+ = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION , getNeutronSfcFlowClassifierPath(flowClassifierId));
+ return sfcFlowClassifier;
+ }
+
private InstanceIdentifier<Port> getNeutronPortPath(Uuid portId) {
- return portsPairIid.builder().child(Port.class, new PortKey(portId)).build();
+ return portsIid.builder().child(Port.class, new PortKey(portId)).build();
+ }
+
+ private InstanceIdentifier<PortPair> getNeutronPortPairPath(Uuid portPairId) {
+ return portPairsIid.builder().child(PortPair.class, new PortPairKey(portPairId)).build();
+ }
+
+ private InstanceIdentifier<PortPairGroup> getNeutronPortPairGroupPath(Uuid portPairGroupId) {
+ return portPairGroupsIid.builder().child(PortPairGroup.class, new PortPairGroupKey(portPairGroupId)).build();
+ }
+
+ private InstanceIdentifier<SfcFlowClassifier> getNeutronSfcFlowClassifierPath(Uuid portId) {
+ return fcIid.builder().child(SfcFlowClassifier.class, new SfcFlowClassifierKey(portId)).build();
}
}
package org.opendaylight.netvirt.openstack.sfc.translator;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier.FlowClassifierTranslator;
-import org.opendaylight.netvirt.openstack.sfc.translator.portchain.PortChainTranslator;
-import org.opendaylight.netvirt.openstack.sfc.translator.portchain.PortPairGroupTranslator;
-import org.opendaylight.netvirt.openstack.sfc.translator.portchain.PortPairTranslator;
+import org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier.NeutronFlowClassifierListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.portchain.NeutronPortChainListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.portchain.NeutronPortPairGroupListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.portchain.NeutronPortPairListener;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.openstack.sfc.translator.config.rev160720.OpenstackSfcTranslatorConfig;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
private static final Logger LOG = LoggerFactory.getLogger(OpenStackSFCTranslatorProvider.class);
private final DataBroker dataBroker;
- private final BundleContext bundleContext;
- private final FlowClassifierTranslator flowClassifierTranslator;
- private final PortPairTranslator portPairTranslator;
- private final PortPairGroupTranslator portPairGroupTranslator;
- private final PortChainTranslator portChainTranslator;
+ private final RenderedServicePathService rspService;
+
public OpenStackSFCTranslatorProvider(
final DataBroker dataBroker,
+ final RenderedServicePathService rspService,
final OpenstackSfcTranslatorConfig openstackSfcTranslatorConfig,
final BundleContext bundleContext) {
this.dataBroker = dataBroker;
- this.bundleContext = bundleContext;
- flowClassifierTranslator = new FlowClassifierTranslator(dataBroker);
- portPairTranslator = new PortPairTranslator(dataBroker);
- portPairGroupTranslator = new PortPairGroupTranslator(dataBroker);
- portChainTranslator = new PortChainTranslator(dataBroker);
+ this.rspService = rspService;
}
//This method will be called by blueprint, during bundle initialization.
public void start() {
LOG.info("OpenStack SFC Translator Session started");
- flowClassifierTranslator.start();
- portPairTranslator.start();
- portPairGroupTranslator.start();
- portChainTranslator.start();
+ new NeutronFlowClassifierListener(dataBroker);
+ new NeutronPortPairListener(dataBroker);
+ new NeutronPortPairGroupListener(dataBroker);
+ new NeutronPortChainListener(dataBroker, rspService);
}
@Override
mdsalUtils = new MdsalUtils(this.dataBroker);
}
- public OvsdbPortMetadata getOvsdbPortMetadata(Uuid ingress) {
- LOG.info("Extract ovsdb port details for neutron port {}", ingress.getValue());
+ public Topology getOvsdbTopologyTree() {
+ LOG.info("Reading OVSDB Topolog Tree (ovsdb:1)");
+ return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
+ }
+
+ public OvsdbPortMetadata getOvsdbPortMetadata(Uuid ingressPort) {
+ LOG.info("Extract ovsdb port details for neutron port {}", ingressPort.getValue());
Topology ovsdbTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
+ return getOvsdbPortMetadata(ingressPort, ovsdbTopology);
+ }
+ public OvsdbPortMetadata getOvsdbPortMetadata(Uuid ingressPort, Topology ovsdbTopology) {
+ LOG.info("Extract ovsdb port details for neutron port {}", ingressPort.getValue());
OvsdbPortMetadata ovsdbPortMetadata = new OvsdbPortMetadata();
OvsdbBridgeAugmentation bridgeAugmentation = null;
if (ovsdbTopology != null) {
= tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
List<InterfaceExternalIds> externalIds = tpAugmentation.getInterfaceExternalIds();
for (InterfaceExternalIds externalId : externalIds) {
- if(externalId.getExternalIdValue().equals(ingress.getValue())) {
+ if(externalId.getExternalIdValue().equals(ingressPort.getValue())) {
ovsdbPortMetadata.setOvsdbPort(tpAugmentation);
break;
}
return ovsdbPortMetadata;
}
- public String getOvsdbPortName(OvsdbTerminationPointAugmentation ovsdbPort) {
+ public static String getOvsdbPortName(OvsdbTerminationPointAugmentation ovsdbPort) {
return ovsdbPort.getName();
}
- public String getNodeIpAddress(OvsdbNodeAugmentation ovsdbNode) {
+ public static String getNodeIpAddress(OvsdbNodeAugmentation ovsdbNode) {
//Currently we support only ipv4
return ovsdbNode.getConnectionInfo().getRemoteIp().getIpv4Address().getValue();
}
+
+ public static String getNodeKey(InstanceIdentifier<?> node) {
+ return node.firstKeyOf(Node.class).getNodeId().getValue();
+ }
}
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
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.service.functions.ServiceFunction;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainKey;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
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.sfp.rev140701.service.function.paths.ServiceFunctionPathKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
mdsalUtils = new MdsalUtils(this.dataBroker);
}
+ //ACL Flow Classifier data store utility methods
public void addAclFlowClassifier(Acl aclFlowClassifier) {
InstanceIdentifier<Acl> aclIid = getAclPath(aclFlowClassifier.getKey());
LOG.info("Write ACL FlowClassifier {} to config data store at {}",aclFlowClassifier, aclIid);
mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, aclIid);
}
+ //Service Function
public void addServiceFunction(ServiceFunction sf) {
InstanceIdentifier<ServiceFunction> sfIid = getSFPath(sf.getKey());
LOG.info("Write Service Function {} to config data store at {}",sf, sfIid);
return sfIid.builder().child(ServiceFunction.class, key).build();
}
- public SffName getExistingSFF(String ipAddress) {
+ private InstanceIdentifier<ServiceFunctionForwarder> getSFFPath(ServiceFunctionForwarderKey key) {
+ return sffIid.builder().child(ServiceFunctionForwarder.class, key).build();
+ }
+
+ private InstanceIdentifier<ServiceFunctionChain> getSFCPath(ServiceFunctionChainKey key) {
+ return sfcIid.builder().child(ServiceFunctionChain.class, key).build();
+ }
+
+ private InstanceIdentifier<ServiceFunctionPath> getSFPPath(ServiceFunctionPathKey key) {
+ return sfpIid.builder().child(ServiceFunctionPath.class, key).build();
+ }
+
+ public ServiceFunctionForwarder getExistingSFF(String ipAddress) {
ServiceFunctionForwarders existingSffs = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, sffIid);
if (existingSffs != null
&& existingSffs.getServiceFunctionForwarder() != null
List<ServiceFunctionForwarder> existingSffList = existingSffs.getServiceFunctionForwarder();
for (ServiceFunctionForwarder sff : existingSffList) {
if (sff.getIpMgmtAddress().getIpv4Address().equals(new Ipv4Address(ipAddress))) {
- return sff.getName();
+ return sff;
}
}
}
return null;
}
+
+ public void addServiceFunctionForwarder(ServiceFunctionForwarder sff) {
+ InstanceIdentifier<ServiceFunctionForwarder> sffIid = getSFFPath(sff.getKey());
+ LOG.info("Write Service Function Forwarder {} to config data store at {}",sff, sffIid);
+ mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, sffIid, sff);
+ }
+
+ public void addServiceFunctionChain(ServiceFunctionChain sfc) {
+ InstanceIdentifier<ServiceFunctionChain> sfcIid = getSFCPath(sfc.getKey());
+ LOG.info("Write Service Function Chain {} to config data store at {}",sfc, sfcIid);
+ mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, sfcIid, sfc);
+ }
+
+ public void removeServiceFunctionChain(ServiceFunctionChainKey sfcKey) {
+ InstanceIdentifier<ServiceFunctionChain> sfcIid = getSFCPath(sfcKey);
+ LOG.info("Remove Service Function Chain {} from config data store at {}",sfcKey, sfcIid);
+ mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, sfcIid);
+ }
+
+ public void addServiceFunctionPath(ServiceFunctionPath sfp) {
+ InstanceIdentifier<ServiceFunctionPath> sfpIid = getSFPPath(sfp.getKey());
+ LOG.info("Write Service Function Path {} to config data store at {}",sfp, sfpIid);
+ mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, sfpIid, sfp);
+ }
}
*/
package org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
-import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv6Acl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.ActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.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.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.AceIpVersion;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.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.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6Builder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRange;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.SourcePortRangeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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.acl.rev150105.RedirectToSfcBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.Closeable;
import java.util.ArrayList;
/**
* Class will convert OpenStack Flow Classifier API yang models to
* OpenDaylight ACL yang models.
*/
-public class FlowClassifierTranslator implements INeutronSfcDataProcessor<SfcFlowClassifier>{
+public class FlowClassifierTranslator {
private static final Logger LOG = LoggerFactory.getLogger(FlowClassifierTranslator.class);
private static final Short PROTO_TCP = 6;
private static final Short PROTO_UDP = 17;
private static final String RULE = "_rule";
- private final DataBroker db;
- private NeutronFlowClassifierListener neutronFlowClassifierListener;
- private final SfcMdsalHelper sfcMdsalHelper;
- private final NeutronMdsalHelper neutronMdsalHelper;
-
- public FlowClassifierTranslator(DataBroker db) {
- this.db = db;
- sfcMdsalHelper = new SfcMdsalHelper(db);
- neutronMdsalHelper = new NeutronMdsalHelper(db);
- }
-
- public void start() {
- LOG.info("Flow Classifier Translator Initialized.");
- if(neutronFlowClassifierListener == null) {
- neutronFlowClassifierListener = new NeutronFlowClassifierListener(db, this);
- }
- }
-
- /**
- * Method removes Acl respective to SfcFlowClassifier which is identified by InstanceIdentifier.
- *
- * @param path - the whole path to SfcFlowClassifier
- * @param deletedSfcFlowClassifier - SfcFlowClassifier for removing
- */
- @Override
- public void remove(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier deletedSfcFlowClassifier) {
- Acl aclFlowClassifier = buildAcl(deletedSfcFlowClassifier);
- sfcMdsalHelper.removeAclFlowClassifier(aclFlowClassifier);
- }
-
- /**
- * Method updates the original SfcFlowClassifier to the update SfcFlowClassifier.
- * Both are identified by same InstanceIdentifier.
- *
- * @param path - the whole path to SfcFlowClassifier
- * @param originalSfcFlowClassifier - original SfcFlowClassifier (for update)
- * @param updatedSfcFlowClassifier - changed SfcFlowClassifier (contain updates)
- */
- @Override
- public void update(InstanceIdentifier<SfcFlowClassifier> path,
- SfcFlowClassifier originalSfcFlowClassifier,
- SfcFlowClassifier updatedSfcFlowClassifier) {
-
- Acl aclFlowClassifier = buildAcl(updatedSfcFlowClassifier);
- sfcMdsalHelper.updateAclFlowClassifier(aclFlowClassifier);
- }
-
- /**
- * Method adds the SfcFlowClassifier which is identified by InstanceIdentifier
- * to device.
- *
- * @param path - the whole path to new SfcFlowClassifier
- * @param sfcFlowClassifier - new SfcFlowClassifier
- */
- @Override
- public void add(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier sfcFlowClassifier) {
- Acl aclFlowClassifier = buildAcl(sfcFlowClassifier);
- sfcMdsalHelper.addAclFlowClassifier(aclFlowClassifier);
+ public static Acl buildAcl(SfcFlowClassifier flowClassifier) {
+ return buildAcl(flowClassifier, null);
}
-
- private Acl buildAcl(SfcFlowClassifier flowClassifier) {
+ public static Acl buildAcl(SfcFlowClassifier flowClassifier, String rspName) {
LOG.info("OpenStack Networkgin SFC pushed Flow classfier : {}", flowClassifier);
AclBuilder aclBuilder = new AclBuilder();
AccessListEntriesBuilder accessListEntriesBuilder = new AccessListEntriesBuilder();
AceBuilder aceBuilder = new AceBuilder();
MatchesBuilder matchesBuilder = new MatchesBuilder();
+
+ ActionsBuilder actionsBuilder = new ActionsBuilder();
+ RedirectToSfcBuilder redirectToSfcBuilder = new RedirectToSfcBuilder();
+
AceIpBuilder aceIpBuilder = new AceIpBuilder();
DestinationPortRangeBuilder destinationPortRange = new DestinationPortRangeBuilder();
SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder();
matchesBuilder.setAceType(aceIpBuilder.build());
+ //Set redirect-to-rsp action if rsp name is provided
+ if (rspName != null) {
+ redirectToSfcBuilder.setRspName(rspName);
+ actionsBuilder.addAugmentation(RedirectToSfc.class, redirectToSfcBuilder.build());
+ aceBuilder.setActions(actionsBuilder.build());
+ }
aceBuilder.setMatches(matchesBuilder.build());
//OpenStack networking-sfc don't pass action information
import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.SfcFlowClassifiers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
private static final InstanceIdentifier<SfcFlowClassifier> flowClassifiersIid =
InstanceIdentifier.create(Neutron.class).child(SfcFlowClassifiers.class).child(SfcFlowClassifier.class);
- public NeutronFlowClassifierListener(DataBroker db, FlowClassifierTranslator flowClassifierTranslator) {
- super(flowClassifierTranslator, db,
- new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,flowClassifiersIid));
+ private final SfcMdsalHelper sfcMdsalHelper;
+
+ public NeutronFlowClassifierListener(DataBroker db) {
+ super(db, new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,flowClassifiersIid));
+ sfcMdsalHelper = new SfcMdsalHelper(db);
+
+ }
+
+ /**
+ * Method removes Acl respective to SfcFlowClassifier which is identified by InstanceIdentifier.
+ *
+ * @param path - the whole path to SfcFlowClassifier
+ * @param deletedSfcFlowClassifier - SfcFlowClassifier for removing
+ */
+ @Override
+ public void remove(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier deletedSfcFlowClassifier) {
+ Acl aclFlowClassifier = FlowClassifierTranslator.buildAcl(deletedSfcFlowClassifier);
+ sfcMdsalHelper.removeAclFlowClassifier(aclFlowClassifier);
+ }
+
+ /**
+ * Method updates the original SfcFlowClassifier to the update SfcFlowClassifier.
+ * Both are identified by same InstanceIdentifier.
+ *
+ * @param path - the whole path to SfcFlowClassifier
+ * @param originalSfcFlowClassifier - original SfcFlowClassifier (for update)
+ * @param updatedSfcFlowClassifier - changed SfcFlowClassifier (contain updates)
+ */
+ @Override
+ public void update(InstanceIdentifier<SfcFlowClassifier> path,
+ SfcFlowClassifier originalSfcFlowClassifier,
+ SfcFlowClassifier updatedSfcFlowClassifier) {
+
+ Acl aclFlowClassifier = FlowClassifierTranslator.buildAcl(updatedSfcFlowClassifier);
+ sfcMdsalHelper.updateAclFlowClassifier(aclFlowClassifier);
}
+
+ /**
+ * Method adds the SfcFlowClassifier which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param path - the whole path to new SfcFlowClassifier
+ * @param sfcFlowClassifier - new SfcFlowClassifier
+ */
+ @Override
+ public void add(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier sfcFlowClassifier) {
+ Acl aclFlowClassifier = FlowClassifierTranslator.buildAcl(sfcFlowClassifier);
+ sfcMdsalHelper.addAclFlowClassifier(aclFlowClassifier);
+ }
+
}
import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
+import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier.FlowClassifierTranslator;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService;
+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.sf.rev140701.service.functions.ServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+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.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortChains;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.chains.PortChain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
/**
* OpenDaylight Neutron Port Chain yang models data change listener
*/
public class NeutronPortChainListener extends DelegatingDataTreeListener<PortChain> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChainListener.class);
+
private static final InstanceIdentifier<PortChain> portChainIid =
InstanceIdentifier.create(Neutron.class).child(PortChains.class).child(PortChain.class);
+ private final SfcMdsalHelper sfcMdsalHelper;
+ private final NeutronMdsalHelper neutronMdsalHelper;
+ private final OvsdbMdsalHelper ovsdbMdsalHelper;
+ private final RenderedServicePathService rspService;
+
+ public NeutronPortChainListener(DataBroker db, RenderedServicePathService rspService) {
+ super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portChainIid));
+ sfcMdsalHelper = new SfcMdsalHelper(db);
+ neutronMdsalHelper = new NeutronMdsalHelper(db);
+ ovsdbMdsalHelper = new OvsdbMdsalHelper(db);
+ this.rspService = rspService;
+ }
+
+ /**
+ * Method removes PortChain which is identified by InstanceIdentifier.
+ *
+ * @param path - the whole path to PortChain
+ * @param deletedPortChain - PortChain for removing
+ */
+ @Override
+ public void remove(InstanceIdentifier<PortChain> path, PortChain deletedPortChain) {
+ sfcMdsalHelper.removeServiceFunctionChain(PortChainTranslator.getSFCKey(deletedPortChain));
+ }
+
+ /**
+ * Method updates the original PortChain to the update PortChain.
+ * Both are identified by same InstanceIdentifier.
+ *
+ * @param path - the whole path to PortChain
+ * @param originalPortChain - original PortChain (for update)
+ * @param updatePortChain - changed PortChain (contain updates)
+ */
+ @Override
+ public void update(InstanceIdentifier<PortChain> path, PortChain originalPortChain, PortChain updatePortChain) {
+ //TODO: Add support for chain update
+ }
+
+ /**
+ * Method adds the PortChain which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param path - the whole path to new PortChain
+ * @param newPortChain - new PortChain
+ */
+ @Override
+ public void add(InstanceIdentifier<PortChain> path, PortChain newPortChain) {
+ processPortChain(newPortChain);
+ }
+
+ private void processPortChain(PortChain newPortChain) {
+ //List of Port Pair Group attached to the Port Chain
+ List<PortPairGroup> portPairGroupList = new ArrayList<>();
+ //Port Pair Group and associated Port Pair
+ Map<Uuid, List<PortPair>> groupPortPairsList = new HashMap<>();
+ //Map of Port Pair uuid and Port pair ingress port related Neutron Port
+ Map<Uuid, Port> portPairToNeutronPortMap = new HashMap<>();
+
+ //Mapping of Port Pair UUID and OvsdbPortMetadata of the port pair ingress port
+ Map<Uuid, OvsdbPortMetadata> portPairOvsdbMetadata = new HashMap<>();
+
+ Map<Uuid, ServiceFunctionForwarderBuilder> portPairGroupToSFFMap = new HashMap<>();
+ List<ServiceFunction> portChainServiceFunctionList = new ArrayList<>();
+
+ //Read chain related port pair group, port pair and neutron port from neutron data store
+ for (Uuid ppgUuid : newPortChain.getPortPairGroups()) {
+ PortPairGroup ppg = neutronMdsalHelper.getNeutronPortPairGroup(ppgUuid);
+ if (ppg != null) {
+ List<PortPair> portPairList = new ArrayList<>();
+ portPairGroupList.add(ppg);
+ for(Uuid ppUuid : ppg.getPortPairs()) {
+ PortPair pp = neutronMdsalHelper.getNeutronPortPair(ppgUuid);
+ if (pp != null) {
+ portPairList.add(pp);
+ //NOTE:Assuming that ingress and egress port is same.
+ Port neutronPort = neutronMdsalHelper.getNeutronPort(pp.getIngress());
+ if (neutronPort != null) {
+ portPairToNeutronPortMap.put(ppgUuid, neutronPort);
+ }
+ }
+ }
+ groupPortPairsList.put(ppgUuid, portPairList);
+ }
+ }
+
+ Topology ovsdbTopology = ovsdbMdsalHelper.getOvsdbTopologyTree();
+
+ //Read ovsdb port details related to neutron port. Each Port pair has two neutron port
+ //With the current implementation, i am assuming that we support SF only with single port
+ //that act as a ingress as well as egress.
+ for(Map.Entry<Uuid, Port> neutronPortEntry : portPairToNeutronPortMap.entrySet()) {
+ OvsdbPortMetadata ovsdbPortMetadata =
+ ovsdbMdsalHelper.getOvsdbPortMetadata(
+ neutronPortEntry.getValue().getKey().getUuid(),
+ ovsdbTopology);
+
+ if(ovsdbPortMetadata != null) {
+ portPairOvsdbMetadata.put(neutronPortEntry.getKey(), ovsdbPortMetadata);
+ }
+ }
+
+ //For each port pair group
+ for (PortPairGroup ppg : portPairGroupList) {
+ List<ServiceFunctionBuilder> portPairSFList = new ArrayList<>();
+
+ List<PortPair> portPairList = groupPortPairsList.get(ppg.getUuid());
+ Map<Uuid, OvsdbPortMetadata> metadataList = new HashMap<>();
+ //Generate OvsdbPortMetadata for list of all the port pair
+ for (PortPair portPair : portPairList) {
+ OvsdbPortMetadata metadata = portPairOvsdbMetadata.get(portPair.getIngress());
+
+ if (metadata != null) {
+ metadataList.put(portPair.getIngress(), metadata);
+ }
+ }
+
+ //Build the SFF Builder from port pair group
+ ServiceFunctionForwarderBuilder sffBuilder =
+ PortPairGroupTranslator.buildServiceFunctionForwarder(ppg,portPairList, metadataList);
+
+ //Check if SFF already exist
+ ServiceFunctionForwarder existingSff =
+ sfcMdsalHelper.getExistingSFF(sffBuilder.getIpMgmtAddress().getIpv4Address().getValue());
+ if(existingSff != null) {
+ LOG.info("SFF already exist for Port Pair Group {}. Existing SFF is {}",ppg, existingSff);
+ sffBuilder = new ServiceFunctionForwarderBuilder(existingSff);
+ }
+ //Add SFF builder to the map for later reference
+ portPairGroupToSFFMap.put(ppg.getUuid(), sffBuilder);
+
+ //Generate all the SF and write it to SFC data store
+ for (PortPair portPair : portPairList) {
+ OvsdbPortMetadata metadata = portPairOvsdbMetadata.get(portPair.getIngress());
+ //Build the service function for the given port pair.
+ ServiceFunctionBuilder sfBuilder = PortPairTranslator.buildServiceFunction(portPair,
+ ppg,
+ portPairToNeutronPortMap.get(portPair.getIngress()),
+ metadata,
+ sffBuilder.build());
+
+ if (sfBuilder != null) {
+ //Write the Service Function to SFC data store.
+ sfcMdsalHelper.addServiceFunction(sfBuilder.build());
+
+ //Add to the list, to populated SFF Service Function Dictionary
+ portPairSFList.add(sfBuilder);
+
+ //Add the SF to Port Chain related SF list
+ portChainServiceFunctionList.add(sfBuilder.build());
+ } else {
+ LOG.warn("Service Function building failed for Port Pair {}", portPair);
+ }
+ }
+
+ //Update the Service Function Dictionary of SFF
+ for (ServiceFunctionBuilder sf : portPairSFList) {
+ PortPairGroupTranslator.buildServiceFunctionDictonary(sffBuilder, sf.build());
+ }
+ // Send SFF create request
+ LOG.info("Add Service Function Forwarder {} for Port Pair Group {}", sffBuilder.build(), ppg);
+ sfcMdsalHelper.addServiceFunctionForwarder(sffBuilder.build());
+ }
+ //Build Service Function Chain Builder
+ ServiceFunctionChain sfc =
+ PortChainTranslator.buildServiceFunctionChain(newPortChain, portChainServiceFunctionList);
+
+ //Write SFC to data store
+ if (sfc != null) {
+ sfcMdsalHelper.addServiceFunctionChain(sfc);
+ } else {
+ LOG.warn("Service Function Chain building failed for Port Chain {}", newPortChain);
+ }
+
+ // Build Service Function Path Builder
+ ServiceFunctionPath sfp = PortChainTranslator.buildServiceFunctionPath(sfc);
+ //Write SFP to data store
+ if (sfp != null) {
+ sfcMdsalHelper.addServiceFunctionPath(sfp);
+ } else {
+ LOG.warn("Service Function Path building failed for Service Chain {}", sfc);
+ }
+
+ //TODO:Generate Flow Classifiers and augment RSP on it.
+
+ if (this.rspService != null) {
+ // Build Create Rendered Service Path input
+ CreateRenderedPathInput rpInput = PortChainTranslator.buildRenderedServicePathInput(sfp);
+
+ //Call Create Rendered Service Path RPC call
+ if (rpInput != null) {
+ Future<RpcResult<CreateRenderedPathOutput>> result = this.rspService.createRenderedPath(rpInput);
+ try {
+ result.get();
+ processFlowClassifiers(newPortChain, newPortChain.getFlowClassifiers(), rpInput.getName());
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error occurred during creating Rendered Service Path using RPC call", e);
+ }
+ }
+ } else {
+ LOG.error("Rendered Path Service is not available, can't create Rendered Path for Port Chain", newPortChain);
+ }
+ }
+
+ private void processFlowClassifiers(PortChain pc, List<Uuid> flowClassifiers, String rspName) {
+ for (Uuid uuid : flowClassifiers) {
+ SfcFlowClassifier fc = neutronMdsalHelper.getNeutronFlowClassifier(uuid);
+ if (fc != null) {
+ Acl acl = FlowClassifierTranslator.buildAcl(fc, rspName);
+ if (acl != null ) {
+ sfcMdsalHelper.addAclFlowClassifier(acl);
+ } else {
+ LOG.warn("Acl building failed for flow classifier {}. Traffic might not be redirected to RSP", fc);
+ }
- public NeutronPortChainListener(DataBroker db, PortChainTranslator portChainTranslator) {
- super(portChainTranslator, db,
- new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portChainIid));
+ } else {
+ LOG.error("Neutron Flow Classifier {} attached to Port Chain {} is not present in the neutron data " +
+ "store", uuid, pc);
+ }
+ }
}
}
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
- * OpenDaylight Neutron Port Group yang models data change listener
+ * OpenDaylight Neutron Port Pair Group yang models data change listener
*/
public class NeutronPortPairGroupListener extends DelegatingDataTreeListener<PortPairGroup> {
private static final InstanceIdentifier<PortPairGroup> portPairGroupIid =
InstanceIdentifier.create(Neutron.class).child(PortPairGroups.class).child(PortPairGroup.class);
- public NeutronPortPairGroupListener(DataBroker db, PortPairGroupTranslator portPairGroupTranslator) {
- super(portPairGroupTranslator, db,
- new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairGroupIid));
+ public NeutronPortPairGroupListener(DataBroker db) {
+ super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairGroupIid));
+ }
+
+ /**
+ * Method removes PortPairGroup which is identified by InstanceIdentifier.
+ *
+ * @param path - the whole path to PortPairGroup
+ * @param deletedPortPairGroup - PortPairGroup for removing
+ */
+ @Override
+ public void remove(InstanceIdentifier<PortPairGroup> path, PortPairGroup deletedPortPairGroup) {
+ //NO-OP
+ }
+
+ /**
+ * Method updates the original PortPairGroup to the update PortPairGroup.
+ * Both are identified by same InstanceIdentifier.
+ *
+ * @param path - the whole path to PortPairGroup
+ * @param originalPortPairGroup - original PortPairGroup (for update)
+ * @param updatePortPairGroup - changed PortPairGroup (contain updates)
+ */
+ @Override
+ public void update(InstanceIdentifier<PortPairGroup> path,
+ PortPairGroup originalPortPairGroup,
+ PortPairGroup updatePortPairGroup) {
+ //NO-OP
+ }
+
+ /**
+ * Method adds the PortPairGroup which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param path - the whole path to new PortPairGroup
+ * @param newPortPairGroup - new PortPairGroup
+ */
+ @Override
+ public void add(InstanceIdentifier<PortPairGroup> path, PortPairGroup newPortPairGroup) {
+ //NO-OP
}
}
import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortPairs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
private static final InstanceIdentifier<PortPair> portPairIid =
InstanceIdentifier.create(Neutron.class).child(PortPairs.class).child(PortPair.class);
- public NeutronPortPairListener(DataBroker db, PortPairTranslator portPairTranslator) {
- super(portPairTranslator, db,
- new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairIid));
+ private final DataBroker db;
+ private final SfcMdsalHelper sfcMdsalHelper;
+ private final NeutronMdsalHelper neutronMdsalHelper;
+ private final OvsdbMdsalHelper ovsdbMdsalHelper;
+
+ public NeutronPortPairListener(DataBroker db) {
+ super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairIid));
+ this.db = db;
+ sfcMdsalHelper = new SfcMdsalHelper(db);
+ neutronMdsalHelper = new NeutronMdsalHelper(db);
+ ovsdbMdsalHelper = new OvsdbMdsalHelper(db);
+ }
+
+ /**
+ * Method removes PortPair which is identified by InstanceIdentifier.
+ *
+ * @param path - the whole path to PortPair
+ * @param deletedPortPair - PortPair for removing
+ */
+ @Override
+ public void remove(InstanceIdentifier<PortPair> path, PortPair deletedPortPair) {
+ sfcMdsalHelper.removeServiceFunction(PortPairTranslator.getSFKey(deletedPortPair));
+ }
+
+ /**
+ * Method updates the original PortPair to the update PortPair.
+ * Both are identified by same InstanceIdentifier.
+ *
+ * @param path - the whole path to PortPair
+ * @param originalPortPair - original PortPair (for update)
+ * @param updatePortPair - changed PortPair (contain updates)
+ */
+ @Override
+ public void update(InstanceIdentifier<PortPair> path, PortPair originalPortPair, PortPair updatePortPair) {
+ //NO-OP
+ }
+
+ /**
+ * Method adds the PortPair which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param path - the whole path to new PortPair
+ * @param newPortPair - new PortPair
+ */
+ @Override
+ public void add(InstanceIdentifier<PortPair> path, PortPair newPortPair) {
+ //NO-OP
+ // Port Pair data written in neutron data store will be used
+ // When user will create port chain.
}
}
*/
package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import com.google.common.base.Preconditions;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+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.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionKey;
+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.opendaylight.neutron.sfc.rev160511.port.chain.attributes.ChainParameters;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.chains.PortChain;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Class will convert OpenStack Port Chain API yang models present in
* neutron northbound project to OpenDaylight SFC yang models.
*/
-public class PortChainTranslator implements INeutronSfcDataProcessor<PortChain> {
+public class PortChainTranslator {
private static final Logger LOG = LoggerFactory.getLogger(PortChainTranslator.class);
+ private static final String SYMMETRIC_PARAM = "symmetric";
+ private static final String SFP_NAME_PREFIX = "Path-";
- private final DataBroker db;
- private NeutronPortChainListener neutronPortChainListener;
- private final SfcMdsalHelper sfcMdsalHelper;
- private final NeutronMdsalHelper neutronMdsalHelper;
+ public static ServiceFunctionChain buildServiceFunctionChain(
+ PortChain portChain, List<ServiceFunction> sfList) {
+ ServiceFunctionChainBuilder sfcBuilder = new ServiceFunctionChainBuilder();
+ sfcBuilder.setName(new SfcName(portChain.getName()));
+ sfcBuilder.setKey(new ServiceFunctionChainKey(sfcBuilder.getName()));
- public PortChainTranslator(DataBroker db) {
- this.db = db;
- sfcMdsalHelper = new SfcMdsalHelper(db);
- neutronMdsalHelper = new NeutronMdsalHelper(db);
- }
+ //By default set it to false. If user specify it in chain parameters, it
+ //will be overridden.
+ sfcBuilder.setSymmetric(false);
- public void start() {
- LOG.info("Port Chain Translator Initialized.");
- if(neutronPortChainListener == null) {
- neutronPortChainListener = new NeutronPortChainListener(db, this);
+ //Set service functions
+ List<SfcServiceFunction> sfcSfList = new ArrayList<>();
+ for(ServiceFunction sf : sfList) {
+ SfcServiceFunctionBuilder sfcSfBuilder = new SfcServiceFunctionBuilder();
+ sfcSfBuilder.setName(sf.getName().getValue());
+ sfcSfBuilder.setType(sf.getType());
+ sfcSfBuilder.setKey(new SfcServiceFunctionKey(sfcSfBuilder.getName()));
+
+ //NOTE: no explicit order is set.
+ sfcSfList.add(sfcSfBuilder.build());
+ }
+ List<ChainParameters> cpList = portChain.getChainParameters();
+ if (cpList != null && !cpList.isEmpty()) {
+ for (ChainParameters cp : cpList) {
+ if(cp.getChainParameter().equals(SYMMETRIC_PARAM)) {
+ //Override the symmetric default value.
+ sfcBuilder.setSymmetric(new Boolean(cp.getChainParameterValue()));
+ break;
+ }
+ }
}
+ sfcBuilder.setSfcServiceFunction(sfcSfList);
+ return sfcBuilder.build();
}
- /**
- * Method removes PortChain which is identified by InstanceIdentifier.
- *
- * @param path - the whole path to PortChain
- * @param deletedPortChain - PortChain for removing
- */
- @Override
- public void remove(InstanceIdentifier<PortChain> path, PortChain deletedPortChain) {
+ public static ServiceFunctionPath buildServiceFunctionPath(ServiceFunctionChain sfc) {
+ Preconditions.checkNotNull(sfc, "Service Function Chain must not be null");
+ ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
- }
-
- /**
- * Method updates the original PortChain to the update PortChain.
- * Both are identified by same InstanceIdentifier.
- *
- * @param path - the whole path to PortChain
- * @param originalPortChain - original PortChain (for update)
- * @param updatePortChain - changed PortChain (contain updates)
- */
- @Override
- public void update(InstanceIdentifier<PortChain> path, PortChain originalPortChain, PortChain updatePortChain) {
+ //Set the name
+ sfpBuilder.setName(new SfpName(SFP_NAME_PREFIX + sfc.getName().getValue()));
+ sfpBuilder.setSymmetric(sfc.isSymmetric());
+ //Set related SFC name
+ sfpBuilder.setServiceChainName(sfc.getName());
+ return sfpBuilder.build();
}
- /**
- * Method adds the PortChain which is identified by InstanceIdentifier
- * to device.
- *
- * @param path - the whole path to new PortChain
- * @param newPortChain - new PortChain
- */
- @Override
- public void add(InstanceIdentifier<PortChain> path, PortChain newPortChain) {
+ public static CreateRenderedPathInput buildRenderedServicePathInput(ServiceFunctionPath sfp) {
+ CreateRenderedPathInputBuilder rpInputBuilder = new CreateRenderedPathInputBuilder();
+ rpInputBuilder.setName(sfp.getName().getValue());
+ rpInputBuilder.setSymmetric(sfp.isSymmetric());
+ rpInputBuilder.setParentServiceFunctionPath(sfp.getName().getValue());
+ return rpInputBuilder.build();
+ }
+ public static ServiceFunctionChainKey getSFCKey(PortChain portChain) {
+ return new ServiceFunctionChainKey(new SfcName(portChain.getName()));
}
}
*/
package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import com.google.common.base.Preconditions;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SnName;
+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.sff.ovs.rev140701.SffOvsBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsBridgeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsLocatorOptionsAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsLocatorOptionsAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsNodeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.bridge.OvsBridgeBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.node.OvsNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.options.OvsOptionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.Open;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.sff.data.plane.locator.DataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionary;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionaryBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionaryKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.service.function.dictionary.SffSfDataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.IpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Class will convert OpenStack Port Pair API yang models present in
* neutron northbound project to OpenDaylight SFC yang models.
*/
-public class PortPairGroupTranslator implements INeutronSfcDataProcessor<PortPairGroup> {
+public class PortPairGroupTranslator {
private static final Logger LOG = LoggerFactory.getLogger(PortPairGroupTranslator.class);
+ private static final String OPT_FLOW_STR = "flow";
+ private static final String OPT_DST_PORT = "6633";
- private final DataBroker db;
- private NeutronPortPairGroupListener neutronPortPairGroupListener;
- private final SfcMdsalHelper sfcMdsalHelper;
- private final NeutronMdsalHelper neutronMdsalHelper;
+ private static final AtomicInteger counter = new AtomicInteger(0);
+ private static final String SFF_DEFAULT_NAME = "sff";
- public PortPairGroupTranslator(DataBroker db) {
- this.db = db;
- sfcMdsalHelper = new SfcMdsalHelper(db);
- neutronMdsalHelper = new NeutronMdsalHelper(db);
- }
+ public static ServiceFunctionForwarderBuilder buildServiceFunctionForwarder(
+ PortPairGroup portPairGroup,
+ List<PortPair> portPairs,
+ Map<Uuid, OvsdbPortMetadata> ovsdbPortsMetadata) {
+ Preconditions.checkNotNull(portPairGroup, "Port pair group must not be null");
+
+ ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
+ SffOvsBridgeAugmentationBuilder sffOvsBridgeAugBuilder = new SffOvsBridgeAugmentationBuilder();
+ SffOvsNodeAugmentationBuilder sffOvsNodeAugBuilder = new SffOvsNodeAugmentationBuilder();
+
+ List<SffDataPlaneLocator> sffDataPlaneLocator = new ArrayList<>();
+ SffDataPlaneLocatorBuilder sffDplBuilder = new SffDataPlaneLocatorBuilder();
+ DataPlaneLocatorBuilder dplBuilder = new DataPlaneLocatorBuilder();
- public void start() {
- LOG.info("Port Pair Group Translator Initialized.");
- if(neutronPortPairGroupListener == null) {
- neutronPortPairGroupListener = new NeutronPortPairGroupListener(db, this);
+ IpBuilder sffLocator = new IpBuilder();
+
+ //Currently we only support one SF per type. Mean, one port-pair per port-pair-group.
+ //Get port pair from neutron data store.
+ PortPair portPair = portPairs.get(0);
+ if (portPair == null) {
+ LOG.error("Port pair {} does not exist in the neutron data store. Port Pair Group {} request can't be " +
+ "processed.", portPairGroup.getPortPairs().get(0), portPairGroup);
+ return null;
}
- }
+ //Get metadata of neutron port related to port pair ingress port from ovsdb data store.
+ OvsdbPortMetadata ovsdbPortMetadata = ovsdbPortsMetadata.get(portPair.getIngress());
- /**
- * Method removes PortPairGroup which is identified by InstanceIdentifier.
- *
- * @param path - the whole path to PortPairGroup
- * @param deletedPortPairGroup - PortPairGroup for removing
- */
- @Override
- public void remove(InstanceIdentifier<PortPairGroup> path, PortPairGroup deletedPortPairGroup) {
+ //Convert the port pair to service function
- }
+ //Set SFF DPL transport type
+ dplBuilder.setTransport(VxlanGpe.class);
- /**
- * Method updates the original PortPairGroup to the update PortPairGroup.
- * Both are identified by same InstanceIdentifier.
- *
- * @param path - the whole path to PortPairGroup
- * @param originalPortPairGroup - original PortPairGroup (for update)
- * @param updatePortPairGroup - changed PortPairGroup (contain updates)
- */
- @Override
- public void update(InstanceIdentifier<PortPairGroup> path,
- PortPairGroup originalPortPairGroup,
- PortPairGroup updatePortPairGroup) {
+ //Set SFF Locator Type
+ OvsdbNodeAugmentation ovsdbNodeAug = ovsdbPortMetadata.getOvsdbNode();
+ if (ovsdbNodeAug != null ) {
+ sffLocator.setIp(ovsdbNodeAug.getConnectionInfo().getRemoteIp());
+ sffLocator.setPort(ovsdbNodeAug.getConnectionInfo().getRemotePort());
+ }
+ dplBuilder.setLocatorType(sffLocator.build());
+ //set data-path-locator for sff-data-path-locator
+ sffDplBuilder.setDataPlaneLocator(dplBuilder.build());
+
+ //Set location options for sff-dp-locator
+ sffDplBuilder.addAugmentation(SffOvsLocatorOptionsAugmentation.class, buildOvsOptions().build());
+
+ //Set ovsdb bridge name for sff
+ OvsBridgeBuilder ovsBridgeBuilder = new OvsBridgeBuilder();
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation = ovsdbPortMetadata.getOvsdbBridgeNode();
+ if (ovsdbBridgeAugmentation != null) {
+ ovsBridgeBuilder.setBridgeName(ovsdbBridgeAugmentation.getBridgeName().getValue());
+ //Set SFF name
+ String serviceNode = OvsdbMdsalHelper.getNodeKey(ovsdbBridgeAugmentation.getManagedBy().getValue());
+ if(serviceNode.isEmpty()) {
+ serviceNode += SFF_DEFAULT_NAME + counter.incrementAndGet();
+ sffBuilder.setName(new SffName(serviceNode));
+ sffBuilder.setServiceNode(new SnName(serviceNode));
+ } else {
+ //Set service node to ovsdbNode
+ sffBuilder.setServiceNode(new SnName(serviceNode));
+
+ //Set SFF name to ovsdbBridgeNode
+ serviceNode += "/" + ovsdbBridgeAugmentation.getBridgeName().getValue();
+ sffBuilder.setName(new SffName(serviceNode));
+ }
+
+ //Set ovsdb-node iid reference for SFF
+ OvsNodeBuilder ovsNodeBuilder = new OvsNodeBuilder();
+ ovsNodeBuilder.setNodeId(ovsdbBridgeAugmentation.getManagedBy());
+ sffOvsNodeAugBuilder.setOvsNode(ovsNodeBuilder.build());
+ sffBuilder.addAugmentation(SffOvsNodeAugmentation.class, sffOvsNodeAugBuilder.build());
+ }
+ sffOvsBridgeAugBuilder.setOvsBridge(ovsBridgeBuilder.build());
+ sffBuilder.addAugmentation(SffOvsBridgeAugmentation.class, sffOvsBridgeAugBuilder.build());
+
+ //Set management ip, same to the ovsdb node ip
+ sffBuilder.setIpMgmtAddress(sffLocator.getIp());
+
+ sffDataPlaneLocator.add(sffDplBuilder.build());
+ //set SFF key
+ sffBuilder.setKey(new ServiceFunctionForwarderKey(sffBuilder.getName()));
+ sffBuilder.setSffDataPlaneLocator(sffDataPlaneLocator);
+
+ return sffBuilder;
}
- /**
- * Method adds the PortPairGroup which is identified by InstanceIdentifier
- * to device.
- *
- * @param path - the whole path to new PortPairGroup
- * @param newPortPairGroup - new PortPairGroup
- */
- @Override
- public void add(InstanceIdentifier<PortPairGroup> path, PortPairGroup newPortPairGroup) {
+ public static void buildServiceFunctionDictonary(ServiceFunctionForwarderBuilder sffBuilder,
+ ServiceFunction sf) {
+ List<ServiceFunctionDictionary> sfdList = new ArrayList<>();
+ ServiceFunctionDictionaryBuilder sfdBuilder = new ServiceFunctionDictionaryBuilder();
+
+ //Build Sff-sf-data-plane-locator
+ SffSfDataPlaneLocatorBuilder sffSfDplBuilder = new SffSfDataPlaneLocatorBuilder();
+ sffSfDplBuilder.setSfDplName(sf.getSfDataPlaneLocator().get(0).getName());
+ sffSfDplBuilder.setSffDplName(sffBuilder.getSffDataPlaneLocator().get(0).getName());
+ sfdBuilder.setSffSfDataPlaneLocator(sffSfDplBuilder.build());
+
+ sfdBuilder.setName(sf.getName());
+ sfdBuilder.setKey(new ServiceFunctionDictionaryKey(sfdBuilder.getName()));
+
+ //NOTE: fail mode is set to Open by default
+ sfdBuilder.setFailmode(Open.class);
+
+ //TODO: set interface name list
+
+ for (Iterator<ServiceFunctionDictionary> sfdItr = sffBuilder.getServiceFunctionDictionary().iterator();sfdItr
+ .hasNext();) {
+ ServiceFunctionDictionary sfd = sfdItr.next();
+ if (sfd.getName().equals(sfdBuilder.getName())) {
+ LOG.info("Existing SF dictionary {} found in SFF {}, removing the SF dictionary", sfd.getName(),
+ sffBuilder.getName());
+ sfdItr.remove();
+ break;
+ }
+ }
+ sfdList.add(sfdBuilder.build());
+
+ if (sffBuilder.getServiceFunctionDictionary() != null) {
+ sffBuilder.getServiceFunctionDictionary().addAll(sfdList);
+ } else {
+ sffBuilder.setServiceFunctionDictionary(sfdList);
+ }
+ LOG.info("Final Service Function Dictionary {}", sffBuilder.getServiceFunctionDictionary());
+ }
+ private static SffOvsLocatorOptionsAugmentationBuilder buildOvsOptions() {
+ SffOvsLocatorOptionsAugmentationBuilder ovsOptions = new SffOvsLocatorOptionsAugmentationBuilder();
+ OvsOptionsBuilder ovsOptionsBuilder = new OvsOptionsBuilder();
+ ovsOptionsBuilder.setRemoteIp(OPT_FLOW_STR);
+ ovsOptionsBuilder.setDstPort(OPT_DST_PORT);
+ ovsOptionsBuilder.setKey(OPT_FLOW_STR);
+ ovsOptionsBuilder.setNsp(OPT_FLOW_STR);
+ ovsOptionsBuilder.setNsi(OPT_FLOW_STR);
+ ovsOptionsBuilder.setNshc1(OPT_FLOW_STR);
+ ovsOptionsBuilder.setNshc2(OPT_FLOW_STR);
+ ovsOptionsBuilder.setNshc3(OPT_FLOW_STR);
+ ovsOptionsBuilder.setNshc4(OPT_FLOW_STR);
+ ovsOptions.setOvsOptions(ovsOptionsBuilder.build());
+ return ovsOptions;
}
}
*/
package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableBiMap;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfDataPlaneLocatorName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocator;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocatorBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocatorKey;
-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.sf.rev140701.service.functions.ServiceFunctionBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.SlTransportType;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.IpBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.port.pair.attributes.ServiceFunctionParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* Class will convert OpenStack Port Pair API yang models present in
* neutron northbound project to OpenDaylight SFC Service Function yang models.
*/
-public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
+public class PortPairTranslator {
private static final Logger LOG = LoggerFactory.getLogger(PortPairTranslator.class);
private static final String NSH_AWARE_PARAM = "nsh-aware";
private static final String SF_TYPE_PARAM = "type";
private static final AtomicInteger counter = new AtomicInteger(0);
private static final String SFF_NAME_PARAM = "sff-name";
- private final DataBroker db;
- private NeutronPortPairListener neutronPortPairListener;
- private final SfcMdsalHelper sfcMdsalHelper;
- private final NeutronMdsalHelper neutronMdsalHelper;
- private final OvsdbMdsalHelper ovsdbMdsalHelper;
-
- public PortPairTranslator(DataBroker db) {
- this.db = db;
- sfcMdsalHelper = new SfcMdsalHelper(db);
- neutronMdsalHelper = new NeutronMdsalHelper(db);
- ovsdbMdsalHelper = new OvsdbMdsalHelper(db);
- }
-
- public void start() {
- LOG.info("Port Pair Translator Initialized.");
- if(neutronPortPairListener == null) {
- neutronPortPairListener = new NeutronPortPairListener(db, this);
- }
- }
-
- /**
- * Method removes PortPair which is identified by InstanceIdentifier.
- *
- * @param path - the whole path to PortPair
- * @param deletedPortPair - PortPair for removing
- */
- @Override
- public void remove(InstanceIdentifier<PortPair> path, PortPair deletedPortPair) {
- sfcMdsalHelper.removeServiceFunction(getSFKey(deletedPortPair));
- }
-
- /**
- * Method updates the original PortPair to the update PortPair.
- * Both are identified by same InstanceIdentifier.
- *
- * @param path - the whole path to PortPair
- * @param originalPortPair - original PortPair (for update)
- * @param updatePortPair - changed PortPair (contain updates)
- */
- @Override
- public void update(InstanceIdentifier<PortPair> path, PortPair originalPortPair, PortPair updatePortPair) {
- ServiceFunction sf = buildServiceFunction(updatePortPair);
- sfcMdsalHelper.updateServiceFunction(sf);
- }
-
- /**
- * Method adds the PortPair which is identified by InstanceIdentifier
- * to device.
- *
- * @param path - the whole path to new PortPair
- * @param newPortPair - new PortPair
- */
- @Override
- public void add(InstanceIdentifier<PortPair> path, PortPair newPortPair) {
- ServiceFunction sf = buildServiceFunction(newPortPair);
- sfcMdsalHelper.addServiceFunction(sf);
- }
-
- private ServiceFunction buildServiceFunction(PortPair portPair) {
+ public static ServiceFunctionBuilder buildServiceFunction(
+ PortPair portPair,
+ PortPairGroup portPairGroup,
+ Port neutronPort,
+ OvsdbPortMetadata ovsdbPortMetadata,
+ ServiceFunctionForwarder sff) {
+ Preconditions.checkNotNull(portPair, "Port pair must not be null");
+ Preconditions.checkNotNull(portPairGroup, "Port pair group must not be null");
+ Preconditions.checkNotNull(neutronPort, "Neutron Port related to port pair must not be null");
LOG.info("Port pair received : {}", portPair);
ServiceFunctionBuilder serviceFunctionBuilder = new ServiceFunctionBuilder();
IpBuilder sfLocator = new IpBuilder();
List<ServiceFunctionParameters> sfParams = portPair.getServiceFunctionParameters();
-
+ //Set SF name, key and tenant-id
serviceFunctionBuilder.setName(new SfName(portPair.getName()));
serviceFunctionBuilder.setKey(new ServiceFunctionKey(serviceFunctionBuilder.getName()));
-
serviceFunctionBuilder.setTenantId(new TenantId(portPair.getTenantId().getValue()));
- //By default set it to true
+
+ //Set SF Type. Setting it to PortPairGroup Type, this will be overridden if user pass
+ //it through service_function_params
+ serviceFunctionBuilder.setType(SftTypeName.getDefaultInstance(portPairGroup.getName()));
+
+ //Set NSH Aware to true, later it will be overridden if user specified otherwise
+ //in service_function_parameters
serviceFunctionBuilder.setNshAware(true);
- //Set data path locator
+ //Set data path locator name and key
sfDataPlaneLocatorBuilder.setName(new SfDataPlaneLocatorName(portPair.getName() + DPL_SUFFIX_PARAM));
sfDataPlaneLocatorBuilder.setKey(new SfDataPlaneLocatorKey(sfDataPlaneLocatorBuilder.getName()));
//Set vxlan-gpe as a default transport type, unless user pass specific transport in
- //service_function_params
+ //service_function_parameters
sfDataPlaneLocatorBuilder.setTransport(VxlanGpe.class);
//Set locator type
- Port neutronPort = neutronMdsalHelper.getNeutronPort(portPair.getIngress());
- if (neutronPort == null) {
- //Try to get the neutron port for egress node. Currently assuming that
- //ingress port and egress port will be same.
- neutronPort = neutronMdsalHelper.getNeutronPort(portPair.getEgress());
- }
if (neutronPort != null) {
List<AllowedAddressPairs> attachedIpAddresses = neutronPort.getAllowedAddressPairs();
//Pick up the first ip address
LOG.warn("Neutron port mapped to Port pair ingress/egress port is not found : {}", portPair);
}
- //Set OVS_Port
- //This call is very costly call, as it reads ovsdb:1 topology from the operational data store.
- // Need to think of caching to optimize it further.
- OvsdbPortMetadata ovsdbPortMetadata = ovsdbMdsalHelper.getOvsdbPortMetadata(portPair.getIngress());
if (ovsdbPortMetadata.getOvsdbPort() != null ) {
- String ovsdbPortName = ovsdbMdsalHelper.getOvsdbPortName(ovsdbPortMetadata.getOvsdbPort());
+ String ovsdbPortName = OvsdbMdsalHelper.getOvsdbPortName(ovsdbPortMetadata.getOvsdbPort());
SfDplOvsAugmentationBuilder sfDplOvsAugmentationBuilder = new SfDplOvsAugmentationBuilder();
OvsPortBuilder ovsPortBuilder = new OvsPortBuilder();
ovsPortBuilder.setPortId(ovsdbPortName);
sfDplOvsAugmentationBuilder.setOvsPort(ovsPortBuilder.build());
sfDataPlaneLocatorBuilder.addAugmentation(SfDplOvsAugmentation.class, sfDplOvsAugmentationBuilder.build());
+ } else {
+ LOG.warn("No OVSDB Port found for the port pair {}. Lack of ovs-port information might not configure SF " +
+ "properly", portPair);
}
- //But if user pass specific param using service_function_parameters, set it accordingly
+ //But if user pass specific param using service_function_parameters, set/override it accordingly
for(ServiceFunctionParameters sfParam : sfParams) {
if (sfParam.getServiceFunctionParameter().equals(NSH_AWARE_PARAM)) {
serviceFunctionBuilder.setNshAware(new Boolean(sfParam.getServiceFunctionParameterValue()));
}
- //There is not default type set, user MUST pass it through service_function_parameters
+ //There is by default type set to port pair group name, override it if user pass it specific type
if (sfParam.getServiceFunctionParameter().equals(SF_TYPE_PARAM)) {
serviceFunctionBuilder.setType(new SftTypeName(sfParam.getServiceFunctionParameterValue()));
}
//Set service_function_forwarder
if (sfDataPlaneLocatorBuilder.getServiceFunctionForwarder() == null
&& ovsdbPortMetadata.getOvsdbNode() != null) {
- String ipAddress = ovsdbMdsalHelper.getNodeIpAddress(ovsdbPortMetadata.getOvsdbNode());
- SffName sffName = sfcMdsalHelper.getExistingSFF(ipAddress);
+ SffName sffName = sff.getName();
if(sffName != null ) {
sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(sffName);
} else {
//Set all data plane locator
serviceFunctionBuilder.setSfDataPlaneLocator(sfDataPlaneLocatorList);
LOG.info("Port Pair translated to Service Function: {}", serviceFunctionBuilder);
- return serviceFunctionBuilder.build();
+ return serviceFunctionBuilder;
}
- private ServiceFunctionKey getSFKey(PortPair portPair) {
+ public static ServiceFunctionKey getSFKey(PortPair portPair) {
return new ServiceFunctionKey(new SfName(portPair.getName()));
}
-
}
<reference id="dataBroker"
interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" />
+ <reference id="rspService"
+ interface="org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService"
+ availability="optional"/>
<odl:clustered-app-config id="openstackSfcTranslatorConfig"
binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.openstack.sfc.translator.config.rev160720.OpenstackSfcTranslatorConfig">
class="org.opendaylight.netvirt.openstack.sfc.translator.OpenStackSFCTranslatorProvider"
init-method="start" destroy-method="close">
<argument ref="dataBroker" />
+ <argument ref="rspService" />
<argument ref="openstackSfcTranslatorConfig" />
<argument ref="blueprintBundleContext" />
</bean>
public static final int TRACKED_NEW_CT_STATE_MASK = 0x21;
public static final int TRACKED_INV_CT_STATE_MASK = 0x30;
+ public static final String IPV4_ALL_NETWORK = "0.0.0.0/0";
+
private AclConstants() {
}
}
flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
new long[] { NwConstants.ETHTYPE_IPV4 }));
Ipv4Prefix srcNetwork = ((AceIpv4)acl.getAceIpVersion()).getSourceIpv4Network();
- if (null != srcNetwork) {
+ if (null != srcNetwork && !srcNetwork.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
String[] ipaddressValues = srcNetwork.getValue().split("/");
flowMatches.add(new MatchInfo(MatchFieldType.ipv4_source,
new String[] {ipaddressValues[0], ipaddressValues[1]}));
flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
new long[] { NwConstants.ETHTYPE_IPV4 }));
Ipv4Prefix dstNetwork = ((AceIpv4)acl.getAceIpVersion()).getDestinationIpv4Network();
- if (null != dstNetwork) {
+ if (null != dstNetwork && !dstNetwork.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
String[] ipaddressValues = dstNetwork.getValue().split("/");
flowMatches.add(new MatchInfo(MatchFieldType.ipv4_destination,
new String[] {ipaddressValues[0], ipaddressValues[1]}));
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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
--->
-<snapshot>
- <required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:dhcpservice:impl?module=dhcpservice-impl&revision=2015-07-10</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
- <capability>urn:opendaylight:genius:mdsalutil?module=odl-mdsalutil&revision=2016-04-06</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service?module=opendaylight-entity-ownership-service&revision=2015-08-10</capability>
- <capability>urn:opendaylight:genius:interfacemanager?module=odl-interface&revision=2016-04-06</capability>
- </required-capabilities>
- <configuration>
-
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:dhcpservice:impl">prefix:dhcpservice-impl</type>
- <name>dhcpservice-default</name>
- <controller-dhcp-enabled>true</controller-dhcp-enabled>
- <broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <name>binding-osgi-broker</name>
- </broker>
- <rpcregistry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <name>binding-rpc-broker</name>
- </rpcregistry>
- <notification-service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
- <name>binding-notification-broker</name>
- </notification-service>
- <mdsalutil>
- <type xmlns:mdsalutil="urn:opendaylight:genius:mdsalutil">mdsalutil:odl-mdsalutil</type>
- <name>mdsalutil-service</name>
- </mdsalutil>
- <entity-ownership-service>
- <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
- <name>entity-ownership-service</name>
- </entity-ownership-service>
- <odlinterface>
- <type xmlns:odlif="urn:opendaylight:genius:interfacemanager">odlif:odl-interface</type>
- <name>interfacemgr-service</name>
- </odlinterface>
- </module>
- </modules>
- </data>
- </configuration>
-</snapshot>
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DhcpConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dhcp.config.Configs;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
private static final Logger LOG = LoggerFactory.getLogger(DhcpConfigListener.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DhcpManager dhcpManager;
+ private final DhcpManager dhcpManager;
+ private final DataBroker dataBroker;
public DhcpConfigListener(final DataBroker db, final DhcpManager dhcpMgr) {
super(DhcpConfig.class, DhcpConfigListener.class);
dhcpManager = dhcpMgr;
- registerListener(db);
+ this.dataBroker = db;
}
- private void registerListener(final DataBroker db) {
- try {
- listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
- getWildCardPath(), DhcpConfigListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
- } catch (final Exception e) {
- LOG.error("NodeListener: DataChange listener registration fail!", e);
- throw new IllegalStateException("NodeListener: registration Listener failed.", e);
- }
+ public void init() {
+ registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
}
+ @Override
protected InstanceIdentifier<DhcpConfig> getWildCardPath() {
return InstanceIdentifier.create(DhcpConfig.class);
}
@Override
public void close() throws Exception {
- if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- LOG.error("Error when cleaning up DhcpConfigListener.", e);
- }
- listenerRegistration = null;
- }
+ super.close();
LOG.debug("DhcpConfig Listener Closed");
}
import java.math.BigInteger;
import java.util.List;
-
import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
public class DhcpDesignatedDpnListener extends AsyncClusteredDataChangeListenerBase<DesignatedSwitchForTunnel, DhcpDesignatedDpnListener> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(DhcpDesignatedDpnListener.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
- private DataBroker broker;
+
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private final DataBroker broker;
public DhcpDesignatedDpnListener(final DhcpExternalTunnelManager dhcpExternalTunnelManager, final DataBroker broker) {
super(DesignatedSwitchForTunnel.class, DhcpDesignatedDpnListener.class);
this.broker = broker;
}
+ public void init() {
+ registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+ }
+
@Override
public void close() throws Exception {
- if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- LOG.error("Error when cleaning up DhcpDesignatedDpnListener.", e);
- }
- listenerRegistration = null;
- }
+ super.close();
LOG.debug("DhcpDesignatedDpnListener Listener Closed");
}
*/
package org.opendaylight.netvirt.dhcpservice;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
public class DhcpExternalTunnelManager {
private static final Logger logger = LoggerFactory.getLogger(DhcpExternalTunnelManager.class);
public static final String UNKNOWN_DMAC = "00:00:00:00:00:00";
+
private final DataBroker broker;
- private IMdsalApiManager mdsalUtil;
+ private final IMdsalApiManager mdsalUtil;
+ private final ItmRpcService itmRpcService;
+ private final EntityOwnershipService entityOwnershipService;
private ConcurrentMap<BigInteger, Set<Pair<IpAddress, String>>> designatedDpnsToTunnelIpElanNameCache = new ConcurrentHashMap<>();
private ConcurrentMap<Pair<IpAddress, String>, Set<String>> tunnelIpElanNameToVmMacCache = new ConcurrentHashMap<>();
private ConcurrentMap<Pair<IpAddress, String>, Set<String>> availableVMCache = new ConcurrentHashMap<>();
private ConcurrentMap<Pair<BigInteger, String>, Port> vniMacAddressToPortCache = new ConcurrentHashMap<>();
- private ItmRpcService itmRpcService;
- private EntityOwnershipService entityOwnershipService;
- public DhcpExternalTunnelManager(DataBroker broker, IMdsalApiManager mdsalUtil, ItmRpcService itmRpcService, EntityOwnershipService entityOwnershipService) {
+
+ public DhcpExternalTunnelManager(final DataBroker broker,
+ final IMdsalApiManager mdsalUtil, final ItmRpcService itmRpcService,
+ final EntityOwnershipService entityOwnershipService) {
this.broker = broker;
this.mdsalUtil = mdsalUtil;
this.itmRpcService = itmRpcService;
this.entityOwnershipService = entityOwnershipService;
+ }
+
+ public void init() {
initilizeCaches();
}
public class DhcpInterfaceConfigListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceConfigListener.class);
+
private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DataBroker dataBroker;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ private final DataBroker dataBroker;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
public DhcpInterfaceConfigListener(DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
super(Interface.class);
this.dataBroker = dataBroker;
this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ }
+
+ public void init() {
registerListener();
}
@Override
public void close() throws Exception {
if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- logger.error("Error when cleaning up DataChangeListener.", e);
- }
- listenerRegistration = null;
+ listenerRegistration.close();
}
logger.info("DhcpInterfaceConfigListener Closed");
}
+
@Override
protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
IfTunnel tunnelInterface = del.getAugmentation(IfTunnel.class);
*/
package org.opendaylight.netvirt.dhcpservice;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
import java.math.BigInteger;
import java.util.List;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-
public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
- private DhcpManager dhcpManager;
+
private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DataBroker dataBroker;
+
+ private final DataBroker dataBroker;
+ private final DhcpManager dhcpManager;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
logger.error("Error in Datastore write operation", error);
}
};
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
super(Interface.class);
@Override
public void close() throws Exception {
if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- logger.error("Error when cleaning up DataChangeListener.", e);
- }
- listenerRegistration = null;
+ listenerRegistration.close();
}
logger.info("Interface Manager Closed");
}
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
public class DhcpLogicalSwitchListener extends AbstractDataChangeListener<LogicalSwitches> implements AutoCloseable {
private static final Logger logger = LoggerFactory.getLogger(DhcpLogicalSwitchListener.class);
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DataBroker dataBroker;
+
+ private final DataBroker dataBroker;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
public DhcpLogicalSwitchListener(DhcpExternalTunnelManager dhcpManager, DataBroker dataBroker) {
super(LogicalSwitches.class);
this.dhcpExternalTunnelManager = dhcpManager;
this.dataBroker = dataBroker;
+ }
+
+ public void init() {
registerListener();
}
@Override
public void close() throws Exception {
if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- logger.error("Error when cleaning up DataChangeListener.", e);
- }
- listenerRegistration = null;
+ listenerRegistration.close();
}
logger.info("DhcpLogicalSwitchListener Closed");
}
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.HashMap;
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.genius.mdsalutil.ActionInfo;
import org.opendaylight.genius.mdsalutil.ActionType;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.opendaylight.genius.mdsalutil.FlowEntity;
import org.opendaylight.genius.mdsalutil.InstructionInfo;
import org.opendaylight.genius.mdsalutil.InstructionType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class DhcpManager implements AutoCloseable {
+public class DhcpManager {
private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
+ private final IMdsalApiManager mdsalUtil;
+ private final INeutronVpnManager neutronVpnService;
+ private final DhcpserviceConfig config;
private final DataBroker broker;
- IMdsalApiManager mdsalUtil;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
private int dhcpOptLeaseTime = 0;
- private int dhcpOptRenewalTime = 0;
- private int dhcpOptRebindingTime = 0;
private String dhcpOptDefDomainName;
- private INeutronVpnManager neutronVpnService;
+ private DhcpInterfaceEventListener dhcpInterfaceEventListener;
+ private DhcpInterfaceConfigListener dhcpInterfaceConfigListener;
+
+ // cache used to maintain DpnId and physical address for each interface.
+ private static HashMap<String, ImmutablePair<BigInteger, String>> interfaceToDpnIdMacAddress = new HashMap<>();
+
+ public DhcpManager(final IMdsalApiManager mdsalApiManager,
+ final INeutronVpnManager neutronVpnManager,
+ DhcpserviceConfig config, final DataBroker dataBroker,
+ final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ this.mdsalUtil = mdsalApiManager;
+ this.neutronVpnService = neutronVpnManager;
+ this.config = config;
+ this.broker = dataBroker;
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
- /**
- * @param db - dataBroker reference
- */
- public DhcpManager(final DataBroker db) {
- broker = db;
configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
}
- public void setMdsalManager(IMdsalApiManager mdsalManager) {
- this.mdsalUtil = mdsalManager;
- }
-
- public void setNeutronVpnService(INeutronVpnManager neutronVpnService) {
- logger.debug("Setting NeutronVpn dependency");
- this.neutronVpnService = neutronVpnService;
+ public void init() {
+ if (config.isControllerDhcpEnabled()) {
+ dhcpInterfaceEventListener = new DhcpInterfaceEventListener(this, broker, dhcpExternalTunnelManager);
+ dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(broker, dhcpExternalTunnelManager);
+ }
}
- @Override
public void close() throws Exception {
- logger.info("DHCP Manager Closed");
+ if (dhcpInterfaceEventListener != null) {
+ dhcpInterfaceEventListener.close();
+ }
+ if (dhcpInterfaceConfigListener != null) {
+ dhcpInterfaceConfigListener.close();
+ }
}
public int setLeaseDuration(int leaseDuration) {
private void configureLeaseDuration(int leaseTime) {
this.dhcpOptLeaseTime = leaseTime;
- if(leaseTime > 0) {
- this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
- this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
- } else {
- this.dhcpOptRenewalTime = -1;
- this.dhcpOptRebindingTime = -1;
- }
}
public Subnet getNeutronSubnet(Port nPort) {
import java.math.BigInteger;
import java.util.List;
-
import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
private static final Logger LOG = LoggerFactory.getLogger(DhcpNeutronPortListener.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
- private DataBroker broker;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private final DataBroker broker;
public DhcpNeutronPortListener(final DataBroker db, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
super(Port.class, DhcpNeutronPortListener.class);
this.broker = db;
}
+ public void init() {
+ registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+ }
+
@Override
protected InstanceIdentifier<Port> getWildCardPath() {
return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
@Override
public void close() throws Exception {
- if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- LOG.error("Error when cleaning up DhcpNeutronPortListener.", e);
- }
- listenerRegistration = null;
- }
+ super.close();
LOG.debug("DhcpNeutronPortListener Listener Closed");
}
*/
package org.opendaylight.netvirt.dhcpservice;
+import com.google.common.base.Optional;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.opendaylight.controller.liblldp.EtherTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
+public class DhcpPktHandler implements PacketProcessingListener {
private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
+
private final DataBroker dataBroker;
private final DhcpManager dhcpMgr;
- private OdlInterfaceRpcService interfaceManagerRpc;
+ private final OdlInterfaceRpcService interfaceManagerRpc;
+ private final PacketProcessingService pktService;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private final IInterfaceManager interfaceManager;
+
private boolean computeUdpChecksum = true;
- private PacketProcessingService pktService;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
- private IInterfaceManager interfaceManager;
- public DhcpPktHandler(final DataBroker broker, final DhcpManager dhcpManager, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ public DhcpPktHandler(final DataBroker broker,
+ final DhcpManager dhcpManager,
+ final DhcpExternalTunnelManager dhcpExternalTunnelManager,
+ final OdlInterfaceRpcService interfaceManagerRpc,
+ final PacketProcessingService pktService,
+ final IInterfaceManager interfaceManager) {
+ this.interfaceManagerRpc = interfaceManagerRpc;
+ this.pktService = pktService;
this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
this.dataBroker = broker;
- dhcpMgr = dhcpManager;
+ this.dhcpMgr = dhcpManager;
+ this.interfaceManager = interfaceManager;
}
//TODO: Handle this in a separate thread
return (pktInReason == SendToController.class);
}
- @Override
- public void close() throws Exception {
- // TODO Auto-generated method stub
- }
-
- public void setPacketProcessingService(PacketProcessingService packetService) {
- this.pktService = packetService;
- }
-
- public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
- LOG.trace("Registered interfaceManager successfully");
- this.interfaceManagerRpc = interfaceManagerRpc;
- }
-
private String getInterfaceNameFromTag(long portTag) {
String interfaceName = null;
GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(new Integer((int)portTag)).build();
}
return actions;
}
-
- public void setInterfaceManager(IInterfaceManager interfaceManager) {
- this.interfaceManager = interfaceManager;
- }
}
+++ /dev/null
-/*
- * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.netvirt.dhcpservice;
-
-import io.netty.util.concurrent.GlobalEventExecutor;
-import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(DhcpProvider.class);
- private IMdsalApiManager mdsalManager;
- private DhcpPktHandler dhcpPktHandler;
- private Registration packetListener = null;
- private NotificationProviderService notificationService;
- private DhcpManager dhcpManager;
- private NodeListener dhcpNodeListener;
- private INeutronVpnManager neutronVpnManager;
- private DhcpConfigListener dhcpConfigListener;
- private OdlInterfaceRpcService interfaceManagerRpc;
- private DhcpInterfaceEventListener dhcpInterfaceEventListener;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
- private DhcpNeutronPortListener dhcpNeutronPortListener;
- private DhcpLogicalSwitchListener dhcpLogicalSwitchListener;
- private DhcpUCastMacListener dhcpUCastMacListener;
- private ItmRpcService itmRpcService;
- private DhcpInterfaceConfigListener dhcpInterfaceConfigListener;
- private EntityOwnershipService entityOwnershipService;
- private DhcpDesignatedDpnListener dhcpDesignatedDpnListener;
- private boolean controllerDhcpEnabled = true;
- private DhcpSubnetListener dhcpSubnetListener;
- private DhcpHwvtepListener dhcpHwvtepListener;
- private IInterfaceManager interfaceManager;
-
- @Override
- public void onSessionInitiated(ProviderContext session) {
- LOG.info("DhcpProvider Session Initiated");
- try {
- final DataBroker dataBroker = session.getSALService(DataBroker.class);
- final PacketProcessingService pktProcessingService = session.getRpcService(PacketProcessingService.class);
- dhcpManager = new DhcpManager(dataBroker);
- dhcpManager.setMdsalManager(mdsalManager);
- dhcpExternalTunnelManager = new DhcpExternalTunnelManager(dataBroker, mdsalManager, itmRpcService, entityOwnershipService);
- dhcpPktHandler = new DhcpPktHandler(dataBroker, dhcpManager, dhcpExternalTunnelManager);
- dhcpPktHandler.setPacketProcessingService(pktProcessingService);
- dhcpPktHandler.setInterfaceManagerRpc(interfaceManagerRpc);
- dhcpPktHandler.setInterfaceManager(interfaceManager);
- packetListener = notificationService.registerNotificationListener(dhcpPktHandler);
- dhcpNodeListener = new NodeListener(dataBroker, dhcpManager, dhcpExternalTunnelManager);
- dhcpConfigListener = new DhcpConfigListener(dataBroker, dhcpManager);
- dhcpLogicalSwitchListener = new DhcpLogicalSwitchListener(dhcpExternalTunnelManager, dataBroker);
- dhcpUCastMacListener = new DhcpUCastMacListener(dhcpManager,dhcpExternalTunnelManager, dataBroker);
- dhcpUCastMacListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
- dhcpNeutronPortListener = new DhcpNeutronPortListener(dataBroker, dhcpExternalTunnelManager);
- dhcpNeutronPortListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
- dhcpDesignatedDpnListener = new DhcpDesignatedDpnListener(dhcpExternalTunnelManager, dataBroker);
- dhcpDesignatedDpnListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
- if (controllerDhcpEnabled) {
- dhcpInterfaceEventListener = new DhcpInterfaceEventListener(dhcpManager, dataBroker, dhcpExternalTunnelManager);
- dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(dataBroker, dhcpExternalTunnelManager);
- }
- dhcpSubnetListener = new DhcpSubnetListener(dhcpManager,dhcpExternalTunnelManager,dataBroker);
- dhcpSubnetListener.registerListener(LogicalDatastoreType.CONFIGURATION,dataBroker);
- dhcpHwvtepListener = new DhcpHwvtepListener(dataBroker, dhcpExternalTunnelManager);
- } catch (Exception e) {
- LOG.error("Error initializing services {}", e);
- }
-
- // TODO: Remove as part of blueprint fix.
- // This is simply here to get the INeutronVPNManager service which is already
- // moved to blueprint.
- GlobalEventExecutor.INSTANCE.execute(new Runnable() {
- @Override
- public void run() {
- Bundle b = FrameworkUtil.getBundle(DhcpProvider.class);
- if (b == null) {
- return;
- }
- BundleContext bundleContext = b.getBundleContext();
- if (bundleContext == null) {
- return;
- }
- final WaitingServiceTracker<INeutronVpnManager> tracker = WaitingServiceTracker.create(
- INeutronVpnManager.class, bundleContext);
- INeutronVpnManager neutronVpnManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
- LOG.info("DhcpProvider initialized. INeutronVpnManager={}", neutronVpnManager);
- dhcpManager.setNeutronVpnService(neutronVpnManager);
- }
- });
- }
-
- public void setMdsalManager(IMdsalApiManager mdsalManager) {
- this.mdsalManager = mdsalManager;
- }
-
- public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
- this.neutronVpnManager = neutronVpnManager;
- }
-
- @Override
- public void close() throws Exception {
- if(packetListener != null) {
- packetListener.close();
- }
- if(dhcpPktHandler != null) {
- dhcpPktHandler.close();
- }
- if(dhcpNodeListener != null) {
- dhcpNodeListener.close();
- }
- LOG.info("DhcpProvider closed");
- }
-
- public void setNotificationProviderService(NotificationProviderService notificationServiceDependency) {
- this.notificationService = notificationServiceDependency;
- }
-
- public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
- this.interfaceManagerRpc = interfaceManagerRpc;
- }
-
- public void setItmRpcService(ItmRpcService itmRpcService) {
- this.itmRpcService = itmRpcService;
- }
-
- public void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
- this.entityOwnershipService = entityOwnershipService;
- }
-
- public void setControllerDhcpEnabled(boolean controllerDhcpEnabled) {
- this.controllerDhcpEnabled = controllerDhcpEnabled;
- }
-
- public void setInterfaceManager(IInterfaceManager interfaceManager) {
- this.interfaceManager = interfaceManager;
- }
-}
*/
package org.opendaylight.netvirt.dhcpservice;
-import java.math.BigInteger;
-
import com.google.common.base.Optional;
+import java.math.BigInteger;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
-import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-
public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<LocalUcastMacs, DhcpUCastMacListener> implements AutoCloseable {
private static final Logger logger = LoggerFactory.getLogger(DhcpUCastMacListener.class);
- private DataBroker broker;
- private ListenerRegistration<DataChangeListener> listenerRegistration;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
private DhcpManager dhcpManager;
+ private final DataBroker broker;
public DhcpUCastMacListener(DhcpManager dhcpManager,DhcpExternalTunnelManager dhcpExtTunnelMgr, DataBroker dataBroker) {
super(LocalUcastMacs.class, DhcpUCastMacListener.class);
this.dhcpManager = dhcpManager;
}
+ public void init() {
+ registerListener(LogicalDatastoreType.OPERATIONAL, broker);
+ }
+
@Override
protected InstanceIdentifier<LocalUcastMacs> getWildCardPath() {
return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class)
@Override
public void close() throws Exception {
- if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- logger.error("Error when cleaning up DataChangeListener.", e);
- }
- listenerRegistration = null;
- }
+ super.close();
logger.info("DhcpUCastMacListener Closed");
}
import java.math.BigInteger;
import java.util.List;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
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.Node;
private static final Logger LOG = LoggerFactory.getLogger(NodeListener.class);
private ListenerRegistration<DataChangeListener> listenerRegistration;
+
private final DataBroker broker;
- private DhcpManager dhcpManager;
- private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private final DhcpManager dhcpManager;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
- public NodeListener(final DataBroker db, final DhcpManager dhcpMgr, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ public NodeListener(final DataBroker db, final DhcpManager dhcpMgr,
+ final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
super(Node.class);
- broker = db;
- dhcpManager = dhcpMgr;
+ this.broker = db;
+ this.dhcpManager = dhcpMgr;
this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
- registerListener(db);
+ }
+
+ public void init() {
+ registerListener(broker);
}
private void registerListener(final DataBroker db) {
@Override
public void close() throws Exception {
if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- LOG.error("Error when cleaning up NodeListener.", e);
- }
- listenerRegistration = null;
- //ToDo: Should we delete DHCP flows when we are closed?
+ listenerRegistration.close();
}
LOG.debug("Node Listener Closed");
}
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710;
-
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.netvirt.dhcpservice.DhcpProvider;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
-
-public class DhcpServiceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModule {
- public DhcpServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public DhcpServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.DhcpServiceImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- RpcProviderRegistry rpcregistryDependency = getRpcregistryDependency();
- DhcpProvider dhcpProvider = new DhcpProvider();
- dhcpProvider.setControllerDhcpEnabled(getControllerDhcpEnabled());
- dhcpProvider.setNotificationProviderService(getNotificationServiceDependency());
- dhcpProvider.setMdsalManager(getMdsalutilDependency());
- //dhcpProvider.setNeutronVpnManager(getNeutronvpnDependency());
- dhcpProvider.setInterfaceManagerRpc(rpcregistryDependency.getRpcService(OdlInterfaceRpcService.class));
- dhcpProvider.setItmRpcService(rpcregistryDependency.getRpcService(ItmRpcService.class));
- dhcpProvider.setEntityOwnershipService(getEntityOwnershipServiceDependency());
- dhcpProvider.setInterfaceManager(getOdlinterfaceDependency());
- getBrokerDependency().registerProvider(dhcpProvider);
- return dhcpProvider;
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: dhcpservice-impl yang module local name: dhcpservice-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Sat Jul 11 21:38:25 IST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710;
-public class DhcpServiceImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModuleFactory {
-
-}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker"
+ interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+ odl:type="default" />
+ <reference id="rpcRegistry"
+ interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" />
+ <reference id="entityOwnershipService"
+ interface="org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService" />
+ <reference id="mdsalUtils"
+ interface="org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager" />
+ <reference id="neutronVpnMapper"
+ interface="org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager" />
+ <reference id="interfaceManager"
+ interface="org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager" />
+
+ <odl:rpc-service id="odlInterfaceRpcService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService" />
+ <odl:rpc-service id="itmRpcService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService" />
+ <odl:rpc-service id="packetProcessingService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService" />
+
+ <odl:clustered-app-config id="dhcpServiceConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig">
+ </odl:clustered-app-config>
+
+ <bean id="dhcpManager" class="org.opendaylight.netvirt.dhcpservice.DhcpManager"
+ init-method="init" destroy-method="close">
+ <argument ref="mdsalUtils" />
+ <argument ref="neutronVpnMapper" />
+ <argument ref="dhcpServiceConfig" />
+ <argument ref="dataBroker" />
+ <argument ref="dhcpExternalTunnelManager" />
+ </bean>
+
+ <bean id="dhcpExternalTunnelManager" class="org.opendaylight.netvirt.dhcpservice.DhcpExternalTunnelManager"
+ init-method="init">
+ <argument ref="dataBroker" />
+ <argument ref="mdsalUtils" />
+ <argument ref="itmRpcService" />
+ <argument ref="entityOwnershipService" />
+ </bean>
+
+ <bean id="dhcpPktHandler" class="org.opendaylight.netvirt.dhcpservice.DhcpPktHandler">
+ <argument ref="dataBroker" />
+ <argument ref="dhcpManager" />
+ <argument ref="dhcpExternalTunnelManager" />
+ <argument ref="odlInterfaceRpcService" />
+ <argument ref="packetProcessingService" />
+ <argument ref="interfaceManager" />
+ </bean>
+ <odl:notification-listener ref="dhcpPktHandler" />
+
+ <bean id="nodeListener" class="org.opendaylight.netvirt.dhcpservice.NodeListener"
+ init-method="init" destroy-method="close">
+ <argument ref="dataBroker" />
+ <argument ref="dhcpManager" />
+ <argument ref="dhcpExternalTunnelManager" />
+ </bean>
+
+ <bean id="dhcpConfigListener" class="org.opendaylight.netvirt.dhcpservice.DhcpConfigListener"
+ init-method="init" destroy-method="close">
+ <argument ref="dataBroker" />
+ <argument ref="dhcpManager" />
+ </bean>
+
+ <bean id="dhcpLogicalSwitchListener" class="org.opendaylight.netvirt.dhcpservice.DhcpLogicalSwitchListener"
+ init-method="init" destroy-method="close">
+ <argument ref="dhcpExternalTunnelManager" />
+ <argument ref="dataBroker" />
+ </bean>
+
+ <bean id="dhcpUCastMacListener" class="org.opendaylight.netvirt.dhcpservice.DhcpUCastMacListener"
+ init-method="init" destroy-method="close">
+ <argument ref="dhcpManager" />
+ <argument ref="dhcpExternalTunnelManager" />
+ <argument ref="dataBroker" />
+ </bean>
+
+ <bean id="dhcpNeutronPortListener" class="org.opendaylight.netvirt.dhcpservice.DhcpNeutronPortListener"
+ init-method="init" destroy-method="close">
+ <argument ref="dataBroker" />
+ <argument ref="dhcpExternalTunnelManager" />
+ </bean>
+
+ <bean id="dhcpDesignatedDpnListener" class="org.opendaylight.netvirt.dhcpservice.DhcpDesignatedDpnListener"
+ init-method="init" destroy-method="close">
+ <argument ref="dhcpExternalTunnelManager" />
+ <argument ref="dataBroker" />
+ </bean>
+</blueprint>
\ No newline at end of file
--- /dev/null
+module dhcpservice-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:dhcpservice:config";
+ prefix "dhcpservice-config";
+
+ description
+ "Service definition for dhcpservice project";
+
+ revision "2015-07-10" {
+ description
+ "Initial revision";
+ }
+
+ container dhcpservice-config {
+ leaf controller-dhcp-enabled {
+ description "Enable the dhcpservice on the controller";
+ type boolean;
+ default true;
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-module dhcpservice-impl {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:dhcpservice:impl";
- prefix "dhcpservice-impl";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
- import odl-mdsalutil { prefix odl-mdsal; revision-date 2016-04-06;}
- //import neutronvpn-api { prefix nvpn; revision-date 2015-08-12;}
- import opendaylight-entity-ownership-service { prefix eos; revision-date 2015-08-10;}
- import odl-interface {prefix odlif; revision-date 2016-04-06;}
-
- description
- "Service definition for dhcpservice project";
-
- revision "2015-07-10" {
- description
- "Initial revision";
- }
-
- identity dhcpservice-impl {
- base config:module-type;
- config:java-name-prefix DhcpServiceImpl;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case dhcpservice-impl {
- when "/config:modules/config:module/config:type = 'dhcpservice-impl'";
- container broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-broker-osgi-registry;
- }
- }
- }
- container rpcregistry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-rpc-registry;
- }
- }
- }
- container notification-service {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-notification-service;
- }
- }
- }
-
- container mdsalutil {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity odl-mdsal:odl-mdsalutil;
- }
- }
- }
-
- /*container neutronvpn {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity nvpn:neutronvpn-api;
- }
- }
- }*/
-
- container entity-ownership-service {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity eos:entity-ownership-service;
- }
- }
- }
-
- container odlinterface {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity odlif:odl-interface;
- }
- }
- }
-
- leaf controller-dhcp-enabled {
- description "Enable the dhcpservice on the controller";
- type boolean;
- }
- }
- }
-}
<artifactId>dhcpservice-impl</artifactId>
<version>${vpnservices.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>dhcpservice-impl</artifactId>
- <version>${vpnservices.version}</version>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dhcpservice-api</artifactId>
<!--<bundle>wrap:mvn:javax.servlet/servlet-api/2.5</bundle>-->
<configfile finalname="${configfile.directory}/bgpmanager-impl-default-config.xml">mvn:org.opendaylight.netvirt/bgpmanager-impl/{{VERSION}}/xml/config</configfile>
<configfile finalname="${configfile.directory}/vpnmanager-impl-default-config.xml">mvn:org.opendaylight.netvirt/vpnmanager-impl/{{VERSION}}/xml/config</configfile>
- <configfile finalname="${configfile.directory}/dhcpservice-impl-default-config.xml">mvn:org.opendaylight.netvirt/dhcpservice-impl/{{VERSION}}/xml/config</configfile>
<configfile finalname="${configfile.directory}/elanmanager-impl-default-config.xml">mvn:org.opendaylight.netvirt/elanmanager-impl/{{VERSION}}/xml/config</configfile>
<configfile finalname="${configfile.directory}/natservice-impl-default-config.xml">mvn:org.opendaylight.netvirt/natservice-impl/{{VERSION}}/xml/config</configfile>
<!--<configfile finalname="${configfile.directory}/cloud-servicechain-impl-default-config.xml">mvn:org.opendaylight.netvirt/cloud-servicechain-impl/{{VERSION}}/xml/config</configfile>-->
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
+import org.opendaylight.netvirt.it.NetvirtITConstants.DefaultFlow;
+import org.opendaylight.netvirt.utils.netvirt.it.utils.FlowITUtil;
import org.opendaylight.netvirt.utils.netvirt.it.utils.NetITUtil;
import org.opendaylight.netvirt.vpnmanager.VpnserviceProvider;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
private static OvsdbItUtils itUtils;
private static MdsalUtils mdsalUtils = null;
private static SouthboundUtils southboundUtils;
+ private static FlowITUtil flowITUtil;
private static String addressStr;
private static String portStr;
private static String connectionType;
assertNotNull("mdsalUtils should not be null", mdsalUtils);
southboundUtils = new SouthboundUtils(mdsalUtils);
assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, this.getNetvirtTopology());
-
-// TODO: need to implement new pipelineOrchestrator for the vpnservice pipeline
+ flowITUtil = new FlowITUtil(dataBroker);
setup.set(true);
}
return found;
}
+ private void validateDefaultFlows(long datapathId, int timeout){
+ LOG.info("Validating default flows");
+ for (DefaultFlow defaultFlow : DefaultFlow.values()){
+ try {
+ flowITUtil.verifyFlowByFields(datapathId, defaultFlow.getFlowId(), defaultFlow.getTableId(), timeout);
+ } catch (Exception e){
+ LOG.error("Failed to verify flow id : {}", defaultFlow.getFlowId());
+ fail();
+ }
+ }
+ }
/**
* Test for basic southbound events to netvirt.
NodeInfo nodeInfo = itUtils.createNodeInfo(connectionInfo, null);
nodeInfo.connect();
+ //validate default flows
+ validateDefaultFlows(nodeInfo.datapathId, 60*1000);
+
LOG.info("testNetVirt: should be connected: {}", nodeInfo.ovsdbNode.getNodeId());
southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, NetvirtITConstants.PORT_NAME,
NodeInfo nodeInfo = itUtils.createNodeInfo(connectionInfo, null);
nodeInfo.connect();
- // waiting for the default flows to be installed before adding the ports
- Thread.sleep(20*100);
+ //validate default flows
+ validateDefaultFlows(nodeInfo.datapathId, 60*1000);
//create the neutron objects
NetITUtil net = new NetITUtil(ovs, southboundUtils, mdsalUtils);
String port1 = net.createPort(nodeInfo.bridgeNode);
String port2 = net.createPort(nodeInfo.bridgeNode);
-// TODO - need to add pipeline validation
-
Thread.sleep(1000);
//ovs interface configuration for running the ping test
*/
package org.opendaylight.netvirt.it;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+
/**
* Constants for NetvirtIT
*/
public static final String PORT_NAME = "porttest";
public static final String INTEGRATION_BRIDGE_NAME = "br-int";
public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
+
+
+ public enum DefaultFlow {
+
+ DHCP("DHCPTableMissFlow", NwConstants.DHCP_TABLE),
+ IPV6("IPv6TableMissFlow", NwConstants.IPV6_TABLE),
+ ELAN_SMAC(""+NwConstants.ELAN_SMAC_TABLE, NwConstants.ELAN_SMAC_TABLE),
+ ELAN_DMAC(""+NwConstants.ELAN_DMAC_TABLE, NwConstants.ELAN_DMAC_TABLE);
+
+ String flowId;
+ short tableId;
+
+ DefaultFlow(String flowId, short tableId){
+ this.flowId = flowId;
+ this.tableId = tableId;
+ }
+
+ public String getFlowId() {
+ return flowId;
+ }
+
+ public short getTableId() {
+ return tableId;
+ }
+ }
}
*/
public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> implements AutoCloseable{
private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
+ private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
private ListenerRegistration<DataChangeListener> listenerRegistration;
private final DataBroker broker;
private OdlInterfaceRpcService interfaceManager;
}
actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
- instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, vpnId, internalIp);
return 0;
}
- List<ActionInfo> actionList = NatUtil.getEgressActionsForInterface(interfaceManager, extInterface, null);
- if (actionList == null || actionList.isEmpty()) {
- LOG.warn("No actions found for interface {} vpn id {}", extInterface, vpnId);
+ List<ActionInfo> egressActionList = NatUtil.getEgressActionsForInterface(interfaceManager, extInterface, null);
+ if (egressActionList == null || egressActionList.isEmpty()) {
+ LOG.warn("No Egress actions found for interface {} vpn id {}", extInterface, vpnId);
return 0;
}
- if(!Strings.isNullOrEmpty(macAddress)) {
- actionList.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{ macAddress }));
+ List<ActionInfo> actionList = new ArrayList<>();
+ if (!Strings.isNullOrEmpty(macAddress)) {
+ actionList.add(new ActionInfo(ActionType.set_field_eth_dest, new String[] { macAddress }));
}
+ actionList.addAll(egressActionList);
List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
listBucketInfo.add(new BucketInfo(actionList));
long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerId), idManager);
GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpId, groupId, routerId, GroupTypes.GroupIndirect,
listBucketInfo);
LOG.trace("Install ext-net Group: id {} gw mac address {} vpn id {}", groupId, macAddress, vpnId);
- mdsalManager.installGroup(groupEntity);
+ mdsalManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
return groupId;
}
@Override
public void onAddFloatingIp(final BigInteger dpnId, final String routerId,
Uuid networkId, final String interfaceName, final String externalIp, final String internalIp) {
- final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ final String vpnName = getAssociatedVPN(networkId, routerId);
if(vpnName == null) {
LOG.info("No VPN associated with ext nw {} to handle add floating ip configuration {} in router {}",
networkId, externalIp, routerId);
@Override
public void onRemoveFloatingIp(final BigInteger dpnId, String routerId, Uuid networkId, final String externalIp,
String internalIp, final long label) {
- final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ final String vpnName = getAssociatedVPN(networkId, routerId);
if(vpnName == null) {
LOG.info("No VPN associated with ext nw {} to handle remove floating ip configuration {} in router {}",
networkId, externalIp, routerId);
RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp + "/32").setServiceId(label).build();
Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
- ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future),
+ ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future),
new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
@Override
LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
}
-}
\ No newline at end of file
+ private String getAssociatedVPN(Uuid networkId, String routerId) {
+ String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ return vpnName != null ? vpnName : routerId;
+ }
+}
public static final Class ETHERTYPE_IPV4 = EthertypeV4.class;
+ public static final String IPV4_ALL_NETWORK = "0.0.0.0/0";
+ public static final String IPV6_ALL_NETWORK = "::/0";
+
// default acp type
public static final Class<? extends AclBase> ACLTYPE = Ipv4Acl.class;
extends AsyncDataTreeChangeListenerBase<SecurityRule, NeutronSecurityRuleListener> {
private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleListener.class);
private final DataBroker dataBroker;
- private static final ImmutableBiMap<Class<? extends DirectionBase>, Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase>> DIRECTION_MAP = ImmutableBiMap.of(
+ private static final ImmutableBiMap<Class<? extends DirectionBase>, Class<? extends org.opendaylight.yang.gen.
+ v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase>> DIRECTION_MAP = ImmutableBiMap.of(
DirectionEgress.class, NeutronSecurityRuleConstants.DIRECTION_EGRESS,
DirectionIngress.class, NeutronSecurityRuleConstants.DIRECTION_INGRESS);
private static final ImmutableBiMap<Class<? extends ProtocolBase>, Short> PROTOCOL_MAP = ImmutableBiMap.of(
aceIpBuilder.setDestinationPortRange(destinationPortRangeBuilder.build());
}
}
- if (securityRule.getEthertype() != null) {
- aceIpBuilder = handleEtherType(securityRule, aceIpBuilder);
- }
- if (securityRule.getRemoteIpPrefix() != null) {
- aceIpBuilder = handleRemoteIpPrefix(securityRule, aceIpBuilder, isDirectionIngress);
- }
+ aceIpBuilder = handleRemoteIpPrefix(securityRule, aceIpBuilder, isDirectionIngress);
if (securityRule.getRemoteGroupId() != null) {
securityRuleAttrBuilder.setRemoteGroupId(securityRule.getRemoteGroupId());
}
private AceIpBuilder handleEtherType(SecurityRule securityRule, AceIpBuilder aceIpBuilder) {
if (NeutronSecurityRuleConstants.ETHERTYPE_IPV4.equals(securityRule.getEthertype())) {
AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
+ aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(
+ NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
+ aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(
+ NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
} else {
AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
+ aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
+ NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
+ aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
+ NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
+
}
return aceIpBuilder;
}
- private AceIpBuilder handleRemoteIpPrefix(SecurityRule securityRule, AceIpBuilder aceIpBuilder, boolean isDirectionIngress) {
- if (securityRule.getRemoteIpPrefix().getIpv4Prefix() != null) {
- AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
- if (isDirectionIngress) {
- aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(securityRule.getRemoteIpPrefix().getIpv4Prefix().getValue()));
+ private AceIpBuilder handleRemoteIpPrefix(SecurityRule securityRule, AceIpBuilder aceIpBuilder,
+ boolean isDirectionIngress) {
+ if (securityRule.getRemoteIpPrefix() != null) {
+ if (securityRule.getRemoteIpPrefix().getIpv4Prefix() != null) {
+ AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
+ if (isDirectionIngress) {
+ aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(securityRule
+ .getRemoteIpPrefix().getIpv4Prefix().getValue()));
+ } else {
+ aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(securityRule
+ .getRemoteIpPrefix().getIpv4Prefix().getValue()));
+ }
+ aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
} else {
- aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(securityRule.getRemoteIpPrefix().getIpv4Prefix().getValue()));
+ AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
+ if (isDirectionIngress) {
+ aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
+ securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
+ } else {
+ aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
+ securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
+ }
+ aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
}
- aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
} else {
- AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
- if (isDirectionIngress) {
- aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
- } else {
- aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
-
+ if (securityRule.getEthertype() != null) {
+ handleEtherType( securityRule, aceIpBuilder);
}
- aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
}
+
return aceIpBuilder;
}
--- /dev/null
+/*
+ * Copyright (c) 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.netvirt.utils.netvirt.it.utils;
+
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import org.junit.Assert;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.utils.mdsal.utils.NotifyingDataChangeListener;
+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.Match;
+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.Node;
+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.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifPacketIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifSwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcRemoveFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcUpdateFlowOriginal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcUpdateFlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionListGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.AllMatchesGrouping;
+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.NxAugMatchNotifPacketIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNotifSwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNotifUpdateFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcRemoveFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcUpdateFlowOriginal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcUpdateFlowUpdated;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Flow utils for NetvirtIT
+ */
+public class FlowITUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlowITUtil.class);
+ private static final String OPENFLOW = "openflow";
+
+ private DataBroker dataBroker;
+
+ public FlowITUtil(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ private final static Class[] MATCH_AUGMENTATIONS = {GeneralAugMatchNodesNodeTableFlow.class,
+ GeneralAugMatchNotifUpdateFlowStats.class,
+ GeneralAugMatchNotifPacketIn.class,
+ GeneralAugMatchNotifSwitchFlowRemoved.class,
+ GeneralAugMatchRpcAddFlow.class,
+ GeneralAugMatchRpcRemoveFlow.class,
+ GeneralAugMatchRpcUpdateFlowOriginal.class,
+ GeneralAugMatchRpcUpdateFlowUpdated.class};
+
+ private final static Class[] EXT_LIST_AUGMENTATIONS = {NxAugMatchNodesNodeTableFlow.class,
+ NxAugMatchNotifUpdateFlowStats.class,
+ NxAugMatchNotifPacketIn.class,
+ NxAugMatchNotifSwitchFlowRemoved.class,
+ NxAugMatchRpcAddFlow.class,
+ NxAugMatchRpcRemoveFlow.class,
+ NxAugMatchRpcUpdateFlowOriginal.class,
+ NxAugMatchRpcUpdateFlowUpdated.class};
+
+ private static Integer DEFAULT_PRIORITY = new Integer(32768);
+
+ private String getNodeName(long dpidLong) {
+ return OPENFLOW + ":" + dpidLong;
+ }
+
+ private NodeBuilder createNodeBuilder(String nodeId) {
+ NodeBuilder builder = new NodeBuilder();
+ builder.setId(new NodeId(nodeId));
+ builder.setKey(new NodeKey(builder.getId()));
+ return builder;
+ }
+
+ private NodeBuilder createNodeBuilder(long dpidLong) {
+ return createNodeBuilder(getNodeName(dpidLong));
+ }
+
+ private InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeBuilder.getKey())
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flowBuilder.getTableId()))
+ .child(Flow.class, flowBuilder.getKey()).build();
+ }
+
+ private InstanceIdentifier<Table> createTablePath(NodeBuilder nodeBuilder, short table) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeBuilder.getKey())
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(table)).build();
+ }
+
+ private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder,
+ ReadOnlyTransaction readTx, final LogicalDatastoreType store) {
+ try {
+ Optional<Flow> data = readTx.read(store, createFlowPath(flowBuilder, nodeBuilder)).get();
+ if (data.isPresent()) {
+ return data.get();
+ }
+ } catch (InterruptedException|ExecutionException e) {
+ LOG.error("Failed to get flow {}", flowBuilder.getFlowName(), e);
+ }
+
+ LOG.info("Cannot find data for Flow {} in {}", flowBuilder.getFlowName(), store);
+ return null;
+ }
+
+
+ /**
+ * Sets up common defaults for the given flow builder: a flow identifier and key based on the given flow name,
+ * strict, no barrier, the given table identifier, no hard timeout and no idle timeout.
+ *
+ * @param flowBuilder The flow builder.
+ * @param flowName The flow name.
+ * @param table The table.
+ * @return The flow builder.
+ */
+ private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table) {
+ final FlowId flowId = new FlowId(flowName);
+ flowBuilder
+ .setId(flowId)
+ .setStrict(true)
+ .setBarrier(false)
+ .setTableId(table)
+ .setKey(new FlowKey(flowId))
+ .setFlowName(flowName)
+ .setHardTimeout(0)
+ .setIdleTimeout(0);
+ return flowBuilder;
+ }
+
+ private Table getTable(NodeBuilder nodeBuilder, short table,
+ ReadOnlyTransaction readTx, final LogicalDatastoreType store) {
+ try {
+ Optional<Table> data = readTx.read(store, this.createTablePath(nodeBuilder, table)).get();
+ if (data.isPresent()) {
+ return data.get();
+ }
+ } catch (InterruptedException|ExecutionException e) {
+ LOG.error("Failed to get table {}", table, e);
+ }
+
+ LOG.info("Cannot find data for table {} in {}", table, store);
+ return null;
+ }
+
+ /**
+ * Verify <strong>by flow id</strong> that the given flow was installed in a table. This method will wait 10
+ * seconds for the flows to appear in each of the md-sal CONFIGURATION and OPERATIONAL data stores
+ * @param datapathId dpid where flow is installed
+ * @param flowId The "name" of the flow, e.g., "TunnelFloodOut_100"
+ * @param table integer value of table
+ * @throws InterruptedException if interrupted while waiting for flow to appear in mdsal
+ */
+ public void verifyFlowById(long datapathId, String flowId, short table) throws InterruptedException {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+ this.createNodeBuilder(datapathId);
+ FlowBuilder flowBuilder =
+ this.initFlowBuilder(new FlowBuilder(), flowId, table);
+
+ InstanceIdentifier<Flow> iid = this.createFlowPath(flowBuilder, nodeBuilder);
+
+ NotifyingDataChangeListener waitForIt = new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ iid, null);
+ waitForIt.registerDataChangeListener(dataBroker);
+ waitForIt.waitForCreation(10000);
+
+ Flow flow = this.getFlow(flowBuilder, nodeBuilder,
+ dataBroker.newReadOnlyTransaction(), LogicalDatastoreType.CONFIGURATION);
+ assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+
+ waitForIt = new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, null);
+ waitForIt.registerDataChangeListener(dataBroker);
+ waitForIt.waitForCreation(10000);
+
+ flow = this.getFlow(flowBuilder, nodeBuilder,
+ dataBroker.newReadOnlyTransaction(), LogicalDatastoreType.OPERATIONAL);
+ assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(),
+ flow);
+ }
+
+ /**
+ * Verify that a flow in CONFIGURATION exists also in OPERATIONAL. This is done by looking up the flow in
+ * CONFIGURATION by flowId and searching the flow's priority and matches in the OPERATIONAL.
+ * @param datapathId dpid where flow is installed
+ * @param flowId The "name" of the flow, e.g., "TunnelFloodOut_100"
+ * @param tableId integer value of table
+ * @param waitFor Retry every second for waitFor milliseconds
+ * @throws InterruptedException if interrupted while waiting for flow to appear in mdsal
+ */
+ public void verifyFlowByFields(long datapathId, String flowId, short tableId, int waitFor) throws InterruptedException {
+ long start = System.currentTimeMillis();
+ int i = 0;
+ do {
+ try {
+ i++;
+ LOG.warn("DEBUG ODED : VERIFY FLOW {}", i);
+ verifyFlowByFields(datapathId, flowId, tableId);
+ return;
+ } catch (AssertionError e) {
+ if((System.currentTimeMillis() - start) >= waitFor) {
+ throw e;
+ }
+ Thread.sleep(1000);
+ }
+ } while (true);
+ }
+
+ /**
+ * Verify that a flow in CONFIGURATION exists also in OPERATIONAL. This is done by looking up the flow in
+ * CONFIGURATION by flowId and searching the flow's priority and matches in the OPERATIONAL.
+ * @param datapathId dpid where flow is installed
+ * @param flowId The "name" of the flow, e.g., "TunnelFloodOut_100"
+ * @param tableId integer value of table
+ * @throws InterruptedException if interrupted while waiting for flow to appear in mdsal
+ */
+ public void verifyFlowByFields(long datapathId, String flowId, short tableId) throws InterruptedException {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+ this.createNodeBuilder(datapathId);
+ FlowBuilder flowBuilder =
+ this.initFlowBuilder(new FlowBuilder(), flowId, tableId);
+
+ InstanceIdentifier<Flow> iid = this.createFlowPath(flowBuilder, nodeBuilder);
+
+ NotifyingDataChangeListener waitForIt = new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ iid, null);
+ waitForIt.registerDataChangeListener(dataBroker);
+ waitForIt.waitForCreation(10000);
+
+ Flow configFlow = this.getFlow(flowBuilder, nodeBuilder,
+ dataBroker.newReadOnlyTransaction(), LogicalDatastoreType.CONFIGURATION);
+ assertNotNull("Could not read flow " + flowId + " from configuration", configFlow);
+
+ Table table = this.getTable(nodeBuilder, tableId, dataBroker.newReadOnlyTransaction(),
+ LogicalDatastoreType.OPERATIONAL);
+ assertNotNull("Could not read table " + tableId + " from operational", table);
+
+ List<Flow> flows = table.getFlow();
+ Assert.assertNotNull("No flows found for table", flows);
+
+
+ for(Flow opFlow : flows) {
+ if (checkFlowsEqual(configFlow, opFlow)) {
+ return;
+ }
+ }
+ Assert.fail("Could not find matching flow in operational for " + flowId);
+ }
+
+ private boolean isMatchInList(AllMatchesGrouping match, List<AllMatchesGrouping> matchList) {
+ for (AllMatchesGrouping match2 : matchList) {
+ if (areMatchAugmentationsEqual(match, match2)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean checkFlowsEqual(Flow configFlow, Flow opFlow) {
+ Integer configPrio = configFlow.getPriority();
+ Integer opPrio = opFlow.getPriority();
+ if (!Objects.equals(configPrio == null ? DEFAULT_PRIORITY : configPrio,
+ opPrio == null ? DEFAULT_PRIORITY : opPrio)) {
+ return false;
+ }
+ return areMatchesEqual(configFlow.getMatch(), opFlow.getMatch());
+ }
+
+ private boolean areMatchesEqual(Match m1, Match m2) {
+ if (m1 == null && m2 == null) {
+ return true;
+ }
+
+ if (m1 == null || m2 == null) {
+ return false;
+ }
+
+ if (!Objects.equals(m1.getInPort(), m2.getInPort())) { return false; }
+ if (!Objects.equals(m1.getInPhyPort(), m2.getInPhyPort())) { return false; }
+ if (!Objects.equals(m1.getMetadata(), m2.getMetadata())) { return false; }
+ if (!Objects.equals(m1.getTunnel(), m2.getTunnel())) { return false; }
+ if (!Objects.equals(m1.getEthernetMatch(), m2.getEthernetMatch())) { return false; }
+ if (!Objects.equals(m1.getVlanMatch(), m2.getVlanMatch())) { return false; }
+ if (!Objects.equals(m1.getIpMatch(), m2.getIpMatch())) { return false; }
+ if (!Objects.equals(m1.getLayer3Match(), m2.getLayer3Match())) { return false; }
+ if (!Objects.equals(m1.getLayer4Match(), m2.getLayer4Match())) { return false; }
+ if (!Objects.equals(m1.getIcmpv4Match(), m2.getIcmpv4Match())) { return false; }
+ if (!Objects.equals(m1.getIcmpv6Match(), m2.getIcmpv6Match())) { return false; }
+ if (!Objects.equals(m1.getProtocolMatchFields(), m2.getProtocolMatchFields())) { return false; }
+ if (!Objects.equals(m1.getTcpFlagsMatch(), m2.getTcpFlagsMatch())) { return false; }
+
+ MatchAugmentationIterator it = new MatchAugmentationIterator(m1);
+ List<AllMatchesGrouping> side1Matches = Lists.newArrayList();
+ AllMatchesGrouping aug;
+ while (null != (aug = it.next())) {
+ side1Matches.add(aug);
+ }
+
+ it = new MatchAugmentationIterator(m2);
+ while(null != (aug = it.next())) {
+ if (!isMatchInList(aug, side1Matches)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean areMatchAugmentationsEqual(AllMatchesGrouping obj1, AllMatchesGrouping obj2) {
+ if (obj1 == null && obj2 == null) {
+ return true;
+ }
+
+ if (obj1 == null || obj2 == null) {
+ return false;
+ }
+ if (!Objects.equals(obj1.getNxmOfEthSrc(), obj2.getNxmOfEthSrc())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfArpOp(), obj2.getNxmOfArpOp())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfUdpDst(), obj2.getNxmOfUdpDst())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxNshc3(), obj2.getNxmNxNshc3())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxCtZone(), obj2.getNxmNxCtZone())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxArpSha(), obj2.getNxmNxArpSha())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfIcmpType(), obj2.getNxmOfIcmpType())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxNshc1(), obj2.getNxmNxNshc1())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfArpSpa(), obj2.getNxmOfArpSpa())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxTunIpv4Dst(), obj2.getNxmNxTunIpv4Dst())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfTcpSrc(), obj2.getNxmOfTcpSrc())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxNshc4(), obj2.getNxmNxNshc4())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfArpTpa(), obj2.getNxmOfArpTpa())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfTcpDst(), obj2.getNxmOfTcpDst())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxNsi(), obj2.getNxmNxNsi())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxNshc2(), obj2.getNxmNxNshc2())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxArpTha(), obj2.getNxmNxArpTha())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxReg(), obj2.getNxmNxReg())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfIpSrc(), obj2.getNxmOfIpSrc())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfEthType(), obj2.getNxmOfEthType())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfEthDst(), obj2.getNxmOfEthDst())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfUdpSrc(), obj2.getNxmOfUdpSrc())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxCtState(), obj2.getNxmNxCtState())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxTunIpv4Src(), obj2.getNxmNxTunIpv4Src())) { return false; }
+ if (!Objects.equals(obj1.getNxmOfIpDst(), obj2.getNxmOfIpDst())) { return false; }
+ if (!Objects.equals(obj1.getNxmNxNsp(), obj2.getNxmNxNsp())) { return false; }
+
+ return true;
+ }
+
+ class MatchAugmentationIterator {
+
+ Match myMatch;
+
+ public MatchAugmentationIterator(Match match) {
+ this.myMatch = match;
+ }
+
+ private int matchAugmentationIdx = 0;
+ private int extListListIdx = 0;
+ private int extListAugmentationIdx = 0;
+
+ public AllMatchesGrouping next() {
+
+ while (matchAugmentationIdx < MATCH_AUGMENTATIONS.length) {
+ GeneralExtensionListGrouping extensionListGrouping = (GeneralExtensionListGrouping)
+ myMatch.getAugmentation(MATCH_AUGMENTATIONS[matchAugmentationIdx]);
+
+ if (null != extensionListGrouping) {
+ List<ExtensionList> extListList = extensionListGrouping.getExtensionList();
+
+ while (extListListIdx < extListList.size()) {
+
+ ExtensionList extList = extListList.get(extListListIdx);
+
+ while(extListAugmentationIdx < EXT_LIST_AUGMENTATIONS.length) {
+ Augmentation res = extList.getExtension().getAugmentation(
+ EXT_LIST_AUGMENTATIONS[extListAugmentationIdx]);
+ ++extListAugmentationIdx;
+ if (res != null) {
+ return (AllMatchesGrouping) res;
+ }
+ }
+ extListAugmentationIdx = 0;
+ ++extListListIdx;
+ }
+ extListListIdx = 0;
+ }
+ ++matchAugmentationIdx;
+
+ }
+
+ return null;
+ }
+
+ }
+
+}