Bug 5199 : DHCP and Transparent code changes 50/34150/1
authorKency <kency.kurian@ericsson.com>
Wed, 3 Feb 2016 06:52:43 +0000 (12:22 +0530)
committerKency Kurian <kency.kurian@ericsson.com>
Fri, 5 Feb 2016 12:51:20 +0000 (12:51 +0000)
Change-Id: I9c0864fd776cb091fca1682f062eaa249f86e680
Signed-off-by: Kency <kency.kurian@ericsson.com>
(cherry picked from commit da5201e942d7f74775d338891b5f69c27844ede5)

30 files changed:
dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/vpnservice/dhcpservice/api/DHCPMConstants.java
dhcpservice/dhcpservice-api/src/main/yang/dhcpservice-api.yang
dhcpservice/dhcpservice-impl/pom.xml
dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpInterfaceEventListener.java [new file with mode: 0644]
dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpManager.java
dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpPktHandler.java
dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpProvider.java
dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/NodeListener.java
dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigRemoveHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateAddHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateRemoveHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/rpcservice/InterfaceManagerRpcService.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigBindHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigUnbindHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateBindHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateUnbindHelper.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/utilities/FlowBasedServicesUtils.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesConfigurationTest.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesStateConfigurationTest.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/VlanInterfaceConfigurationTest.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/IEEE8021Q.java [new file with mode: 0644]

index bcf8612da273a357949bf0a066407a0027a541f0..ef3a495a634530700976ebac71457c7fa04d2488 100644 (file)
@@ -12,10 +12,6 @@ import java.math.BigInteger;
 
 public final class DHCPMConstants {
 
-    // DHCP Service Table Ids
-    public static final short DHCP_TABLE = 0;
-    public static final short L3_FIB_TABLE = 20;
-
     public static final long DHCP_TABLE_MAX_ENTRY = 10000;
 
     public static final int DEFAULT_DHCP_FLOW_PRIORITY = 50;
@@ -35,4 +31,6 @@ public final class DHCPMConstants {
 
     public static final int DEFAULT_LEASE_TIME = 86400;
     public static final String DEFAULT_DOMAIN_NAME = "openstacklocal";
+
+    public static final BigInteger INVALID_DPID = new BigInteger("-1");
 }
index 6d45eed9877e051d9fbcf2fae4ddf5e63cd2fb9f..fd86e9ff7680e1bcc05c99ef3977e27387ffebe0 100644 (file)
@@ -8,4 +8,29 @@ module dhcpservice-api {
             "Initial revision for DHCP Service module";
     }
 
+    container interface-name-mac-addresses {
+        config false;
+        description
+            "Container to hold list of interface names and MAC address";
+
+        list interface-name-mac-address {
+            max-elements "unbounded";
+            min-elements "0";
+            key "interface-name";
+            description
+                "Specifies the name of the interface";
+
+            leaf interface-name {
+                type string;
+                description
+                    "The name of the interface.";
+            }
+
+            leaf mac-address {
+                type string;
+                description
+                    "The VM mac address for the interface.";
+            }
+        }
+    }
 }
\ No newline at end of file
index 35147084448f3a3749078bb8ea0aa5657d685b98..cff44a5f53057800f367a9ff744883e538d758f4 100644 (file)
@@ -59,6 +59,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>commons-net</groupId>
       <artifactId>commons-net</artifactId>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>interfacemgr-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
    </dependencies>
 
 </project>
diff --git a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpInterfaceEventListener.java b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpInterfaceEventListener.java
new file mode 100644 (file)
index 0000000..b7f2629
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 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.vpnservice.dhcpservice;
+
+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.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
+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;
+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 static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
+        public void onSuccess(Void result) {
+            logger.debug("Success in Datastore write operation");
+        }
+
+        public void onFailure(Throwable error) {
+            logger.error("Error in Datastore write operation", error);
+        }
+    };
+
+    public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker) {
+        super(Interface.class);
+        this.dhcpManager = dhcpManager;
+        this.dataBroker = dataBroker;
+        registerListener();
+    }
+
+    private void registerListener() {
+        try {
+            listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                    getWildCardPath(), DhcpInterfaceEventListener.this, DataChangeScope.SUBTREE);
+        } catch (final Exception e) {
+            logger.error("DhcpInterfaceEventListener DataChange listener registration fail!", e);
+            throw new IllegalStateException("DhcpInterfaceEventListener registration Listener failed.", e);
+        }
+    }
+
+    private InstanceIdentifier<Interface> getWildCardPath() {
+        return InstanceIdentifier.create(InterfacesState.class).child(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;
+        }
+        logger.info("Interface Manager Closed");
+    }
+
+
+    @Override
+    protected void remove(InstanceIdentifier<Interface> identifier,
+            Interface del) {
+        String interfaceName = del.getName();
+        List<String> ofportIds = del.getLowerLayerIf();
+        NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+        BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+        logger.trace("Received remove DCN for interface {} dpId {}", interfaceName, dpId);
+        unInstallDhcpEntries(interfaceName, dpId);
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<Interface> identifier,
+            Interface original, Interface update) {
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
+        String interfaceName = add.getName();
+        List<String> ofportIds = add.getLowerLayerIf();
+        NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+        BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+        logger.trace("Received add DCN for interface {}, dpid{}", interfaceName, dpId);
+        installDhcpEntries(interfaceName, dpId);
+    }
+
+    private String getNeutronMacAddress(String interfaceName) {
+        Port port = dhcpManager.getNeutronPort(interfaceName);
+        if (port!=null) {
+            logger.trace("Port found in neutron. Interface Name {}, port {}", interfaceName, port);
+            return port.getMacAddress();
+        }
+        logger.trace("Port not found in neutron. Interface Name {}, vlanId {}", interfaceName);
+        return null;
+    }
+
+    private void unInstallDhcpEntries(String interfaceName, BigInteger dpId) {
+        String vmMacAddress = getAndRemoveVmMacAddress(interfaceName);
+        dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress);
+    }
+
+    private void installDhcpEntries(String interfaceName, BigInteger dpId) {
+        String vmMacAddress = getAndUpdateVmMacAddress(interfaceName);
+        dhcpManager.installDhcpEntries(dpId, vmMacAddress);
+    }
+
+    private String getAndUpdateVmMacAddress(String interfaceName) {
+        InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
+        Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+        if (!existingEntry.isPresent()) {
+            logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
+            String vmMacAddress = getNeutronMacAddress(interfaceName);
+            if (vmMacAddress==null || vmMacAddress.isEmpty()) {
+                return null;
+            }
+            logger.trace("Updating InterfaceNameVmMacAddress map with {}, {}", interfaceName,vmMacAddress);
+            InterfaceNameMacAddress interfaceNameMacAddress = new InterfaceNameMacAddressBuilder().setKey(new InterfaceNameMacAddressKey(interfaceName)).setInterfaceName(interfaceName).setMacAddress(vmMacAddress).build();
+            MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, interfaceNameMacAddress);
+            return vmMacAddress;
+        }
+        return existingEntry.get().getMacAddress();
+    }
+
+    private String getAndRemoveVmMacAddress(String interfaceName) {
+        InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
+        Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+        if (existingEntry.isPresent()) {
+            String vmMacAddress = existingEntry.get().getMacAddress();
+            logger.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName, vmMacAddress);
+            MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, DEFAULT_CALLBACK);
+            return vmMacAddress;
+        }
+        logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
+        return null;
+    }
+}
index f195fa89535403a816bd697467a208c52c70997a..6233d40d8a713c7734a3e4f21a94a29dd2e7cba7 100644 (file)
@@ -8,18 +8,22 @@
 package org.opendaylight.vpnservice.dhcpservice;
 
 import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+
 import com.google.common.base.Optional;
+
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
+
 import com.google.common.util.concurrent.FutureCallback;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
