]> git.proxmox.com Git - mirror_ifupdown2.git/blobdiff - addons/vrf.py
addons: vrf: fix vrf slave link kind (fixes #39)
[mirror_ifupdown2.git] / addons / vrf.py
index 26d77f30098656589676bd3a148fc0f1046fb52f..5e46aa3076e4781b2f71d6d1241ae0251f983e68 100644 (file)
@@ -5,29 +5,41 @@
 #
 
 import os
+import signal
+import errno
+import fcntl
 import atexit
+import re
+from sets import Set
 from ifupdown.iface import *
+from ifupdown.utils import utils
 import ifupdown.policymanager as policymanager
 import ifupdownaddons
-import ifupdown.rtnetlink_api as rtnetlink_api
+from ifupdown.netlink import netlink
+import ifupdown.ifupdownflags as ifupdownflags
 from ifupdownaddons.modulebase import moduleBase
 from ifupdownaddons.bondutil import bondutil
 from ifupdownaddons.iproute2 import iproute2
+from ifupdownaddons.dhclient import dhclient
+from ifupdownaddons.utilsbase import *
+
+class vrfPrivFlags:
+    PROCESSED = 0x1
 
 class vrf(moduleBase):
     """  ifupdown2 addon module to configure vrfs """
     _modinfo = { 'mhelp' : 'vrf configuration module',
                     'attrs' : {
                     'vrf-table':
-                         {'help' : 'vrf device table id. key to ' +
-                                   'creating a vrf device',
-                          'example': ['vrf-table-id 1']},
-                    'vrf-default-route':
-                         {'help' : 'vrf device default route ' +
-                                   'to avoid communication outside the vrf device',
-                          'example': ['vrf-default-route yes/no']},
+                         {'help' : 'vrf device routing table id. key to ' +
+                                   'creating a vrf device. ' +
+                                   'Table id is either \'auto\' or '+
+                                   '\'valid routing table id\'',
+                          'validvals': ['auto', '<number>'],
+                          'example': ['vrf-table auto', 'vrf-table 1001']},
                     'vrf':
                          {'help' : 'vrf the interface is part of.',
+                          'validvals': ['<text>'],
                           'example': ['vrf blue']}}}
 
     iproute2_vrf_filename = '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf'
@@ -37,23 +49,48 @@ class vrf(moduleBase):
     VRF_TABLE_START = 1001
     VRF_TABLE_END = 5000
 
+    system_reserved_rt_tables = {'255' : 'local', '254' : 'main', 
+                                 '253' : 'default', '0' : 'unspec'}
+
     def __init__(self, *args, **kargs):
         ifupdownaddons.modulebase.moduleBase.__init__(self, *args, **kargs)
         self.ipcmd = None
         self.bondcmd = None
+        self.dhclientcmd = None
+        self.name = self.__class__.__name__
+        self.vrf_mgmt_devname = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-mgmt-devname')
+
+        if (ifupdownflags.flags.PERFMODE and
+            not (self.vrf_mgmt_devname and os.path.exists('/sys/class/net/%s'
+            %self.vrf_mgmt_devname))):
+            # if perf mode is set (PERFMODE is set at boot), and this is the first
+            # time we are calling ifup at boot (check for mgmt vrf existance at
+            # boot, make sure this is really the first invocation at boot.
+            # ifup is called with PERFMODE at boot multiple times (once for mgmt vrf
+            # and the second time with all auto interfaces). We want to delete
+            # the map file only the first time. This is to avoid accidently
+            # deleting map file with a valid mgmt vrf entry
+            if os.path.exists(self.iproute2_vrf_filename):
+                try:
+                    self.logger.info('vrf: removing file %s'
+                                     %self.iproute2_vrf_filename)
+                    os.remove(self.iproute2_vrf_filename)
+                except Exception, e:
+                    self.logger.debug('vrf: removing file failed (%s)'
+                                      %str(e))
         try:
-            ip_rules = self.exec_command('/sbin/ip rule show').splitlines()
+            ip_rules = utils.exec_command('/sbin/ip rule show').splitlines()
             self.ip_rule_cache = [' '.join(r.split()) for r in ip_rules]
         except Exception, e:
             self.ip_rule_cache = []
-            self.logger.warn('%s' %str(e))
+            self.logger.warn('vrf: cache v4: %s' % str(e))
 
         try:
-            ip_rules = self.exec_command('/sbin/ip -6 rule show').splitlines()
+            ip_rules = utils.exec_command('/sbin/ip -6 rule show').splitlines()
             self.ip6_rule_cache = [' '.join(r.split()) for r in ip_rules]
         except Exception, e:
             self.ip6_rule_cache = []
-            self.logger.warn('%s' %str(e))
+            self.logger.warn('vrf: cache v6: %s' % str(e))
 
         #self.logger.debug("vrf: ip rule cache")
         #self.logger.info(self.ip_rule_cache)
@@ -61,38 +98,19 @@ class vrf(moduleBase):
         #self.logger.info("vrf: ip -6 rule cache")
         #self.logger.info(self.ip6_rule_cache)
 
-        # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
+        self.l3mdev_checked = False
+        self.l3mdev4_rule = False
+        if self._l3mdev_rule(self.ip_rule_cache):
+            self.l3mdev4_rule = True
+            self.l3mdev_checked = True
+        self.l3mdev6_rule = False
+        if self._l3mdev_rule(self.ip6_rule_cache):
+            self.l3mdev6_rule = True
+            self.l3mdev_checked = True
+        self._iproute2_vrf_map_initialized = False
         self.iproute2_vrf_map = {}
-        # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
-        if os.path.exists(self.iproute2_vrf_filename):
-            self.vrf_map_fd = open(self.iproute2_vrf_filename, 'a+')
-            lines = self.vrf_map_fd.readlines()
-            for l in lines:
-                l = l.strip()
-                if l[0] == '#':
-                    continue
-                try:
-                    (table, vrf_name) = l.strip().split()
-                    self.iproute2_vrf_map[table] = vrf_name
-                except Exception, e:
-                    self.logger.info('vrf: iproute2_vrf_map: unable to parse %s'
-                                     %l)
-                    pass
-        #self.logger.info("vrf: dumping iproute2_vrf_map")
-        #self.logger.info(self.iproute2_vrf_map)
-
-        # purge vrf table entries that are not around
-        iproute2_vrf_map_pruned = {}
-        for t, v in self.iproute2_vrf_map.iteritems():
-            if os.path.exists('/sys/class/net/%s' %v):
-                iproute2_vrf_map_pruned[t] = v
-            else:
-                try:
-                    # cleanup rules
-                    self._del_vrf_rules(v, t)
-                except Exception:
-                    pass
-        self.iproute2_vrf_map = iproute2_vrf_map_pruned
+        self.iproute2_vrf_map_fd = None
+        self.iproute2_vrf_map_sync_to_disk = False
 
         self.vrf_table_id_start = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-table-id-start')
         if not self.vrf_table_id_start:
@@ -102,6 +120,66 @@ class vrf(moduleBase):
             self.vrf_table_id_end = self.VRF_TABLE_END
         self.vrf_max_count = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-max-count')
 
+        self.vrf_fix_local_table = True
+        self.vrf_count = 0
+        self.vrf_helper = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-helper')
+        self.vrf_close_socks_on_down = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-close-socks-on-down')
+        self.warn_on_vrf_map_write_err = True
+
+    def _iproute2_vrf_map_initialize(self, writetodisk=True):
+        if self._iproute2_vrf_map_initialized:
+            return
+
+        # XXX: check for vrf reserved overlap in /etc/iproute2/rt_tables
+        self.iproute2_vrf_map = {}
+        iproute2_vrf_map_force_rewrite = False
+        # read or create /etc/iproute2/rt_tables.d/ifupdown2.vrf_map
+        if os.path.exists(self.iproute2_vrf_filename):
+            with open(self.iproute2_vrf_filename, 'r+') as vrf_map_fd:
+                lines = vrf_map_fd.readlines()
+                for l in lines:
+                    l = l.strip()
+                    if l[0] == '#':
+                        continue
+                    try:
+                        (table, vrf_name) = l.strip().split()
+                        if self.iproute2_vrf_map.get(int(table)):
+                            # looks like the existing file has
+                            # duplicate entries, force rewrite of the
+                            # file
+                            iproute2_vrf_map_force_rewrite = True
+                            continue
+                        self.iproute2_vrf_map[int(table)] = vrf_name
+                    except Exception, e:
+                        self.logger.info('vrf: iproute2_vrf_map: unable to parse %s (%s)' %(l, str(e)))
+                        pass
+
+        vrfs = self.ipcmd.link_get_vrfs()
+        running_vrf_map = {}
+        if vrfs:
+            for v, lattrs in vrfs.iteritems():
+                table = lattrs.get('table', None)
+                if table:
+                   running_vrf_map[int(table)] = v
+
+        if (not running_vrf_map or (running_vrf_map != self.iproute2_vrf_map)):
+            self.iproute2_vrf_map = running_vrf_map
+            iproute2_vrf_map_force_rewrite = True
+
+        self.iproute2_vrf_map_fd = None
+        if writetodisk:
+            if iproute2_vrf_map_force_rewrite:
+                # reopen the file and rewrite the map
+                self._iproute2_vrf_map_open(True, False)
+            else:
+                self._iproute2_vrf_map_open(False, True)
+
+        self.iproute2_vrf_map_sync_to_disk = False
+        atexit.register(self._iproute2_vrf_map_sync_to_disk)
+
+        self.logger.info("vrf: dumping iproute2_vrf_map")
+        self.logger.info(self.iproute2_vrf_map)
+
         last_used_vrf_table = None
         for t in range(self.vrf_table_id_start,
                        self.vrf_table_id_end):
@@ -109,28 +187,61 @@ class vrf(moduleBase):
                 break
             last_used_vrf_table = t
         self.last_used_vrf_table = last_used_vrf_table
-        self.iproute2_write_vrf_map = False
-        atexit.register(self.iproute2_vrf_map_write)
-        self.vrf_fix_local_table = True
-        self.vrf_count = 0
-        self.vrf_cgroup_create = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='vrf-cgroup-create')
-        if not self.vrf_cgroup_create:
-            self.vrf_cgroup_create = False
-        elif self.vrf_cgroup_create == 'yes':
-            self.vrf_cgroup_create = True
-        else:
-            self.vrf_cgroup_create = False
+        self._iproute2_vrf_map_initialized = True
+        self.vrf_count = len(self.iproute2_vrf_map)
 
