From 1e942995f39c91805c647d5a5cfe7a235da20cdd Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Tue, 2 Aug 2016 02:03:17 -0700 Subject: [PATCH] OpenStack Networking SFC Flow classifier translator Patch contains translator code that converts OpenStack Networking SFC flow classifier neutron yang models to OpenDaylight ACL Flow classifier yang models Change-Id: I028e312755c968cbeb1f2c50a1152d65f83463ce Signed-off-by: Anil Vishnoi --- .../DelegatingDataTreeListener.java | 106 +++++++++ .../translator/INeutronSfcDataProcessor.java | 46 ++++ .../sfc/translator/NeutronMdsalHelper.java | 29 +++ .../OpenStackSFCTranslatorProvider.java | 12 +- .../sfc/translator/SfcMdsalHelper.java | 55 +++++ .../FlowClassifierTranslator.java | 225 ++++++++++++++++++ .../NeutronFlowClassifierListener.java | 31 +++ 7 files changed, 497 insertions(+), 7 deletions(-) create mode 100644 openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/DelegatingDataTreeListener.java create mode 100644 openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/INeutronSfcDataProcessor.java create mode 100644 openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/NeutronMdsalHelper.java create mode 100644 openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/SfcMdsalHelper.java create mode 100644 openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/FlowClassifierTranslator.java create mode 100644 openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/NeutronFlowClassifierListener.java diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/DelegatingDataTreeListener.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/DelegatingDataTreeListener.java new file mode 100644 index 0000000000..f960c98415 --- /dev/null +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/DelegatingDataTreeListener.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, 2016 Dell, 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.openstack.sfc.translator; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +/** + * Data-tree listener which delegates data processing to a {@link INeutronSfcDataProcessor}. + */ +public class DelegatingDataTreeListener implements AutoCloseable, DataTreeChangeListener { + private static final Logger LOG = LoggerFactory.getLogger(DelegatingDataTreeListener.class); + private static final ThreadFactory threadFactory = new ThreadFactoryBuilder() + .setNameFormat("NeutronSfcListener-%d").build(); + private final ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory); + private final INeutronSfcDataProcessor dataProcessor; + private ListenerRegistration> listenerRegistration; + + public DelegatingDataTreeListener(INeutronSfcDataProcessor dataProcessor, + DataBroker db, DataTreeIdentifier treeId) { + this.dataProcessor = Preconditions.checkNotNull(dataProcessor, "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!")); + } + + private void registerListener(final DataBroker db, DataTreeIdentifier treeId) { + try { + LOG.info("Registering Data Change Listener for {}", getClass().getSimpleName()); + listenerRegistration = db.registerDataTreeChangeListener(treeId, this); + } catch (final Exception e) { + LOG.warn("{} DataChange listener registration fail!", getClass().getSimpleName(), e); + throw new IllegalStateException("DataTreeListener startup fail! System needs restart.", e); + } + } + + private void processChanges(Collection> changes) { + LOG.info("onDataTreeChanged: Received Data Tree Changed {}", changes); + for (DataTreeModification change : changes) { + final InstanceIdentifier key = change.getRootPath().getRootIdentifier(); + final DataObjectModification mod = change.getRootNode(); + LOG.info("onDataTreeChanged: Received Data Tree Changed Update of Type={} for Key={}", + mod.getModificationType(), key); + switch (mod.getModificationType()) { + case DELETE: + dataProcessor.remove(key, mod.getDataBefore()); + break; + case SUBTREE_MODIFIED: + dataProcessor.update(key, mod.getDataBefore(), mod.getDataAfter()); + break; + case WRITE: + if (mod.getDataBefore() == null) { + dataProcessor.add(key, mod.getDataAfter()); + } else { + dataProcessor.update(key, mod.getDataBefore(), mod.getDataAfter()); + } + break; + default: + throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType()); + } + } + } + + @Override + public void onDataTreeChanged(@Nonnull final Collection> changes) { + Preconditions.checkNotNull(changes, "Changes may not be null!"); + executorService.submit(new Runnable() { + @Override + public void run() { + processChanges(changes); + } + }); + } + + @Override + public void close() { + if (listenerRegistration != null) { + listenerRegistration.close(); + listenerRegistration = null; + } + if (executorService != null) { + executorService.shutdownNow(); + } + } +} diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/INeutronSfcDataProcessor.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/INeutronSfcDataProcessor.java new file mode 100644 index 0000000000..829b87ec78 --- /dev/null +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/INeutronSfcDataProcessor.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, 2016 Dell, 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.openstack.sfc.translator; + +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Neutron SFC yang model processor + */ +public interface INeutronSfcDataProcessor { + + /** + * Method removes DataObject which is identified by InstanceIdentifier. + * + * @param identifier - the whole path to DataObject + * @param del - DataObject for removing + */ + void remove(InstanceIdentifier identifier, D del); + + /** + * Method updates the original DataObject to the update DataObject. + * Both are identified by same InstanceIdentifier. + * + * @param identifier - the whole path to DataObject + * @param original - original DataObject (for update) + * @param update - changed DataObject (contain updates) + */ + void update(InstanceIdentifier identifier, D original, D update); + + /** + * Method adds the DataObject which is identified by InstanceIdentifier + * to device. + * + * @param identifier - the whole path to new DataObject + * @param add - new DataObject + */ + void add(InstanceIdentifier identifier, D add); + +} diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/NeutronMdsalHelper.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/NeutronMdsalHelper.java new file mode 100644 index 0000000000..7b2242a486 --- /dev/null +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/NeutronMdsalHelper.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Brocade Communications Systems, 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.openstack.sfc.translator; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility functions to read Neutron models (e.g network, subnet, port, sfc flow classifier + * port pair, port group, port chain) from md-sal data store. + */ +public class NeutronMdsalHelper { + private static final Logger LOG = LoggerFactory.getLogger(NeutronMdsalHelper.class); + + private final DataBroker dataBroker; + private final MdsalUtils mdsalUtils; + + public NeutronMdsalHelper(DataBroker dataBroker) { + this.dataBroker = dataBroker; + mdsalUtils = new MdsalUtils(this.dataBroker); + } +} diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/OpenStackSFCTranslatorProvider.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/OpenStackSFCTranslatorProvider.java index cf2f1611b4..9e3859ee28 100644 --- a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/OpenStackSFCTranslatorProvider.java +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/OpenStackSFCTranslatorProvider.java @@ -9,9 +9,9 @@ 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.openstack.sfc.translator.config.rev160720.OpenstackSfcTranslatorConfig; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,9 +20,7 @@ public class OpenStackSFCTranslatorProvider implements AutoCloseable { private final DataBroker dataBroker; private final BundleContext bundleContext; - - private ServiceRegistration reg; - + private final FlowClassifierTranslator flowClassifierTranslator; public OpenStackSFCTranslatorProvider( final DataBroker dataBroker, final OpenstackSfcTranslatorConfig openstackSfcTranslatorConfig, @@ -30,17 +28,17 @@ public class OpenStackSFCTranslatorProvider implements AutoCloseable { LOG.info("OpenStack SFC Translator started"); this.dataBroker = dataBroker; this.bundleContext = bundleContext; + flowClassifierTranslator = new FlowClassifierTranslator(dataBroker); } + //This method will be called by blueprint, during bundle initialization. public void start() { LOG.info("OpenStack SFC Translator Session Initiated"); + flowClassifierTranslator.start(); } @Override public void close() throws Exception { LOG.info("OpenStack SFC Translator Closed"); - if (reg != null) { - reg.unregister(); - } } } \ No newline at end of file diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/SfcMdsalHelper.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/SfcMdsalHelper.java new file mode 100644 index 0000000000..d2a455a20b --- /dev/null +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/SfcMdsalHelper.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Brocade Communications Systems, 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.openstack.sfc.translator; + +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.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.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility methods to read OpenDaylight SFC models. + */ +public class SfcMdsalHelper { + private static final Logger LOG = LoggerFactory.getLogger(SfcMdsalHelper.class); + private static InstanceIdentifier accessListIid = InstanceIdentifier.create(AccessLists.class); + + private final DataBroker dataBroker; + private final MdsalUtils mdsalUtils; + + public SfcMdsalHelper(DataBroker dataBroker) { + this.dataBroker = dataBroker; + mdsalUtils = new MdsalUtils(this.dataBroker); + } + + public void addAclFlowClassifier(Acl aclFlowClassifier) { + InstanceIdentifier aclIid = getAclKey(aclFlowClassifier); + LOG.info("Write ACL FlowClassifier {} to config data store at {}",aclFlowClassifier, aclIid); + mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, aclIid, aclFlowClassifier); + } + + public void updateAclFlowClassifier(Acl aclFlowClassifier) { + InstanceIdentifier aclIid = getAclKey(aclFlowClassifier); + LOG.info("Update ACL FlowClassifier {} in config data store at {}",aclFlowClassifier, aclIid); + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, aclIid, aclFlowClassifier); + } + + public void removeAclFlowClassifier(Acl aclFlowClassifier) { + InstanceIdentifier aclIid = getAclKey(aclFlowClassifier); + LOG.info("Remove ACL FlowClassifier {} from config data store at {}",aclFlowClassifier, aclIid); + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, aclIid); + } + + private InstanceIdentifier getAclKey(Acl aclFlowClassifier) { + return accessListIid.builder().child(Acl.class, aclFlowClassifier.getKey()).build(); + } +} diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/FlowClassifierTranslator.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/FlowClassifierTranslator.java new file mode 100644 index 0000000000..a0ae0e1a5d --- /dev/null +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/FlowClassifierTranslator.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2016 Brocade Communications Systems, 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.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.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.EthertypeV6; +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.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{ + 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 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 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 path, SfcFlowClassifier sfcFlowClassifier) { + Acl aclFlowClassifier = buildAcl(sfcFlowClassifier); + sfcMdsalHelper.addAclFlowClassifier(aclFlowClassifier); + } + + private Acl buildAcl(SfcFlowClassifier flowClassifier) { + 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(); + AceIpBuilder aceIpBuilder = new AceIpBuilder(); + DestinationPortRangeBuilder destinationPortRange = new DestinationPortRangeBuilder(); + SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder(); + + if (flowClassifier.getUuid() != null) { + if (flowClassifier.getName() != null) { + aclBuilder.setAclName(flowClassifier.getUuid().getValue() + "_" + flowClassifier.getName()); + } else { + aclBuilder.setAclName(flowClassifier.getUuid().getValue()); + } + + } + if (flowClassifier.getEthertype() != null) { + IpPrefix sourceIp = null; + IpPrefix destinationIp = null; + if (flowClassifier.getSourceIpPrefix() != null) { + sourceIp = flowClassifier.getSourceIpPrefix(); + } + if (flowClassifier.getDestinationIpPrefix() != null) { + destinationIp = flowClassifier.getDestinationIpPrefix(); + } + if (flowClassifier.getEthertype() == EthertypeV4.class) { + AceIpv4Builder aceIpv4Builder = new AceIpv4Builder(); + if (sourceIp.getIpv4Prefix() != null ) { + aceIpv4Builder.setSourceIpv4Network(sourceIp.getIpv4Prefix()); + } + if (destinationIp.getIpv4Prefix() != null) { + aceIpv4Builder.setDestinationIpv4Network(destinationIp.getIpv4Prefix()); + } + aceIpBuilder.setAceIpVersion(aceIpv4Builder.build()); + aclBuilder.setAclType(Ipv4Acl.class); + } + if (flowClassifier.getEthertype() == EthertypeV6.class) { + AceIpv6Builder aceIpv6Builder = new AceIpv6Builder(); + if (sourceIp.getIpv6Prefix() != null ) { + aceIpv6Builder.setSourceIpv6Network(sourceIp.getIpv6Prefix()); + } + if (destinationIp.getIpv6Prefix() != null) { + aceIpv6Builder.setDestinationIpv6Network(destinationIp.getIpv6Prefix()); + } + aceIpBuilder.setAceIpVersion(aceIpv6Builder.build()); + aclBuilder.setAclType(Ipv6Acl.class); + } + } + if (flowClassifier.getProtocol() != null) { + if (flowClassifier.getProtocol() == ProtocolTcp.class) { + aceIpBuilder.setProtocol(PROTO_TCP); + } + if (flowClassifier.getProtocol() == ProtocolUdp.class) { + aceIpBuilder.setProtocol(PROTO_UDP); + } + } + if (flowClassifier.getSourcePortRangeMin() != null) { + sourcePortRangeBuilder.setLowerPort(new PortNumber(flowClassifier.getSourcePortRangeMin())); + } + if (flowClassifier.getSourcePortRangeMax() != null) { + sourcePortRangeBuilder.setUpperPort(new PortNumber(flowClassifier.getSourcePortRangeMax())); + } + if (flowClassifier.getDestinationPortRangeMin() != null) { + destinationPortRange.setLowerPort(new PortNumber(flowClassifier.getDestinationPortRangeMin())); + } + if (flowClassifier.getDestinationPortRangeMax() != null) { + destinationPortRange.setUpperPort(new PortNumber(flowClassifier.getDestinationPortRangeMax())); + } + if (flowClassifier.getLogicalSourcePort() != null) { + // No respective ACL construct for it. + } + if (flowClassifier.getLogicalDestinationPort() != null) { + // No respective ACL construct for it. + } + if (flowClassifier.getL7Parameter() != null) { + //It's currently not supported. + } + + aceIpBuilder.setSourcePortRange(sourcePortRangeBuilder.build()); + aceIpBuilder.setDestinationPortRange(destinationPortRange.build()); + + matchesBuilder.setAceType(aceIpBuilder.build()); + + aceBuilder.setMatches(matchesBuilder.build()); + + //OpenStack networking-sfc don't pass action information + //with flow classifier. It need to be determined using the + //Port Chain data and then flow calssifier need to be updated + //with the actions. + + aceBuilder.setRuleName(aclBuilder.getAclName() + RULE); + aceBuilder.setKey(new AceKey(aceBuilder.getRuleName())); + + ArrayList aceList = new ArrayList<>(); + aceList.add(aceBuilder.build()); + accessListEntriesBuilder.setAce(aceList); + + aclBuilder.setAccessListEntries(accessListEntriesBuilder.build()); + aclBuilder.setKey(new AclKey(aclBuilder.getAclName(),aclBuilder.getAclType())); + + LOG.info("Translated ACL Flow classfier : {}", aclBuilder); + + return aclBuilder.build(); + } +} diff --git a/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/NeutronFlowClassifierListener.java b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/NeutronFlowClassifierListener.java new file mode 100644 index 0000000000..09854e1c49 --- /dev/null +++ b/openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/NeutronFlowClassifierListener.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 Brocade Communications Systems, 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.openstack.sfc.translator.flowclassifier; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener; +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.yangtools.yang.binding.InstanceIdentifier; + +/** + * OpenDaylight Neutron Flow Classifier yang models data change listener + */ +public class NeutronFlowClassifierListener extends DelegatingDataTreeListener { + + private static final InstanceIdentifier 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)); + } +} -- 2.36.6