diff --git a/akanda/neutron/plugins/floatingip.py b/akanda/neutron/plugins/floatingip.py
new file mode 100644
index 0000000..31d5e39
--- /dev/null
+++ b/akanda/neutron/plugins/floatingip.py
@@ -0,0 +1,63 @@
+from neutron.common import exceptions as q_exc
+from neutron.openstack.common import uuidutils
+from neutron.api.v2 import attributes
+from neutron.db.l3_db import DEVICE_OWNER_FLOATINGIP, FloatingIP
+
+
+class ExplicitFloatingIPAllocationMixin(object):
+    """Overrides methods for managing floating ips
+
+    Should be mixed in before inheriting from
+    neutron.db.l3_db.L3_NAT_db_mixin.
+
+    """
+
+    def create_floatingip(self, context, floatingip):
+        fip = floatingip['floatingip']
+        tenant_id = self._get_tenant_id_for_create(context, fip)
+        fip_id = uuidutils.generate_uuid()
+
+        f_net_id = fip['floating_network_id']
+        if not self._core_plugin._network_is_external(context, f_net_id):
+            msg = _("Network %s is not a valid external network") % f_net_id
+            raise q_exc.BadRequest(resource='floatingip', msg=msg)
+
+        with context.session.begin(subtransactions=True):
+            # This external port is never exposed to the tenant.
+            # it is used purely for internal system and admin use when
+            # managing floating IPs.
+            external_port = self._core_plugin.create_port(context.elevated(), {
+                'port':
+                {'tenant_id': '',  # tenant intentionally not set
+                 'network_id': f_net_id,
+                 'mac_address': attributes.ATTR_NOT_SPECIFIED,
+                 'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
+                 'admin_state_up': True,
+                 'device_id': fip_id,
+                 'device_owner': DEVICE_OWNER_FLOATINGIP,
+                 'name': ''}})
+            # Ensure IP addresses are allocated on external port
+            if not external_port['fixed_ips']:
+                raise q_exc.ExternalIpAddressExhausted(net_id=f_net_id)
+
+            floating_fixed_ip = external_port['fixed_ips'][0]
+            floating_ip_address = floating_fixed_ip['ip_address']
+            floatingip_db = FloatingIP(
+                id=fip_id,
+                tenant_id=tenant_id,
+                floating_network_id=fip['floating_network_id'],
+                floating_ip_address=floating_ip_address,
+                floating_port_id=external_port['id'])
+            fip['tenant_id'] = tenant_id
+            # Update association with internal port
+            # and define external IP address
+            self._update_fip_assoc(context, fip,
+                                   floatingip_db, external_port)
+            context.session.add(floatingip_db)
+
+        router_id = floatingip_db['router_id']
+        if router_id:
+            self.l3_rpc_notifier.routers_updated(
+                context, [router_id],
+                'create_floatingip')
+        return self._make_floatingip_dict(floatingip_db)
diff --git a/akanda/neutron/plugins/nvp_neutron_plugin.py b/akanda/neutron/plugins/nvp_neutron_plugin.py
index d370480..3a62d4c 100644
--- a/akanda/neutron/plugins/nvp_neutron_plugin.py
+++ b/akanda/neutron/plugins/nvp_neutron_plugin.py
@@ -28,6 +28,7 @@ from neutron.plugins.nicira.NeutronPlugin import nicira_db
 from neutron.plugins.nicira import NeutronPlugin as nvp
 
 from akanda.neutron.plugins import decorators as akanda
+from akanda.neutron.plugins import floatingip
 
 LOG = logging.getLogger("NeutronPlugin")
 akanda.monkey_patch_ipv6_generator()
@@ -75,7 +76,8 @@ class AkandaNvpRpcCallbacks(l3_rpc.L3RpcCallbackMixin,
     pass
 
 
-class NvpPluginV2(nvp.NvpPluginV2):
+class NvpPluginV2(floatingip.ExplicitFloatingIPAllocationMixin,
+                  nvp.NvpPluginV2):
     """
     NvpPluginV2 is a Neutron plugin that provides L2 Virtual Network
     functionality using NVP.
@@ -136,7 +138,6 @@ class NvpPluginV2(nvp.NvpPluginV2):
     get_routers = l3_db.L3_NAT_db_mixin.get_routers
     add_router_interface = l3_db.L3_NAT_db_mixin.add_router_interface
     remove_router_interface = l3_db.L3_NAT_db_mixin.remove_router_interface
-    create_floatingip = l3_db.L3_NAT_db_mixin.create_floatingip
     update_floatingip = l3_db.L3_NAT_db_mixin.update_floatingip
     delete_floatingip = l3_db.L3_NAT_db_mixin.delete_floatingip
     get_floatingip = l3_db.L3_NAT_db_mixin.get_floatingip
diff --git a/akanda/neutron/plugins/ovs_neutron_plugin.py b/akanda/neutron/plugins/ovs_neutron_plugin.py
index b2e1371..30b1dc4 100644
--- a/akanda/neutron/plugins/ovs_neutron_plugin.py
+++ b/akanda/neutron/plugins/ovs_neutron_plugin.py
@@ -19,10 +19,13 @@
 from neutron.plugins.openvswitch import ovs_neutron_plugin
 
 from akanda.neutron.plugins import decorators as akanda
+from akanda.neutron.plugins import floatingip
+
 akanda.monkey_patch_ipv6_generator()
 
 
-class OVSNeutronPluginV2(ovs_neutron_plugin.OVSNeutronPluginV2):
+class OVSNeutronPluginV2(floatingip.ExplicitFloatingIPAllocationMixin,
+                         ovs_neutron_plugin.OVSNeutronPluginV2):
     _supported_extension_aliases = (
         ovs_neutron_plugin.OVSNeutronPluginV2._supported_extension_aliases +
         ["dhportforward", "dhaddressgroup", "dhaddressentry",