-    def iproute2_vrf_map_write(self):
-        if not self.iproute2_write_vrf_map:
+    def _iproute2_map_warn(self, errstr):
+        if self.warn_on_vrf_map_write_err:
+            if not os.path.exists('/etc/iproute2/rt_tables.d/'):
+                self.logger.info('unable to save iproute2 vrf to table ' +
+                                 'map (%s)\n' %errstr)
+                self.logger.info('cannot find /etc/iproute2/rt_tables.d.' +
+                                 ' pls check if your iproute2 version' +
+                                 ' supports rt_tables.d')
+            else:
+                self.logger.warn('unable to open iproute2 vrf to table ' +
+                                 'map (%s)\n' %errstr)
+            self.warn_on_vrf_map_write_err = False
+
+    def _iproute2_vrf_map_sync_to_disk(self):
+        if (ifupdownflags.flags.DRYRUN or
+            not self.iproute2_vrf_map_sync_to_disk):
             return
-        self.logger.info('vrf: writing table map to %s'
+        self.logger.info('vrf: syncing table map to %s'
                          %self.iproute2_vrf_filename)
-        with open(self.iproute2_vrf_filename, 'w') as f:
-            f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
-                    self.vrf_table_id_end))
+        try:
+            with open(self.iproute2_vrf_filename, 'w') as f:
+                f.write(self.iproute2_vrf_filehdr %(self.vrf_table_id_start,
+                        self.vrf_table_id_end))
+                for t, v in self.iproute2_vrf_map.iteritems():
+                    f.write('%s %s\n' %(t, v))
+                f.flush()
+        except Exception, e:
+            self._iproute2_map_warn(str(e))
+            pass
+
+    def _iproute2_vrf_map_open(self, sync_vrfs=False, append=False):
+        self.logger.info('vrf: syncing table map to %s'
+                         %self.iproute2_vrf_filename)
+        if ifupdownflags.flags.DRYRUN:
+            return
+        fmode = 'a+' if append else 'w'
+        try:
+            self.iproute2_vrf_map_fd = open(self.iproute2_vrf_filename,
+                                         '%s' %fmode)
+            fcntl.fcntl(self.iproute2_vrf_map_fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+        except Exception, e:
+            self._iproute2_map_warn(str(e))
+            return
+
+        if not append:
+            # write file header
+            self.iproute2_vrf_map_fd.write(self.iproute2_vrf_filehdr
+                                           %(self.vrf_table_id_start,
+                                             self.vrf_table_id_end))
             for t, v in self.iproute2_vrf_map.iteritems():
-                f.write('%s %s\n' %(t, v))
+                self.iproute2_vrf_map_fd.write('%s %s\n' %(t, v))
+            self.iproute2_vrf_map_fd.flush()
 
     def _is_vrf(self, ifaceobj):
         if ifaceobj.get_attr_value_first('vrf-table'):
@@ -144,10 +255,13 @@ class vrf(moduleBase):
         if vrf_table:
             ifaceobj.link_type = ifaceLinkType.LINK_MASTER
             ifaceobj.link_kind |= ifaceLinkKind.VRF
+            ifaceobj.role |= ifaceRole.MASTER
         vrf_iface_name = ifaceobj.get_attr_value_first('vrf')
         if not vrf_iface_name:
             return None
         ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
+        ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
+
         return [vrf_iface_name]
 
     def get_upper_ifacenames_running(self, ifaceobj):
@@ -156,7 +270,7 @@ class vrf(moduleBase):
     def _get_iproute2_vrf_table(self, vrf_dev_name):
         for t, v in self.iproute2_vrf_map.iteritems():
             if v == vrf_dev_name:
-                return t
+                return str(t)
         return None
 
     def _get_avail_vrf_table_id(self):
@@ -171,25 +285,146 @@ class vrf(moduleBase):
                 return str(t)
         return None
 
-    def _iproute2_vrf_table_entry_add(self, vrf_dev_name, table_id):
-        self.iproute2_vrf_map[table_id] = vrf_dev_name
-        self.iproute2_write_vrf_map = True
+    def _iproute2_is_vrf_tableid_inuse(self, vrfifaceobj, table_id):
+        old_vrf_name = self.iproute2_vrf_map.get(int(table_id))
+        if old_vrf_name and old_vrf_name != vrfifaceobj.name:
+            self.log_error('table id %s already assigned to vrf dev %s'
+                           %(table_id, old_vrf_name), vrfifaceobj)
+
+    def _iproute2_vrf_table_entry_add(self, vrfifaceobj, table_id):
+        old_vrf_name = self.iproute2_vrf_map.get(int(table_id))
+        if not old_vrf_name:
+            self.iproute2_vrf_map[int(table_id)] = vrfifaceobj.name
+            if self.iproute2_vrf_map_fd:
+                self.iproute2_vrf_map_fd.write('%s %s\n'
+                                               %(table_id, vrfifaceobj.name))
+                self.iproute2_vrf_map_fd.flush()
+                self.vrf_count += 1
+            return
+        if old_vrf_name != vrfifaceobj.name:
+            self.log_error('table id %d already assigned to vrf dev %s'
+                           %(table_id, old_vrf_name))
 
     def _iproute2_vrf_table_entry_del(self, table_id):
         try:
-            del self.iproute2_vrf_map[table_id]
-            self.iproute2_write_vrf_map = True
+            # with any del of vrf map, we need to force sync to disk
+            self.iproute2_vrf_map_sync_to_disk = True
+            del self.iproute2_vrf_map[int(table_id)]
         except Exception, e:
-            self.logger.info('vrf: iproute2 vrf map del failed for %d (%s)'
+            self.logger.info('vrf: iproute2 vrf map del failed for %s (%s)'
                              %(table_id, str(e)))
             pass
 
-    def _up_vrf_slave(self, ifacename, vrfname):
+    def _is_vrf_dev(self, ifacename):
+        # Look at iproute2 map for now.
+        # If it was a master we knew about,
+        # it is definately there
+        if ifacename in self.iproute2_vrf_map.values():
+            return True
+        return False
+
+    def _is_dhcp_slave(self, ifaceobj):
+        if (not ifaceobj.addr_method or
+            (ifaceobj.addr_method != 'dhcp' and
+             ifaceobj.addr_method != 'dhcp6')):
+                return False
+        return True
+
+    def _up_vrf_slave_without_master(self, ifacename, vrfname, ifaceobj,
+                                     vrf_master_objs):
+        """ If we have a vrf slave that has dhcp configured, bring up the
+            vrf master now. This is needed because vrf has special handling
+            in dhclient hook which requires the vrf master to be present """
+
+        vrf_master = ifaceobj.upperifaces[0]
+        if not vrf_master:
+            self.logger.warn('%s: vrf master not found' %ifacename)
+            return
+        if os.path.exists('/sys/class/net/%s' %vrf_master):
+            self.logger.info('%s: vrf master %s exists returning'
+                             %(ifacename, vrf_master))
+            return
+        self.logger.info('%s: bringing up vrf master %s'
+                         %(ifacename, vrf_master))
+        for mobj in vrf_master_objs:
+            vrf_table = mobj.get_attr_value_first('vrf-table')
+            if vrf_table:
+                if vrf_table == 'auto':
+                    vrf_table = self._get_avail_vrf_table_id()
+                    if not vrf_table:
+                        self.log_error('%s: unable to get an auto table id'
+                                       %mobj.name, ifaceobj)
+                    self.logger.info('%s: table id auto: selected table id %s\n'
+                                     %(mobj.name, vrf_table))
+                try:
+                    self._up_vrf_dev(mobj, vrf_table, False)
+                except Exception:
+                    raise
+                break
+        self._handle_existing_connections(ifaceobj, vrfname)
+        netlink.link_set_master(ifacename, vrfname)
+        return
+
+    def _down_dhcp_slave(self, ifaceobj, vrfname):
         try:
-            if self.ipcmd.link_exists(vrfname):
-                self.ipcmd.link_set(ifacename, 'master', vrfname)
+            dhclient_cmd_prefix = None
+            if (vrfname and self.vrf_exec_cmd_prefix and
+                self.ipcmd.link_exists(vrfname)):
+                dhclient_cmd_prefix = '%s %s' %(self.vrf_exec_cmd_prefix,
+                                                vrfname)
+            self.dhclientcmd.release(ifaceobj.name, dhclient_cmd_prefix)
+        except:
+            # ignore any dhclient release errors
+            pass
+
+    def _handle_existing_connections(self, ifaceobj, vrfname):
+        if not ifaceobj or ifupdownflags.flags.PERFMODE:
+            return
+        if (self.vrf_mgmt_devname and
+            self.vrf_mgmt_devname == vrfname):
+            self._kill_ssh_connections(ifaceobj.name)
+        if self._is_dhcp_slave(ifaceobj):
+            self._down_dhcp_slave(ifaceobj, vrfname)
+
+    def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None,
+                      ifaceobj_getfunc=None, vrf_exists=False):
+        try:
+            master_exists = True
+            if vrf_exists or self.ipcmd.link_exists(vrfname):
+                uppers = self.ipcmd.link_get_uppers(ifacename)
+                if not uppers or vrfname not in uppers:
+                    self._handle_existing_connections(ifaceobj, vrfname)
+                    netlink.link_set_master(ifacename, vrfname)
+            elif ifaceobj:
+                vrf_master_objs = ifaceobj_getfunc(vrfname)
+                if not vrf_master_objs:
+                    # this is the case where vrf is assigned to an interface
+                    # but user has not provided a vrf interface.
+                    # people expect you to warn them but go ahead with the
+                    # rest of the config on that interface
+                    netlink.link_set_updown(ifacename, "up")
+                    self.log_error('vrf master ifaceobj %s not found'
+                                   %vrfname)
+                    return
+                if (ifupdownflags.flags.ALL or
+                    ifupdownflags.flags.WITH_DEPENDS or
+                    (ifupdownflags.flags.CLASS and
+                     ifaceobj.classes and vrf_master_objs[0].classes and
+                     Set(ifaceobj.classes).intersection(vrf_master_objs[0].classes))):
+                    self._up_vrf_slave_without_master(ifacename, vrfname,
+                                                      ifaceobj,
+                                                      vrf_master_objs)
+                else:
+                    master_exists = False
+            else:
+                master_exists = False
+            if master_exists:
+                netlink.link_set_updown(ifacename, "up")
+            else:
+                self.log_error('vrf %s not around, skipping vrf config'
+                               %(vrfname), ifaceobj)
         except Exception, e:
-            self.logger.warn('%s: %s' %(ifacename, str(e)))
+            self.log_error('%s: %s' %(ifacename, str(e)), ifaceobj)
 
     def _del_vrf_rules(self, vrf_dev_name, vrf_table):
         pref = 200
@@ -198,25 +433,43 @@ class vrf(moduleBase):
 
         rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
         if rule in self.ip_rule_cache:
-            rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name, vrf_table)
-            self.exec_command(rule_cmd)
+            rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name,
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
         rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
         if rule in self.ip_rule_cache:
