Fix FloatingIp add GARP handling 90/44990/4
authorRavit Peretz <ravit.peretz@hpe.com>
Wed, 31 Aug 2016 15:49:20 +0000 (18:49 +0300)
committerSam Hague <shague@redhat.com>
Thu, 1 Sep 2016 15:24:14 +0000 (15:24 +0000)
Consolidate VpnFloatingIPHanlder
Send GARP only for VM OVS
Reuse SendArpRequestInput
Change-Id: I0ff992d3175470163a77f4f216c5febeeb6b53a3
Signed-off-by: Ravit Peretz <ravit.peretz@hpe.com>
vpnservice/natservice/natservice-impl/pom.xml
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatServiceCounters.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/VpnFloatingIpHandler.java
vpnservice/natservice/natservice-impl/src/main/resources/org/opendaylight/blueprint/natservice.xml
vpnservice/neutronvpn/neutronvpn-api/src/main/java/org/opendaylight/netvirt/neutronvpn/api/utils/NeutronConstants.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/FloatingIpGarpHandler.java [deleted file]

index 23714e63dae862d09093cd1d55edde71c8fbc8cb..728959a592815e8dcfdfcdaf7b74303348146763 100644 (file)
@@ -30,6 +30,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>natservice-api</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.genius</groupId>
+      <artifactId>arputil-api</artifactId>
+      <version>${genius.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.genius</groupId>
       <artifactId>mdsalutil-api</artifactId>
index f7e8e69af369f63272714ea7dea217c0906ee3ce..9ae79038f68555000d0525f4249ef05c435b4622 100644 (file)
@@ -16,7 +16,11 @@ public enum NatServiceCounters {
     remove_external_network_group, //
     subnetmap_add, //
     subnetmap_remove, //
-    subnetmap_update;
+    subnetmap_update, //
+    port_not_found_for_floating, //
+    garp_sent, //
+    garp_sent_ipv6, //
+    garp_sent_failed;
 
     private OccurenceCounter counter;
 
index 242910ea22a67e166c835107005cdd4ebc315c35..6b95c2b797a485b75ac892f2748a159f42e63a20 100644 (file)
@@ -1087,17 +1087,17 @@ public class NatUtil {
     }
 
     public static Port getNeutronPortForFloatingIp(DataBroker broker,
-            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP) {
-      return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_FLOATING_IP);
+        IpAddress targetIP) {
+       return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_FLOATING_IP);
     }
 
     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker,
-            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP) {
-      return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
+        IpAddress targetIP) {
+       return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
     }
 
     public static Port getNeutronPortForIp(DataBroker broker,
-            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP, String deviceType) {
+        IpAddress targetIP, String deviceType) {
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
         portsIdentifier = InstanceIdentifier
                 .create(Neutron.class)
index 002f501b7985e9fdb9016790c1ddff92a2880d29..4d69038dfe76a891108b6b760dbc5ebc7cda63c1 100644 (file)
@@ -29,9 +29,18 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
@@ -43,8 +52,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.G
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -57,6 +66,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
     private final FibRpcService fibService;
     private final FloatingIPListener floatingIPListener;
     private final IFibManager fibManager;
+    private final OdlArputilService arpUtilService;
     static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
     static final String FLOWID_PREFIX = "NAT.";
 
@@ -65,7 +75,8 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                                 final IBgpManager bgpManager,
                                 final FibRpcService fibService,
                                 final FloatingIPListener floatingIPListener,
-                                final IFibManager fibManager) {
+                                final IFibManager fibManager,
+                                final OdlArputilService arputilService) {
         this.dataBroker = dataBroker;
         this.mdsalManager = mdsalManager;
         this.vpnService = vpnService;
@@ -73,22 +84,26 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         this.fibService = fibService;
         this.floatingIPListener = floatingIPListener;
         this.fibManager = fibManager;
+        this.arpUtilService = arputilService;
     }
 
     @Override
     public void onAddFloatingIp(final BigInteger dpnId, final String routerId,
-                                Uuid networkId, final String interfaceName, final String externalIp, final String internalIp) {
+                                Uuid networkId, final String interfaceName, final String externalIp,
+                                final String internalIp) {
         final String vpnName = getAssociatedVPN(networkId, routerId);
-        if(vpnName == null) {
+        if (vpnName == null) {
             LOG.info("No VPN associated with ext nw {} to handle add floating ip configuration {} in router {}",
                     networkId, externalIp, routerId);
             return;
         }
 
-        GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
+        GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName)
+                .setIpPrefix(externalIp).build();
         Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
 
-        ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
+        ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture),
+                new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
 
             @Override
             public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
@@ -144,13 +159,26 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                 }
             }
         });
