DHCP Handling for TOR VM
[vpnservice.git] / dhcpservice / dhcpservice-impl / src / main / java / org / opendaylight / vpnservice / dhcpservice / DhcpManager.java
index 458ad968210da082b0d554468a3e3b7878dd983e..af36ca955d24949290f1b1a0b990fe13987fe5d2 100644 (file)
@@ -7,31 +7,22 @@
  */
 package org.opendaylight.vpnservice.dhcpservice;
 
-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.HashMap;
 import java.util.List;
-import com.google.common.util.concurrent.FutureCallback;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
-import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
-import org.opendaylight.vpnservice.mdsalutil.ActionType;
 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
-import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
 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.subnets.attributes.subnets.Subnet;
 import org.slf4j.Logger;
@@ -46,17 +37,10 @@ public class DhcpManager implements AutoCloseable {
     private int dhcpOptLeaseTime = 0;
     private int dhcpOptRenewalTime = 0;
     private int dhcpOptRebindingTime = 0;
-    private String dhcpOptDefDomainName = "openstacklocal";
-
-    private static final FutureCallback<Void> DEFAULT_CALLBACK =
-        new FutureCallback<Void>() {
-            public void onSuccess(Void result) {
-                logger.debug("Success in Datastore write operation");
-            }
-            public void onFailure(Throwable error) {
-                logger.error("Error in Datastore write operation", error);
-            };
-        };
+    private String dhcpOptDefDomainName;
+    private INeutronVpnManager neutronVpnService;
+    // cache used to maintain DpnId and physical address for each interface.
+    private static HashMap<String, ImmutablePair<BigInteger, String>> interfaceToDpnIdMacAddress = new HashMap<String, ImmutablePair<BigInteger, String>>();
 
     /**
     * @param db - dataBroker reference
@@ -70,48 +54,16 @@ public class DhcpManager implements AutoCloseable {
         this.mdsalUtil = mdsalManager;
     }
 
+    public void setNeutronVpnService(INeutronVpnManager neutronVpnService) {
+        logger.debug("Setting NeutronVpn dependency");
+        this.neutronVpnService = neutronVpnService;
+    }
+
     @Override
     public void close() throws Exception {
         logger.info("DHCP Manager Closed");
     }
 
-    public void installDhcpEntries(BigInteger dpnId) {
-        logger.debug("Installing Default DHCP Flow tp DPN: {}", dpnId);
-        setupDefaultDhcpFlow(dpnId, DHCPMConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
-    }
-
-    private void setupDefaultDhcpFlow(BigInteger dpId,  short tableId, int addOrRemove) {
-
-        List<MatchInfo> matches = new ArrayList<MatchInfo>();
-
-        matches.add(new MatchInfo(MatchFieldType.eth_type,
-                new long[] { NwConstants.ETHTYPE_IPV4 }));
-        matches.add(new MatchInfo(MatchFieldType.ip_proto,
-                new long[] { IPProtocols.UDP.intValue() }));
-        matches.add(new MatchInfo(MatchFieldType.udp_src,
-                new long[] { DHCPMConstants.dhcpClientPort }));
-        matches.add(new MatchInfo(MatchFieldType.udp_dst,
-                new long[] { DHCPMConstants.dhcpServerPort }));
-
-        List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
-        List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
-
-        // Punt to controller
-        actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
-                new String[] {}));
-        instructions.add(new InstructionInfo(InstructionType.write_actions,
-                actionsInfos));
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
-                getDefaultDhcpFlowRef(dpId, tableId),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
-                DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
-        mdsalUtil.installFlow(flowEntity);
-    }
-
-    private String getDefaultDhcpFlowRef(BigInteger dpId, long tableId) {
-        return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX).append(dpId)
-                        .append(NwConstants.FLOWID_SEPARATOR).append(tableId).toString();
-    }
-
     public int setLeaseDuration(int leaseDuration) {
         configureLeaseDuration(leaseDuration);
         return getDhcpLeaseTime();
@@ -150,7 +102,6 @@ public class DhcpManager implements AutoCloseable {
     }
 
     public Subnet getNeutronSubnet(Port nPort) {
-        /* TODO: Once NeutronVpn is merged, use it to get Subnet
         if (nPort != null) {
             try {
                 return neutronVpnService.getNeutronSubnet(nPort.getFixedIps().get(0).getSubnetId());
@@ -158,32 +109,60 @@ public class DhcpManager implements AutoCloseable {
                 logger.warn("Failed to get Neutron Subnet from Port: {}", e);
             }
         }
-        */
-        if (nPort.getFixedIps() != null && !nPort.getFixedIps().isEmpty()) {
-            InstanceIdentifier<Subnet> sIid =
-                            InstanceIdentifier.create(Neutron.class).child(Subnets.class)
-                                .child(Subnet.class, new SubnetKey(nPort.getFixedIps().get(0).getSubnetId()));
-            Optional<Subnet> optSubnet = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, sIid, broker);
-            if (optSubnet.isPresent()) {
-                return optSubnet.get();
-            }
-        }
         return null;
     }
 
     public Port getNeutronPort(String name) {
-        // TODO Once NeutronVpn is merged, use it to get port
-        //return neutronVpnService.getNeutronPort(name);
-        InstanceIdentifier<Ports> pIid = InstanceIdentifier.create(Neutron.class).child(Ports.class);
-        Optional<Ports> optPorts = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, pIid, broker);
-        if(optPorts.isPresent()) {
-            for(Port port: optPorts.get().getPort()) {
-                if(port.getUuid().getValue().startsWith(name.substring(3))) {
-                    return port;
-                }
-            }
+        try {
+            return neutronVpnService.getNeutronPort(name);
+        } catch (IllegalArgumentException e) {
+            return null;
+        } catch (Exception ex) {
+            logger.trace("In getNeutronPort interface name passed {} exception message {}.", name, ex.getMessage());
+            return null;
         }
-        return null;
     }
 
+    public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
+        DhcpServiceUtils.setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW, mdsalUtil);
+    }
+
+    public void unInstallDhcpEntries(BigInteger dpId, String vmMacAddress) {
+        DhcpServiceUtils.setupDhcpFlowEntry(dpId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW, mdsalUtil);
+    }
+
+    public void setupTableMissForDhcpTable(BigInteger dpId) {
+        List<MatchInfo> matches = new ArrayList<MatchInfo>();
+        List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+        instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
+
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE, "DHCPTableMissFlow",
+                0, "DHCP Table Miss Flow", 0, 0,
+                DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+        mdsalUtil.installFlow(flowEntity);
+        setupTableMissForHandlingExternalTunnel(dpId);
+    }
+
+    private void setupTableMissForHandlingExternalTunnel(BigInteger dpId) {
+        List<MatchInfo> matches = new ArrayList<MatchInfo>();
+        List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+        instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.EXTERNAL_TUNNEL_TABLE }));
+
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, "DHCPTableMissFlowForExternalTunnel",
+                0, "DHCP Table Miss Flow For External Tunnel", 0, 0,
+                DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+        mdsalUtil.installFlow(flowEntity);
+    }
+
+    public void updateInterfaceCache(String interfaceName, ImmutablePair<BigInteger, String> pair) {
+        interfaceToDpnIdMacAddress.put(interfaceName, pair);
+    }
+
+    public ImmutablePair<BigInteger, String> getInterfaceCache(String interfaceName) {
+        return interfaceToDpnIdMacAddress.get(interfaceName);
+    }
+
+    public void removeInterfaceCache(String interfaceName) {
+        interfaceToDpnIdMacAddress.remove(interfaceName);
+    }
 }