-            rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name, vrf_table)
-            self.exec_command(rule_cmd)
+            rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name,
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
         rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
-        if rule in self.ip_rule_cache:
+        if rule in self.ip6_rule_cache:
             rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
-                                     vrf_table)
-            self.exec_command(rule_cmd)
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
         rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
-        if rule in self.ip_rule_cache:
+        if rule in self.ip6_rule_cache:
             rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
-                                     vrf_table)
-            self.exec_command(rule_cmd)
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
+
+    def _l3mdev_rule(self, ip_rules):
+        for rule in ip_rules:
+            if not re.search(r"\d.*from\s+all\s+lookup\s+\W?l3mdev-table\W?",
+                             rule):
+                continue
+            return True
+        return False
+
+    def _rule_cache_fill(self):
+        ip_rules = utils.exec_command('/sbin/ip rule show').splitlines()
+        self.ip_rule_cache = [' '.join(r.split()) for r in ip_rules]
+        self.l3mdev4_rule = self._l3mdev_rule(self.ip_rule_cache)
+        ip_rules = utils.exec_command('/sbin/ip -6 rule show').splitlines()
+        self.ip6_rule_cache = [' '.join(r.split()) for r in ip_rules]
+        self.l3mdev6_rule = self._l3mdev_rule(self.ip6_rule_cache)
 
     def _add_vrf_rules(self, vrf_dev_name, vrf_table):
         pref = 200
