Fixed NAT in OFOverlay based on EIG
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / NeutronPortAware.java
index 4f391e3be5cd9d1999308f62054d99c952d9ebb5..ee22c5729e4d4a8b88b0997a069a79589fd3f377 100644 (file)
@@ -11,57 +11,78 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.Router;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.group.NeutronSecurityGroupAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.neutron.spi.INeutronPortAware;
 import org.opendaylight.neutron.spi.NeutronPort;
 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
 import org.opendaylight.neutron.spi.NeutronSecurityRule;
 import org.opendaylight.neutron.spi.Neutron_IPs;
+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.inet.types.rev100924.IpPrefix;
 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.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.floating.ip.ports.EndpointByFloatingIpPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router._interface.ports.EndpointByRouterInterfacePort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.router.gateway.ports.EndpointByRouterGatewayPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.floating.ip.ports.by.endpoints.FloatingIpPortByEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router._interface.ports.by.endpoints.RouterInterfacePortByEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.router.gateway.ports.by.endpoints.RouterGatewayPortByEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -77,14 +98,19 @@ public class NeutronPortAware implements INeutronPortAware {
     public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class);
     private static final String DEVICE_OWNER_DHCP = "network:dhcp";
     private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface";
-    private static final int DHCP_CLIENT_PORT = 68;
-    private static final int DHCP_SERVER_PORT = 67;
+    private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway";
+    private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
     private final DataBroker dataProvider;
     private final EndpointService epService;
+    private final NeutronSecurityRuleAware secRuleAware;
+    private final NeutronSecurityGroupAware secGrpAware;
+    private final static Map<String, UniqueId> floatingIpPortByDeviceId = new HashMap<>();
 
