diff --git a/akanda/neutron/plugins/nvp_neutron_plugin.py b/akanda/neutron/plugins/nvp_neutron_plugin.py
index c73cbc1..23e3cc1 100644
--- a/akanda/neutron/plugins/nvp_neutron_plugin.py
+++ b/akanda/neutron/plugins/nvp_neutron_plugin.py
@@ -28,7 +28,6 @@ from neutron.openstack.common import rpc
 from neutron.plugins.nicira.dhcp_meta import rpc as nvp_rpc
 from neutron.plugins.nicira.NeutronPlugin import nicira_db
 from neutron.plugins.nicira import NeutronPlugin as nvp
-from neutron.plugins.nicira.NeutronPlugin import nvplib
 
 from akanda.neutron.plugins import decorators as akanda
 
@@ -39,9 +38,12 @@ akanda.monkey_patch_ipv6_generator()
 def akanda_nvp_ipv6_port_security_wrapper(f):
     @functools.wraps(f)
     def wrapper(lport_obj, mac_address, fixed_ips, port_security_enabled,
-                security_profiles, queue_id):
+                security_profiles, queue_id, mac_learning_enabled,
+                allowed_address_pairs):
+
         f(lport_obj, mac_address, fixed_ips, port_security_enabled,
-          security_profiles, queue_id)
+          security_profiles, queue_id, mac_learning_enabled,
+          allowed_address_pairs)
 
         # evaulate the state so that we only override the value when enabled
         # otherwise we are preserving the underlying behavior of the NVP plugin
@@ -49,6 +51,8 @@ def akanda_nvp_ipv6_port_security_wrapper(f):
             # hotfix to enable egress mulitcast
             lport_obj['allow_egress_multicast'] = True
 
+            # TODO(mark): investigate moving away from this an wrapping
+            # (create|update)_port
             # add link-local and subnet cidr for IPv6 temp addresses
             special_ipv6_addrs = akanda.get_special_ipv6_addrs(
                 (p['ip_address'] for p in lport_obj['allowed_address_pairs']),
@@ -144,6 +148,7 @@ class NvpPluginV2(nvp.NvpPluginV2):
     get_floatingip = l3_db.L3_NAT_db_mixin.get_floatingip
     get_floatings = l3_db.L3_NAT_db_mixin.get_floatingips
     _update_fip_assoc = l3_db.L3_NAT_db_mixin._update_fip_assoc
+    _update_router_gw_info = l3_db.L3_NAT_db_mixin._update_router_gw_info
     disassociate_floatingips = l3_db.L3_NAT_db_mixin.disassociate_floatingips
 
     def _ensure_metadata_host_route(self, *args, **kwargs):
@@ -153,70 +158,56 @@ class NvpPluginV2(nvp.NvpPluginV2):
     def _nvp_create_port(self, context, port_data):
         """ Driver for creating a logical switch port on NVP platform """
         # NOTE(mark): Akanda does want ports for external networks so
-        # this method is basically same with external check removed
-        network = self._get_network(context, port_data['network_id'])
-        network_binding = nicira_db.get_network_binding(
-            context.session, port_data['network_id'])
-        max_ports = self.nvp_opts.max_lp_per_overlay_ls
-        allow_extra_lswitches = False
-        if (network_binding and
-            network_binding.binding_type in (NetworkTypes.FLAT,
-                                             NetworkTypes.VLAN)):
-            max_ports = self.nvp_opts.max_lp_per_bridged_ls
-            allow_extra_lswitches = True
+        # this method is basically same with external check removed and
+        # the auto plugging of router ports
+        lport = None
+        selected_lswitch = None
         try:
-            cluster = self._find_target_cluster(port_data)
-            selected_lswitch = self._handle_lswitch_selection(
-                cluster, network, network_binding, max_ports,
-                allow_extra_lswitches)
-            lswitch_uuid = selected_lswitch['uuid']
-            lport = nvplib.create_lport(cluster,
-                                        lswitch_uuid,
-                                        port_data['tenant_id'],
-                                        port_data['id'],
-                                        port_data['name'],
-                                        port_data['device_id'],
-                                        port_data['admin_state_up'],
-                                        port_data['mac_address'],
-                                        port_data['fixed_ips'],
-                                        port_data[psec.PORTSECURITY],
-                                        port_data[ext_sg.SECURITYGROUPS])
+            selected_lswitch = self._nvp_find_lswitch_for_port(context,
+                                                               port_data)
+            lport = self._nvp_create_port_helper(self.cluster,
+                                                 selected_lswitch['uuid'],
+                                                 port_data,
+                                                 True)
             nicira_db.add_neutron_nvp_port_mapping(
                 context.session, port_data['id'], lport['uuid'])
-            d_owner = port_data['device_owner']
 
-            nvplib.plug_interface(cluster, lswitch_uuid,
-                                  lport['uuid'], "VifAttachment",
-                                  port_data['id'])
-            LOG.debug(_("_nvp_create_port completed for port %(port_name)s "
-                        "on network %(net_id)s. The new port id is "
-                        "%(port_id)s. NVP port id is %(nvp_port_id)s"),
-                      {'port_name': port_data['name'],
-                       'net_id': port_data['network_id'],
-                       'port_id': port_data['id'],
-                       'nvp_port_id': lport['uuid']})
-        except Exception:
-            # failed to create port in NVP delete port from neutron_db
-            LOG.exception(_("An exception occured while plugging "
-                            "the interface"))
-            raise
+            nvp.nvplib.plug_interface(self.cluster, selected_lswitch['uuid'],
+                                      lport['uuid'], "VifAttachment",
+                                      port_data['id'])
+
+            LOG.debug(_("_nvp_create_port completed for port %(name)s "
+                        "on network %(network_id)s. The new port id is "
+                        "%(id)s."), port_data)
+        except (nvp.NvpApiClient.NvpApiException, nvp.q_exc.NeutronException):
+            self._handle_create_port_exception(
+                context, port_data['id'],
+                selected_lswitch and selected_lswitch['uuid'],
+                lport and lport['uuid'])
 
     def _nvp_delete_port(self, context, port_data):
         # NOTE(mark): Akanda does want ports for external networks so
         # this method is basically same with external check removed
-        port = nicira_db.get_nvp_port_id(context.session, port_data['id'])
-        if port is None:
-            raise q_exc.PortNotFound(port_id=port_data['id'])
+        nvp_port_id = self._nvp_get_port_id(context, self.cluster,
+                                            port_data)
+        if not nvp_port_id:
+            LOG.debug(_("Port '%s' was already deleted on NVP platform"), id)
+            return
         # TODO(bgh): if this is a bridged network and the lswitch we just got
         # back will have zero ports after the delete we should garbage collect
         # the lswitch.
-        nvplib.delete_port(self.default_cluster,
-                           port_data['network_id'],
-                           port)
-        LOG.debug(_("_nvp_delete_port completed for port %(port_id)s "
-                    "on network %(net_id)s"),
-                  {'port_id': port_data['id'],
-                   'net_id': port_data['network_id']})
+        try:
+            nvp.nvplib.delete_port(self.cluster,
+                                   port_data['network_id'],
+                                   nvp_port_id)
+            LOG.debug(_("_nvp_delete_port completed for port %(port_id)s "
+                        "on network %(net_id)s"),
+                      {'port_id': port_data['id'],
+                       'net_id': port_data['network_id']})
+
+        except q_exc.NotFound:
+            LOG.warning(_("Port %s not found in NVP"), port_data['id'])
+
 
 def noop(*args, **kwargs):
     pass