@@ -227,210 +480,418 @@ class vrf(moduleBase):
             rule = '0: from all lookup local'
             if rule in self.ip_rule_cache:
                 try:
-                    self.exec_command('ip rule del pref 0')
-                    self.exec_command('ip rule add pref 32765 table local')
+                    utils.exec_command('ip rule del pref 0')
+                    utils.exec_command('ip rule add pref 32765 table local')
                 except Exception, e:
-                    self.logger.info('%s' %str(e))
+                    self.logger.info('%s: %s' % (vrf_dev_name, str(e)))
+                    pass
+            if rule in self.ip6_rule_cache:
+                try:
+                    utils.exec_command('ip -6 rule del pref 0')
+                    utils.exec_command('ip -6 rule add pref 32765 table local')
+                except Exception, e:
+                    self.logger.info('%s: %s' % (vrf_dev_name, str(e)))
                     pass
 
+        if not self.l3mdev_checked:
+            self._rule_cache_fill()
+            self.l3mdev_checked = True
         #Example ip rule
         #200: from all oif blue lookup blue
         #200: from all iif blue lookup blue
 
         rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
-        if rule not in self.ip_rule_cache:
-            rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name, vrf_table)
-            self.exec_command(rule_cmd)
+        if not self.l3mdev4_rule and rule not in self.ip_rule_cache:
+            rule_cmd = ip_rule_cmd %('', pref, 'oif', vrf_dev_name,
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
         rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
-        if rule not in self.ip_rule_cache:
-            rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name, vrf_table)
-            self.exec_command(rule_cmd)
+        if not self.l3mdev4_rule and rule not in self.ip_rule_cache:
+            rule_cmd = ip_rule_cmd %('', pref, 'iif', vrf_dev_name,
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
         rule = ip_rule_out_format %(pref, 'oif', vrf_dev_name, vrf_dev_name)
-        if rule not in self.ip_rule_cache:
-            rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name, vrf_table)
-            self.exec_command(rule_cmd)
+        if not self.l3mdev6_rule and rule not in self.ip6_rule_cache:
+            rule_cmd = ip_rule_cmd %('-6', pref, 'oif', vrf_dev_name,
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
         rule = ip_rule_out_format %(pref, 'iif', vrf_dev_name, vrf_dev_name)
-        if rule not in self.ip_rule_cache:
+        if not self.l3mdev6_rule and rule not in self.ip6_rule_cache:
             rule_cmd = ip_rule_cmd %('-6', pref, 'iif', vrf_dev_name,
-                                     vrf_table)
-            self.exec_command(rule_cmd)
+                                     vrf_dev_name)
+            utils.exec_command(rule_cmd)
 
