From 007910122eafb7ccfdfbdd2c48c6ec242c143c87 Mon Sep 17 00:00:00 2001 From: Kency Date: Wed, 3 Feb 2016 12:22:43 +0530 Subject: [PATCH] Bug 5199 : DHCP and Transparent code changes Change-Id: I9c0864fd776cb091fca1682f062eaa249f86e680 Signed-off-by: Kency (cherry picked from commit da5201e942d7f74775d338891b5f69c27844ede5) --- .../dhcpservice/api/DHCPMConstants.java | 6 +- .../src/main/yang/dhcpservice-api.yang | 25 +++ dhcpservice/dhcpservice-impl/pom.xml | 5 + .../DhcpInterfaceEventListener.java | 162 ++++++++++++++ .../vpnservice/dhcpservice/DhcpManager.java | 74 ++++++- .../dhcpservice/DhcpPktHandler.java | 209 +++++++++++++----- .../vpnservice/dhcpservice/DhcpProvider.java | 11 +- .../vpnservice/dhcpservice/NodeListener.java | 2 +- .../impl/rev150710/DhcpServiceImplModule.java | 4 + .../vpnservice/interfacemgr/IfmConstants.java | 4 + .../OvsInterfaceConfigAddHelper.java | 25 ++- .../OvsInterfaceConfigRemoveHelper.java | 11 +- .../OvsVlanMemberConfigAddHelper.java | 13 ++ .../OvsVlanMemberConfigRemoveHelper.java | 15 +- .../OvsInterfaceStateAddHelper.java | 20 +- .../OvsInterfaceStateRemoveHelper.java | 22 +- .../InterfaceManagerRpcService.java | 9 +- .../FlowBasedServicesConfigBindHelper.java | 104 ++++++--- .../FlowBasedServicesConfigUnbindHelper.java | 110 +++++++-- .../FlowBasedServicesStateBindHelper.java | 72 ++++-- .../FlowBasedServicesStateUnbindHelper.java | 76 +++++-- .../utilities/FlowBasedServicesUtils.java | 142 ++++++++++-- .../FlowBasedServicesConfigurationTest.java | 9 +- ...owBasedServicesStateConfigurationTest.java | 9 +- .../test/InterfaceManagerTestUtil.java | 3 +- .../test/VlanInterfaceConfigurationTest.java | 12 + .../vpnservice/mdsalutil/MDSALUtil.java | 11 + .../vpnservice/mdsalutil/NwConstants.java | 5 +- .../vpnservice/mdsalutil/packet/Ethernet.java | 2 +- .../mdsalutil/packet/IEEE8021Q.java | 126 +++++++++++ 30 files changed, 1093 insertions(+), 205 deletions(-) create mode 100644 dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpInterfaceEventListener.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/IEEE8021Q.java diff --git a/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/vpnservice/dhcpservice/api/DHCPMConstants.java b/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/vpnservice/dhcpservice/api/DHCPMConstants.java index bcf8612d..ef3a495a 100644 --- a/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/vpnservice/dhcpservice/api/DHCPMConstants.java +++ b/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/vpnservice/dhcpservice/api/DHCPMConstants.java @@ -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"); } diff --git a/dhcpservice/dhcpservice-api/src/main/yang/dhcpservice-api.yang b/dhcpservice/dhcpservice-api/src/main/yang/dhcpservice-api.yang index 6d45eed9..fd86e9ff 100644 --- a/dhcpservice/dhcpservice-api/src/main/yang/dhcpservice-api.yang +++ b/dhcpservice/dhcpservice-api/src/main/yang/dhcpservice-api.yang @@ -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 diff --git a/dhcpservice/dhcpservice-impl/pom.xml b/dhcpservice/dhcpservice-impl/pom.xml index 35147084..cff44a5f 100644 --- a/dhcpservice/dhcpservice-impl/pom.xml +++ b/dhcpservice/dhcpservice-impl/pom.xml @@ -59,6 +59,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html commons-net commons-net + + ${project.groupId} + interfacemgr-api + ${vpnservices.version} + 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 index 00000000..b7f26298 --- /dev/null +++ b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpInterfaceEventListener.java @@ -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 implements AutoCloseable { + + private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class); + private DhcpManager dhcpManager; + private ListenerRegistration listenerRegistration; + private DataBroker dataBroker; + private static final FutureCallback DEFAULT_CALLBACK = new FutureCallback() { + 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 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 identifier, + Interface del) { + String interfaceName = del.getName(); + List 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 identifier, + Interface original, Interface update) { + } + + @Override + protected void add(InstanceIdentifier identifier, Interface add) { + String interfaceName = add.getName(); + List 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 instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build(); + Optional 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 instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build(); + Optional 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; + } +} diff --git a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpManager.java b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpManager.java index f195fa89..6233d40d 100644 --- a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpManager.java +++ b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpManager.java @@ -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 matches = new ArrayList(); + + 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 instructions = new ArrayList(); + List actionsInfos = new ArrayList(); + + // 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 matches = new ArrayList(); + List instructions = new ArrayList(); + 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); + } } diff --git a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpPktHandler.java b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpPktHandler.java index 6a4539f1..5c26610c 100644 --- a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpPktHandler.java +++ b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpPktHandler.java @@ -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> localCache = new HashMap>(); private boolean computeUdpChecksum = true; private PacketProcessingService pktService; @@ -75,7 +87,7 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener { LOG.trace("Pkt received: {}", packet); Class 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 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 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 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 = 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 ncId = inNcRef.getValue().firstIdentifierOf(NodeConnector.class); - Optional 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> 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 ifStateId = + buildStateInterfaceId(interfaceName); + Optional ifStateOptional = + MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker); + if (!ifStateOptional.isPresent()) { + return null; + } + + return ifStateOptional.get(); + } + + private InstanceIdentifier buildStateInterfaceId(String interfaceName) { + InstanceIdentifierBuilder 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 id = idBuilder.build(); + return id; + } + + private List getEgressAction(String interfaceName) { + List actions = null; + try { + Future> result = + interfaceManagerRpc.getEgressActionsForInterface( + new GetEgressActionsForInterfaceInputBuilder().setIntfName(interfaceName).build()); + RpcResult 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 getDpnIdPhysicalAddressFromInterfaceName(String interfaceName) { + ImmutablePair 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 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(dpId, phyAddress); + localCache.put(interfaceName, pair); + return null; + } } diff --git a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpProvider.java b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpProvider.java index 5f15135f..439d7352 100644 --- a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpProvider.java +++ b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/DhcpProvider.java @@ -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; + } } diff --git a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/NodeListener.java b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/NodeListener.java index 8cb8a7ad..b7d0f2be 100644 --- a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/NodeListener.java +++ b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/vpnservice/dhcpservice/NodeListener.java @@ -73,7 +73,7 @@ public class NodeListener extends AbstractDataChangeListener implements Au NodeId nodeId = add.getId(); String[] node = nodeId.getValue().split(":"); BigInteger dpId = new BigInteger(node[1]); - dhcpManager.installDhcpEntries(dpId); + dhcpManager.setupTableMissForDhcpTable(dpId); } @Override diff --git a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java index eac19a99..2fa746dc 100644 --- a/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java +++ b/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java @@ -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; } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java index 927f8aeb..9a315e02 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java @@ -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); } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java index a8e2d6ed..11eed1c6 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigAddHelper.java @@ -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 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 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 matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, ifaceChild); + FlowBasedServicesUtils.installVlanFlow(dpId, portNo, ifaceChild, transaction, matches, ifIndex); + } } futures.add(transaction.submit()); } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java index 04e12107..722db1aa 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsInterfaceConfigRemoveHelper.java @@ -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 ifChildStateId = IfmUtil.buildStateInterfaceId(interfaceChildEntry.getChildInterface()); t.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId); + InterfaceKey childIfKey = new InterfaceKey(interfaceChildEntry.getChildInterface()); + FlowBasedServicesUtils.removeIngressFlow(InterfaceManagerCommonUtils.getInterfaceFromConfigDS(childIfKey, dataBroker), dpId, t); } } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java index 6f7d6349..808fa7ec 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java @@ -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 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. diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigRemoveHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigRemoveHelper.java index cb039796..83c7c042 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigRemoveHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigRemoveHelper.java @@ -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 ifStateId = IfmUtil.buildStateInterfaceId(interfaceOld.getName()); t.delete(LogicalDatastoreType.OPERATIONAL, ifStateId); + FlowBasedServicesUtils.removeIngressFlow(interfaceOld, dpId, t); } futures.add(t.submit()); diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateAddHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateAddHelper.java index d7fc0879..f43d40be 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateAddHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateAddHelper.java @@ -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 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 ifChildStateId = IfmUtil.buildStateInterfaceId(ifaceChild.getName()); List 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 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 diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateRemoveHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateRemoveHelper.java index ee9382d5..d742a354 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateRemoveHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/statehelpers/OvsInterfaceStateRemoveHelper.java @@ -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); } } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/rpcservice/InterfaceManagerRpcService.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/rpcservice/InterfaceManagerRpcService.java index b21cd15b..daa613aa 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/rpcservice/InterfaceManagerRpcService.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/rpcservice/InterfaceManagerRpcService.java @@ -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) })); diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigBindHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigBindHelper.java index 0e9be053..5bc4219e 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigBindHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigBindHelper.java @@ -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> bindService(InstanceIdentifier instanceIdentifier, BoundServices boundServiceNew, DataBroker dataBroker) { List> 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> bindServiceOnTunnel(BoundServices boundServiceNew, List allServices, Interface iface, int ifIndex, DataBroker dataBroker) { + List> 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 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 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> bindServiceOnVlan(BoundServices boundServiceNew, List allServices, Interface iface, int ifIndex, DataBroker dataBroker) { + List> 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 diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigUnbindHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigUnbindHelper.java index cd0c00d9..6984e784 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigUnbindHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/confighelpers/FlowBasedServicesConfigUnbindHelper.java @@ -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> unbindService(InstanceIdentifier instanceIdentifier, BoundServices boundServiceOld, DataBroker dataBroker) { List> 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 = 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> unbindServiceOnVlan( + BoundServices boundServiceOld, + List boundServices, Interface iface, int ifIndex, + DataBroker dataBroker) { + + List> 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> unbindServiceOnTunnel( + BoundServices boundServiceOld, + List boundServices, Interface iface, int ifIndex, + DataBroker dataBroker) { + List> 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 = 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 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 diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateBindHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateBindHelper.java index 25812cdf..6186802f 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateBindHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateBindHelper.java @@ -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> bindServicesOnInterface(Interface ifaceState, DataBroker dataBroker) { List> 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 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> bindServiceOnTunnel( + List allServices, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface, + Integer ifIndex, DataBroker dataBroker) { + List> futures = new ArrayList<>(); + NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker); + long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId)); + BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId)); + List 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> bindServiceOnVlan( + List allServices, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface, + Integer ifIndex, DataBroker dataBroker) { + List> 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() { + @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 diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateUnbindHelper.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateUnbindHelper.java index aa0b9bc2..f422f0ea 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateUnbindHelper.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/statehelpers/FlowBasedServicesStateUnbindHelper.java @@ -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> unbindServicesFromInterface(Interface ifaceState, DataBroker dataBroker) { List> 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> unbindServiceOnTunnel( + List allServices, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface, + Integer ifIndex, DataBroker dataBroker) { + List> 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> unbindServiceOnVlan( + List allServices, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface, + Integer ifIndex, DataBroker dataBroker) { + List> 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() { + @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 + +} diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/utilities/FlowBasedServicesUtils.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/utilities/FlowBasedServicesUtils.java index a9da21e2..517240f0 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/utilities/FlowBasedServicesUtils.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/servicebindings/flowbased/utilities/FlowBasedServicesUtils.java @@ -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 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 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 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 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 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 availableServiceInfos = new ArrayList(serviceInfos); + Collections.sort(availableServiceInfos, new Comparator() { + @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 serviceInfos) { + List availableServiceInfos = new ArrayList(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 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 instructions = new ArrayList(); + 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 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); + } + + +} diff --git a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesConfigurationTest.java b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesConfigurationTest.java index 86cc38a9..6b562ccc 100644 --- a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesConfigurationTest.java +++ b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesConfigurationTest.java @@ -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 instructionList = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction(); String serviceRef = boundServiceNew.getServiceName(); List 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); diff --git a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesStateConfigurationTest.java b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesStateConfigurationTest.java index ce7e9779..578cd949 100644 --- a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesStateConfigurationTest.java +++ b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/FlowBasedServicesStateConfigurationTest.java @@ -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; Listinstructions = 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 instructionList = boundService.getAugmentation(StypeOpenflow.class).getInstruction(); String serviceRef = boundService.getServiceName(); List 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())); diff --git a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java index 89d7db18..0da5c10d 100644 --- a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java +++ b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java @@ -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; } diff --git a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/VlanInterfaceConfigurationTest.java b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/VlanInterfaceConfigurationTest.java index cd460f22..8030fff7 100644 --- a/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/VlanInterfaceConfigurationTest.java +++ b/interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/VlanInterfaceConfigurationTest.java @@ -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 allocateIdRpcBuilder = RpcResultBuilder.success(); + allocateIdRpcBuilder.withResult(output); + ListenableFuture> 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 diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java index 27afd5c3..7d72f3a8 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java @@ -490,4 +490,15 @@ public class MDSALUtil { return null; } + public static TransmitPacketInput getPacketOut(List 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(); + } + } diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java index ead21fd4..9133de48 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/NwConstants.java @@ -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 + } diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java index da9c61c2..706f2599 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/Ethernet.java @@ -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 index 00000000..c5613eea --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/packet/IEEE8021Q.java @@ -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> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(PRIORITY, new ImmutablePair(0, 3)); + put(CFI, new ImmutablePair(3, 1)); + put(VLAN_ID, new ImmutablePair(4, 12)); + put(ETHT, new ImmutablePair(16, 16)); + } + }; + private Map fieldValues; + + /** + * Default constructor that creates and sets the HashMap + */ + public IEEE8021Q() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + public IEEE8021Q(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + 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; + } +} -- 2.36.6