@@ -84,7 +88,7 @@ public class DhcpManager implements AutoCloseable {
 
     public void installDhcpEntries(BigInteger dpnId) {
         logger.debug("Installing Default DHCP Flow tp DPN: {}", dpnId);
-        setupDefaultDhcpFlow(dpnId, DHCPMConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
+        setupDefaultDhcpFlow(dpnId, NwConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
     }
 
     private void setupDefaultDhcpFlow(BigInteger dpId,  short tableId, int addOrRemove) {
@@ -171,4 +175,70 @@ public class DhcpManager implements AutoCloseable {
         return neutronVpnService.getNeutronPort(name);
     }
 
+    public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
+        setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW);
+    }
+
+    private void setupDhcpFlowEntry(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove) {
+        if (dpId == null || dpId == DHCPMConstants.INVALID_DPID || vmMacAddress == null) {
+            return;
+        }
+        List<MatchInfo> matches = new ArrayList<MatchInfo>();
+
+        matches.add(new MatchInfo(MatchFieldType.eth_type,
+                new long[] { NwConstants.ETHTYPE_IPV4 }));
+        matches.add(new MatchInfo(MatchFieldType.ip_proto,
+                new long[] { IPProtocols.UDP.intValue() }));
+        matches.add(new MatchInfo(MatchFieldType.udp_src,
+                new long[] { DHCPMConstants.dhcpClientPort }));
+        matches.add(new MatchInfo(MatchFieldType.udp_dst,
+                new long[] { DHCPMConstants.dhcpServerPort }));
+        matches.add(new MatchInfo(MatchFieldType.eth_src,
+                new String[] { vmMacAddress }));
+
+        List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+        List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+
+        // Punt to controller
+        actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
+                new String[] {}));
+        instructions.add(new InstructionInfo(InstructionType.write_actions,
+                actionsInfos));
+        if (addOrRemove == NwConstants.DEL_FLOW) {
+            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+                    getDhcpFlowRef(dpId, tableId, vmMacAddress),
+                    DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+                    DHCPMConstants.COOKIE_DHCP_BASE, matches, null);
+            logger.trace("Removing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+            mdsalUtil.removeFlow(flowEntity);
+        } else {
+            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+                    getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+                    DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+            logger.trace("Installing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+            mdsalUtil.installFlow(flowEntity);
+        }
+    }
+
+    private String getDhcpFlowRef(BigInteger dpId, long tableId, String vmMacAddress) {
+        return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX)
+                .append(dpId).append(NwConstants.FLOWID_SEPARATOR)
+                .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+                .append(vmMacAddress).toString();
+    }
+
+    public void unInstallDhcpEntries(BigInteger dpId, String vmMacAddress) {
+        setupDhcpFlowEntry(dpId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW);
+    }
+
+    public void setupTableMissForDhcpTable(BigInteger dpId) {
+        List<MatchInfo> matches = new ArrayList<MatchInfo>();
+        List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+        instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
+
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE, "DHCPTableMissFlow",
+                0, "DHCP Table Miss Flow", 0, 0,
+                DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+        mdsalUtil.installFlow(flowEntity);
+    }
 }
index 6a4539f11f4ab30b5f69e3ab9f1010d9e55bef6e..5c26610c157044fa4a8247dde4d4600b1475ab0a 100644 (file)
@@ -9,18 +9,20 @@ package org.opendaylight.vpnservice.dhcpservice;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.net.util.SubnetUtils;
 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.opendaylight.controller.liblldp.EtherTypes;
-import org.opendaylight.controller.liblldp.HexEncode;
 import org.opendaylight.controller.liblldp.NetUtils;
 import org.opendaylight.controller.liblldp.PacketException;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -29,38 +31,48 @@ import org.opendaylight.vpnservice.dhcpservice.api.DHCP;
 import org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants;
 import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.vpnservice.dhcpservice.api.DHCPUtils;
-import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.packet.IEEE8021Q;
 import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
 import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
 import org.opendaylight.vpnservice.mdsalutil.packet.UDP;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 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.subnet.attributes.HostRoutes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
 public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
-    
+
     private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
     private final DataBroker dataBroker;
     private final DhcpManager dhcpMgr;
-
+    private OdlInterfaceRpcService interfaceManagerRpc;
+    private static HashMap<String, ImmutablePair<BigInteger, String>> localCache = new HashMap<String, ImmutablePair<BigInteger, String>>();
     private boolean computeUdpChecksum = true;
     private PacketProcessingService pktService;
 
@@ -75,7 +87,7 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         LOG.trace("Pkt received: {}", packet);
         Class<? extends PacketInReason> pktInReason = packet.getPacketInReason();
         short tableId = packet.getTableId().getValue();
-        if (isPktInReasonSendtoCtrl(pktInReason) && ((DHCPMConstants.DHCP_TABLE == tableId))) {
+        if (isPktInReasonSendtoCtrl(pktInReason) && ((NwConstants.DHCP_TABLE == tableId))) {
             byte[] inPayload = packet.getPayload();
             Ethernet ethPkt = new Ethernet();
             try {
@@ -85,36 +97,33 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
                 return;
             }
             try {
-                DHCP pktIn = getDhcpPktIn(ethPkt);
-                LOG.trace("DHCPPkt received: {}", pktIn);
+                DHCP pktIn;
+                pktIn = getDhcpPktIn(ethPkt);
                 if (pktIn != null) {
-                    NodeConnectorRef inNcRef = packet.getIngress();
-                    FlowCapableNodeConnector fcNc = this.getFlowCapableNodeConnector(inNcRef);
-                    DHCP replyPkt = handleDhcpPacket(pktIn, fcNc);
-                    byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, fcNc);
-                    sendPacketOut(pktOut, inNcRef);
+                    LOG.trace("DHCPPkt received: {}", pktIn);
+                    BigInteger metadata = packet.getMatch().getMetadata().getMetadata();
+                    long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+                    String interfaceName = getInterfaceNameFromTag(portTag);
+                    ImmutablePair<BigInteger, String> pair = getDpnIdPhysicalAddressFromInterfaceName(interfaceName);
+                    DHCP replyPkt = handleDhcpPacket(pktIn, interfaceName);
+                    byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, pair.getRight());
+                    sendPacketOut(pktOut, pair.getLeft(), interfaceName);
                 }
             } catch (Exception e) {
-                LOG.warn("Failed to get DHCP Reply", e);
+                LOG.warn("Failed to get DHCP Reply {}", e);
             }
         }
     }
 