-    public NeutronPortAware(DataBroker dataProvider, EndpointService epService) {
+    public NeutronPortAware(DataBroker dataProvider, EndpointService epService, NeutronSecurityRuleAware secRuleAware, NeutronSecurityGroupAware secGrpAware) {
         this.dataProvider = checkNotNull(dataProvider);
         this.epService = checkNotNull(epService);
+        this.secRuleAware = checkNotNull(secRuleAware);
+        this.secGrpAware = secGrpAware;
     }
 
     /**
@@ -113,24 +139,28 @@ public class NeutronPortAware implements INeutronPortAware {
                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
             return;
         }
+        if (isRouterGatewayPort(port)) {
+            LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
+                    NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
+            return;
+        }
+        if (isFloatingIpPort(port)) {
+            LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
+            floatingIpPortByDeviceId.put(port.getDeviceID(), new UniqueId(port.getID()));
+            return;
+        }
         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
         if (isDhcpPort(port)) {
-            LOG.trace("Port is DHCP port.");
-            List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, null, rwTx);
-            if (dhcpSecRules == null) {
+            LOG.trace("Port is DHCP port. - {}", port.getID());
+            Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
+            if (firstIp == null) {
+                LOG.warn("Illegal state - DHCP port does not have an IP address.");
                 rwTx.cancel();
                 return;
             }
-
-            for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) {
-                boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx);
-                if (!isDhcpSecRuleAdded) {
-                    rwTx.cancel();
-                    return;
-                }
-            }
         } else {
+            // this is here b/c stable/kilo sends sec-groups only with port
             List<NeutronSecurityGroup> secGroups = port.getSecurityGroups();
             if (secGroups != null) {
                 for (NeutronSecurityGroup secGroup : secGroups) {
@@ -138,35 +168,22 @@ public class NeutronPortAware implements INeutronPortAware {
                     Optional<EndpointGroup> potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
                             IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
                     if (!potentialEpg.isPresent()) {
-                        boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx);
+                        boolean isSecGroupCreated = secGrpAware.addNeutronSecurityGroup(secGroup, rwTx);
                         if (!isSecGroupCreated) {
                             rwTx.cancel();
                             return;
                         }
-                        if (containsSecRuleWithRemoteSecGroup(secGroup)) {
-                            List<NeutronSecurityRule> dhcpSecRules = createDhcpSecRules(port, epgId, rwTx);
-                            if (dhcpSecRules == null) {
-                                rwTx.cancel();
-                                return;
-                            }
-                            List<NeutronSecurityRule> routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx);
-                            if (routerSecRules == null) {
-                                rwTx.cancel();
-                                return;
-                            }
-                        }
                     } else {
                         List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
                         if (secRules != null) {
                             for (NeutronSecurityRule secRule : secRules) {
-                                NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx);
+                                secRuleAware.addNeutronSecurityRule(secRule, rwTx);
                             }
                         }
                     }
                 }
             }
         }
-
         boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService);
         if (!isNeutronPortCreated) {
             rwTx.cancel();
@@ -185,26 +202,108 @@ public class NeutronPortAware implements INeutronPortAware {
             return false;
         }
         EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
-        UniqueId portId = new UniqueId(port.getID());
-        EndpointByPort endpointByPort = createEndpointByPort(epKey, portId);
-        rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByPortIid(portId), endpointByPort);
-        PortByEndpoint portByEndpoint = createPortByEndpoint(portId, epKey);
-        rwTx.put(LogicalDatastoreType.OPERATIONAL,
-                IidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint);
+        addNeutronGbpMapping(port, epKey, rwTx);
 
         try {
             RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx);
-
             RpcResult<Void> rpcResult = epService.registerEndpoint(registerEpRpcInput).get();
             if (!rpcResult.isSuccessful()) {
                 LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput);
                 return false;
             }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("addNeutronPort failed. {}", port, e);
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean addL3EndpointForExternalGateway(TenantId tenantId, L3ContextId l3ContextId,
+            IpAddress ipAddress, NetworkDomainId networkContainment, ReadWriteTransaction rwTx) {
+
+        EndpointL3Key epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
+        addNeutronExtGwGbpMapping(epL3Key, rwTx);
+        List<EndpointGroupId> epgIds = new ArrayList<>();
+        // each EP has to be in EPG ANY, except dhcp and router
+        epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
+        epgIds.add(Router.EPG_ID);
+        EndpointL3 epL3 = createL3Endpoint(tenantId, epL3Key, epgIds, networkContainment);
+        InstanceIdentifier<EndpointL3> iid_l3 = IidFactory.l3EndpointIid(l3ContextId, ipAddress);
+        rwTx.put(LogicalDatastoreType.OPERATIONAL, iid_l3, epL3, true);
+        return true;
+    }
+
+    private static void addNeutronExtGwGbpMapping(EndpointL3Key epL3Key, ReadWriteTransaction rwTx) {
+            ExternalGatewayAsL3Endpoint externalGatewayL3Endpoint = MappingFactory.createExternalGatewayByL3Endpoint(epL3Key);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.externalGatewayAsL3Endpoint(epL3Key.getL3Context(), epL3Key.getIpAddress()),
+                    externalGatewayL3Endpoint, true);
+    }
+
+    private static void addNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
+        UniqueId portId = new UniqueId(port.getID());
+        if (isRouterInterfacePort(port)) {
+            LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+            EndpointByRouterInterfacePort endpointByPort = MappingFactory.createEndpointByRouterInterfacePort(epKey,
+                    portId);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId),
+                    endpointByPort, true);
+            RouterInterfacePortByEndpoint portByEndpoint = MappingFactory.createRouterInterfacePortByEndpoint(portId,
+                    epKey);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
+                    portByEndpoint, true);
+        } else if (isRouterGatewayPort(port)) {
+            LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+            EndpointByRouterGatewayPort endpointByPort = MappingFactory.createEndpointByRouterGatewayPort(epKey, portId);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId),
+                    endpointByPort, true);
+            RouterGatewayPortByEndpoint portByEndpoint = MappingFactory.createRouterGatewayPortByEndpoint(portId, epKey);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
+                    portByEndpoint, true);
+        } else if (isFloatingIpPort(port)) {
+            LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+            EndpointByFloatingIpPort endpointByPort = MappingFactory.createEndpointByFloatingIpPort(epKey, portId);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByFloatingIpPortIid(portId),
+                    endpointByPort, true);
+            FloatingIpPortByEndpoint portByEndpoint = MappingFactory.createFloatingIpPortByEndpoint(portId, epKey);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()),
+                    portByEndpoint, true);
+        } else {
+            LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
+                    port.getDeviceOwner(), epKey);
+            EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true);
+            PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, true);
+        }
+    }
+
+    public static boolean addL3PrefixEndpoint(L3ContextId l3ContextId, IpPrefix ipPrefix, IpAddress ipAddress, TenantId tenantId,
+            EndpointService epService) {
+        EndpointL3PrefixKey epL3PrefixKey = new EndpointL3PrefixKey( ipPrefix, l3ContextId);
+        EndpointL3Key epL3Key = null;
+        List<EndpointL3Key> l3Gateways = new ArrayList<>();
+        if (ipAddress != null) {
+            epL3Key = new EndpointL3Key(ipAddress, l3ContextId);
+            l3Gateways.add(epL3Key);
+        }
+        try {
+            RegisterL3PrefixEndpointInput registerL3PrefixEpRpcInput = createRegisterL3PrefixEndpointInput(epL3PrefixKey, l3Gateways,tenantId);
+
+            RpcResult<Void> rpcResult = epService.registerL3PrefixEndpoint(registerL3PrefixEpRpcInput).get();
+            if (!rpcResult.isSuccessful()) {
+                LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerL3PrefixEpRpcInput);
+                return false;
+            }
         } catch (InterruptedException | ExecutionException e) {
             LOG.error("addPort - RPC invocation failed.", e);
             return false;
         }
         return true;
+
     }
 
     private static boolean validateForwardingCtx(ForwardingCtx fwCtx) {
@@ -223,69 +322,6 @@ public class NeutronPortAware implements INeutronPortAware {
         return true;
     }
 
-    private static EndpointByPort createEndpointByPort(EndpointKey epKey, UniqueId portId) {
-        return new EndpointByPortBuilder().setPortId(portId)
-            .setL2Context(epKey.getL2Context())
-            .setMacAddress(epKey.getMacAddress())
-            .build();
-    }
-
-    private static PortByEndpoint createPortByEndpoint(UniqueId portId, EndpointKey epKey) {
-        return new PortByEndpointBuilder().setPortId(portId)
-            .setL2Context(epKey.getL2Context())
-            .setMacAddress(epKey.getMacAddress())
-            .build();
-    }
-
-    private List<NeutronSecurityRule> createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) {
-        TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
-        Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs());
-        if (firstIp == null) {
-            LOG.warn("Illegal state - DHCP port does not have an IP address.");
-            return null;
-        }
-        SubnetId dhcpSubnetId = new SubnetId(firstIp.getSubnetUUID());
-        Optional<Subnet> potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.subnetIid(tenantId, dhcpSubnetId), rTx);
-        if (!potentialSubnet.isPresent()) {
-            LOG.warn("Illegal state - Subnet {} where is DHCP port does not exist.", dhcpSubnetId.getValue());
-            return null;
-        }
-        IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix();
-        NeutronSecurityRule dhcpRuleEgress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, true);
-        NeutronSecurityRule dhcpRuleIngress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, false);
-        return ImmutableList.of(dhcpRuleEgress, dhcpRuleIngress);
-    }
-
-    private NeutronSecurityRule createDhcpSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId,
-            boolean isEgress) {
-        NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
-        dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue());
-        dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
-        dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
-        if (consumerEpgId != null) {
-            dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue());
-        }
-        if (isEgress) {
-            dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
-            dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
-            dhcpSecRule.setSecurityRulePortMin(DHCP_CLIENT_PORT);
-            dhcpSecRule.setSecurityRulePortMax(DHCP_CLIENT_PORT);
-        } else {
-            dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
-            dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
-            dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT);
-            dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT);
-        }
-        dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP);
-        if (ipSubnet.getIpv4Prefix() != null) {
-            dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
-        } else {
-            dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
-        }
-        return dhcpSecRule;
-    }
-
     /**
      * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort,
      *      org.opendaylight.neutron.spi.NeutronPort)
@@ -316,6 +352,19 @@ public class NeutronPortAware implements INeutronPortAware {
                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
             return;
         }
+        if (isRouterGatewayPort(port)) {
+            LOG.trace("Port is router gateway - {}", port.getID());
+            return;
+        }
+        if (isFloatingIpPort(port)) {
+            LOG.trace("Port is floating ip - {}", port.getID());
+            return;
+        }
+        if (Strings.isNullOrEmpty(port.getTenantID())) {
+            LOG.trace("REMOVE ME: Tenant is null - {}", port.getID());
+            return;
+        }
+
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
         MacAddress macAddress = new MacAddress(port.getMacAddress());
@@ -425,41 +474,115 @@ public class NeutronPortAware implements INeutronPortAware {
                     NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
             return;
         }
-        ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+        if (isRouterGatewayPort(port)) {
+            LOG.trace("Port is router gateway - {} does nothing. {} handles router iface.",
+                    NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName());
+            return;
+        }
+        if (isFloatingIpPort(port)) {
+            LOG.trace("Port is floating ip - {} device id - {}", port.getID(), port.getDeviceID());
+            floatingIpPortByDeviceId.remove(port.getDeviceID());
+        }
+        ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
         TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID()));
         L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID());
-        ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx);
+        ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx);
         boolean isFwCtxValid = validateForwardingCtx(fwCtx);
         if (!isFwCtxValid) {
-            rTx.close();
+            rwTx.cancel();
             return;
         }
 
         UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx);
+        boolean isEndpointUnregistered = false;
         try {
-            RpcResult<Void> rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get();
-            if (!rpcResult.isSuccessful()) {
-                LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
-            }
+            isEndpointUnregistered = epService.unregisterEndpoint(unregisterEpRpcInput).get().isSuccessful();
         } catch (InterruptedException | ExecutionException e) {
-            LOG.error("addPort - RPC invocation failed.", e);
-        } finally {
-            rTx.close();
+            LOG.error("unregisterEndpoint - RPC invocation failed.", e);
+        }
+        if (isEndpointUnregistered) {
+            EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress()));
+            deleteNeutronGbpMapping(port, epKey, rwTx);
+            DataStoreHelper.submitToDs(rwTx);
+        } else {
+            LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput);
+            rwTx.cancel();
         }
     }
 
+    private static void deleteNeutronGbpMapping(NeutronPort port, EndpointKey epKey, ReadWriteTransaction rwTx) {
+        UniqueId portId = new UniqueId(port.getID());
+        if (isRouterInterfacePort(port)) {
+            LOG.trace("Adding RouterInterfacePort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.endpointByRouterInterfacePortIid(portId), rwTx);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.routerInterfacePortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+        } else if (isRouterGatewayPort(port)) {
+            LOG.trace("Adding RouterGatewayPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.endpointByRouterGatewayPortIid(portId), rwTx);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.routerGatewayPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+        } else if (isFloatingIpPort(port)) {
+            LOG.trace("Adding FloatingIpPort-Endpoint mapping for port {} and endpoint {}", port.getID(), epKey);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.endpointByFloatingIpPortIid(portId), rwTx);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.floatingIpPortByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+        } else {
+            LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getID(),
+                    port.getDeviceOwner(), epKey);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), rwTx);
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx);
+        }
+    }
+
+    private static RegisterL3PrefixEndpointInput createRegisterL3PrefixEndpointInput(EndpointL3PrefixKey key, List<EndpointL3Key> endpointL3Keys, TenantId tenantId) {
+        List<EndpointGroupId> epgIds = new ArrayList<>();
+        List<EndpointL3Gateways> l3Gateways = new ArrayList<EndpointL3Gateways>();
+        for (EndpointL3Key epL3Key : endpointL3Keys) {
+            EndpointL3Gateways l3Gateway = new EndpointL3GatewaysBuilder().setIpAddress(epL3Key.getIpAddress())
+                .setL3Context(epL3Key.getL3Context())
+                .build();
+            l3Gateways.add(l3Gateway);
+        }
+        RegisterL3PrefixEndpointInputBuilder inputBuilder = new RegisterL3PrefixEndpointInputBuilder()
+                                                .setL3Context(key.getL3Context())
+                                                .setIpPrefix(key.getIpPrefix())
+                                                .setEndpointGroups(epgIds)
+                                                .setTenant(tenantId)
+                                                .setEndpointL3Gateways(l3Gateways)
+                                                .setTimestamp(System.currentTimeMillis());
+        return inputBuilder.build();
+    }
+
+    private static EndpointL3 createL3Endpoint(TenantId tenantId, EndpointL3Key epL3Key,
+            List<EndpointGroupId> epgIds, NetworkDomainId containment) {
+
+        EndpointL3Builder epL3Builder = new EndpointL3Builder()
+        .setTenant(tenantId)
+        .setNetworkContainment(containment)
+        .setIpAddress(epL3Key.getIpAddress())
+        .setL3Context(epL3Key.getL3Context())
+        .setEndpointGroups(epgIds)
+        .setTimestamp(System.currentTimeMillis());
+
+        return epL3Builder.build();
+    }
+
     private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) {
         List<EndpointGroupId> epgIds = new ArrayList<>();
-        // each EP has to be in EPG ANY, except dhcp and router
         if (isDhcpPort(port)) {
-            epgIds.add(MappingUtils.EPG_DHCP_ID);
-        } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) {
-            epgIds.add(MappingUtils.EPG_ANY_ID);
+            epgIds.add(NetworkService.EPG_ID);
         }
 
         List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
         if ((securityGroups == null || securityGroups.isEmpty())) {
-            if (!isDhcpPort(port)) {
+            if (isFloatingIpPort(port)) {
+                epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
+            } else if (!isDhcpPort(port)) {
                 LOG.warn(
                         "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
                         port.getPortUUID());
@@ -468,6 +591,7 @@ public class NeutronPortAware implements INeutronPortAware {
             for (NeutronSecurityGroup secGrp : securityGroups) {
                 epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID()));
             }
+            epgIds.add(NetworkClient.EPG_ID);
         }
         RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context(
                 fwCtx.getL2BridgeDomain().getId())
@@ -475,7 +599,9 @@ public class NeutronPortAware implements INeutronPortAware {
             .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID())))
             .setEndpointGroups(epgIds)
             .addAugmentation(OfOverlayContextInput.class,
-                    new OfOverlayContextInputBuilder().setPortName(createTapPortName(port)).build())
+                    new OfOverlayContextInputBuilder()
+                        .setPortName(createTapPortName(port))
+                    .build())
             .setTimestamp(System.currentTimeMillis());
         List<Neutron_IPs> fixedIPs = port.getFixedIPs();
         // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer
@@ -494,32 +620,6 @@ public class NeutronPortAware implements INeutronPortAware {
         return inputBuilder.build();
     }
 
-    private static boolean containsSecRuleWithRemoteSecGroup(List<NeutronSecurityGroup> secGroups) {
-        if (secGroups == null) {
-            return false;
-        }
-        for (NeutronSecurityGroup secGroup : secGroups) {
-            boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup);
-            if (containsSecRuleWithRemoteSecGroup) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) {
-        List<NeutronSecurityRule> secRules = secGroup.getSecurityRules();
-        if (secRules == null) {
-            return false;
-        }
-        for (NeutronSecurityRule secRule : secRules) {
-            if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     private static Name createTapPortName(NeutronPort port) {
         return new Name("tap" + port.getID().substring(0, 11));
     }
@@ -532,6 +632,14 @@ public class NeutronPortAware implements INeutronPortAware {
         return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner());
     }
 
+    private static boolean isRouterGatewayPort(NeutronPort port) {
+        return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner());
+    }
+
+    private static boolean isFloatingIpPort(NeutronPort port) {
+        return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner());
+    }
+
     private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) {
         UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder();
         L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build();
@@ -574,4 +682,8 @@ public class NeutronPortAware implements INeutronPortAware {
         return l3s;
     }
 
+    public static UniqueId getFloatingIpPortIdByDeviceId(String deviceId) {
+        return floatingIpPortByDeviceId.get(deviceId);
+    }
+
 }