-    def _add_vrf_slaves(self, ifaceobj):
+    def _is_address_virtual_slaves(self, vrfobj, config_vrfslaves,
+                                   vrfslave):
+        # Address virtual lines on a vrf slave will create
+        # macvlan devices on the vrf slave and enslave them
+        # to the vrf master. This function checks if the
+        # vrf slave is such a macvlan interface.
+        # XXX: additional possible checks that can be done here
+        # are:
+        #  - check if it is also a macvlan device of the
+        #    format <vrf_slave>-v<int> created by the 
+        #    address virtual module
+        vrfslave_lowers = self.ipcmd.link_get_lowers(vrfslave)
+        if vrfslave_lowers:
+            if vrfslave_lowers[0] in config_vrfslaves:
+                return True
+        return False
+
+    def _add_vrf_slaves(self, ifaceobj, ifaceobj_getfunc=None):
         running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
         config_slaves = ifaceobj.lowerifaces
         if not config_slaves and not running_slaves:
             return
+
+        if not config_slaves: config_slaves = []
+        if not running_slaves: running_slaves = []
         add_slaves = set(config_slaves).difference(set(running_slaves))
         del_slaves = set(running_slaves).difference(set(config_slaves))
         if add_slaves:
             for s in add_slaves:
                 try:
-                    self._up_vrf_slave(s, ifaceobj.name)
+                    if not self.ipcmd.link_exists(s):
+                        continue
+                    sobj = None
+                    if ifaceobj_getfunc:
+                        sobj = ifaceobj_getfunc(s)
+                    self._up_vrf_slave(s, ifaceobj.name,
+                                       sobj[0] if sobj else None,
+                                       ifaceobj_getfunc, True)
                 except Exception, e:
                     self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
 
         if del_slaves:
             for s in del_slaves:
                 try:
-                    self._down_vrf_slave(s, ifaceobj.name)
+                    if self._is_address_virtual_slaves(ifaceobj,
+                                                       config_slaves, s):
+                        continue
+                    sobj = None
+                    if ifaceobj_getfunc:
+                        sobj = ifaceobj_getfunc(s)
+                    self._down_vrf_slave(s, sobj[0] if sobj else None,
+                                         ifaceobj.name)
                 except Exception, e:
                     self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
 
         if ifaceobj.link_type == ifaceLinkType.LINK_MASTER:
             for s in config_slaves:
                 try:
-                    rtnetlink_api.rtnl_api.link_set(s, "up")
+                    netlink.link_set_updown(s, "up")
                 except Exception, e:
-                    self.logger.debug('%s: %s: link set up (%s)'
-                                      %(ifaceobj.name, s, str(e)))
+                    self.logger.debug('%s: %s' % (ifaceobj.name, str(e)))
                     pass
 
-    def _create_cgroup(self, ifaceobj):
-        if not self.vrf_cgroup_create:
-            return
-        try:
-            if not os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
-                self.exec_command('/usr/bin/cgcreate -g l3mdev:%s' %ifaceobj.name)
-            self.exec_command('/usr/bin/cgset -r l3mdev.master-device=%s %s'
-                              %(ifaceobj.name, ifaceobj.name))
-        except Exception, e:
-            self.log_warn('%s: cgroup create failed (%s)\n'
-                          %(ifaceobj.name, str(e)), ifaceobj)
+    def _set_vrf_dev_processed_flag(self, ifaceobj):
+        ifaceobj.module_flags[self.name] = \
+                             ifaceobj.module_flags.setdefault(self.name, 0) | \
+                                        vrfPrivFlags.PROCESSED
 
-    def _up_vrf_dev(self, ifaceobj, vrf_table):
+    def _check_vrf_dev_processed_flag(self, ifaceobj):
+        if (ifaceobj.module_flags.get(self.name, 0) & vrfPrivFlags.PROCESSED):
+            return True
+        return False
 
+    def _create_vrf_dev(self, ifaceobj, vrf_table):
         if not self.ipcmd.link_exists(ifaceobj.name):
+            if ifaceobj.name in self.system_reserved_rt_tables.values():
+                self.log_error('cannot use system reserved %s vrf names'
+                                %(str(self.system_reserved_rt_tables.values())),
+                                ifaceobj)
+            if self.vrf_count == self.vrf_max_count:
+                self.log_error('max vrf count %d hit...not '
+                               'creating vrf' % self.vrf_count, ifaceobj)
             if vrf_table == 'auto':
                 vrf_table = self._get_avail_vrf_table_id()
                 if not vrf_table:
-                    self.log_error('%s: unable to get an auto table id'
-                                   %ifaceobj.name)
+                    self.log_error('unable to get an auto table id', ifaceobj)
                 self.logger.info('%s: table id auto: selected table id %s\n'
                                  %(ifaceobj.name, vrf_table))
+            else:
+                self._iproute2_is_vrf_tableid_inuse(ifaceobj, vrf_table)
+                if ifaceobj.name in self.system_reserved_rt_tables.keys():
+                    self.log_error('cannot use system reserved %s table ids'
+                                  %(str(self.system_reserved_rt_tables.keys())),
+                                  ifaceobj)
+
+            if not vrf_table.isdigit():
+                self.log_error('vrf-table must be an integer or \'auto\'', ifaceobj)
+
             # XXX: If we decide to not allow vrf id usages out of
             # the reserved ifupdown range, then uncomment this code.