-    private void sendPacketOut(byte[] pktOut, NodeConnectorRef ingress) {
-        // We go out the same port we came in on
-        InstanceIdentifier<Node> egressNodePath = getNodePath(ingress.getValue());
-        TransmitPacketInput input = new TransmitPacketInputBuilder()
-            .setPayload(pktOut).setNode(new NodeRef(egressNodePath))
-            .setEgress(ingress).build();
-        LOG.trace("Transmitting packet: {}",input);
-        this.pktService.transmitPacket(input);
-    }
-
-    private InstanceIdentifier<Node> getNodePath(InstanceIdentifier<?> nodeInstanceId) {
-        return nodeInstanceId.firstIdentifierOf(Node.class);
+    private void sendPacketOut(byte[] pktOut, BigInteger dpnId, String interfaceName) {
+        LOG.trace("Sending packet out DpId {}, portId {}, vlanId {}, interfaceName {}", dpnId, interfaceName);
+        List<Action> action = getEgressAction(interfaceName);
+        TransmitPacketInput output = MDSALUtil.getPacketOut(action, pktOut, dpnId);
+        LOG.trace("Transmitting packet: {}",output);
+        this.pktService.transmitPacket(output);
     }
 
-    private DHCP handleDhcpPacket(DHCP dhcpPkt, FlowCapableNodeConnector fcNc) {
+    private DHCP handleDhcpPacket(DHCP dhcpPkt, String interfaceName) {
         LOG.debug("DHCP pkt rcvd {}", dhcpPkt);
         byte msgType = dhcpPkt.getMsgType();
         if (msgType == DHCPConstants.MSG_DECLINE) {
@@ -125,7 +134,7 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
             return null;
         }
 
-        Port nPort = getNeutronPort(fcNc);
+        Port nPort = getNeutronPort(interfaceName);
         Subnet nSubnet = getNeutronSubnet(nPort);
         DhcpInfo dhcpInfo = getDhcpInfo(nPort, nSubnet);
         LOG.trace("NeutronPort: {} \n NeutronSubnet: {}, dhcpInfo{}",nPort, nSubnet, dhcpInfo);
@@ -166,36 +175,29 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         return dhcpMgr.getNeutronSubnet(nPort);
     }
 
-    private Port getNeutronPort(FlowCapableNodeConnector fcNc) {
-            return dhcpMgr.getNeutronPort(fcNc.getName());
+    private Port getNeutronPort(String interfaceName) {
+            return dhcpMgr.getNeutronPort(interfaceName);
     }
 
-    private FlowCapableNodeConnector getFlowCapableNodeConnector(NodeConnectorRef inNcRef) {
-        InstanceIdentifier<NodeConnector> ncId = inNcRef.getValue().firstIdentifierOf(NodeConnector.class);
-        Optional<NodeConnector> nodeConnector = 
-                        MDSALDataStoreUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ncId);
-        if(nodeConnector.isPresent()) {
-            NodeConnector nc = nodeConnector.get();
-            LOG.trace("Incoming pkt's NodeConnector: {}", nc);
-            FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
-            return fcnc;
+    private DHCP getDhcpPktIn(Ethernet actualEthernetPacket) {
+        Ethernet ethPkt = actualEthernetPacket;
+        LOG.trace("Inside getDhcpPktIn ethPkt {} \n getPayload {}", ethPkt, ethPkt.getPayload());
+        if (ethPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+            ethPkt = (Ethernet)ethPkt.getPayload();
         }
-        return null;
-    }
-
-    private DHCP getDhcpPktIn(Ethernet ethPkt) {
         if (ethPkt.getPayload() instanceof IPv4) {
             IPv4 ipPkt = (IPv4) ethPkt.getPayload();
             if (ipPkt.getPayload() instanceof UDP) {
                 UDP udpPkt = (UDP) ipPkt.getPayload();
                 if ((udpPkt.getSourcePort() == DHCPMConstants.dhcpClientPort)
                         && (udpPkt.getDestinationPort() == DHCPMConstants.dhcpServerPort)) {
+                    LOG.trace("Matched dhcpClientPort and dhcpServerPort");
                     byte[] rawDhcpPayload = udpPkt.getRawPayload();
                     DHCP reply = new DHCP();
                     try {
                         reply.deserialize(rawDhcpPayload, 0, rawDhcpPayload.length);
                     } catch (PacketException e) {
-                        LOG.warn("Failed to deserialize DHCP pkt", e);
+                        LOG.warn("Failed to deserialize DHCP pkt {}", e);
                         return null;
                     }
                     return reply;
@@ -268,7 +270,7 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         return reply;
     }
 
-    protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, FlowCapableNodeConnector fcNc) {
+    protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, String phyAddrees) {
         if (reply == null) {
             /*
              * DECLINE or RELEASE don't result in reply packet
@@ -313,11 +315,24 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         ip4Reply.setTtl((byte) 32);
         // create Ethernet Frame
         Ethernet ether = new Ethernet();
+        if (etherPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+            IEEE8021Q vlanPacket = (IEEE8021Q) etherPkt.getPayload();
+            IEEE8021Q vlanTagged = new IEEE8021Q();
+            vlanTagged.setCFI(vlanPacket.getCfi());
+            vlanTagged.setPriority(vlanPacket.getPriority());
+            vlanTagged.setVlanId(vlanPacket.getVlanId());
+            vlanTagged.setPayload(ip4Reply);
+            vlanTagged.setEtherType(EtherTypes.IPv4.shortValue());
+            ether.setPayload(vlanTagged);
+            ether.setEtherType((short) NwConstants.ETHTYPE_802_1Q);
+        } else {
+            ether.setEtherType(EtherTypes.IPv4.shortValue());
+            ether.setPayload(ip4Reply);
+        }
         //TODO: 
-        ether.setSourceMACAddress(getServerMacAddress(fcNc));
+        ether.setSourceMACAddress(getServerMacAddress(phyAddrees));
         ether.setDestinationMACAddress(etherPkt.getSourceMACAddress());
-        ether.setEtherType(EtherTypes.IPv4.shortValue());
-        ether.setPayload(ip4Reply);
+
         try {
             rawPkt = ether.serialize();
         } catch (PacketException e) {
@@ -327,10 +342,9 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         return rawPkt;
     }
 
-    private byte[] getServerMacAddress(FlowCapableNodeConnector fcNc) {
+    private byte[] getServerMacAddress(String phyAddress) {
         // Should we return ControllerMac instead?
-        MacAddress macAddress = fcNc.getHardwareAddress();
-        return DHCPUtils.strMacAddrtoByteArray(macAddress.getValue());
+        return DHCPUtils.strMacAddrtoByteArray(phyAddress);
     }
 
     public short computeChecksum(byte[] inData, byte[] srcAddr, byte[] destAddr) {
@@ -523,4 +537,79 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         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();
+        Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput = interfaceManagerRpc.getInterfaceFromIfIndex(input);
+        try {
+            GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
+            interfaceName = output.getInterfaceName();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error while retrieving the interfaceName from tag using getInterfaceFromIfIndex RPC");
+        }
+        LOG.trace("Returning interfaceName {} for tag {} form getInterfaceNameFromTag", interfaceName, portTag);
+        return interfaceName;
+    }
+
+    private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(String interfaceName) {
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+                buildStateInterfaceId(interfaceName);
+        Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional =
+                MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+        if (!ifStateOptional.isPresent()) {
+            return null;
+        }
+
+        return ifStateOptional.get();
+    }
+
+    private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
+        InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+                InstanceIdentifier.builder(InterfacesState.class)
+                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+        return id;
+    }
+
+    private List<Action> getEgressAction(String interfaceName) {
+        List<Action> actions = null;
+        try {
+            Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+                    interfaceManagerRpc.getEgressActionsForInterface(
+                            new GetEgressActionsForInterfaceInputBuilder().setIntfName(interfaceName).build());
+            RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+            if(!rpcResult.isSuccessful()) {
+                LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", interfaceName, rpcResult.getErrors());
+            } else {
+                actions = rpcResult.getResult().getAction();
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when egress actions for interface {}", interfaceName, e);
+        }
+        return actions;
+    }
+
+    private ImmutablePair<BigInteger, String> getDpnIdPhysicalAddressFromInterfaceName(String interfaceName) {
+        ImmutablePair<BigInteger, String> pair = localCache.get(interfaceName);
+        if (pair!=null && pair.getLeft() != null && pair.getRight() != null) {
+            return pair;
+        }
+        NodeConnectorId nodeConnectorId = null;
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = getInterfaceStateFromOperDS(interfaceName);
+        if(interfaceState != null) {
+            List<String> ofportIds = interfaceState.getLowerLayerIf();
+            nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+        }
+        BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+        String phyAddress = interfaceState==null ? "":interfaceState.getPhysAddress().getValue();
+        pair = new ImmutablePair<BigInteger, String>(dpId, phyAddress);
+        localCache.put(interfaceName, pair);
+        return null;
+    }
 }
index 5f15135fb3103bb5505ad1f2b48d3d165fe8bb0b..439d7352ada125065e56709c544c8a17d38d72f4 100644 (file)
@@ -8,9 +8,9 @@
 package org.opendaylight.vpnservice.dhcpservice;
 
 import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
-
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
@@ -30,6 +30,8 @@ public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
     private NodeListener dhcpNodeListener;
     private INeutronVpnManager neutronVpnManager;
     private DhcpConfigListener dhcpConfigListener;
+    private OdlInterfaceRpcService interfaceManagerRpc;
+    private DhcpInterfaceEventListener dhcpInterfaceEventListener;
 
     @Override
     public void onSessionInitiated(ProviderContext session) {
@@ -42,11 +44,13 @@ public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
             dhcpManager.setNeutronVpnService(neutronVpnManager);
             dhcpPktHandler = new DhcpPktHandler(dataBroker, dhcpManager);
             dhcpPktHandler.setPacketProcessingService(pktProcessingService);
+            dhcpPktHandler.setInterfaceManagerRpc(interfaceManagerRpc);
             packetListener = notificationService.registerNotificationListener(dhcpPktHandler);
             dhcpNodeListener = new NodeListener(dataBroker, dhcpManager);
             dhcpConfigListener = new DhcpConfigListener(dataBroker, dhcpManager);
+            dhcpInterfaceEventListener = new DhcpInterfaceEventListener(dhcpManager, dataBroker);
         } catch (Exception e) {
-            LOG.error("Error initializing services", e);
+            LOG.error("Error initializing services {}", e);
         }
     }
 
@@ -77,4 +81,7 @@ public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
         this.notificationService = notificationServiceDependency;
     }
 
+    public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
+        this.interfaceManagerRpc = interfaceManagerRpc;
+    }
 }
index 8cb8a7addb432ccfc1d9a623e2f8faf89aceadb8..b7d0f2be5aa45994182b49eec67072a317b41892 100644 (file)
@@ -73,7 +73,7 @@ public class NodeListener extends AbstractDataChangeListener<Node> implements Au
         NodeId nodeId = add.getId();
         String[] node =  nodeId.getValue().split(":");
         BigInteger dpId = new BigInteger(node[1]);
-        dhcpManager.installDhcpEntries(dpId);
+        dhcpManager.setupTableMissForDhcpTable(dpId);
     }
 
     @Override
index eac19a9934d7f5b397c8d6f23abb795b81040558..2fa746dce7abb10fa7790114cc113195af39aa74 100644 (file)
@@ -1,6 +1,8 @@
 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.vpnservice.dhcpservice.DhcpProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 
 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) {
@@ -18,10 +20,12 @@ public class DhcpServiceImplModule extends org.opendaylight.yang.gen.v1.urn.open
 
     @Override
     public java.lang.AutoCloseable createInstance() {
+        RpcProviderRegistry rpcregistryDependency = getRpcregistryDependency();
         DhcpProvider dhcpProvider = new DhcpProvider();
         dhcpProvider.setNotificationProviderService(getNotificationServiceDependency());
         dhcpProvider.setMdsalManager(getMdsalutilDependency());
         dhcpProvider.setNeutronVpnManager(getNeutronvpnDependency());
+        dhcpProvider.setInterfaceManagerRpc(rpcregistryDependency.getRpcService(OdlInterfaceRpcService.class));
         getBrokerDependency().registerProvider(dhcpProvider);
         return dhcpProvider;
     }
index 927f8aebbce2436462e9c96575c2e585f387dda4..9a315e0258c66cd608ab529ca6108e67987d8066 100644 (file)
@@ -31,4 +31,8 @@ public class IfmConstants {
     public static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
     public static final String TUNNEL_TABLE_FLOWID_PREFIX = "TUNNEL.";
     public static final BigInteger TUNNEL_TABLE_COOKIE = new BigInteger("9000000", 16);
+    public static final short DEFAULT_SERVICE_INDEX = 0;
+    public static final int FLOW_HIGH_PRIORITY = 10;
+    public static final int FLOW_PRIORITY_FOR_UNTAGGED_VLAN = 4;
+    public static final BigInteger VLAN_TABLE_COOKIE = new BigInteger("8000000", 16);
 }
index a8e2d6ed01de01b266e0a7a7e7a620199acd39d9..11eed1c6dc3baf53525dcb06d48b964c39306a7d 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
+
 import org.eclipse.xtend.lib.annotations.Data;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
@@ -21,6 +22,8 @@ import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUt
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
@@ -90,8 +93,21 @@ public class OvsInterfaceConfigAddHelper {
         }
         updateStateEntry(interfaceNew, transaction, ifState);
 
+        NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+        Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceNew.getName());
         IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
-        if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+        if (ifL2vlan == null) {
+            futures.add(transaction.submit());
+            return;
+        }
+        if(interfaceNew.isEnabled() && ifState.getOperStatus() == OperStatus.Up) {
+            List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, interfaceNew);
+            FlowBasedServicesUtils.installVlanFlow(dpId, portNo, interfaceNew, transaction, matches, ifIndex);
+        }
+        if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+            futures.add(transaction.submit());
             return;
         }
 
@@ -99,6 +115,7 @@ public class OvsInterfaceConfigAddHelper {
         InterfaceParentEntry interfaceParentEntry =
                 InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
         if (interfaceParentEntry == null) {
+            futures.add(transaction.submit());
             return;
         }
 
@@ -110,7 +127,6 @@ public class OvsInterfaceConfigAddHelper {
         OperStatus operStatus = ifState.getOperStatus();
         PhysAddress physAddress = ifState.getPhysAddress();
         AdminStatus adminStatus = ifState.getAdminStatus();
-        NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
 
         //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
         for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
@@ -127,10 +143,15 @@ public class OvsInterfaceConfigAddHelper {
             List<String> childLowerLayerIfList = new ArrayList<>();
             childLowerLayerIfList.add(0, nodeConnectorId.getValue());
             childLowerLayerIfList.add(1, interfaceNew.getName());
+            ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, ifaceChild.getName());
             InterfaceBuilder childIfaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus)
                     .setOperStatus(operStatus).setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
             childIfaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifaceChild.getName()));
             transaction.put(LogicalDatastoreType.OPERATIONAL, ifChildStateId, childIfaceBuilder.build(), true);
+            if (operStatus == OperStatus.Up) {
+                List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, ifaceChild);
+                FlowBasedServicesUtils.installVlanFlow(dpId, portNo, ifaceChild, transaction, matches, ifIndex);
+            }
         }
         futures.add(transaction.submit());
     }
index 04e121074ab0550aa4dd82263f729343f4431276..722db1aa8d526eb115dd7b9a68fdf8e04485fdd8 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -17,6 +18,7 @@ import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -101,7 +103,12 @@ public class OvsInterfaceConfigRemoveHelper {
             }
         }
         IfL2vlan ifL2vlan = interfaceOld.getAugmentation(IfL2vlan.class);
-        if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+        if (ifL2vlan == null) {
+            return;
+        }
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        FlowBasedServicesUtils.removeIngressFlow(interfaceOld, dpId, t);
+        if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
             return;
         }
 
@@ -130,6 +137,8 @@ public class OvsInterfaceConfigRemoveHelper {
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
                     IfmUtil.buildStateInterfaceId(interfaceChildEntry.getChildInterface());
             t.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
+            InterfaceKey childIfKey = new InterfaceKey(interfaceChildEntry.getChildInterface());
+            FlowBasedServicesUtils.removeIngressFlow(InterfaceManagerCommonUtils.getInterfaceFromConfigDS(childIfKey, dataBroker), dpId, t);
         }
     }
 
index 6f7d6349b9d97d8a3b7b3dda290b6e5081b73f21..808fa7ec1944cb6d7b7c1e56103f0415fad5c6f2 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -17,12 +18,15 @@ import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryBuilder;
@@ -36,6 +40,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -91,6 +96,14 @@ public class OvsVlanMemberConfigAddHelper {
 
             // create lportTag Interface Map
             InterfaceMetaUtils.createLportTagInterfaceMap(t, interfaceNew.getName(), ifIndex);
+            //Installing vlan flow for vlan member
+            NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
+            BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+            long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+            if (operStatus == OperStatus.Up) {
+                List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, interfaceNew);
+                FlowBasedServicesUtils.installVlanFlow(dpId, portNo, interfaceNew, t, matches, ifIndex);
+            }
 
             // FIXME: Maybe, add the new interface to the higher-layer if of the parent interface-state.
             // That may not serve any purpose though for interface manager.... Unless some external parties are interested in it.
index cb0397968898e3c17d18afd128f6e3f1812ba71c..83c7c042b17a6ca76032d461c9fec05feba6bf64 100644 (file)
@@ -7,15 +7,19 @@
  */
 package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
 
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.idmanager.IdManager;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
@@ -27,8 +31,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class OvsVlanMemberConfigRemoveHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigRemoveHelper.class);
@@ -81,9 +84,13 @@ public class OvsVlanMemberConfigRemoveHelper {
                 }
             } */
 
+            String ncStr = ifState.getLowerLayerIf().get(0);
+            NodeConnectorId nodeConnectorId = new NodeConnectorId(ncStr);
+            BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
                     IfmUtil.buildStateInterfaceId(interfaceOld.getName());
             t.delete(LogicalDatastoreType.OPERATIONAL, ifStateId);
+            FlowBasedServicesUtils.removeIngressFlow(interfaceOld, dpId, t);
         }
 
         futures.add(t.submit());
index d7fc08795dc949ef05fd44624d65f6fa16030f79..f43d40be54e9b370fc962fddcff2a13ba13c2cbd 100644 (file)
@@ -101,11 +101,11 @@ public class OvsInterfaceStateAddHelper {
             return futures;
         }
 
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
         // If this interface is a tunnel interface, create the tunnel ingress flow
         IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
         if(tunnel != null){
-            BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
-            long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
             InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel,dpId, portNo, iface,
                     ifIndex, NwConstants.ADD_FLOW);
             futures.add(transaction.submit());
@@ -116,11 +116,18 @@ public class OvsInterfaceStateAddHelper {
         // If this interface maps to a Vlan trunk entity, operational states of all the vlan-trunk-members
         // should also be created here.
         IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
-        if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+        if (ifL2vlan == null) {
+            futures.add(transaction.submit());
+            return futures;
+        }
+        if(operStatus == Interface.OperStatus.Up) {
+            List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
+            FlowBasedServicesUtils.installVlanFlow(dpId, portNo, iface, transaction, matches, ifIndex);
+        }
+        if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
             futures.add(transaction.submit());
             return futures;
         }
-
         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(iface.getName());
         InterfaceParentEntry interfaceParentEntry =
                 InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
@@ -148,7 +155,6 @@ public class OvsInterfaceStateAddHelper {
             if (!ifaceChild.isEnabled()) {
                 operStatus = Interface.OperStatus.Down;
             }
-
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
                     IfmUtil.buildStateInterfaceId(ifaceChild.getName());
             List<String> childLowerLayerIfList = new ArrayList<>();
@@ -162,6 +168,10 @@ public class OvsInterfaceStateAddHelper {
 
             // create lportTag Interface Map
             InterfaceMetaUtils.createLportTagInterfaceMap(transaction, ifaceChild.getName(), ifIndex);
+            if (operStatus == Interface.OperStatus.Up) {
+                List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, ifaceChild);
+                FlowBasedServicesUtils.installVlanFlow(dpId, portNo, ifaceChild, transaction, matches, ifIndex);
+            }
         }
 
         /** Below code will be needed if we want to update the vlan-trunks on the of-port
index ee9382d58890e5aa497f283a16bb0153edbcf429..d742a35458d0bcdf1b5db4f40151605064802a84 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -15,11 +16,14 @@ import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
@@ -30,6 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -69,11 +74,11 @@ public class OvsInterfaceStateRemoveHelper {
             return futures;
         }
 
+        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
         // If this interface is a tunnel interface, remove the tunnel ingress flow and stop lldp monitoring
         IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
         if(tunnel != null){
-            NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
-            BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
             long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
             InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel, dpId, portNo, iface, -1,
                     NwConstants.DEL_FLOW);
@@ -82,6 +87,17 @@ public class OvsInterfaceStateRemoveHelper {
             return futures;
         }
 
+        IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
+        if (ifL2vlan == null) {
+            futures.add(transaction.submit());
+            return futures;
+        }
+        FlowBasedServicesUtils.removeIngressFlow(iface, dpId, transaction);
+        if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+            futures.add(transaction.submit());
+            return futures;
+        }
+
         InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(iface.getName());
         InterfaceParentEntry interfaceParentEntry =
                 InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
@@ -105,6 +121,8 @@ public class OvsInterfaceStateRemoveHelper {
             if(interfaceState != null) {
                 InterfaceMetaUtils.removeLportTagInterfaceMap(transaction, idManager, dataBroker, childInterfaceState.getName(), childInterfaceState.getIfIndex());
                 transaction.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
+                InterfaceKey childIfKey = new InterfaceKey(interfaceChildEntry.getChildInterface());
+                FlowBasedServicesUtils.removeIngressFlow(InterfaceManagerCommonUtils.getInterfaceFromConfigDS(childIfKey, dataBroker), dpId, transaction);
             }
         }
 
index b21cd15b1790164e64f790393378dfa080290efd..daa613aac4ddaa81d10686fa650b5052ba1a9a52 100644 (file)
@@ -357,8 +357,13 @@ public class InterfaceManagerRpcService implements OdlInterfaceRpcService {
         if(L2vlan.class.equals(ifType)){
             IfL2vlan vlanIface = interfaceInfo.getAugmentation(IfL2vlan.class);
             LOG.trace("L2Vlan: {}",vlanIface);
-            long vlanVid = (vlanIface == null) ? 0 : vlanIface.getVlanId().getValue();
-            if (vlanVid != 0) {
+            long vlanVid = 0;
+            boolean isVlanTransparent = false;
+            if (vlanIface != null) {
+                vlanVid = vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue();
+                isVlanTransparent = vlanIface.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+            }
+            if (vlanVid != 0 && !isVlanTransparent) {
                 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
                 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
                         new String[] { Long.toString(vlanVid) }));
index 0e9be0533372d9cd9c9c052d230126e02fb6f4c4..5bc4219e9fb833ff2bcdeb4e1d95c5def688f7b4 100644 (file)
@@ -7,7 +7,12 @@
  */
 package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers;
 
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
@@ -24,16 +29,11 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class FlowBasedServicesConfigBindHelper {
     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigBindHelper.class);
@@ -41,7 +41,6 @@ public class FlowBasedServicesConfigBindHelper {
     public static List<ListenableFuture<Void>> bindService(InstanceIdentifier<BoundServices> instanceIdentifier,
                                                            BoundServices boundServiceNew, DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
         String interfaceName =
                 InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
 
@@ -69,25 +68,28 @@ public class FlowBasedServicesConfigBindHelper {
             return futures;
         }
 
+        // Split based on type of interface....
+        if (iface.getType().isAssignableFrom(L2vlan.class)) {
+            return bindServiceOnVlan(boundServiceNew, allServices, iface, ifState.getIfIndex(), dataBroker);
+        } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+           return bindServiceOnTunnel(boundServiceNew, allServices, iface, ifState.getIfIndex(), dataBroker);
+        }
+        return futures;
+    }
+
+    private static List<ListenableFuture<Void>> bindServiceOnTunnel(BoundServices boundServiceNew, List<BoundServices> allServices, Interface iface, int ifIndex, DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
         NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
         long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
         BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
 
         if (allServices.size() == 1) {
             // If only one service present, install instructions in table 0.
-            int vlanId = 0;
             List<MatchInfo> matches = null;
-            if (iface.getType().isAssignableFrom(L2vlan.class)) {
-                matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
-            } else if (iface.getType().isAssignableFrom(Tunnel.class)){
-                matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
-            }
-
-            if (matches != null) {
-                FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew,
-                        transaction, matches, ifState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
-            }
-
+            matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+            FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew,
+                    transaction, matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
             if (transaction != null) {
                 futures.add(transaction.submit());
             }
@@ -112,17 +114,13 @@ public class FlowBasedServicesConfigBindHelper {
 
         if (!isCurrentServiceHighestPriority) {
             FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface, transaction,
-                    ifState.getIfIndex());
+                    ifIndex, boundServiceNew.getServicePriority(), (short) (boundServiceNew.getServicePriority()+1));
         } else {
             BoundServices serviceToReplace = tmpServicesMap.get(highestPriority);
             FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, serviceToReplace, iface, transaction,
-                    ifState.getIfIndex());
+                    ifIndex, boundServiceNew.getServicePriority(), (short) (boundServiceNew.getServicePriority()+1));
             List<MatchInfo> matches = null;
-            if (iface.getType().isAssignableFrom(L2vlan.class)) {
-                matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
-            } else if (iface.getType().isAssignableFrom(Tunnel.class)){
-                matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
-            }
+            matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
 
             if (matches != null) {
 
@@ -132,7 +130,7 @@ public class FlowBasedServicesConfigBindHelper {
 
                 WriteTransaction installFlowTransaction = dataBroker.newWriteOnlyTransaction();
                 FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew, installFlowTransaction,
-                        matches, ifState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+                        matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
                 futures.add(installFlowTransaction.submit());
             }
         }
@@ -142,4 +140,54 @@ public class FlowBasedServicesConfigBindHelper {
         }
         return futures;
     }
+
+    private static List<ListenableFuture<Void>> bindServiceOnVlan(BoundServices boundServiceNew, List<BoundServices> allServices, Interface iface, int ifIndex, DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+        if (allServices.size() == 1) {
+            //calling LportDispatcherTableForService with current service index as 0 and next service index as some value since this is the only service bound.
+            FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface,
+                    transaction, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX,(short) (boundServiceNew.getServicePriority() + 1));
+            if (transaction != null) {
+                futures.add(transaction.submit());
+            }
+            return futures;
+        }
+        allServices.remove(boundServiceNew);
+        BoundServices[] highLowPriorityService = FlowBasedServicesUtils.getHighAndLowPriorityService(allServices, boundServiceNew);
+        BoundServices low = highLowPriorityService[0];
+        BoundServices high = highLowPriorityService[1];
+        BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+        short currentServiceIndex = IfmConstants.DEFAULT_SERVICE_INDEX;
+        short nextServiceIndex = (short) (boundServiceNew.getServicePriority() + 1); // dummy service index
+        if (low != null) {
+            nextServiceIndex = low.getServicePriority();
+            if (low.equals(highest)) {
+                //In this case the match criteria of existing service should be changed.
+                BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(allServices, low)[0];
+                short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+                LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", low, low.getServicePriority(), lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId,low, iface, transaction, ifIndex,low.getServicePriority(), lowerServiceIndex);
+            } else {
+                currentServiceIndex = boundServiceNew.getServicePriority();
+            }
+        }
+        if (high != null) {
+            currentServiceIndex = boundServiceNew.getServicePriority();
+            if (high.equals(highest)) {
+                LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, currentServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, transaction, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, currentServiceIndex);
+            } else {
+                LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", high, high.getServicePriority(), currentServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, transaction, ifIndex, high.getServicePriority(), currentServiceIndex);
+            }
+        }
+        LOG.trace("Installing table 30 entry for new service match on service index {} update with service index {}", currentServiceIndex, nextServiceIndex);
+        FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface, transaction, ifIndex, currentServiceIndex, nextServiceIndex);
+        futures.add(transaction.submit());
+        return futures;
+    }
 }
