def __update_bgp()

in src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py [0:0]


    def __update_bgp(self, data_list):
        while not self.bgp_message.empty():
            key, del_table, table, data = self.bgp_message.get()
            if table == 'STATIC_ROUTE' and len(key.split('|')) == 1:
                key = self.DEFAULT_VRF + '|' + key
            key_list = key.split('|', 1)
            if table == 'BGP_NEIGHBOR' and len(key_list) == 1:
                # bypass non-compatible neighbor table
                continue
            data_list.append((table, key, data))
            if len(key_list) > 1:
                key = key_list[1]
            else:
                key = None
            prefix = key_list[0]
            syslog.syslog(syslog.LOG_INFO, 'value for table {} prefix {} key {} changed to {}'.format(table, prefix, key, data))
            if self.__vrf_based_table(table):
                vrf = prefix
                local_asn = self.__get_vrf_asn(vrf)
                if local_asn is None and (table != 'BGP_GLOBALS' or 'local_asn' not in data):
                    syslog.syslog(syslog.LOG_DEBUG, 'ignore table {} update because local_asn for VRF {} was not configured'.\
                            format(table, vrf))
                    continue
            if table in self.tbl_to_key_map:
                tbl_key = None
                if table == 'BGP_NEIGHBOR_AF' or table == 'BGP_PEER_GROUP_AF' and key is not None:
                    _, af_ip_type = key.split('|')
                    tbl_key, _ = af_ip_type.lower().split('_')
                    tbl_key = {'admin_status': tbl_key}
                elif table == 'ROUTE_MAP':
                    tbl_key = {}
                    for attr_name, table_name in {'match_prefix_set': 'PREFIX', 'match_next_hop_set': 'PREFIX'}.items():
                        if attr_name in data:
                            pfx_set_name = self.get_prefix_set_name(data[attr_name].data, table_name)
                            if pfx_set_name in self.prefix_set_list:
                                af_mode = self.prefix_set_list[pfx_set_name].af
                                tbl_key[attr_name] = 'ipv4' if af_mode == socket.AF_INET else 'ipv6'
                elif table == 'STATIC_ROUTE':
                    af_id, new_key = IpNextHopSet.get_af_norm_prefix(key)
                    if new_key is not None:
                        key = new_key
                        tbl_key = {'ip_prefix': ('ipv4' if af_id == socket.AF_INET else 'ipv6')}
                key_map = BGPKeyMapList(self.tbl_to_key_map[table], table, tbl_key)
            else:
                key_map = None
            if table == 'BGP_GLOBALS':
                if not del_table:
                    if 'local_asn' in data:
                        dval = data['local_asn']
                        if dval.op == CachedDataWithOp.OP_DELETE:
                            # delete local_asn will delete whole VRF instance
                            self.__delete_vrf_asn(vrf, table, data)
                            continue
                        prog_asn = True
                        if dval.op == CachedDataWithOp.OP_UPDATE:
                            syslog.syslog(syslog.LOG_ERR, 'local_asn could not be modified')
                            prog_asn = False
                        if dval.op == CachedDataWithOp.OP_NONE:
                            prog_asn = False
                        if prog_asn:
                            command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' -c 'no bgp default ipv4-unicast'".format(dval.data, vrf)
                            if self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_DEBUG, 'set local_asn %s to VRF %s, re-apply all VRF related tables' % (dval.data, vrf))
                                self.bgp_asn[vrf] = dval.data
                                self.__apply_dep_vrf_table(vrf, 'ROUTE_REDISTRIBUTE')
                                dval.status = CachedDataWithOp.STAT_SUCC
                            else:
                                syslog.syslog(syslog.LOG_ERR, 'failed to set local_asn %s to VRF %s' % (dval.data, vrf))
                        else:
                            dval.status = CachedDataWithOp.STAT_SUCC
                    if 'confed_peers' in data:
                        self.upd_confed_peers = copy.copy(self.bgp_confed_peers.get(vrf, set()))
                    local_asn = self.__get_vrf_asn(vrf)
                    if local_asn is None:
                        syslog.syslog(syslog.LOG_ERR, 'local ASN for VRF %s was not configured' % vrf)
                        continue
                    cmd_prefix = ['configure terminal', 'router bgp {} vrf {}'.format(local_asn, vrf)]
                    if not key_map.run_command(self, table, data, cmd_prefix):
                        syslog.syslog(syslog.LOG_ERR, 'failed running BGP global config command')
                        continue
                    if 'confed_peers' in data:
                        self.bgp_confed_peers[vrf] = copy.copy(self.upd_confed_peers)
                else:
                    self.__delete_vrf_asn(vrf, table, data)
            elif table == 'BGP_GLOBALS_AF':
                af, ip_type = key.lower().split('_')
                #this is to temporarily make table cache key accessible to key_map handler function
                self.tmp_cache_key = 'BGP_GLOBALS_AF&&{}|{}'.format(vrf, key.lower())
                syslog.syslog(syslog.LOG_INFO, 'Set address family global to {} {} cache-key to {}'.format(af, ip_type, self.tmp_cache_key))
                cmd_prefix = ['configure terminal',
                              'router bgp {} vrf {}'.format(local_asn, vrf),
                              'address-family {} {}'.format(af, ip_type)]
                if not key_map.run_command(self, table, data, cmd_prefix):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP global AF config command')
                    continue
                self.tmp_cache_key = ''
            elif table == 'BGP_GLOBALS_LISTEN_PREFIX':
                syslog.syslog(syslog.LOG_INFO, 'Set BGP listen prefix {}'.format(key))
                cmd_prefix = ['configure terminal',
                              'router bgp {} vrf {}'.format(local_asn, vrf)]
                if not key_map.run_command(self, table, data, cmd_prefix, key):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP global listen prefix config command')
                    continue
            elif table == 'BGP_NEIGHBOR' or table == 'BGP_PEER_GROUP':
                is_peer_group = table == 'BGP_PEER_GROUP'
                if not del_table:
                    if is_peer_group:
                        # if peer group is not created, create it before setting other attributes
                        if key not in self.bgp_peer_group.setdefault(vrf, {}):
                            command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' ".format(local_asn, vrf)
                            command += "-c 'neighbor {} peer-group'".format(key)
                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to create peer-group %s for VRF %s' % (key, vrf))
                                continue
                            self.bgp_peer_group[vrf][key] = BGPPeerGroup(vrf)
                    elif not self.__peer_is_ip(key):
                        if key not in self.bgp_intf_nbr.setdefault(vrf, set()):
                            command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' ".format(local_asn, vrf)
                            command += "-c 'neighbor {} interface'".format(key)
                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to create neighbor of interface %s for VRF %s' % (key, vrf))
                                continue
                            self.bgp_intf_nbr[vrf].add(key)
                    bfd_val = data.get('bfd', None)
                    if (bfd_val is not None and (bfd_val.op == CachedDataWithOp.OP_ADD or bfd_val.op == CachedDataWithOp.OP_UPDATE) and
                        bfd_val.data == 'true'):
                        cp_chk_val = data.get('bfd_check_ctrl_plane_failure', None)
                        if cp_chk_val is not None and cp_chk_val.op == CachedDataWithOp.OP_NONE and cp_chk_val.data == 'true':
                            cp_chk_val.op = CachedDataWithOp.OP_ADD
                    cmd_prefix = ['configure terminal', 'router bgp {} vrf {}'.format(local_asn, vrf)]
                    if not key_map.run_command(self, table, data, cmd_prefix, key):
                        syslog.syslog(syslog.LOG_ERR, 'failed running BGP neighbor config command')
                        continue
                    if ('peer_group_name' in data and
                        (data['peer_group_name'].op == CachedDataWithOp.OP_ADD or
                         data['peer_group_name'].op == CachedDataWithOp.OP_DELETE)):
                        dval = data['peer_group_name']
                        if vrf not in self.bgp_peer_group or dval.data not in self.bgp_peer_group[vrf]:
                            # should not happen because vtysh command will fail if peer_group not exists
                            syslog.syslog(syslog.LOG_ERR, 'invalid peer-group %s was referenced' % dval.data)
                            continue
                        peer_grp = self.bgp_peer_group[vrf][dval.data]
                        if dval.op == CachedDataWithOp.OP_ADD:
                            peer_grp.ref_nbrs.add(key)
                        else:
                            peer_grp.ref_nbrs.discard(key)
                    nbr_action = self.__nbr_impl_action(data, key, is_peer_group)
                    if nbr_action == 'delete':
                        if not is_peer_group and self.__peer_is_ip(key):
                            # delete asn or peer_group will delete all neighbor
                            self.__delete_vrf_neighbor(vrf, key, data, False)
                        elif is_peer_group:
                            # clear associated neighbor list in cache
                            self.__delete_pg_neighbors(vrf, key)
                    elif nbr_action == 'apply':
                        if is_peer_group:
                            syslog.syslog(syslog.LOG_DEBUG, 'apply attributes to FRR for vrf %s peer_group %s' % (vrf, key))
                            match_pg = lambda data: data.get('peer_group', None) == key
                            self.__apply_dep_vrf_table(vrf, 'BGP_GLOBALS_LISTEN_PREFIX', match = match_pg)
                            match_nbr = lambda data: data.get('peer_group_name', None) == key
                            self.__apply_dep_vrf_table(vrf, 'BGP_NEIGHBOR', match = match_nbr)
                        else:
                            for af in ['ipv4_unicast', 'ipv6_unicast']:
                                syslog.syslog(syslog.LOG_DEBUG, 'apply attributes to FRR for vrf %s neighbor %s af %s' % (vrf, key, af))
                                self.__apply_dep_vrf_table(vrf, 'BGP_NEIGHBOR_AF', key, af)
                else:
                    # Neighbor is deleted
                    if is_peer_group:
                        # clear associated neighbor list in cache
                        self.__delete_pg_neighbors(vrf, key)
                    command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' -c 'no neighbor {}'".\
                        format(local_asn, vrf, key)
                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete VRF %s bgp neigbor %s' % (vrf, key))
                    self.__delete_vrf_neighbor(vrf, key, data, is_peer_group)
            elif table == 'BGP_NEIGHBOR_AF' or table == 'BGP_PEER_GROUP_AF':
                nbr, af_type = key.split('|')
                af, ip_type = af_type.lower().split('_')
                syslog.syslog(syslog.LOG_INFO, 'Set address family for neighbor {} to {} {}'.format(nbr, af, ip_type))
                cmd_prefix = ['configure terminal',
                              'router bgp {} vrf {}'.format(local_asn, vrf),
                              'address-family {} {}'.format(af, ip_type)]
                if not key_map.run_command(self, table, data, cmd_prefix, nbr):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP neighbor AF config command')
                    continue
            elif table == 'COMMUNITY_SET' or table == 'EXTENDED_COMMUNITY_SET':
                comm_set_name = prefix
                syslog.syslog(syslog.LOG_INFO, 'Set community set {} for table {}'.format(comm_set_name, table))
                cmd_prefix = ['configure terminal']
                if not key_map.run_command(self, table, data, cmd_prefix, comm_set_name):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP community config command')
                    continue
                extended = (table != 'COMMUNITY_SET')
                comm_set = (self.comm_set_list if not extended else self.extcomm_set_list).setdefault(comm_set_name,
                    CommunityList(comm_set_name, extended))
                if del_table:
                    del((self.comm_set_list if not extended else self.extcomm_set_list)[comm_set_name])
                else:
                    for dkey, dval in data.items():
                        if dval.op == CachedDataWithOp.OP_DELETE:
                            upd_val = None
                        else:
                            upd_val = dval.data
                        comm_set.db_data_to_attr(dkey, upd_val)
            elif table == 'PREFIX_SET':
                pfx_set_name = prefix
                if not del_table:
                    if pfx_set_name in self.prefix_set_list:
                        syslog.syslog(syslog.LOG_DEBUG, 'prefix-set %s exists with af %d' %
                                (pfx_set_name, self.prefix_set_list[pfx_set_name].af))
                        continue
                    if 'mode' not in data:
                        syslog.syslog(syslog.LOG_ERR, 'no mode given for prefix-set %s' % pfx_set_name)
                        continue
                    set_mode = data['mode'].data.lower()
                    self.prefix_set_list[pfx_set_name] = MatchPrefixList(set_mode)
                else:
                    if pfx_set_name in self.prefix_set_list:
                        del(self.prefix_set_list[pfx_set_name])
                for _, dval in data.items():
                    dval.status = CachedDataWithOp.STAT_SUCC
            elif table == 'PREFIX' or table == 'NEIGHBOR_SET' or table == 'NEXTHOP_SET':
                pfx_set_name = self.get_prefix_set_name(prefix, table)
                if table == 'PREFIX':
                    if pfx_set_name not in self.prefix_set_list:
                        syslog.syslog(syslog.LOG_ERR, 'could not find prefix-set %s from cache' % pfx_set_name)
                        continue
                    ip_pfx, len_range = key.split('|')
                    if len_range == 'exact':
                        len_range = None
                    pfx_action = data.get('action', None)
                    if pfx_action is None or pfx_action.op == CachedDataWithOp.OP_NONE:
                        continue
                    af = self.prefix_set_list[pfx_set_name].af
                    if af == socket.AF_INET:
                        # use table daemons setting
                        daemons = None
                    else:
                        daemons = ['bgpd', 'zebra']
                    if pfx_action.op == CachedDataWithOp.OP_DELETE or pfx_action.op == CachedDataWithOp.OP_UPDATE:
                        del_pfx, pfx_idx = self.prefix_set_list[pfx_set_name].get_prefix(ip_pfx, len_range)
                        if del_pfx is None:
                            syslog.syslog(syslog.LOG_ERR, 'prefix of {} with range {} not found from prefix-set {}'.\
                                            format(ip_pfx, len_range, pfx_set_name))
                            continue
                        command = "vtysh -c 'configure terminal' -c 'no {} prefix-list {} {}'".\
                                    format(('ip' if af == socket.AF_INET else 'ipv6'), pfx_set_name, str(del_pfx))
                        if not self.__run_command(table, command, daemons):
                            syslog.syslog(syslog.LOG_ERR, 'failed to delete prefix %s with range %s from set %s' %
                                          (ip_pfx, len_range, pfx_set_name))
                            continue
                        del(self.prefix_set_list[pfx_set_name][pfx_idx])
                    if pfx_action.op == CachedDataWithOp.OP_ADD or pfx_action.op == CachedDataWithOp.OP_UPDATE:
                        try:
                            add_pfx = self.prefix_set_list[pfx_set_name].add_prefix(ip_pfx, len_range, pfx_action.data)
                        except ValueError:
                            syslog.syslog(syslog.LOG_ERR, 'failed to update prefix-set %s in cache with prefix %s range %s' %
                                    (pfx_set_name, ip_pfx, len_range))
                            continue
                        command = "vtysh -c 'configure terminal' -c '{} prefix-list {} {}'".\
                                    format(('ip' if af == socket.AF_INET else 'ipv6'), pfx_set_name, str(add_pfx))
                        if not self.__run_command(table, command, daemons):
                            syslog.syslog(syslog.LOG_ERR, 'failed to add prefix %s with range %s to set %s' %
                                          (ip_pfx, len_range, pfx_set_name))
                            # revert cached update on failure
                            del_pfx, pfx_idx = self.prefix_set_list[pfx_set_name].get_prefix(ip_pfx, len_range)
                            if del_pfx is not None:
                                del(self.prefix_set_list[pfx_set_name][pfx_idx])
                            continue
                else:
                    if 'address' not in data or data['address'].op == CachedDataWithOp.OP_NONE:
                        continue
                    ip_addr_list = data['address'].data
                    if pfx_set_name in self.prefix_set_list:
                        af = self.prefix_set_list[pfx_set_name].af
                        command = "vtysh -c 'configure terminal' -c 'no {} prefix-list {}'".\
                                   format(('ip' if af == socket.AF_INET else 'ipv6'), pfx_set_name)
                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to delete existing prefix-set {}'.format(pfx_set_name))
                            continue
                        del(self.prefix_set_list[pfx_set_name])
                    if not del_table:
                        prefix_set = MatchPrefixList()
                        for ip_addr in ip_addr_list:
                            try:
                                prefix_set.add_prefix(ip_addr)
                            except ValueError:
                                continue
                        for prefix in prefix_set:
                            command = "vtysh -c 'configure terminal' -c '{} prefix-list {} {}'".\
                                       format(('ip' if prefix_set.af == socket.AF_INET else 'ipv6'), pfx_set_name, str(prefix))
                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to delete existing prefix-set {}'.format(pfx_set_name))
                                continue
                        self.prefix_set_list[pfx_set_name] = prefix_set
                for _, dval in data.items():
                    dval.status = CachedDataWithOp.STAT_SUCC
            elif table == 'AS_PATH_SET':
                as_set_name = prefix
                syslog.syslog(syslog.LOG_INFO, 'Set AS path set {} for table {}'.format(as_set_name, table))
                cmd_prefix = ['configure terminal']
                if not key_map.run_command(self, table, data, cmd_prefix, as_set_name):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP AS path set config command')
                    continue
                as_set_data = data.get('as_path_set_member', None)
                if as_set_data is not None and (as_set_data.op == CachedDataWithOp.OP_DELETE or len(as_set_data.data) == 0):
                    del_table = True
                if del_table:
                    self.as_path_set_list.pop(as_set_name, None)
                elif as_set_data is not None:
                    self.as_path_set_list[as_set_name] = as_set_data.data[:]
            elif table == 'TAG_SET':
                tag_set_name = prefix
                if not del_table and 'tag_value' not in data:
                    continue
                tag_set_data = data.get('tag_value', None)
                if tag_set_data is not None and (tag_set_data.op == CachedDataWithOp.OP_DELETE or len(tag_set_data.data) == 0):
                    del_table = True
                if not del_table:
                    self.tag_set_list[tag_set_name] = set(tag_set_data.data)
                else:
                    self.tag_set_list.pop(tag_set_name, None)
                for _, dval in data.items():
                    dval.status = CachedDataWithOp.STAT_SUCC
            elif table == 'BGP_GLOBALS_EVPN_VNI':
                af_type, vni = key.split('|')
                af, ip_type = af_type.lower().split('_')
                #this is to temporarily make table cache key accessible to key_map handler function
                self.tmp_cache_key = 'BGP_GLOBALS_EVPN_VNI&&{}|{}|{}'.format(vrf, af_type, vni)
                syslog.syslog(syslog.LOG_INFO, 'Set address family for VNI {} to {} {} cache-key to {}'.format(vni, af, ip_type, self.tmp_cache_key))
                cmd_prefix = ['configure terminal',
                              'router bgp {} vrf {}'.format(local_asn, vrf),
                              'address-family {} {}'.format(af, ip_type),
                              'vni {}'.format(vni)]
                if not key_map.run_command(self, table, data, cmd_prefix):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI config command')
                    continue
                self.tmp_cache_key = ''
                if del_table:
                    cmd = "vtysh -c 'configure terminal'"
                    cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf)
                    cmd += " -c 'address-family {} {}'".format(af, ip_type)
                    cmd += " -c 'no vni {}'".format(vni)
                    if not self.__run_command(table, cmd):
                        syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI unconfig command')
                        continue
                else:
                    if not data:
                        cmd = "vtysh -c 'configure terminal'"
                        cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf)
                        cmd += " -c 'address-family {} {}'".format(af, ip_type)
                        cmd += " -c 'vni {}'".format(vni)
                        if not self.__run_command(table, cmd):
                            syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI config command')
                            continue
            elif table == 'BGP_GLOBALS_EVPN_RT':
                af_type, rt = key.split('|')
                af, ip_type = af_type.lower().split('_')
                nostr = "no " if del_table else ""
                syslog.syslog(syslog.LOG_INFO, 'Set address family for RT {} to {} {}'.format(rt, af, ip_type))
                cmd = "vtysh -c 'configure terminal'"
                cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf)
                cmd += " -c 'address-family {} {}'".format(af, ip_type)
                cmd += " -c '{}route-target {} {}'".format(nostr,data['route-target-type'].data, rt)
                cache_tbl_key = 'BGP_GLOBALS_EVPN_RT&&{}|L2VPN_EVPN|{}'.format(vrf, rt)
                if not del_table and cache_tbl_key in self.table_data_cache.keys():
                    new_rttype = data['route-target-type'].data
                    cache_tbl_data = self.table_data_cache[cache_tbl_key]
                    if 'route-target-type' in cache_tbl_data:
                        old_rttype = cache_tbl_data['route-target-type']
                        if new_rttype == "export":
                            if old_rttype == "import" or old_rttype == "both":
                                cmd += " -c 'no route-target import {}'".format(rt)
                        if new_rttype == "import":
                            if old_rttype == "export" or old_rttype == "both":
                                cmd += " -c 'no route-target export {}'".format(rt)
                if not self.__run_command(table, cmd):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN RT config command')
                    continue
                else:
                    data['route-target-type'].status = CachedDataWithOp.STAT_SUCC
            elif table == 'BGP_GLOBALS_EVPN_VNI_RT':
                af_type, vni, rt = key.split('|')
                af, ip_type = af_type.lower().split('_')
                nostr = "no " if del_table else ""
                syslog.syslog(syslog.LOG_INFO, 'Set address family for VNI {} RT {} to {} {}'.format(vni, rt, af, ip_type))
                cmd = "vtysh -c 'configure terminal'"
                cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf)
                cmd += " -c 'address-family {} {}'".format(af, ip_type)
                cmd += " -c 'vni {}'".format(vni)
                cmd += " -c '{}route-target {} {}'".format(nostr,data['route-target-type'].data, rt)
                cache_tbl_key = 'BGP_GLOBALS_EVPN_VNI_RT&&{}|L2VPN_EVPN|{}|{}'.format(vrf, vni, rt)
                if not del_table and cache_tbl_key in self.table_data_cache.keys():
                    new_rttype = data['route-target-type'].data
                    cache_tbl_data = self.table_data_cache[cache_tbl_key]
                    if 'route-target-type' in cache_tbl_data:
                        old_rttype = cache_tbl_data['route-target-type']
                        if new_rttype == "export":
                            if old_rttype == "import" or old_rttype == "both":
                                cmd += " -c 'no route-target import {}'".format(rt)
                        if new_rttype == "import":
                            if old_rttype == "export" or old_rttype == "both":
                                cmd += " -c 'no route-target export {}'".format(rt)
                if not self.__run_command(table, cmd):
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI RT config command')
                    continue
                else:
                    data['route-target-type'].status = CachedDataWithOp.STAT_SUCC
            elif table == 'ROUTE_MAP':
                map_name = prefix
                seq_no = key
                if not del_table:
                    if 'route_operation' in data:
                        dval = data['route_operation']
                        if dval.op != CachedDataWithOp.OP_NONE:
                            enable = (dval.op != CachedDataWithOp.OP_DELETE)
                            no_arg = CommandArgument(self, enable)
                            command = "vtysh -c 'configure terminal' -c '{:no-prefix}route-map {} {} {}'".\
                                       format(no_arg, map_name, dval.data, seq_no)
                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to configure route-map {} seq {}'.format(map_name, seq_no))
                                continue
                            if dval.op == CachedDataWithOp.OP_DELETE:
                                self.__delete_route_map(map_name, seq_no, data)
                                continue
                            self.route_map.setdefault(map_name, {})[seq_no] = dval.data
                            for k, v in data.items():
                                if v.op == CachedDataWithOp.OP_NONE:
                                    v.op = CachedDataWithOp.OP_UPDATE
                        dval.status = CachedDataWithOp.STAT_SUCC
                    if map_name not in self.route_map or seq_no not in self.route_map[map_name]:
                        syslog.syslog(syslog.LOG_ERR, 'route-map {} seq {} not found for update'.format(map_name, seq_no))
                        continue
                    cmd_prefix = ['configure terminal',
                                  'route-map {} {} {}'.format(map_name, self.route_map[map_name][seq_no], seq_no)]
                    if not key_map.run_command(self, table, data, cmd_prefix):
                        syslog.syslog(syslog.LOG_ERR, 'failed running route-map config command')
                        continue
                else:
                    if map_name not in self.route_map or seq_no not in self.route_map[map_name]:
                        syslog.syslog(syslog.LOG_ERR, 'route-map {} seq {} not found for delete'.format(map_name, seq_no))
                        continue
                    command = "vtysh -c 'configure terminal' -c 'no route-map {} {} {}'".\
                               format(map_name, self.route_map[map_name][seq_no], seq_no)
                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed running route-map delete command')
                        continue
                    self.__delete_route_map(map_name, seq_no, data)
            elif table == 'ROUTE_REDISTRIBUTE':
                src_proto, dst_proto, af = key.split('|')
                if af == 'ipv6' and src_proto == 'ospf3':
                    src_proto = 'ospf6'
                ip_type = 'unicast'
                syslog.syslog(syslog.LOG_INFO, 'Set route distribute for src_proto {} dst_proto {} {}'.\
                                format(src_proto, dst_proto, af, ip_type))
                if dst_proto != 'bgp':
                    syslog.syslog(syslog.LOG_ERR, 'only bgp could be used as dst protocol, but {} was given'.format(dst_proto))
                    continue
                op = CachedDataWithOp.OP_DELETE if del_table else CachedDataWithOp.OP_UPDATE
                data['protocol'] = CachedDataWithOp(src_proto, op)
                cmd_prefix = ['configure terminal',
                              'router bgp {} vrf {}'.format(local_asn, vrf),
                              'address-family {} {}'.format(af, ip_type)]
                ret_val = key_map.run_command(self, table, data, cmd_prefix)
                del(data['protocol'])
                if not ret_val:
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP route redistribute config command')
                    continue
            elif table == 'BGP_GLOBALS_AF_AGGREGATE_ADDR' or table == 'BGP_GLOBALS_AF_NETWORK':
                af_type, ip_prefix = key.split('|')
                af, ip_type = af_type.lower().split('_')
                norm_ip_prefix = MatchPrefix.normalize_ip_prefix((socket.AF_INET if af == 'ipv4' else socket.AF_INET6), ip_prefix)
                if norm_ip_prefix is None:
                    syslog.syslog(syslog.LOG_ERR, 'invalid IP prefix format %s for af %s' % (ip_prefix, af))
                    continue
                syslog.syslog(syslog.LOG_INFO, 'Set address family for IP prefix {} to {} {}'.format(norm_ip_prefix, af, ip_type))
                op = CachedDataWithOp.OP_DELETE if del_table else CachedDataWithOp.OP_UPDATE
                data['ip_prefix'] = CachedDataWithOp(norm_ip_prefix, op)
                cmd_prefix = ['configure terminal',
                              'router bgp {} vrf {}'.format(local_asn, vrf),
                              'address-family {} {}'.format(af, ip_type)]
                ret_val = key_map.run_command(self, table, data, cmd_prefix, vrf, af)
                del(data['ip_prefix'])
                if not ret_val:
                    syslog.syslog(syslog.LOG_ERR, 'failed running BGP IP prefix AF config command')
                    continue
                if table == 'BGP_GLOBALS_AF_AGGREGATE_ADDR':
                    if not del_table:
                        aggr_obj = AggregateAddr()
                        for attr in ['as_set', 'summary_only']:
                            if attr in data and data[attr].op != CachedDataWithOp.OP_DELETE and data[attr].data == 'true':
                                setattr(aggr_obj, attr, True)
                        self.af_aggr_list.setdefault(vrf, {})[norm_ip_prefix] = aggr_obj
                    else:
                        if vrf in self.af_aggr_list:
                            self.af_aggr_list[vrf].pop(norm_ip_prefix, None)

            elif table == 'BFD_PEER_SINGLE_HOP':
                key = prefix + '|' + key
                remoteaddr, interface, vrf, localaddr = key.split('|')
                if not del_table:
                    if not 'null' in localaddr:
                        syslog.syslog(syslog.LOG_INFO, 'Set BFD single hop peer {} {} {} {}'.format(remoteaddr, vrf, interface, localaddr))

                        suffix_cmd, oper = self.__bfd_handle_delete (data)
                        if suffix_cmd and oper == CachedDataWithOp.OP_DELETE:
                            command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} local-address {} vrf {} interface {}' -c '{}'".\
                            format(remoteaddr, localaddr, vrf, interface, suffix_cmd)

                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key))
                                continue
                        else:
                            cmd_prefix = ['configure terminal',
                                          'bfd',
                                          'peer {} local-address {} vrf {} interface {}'.format(remoteaddr, localaddr, vrf, interface)]
                            if not key_map.run_command(self, table, data, cmd_prefix):
                                syslog.syslog(syslog.LOG_ERR, 'failed running BFD single-hop config command')
                                continue

                    else:
                        syslog.syslog(syslog.LOG_INFO, 'Set BFD single hop peer {} {} {}'.format(remoteaddr, vrf, interface))

                        suffix_cmd, oper = self.__bfd_handle_delete (data)

                        if suffix_cmd and oper == CachedDataWithOp.OP_DELETE:
                            command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} vrf {} interface {}' -c '{}'".\
                            format(remoteaddr, vrf, interface, suffix_cmd)

                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key))
                                continue
                        else:
                            syslog.syslog(syslog.LOG_INFO, 'Set BFD single hop peer {} {} {}'.format(remoteaddr, vrf, interface))
                            cmd_prefix = ['configure terminal',
                                          'bfd',
                                          'peer {} vrf {} interface {}'.format(remoteaddr, vrf, interface)]
                            if not key_map.run_command(self, table, data, cmd_prefix):
                                syslog.syslog(syslog.LOG_ERR, 'failed running BFD single-hop config command')
                                continue
                else:
                    if 'local-address' in data:
                        dval = data['local-address']
                        localaddr = dval.data
                        syslog.syslog(syslog.LOG_INFO, 'Delete BFD single hop to {} {} {}'.format(remoteaddr, vrf, interface, localaddr))
                        command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} local-address {} vrf {} interface {}'".\
                            format(remoteaddr, localaddr, vrf, interface)
                    else:
                        syslog.syslog(syslog.LOG_INFO, 'Delete BFD single hop to {} {} {}'.format(remoteaddr, vrf, interface))
                        command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} vrf {} interface {}'".\
                            format(remoteaddr, vrf, interface)
                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key))
                        continue
                    self.__delete_bfd_peer(data)
            elif table == 'BFD_PEER_MULTI_HOP':
                key = prefix + '|' + key
                remoteaddr, interface, vrf, localaddr = key.split('|')
                if not del_table:
                    syslog.syslog(syslog.LOG_INFO, 'Set BFD multi hop to {} {} {} {}'.format(remoteaddr, interface, vrf, localaddr))
                    suffix_cmd, oper = self.__bfd_handle_delete (data)
                    if suffix_cmd and oper == CachedDataWithOp.OP_DELETE:
                        if not 'null' in interface:
                            command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} local-address {} vrf {} interface {}' -c '{}'".\
                            format(remoteaddr, localaddr, vrf, interface, suffix_cmd)
                        else:
                            command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} local-address {} vrf {}' -c '{}'".\
                            format(remoteaddr, localaddr, vrf, suffix_cmd)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key))
                            continue
                    else:
                        if not 'null' in interface:
                            cmd_prefix = ['configure terminal',
                                          'bfd',
                                                'peer {} vrf {} multihop local-address {} interface {}'.format(remoteaddr, vrf, localaddr, interface)]
                        else:
                            cmd_prefix = ['configure terminal',
                                          'bfd',
                                          'peer {} vrf {} multihop local-address {}'.format(remoteaddr, vrf, localaddr)]

                        if not key_map.run_command(self, table, data, cmd_prefix):
                            syslog.syslog(syslog.LOG_ERR, 'failed running BFD multi-hop config command')
                            continue
                else:
                    syslog.syslog(syslog.LOG_INFO, 'Delete BFD multi hop to {} {} {} {}'.format(remoteaddr, vrf, localaddr, interface))
                    if not 'null' in interface:
                        command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} vrf {} multihop local-address {} interface {}'".\
                        format(remoteaddr, vrf, localaddr, interface)
                    else:
                        command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} vrf {} multihop local-address {}'".\
                        format(remoteaddr, vrf, localaddr)

                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete multihop peer {}'.format(key))
                        continue
                    self.__delete_bfd_peer(data)
            elif table == 'IP_SLA':
                sla_id = prefix
                icmp_config = False
                tcp_config = False
                cmd_prefix = ['configure terminal']
                ipsla_table = self.config_db.get_table('IP_SLA')
                syslog.syslog(syslog.LOG_INFO, 'Config ip sla data {}'.format(data))
                found_in_configdb = False
                for key, entry in ipsla_table.items():
                    ipsla_id = key
                    if sla_id == ipsla_id:
                        found_in_configdb = True
                        break
                syslog.syslog(syslog.LOG_INFO, 'Config ip sla found_in_configdb {}'.format(found_in_configdb))
                if 'icmp_source_interface' in data or 'icmp_source_ip' in data or  'icmp_size' in data or 'icmp_dst_ip' in data or 'icmp_vrf' in data or 'icmp_ttl' in data or 'icmp_tos' in data:
                    cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id)]
                    icmp_config = True
                    for key, entry in ipsla_table.items():
                        ipsla_id = key
                        if sla_id == ipsla_id:
                            if 'icmp_dst_ip' in entry:
                                icmp_cmd = ("icmp", "echo")
                                icmp_cmd_str = "-".join(icmp_cmd)
                                icmp_cmd_mode = icmp_cmd_str + " " + entry['icmp_dst_ip']
                                syslog.syslog(syslog.LOG_INFO, 'Data: icmp_cmd_str %s icmp_cmd_mode %s' % (icmp_cmd_str, icmp_cmd_mode))
                                 
                                cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id), icmp_cmd_mode]
                                chk_icmp_attrs = ['icmp_source_interface', 'icmp_source_ip', 'icmp_size', 'icmp_vrf', 'icmp_tos', 'icmp_ttl']
                                chk_icmp_attrs_dict = {'icmp_source_interface':'source-interface ', 'icmp_source_ip':'source-address ', 'icmp_size':'request-data-size ', 'icmp_vrf':'source-vrf ', 'icmp_tos':'tos ', 'icmp_ttl':'ttl '}
                                for attr in chk_icmp_attrs:
                                    if attr in data and data[attr].op != CachedDataWithOp.OP_DELETE:
                                        command = "vtysh -c 'configure terminal' -c 'ip sla {}' -c '{}' -c '{} {}'".\
                                        format(sla_id, icmp_cmd_mode, chk_icmp_attrs_dict[attr], data[attr].data)
                                        syslog.syslog(syslog.LOG_INFO, 'Execute Icmp Cmd {}'.format(command))
                                        if not self.__run_command(table, command):
                                            syslog.syslog(syslog.LOG_ERR, 'failed to add icmp config for  ip sla {}'.format(sla_id))
                                            continue
 
                    syslog.syslog(syslog.LOG_INFO, 'Done with Icmp {}'.format(sla_id))
                    if not key_map.run_command(self, table, data, cmd_prefix, sla_id):
                        syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command')
                        continue
                if 'tcp_source_interface' in data or 'tcp_source_port' in data or 'tcp_source_ip' in data or 'tcp_dst_ip' in data or 'tcp_dst_port' in data or 'tcp_vrf' in data or 'tcp_ttl' in data or 'tcp_tos' in data:
                    cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id)]
                    tcp_config = True
                    for key, entry in ipsla_table.items():
                        ipsla_id = key
                        if sla_id == ipsla_id:
                            if 'tcp_dst_ip' in entry and 'tcp_dst_port' in entry:
                                tcp_cmd = ("tcp", "connect")
                                tcp_cmd_str = "-".join(tcp_cmd)
                                tcp_cmd_mode = tcp_cmd_str + " " + entry['tcp_dst_ip'] + " port " + entry['tcp_dst_port']
                                syslog.syslog(syslog.LOG_INFO, 'Init Config DB Data: tcp_cmd_str %s tcp_cmd_mode %s' % (tcp_cmd_str, tcp_cmd_mode))
                                cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id), tcp_cmd_mode]
                                chk_tcp_attrs = ['tcp_source_interface', 'tcp_source_ip', 'tcp_source_port', 'tcp_vrf', 'tcp_tos', 'tcp_ttl']
                                chk_tcp_attrs_dict = {'tcp_source_interface':'source-interface ', 'tcp_source_ip':'source-address ', 'tcp_source_port':'source-port ', 'tcp_vrf':'source-vrf ', 'tcp_tos':'tos ', 'tcp_ttl':'ttl '}
                                for attr in chk_tcp_attrs:
                                    if attr in data and data[attr].op != CachedDataWithOp.OP_DELETE:
                                        command = "vtysh -c 'configure terminal' -c 'ip sla {}' -c '{}' -c '{} {}'".\
                                        format(sla_id, tcp_cmd_mode, chk_tcp_attrs_dict[attr], data[attr].data)
                                        syslog.syslog(syslog.LOG_INFO, 'Execute Tcp Cmd {}'.format(command))
                                        if not self.__run_command(table, command):
                                            syslog.syslog(syslog.LOG_ERR, 'failed to add Tcp config for  ip sla {}'.format(sla_id))
                                            continue
 
                    syslog.syslog(syslog.LOG_INFO, 'Done with Tcp {}'.format(sla_id))
                    if not key_map.run_command(self, table, data, cmd_prefix, sla_id):
                        syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command')
                        continue
                if 'frequency' in data or 'threshold' in data or 'timeout' in data:
                    syslog.syslog(syslog.LOG_INFO, 'ip sla mode Configure freq/thresh/timeout for sla {}'.format(sla_id))
                    cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id)]
                    if not key_map.run_command(self, table, data, cmd_prefix, sla_id):
                        syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command')
                        continue
 
                elif icmp_config == False or tcp_config == False:
                    syslog.syslog(syslog.LOG_INFO, 'Basic mode Configure for ip sla {}'.format(sla_id))
                    cmd_prefix = ['configure terminal']

                # Always delete ip sla if it is not found in configdb
                if not found_in_configdb:
                    command = "vtysh -c 'configure terminal' -c 'no ip sla {}'".format(sla_id)
                    syslog.syslog(syslog.LOG_ERR, 'Entry deleted in ip sla config db')
                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete router ip sla {}'.format(sla_id))
                        continue
                elif not key_map.run_command(self, table, data, cmd_prefix, sla_id):
                    syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command')
                    continue

            elif table == 'OSPFV2_ROUTER':
                vrf = prefix
                if not del_table:
                    syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf))
                
                    cmd_prefix = ['configure terminal',
                                  'router ospf vrf {}'.format(vrf)]

                    if not key_map.run_command(self, table, data, cmd_prefix):
                        syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command')
                        continue
                else:
                    command = "vtysh -c 'configure terminal' -c 'no router ospf vrf {}'".format(vrf)

                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete router ospf vrf {}'.format(vrf))
                        continue
                    else:
                        self.__ospf_delete(data)

            elif table == 'OSPFV2_ROUTER_AREA':
                vrf = prefix
                syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf))

                cmd_prefix = ['configure terminal',
                              'router ospf vrf {}'.format(vrf)]

                if not key_map.run_command(self, table, data, cmd_prefix, key):
                    syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command')
                    continue
            elif table == 'OSPFV2_ROUTER_AREA_VIRTUAL_LINK':
                vrf = prefix
          
                keyvals = key.split('|')
                area = keyvals[0]
                vlinkid = keyvals[1]

                syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}, Vlink: {}, tableop {}'.format(vrf, data, del_table))

                if data == {}:
                    command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no area {} virtual-link {}'".\
                    format(vrf, area, vlinkid)

                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete vlink {} {}'.format(area, vlinkid))
                        continue
                    else:
                        self.__ospf_delete(data)
                else:
                    cmd_prefix = ['configure terminal',
                                  'router ospf vrf {}'.format(vrf)]

                    if not key_map.run_command(self, table, data, cmd_prefix, area, vlinkid):
                        syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command')
                        continue

                    if del_table:
                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no area {} virtual-link {}'".\
                        format(vrf, area, vlinkid)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to delete vlink {} {}'.format(area, vlinkid))
                            continue
                        else:
                            self.__ospf_delete(data)

            elif table == 'OSPFV2_ROUTER_AREA_NETWORK':
                vrf = prefix
                syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf))

                keyvals = key.split('|')
                area = keyvals[0]
                network = keyvals[1]
                   
                if not del_table: 
                    command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'network {} area {}'".\
                    format(vrf, network, area)

                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to create network {} {}'.format(area, network))
                        continue
                else:
                    command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no network {} area {}'".\
                    format(vrf, network, area)

                    if not self.__run_command(table, command):
                        syslog.syslog(syslog.LOG_ERR, 'failed to delete network {} {}'.format(area, network))
                        continue
                    else:
                        self.__ospf_delete(data)

            elif table == 'OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE':
                vrf = prefix

                keyvals = key.split('|')
                area = keyvals[0]
                range = keyvals[1]

                syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf))

                if data == {}:
                   if not del_table:
                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'area {} range {}'".\
                        format(vrf, area, range)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to create range {} {}'.format(area, range))
                            continue
                   else:
                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no area {} range {}'".\
                        format(vrf, area, range)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to delete range {} {}'.format(area, range))
                            continue
                        else:
                            self.__ospf_delete(data)
                else:
                    cmd_prefix = ['configure terminal',
                              'router ospf vrf {}'.format(vrf)]

                    if not key_map.run_command(self, table, data, cmd_prefix, area, range):
                        syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command')
                        continue

            elif table == 'OSPFV2_ROUTER_DISTRIBUTE_ROUTE':
                vrf = prefix

                keyvals = key.split('|')
                protocol = keyvals[0]
                direction = keyvals[1]

                if (protocol == "DIRECTLY_CONNECTED"):
                    protocol = "CONNECTED"

                syslog.syslog(syslog.LOG_INFO, 'Create redistribute-list {} {}'.format(protocol, direction))

                cmd_suffix = ""
                del_cmd_suffix = ""
                cmd_oper = ""
                rmapcmd = ""
                metriccmd = ""
                metrictypecmd = ""
                alwayscmd = ""
                acclistname = ""
                rmapoper = ""
                metricoper = ""
                metrictypeoper = ""
                alwaysoper = ""
                acclistoper = ""

                if 'route-map' in data:
                    dval = data['route-map']
                    rmapoper = dval.op
                    rmapcmd = " route-map {}".format(dval.data)

                if 'access-list' in data:
                    dval = data['access-list']
                    acclistoper = dval.op
                    acclistname = dval.data

                if 'metric' in data:
                    dval = data['metric']
                    metricoper = dval.op
                    metriccmd = " metric {}".format(dval.data)

                if 'metric-type' in data:
                    dval = data['metric-type']
                    metrictypeoper = dval.op

                    if dval.data == "TYPE_1":
                        metrictypecmd = " metric-type 1"
                    else:
                        metrictypecmd = " metric-type 2"

                if 'always' in data:
                    dval = data['always']
                    alwaysoper = dval.op
                    alwayscmd = " always"

                if not del_table:

                    if ((rmapoper == CachedDataWithOp.OP_DELETE) or
                        (metricoper == CachedDataWithOp.OP_DELETE) or
                        (metrictypeoper == CachedDataWithOp.OP_DELETE) or
                        (alwaysoper == CachedDataWithOp.OP_DELETE) or
                        (acclistoper == CachedDataWithOp.OP_DELETE)):

                        cmd_oper = "no"
                    
                        if (alwaysoper == CachedDataWithOp.OP_DELETE):
                            del_cmd_suffix = alwayscmd
                        if (rmapoper == CachedDataWithOp.OP_DELETE):
                            del_cmd_suffix = rmapcmd
                        if (metricoper == CachedDataWithOp.OP_DELETE):
                            del_cmd_suffix = metriccmd
                        if (metrictypeoper == CachedDataWithOp.OP_DELETE):
                            del_cmd_suffix = metrictypecmd

                    if (direction == "EXPORT"):
                        if (cmd_oper != "no"):
                            cmd_suffix = "distribute-list {} out {}".format(acclistname, protocol.lower())
                        else:
                            cmd_suffix = "no distribute-list {} out {}".format(acclistname, protocol.lower())

                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c '{}'".\
                            format(vrf, cmd_suffix)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to create distribute-list {} {}'.format(protocol, direction))
                            continue
                        else:
                            self.__ospf_apply_config(data, rmapoper, metricoper, metrictypeoper, alwaysoper, acclistoper)
                    elif (direction == "IMPORT"):
                        if (cmd_oper != "no"):
                            if (protocol == "DEFAULT_ROUTE"):
                                cmd_suffix = cmd_suffix + "default-information originate" + alwayscmd + rmapcmd + metriccmd + metrictypecmd
                            else:
                                cmd_suffix = cmd_suffix + "redistribute {}".format(protocol.lower()) + rmapcmd + metriccmd + metrictypecmd
                        else:
                            if (protocol == "DEFAULT_ROUTE"):
                                cmd_suffix = "no default-information originate" + del_cmd_suffix
                            else:
                                cmd_suffix = "no redistribute {}".format(protocol.lower()) + del_cmd_suffix

                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c '{}'".\
                            format(vrf, cmd_suffix)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to create default-info/redistribute {} {}'.format(protocol, direction))
                            continue
                        else:
                            self.__ospf_apply_config(data, rmapoper, metricoper, metrictypeoper, alwaysoper, acclistoper)
                else:
                    if (direction == "IMPORT"):
                        command = ""
                        if (protocol == "DEFAULT_ROUTE"):
                            command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no default-information originate'".\
                            format(vrf)
                        else:
                            command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no redistribute {}'".\
                            format(vrf, protocol.lower())

                        if (command != ""):
                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to delete default-info/redistribute {}'.format(protocol.lower()))
                                continue
                            else:
                                self.__ospf_delete(data)
                    else:
                        if (acclistname != ""):
                            command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no distribute-list {} out {}'".\
                            format(vrf, acclistname, protocol.lower())

                            if not self.__run_command(table, command):
                                syslog.syslog(syslog.LOG_ERR, 'failed to delete distribute-list {} {}'.format(protocol, direction))
                                continue
                            
                        self.__ospf_delete(data)
 
            elif table == 'OSPFV2_INTERFACE':

                key = prefix + '|' + key
                if_name, if_addr = key.split('|')

                vrf = ""
                if 'vrf_name' in data :
                   vrf = 'vrf {}'.format(data['vrf_name'].data)

                cmd_prefix = ['configure terminal',
                              'interface {} {}'.format(if_name, vrf) ]

                if del_table and len(data) == 0:
                    syslog.syslog(syslog.LOG_INFO, 'Delete table {} {} data {}'.format(key, vrf, data))

                    cmd_data = {}
                    cache_tbl_key = 'OSPFV2_INTERFACE&&{}|{}'.format(if_name, if_addr)
                    syslog.syslog(syslog.LOG_INFO, 'Row delete key {}'.format(cache_tbl_key))

                    if cache_tbl_key in self.table_data_cache.keys():
                        cache_tbl_data = self.table_data_cache[cache_tbl_key]
                        syslog.syslog(syslog.LOG_INFO, 'Row delete cached data {} '.format(cache_tbl_data))

                        for key, data in cache_tbl_data.items() :
                            cached_op_data = CachedDataWithOp(data, CachedDataWithOp.OP_DELETE)
                            cmd_data.update({ key : cached_op_data } ) 

                    syslog.syslog(syslog.LOG_INFO, 'Row delete cmd data {} '.format(cmd_data))

                    if len(cmd_data) :
                        if not key_map.run_command(self, table, cmd_data, cmd_prefix, if_name, if_addr):
                            syslog.syslog(syslog.LOG_INFO, 'failed running interface no ip ospf config command')
                            self.__apply_config_delete_success(cmd_data)
                            continue
                    else :
                        self.__apply_config_delete_success(cmd_data)

                else :
                    syslog.syslog(syslog.LOG_INFO, 'Create/update ospf {} interface {} in {}'.format(key, if_name, vrf))

                    #Work arround for router area config fail, update area every time
                    if 'area-id' in data.keys():
                        dval = data['area-id']
                        if dval.op == CachedDataWithOp.OP_NONE :
                            dval.op = CachedDataWithOp.OP_ADD 

                    if not key_map.run_command(self, table, data, cmd_prefix, if_name, if_addr):
                        syslog.syslog(syslog.LOG_ERR, 'failed running interface ip ospf config command')
                        if 'area-id' in data.keys():
                            dval = data['area-id']
                            if dval.op == CachedDataWithOp.OP_DELETE:
                                #Work arround for router area config delete fail
                                self.__apply_config_op_success(data, {'area-id': dval.op } )
                                syslog.syslog(syslog.LOG_INFO, 'area-id delete enforced')
                        continue
                    else :
                        self.__apply_config_op_success(data) 

            elif table == 'OSPFV2_ROUTER_PASSIVE_INTERFACE':
                syslog.syslog(syslog.LOG_INFO, 'Create passive interface')

                vrf = prefix

                keyvals = key.split('|')
                if_name = keyvals[0]
                if_addr = keyvals[1]

                syslog.syslog(syslog.LOG_INFO, 'Create passive interface vrf {}'.format(vrf))

                if (if_addr == "0.0.0.0"):
                    if_addr = ""

                if data == {}:
                   if not del_table:

                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'passive-interface {} {}'".\
                        format(vrf, if_name, if_addr)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to create passive interface {} {}'.format(if_name, if_addr))
                            continue
                   else:
                        command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no passive-interface {} {}'".\
                        format(vrf, if_name, if_addr)

                        if not self.__run_command(table, command):
                            syslog.syslog(syslog.LOG_ERR, 'failed to delete passive interface {} {}'.format(if_name, if_addr))
                            continue

            elif table == 'STATIC_ROUTE':
                vrf = prefix
                syslog.syslog(syslog.LOG_INFO, 'Set static IP route for vrf {} prefix {}'.format(vrf, key))
                op = CachedDataWithOp.OP_DELETE if del_table else CachedDataWithOp.OP_UPDATE
                data['ip_prefix'] = CachedDataWithOp(key, op)
                cmd_prefix = ['configure terminal', 'vrf {}'.format(vrf)]
                ret_val = key_map.run_command(self, table, data, cmd_prefix, vrf)
                del(data['ip_prefix'])
                if not ret_val:
                    syslog.syslog(syslog.LOG_ERR, 'failed running static route config command')
                    continue
                self.static_route_list.setdefault(vrf, {})[key] = self.upd_nh_set
            elif table == 'PIM_INTERFACE':

                vrf = prefix
                af, if_name = key.split('|')
                syslog.syslog(syslog.LOG_INFO,
                              'PIM interface update for vrf {}, af: {}, interface {}'.format(vrf, af, if_name))
                cmd_prefix = ['configure terminal',
                              'interface {}'.format(if_name)]
                syslog.syslog(syslog.LOG_INFO,
                              'Create/update PIM interface: key {} interface {} in {}'.format(key, if_name, vrf))

                # If sparse-mode has been disabled, clear other interface
                # entries in cache so that they will be re-programmed in FRR
                # on re-enabling of sparse-mode.

                if 'mode' in data:
                    modeval = data['mode']
                    modeval_pim_mode = modeval.data
                    modeval_op = modeval.op
                    if (modeval_op == CachedDataWithOp.OP_DELETE):
                        syslog.syslog(syslog.LOG_INFO,
                                      "Flushing PIM interface cache for deletion "
                                      "of PIM sparse-mode")
                        for dkey, dval in data.items():
                            dval.status = CachedDataWithOp.STAT_SUCC
                            dval.op = CachedDataWithOp.OP_DELETE

                    # Only send the VTYSH command to FRR if the PIM interface mode
                    # is present in the update.
                    if not key_map.run_command(self, table, data, cmd_prefix):
                        syslog.syslog(syslog.LOG_ERR, 'failed running PIM config command')
                        continue

            elif table == 'PIM_GLOBALS':

                vrf = prefix

                af = key.split('|')
                syslog.syslog(syslog.LOG_INFO,
                              'PIM global update for vrf {}, af: {}'.format(vrf, af))

                cmd_prefix = ['configure terminal',
                              'vrf {}'.format(vrf)]

                syslog.syslog(syslog.LOG_INFO,
                              'Create/update PIM global {} af {} in {}'.format(key, af, vrf))

                # if not key_map.run_command(self, table, data, cmd_prefix, vrf, af):
                if not key_map.run_command(self, table, data, cmd_prefix):
                    syslog.syslog(syslog.LOG_ERR, 'failed running PIM config command')
                    continue

            elif table == 'IGMP_INTERFACE':
                ifname = prefix

                syslog.syslog(syslog.LOG_INFO, 'IGMP Interface MCast Grp ifname {} prefix {}'.format(ifname, key))

                keyvals = key.split('|')
                mcast_grp = keyvals[0]
                source_ip = keyvals[1]

                syslog.syslog(syslog.LOG_INFO, 'Configure ip igmp join interface {}, mcast_grp {}, source_ip {}'.format(ifname, mcast_grp, source_ip))

                cmd_prefix = ['configure terminal',
                          'interface {}'.format(ifname)]

                if not key_map.run_command(self, table, data, cmd_prefix, mcast_grp, source_ip):
                    syslog.syslog(syslog.LOG_ERR, 'failed running ip igmp join config command')
                    continue


            elif table == 'IGMP_INTERFACE_QUERY':
                ifname = prefix

                syslog.syslog(syslog.LOG_INFO, 'IGMP Interface {} Config prefix {}'.format(ifname, key))

                cmd_prefix = ['configure terminal',
                          'interface {}'.format(ifname)]

                if not key_map.run_command(self, table, data, cmd_prefix):
                    syslog.syslog(syslog.LOG_ERR, 'failed running ip igmp interface config command')
                    continue