-            #else:
-            #    if (int(vrf_table) < self.vrf_table_id_start or
-            #        int(vrf_table) > self.vrf_table_id_end):
-            #        self.log_error('%s: vrf table id %s out of reserved range [%d,%d]'
-            #                       %(ifaceobj.name, vrf_table,
-            #                         self.vrf_table_id_start,
-            #                         self.vrf_table_id_end))
+            else:
+                if (int(vrf_table) < self.vrf_table_id_start or
+                    int(vrf_table) > self.vrf_table_id_end):
+                    self.log_error('vrf table id %s out of reserved range [%d,%d]'
+                                   %(vrf_table,
+                                     self.vrf_table_id_start,
+                                     self.vrf_table_id_end), ifaceobj)
             try:
                 self.ipcmd.link_create(ifaceobj.name, 'vrf',
                                        {'table' : '%s' %vrf_table})
             except Exception, e:
-                self.log_error('%s: create failed (%s)\n'
-                               %(ifaceobj.name, str(e)))
+                self.log_error('create failed (%s)\n' % str(e), ifaceobj)
+            if vrf_table != 'auto':
+                self._iproute2_vrf_table_entry_add(ifaceobj, vrf_table)
         else:
-            vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
-            if not vrf_table:
-                self.log_error('%s: unable to get vrf table id'
-                               %ifaceobj.name)
+            if vrf_table == 'auto':
+                vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
+                if not vrf_table:
+                    self.log_error('unable to get vrf table id', ifaceobj)
 
             # if the device exists, check if table id is same
             vrfdev_attrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
             if vrfdev_attrs:
                 running_table = vrfdev_attrs.get('table', None)
                 if vrf_table != running_table:
-                    self.log_error('%s: cannot change vrf table id,running table id %s is different from config id %s' %(ifaceobj.name,
-                                         running_table, vrf_table))
+                    self.log_error('cannot change vrf table id,running table id'
+                                   ' %s is different from config id %s'
+                                   % (running_table, vrf_table), ifaceobj)
+        return vrf_table
 
+    def _up_vrf_helper(self, ifaceobj, vrf_table):
+        mode = ""
+        if ifupdownflags.flags.PERFMODE:
+            mode = "boot"
+        if self.vrf_helper:
+            utils.exec_command('%s create %s %s %s' %
+                               (self.vrf_helper,
+                                ifaceobj.name,
+                                vrf_table,
+                                mode))
+
+    def _up_vrf_dev(self, ifaceobj, vrf_table, add_slaves=True,
+                    ifaceobj_getfunc=None):
+
+        # if vrf dev is already processed return. This can happen
+        # if we the slave was configured before.
+        # see self._up_vrf_slave_without_master
+        if self._check_vrf_dev_processed_flag(ifaceobj):
+            return True
+
+        try:
+            vrf_table = self._create_vrf_dev(ifaceobj, vrf_table)
+        except Exception, e:
+            self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
+        
         try:
-            self._iproute2_vrf_table_entry_add(ifaceobj.name, vrf_table)
             self._add_vrf_rules(ifaceobj.name, vrf_table)
-            self._add_vrf_slaves(ifaceobj)
-            self._create_cgroup(ifaceobj)
+            self._up_vrf_helper(ifaceobj, vrf_table)
+            if add_slaves:
+                self._add_vrf_slaves(ifaceobj, ifaceobj_getfunc)
+            self._set_vrf_dev_processed_flag(ifaceobj)
+            netlink.link_set_updown(ifaceobj.name, "up")
         except Exception, e:
-            self.log_error('%s: %s' %(ifaceobj.name, str(e)))
-
-    def _up_vrf_default_route(self, ifaceobj,  vrf_table):
-        vrf_default_route = ifaceobj.get_attr_value_first('vrf-default-route')
-        if not vrf_default_route:
-            vrf_default_route = policymanager.policymanager_api.get_attr_default(
-            module_name=self.__class__.__name__, attr='vrf-default-route')
-        if not vrf_default_route:
-            return
-        if str(vrf_default_route).lower() == "yes":
-            try:
-                self.exec_command('ip route add table %s unreachable default' %vrf_table)
-            except OSError, e:
-                if e.errno != 17:
-                    raise
-                pass
+            self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
 
-            try:
-                self.exec_command('ip -6 route add table %s unreachable default' %vrf_table)
-            except OSError, e:
-                if e.errno != 17:
-                    raise
-                pass
+    def _kill_ssh_connections(self, ifacename):
+        try:
+            runningaddrsdict = self.ipcmd.addr_get(ifacename)
+            if not runningaddrsdict:
+                return
+            iplist = [i.split('/', 1)[0] for i in runningaddrsdict.keys()]
+            if not iplist:
+                return
+            proc=[]
+            #Example output:
+            #ESTAB      0      0      10.0.1.84:ssh       10.0.1.228:45186     
+            #users:(("sshd",pid=2528,fd=3))
+            cmdl = ['/bin/ss', '-t', '-p']
+            for line in utils.exec_commandl(cmdl).splitlines():
+                citems = line.split()
+                addr = None
+                if '%' in citems[3]:
+                    addr = citems[3].split('%')[0]
+                elif ':ssh' in citems[3]:
+                    addr = citems[3].split(':')[0]
+                if not addr:
+                    continue
+                if addr in iplist:
+                    if len(citems) == 6:
+                        proc.append(citems[5].split(',')[1].split('=')[1])
+
+            if not proc:
+                return
+            pid = None
+            # outpt of '/usr/bin/pstree -Aps <pid>':
+            # 'systemd(1)---sshd(990)---sshd(16112)---sshd(16126)---bash(16127)---sudo(16756)---ifreload(16761)---pstree(16842)\n'
+            # get the above output to following format
+            # ['systemd(1)', 'sshd(990)', 'sshd(16112)', 'sshd(16126)', 'bash(16127)', 'sudo(16756)', 'ifreload(16761)', 'pstree(16850)']
+            pstree = list(reversed(utils.exec_command('/usr/bin/pstree -Aps %s' %os.getpid()).strip().split('---')))
+            for index, process in enumerate(pstree):
+                # check the parent of SSH process to make sure
+                # we don't kill SSH server or systemd process
+                if 'sshd' in process and 'sshd' in pstree[index + 1]:
+                    pid = filter(lambda x: x.isdigit(), process)
+                    break
+            self.logger.info("%s: killing active ssh sessions: %s"
+                             %(ifacename, str(proc)))
+
+            if ifupdownflags.flags.DRYRUN:
+                return
+            for id in proc:
+                if id != pid:
+                    try:
+                        os.kill(int(id), signal.SIGINT)
+                    except OSError as e:
+                        continue
 