\ No newline at end of file
index cd0c00d94d186675c0177b4de8b7f2c134eb18ee..6984e784d3b7a61988df7ac55f0edbef99211eb4 100644 (file)
@@ -7,7 +7,12 @@
  */
 package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers;
 
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
@@ -24,16 +29,11 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class FlowBasedServicesConfigUnbindHelper {
     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigUnbindHelper.class);
@@ -41,10 +41,18 @@ public class FlowBasedServicesConfigUnbindHelper {
     public static List<ListenableFuture<Void>> unbindService(InstanceIdentifier<BoundServices> instanceIdentifier,
                                                              BoundServices boundServiceOld, DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-
         String interfaceName =
                 InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+
+        // Get the Parent ServiceInfo
+        ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
+        if (servicesInfo == null) {
+            LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+            return futures;
+        }
+
+        InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+        Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
                 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
         if (ifState == null || ifState.getOperStatus() == OperStatus.Down) {
@@ -52,21 +60,78 @@ public class FlowBasedServicesConfigUnbindHelper {
                     ifState.getOperStatus(), interfaceName);
             return futures;
         }
+        List<BoundServices> boundServices = servicesInfo.getBoundServices();
 
-        // Get the Parent ServiceInfo
-        ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
-        if (servicesInfo == null) {
-            LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+        // Split based on type of interface....
+        if (iface.getType().isAssignableFrom(L2vlan.class)) {
+            return unbindServiceOnVlan(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+        } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+           return unbindServiceOnTunnel(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+        }
+        return futures;
+    }
+
+    private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+            BoundServices boundServiceOld,
+            List<BoundServices> boundServices, Interface iface, int ifIndex,
+            DataBroker dataBroker) {
+
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        if (boundServices.isEmpty()) {
+            // Remove default entry from Lport Dispatcher Table.
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+            if (t != null) {
+                futures.add(t.submit());
+            }
             return futures;
         }
+        BoundServices[] highLow = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, boundServiceOld);
+        BoundServices low = highLow[0];
+        BoundServices high = highLow[1];
+        // This means the one removed was the highest priority service
+        if (high == null) {
+            LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, IfmConstants.DEFAULT_SERVICE_INDEX);
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+            if (low != null) {
+                //delete the lower services flow entry.
+                LOG.trace("Deleting table entry for lower service {}, match service index {}", low, low.getServicePriority());
+                FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, low, t, low.getServicePriority());
+                BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, low)[0];
+                short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+                LOG.trace("Installing new entry for lower service {}, match service index {}, update service index {}", low, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, low, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+            }
+        } else {
+            LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, boundServiceOld.getServicePriority());
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, boundServiceOld.getServicePriority());
+            short lowerServiceIndex = (short) ((low!=null) ? low.getServicePriority() : boundServiceOld.getServicePriority() + 1);
+            BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(boundServices);
+            if (high.equals(highest)) {
+                LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+            } else {
+                LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, high.getServicePriority(), lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, high.getServicePriority(), lowerServiceIndex);
+            }
+        }
+        futures.add(t.submit());
+        return futures;
+    }
 
