Fixing socket for vpp endpoint
[groupbasedpolicy.git] / neutron-vpp-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / vpp / mapper / processors / PortHandler.java
index fb7fdfa262dba6aec5f70c40c280976ac5041719..01c2152cc0309627e18c489ee87464937916f265 100644 (file)
@@ -8,6 +8,11 @@
 \r
 package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;\r
 \r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import javax.annotation.Nullable;\r
+\r
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;\r
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
@@ -16,7 +21,6 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;\r
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;\r
-import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.SocketInfo;\r
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
@@ -29,14 +33,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gb
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPortKey;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCase;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCaseBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCaseBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.binding.attributes.VifDetails;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;\r
@@ -50,13 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;\r
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;\r
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;\r
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;\r
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;\r
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;\r
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\r
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;\r
 import org.slf4j.Logger;\r
@@ -65,31 +63,27 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;\r
 import com.google.common.base.Optional;\r
 \r
-import javax.annotation.Nullable;\r
-import java.util.Collections;\r
-import java.util.List;\r
-\r
+import javax.annotation.Nonnull;\r
 public class PortHandler implements TransactionChainListener {\r
 \r
-    private static final Logger LOG = LoggerFactory.getLogger(MappingProvider.class);\r
+    private static final Logger LOG = LoggerFactory.getLogger(PortHandler.class);\r
 \r
     private static final String COMPUTE_OWNER = "compute";\r
     private static final String DHCP_OWNER = "dhcp";\r
     private static final String ROUTER_OWNER = "network:router_interface";\r
     private static final String[] SUPPORTED_DEVICE_OWNERS = {COMPUTE_OWNER, DHCP_OWNER, ROUTER_OWNER};\r
     private static final String VHOST_USER = "vhostuser";\r
-    private static final String NETCONF_TOPOLOGY_ID = "topology-netconf";\r
+    private static final String UNBOUND = "unbound";\r
     private static final String VPP_INTERFACE_NAME_PREFIX = "neutron_port_";\r
     private static final String TAP_PORT_NAME_PREFIX = "tap";\r
     private static final String RT_PORT_NAME_PREFIX = "qr-";\r
+    private static final String VHOST_SOCKET_KEY = "vhostuser_socket";\r
 \r
     private BindingTransactionChain transactionChain;\r
     private DataBroker dataBroker;\r
-    private SocketInfo socketInfo;\r
 \r
-    PortHandler(DataBroker dataBroker, SocketInfo socketInfo) {\r
+    PortHandler(DataBroker dataBroker) {\r
         this.dataBroker = dataBroker;\r
-        this.socketInfo = socketInfo;\r
         transactionChain = this.dataBroker.createTransactionChain(this);\r
     }\r
 \r
@@ -164,18 +158,38 @@ public class PortHandler implements TransactionChainListener {
         processCreated(delta);\r
     }\r
 \r
-    private boolean isUpdateNeeded(Port oldPort, Port newPort) {\r
+    private boolean isUpdateNeeded(final Port oldPort, final Port newPort) {\r
         //TODO fix this to better support update of ports for VPP\r
-        PortBindingExtension oldPortAugmentation = oldPort.getAugmentation(PortBindingExtension.class);\r
-        PortBindingExtension newPortAugmentation = newPort.getAugmentation(PortBindingExtension.class);\r
-\r
-        List<VifDetails> vifDetails = oldPortAugmentation.getVifDetails();\r
+        final PortBindingExtension oldPortAugmentation = oldPort.getAugmentation(PortBindingExtension.class);\r
+        final PortBindingExtension newPortAugmentation = newPort.getAugmentation(PortBindingExtension.class);\r
 \r
         if (newPortAugmentation == null) {\r
             LOG.trace("Port {} is no longer a vhost type port, updating port...");\r
             return true;\r
         }\r
 \r
+        final String oldDeviceOwner = oldPort.getDeviceOwner();\r
+        final String oldVifType = oldPortAugmentation.getVifType();\r
+        final String newDeviceOwner = newPort.getDeviceOwner();\r
+        final String newVifType = newPortAugmentation.getVifType();\r
+\r
+        // TODO potential bug here\r
+        // Temporary change for Openstack Mitaka: If old neutron-binding:vif-type is vhost, new one is unbound and\r
+        // device owner is ROUTER_OWNER, skip update. Openstack (or ml2) sometimes sends router update messages in\r
+        // incorrect order which causes unwanted port removal\r
+        if (oldVifType.equals(VHOST_USER) && newVifType.equals(UNBOUND) && oldDeviceOwner != null &&\r
+                ROUTER_OWNER.equals(oldDeviceOwner) && ROUTER_OWNER.equals(newDeviceOwner)) {\r
+            LOG.warn("Port vif-type was updated from vhost to unbound. This update is currently disabled and will be skipped");\r
+            return false;\r
+        }\r
+\r
+        if (newVifType != null && !newVifType.equals(oldVifType)) {\r
+            LOG.trace("Vif type changed, old: {} new {}", oldVifType, newVifType);\r
+            return true;\r
+        }\r
+\r
+        final List<VifDetails> vifDetails = oldPortAugmentation.getVifDetails();\r
+\r
         if (!oldPortAugmentation.getHostId().equals(newPortAugmentation.getHostId()) ||\r
             nullToEmpty(vifDetails).size() != nullToEmpty(newPortAugmentation.getVifDetails()).size()) {\r
             return true;\r
@@ -222,10 +236,11 @@ public class PortHandler implements TransactionChainListener {
             .setAddress(bebp.getAddress())\r
             .setAddressType(bebp.getAddressType())\r
             .setVppInterfaceName(VPP_INTERFACE_NAME_PREFIX + bebp.getPortId().getValue())\r
-            .setVppNodePath(createNodeIid(new NodeId(portBinding.getHostId())));\r
+            .setVppNodeId(new NodeId(portBinding.getHostId()));\r
+\r
         if (port.getDeviceOwner().contains(COMPUTE_OWNER)) {\r
-            String socket = socketInfo.getSocketPath() + socketInfo.getSocketPrefix() + bebp.getPortId().getValue();\r
-            vppEpBuilder.setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(socket).build());\r
+            vppEpBuilder.setInterfaceTypeChoice(\r
+                new VhostUserCaseBuilder().setSocket(getSocketFromPortBinding(portBinding)).build());\r
         } else if (port.getDeviceOwner().contains(DHCP_OWNER) && port.getMacAddress() != null) {\r
             TapCase tapCase = new TapCaseBuilder().setPhysicalAddress(new PhysAddress(port.getMacAddress().getValue()))\r
                 .setName(createPortName(port.getUuid()))\r
@@ -242,6 +257,17 @@ public class PortHandler implements TransactionChainListener {
         return vppEpBuilder.build();\r
     }\r
 \r
+    private String getSocketFromPortBinding(@Nonnull PortBindingExtension portBindingExtension) {\r
+        List<VifDetails> vifDetails = nullToEmpty(portBindingExtension.getVifDetails());\r
+\r
+        for (VifDetails detail : vifDetails) {\r
+            if (VHOST_SOCKET_KEY.equalsIgnoreCase(detail.getDetailsKey())) {\r
+                return detail.getValue();\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+\r
     private LoopbackCase getLoopbackCase(Port port) {\r
         LoopbackCaseBuilder loopbackCase = new LoopbackCaseBuilder()\r
             .setPhysAddress(new PhysAddress(port.getMacAddress().getValue()));\r
@@ -329,13 +355,6 @@ public class PortHandler implements TransactionChainListener {
         return tapPortName;\r
     }\r
 \r
-    private InstanceIdentifier<Node> createNodeIid(NodeId nodeId) {\r
-        return InstanceIdentifier.builder(NetworkTopology.class)\r
-            .child(Topology.class, new TopologyKey(new TopologyId(NETCONF_TOPOLOGY_ID)))\r
-            .child(Node.class, new NodeKey(nodeId))\r
-            .build();\r
-    }\r
-\r
     private InstanceIdentifier<VppEndpoint> createVppEndpointIid(VppEndpointKey vppEpKey) {\r
         return InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEpKey).build();\r
     }\r