BUG 4208 - Unstack and restack existing compute
authorravi_sabapathy <ravi_sabapathy@dell.com>
Mon, 28 Sep 2015 15:15:11 +0000 (08:15 -0700)
committerFlavio Fernandes <ffernand@redhat.com>
Thu, 15 Oct 2015 19:53:59 +0000 (19:53 +0000)
Loop through all the ports in the same network
and add the VM's unicast mac rule of the destination
node in the source node.
Change-Id: I73c0056e1a8386ffbab71a7a5732e81791eb6c88
Signed-off-by: ravi_sabapathy <ravi_sabapathy@dell.com>
(cherry picked from commit ad0cb7e3855721477e5d98a8e7988492ab16771f)

openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/SecurityServicesManager.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImpl.java

index 12879dadda1c22db175238ea5b35d3002beb1fe8..f2d687f1066534baca3aa346250a04f256f1e856 100644 (file)
@@ -1044,6 +1044,62 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider {
             LOG.warn("programLocalRules: No DCHP port seen in  network of {}", intf);
         }
     }
+
+    /*
+     * The function is for the new compute node joining the existing network.
+     * When a new VM is instantiated in the new compute node, neutron port add
+     * event is generated. This event is processed only for that node. So,
+     * loop through all the ports of the same network and install unicast mac
+     * flow for the VM's created on the TEP of the destination node in src node.
+     * This function will be executed even for any new VM creation in an existing
+     * network. If a cache is maintained to optimize the below flow addition, it will
+     * work only for one unstack and restack. For the next unstack and restack,
+     * it will not work since the cache would have been already deleted.
+     */
+    private void programTunnelRulesInNewNode(NeutronNetwork network,
+                                             String networkType, String segmentationId,
+                                             InetAddress src, InetAddress dst,
+                                             Node srcBridgeNode, Node dstBridgeNode,
+                                             OvsdbTerminationPointAugmentation intf){
+        try {
+            long localPort = southbound.getOFPort(intf);
+            if(localPort != 0)
+            {
+                LOG.debug("Interface update details {}", intf);
+
+                /*
+                 * When a network is added and the TEP destination is not present in a
+                 * node C1, tunnelin and broadcast rules will not be programmed, since
+                 * OF port is not created. So, when a new node C2 joins and create a new
+                 * VM, the tunnelin and broadcast rule will not be present in C1.
+                 * So, handling it in the case below to make ping work.
+                 */
+                if(securityServicesManager.getNeutronPortFromDhcpIntf(intf) == null){
+                    programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, true);
+                }
+
+                /*
+                 * FIX for 4208 - loop through all the ports and add the VM's
+                 * unicast mac rule of the destination node in the source node.
+                 * When a new node is added, it needs to configure the VM unicast mac
+                 * flow rules which were created before it was joined to an existing
+                 * network.
+                 */
+                List<OvsdbTerminationPointAugmentation> ports = southbound.getTerminationPointsOfBridge(dstBridgeNode);
+                for (OvsdbTerminationPointAugmentation port : ports) {
+                    if(network == tenantNetworkManager.getTenantNetwork(port)){
+                        programTunnelRules(networkType, segmentationId, dst, srcBridgeNode, port, false);
+                    }
+                    else{
+                        LOG.trace("Port {} is not part of network {}", port, network);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Exception during handlingNeutron network add", e);
+        }
+    }
+
     @Override
     public boolean handleInterfaceUpdate(NeutronNetwork network, Node srcNode,
                                          OvsdbTerminationPointAugmentation intf) {
@@ -1060,7 +1116,7 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider {
             programVlanRules(network, srcNode, intf);
         } else if (isTunnel(networkType)){
 
-            boolean sourceTunnelStatus;
+            boolean sourceTunnelStatus = false;
             boolean destTunnelStatus = false;
             for (Node dstNode : nodes.values()) {
                 InetAddress src = configurationService.getTunnelEndPoint(srcNode);
@@ -1080,6 +1136,8 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider {
                     }
                     if (destTunnelStatus) {
                         programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, false);
+                        programTunnelRulesInNewNode(network, networkType, segmentationId, src, dst,
+                                                    srcBridgeNode, dstBridgeNode, intf);
                     }
                 } else {
                     LOG.warn("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table. "
index b5f06675942b6b3cbfa16bad6e6977dd47b7dc11..1bb10552c6d07da7fa07c66c4066804750d9cab8 100644 (file)
@@ -43,6 +43,14 @@ public interface SecurityServicesManager {
      */
     NeutronPort getDhcpServerPort(OvsdbTerminationPointAugmentation intf);
 
+    /**
+      * Check if the given interface corresponds to a DHCP server port.
+      *
+      * @param intf the intf
+      * @return Return the DHCP neutron port
+      */
+    NeutronPort getNeutronPortFromDhcpIntf(OvsdbTerminationPointAugmentation intf);
+
     /**
      * Is the port a compute port.
      *
@@ -81,4 +89,4 @@ public interface SecurityServicesManager {
      */
     List<Neutron_IPs> getVmListForSecurityGroup(List<Neutron_IPs> srcAddressList,
                                                 String securityGroupUuid);
-}
\ No newline at end of file
+}
index 4409731be49429e09a8724485c43e607095a0814..1284419ff6af048126d3b08bc9949e4c391db5ef 100644 (file)
@@ -133,9 +133,33 @@ public class SecurityServicesImpl implements ConfigInterface, SecurityServicesMa
             LOG.error("getDHCPServerPort:getDHCPServerPort failed due to ", e);
             return null;
         }
-
         return null;
+    }
 
+    @Override
+    public NeutronPort getNeutronPortFromDhcpIntf(
+            OvsdbTerminationPointAugmentation terminationPointAugmentation) {
+        if (neutronPortCache == null) {
+            LOG.error("getNeutronPortFromDhcpIntf: neutron port is null");
+            return null;
+        }
+        String neutronPortId = southbound.getInterfaceExternalIdsValue(
+                terminationPointAugmentation,
+                Constants.EXTERNAL_ID_INTERFACE_ID);
+        if (neutronPortId == null) {
+            return null;
+        }
+        NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
+        if (neutronPort == null) {
+            LOG.error("getNeutronPortFromDhcpIntf: neutron port of {} is not found", neutronPortId);
+            return null;
+        }
+        /* if the current port is a DHCP port, return true*/
+        if (neutronPort.getDeviceOwner().contains("dhcp")) {
+            LOG.trace("getNeutronPortFromDhcpIntf: neutronPort is a dhcp port", neutronPort );
+            return neutronPort;
+        }
+        return null;
     }
 
     @Override
@@ -315,4 +339,4 @@ public class SecurityServicesImpl implements ConfigInterface, SecurityServicesMa
             neutronSubnetCache = (INeutronSubnetCRUD) impl;
         }
     }
-}
\ No newline at end of file
+}