-        InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
-        Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+    private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+            BoundServices boundServiceOld,
+            List<BoundServices> boundServices, Interface iface, int ifIndex,
+            DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
         NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
         long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
         BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
 
-        List<BoundServices> boundServices = servicesInfo.getBoundServices();
         if (boundServices.isEmpty()) {
             // Remove entry from Ingress Table.
             FlowBasedServicesUtils.removeIngressFlow(iface, boundServiceOld, dpId, t);
@@ -86,7 +151,7 @@ public class FlowBasedServicesConfigUnbindHelper {
         }
 
         if (highestPriority < boundServiceOld.getServicePriority()) {
-            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t);
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, boundServiceOld.getServicePriority());
             if (t != null) {
                 futures.add(t.submit());
             }
@@ -94,21 +159,18 @@ public class FlowBasedServicesConfigUnbindHelper {
         }
 
         List<MatchInfo> matches = null;
-        if (iface.getType().isAssignableFrom(L2vlan.class)) {
-            matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
-        } else if (iface.getType().isAssignableFrom(Tunnel.class)){
-            matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
-        }
+        matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
 
         BoundServices toBeMoved = tmpServicesMap.get(highestPriority);
         FlowBasedServicesUtils.removeIngressFlow(iface, boundServiceOld, dpId, t);
         FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, toBeMoved, t,