-    def _up(self, ifaceobj):
+            # Kill current SSH client
+            if pid in proc:
+                try:
+                    forkret = os.fork()
+                except OSError, e:
+                    self.logger.info("fork error : %s [%d]" % (e.strerror, e.errno))
+                if (forkret == 0):  # The first child.
+                    try:
+                        os.setsid()
+                        self.logger.info("%s: ifreload continuing in the background" %ifacename)
+                    except OSError, (err_no, err_message):
+                        self.logger.info("os.setsid failed: errno=%d: %s" % (err_no, err_message))
+                        self.logger.info("pid=%d  pgid=%d" % (os.getpid(), os.getpgid(0)))
+                try:
+                    self.logger.info("%s: killing our session: %s"
+                                     %(ifacename, str(proc)))
+                    os.kill(int(pid), signal.SIGINT)
+                    return
+                except OSError as e:
+                    return
+        except Exception, e:
+            self.logger.info('%s: %s' %(ifacename, str(e)))
+
+    def _up(self, ifaceobj, ifaceobj_getfunc=None):
         try:
             vrf_table = ifaceobj.get_attr_value_first('vrf-table')
             if vrf_table:
-                if self.vrf_count == self.vrf_max_count:
-                    self.log_error('%s: max vrf count %d hit...not '
-                                   'creating vrf' %(ifaceobj.name,
-                                                    self.vrf_count))
-                self._up_vrf_dev(ifaceobj, vrf_table)
-                self._up_vrf_default_route(ifaceobj, vrf_table)
+                self._iproute2_vrf_map_initialize()
+                # This is a vrf device
+                self._up_vrf_dev(ifaceobj, vrf_table, True, ifaceobj_getfunc)
             else:
                 vrf = ifaceobj.get_attr_value_first('vrf')
                 if vrf:
-                    self._up_vrf_slave(ifaceobj.name, vrf)
+                    self._iproute2_vrf_map_initialize()
+                    # This is a vrf slave
+                    self._up_vrf_slave(ifaceobj.name, vrf, ifaceobj,
+                                       ifaceobj_getfunc)
+                else:
+                    # check if we were a slave before
+                    master = self.ipcmd.link_get_master(ifaceobj.name)
+                    if master:
+                        self._iproute2_vrf_map_initialize()
+                        if self._is_vrf_dev(master):
+                            self._down_vrf_slave(ifaceobj.name, ifaceobj,
+                                                 master)
         except Exception, e:
-            self.log_error(str(e))
+            self.log_error(str(e), ifaceobj)
+
+    def _down_vrf_helper(self, ifaceobj, vrf_table):
+        mode = ""
+        if ifupdownflags.flags.PERFMODE:
+            mode = "boot"
+        if self.vrf_helper:
+            utils.exec_command('%s delete %s %s %s' %
+                               (self.vrf_helper,
+                                ifaceobj.name,
+                                vrf_table,
+                                mode))
+
+    def _close_sockets(self, ifaceobj, ifindex):
+        if not self.vrf_close_socks_on_down:
+            return
 
-    def _delete_cgroup(self, ifaceobj):
         try:
-            if os.path.exists('/sys/fs/cgroup/l3mdev/%s' %ifaceobj.name):
-                self.exec_command('cgdelete -g l3mdev:%s' %ifaceobj.name)
+            utils.exec_command('/bin/ss -aK \"dev == %s\"'
+                               %ifindex)
         except Exception, e:
-            self.log_warn('%s: cgroup delete failed (%s)\n'
-                          %(ifaceobj.name, str(e)), ifaceobj)
+            self.logger.info('%s: closing socks using ss'
+                             ' failed (%s)\n' %(ifaceobj.name, str(e)))
+            pass
+
+    def _down_vrf_dev(self, ifaceobj, vrf_table, ifaceobj_getfunc=None):
+
+        if not self.ipcmd.link_exists(ifaceobj.name):
+            return
 
-    def _down_vrf_dev(self, ifaceobj, vrf_table):
         if vrf_table == 'auto':
             vrf_table = self._get_iproute2_vrf_table(ifaceobj.name)
+
+        running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
+        if running_slaves:
+            for s in running_slaves:
+                if ifaceobj_getfunc:
+                    sobj = ifaceobj_getfunc(s)
+                    try:
+                        self._handle_existing_connections(sobj[0]
+                                                          if sobj else None,
+                                                          ifaceobj.name)
+                    except Exception, e:
+                        self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
+                        pass
+                try:
+                    self.ipcmd.addr_flush(s)
+                    netlink.link_set_updown(s, "down")
+                except Exception, e:
+                    self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
+                    pass
+
         try:
-            self.ipcmd.link_delete(ifaceobj.name)
+            self._down_vrf_helper(ifaceobj, vrf_table)
+        except Exception, e:
+            self.logger.warn('%s: %s' %(ifaceobj.name, str(e)))
+            pass
+
+        try:
+            self._del_vrf_rules(ifaceobj.name, vrf_table)
         except Exception, e:
             self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
             pass
 
+        ifindex = self.ipcmd.link_get_ifindex(ifaceobj.name)
+
         try:
-            self._iproute2_vrf_table_entry_del(vrf_table)
-            self._delete_cgroup(ifaceobj)
+            self.ipcmd.link_delete(ifaceobj.name)
         except Exception, e:
             self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
             pass
 
+        self._close_sockets(ifaceobj, ifindex)
+
         try:
-            self._del_vrf_rules(ifaceobj.name, vrf_table)
+            self._iproute2_vrf_table_entry_del(vrf_table)
         except Exception, e:
             self.logger.info('%s: %s' %(ifaceobj.name, str(e)))
             pass
 