+
+        // Handle GARP transmission
+        final IpAddress extrenalAddress = IpAddressBuilder.getDefaultInstance(externalIp);
+        final IpAddress internalAddress = IpAddressBuilder.getDefaultInstance(internalIp);
+        Port neutronPortForIp = NatUtil.getNeutronPortForIp(dataBroker,internalAddress,
+                NeutronConstants.DEVICE_OWNER_NEUTRON_PORT);
+        if (neutronPortForIp == null) {
+            LOG.warn("No neutron port was found for external ip {} in router {}", internalIp, routerId);
+            NatServiceCounters.port_not_found_for_floating.inc();
+            return;
+        }
+        sendGarpOnInterface(neutronPortForIp.getUuid().getValue(), extrenalAddress, routerId);
+
     }
 
     @Override
     public void onRemoveFloatingIp(final BigInteger dpnId, String routerId, Uuid networkId, final String externalIp,
                                    String internalIp, final long label) {
         final String vpnName = getAssociatedVPN(networkId, routerId);
-        if(vpnName == null) {
+        if (vpnName == null) {
             LOG.info("No VPN associated with ext nw {} to handle remove floating ip configuration {} in router {}",
                     networkId, externalIp, routerId);
             return;
@@ -331,4 +359,32 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
         return vpnName != null ? vpnName : routerId;
     }
+
+    private void sendGarpOnInterface(String interfaceName, final IpAddress floatingIpAddress, final String routerId) {
+        if (floatingIpAddress.getIpv4Address() == null) {
+            LOG.warn("Faild to send GARP for IP. recieved IPv6.");
+            NatServiceCounters.garp_sent_ipv6.inc();
+            return;
+        }
+
+        try {
+            Port floatingPort = NatUtil.getNeutronPortForFloatingIp(dataBroker, floatingIpAddress);
+            PhysAddress floatingPortMac = new PhysAddress(floatingPort.getMacAddress().getValue());
+            List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
+            interfaceAddresses.add(new InterfaceAddressBuilder()
+                    .setInterface(interfaceName)
+                    .setIpAddress(floatingIpAddress)
+                    .setMacaddress(floatingPortMac).build());
+
+            SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(floatingIpAddress)
+                    .setInterfaceAddress(interfaceAddresses).build();
+            arpUtilService.sendArpRequest(sendArpRequestInput);
+            NatServiceCounters.garp_sent.inc();
+        } catch (Exception e) {
+            LOG.error("Failed to send GARP request for floating ip {} from interface {}",
+                    floatingIpAddress.getIpv4Address().getValue(), interfaceName, e);
+            NatServiceCounters.garp_sent_failed.inc();
+        }
+    }
+
 }
index c84d618efe77988512d9c418cd25c07f7e024108..e1c1e43f6ef8aa55030a7a3f815a352dd74c760a 100644 (file)
@@ -33,6 +33,8 @@
                    interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService" />
   <odl:rpc-service id="fibRpcService"
                    interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService" />
+  <odl:rpc-service id="odlArputilService"
+                   interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService" />
 
   <bean id="subnetmapListener"
         class="org.opendaylight.netvirt.natservice.internal.SubnetmapListener"
@@ -95,6 +97,7 @@
     <argument ref="fibRpcService" />
     <argument ref="floatingIPListener" />
     <argument ref="fibManager" />
+    <argument ref="odlArputilService" />
   </bean>
   <service ref="vpnFloatingIpHandler"
            interface="org.opendaylight.netvirt.natservice.internal.FloatingIPHandler" />
index ef3c00ba4c5721c7607a59db3fdbee2c98b46159..932368bd0ccd6b7d24626a679d2f3d5683ff53a0 100644 (file)
@@ -12,6 +12,7 @@ public class NeutronConstants {
     public static final String DEVICE_OWNER_GATEWAY_INF = "network:router_gateway";
     public static final String DEVICE_OWNER_ROUTER_INF = "network:router_interface";
     public static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
+    public static final String DEVICE_OWNER_NEUTRON_PORT = "compute:nova";
     public static final String VNIC_TYPE_NORMAL = "normal";
     public static final String VIF_TYPE_VHOSTUSER = "vhostuser";
     public static final String VIF_TYPE_UNBOUND = "unbound";
diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/FloatingIpGarpHandler.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/FloatingIpGarpHandler.java
deleted file mode 100644 (file)
index ce3fcbc..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netvirt.vpnmanager;
-
-import com.google.common.net.InetAddresses;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.mdsalutil.ActionInfo;
-import org.opendaylight.genius.mdsalutil.ActionType;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
-import org.opendaylight.netvirt.elanmanager.api.IElanService;
-import org.opendaylight.netvirt.vpnmanager.utilities.VpnManagerCounters;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FloatingIpGarpHandler extends AsyncDataTreeChangeListenerBase<RouterPorts, FloatingIpGarpHandler>
-        implements AutoCloseable {
-    private static final Logger LOG = LoggerFactory.getLogger(FloatingIpGarpHandler.class);
-    private final DataBroker dataBroker;
-    private final PacketProcessingService packetService;
-    private final IElanService elanService;
-    private final OdlInterfaceRpcService intfRpc;
-
-    public FloatingIpGarpHandler(final DataBroker dataBroker, final PacketProcessingService packetService,
-                                 final IElanService elanService, final OdlInterfaceRpcService interfaceManager) {
-        super(RouterPorts.class, FloatingIpGarpHandler.class);
-        this.dataBroker = dataBroker;
-        this.packetService = packetService;
-        this.elanService = elanService;
-        this.intfRpc = interfaceManager;
-    }
-
-    public void start() {
-        LOG.info("{} start", getClass().getSimpleName());
-        registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
-    }
-
-    @Override
-    protected InstanceIdentifier<RouterPorts> getWildCardPath() {
-        return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class);
-    }
-
-    @Override
-    protected void remove(InstanceIdentifier<RouterPorts> key, RouterPorts dataObjectModification) {
-    }
-
-    @Override
-    protected void update(InstanceIdentifier<RouterPorts> key, RouterPorts dataObjectModificationBefore,
-            RouterPorts dataObjectModificationAfter) {
-        VpnManagerCounters.garp_update_notification.inc();
-        sendGarpForFloatingIps(dataObjectModificationAfter);
-    }
-
-    private void sendGarpForFloatingIps(RouterPorts dataObjectModificationAfter) {
-        for (Ports port : dataObjectModificationAfter.getPorts()) {
-            for (IpMapping ipMapping : port.getIpMapping()) {
-                IpAddress ip = IpAddressBuilder.getDefaultInstance(ipMapping.getExternalIp());
-                sendGarpForIp(dataObjectModificationAfter, ip);
-            }
-        }
-    }
-
-    private void sendGarpForIp(RouterPorts dataObjectModificationAfter, IpAddress ip) {
-        if (ip.getIpv4Address() == null) {
-            LOG.warn("Faild to send GARP for IP. recieved IPv6.");
-            VpnManagerCounters.garp_sent_ipv6.inc();
-            return;
-        }
-        Port floatingIpPort = VpnUtil.getNeutronPortForFloatingIp(dataBroker, ip);
-        MacAddress floatingIpMac = floatingIpPort.getMacAddress();
-        String extNet = VpnUtil.getAssociatedExternalNetwork(dataBroker, dataObjectModificationAfter.getRouterId());
-        Collection<String> interfaces = elanService.getExternalElanInterfaces(extNet);
-        for (String externalInterface:interfaces) {
-            sendGarpOnInterface(ip, floatingIpMac, externalInterface);
-        }
-    }
-
-    private void sendGarpOnInterface(IpAddress ip, MacAddress floatingIpMac, String externalInterface) {
-        try {
-            GetPortFromInterfaceInput getPortFromInterfaceInput = new GetPortFromInterfaceInputBuilder()
-                    .setIntfName(externalInterface).build();
-            Future<RpcResult<GetPortFromInterfaceOutput>> interfacePort = intfRpc
-                    .getPortFromInterface(getPortFromInterfaceInput);
-            if (interfacePort == null || !interfacePort.get().isSuccessful()) {
-                VpnManagerCounters.garp_interface_rpc_failed.inc();
-                return;
-            }
-            BigInteger dpId = interfacePort.get().getResult().getDpid();
-            String portId = interfacePort.get().getResult().getPortno().toString();
-            NodeConnectorRef ingress = MDSALUtil.getNodeConnRef(dpId, portId);
-            byte[] ipBytes = InetAddresses.forString(ip.getIpv4Address().getValue()).getAddress();
-            List<ActionInfo> actionList = new ArrayList<ActionInfo>();
-            actionList.add(new ActionInfo(ActionType.output, new String[]{portId}));
-
-            byte[] floatingMac = ArpUtils.getMacInBytes(floatingIpMac.getValue());
-            TransmitPacketInput arpRequestInput = ArpUtils.createArpRequestInput(dpId, null,
-                    floatingMac, VpnConstants.MAC_Broadcast, ipBytes, ipBytes, ingress, actionList);
-            packetService.transmitPacket(arpRequestInput);
-            VpnManagerCounters.garp_sent.inc();
-        } catch (InterruptedException|ExecutionException e) {
-            LOG.warn("Faild to send GARP. rpc call getPortFromInterface did not return with a value.");
-            VpnManagerCounters.garp_sent_failed.inc();
-        }
-    }
-
-    @Override
-    protected void add(InstanceIdentifier<RouterPorts> key, RouterPorts dataObjectModification) {
-        sendGarpForFloatingIps(dataObjectModification);
-    }
-
-    @Override
-    protected FloatingIpGarpHandler getDataTreeChangeListener() {
-        return this;
-    }
-}