-                matches, ifState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
-        FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, toBeMoved, t);
+                matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+        FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, toBeMoved, t, toBeMoved.getServicePriority());
 
         if (t != null) {
             futures.add(t.submit());
         }
         return futures;
     }
+
 }
\ No newline at end of file
index 25812cdf24236ae21885898364fbd9e42d79d832..6186802fcc37e780c0c1a4a068a62e2a253f986a 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
@@ -30,6 +31,9 @@ import org.slf4j.LoggerFactory;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 public class FlowBasedServicesStateBindHelper {
@@ -38,7 +42,6 @@ public class FlowBasedServicesStateBindHelper {
     public static List<ListenableFuture<Void>> bindServicesOnInterface(Interface ifaceState,
                                                              DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
         ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(ifaceState.getName(), dataBroker);
         if (servicesInfo == null) {
             return futures;
@@ -49,41 +52,74 @@ public class FlowBasedServicesStateBindHelper {
             return futures;
         }
 
-        BoundServices highestPriorityBoundService = null;
-        short highestPriority = 0xFF;
-        for (BoundServices boundService : allServices) {
-            if (boundService.getServicePriority() < highestPriority) {
-                highestPriorityBoundService = boundService;
-                highestPriority = boundService.getServicePriority();
-            }
-        }
-
         InterfaceKey interfaceKey = new InterfaceKey(ifaceState.getName());
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
                     InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
 
-        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
-        long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
-        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
-        List<MatchInfo> matches = null;
         if (iface.getType().isAssignableFrom(L2vlan.class)) {
-            matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
+            return bindServiceOnVlan(allServices, iface, ifaceState.getIfIndex(), dataBroker);
         } else if (iface.getType().isAssignableFrom(Tunnel.class)){
-            matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+             return bindServiceOnTunnel(allServices, iface, ifaceState.getIfIndex(), dataBroker);
         }
+        return futures;
+    }
 
+    private static List<ListenableFuture<Void>> bindServiceOnTunnel(
+            List<BoundServices> allServices,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            Integer ifIndex, DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+        long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+        BoundServices highestPriorityBoundService = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
         if (matches != null) {
             FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, highestPriorityBoundService,
-                    t, matches, ifaceState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+                    t, matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
         }
 
         for (BoundServices boundService : allServices) {
             if (!boundService.equals(highestPriorityBoundService)) {
-                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundService, iface, t, ifaceState.getIfIndex());
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundService, iface, t, ifIndex, boundService.getServicePriority(), (short) (boundService.getServicePriority()+1));
             }
         }
 
         futures.add(t.submit());
         return futures;
     }
+
+    private static List<ListenableFuture<Void>> bindServiceOnVlan(
+            List<BoundServices> allServices,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            Integer ifIndex, DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+        Collections.sort(allServices, new Comparator<BoundServices>() {
+            @Override
+            public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+                return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+            }
+        });
+        BoundServices highestPriority = allServices.remove(0);
+        short nextServiceIndex = (short) (allServices.size() > 0 ? allServices.get(0).getServicePriority() : highestPriority.getServicePriority() + 1);
+        FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, highestPriority, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, nextServiceIndex);
+        BoundServices prev = null;
+        for (BoundServices boundService : allServices) {
+            if (prev!=null) {
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, prev, iface, t, ifIndex, prev.getServicePriority(), boundService.getServicePriority());
+            }
+            prev = boundService;
+        }
+        if (prev!=null) {
+            FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, prev, iface, t, ifIndex, prev.getServicePriority(), (short) (prev.getServicePriority()+1));
+        }
+        futures.add(t.submit());
+        return futures;
+
+    }
+
 }
\ No newline at end of file
index aa0b9bc29641e23ce0ff5566fa66668206a2b2fd..f422f0eae47f1be8864a7d55ac28ed8b694419e0 100644 (file)
@@ -7,12 +7,20 @@
  */
 package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers;
 
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
@@ -21,9 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.serviceb
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class FlowBasedServicesStateUnbindHelper {
     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesStateUnbindHelper.class);
@@ -31,7 +37,6 @@ public class FlowBasedServicesStateUnbindHelper {
     public static List<ListenableFuture<Void>> unbindServicesFromInterface(Interface ifaceState,
                                                                            DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
 
         ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(ifaceState.getName(), dataBroker);
         if (servicesInfo == null) {
@@ -43,32 +48,69 @@ public class FlowBasedServicesStateUnbindHelper {
             return futures;
         }
 
-        BoundServices highestPriorityBoundService = null;
-        short highestPriority = 0xFF;
-        for (BoundServices boundService : allServices) {
-            if (boundService.getServicePriority() < highestPriority) {
-                highestPriorityBoundService = boundService;
-                highestPriority = boundService.getServicePriority();
-            }
-        }
-
         InterfaceKey interfaceKey = new InterfaceKey(ifaceState.getName());
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+                    InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+        if (iface.getType().isAssignableFrom(L2vlan.class)) {
+            return unbindServiceOnVlan(allServices, iface, ifaceState.getIfIndex(), dataBroker);
+        } else if (iface.getType().isAssignableFrom(Tunnel.class)){
+             return unbindServiceOnTunnel(allServices, iface, ifaceState.getIfIndex(), dataBroker);
+        }
+        return futures;
+    }
+
+    private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+            List<BoundServices> allServices,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            Integer ifIndex, DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
 
         NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
         if(nodeConnectorId == null){
             return futures;
         }
+        BoundServices highestPriorityBoundService = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+
         BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
         FlowBasedServicesUtils.removeIngressFlow(iface, highestPriorityBoundService, dpId, t);
 
         for (BoundServices boundService : allServices) {
             if (!boundService.equals(highestPriorityBoundService)) {
-                FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundService, t);
+                FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundService, t, boundService.getServicePriority());
             }
         }
 
+        futures.add(t.submit());
+        return futures;
+    }
+
+    private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+            List<BoundServices> allServices,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            Integer ifIndex, DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+        if (nodeConnectorId == null) {
+            return futures;
+        }
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        Collections.sort(allServices, new Comparator<BoundServices>() {
+            @Override
+            public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+                return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+            }
+        });
+        BoundServices highestPriority = allServices.remove(0);
+        FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, highestPriority, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+        for (BoundServices boundService : allServices) {
+                FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundService, t, boundService.getServicePriority());
+        }
+        futures.add(t.submit());
         return futures;
+
     }
-}
\ No newline at end of file
+
+}
index a9da21e276a5d8c0f8fdfcb83083c308b51dae6e..517240f065d61b3be715ae071b65f72e9c7424ce 100644 (file)
@@ -7,14 +7,23 @@
  */
 package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities;
 