-    def _down_vrf_slave(self, ifacename, vrf):
+
+    def _down_vrf_slave(self, ifacename, ifaceobj=None, vrfname=None):
         try:
-            self.ipcmd.link_set(ifacename, 'nomaster')
+            self._handle_existing_connections(ifaceobj, vrfname)
+            netlink.link_set_nomaster(ifacename)
+            # Down this slave only if it is a slave ifupdown2 manages.
+            # we dont want to down slaves that maybe up'ed by
+            # somebody else. One such example is a macvlan device
+            # which ifupdown2 addressvirtual addon module auto creates
+            if ifaceobj:
+                netlink.link_set_updown(ifacename, "down")
         except Exception, e:
             self.logger.warn('%s: %s' %(ifacename, str(e)))
 
-    def _down(self, ifaceobj):
+    def _down(self, ifaceobj, ifaceobj_getfunc=None):
         try:
             vrf_table = ifaceobj.get_attr_value_first('vrf-table')
             if vrf_table:
-                self._down_vrf_dev(ifaceobj, vrf_table)
+                self._iproute2_vrf_map_initialize()
+                self._down_vrf_dev(ifaceobj, vrf_table, ifaceobj_getfunc)
             else:
                 vrf = ifaceobj.get_attr_value_first('vrf')
                 if vrf:
-                    self._down_vrf_slave(ifaceobj.name, vrf)
+                    self._iproute2_vrf_map_initialize()
+                    self._down_vrf_slave(ifaceobj.name, ifaceobj, None)
         except Exception, e:
             self.log_warn(str(e))
 
@@ -438,11 +899,11 @@ class vrf(moduleBase):
         try:
             master = self.ipcmd.link_get_master(ifaceobj.name)
             if not master or master != vrf:
-                ifaceobjcurr.update_config_with_status('vrf', master, 1)
+                ifaceobjcurr.update_config_with_status('vrf', str(master), 1)
             else:
                 ifaceobjcurr.update_config_with_status('vrf', master, 0)
         except Exception, e:
-            self.log_warn(str(e))
+            self.log_error(str(e), ifaceobjcurr)
 
     def _query_check_vrf_dev(self, ifaceobj, ifaceobjcurr, vrf_table):
         try:
@@ -467,6 +928,25 @@ class vrf(moduleBase):
             else:
                 ifaceobjcurr.update_config_with_status('vrf-table',
                                                        running_table, 0)
+            if not ifupdownflags.flags.WITHDEFAULTS:
+                return
+            if self.vrf_helper:
+                try:
+                    utils.exec_command('%s verify %s %s'
+                                      %(self.vrf_helper,
+                                      ifaceobj.name, config_table))
+                    ifaceobjcurr.update_config_with_status('vrf-helper',
+                                                           '%s create %s %s'
+                                                           %(self.vrf_helper,
+                                                           ifaceobj.name,
+                                                           config_table), 0)
+                except Exception, e:
+                    ifaceobjcurr.update_config_with_status('vrf-helper',
+                                                           '%s create %s %s'
+                                                           %(self.vrf_helper,
+                                                           ifaceobj.name,
+                                                           config_table), 1)
+                    pass
         except Exception, e:
             self.log_warn(str(e))
 
@@ -474,15 +954,17 @@ class vrf(moduleBase):
         try:
             vrf_table = ifaceobj.get_attr_value_first('vrf-table')
             if vrf_table:
+                self._iproute2_vrf_map_initialize(writetodisk=False)
                 self._query_check_vrf_dev(ifaceobj, ifaceobjcurr, vrf_table)
             else:
                 vrf = ifaceobj.get_attr_value_first('vrf')
                 if vrf:
+                    self._iproute2_vrf_map_initialize(writetodisk=False)
                     self._query_check_vrf_slave(ifaceobj, ifaceobjcurr, vrf)
         except Exception, e:
             self.log_warn(str(e))
 
-    def _query_running(self, ifaceobjrunning):
+    def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
         try:
             kind = self.ipcmd.link_get_kind(ifaceobjrunning.name)
             if kind == 'vrf':
@@ -492,30 +974,42 @@ class vrf(moduleBase):
                     if running_table:
                         ifaceobjrunning.update_config('vrf-table',
                                                       running_table)
-            elif kind == 'vrf_slave':
+                        return
+            slave_kind = self.ipcmd.link_get_slave_kind(ifaceobjrunning.name)
+            if slave_kind == 'vrf_slave':
                 vrf = self.ipcmd.link_get_master(ifaceobjrunning.name)
                 if vrf:
                     ifaceobjrunning.update_config('vrf', vrf)
         except Exception, e:
             self.log_warn(str(e))
 
+    def _query(self, ifaceobj, **kwargs):
+        if not self.vrf_helper:
+            return
+        if (ifaceobj.link_kind & ifaceLinkKind.VRF):
+            ifaceobj.update_config('vrf-helper', '%s %s' %(self.vrf_helper,
+                                   ifaceobj.name))
+
     _run_ops = {'pre-up' : _up,
                'post-down' : _down,
                'query-running' : _query_running,
-               'query-checkcurr' : _query_check}
+               'query-checkcurr' : _query_check,
+               'query' : _query}
 
     def get_ops(self):
         """ returns list of ops supported by this module """
         return self._run_ops.keys()
 
     def _init_command_handlers(self):
-        flags = self.get_flags()
         if not self.ipcmd:
-            self.ipcmd = iproute2(**flags)
+            self.ipcmd = iproute2()
         if not self.bondcmd:
-            self.bondcmd = bondutil(**flags)
+            self.bondcmd = bondutil()
+        if not self.dhclientcmd:
+            self.dhclientcmd = dhclient()
 
-    def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
+    def run(self, ifaceobj, operation, query_ifaceobj=None,
+            ifaceobj_getfunc=None, **extra_args):
         """ run bond configuration on the interface object passed as argument
 
         Args:
@@ -539,4 +1033,4 @@ class vrf(moduleBase):
         if operation == 'query-checkcurr':
             op_handler(self, ifaceobj, query_ifaceobj)
         else:
-            op_handler(self, ifaceobj)
+            op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)