-import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
-import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -30,6 +39,7 @@ 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.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
@@ -40,9 +50,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.base.Optional;
 
 public class FlowBasedServicesUtils {
     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
@@ -76,8 +84,8 @@ public class FlowBasedServicesUtils {
         matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
         int vlanId = 0;
         IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
-        if(l2vlan != null && l2vlan.getVlanId() != null){
-            vlanId = l2vlan.getVlanId().getValue();
+        if(l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent){
+            vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
         }
         if (vlanId > 0) {
             matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
@@ -163,7 +171,7 @@ public class FlowBasedServicesUtils {
         }
 
         String serviceRef = boundServiceNew.getServiceName();
-        String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew);
+        String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew, boundServiceNew.getServicePriority());
         StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
         Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
                 stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
@@ -200,19 +208,18 @@ public class FlowBasedServicesUtils {
     }
 
     public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, Interface iface,
-                                                  WriteTransaction t, int interfaceTag) {
+                                                  WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
         LOG.debug("Installing LPort Dispatcher Flows {}, {}", dpId, iface);
-        short serviceIndex = boundService.getServicePriority();
         String serviceRef = boundService.getServiceName();
         List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId, iface,
-                interfaceTag, serviceIndex);
+                interfaceTag, currentServiceIndex);
 
         // Get the metadata and mask from the service's write metadata instruction
         StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
         List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
         int instructionSize = serviceInstructions.size();
         BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
-        BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, ++serviceIndex, metadataValues[0]);
+        BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
                 MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
 
@@ -230,15 +237,15 @@ public class FlowBasedServicesUtils {
         }
 
         // build the flow and install it
-        String flowRef = getFlowRef(dpId, iface.getName(), boundService);
-        Flow ingressFlow = MDSALUtil.buildFlowNew(stypeOpenFlow.getDispatcherTableId(), flowRef,
+        String flowRef = getFlowRef(dpId, iface.getName(), boundService, currentServiceIndex);
+        Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
                 boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
         installFlow(dpId, ingressFlow, t);
     }
 
     public static void removeIngressFlow(Interface iface, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
         LOG.debug("Removing Ingress Flows");
-        String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld);
+        String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld, serviceOld.getServicePriority());
         FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
         Node nodeDpn = buildInventoryDpnNode(dpId);
         InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
@@ -248,12 +255,12 @@ public class FlowBasedServicesUtils {
         t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
     }
 
-    public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t) {
+    public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
         LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
 
         StypeOpenflow stypeOpenFlow = boundServicesOld.getAugmentation(StypeOpenflow.class);
         // build the flow and install it
-        String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld);
+        String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld, currentServiceIndex);
         FlowKey flowKey = new FlowKey(new FlowId(flowRef));
         Node nodeDpn = buildInventoryDpnNode(dpId);
         InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
@@ -263,9 +270,100 @@ public class FlowBasedServicesUtils {
         t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
     }
 
-    private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service) {
-        return new StringBuffer().append(dpnId).append( NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
-                .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(service.getServiceName()).append(NwConstants.FLOWID_SEPARATOR)
-                .append(service.getServicePriority()).toString();
+    private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service, short currentServiceIndex) {
+        return new StringBuffer().append(dpnId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
+                .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(currentServiceIndex).toString();
+    }
+
+    /**
+     * This util method returns an array of ServiceInfo in which index 0 will
+     * have the immediate lower priority service and index 1 will have the
+     * immediate higher priority service among the list of existing serviceInfos
+     *
+     * @param serviceInfos
+     * @param currentServiceInfo
+     * @return
+     */
+ public static BoundServices[] getHighAndLowPriorityService(
+            List<BoundServices> serviceInfos, BoundServices currentServiceInfo) {
+    BoundServices higher = null; // this will be used to hold the immediate higher service priority with respect to the currentServiceInfo
+    BoundServices lower = null; // this will be used to hold the immediate lower service priority with respect to the currentServiceInfo
+        if (serviceInfos == null || serviceInfos.isEmpty()) {
+            return new BoundServices[]{lower, higher};
+        }
+        List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+        Collections.sort(availableServiceInfos, new Comparator<BoundServices>() {
+            @Override
+            public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+                return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+            }
+        });
+        for (BoundServices availableServiceInfo: availableServiceInfos) {
+            if (currentServiceInfo.getServicePriority() > availableServiceInfo.getServicePriority()) {
+                lower = availableServiceInfo;
+                break;
+            } else {
+                higher = availableServiceInfo;
+            }
+        }
+        return new BoundServices[]{lower,higher};
+    }
+
+    public static BoundServices getHighestPriorityService(List<BoundServices> serviceInfos) {
+        List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+        if (availableServiceInfos.isEmpty()) {
+            return null;
+        }
+        BoundServices highPriorityService = availableServiceInfos.get(0);
+        availableServiceInfos.remove(0);
+        for (BoundServices availableServiceInfo: availableServiceInfos) {
+            if (availableServiceInfo.getServicePriority() > highPriorityService.getServicePriority()) {
+                highPriorityService = availableServiceInfo;
+            }
+        }
+        return highPriorityService;
     }
-}
\ No newline at end of file
+
+    public static void installVlanFlow(BigInteger dpId, long portNo, Interface iface, 
+            WriteTransaction t, List<MatchInfo> matches, int lportTag) {
+        int vlanId = 0;
+        boolean isVlanTransparent = false;
+        IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+        if(l2vlan != null){
+            vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
+            isVlanTransparent = l2vlan.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+        }
+        int instructionKey = 0;
+        BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, (short) 0);
+        BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher();
+        List<Instruction> instructions = new ArrayList<Instruction>();
+        if (vlanId != 0 && !isVlanTransparent) {
+            instructions.add(MDSALUtil.buildAndGetPopVlanActionInstruction(lportTag, instructionKey++));
+        }
+        instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, instructionKey++));
+        instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.DHCP_TABLE, instructionKey++));
+        int priority =  isVlanTransparent ? 1 : vlanId == 0 ? IfmConstants.FLOW_PRIORITY_FOR_UNTAGGED_VLAN : IfmConstants.FLOW_HIGH_PRIORITY;
+        String flowRef = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+        Flow ingressFlow = MDSALUtil.buildFlowNew(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef, priority, flowRef, 0, 0,
+                IfmConstants.VLAN_TABLE_COOKIE, matches, instructions);
+        installFlow(dpId, ingressFlow, t);
+}
+
+    public static String getFlowRef(short tableId, BigInteger dpnId, String infName) {
+        return String.format("%d:%s:%s", tableId, dpnId, infName);
+    }
+
+    public static void removeIngressFlow(Interface iface, BigInteger dpId, WriteTransaction t) {
+        LOG.debug("Removing Ingress Flows");
+        String flowKeyStr = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+        FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
+        Node nodeDpn = buildInventoryDpnNode(dpId);
+        InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
+
+        t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+    }
+
+
+}
index 86cc38a985f92269a3f3e2bc622e7ffab899a09c..6b562ccc4cf4c3f3c0c70d8e011c10da7ef62d16 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.vpnservice.interfacemgr.test;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.Futures;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -106,7 +107,7 @@ public class FlowBasedServicesConfigurationTest {
                 .setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName))
                 .setName(InterfaceManagerTestUtil.interfaceName);
 
-        stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId, flowPriority,key,instructions);
+        stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId, flowPriority,NwConstants.LPORT_DISPATCHER_TABLE,instructions);
         boundServiceNew = InterfaceManagerTestUtil.buildBoundServices(serviceName, key, new BoundServicesKey(key), stypeOpenflow);
         instructionKey = new InstructionKey(instructionKeyval);
         BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
@@ -135,8 +136,10 @@ public class FlowBasedServicesConfigurationTest {
         List<Instruction> instructionList = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
         String serviceRef = boundServiceNew.getServiceName();
         List<MatchInfo> matches = new ArrayList<>();
-        matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNum)}));
-        ingressFlow = MDSALUtil.buildFlowNew(stypeOpenflow.getDispatcherTableId(), flowRef, boundServiceNew.getServicePriority(), serviceRef, 0, 0,
+        matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+                MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(), boundServiceNew.getServicePriority()),
+                MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+        ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef, boundServiceNew.getServicePriority(), serviceRef, 0, 0,
                 stypeOpenflow.getFlowCookie(), matches, instructionList);
         FlowKey flowKey = new FlowKey(new FlowId(ingressFlow.getId()));
         flowInstanceId = InterfaceManagerTestUtil.getFlowInstanceIdentifier(dpId,ingressFlow.getTableId(),flowKey);
index ce7e9779f41d1c5300d96e2c8df6720156b3bf89..578cd949eb959ed0fc44803ff830f474322c899b 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.vpnservice.interfacemgr.test;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.Futures;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -63,7 +64,7 @@ public class FlowBasedServicesStateConfigurationTest {
     Instruction instruction = null;
     InstructionKey instructionKey = null;
     List<Instruction>instructions = new ArrayList<>();
-    short key =2;
+    short key =0;
     int ifIndexval = 100;
     int flowpriority = 2;
     String serviceName = "VPN";
@@ -101,7 +102,7 @@ public class FlowBasedServicesStateConfigurationTest {
                 .setLowerLayerIf(lowerLayerIfList)
                 .setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName))
                 .setName(InterfaceManagerTestUtil.interfaceName);
-        stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId,flowpriority, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, instructions);
+        stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId,flowpriority, NwConstants.LPORT_DISPATCHER_TABLE, instructions);
         instructionKey = new InstructionKey(instructionKeyval);
         BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
         boundService = InterfaceManagerTestUtil.buildBoundServices(serviceName,key,new BoundServicesKey(key),stypeOpenflow);
@@ -125,7 +126,9 @@ public class FlowBasedServicesStateConfigurationTest {
         List<Instruction> instructionList = boundService.getAugmentation(StypeOpenflow.class).getInstruction();
         String serviceRef = boundService.getServiceName();
         List<MatchInfo> matches = new ArrayList<>();
-        matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[]{dpId, BigInteger.valueOf(portNum)}));
+        matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+                MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(), boundService.getServicePriority()),
+                MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
         ingressFlow = MDSALUtil.buildFlowNew(stypeOpenflow.getDispatcherTableId(), flowRef, boundService.getServicePriority(), serviceRef, 0, 0,
                 stypeOpenflow.getFlowCookie(), matches, instructionList);
         FlowKey flowKey = new FlowKey(new FlowId(ingressFlow.getId()));
index 89d7db18a4b3e0d8ab75f0dad761d2052778a22a..0da5c10dce4bd19393ccaefd97c405ddc951e98d 100644 (file)
@@ -218,8 +218,7 @@ public class InterfaceManagerTestUtil {
     public static String buildflowRef(BigInteger dpId,String servicaName,String boundServicename, short servicePriority)
     {
         String flowRef = new StringBuffer().append(dpId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR).
-                append(servicaName).append(NwConstants.FLOWID_SEPARATOR).append(boundServicename).
-                append(NwConstants.FLOWID_SEPARATOR).append(servicePriority).toString();
+                append(servicaName).append(NwConstants.FLOWID_SEPARATOR).append(servicePriority).toString();
         return flowRef;
     }
 
index cd460f228bb7aa35afb461181e8875dbe3977ce4..8030fff7166ff944b9c2dc02bedbfbe6399c2336 100644 (file)
@@ -13,6 +13,7 @@ import static org.mockito.Mockito.*;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 
 import java.math.BigInteger;
 
@@ -40,8 +41,13 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 @RunWith(MockitoJUnitRunner.class)
 public class VlanInterfaceConfigurationTest {
@@ -91,10 +97,16 @@ public class VlanInterfaceConfigurationTest {
         nodeConnectorInstanceIdentifier = InterfaceManagerTestUtil.getNcIdent("openflow:1", nodeConnectorId);
         interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(vlanInterfaceEnabled.getName());
         stateInterface = InterfaceManagerTestUtil.buildStateInterface(InterfaceManagerTestUtil.interfaceName, nodeConnectorId);
+        AllocateIdOutput output = new AllocateIdOutputBuilder().setIdValue((long)1).build();
+        RpcResultBuilder<AllocateIdOutput> allocateIdRpcBuilder = RpcResultBuilder.success();
+        allocateIdRpcBuilder.withResult(output);
+        ListenableFuture<RpcResult<AllocateIdOutput>> future = Futures.immediateFuture(allocateIdRpcBuilder.build());
 
         // Setup mocks
         when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
         when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+
+        when(idManager.allocateId(any(AllocateIdInput.class))).thenReturn(future);
     }
 
     @Test
index 27afd5c35c72ff6987db65c35aa625dd207fa231..7d72f3a88d73ecb2106e68b30c960fd8723980c9 100644 (file)
@@ -490,4 +490,15 @@ public class MDSALUtil {
         return null;
     }
 
+    public static TransmitPacketInput getPacketOut(List<Action> actions, byte[] payload, BigInteger dpnId) {
+        NodeConnectorRef ncRef = getDefaultNodeConnRef(dpnId);
+        return new TransmitPacketInputBuilder()
+                .setAction(actions)
+                .setPayload(payload)
+                .setNode(
+                        new NodeRef(InstanceIdentifier.builder(Nodes.class)
+                                .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
+                .setIngress(ncRef).setEgress(ncRef).build();
+    }
+
 }
index ead21fd4e0e5e34da728896116be1e7cc245159a..9133de482765b11ce3d102684e48765b17eb2dbb 100644 (file)
@@ -47,9 +47,10 @@ public class NwConstants {
 
     public static final short L3_PROTOCOL_TABLE = 36;
     public static final short L3_INTERFACE_TABLE = 80;
-    public static final short LPORT_DISPATCHER_TABLE = 30;
+    public static final short LPORT_DISPATCHER_TABLE = 17;
     public static final short VLAN_INTERFACE_INGRESS_TABLE = 0;
     public static final short INTERNAL_TUNNEL_TABLE = 36;
     public static final short EXTERNAL_TUNNEL_TABLE = 36;
+    public static final short DHCP_TABLE = 16;
 
- }
\ No newline at end of file
+ }
index da9c61c28ba67909fbc2644522f318405142a686..706f25997c7e5e9348ed582b15d070cb9a894f54 100644 (file)
@@ -38,7 +38,7 @@ public class Ethernet extends Packet {
         etherTypeClassMap.put(EtherTypes.LLDP.shortValue(), LLDP.class);
         etherTypeClassMap.put(EtherTypes.IPv4.shortValue(), IPv4.class);
         // TODO: Add support for more classes here
-        // etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class);
+        etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class);
         // etherTypeClassMap.put(EtherTypes.OLDQINQ.shortValue(), IEEE8021Q.class);
         // etherTypeClassMap.put(EtherTypes.QINQ.shortValue(), IEEE8021Q.class);
         // etherTypeClassMap.put(EtherTypes.CISCOQINQ.shortValue(), IEEE8021Q.class);
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/IEEE8021Q.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/IEEE8021Q.java
new file mode 100644 (file)
index 0000000..c5613ee
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 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.vpnservice.mdsalutil.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+
+public class IEEE8021Q extends Ethernet {
+    private static final String PRIORITY = "Priority";
+    private static final String CFI = "CFI";
+    private static final String VLAN_ID = "VlanId";
+    private static final String ETHT = "EtherType";
+
+    private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+        private static final long serialVersionUID = 1L;
+        {
+            put(PRIORITY, new ImmutablePair<Integer, Integer>(0, 3));
+            put(CFI, new ImmutablePair<Integer, Integer>(3, 1));
+            put(VLAN_ID, new ImmutablePair<Integer, Integer>(4, 12));
+            put(ETHT, new ImmutablePair<Integer, Integer>(16, 16));
+        }
+    };
+    private Map<String, byte[]> fieldValues;
+
+    /**
+     * Default constructor that creates and sets the HashMap
+     */
+    public IEEE8021Q() {
+        super();
+        fieldValues = new HashMap<String, byte[]>();
+        hdrFieldCoordMap = fieldCoordinates;
+        hdrFieldsMap = fieldValues;
+    }
+
+    public IEEE8021Q(boolean writeAccess) {
+        super(writeAccess);
+        fieldValues = new HashMap<String, byte[]>();
+        hdrFieldCoordMap = fieldCoordinates;
+        hdrFieldsMap = fieldValues;
+    }
+
+    public short getPriority() {
+        return (BitBufferHelper.getShort(fieldValues.get(PRIORITY)));
+    }
+
+    public short getCfi() {
+        return (BitBufferHelper.getShort(fieldValues.get(CFI)));
+    }
+
+    public short getVlanId() {
+        return (BitBufferHelper.getShort(fieldValues.get(VLAN_ID)));
+    }
+
+    @Override
+    public short getEtherType() {
+        return BitBufferHelper.getShort(fieldValues.get(ETHT));
+    }
+
+    public IEEE8021Q setPriority(short priority) {
+        byte[] priorityByte = BitBufferHelper.toByteArray(priority);
+        fieldValues.put(PRIORITY, priorityByte);
+        return this;
+    }
+
+    public IEEE8021Q setCFI(short cfi) {
+        byte[] cfiByte = BitBufferHelper
+                .toByteArray(cfi);
+        fieldValues.put(CFI, cfiByte);
+        return this;
+    }
+
+    public IEEE8021Q setVlanId(short vlanId) {
+        byte[] vlan = BitBufferHelper
+                .toByteArray(vlanId);
+        fieldValues.put(VLAN_ID, vlan);
+        return this;
+    }
+
+    @Override
+    public IEEE8021Q setEtherType(short etherType) {
+        byte[] ethType = BitBufferHelper.toByteArray(etherType);
+        fieldValues.put(ETHT, ethType);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result
+                + ((fieldValues == null) ? 0 : fieldValues.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        IEEE8021Q other = (IEEE8021Q) obj;
+        if (fieldValues == null) {
+            if (other.fieldValues != null) {
+                return false;
+            }
+        } else if (!fieldValues.equals(other.fieldValues)) {
+            return false;
+        }
+        return true;
+    }
+}