]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_routemap.c
Merge pull request #3394 from karamalla0406/frr3360
[mirror_frr.git] / bgpd / bgp_routemap.c
index 8e7c0a69dd4a77d78ffd5f75ad938225a6cd787a..fc27c546b464be1206d0405e27737013c131a10d 100644 (file)
@@ -233,7 +233,7 @@ struct bgp_match_peer_compiled {
 /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
 
 /* Compares the peer specified in the 'match peer' clause with the peer
-    received in bgp_info->peer. If it is the same, or if the peer structure
+    received in bgp_path_info->peer. If it is the same, or if the peer structure
     received is a peer_group containing it, returns RMAP_MATCH. */
 static route_map_result_t route_match_peer(void *rule,
                                           const struct prefix *prefix,
@@ -251,7 +251,7 @@ static route_map_result_t route_match_peer(void *rule,
        if (type == RMAP_BGP) {
                pc = rule;
                su = &pc->su;
-               peer = ((struct bgp_info *)object)->peer;
+               peer = ((struct bgp_path_info *)object)->peer;
 
                if (pc->interface) {
                        if (!peer->conf_if)
@@ -341,7 +341,7 @@ static route_map_result_t route_match_command(void *rule,
        u_int32_t locpref = 0;
        u_int32_t newlocpref = 0;
        enum lua_rm_status lrm_status;
-       struct bgp_info *info = (struct bgp_info *)object;
+       struct bgp_path_info *path = (struct bgp_path_info *)object;
        lua_State *L = lua_initialize("/etc/frr/lua.scr");
 
        if (L == NULL)
@@ -354,18 +354,18 @@ static route_map_result_t route_match_command(void *rule,
 
        zlog_debug("Set up prefix table");
        /*
-        * Setup the bgp_info information
+        * Setup the bgp_path_info information
         */
        lua_newtable(L);
-       lua_pushinteger(L, info->attr->med);
+       lua_pushinteger(L, path->attr->med);
        lua_setfield(L, -2, "metric");
-       lua_pushinteger(L, info->attr->nh_ifindex);
+       lua_pushinteger(L, path->attr->nh_ifindex);
        lua_setfield(L, -2, "ifindex");
-       lua_pushstring(L, info->attr->aspath->str);
+       lua_pushstring(L, path->attr->aspath->str);
        lua_setfield(L, -2, "aspath");
-       lua_pushinteger(L, info->attr->local_pref);
+       lua_pushinteger(L, path->attr->local_pref);
        lua_setfield(L, -2, "localpref");
-       zlog_debug("%s %d", info->attr->aspath->str, info->attr->nh_ifindex);
+       zlog_debug("%s %d", path->attr->aspath->str, path->attr->nh_ifindex);
        lua_setglobal(L, "nexthop");
 
        zlog_debug("Set up nexthop information");
@@ -383,16 +383,16 @@ static route_map_result_t route_match_command(void *rule,
        case LUA_RM_MATCH_AND_CHANGE:
                zlog_debug("MATCH AND CHANGE");
                lua_getglobal(L, "nexthop");
-               info->attr->med = get_integer(L, "metric");
+               path->attr->med = get_integer(L, "metric");
                /*
                 * This needs to be abstraced with the set function
                 */
-               if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
-                       locpref = info->attr->local_pref;
+               if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
+                       locpref = path->attr->local_pref;
                newlocpref = get_integer(L, "localpref");
                if (newlocpref != locpref) {
-                       info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
-                       info->attr->local_pref = newlocpref;
+                       path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+                       path->attr->local_pref = newlocpref;
                }
                status = RMAP_MATCH;
                break;
@@ -477,13 +477,13 @@ static route_map_result_t route_match_ip_next_hop(void *rule,
                                                  void *object)
 {
        struct access_list *alist;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct prefix_ipv4 p;
 
        if (type == RMAP_BGP && prefix->family == AF_INET) {
-               bgp_info = object;
+               path = object;
                p.family = AF_INET;
-               p.prefix = bgp_info->attr->nexthop;
+               p.prefix = path->attr->nexthop;
                p.prefixlen = IPV4_MAX_BITLEN;
 
                alist = access_list_lookup(AFI_IP, (char *)rule);
@@ -524,13 +524,13 @@ static route_map_result_t route_match_ip_route_source(void *rule,
                                                      void *object)
 {
        struct access_list *alist;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct peer *peer;
        struct prefix_ipv4 p;
 
        if (type == RMAP_BGP && pfx->family == AF_INET) {
-               bgp_info = object;
-               peer = bgp_info->peer;
+               path = object;
+               peer = path->peer;
 
                if (!peer || sockunion_family(&peer->su) != AF_INET)
                        return RMAP_NOMATCH;
@@ -610,13 +610,13 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
                                    route_map_object_t type, void *object)
 {
        struct prefix_list *plist;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct prefix_ipv4 p;
 
        if (type == RMAP_BGP && prefix->family == AF_INET) {
-               bgp_info = object;
+               path = object;
                p.family = AF_INET;
-               p.prefix = bgp_info->attr->nexthop;
+               p.prefix = path->attr->nexthop;
                p.prefixlen = IPV4_MAX_BITLEN;
 
                plist = prefix_list_lookup(AFI_IP, (char *)rule);
@@ -645,6 +645,45 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
        route_match_ip_next_hop_prefix_list_compile,
        route_match_ip_next_hop_prefix_list_free};
 
+/* `match ip next-hop type <blackhole>' */
+
+static route_map_result_t
+route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
+                            route_map_object_t type, void *object)
+{
+       struct bgp_path_info *path;
+
+       if (type == RMAP_BGP && prefix->family == AF_INET) {
+               path = (struct bgp_path_info *)object;
+               if (!path || !path->attr)
+                       return RMAP_DENYMATCH;
+
+               /* If nexthop interface's index can't be resolved and nexthop is
+                  set to any address then mark it as type `blackhole`.
+                  This logic works for matching kernel/static routes like:
+                  `ip route add blackhole 10.0.0.1`. */
+               if (path->attr->nexthop.s_addr == INADDR_ANY
+                   && !path->attr->nh_ifindex)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ip_next_hop_type_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ip_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
+       "ip next-hop type", route_match_ip_next_hop_type,
+       route_match_ip_next_hop_type_compile,
+       route_match_ip_next_hop_type_free};
+
 /* `match ip route-source prefix-list PREFIX_LIST' */
 
 static route_map_result_t
@@ -653,13 +692,13 @@ route_match_ip_route_source_prefix_list(void *rule,
                                        route_map_object_t type, void *object)
 {
        struct prefix_list *plist;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct peer *peer;
        struct prefix_ipv4 p;
 
        if (type == RMAP_BGP && prefix->family == AF_INET) {
-               bgp_info = object;
-               peer = bgp_info->peer;
+               path = object;
+               peer = path->peer;
 
                if (!peer || sockunion_family(&peer->su) != AF_INET)
                        return RMAP_NOMATCH;
@@ -771,16 +810,16 @@ static route_map_result_t route_match_vni(void *rule,
                                          route_map_object_t type, void *object)
 {
        vni_t vni = 0;
-       struct bgp_info *bgp_info = NULL;
+       struct bgp_path_info *path = NULL;
 
        if (type == RMAP_BGP) {
                vni = *((vni_t *)rule);
-               bgp_info = (struct bgp_info *)object;
+               path = (struct bgp_path_info *)object;
 
-               if (bgp_info->extra == NULL)
+               if (path->extra == NULL)
                        return RMAP_NOMATCH;
 
-               if (vni == label2vni(&bgp_info->extra->label[0]))
+               if (vni == label2vni(&path->extra->label[0]))
                        return RMAP_MATCH;
        }
 
@@ -875,13 +914,13 @@ static route_map_result_t route_match_local_pref(void *rule,
                                                 void *object)
 {
        uint32_t *local_pref;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                local_pref = rule;
-               bgp_info = object;
+               path = object;
 
-               if (bgp_info->attr->local_pref == *local_pref)
+               if (path->attr->local_pref == *local_pref)
                        return RMAP_MATCH;
                else
                        return RMAP_NOMATCH;
@@ -935,12 +974,12 @@ static route_map_result_t route_match_metric(void *rule,
                                             void *object)
 {
        struct rmap_value *rv;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                rv = rule;
-               bgp_info = object;
-               return route_value_match(rv, bgp_info->attr->med);
+               path = object;
+               return route_value_match(rv, path->attr->med);
        }
        return RMAP_NOMATCH;
 }
@@ -960,17 +999,17 @@ static route_map_result_t route_match_aspath(void *rule,
 {
 
        struct as_list *as_list;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                as_list = as_list_lookup((char *)rule);
                if (as_list == NULL)
                        return RMAP_NOMATCH;
 
-               bgp_info = object;
+               path = object;
 
                /* Perform match. */
-               return ((as_list_apply(as_list, bgp_info->attr->aspath)
+               return ((as_list_apply(as_list, path->attr->aspath)
                         == AS_FILTER_DENY)
                                ? RMAP_NOMATCH
                                : RMAP_MATCH);
@@ -1008,11 +1047,11 @@ static route_map_result_t route_match_community(void *rule,
                                                void *object)
 {
        struct community_list *list;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct rmap_community *rcom;
 
        if (type == RMAP_BGP) {
-               bgp_info = object;
+               path = object;
                rcom = rule;
 
                list = community_list_lookup(bgp_clist, rcom->name,
@@ -1021,12 +1060,11 @@ static route_map_result_t route_match_community(void *rule,
                        return RMAP_NOMATCH;
 
                if (rcom->exact) {
-                       if (community_list_exact_match(
-                                   bgp_info->attr->community, list))
+                       if (community_list_exact_match(path->attr->community,
+                                                      list))
                                return RMAP_MATCH;
                } else {
-                       if (community_list_match(bgp_info->attr->community,
-                                                list))
+                       if (community_list_match(path->attr->community, list))
                                return RMAP_MATCH;
                }
        }
@@ -1076,11 +1114,11 @@ static route_map_result_t route_match_lcommunity(void *rule,
                                                 void *object)
 {
        struct community_list *list;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct rmap_community *rcom;
 
        if (type == RMAP_BGP) {
-               bgp_info = object;
+               path = object;
                rcom = rule;
 
                list = community_list_lookup(bgp_clist, rcom->name,
@@ -1088,7 +1126,7 @@ static route_map_result_t route_match_lcommunity(void *rule,
                if (!list)
                        return RMAP_NOMATCH;
 
-               if (lcommunity_list_match(bgp_info->attr->lcommunity, list))
+               if (lcommunity_list_match(path->attr->lcommunity, list))
                        return RMAP_MATCH;
        }
        return RMAP_NOMATCH;
@@ -1137,17 +1175,17 @@ static route_map_result_t route_match_ecommunity(void *rule,
                                                 void *object)
 {
        struct community_list *list;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
-               bgp_info = object;
+               path = object;
 
                list = community_list_lookup(bgp_clist, (char *)rule,
                                             EXTCOMMUNITY_LIST_MASTER);
                if (!list)
                        return RMAP_NOMATCH;
 
-               if (ecommunity_list_match(bgp_info->attr->ecommunity, list))
+               if (ecommunity_list_match(path->attr->ecommunity, list))
                        return RMAP_MATCH;
        }
        return RMAP_NOMATCH;
@@ -1180,13 +1218,13 @@ static route_map_result_t route_match_origin(void *rule,
                                             void *object)
 {
        uint8_t *origin;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                origin = rule;
-               bgp_info = object;
+               path = object;
 
-               if (bgp_info->attr->origin == *origin)
+               if (path->attr->origin == *origin)
                        return RMAP_MATCH;
        }
 
@@ -1283,17 +1321,17 @@ static route_map_result_t route_match_interface(void *rule,
                                                void *object)
 {
        struct interface *ifp;
-       struct bgp_info *info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
-               info = object;
+               path = object;
 
-               if (!info || !info->attr)
+               if (!path || !path->attr)
                        return RMAP_NOMATCH;
 
                ifp = if_lookup_by_name_all_vrf((char *)rule);
 
-               if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex)
+               if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
                        return RMAP_NOMATCH;
 
                return RMAP_MATCH;
@@ -1329,14 +1367,13 @@ static route_map_result_t route_match_tag(void *rule,
                                          route_map_object_t type, void *object)
 {
        route_tag_t *tag;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                tag = rule;
-               bgp_info = object;
+               path = object;
 
-               return ((bgp_info->attr->tag == *tag) ? RMAP_MATCH
-                                                     : RMAP_NOMATCH);
+               return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
        }
 
        return RMAP_NOMATCH;
@@ -1363,49 +1400,48 @@ static route_map_result_t route_set_ip_nexthop(void *rule,
                                               void *object)
 {
        struct rmap_ip_nexthop_set *rins = rule;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct peer *peer;
 
-       if (type == RMAP_BGP) {
-               bgp_info = object;
-               peer = bgp_info->peer;
-
-               if (rins->unchanged) {
-                       SET_FLAG(bgp_info->attr->rmap_change_flags,
-                                BATTR_RMAP_NEXTHOP_UNCHANGED);
-               } else if (rins->peer_address) {
-                       if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
-                            || CHECK_FLAG(peer->rmap_type,
-                                          PEER_RMAP_TYPE_IMPORT))
-                           && peer->su_remote
-                           && sockunion_family(peer->su_remote) == AF_INET) {
-                               bgp_info->attr->nexthop.s_addr =
-                                       sockunion2ip(peer->su_remote);
-                               bgp_info->attr->flag |=
-                                       ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
-                       } else if (CHECK_FLAG(peer->rmap_type,
-                                             PEER_RMAP_TYPE_OUT)) {
-                               /* The next hop value will be set as part of
-                                * packet rewrite.
-                                * Set the flags here to indicate that rewrite
-                                * needs to be done.
-                                * Also, clear the value.
-                                */
-                               SET_FLAG(bgp_info->attr->rmap_change_flags,
-                                        BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
-                               bgp_info->attr->nexthop.s_addr = 0;
-                       }
-               } else {
-                       /* Set next hop value. */
-                       bgp_info->attr->flag |=
-                               ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
-                       bgp_info->attr->nexthop = *rins->address;
-                       SET_FLAG(bgp_info->attr->rmap_change_flags,
-                                BATTR_RMAP_IPV4_NHOP_CHANGED);
-                       /* case for MP-BGP : MPLS VPN */
-                       bgp_info->attr->mp_nexthop_global_in = *rins->address;
-                       bgp_info->attr->mp_nexthop_len = sizeof(*rins->address);
+       if (type != RMAP_BGP)
+               return RMAP_OKAY;
+
+       if (prefix->family == AF_INET6)
+               return RMAP_OKAY;
+
+       path = object;
+       peer = path->peer;
+
+       if (rins->unchanged) {
+               SET_FLAG(path->attr->rmap_change_flags,
+                        BATTR_RMAP_NEXTHOP_UNCHANGED);
+       } else if (rins->peer_address) {
+               if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
+                    || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
+                   && peer->su_remote
+                   && sockunion_family(peer->su_remote) == AF_INET) {
+                       path->attr->nexthop.s_addr =
+                               sockunion2ip(peer->su_remote);
+                       path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+               } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
+                       /* The next hop value will be set as part of
+                        * packet rewrite.  Set the flags here to indicate
+                        * that rewrite needs to be done.
+                        * Also, clear the value.
+                        */
+                       SET_FLAG(path->attr->rmap_change_flags,
+                                BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
+                       path->attr->nexthop.s_addr = 0;
                }
+       } else {
+               /* Set next hop value. */
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+               path->attr->nexthop = *rins->address;
+               SET_FLAG(path->attr->rmap_change_flags,
+                        BATTR_RMAP_IPV4_NHOP_CHANGED);
+               /* case for MP-BGP : MPLS VPN */
+               path->attr->mp_nexthop_global_in = *rins->address;
+               path->attr->mp_nexthop_len = sizeof(*rins->address);
        }
 
        return RMAP_OKAY;
@@ -1471,21 +1507,21 @@ static route_map_result_t route_set_local_pref(void *rule,
                                               void *object)
 {
        struct rmap_value *rv;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        uint32_t locpref = 0;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                rv = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set local preference value. */
-               if (bgp_info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
-                       locpref = bgp_info->attr->local_pref;
+               if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
+                       locpref = path->attr->local_pref;
 
-               bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
-               bgp_info->attr->local_pref =
-                       route_value_adjust(rv, locpref, bgp_info->peer);
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+               path->attr->local_pref =
+                       route_value_adjust(rv, locpref, path->peer);
        }
 
        return RMAP_OKAY;
@@ -1506,16 +1542,15 @@ static route_map_result_t route_set_weight(void *rule,
                                           void *object)
 {
        struct rmap_value *rv;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                rv = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set weight value. */
-               bgp_info->attr->weight =
-                       route_value_adjust(rv, 0, bgp_info->peer);
+               path->attr->weight = route_value_adjust(rv, 0, path->peer);
        }
 
        return RMAP_OKAY;
@@ -1535,21 +1570,19 @@ static route_map_result_t route_set_metric(void *rule,
                                           void *object)
 {
        struct rmap_value *rv;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        uint32_t med = 0;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                rv = rule;
-               bgp_info = object;
+               path = object;
 
-               if (bgp_info->attr->flag
-                   & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
-                       med = bgp_info->attr->med;
+               if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+                       med = path->attr->med;
 
-               bgp_info->attr->med =
-                       route_value_adjust(rv, med, bgp_info->peer);
-               bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+               path->attr->med = route_value_adjust(rv, med, path->peer);
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
        }
        return RMAP_OKAY;
 }
@@ -1569,15 +1602,15 @@ static route_map_result_t route_set_aspath_prepend(void *rule,
 {
        struct aspath *aspath;
        struct aspath *new;
-       struct bgp_info *binfo;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
-               binfo = object;
+               path = object;
 
-               if (binfo->attr->aspath->refcnt)
-                       new = aspath_dup(binfo->attr->aspath);
+               if (path->attr->aspath->refcnt)
+                       new = aspath_dup(path->attr->aspath);
                else
-                       new = binfo->attr->aspath;
+                       new = path->attr->aspath;
 
                if ((uintptr_t)rule > 10) {
                        aspath = rule;
@@ -1585,11 +1618,11 @@ static route_map_result_t route_set_aspath_prepend(void *rule,
                } else {
                        as_t as = aspath_leftmost(new);
                        if (!as)
-                               as = binfo->peer->as;
+                               as = path->peer->as;
                        new = aspath_add_seq_n(new, as, (uintptr_t)rule);
                }
 
-               binfo->attr->aspath = new;
+               path->attr->aspath = new;
        }
 
        return RMAP_OKAY;
@@ -1631,16 +1664,16 @@ static route_map_result_t route_set_aspath_exclude(void *rule,
                                                   void *object)
 {
        struct aspath *new_path, *exclude_path;
-       struct bgp_info *binfo;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                exclude_path = rule;
-               binfo = object;
-               if (binfo->attr->aspath->refcnt)
-                       new_path = aspath_dup(binfo->attr->aspath);
+               path = object;
+               if (path->attr->aspath->refcnt)
+                       new_path = aspath_dup(path->attr->aspath);
                else
-                       new_path = binfo->attr->aspath;
-               binfo->attr->aspath =
+                       new_path = path->attr->aspath;
+               path->attr->aspath =
                        aspath_filter_exclude(new_path, exclude_path);
        }
        return RMAP_OKAY;
@@ -1666,7 +1699,7 @@ static route_map_result_t route_set_community(void *rule,
                                              void *object)
 {
        struct rmap_com_set *rcs;
-       struct bgp_info *binfo;
+       struct bgp_path_info *path;
        struct attr *attr;
        struct community *new = NULL;
        struct community *old;
@@ -1674,8 +1707,8 @@ static route_map_result_t route_set_community(void *rule,
 
        if (type == RMAP_BGP) {
                rcs = rule;
-               binfo = object;
-               attr = binfo->attr;
+               path = object;
+               attr = path->attr;
                old = attr->community;
 
                /* "none" case.  */
@@ -1684,7 +1717,7 @@ static route_map_result_t route_set_community(void *rule,
                        attr->community = NULL;
                        /* See the longer comment down below. */
                        if (old && old->refcnt == 0)
-                               community_free(old);
+                               community_free(&old);
                        return RMAP_OKAY;
                }
 
@@ -1693,7 +1726,7 @@ static route_map_result_t route_set_community(void *rule,
                        merge = community_merge(community_dup(old), rcs->com);
 
                        new = community_uniq_sort(merge);
-                       community_free(merge);
+                       community_free(&merge);
                } else
                        new = community_dup(rcs->com);
 
@@ -1703,7 +1736,7 @@ static route_map_result_t route_set_community(void *rule,
                 * Really need to cleanup attribute caching sometime.
                 */
                if (old && old->refcnt == 0)
-                       community_free(old);
+                       community_free(&old);
 
                /* will be interned by caller if required */
                attr->community = new;
@@ -1757,7 +1790,7 @@ static void route_set_community_free(void *rule)
        struct rmap_com_set *rcs = rule;
 
        if (rcs->com)
-               community_free(rcs->com);
+               community_free(&rcs->com);
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
 }
 
@@ -1782,7 +1815,7 @@ static route_map_result_t route_set_lcommunity(void *rule,
                                               void *object)
 {
        struct rmap_lcom_set *rcs;
-       struct bgp_info *binfo;
+       struct bgp_path_info *path;
        struct attr *attr;
        struct lcommunity *new = NULL;
        struct lcommunity *old;
@@ -1790,8 +1823,8 @@ static route_map_result_t route_set_lcommunity(void *rule,
 
        if (type == RMAP_BGP) {
                rcs = rule;
-               binfo = object;
-               attr = binfo->attr;
+               path = object;
+               attr = path->attr;
                old = attr->lcommunity;
 
                /* "none" case.  */
@@ -1898,16 +1931,16 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
        struct lcommunity *merge;
        struct lcommunity *new;
        struct lcommunity *old;
-       struct bgp_info *binfo;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                if (!rule)
                        return RMAP_OKAY;
 
-               binfo = object;
+               path = object;
                list = community_list_lookup(bgp_clist, rule,
                                             LARGE_COMMUNITY_LIST_MASTER);
-               old = binfo->attr->lcommunity;
+               old = path->attr->lcommunity;
 
                if (list && old) {
                        merge = lcommunity_list_match_delete(
@@ -1924,13 +1957,13 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
                                lcommunity_free(&old);
 
                        if (new->size == 0) {
-                               binfo->attr->lcommunity = NULL;
-                               binfo->attr->flag &= ~ATTR_FLAG_BIT(
+                               path->attr->lcommunity = NULL;
+                               path->attr->flag &= ~ATTR_FLAG_BIT(
                                        BGP_ATTR_LARGE_COMMUNITIES);
                                lcommunity_free(&new);
                        } else {
-                               binfo->attr->lcommunity = new;
-                               binfo->attr->flag |= ATTR_FLAG_BIT(
+                               path->attr->lcommunity = new;
+                               path->attr->flag |= ATTR_FLAG_BIT(
                                        BGP_ATTR_LARGE_COMMUNITIES);
                        }
                }
@@ -1983,22 +2016,22 @@ static route_map_result_t route_set_community_delete(
        struct community *merge;
        struct community *new;
        struct community *old;
-       struct bgp_info *binfo;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                if (!rule)
                        return RMAP_OKAY;
 
-               binfo = object;
+               path = object;
                list = community_list_lookup(bgp_clist, rule,
                                             COMMUNITY_LIST_MASTER);
-               old = binfo->attr->community;
+               old = path->attr->community;
 
                if (list && old) {
                        merge = community_list_match_delete(community_dup(old),
                                                            list);
                        new = community_uniq_sort(merge);
-                       community_free(merge);
+                       community_free(&merge);
 
                        /* HACK: if the old community is not intern'd,
                         * we should free it here, or all reference to it may be
@@ -2006,16 +2039,16 @@ static route_map_result_t route_set_community_delete(
                         * Really need to cleanup attribute caching sometime.
                         */
                        if (old->refcnt == 0)
-                               community_free(old);
+                               community_free(&old);
 
                        if (new->size == 0) {
-                               binfo->attr->community = NULL;
-                               binfo->attr->flag &=
+                               path->attr->community = NULL;
+                               path->attr->flag &=
                                        ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
-                               community_free(new);
+                               community_free(&new);
                        } else {
-                               binfo->attr->community = new;
-                               binfo->attr->flag |=
+                               path->attr->community = new;
+                               path->attr->flag |=
                                        ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
                        }
                }
@@ -2065,17 +2098,17 @@ static route_map_result_t route_set_ecommunity(void *rule,
        struct ecommunity *ecom;
        struct ecommunity *new_ecom;
        struct ecommunity *old_ecom;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                ecom = rule;
-               bgp_info = object;
+               path = object;
 
                if (!ecom)
                        return RMAP_OKAY;
 
                /* We assume additive for Extended Community. */
-               old_ecom = bgp_info->attr->ecommunity;
+               old_ecom = path->attr->ecommunity;
 
                if (old_ecom) {
                        new_ecom = ecommunity_merge(ecommunity_dup(old_ecom),
@@ -2091,9 +2124,9 @@ static route_map_result_t route_set_ecommunity(void *rule,
                        new_ecom = ecommunity_dup(ecom);
 
                /* will be intern()'d or attr_flush()'d by bgp_update_main() */
-               bgp_info->attr->ecommunity = new_ecom;
+               path->attr->ecommunity = new_ecom;
 
-               bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
        }
        return RMAP_OKAY;
 }
@@ -2151,13 +2184,13 @@ static route_map_result_t route_set_origin(void *rule,
                                           void *object)
 {
        uint8_t *origin;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                origin = rule;
-               bgp_info = object;
+               path = object;
 
-               bgp_info->attr->origin = *origin;
+               path->attr->origin = *origin;
        }
 
        return RMAP_OKAY;
@@ -2200,12 +2233,11 @@ static route_map_result_t route_set_atomic_aggregate(void *rule,
                                                     route_map_object_t type,
                                                     void *object)
 {
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
-               bgp_info = object;
-               bgp_info->attr->flag |=
-                       ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
+               path = object;
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
        }
 
        return RMAP_OKAY;
@@ -2240,16 +2272,16 @@ static route_map_result_t route_set_aggregator_as(void *rule,
                                                  route_map_object_t type,
                                                  void *object)
 {
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct aggregator *aggregator;
 
        if (type == RMAP_BGP) {
-               bgp_info = object;
+               path = object;
                aggregator = rule;
 
-               bgp_info->attr->aggregator_as = aggregator->as;
-               bgp_info->attr->aggregator_addr = aggregator->address;
-               bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
+               path->attr->aggregator_as = aggregator->as;
+               path->attr->aggregator_addr = aggregator->address;
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
        }
 
        return RMAP_OKAY;
@@ -2288,20 +2320,20 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = {
        route_set_aggregator_as_compile, route_set_aggregator_as_free,
 };
 
-/* Set tag to object. object must be pointer to struct bgp_info */
+/* Set tag to object. object must be pointer to struct bgp_path_info */
 static route_map_result_t route_set_tag(void *rule,
                                        const struct prefix *prefix,
                                        route_map_object_t type, void *object)
 {
        route_tag_t *tag;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                tag = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set tag value */
-               bgp_info->attr->tag = *tag;
+               path->attr->tag = *tag;
        }
 
        return RMAP_OKAY;
@@ -2313,27 +2345,26 @@ static struct route_map_rule_cmd route_set_tag_cmd = {
        route_map_rule_tag_free,
 };
 
-/* Set label-index to object. object must be pointer to struct bgp_info */
+/* Set label-index to object. object must be pointer to struct bgp_path_info */
 static route_map_result_t route_set_label_index(void *rule,
                                                const struct prefix *prefix,
                                                route_map_object_t type,
                                                void *object)
 {
        struct rmap_value *rv;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        uint32_t label_index;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                rv = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set label-index value. */
                label_index = rv->value;
                if (label_index) {
-                       bgp_info->attr->label_index = label_index;
-                       bgp_info->attr->flag |=
-                               ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
+                       path->attr->label_index = label_index;
+                       path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
                }
        }
 
@@ -2390,17 +2421,17 @@ static route_map_result_t route_match_ipv6_next_hop(void *rule,
                                                    void *object)
 {
        struct in6_addr *addr = rule;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
-               bgp_info = object;
+               path = object;
 
-               if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr))
+               if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
                        return RMAP_MATCH;
 
-               if (bgp_info->attr->mp_nexthop_len
+               if (path->attr->mp_nexthop_len
                            == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
-                   && IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_local, rule))
+                   && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
                        return RMAP_MATCH;
 
                return RMAP_NOMATCH;
@@ -2469,6 +2500,53 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
        route_match_ipv6_address_prefix_list_compile,
        route_match_ipv6_address_prefix_list_free};
 
+/* `match ipv6 next-hop type <TYPE>' */
+
+static route_map_result_t
+route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
+                             route_map_object_t type, void *object)
+{
+       struct bgp_path_info *path;
+       struct in6_addr *addr = rule;
+
+       if (type == RMAP_BGP && prefix->family == AF_INET6) {
+               path = (struct bgp_path_info *)object;
+               if (!path || !path->attr)
+                       return RMAP_DENYMATCH;
+
+               if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
+                   && !path->attr->nh_ifindex)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_type_compile(const char *arg)
+{
+       struct in6_addr *address;
+       int ret;
+
+       address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
+
+       ret = inet_pton(AF_INET6, "::0", address);
+       if (!ret) {
+               XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
+               return NULL;
+       }
+
+       return address;
+}
+
+static void route_match_ipv6_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
+       "ipv6 next-hop type", route_match_ipv6_next_hop_type,
+       route_match_ipv6_next_hop_type_compile,
+       route_match_ipv6_next_hop_type_free};
+
 /* `set ipv6 nexthop global IP_ADDRESS' */
 
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
@@ -2478,22 +2556,21 @@ static route_map_result_t route_set_ipv6_nexthop_global(void *rule,
                                                        void *object)
 {
        struct in6_addr *address;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                address = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set next hop value. */
-               bgp_info->attr->mp_nexthop_global = *address;
+               path->attr->mp_nexthop_global = *address;
 
                /* Set nexthop length. */
-               if (bgp_info->attr->mp_nexthop_len == 0)
-                       bgp_info->attr->mp_nexthop_len =
-                               BGP_ATTR_NHLEN_IPV6_GLOBAL;
+               if (path->attr->mp_nexthop_len == 0)
+                       path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
 
-               SET_FLAG(bgp_info->attr->rmap_change_flags,
+               SET_FLAG(path->attr->rmap_change_flags,
                         BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
        }
 
@@ -2536,25 +2613,25 @@ static route_map_result_t
 route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
                                     route_map_object_t type, void *object)
 {
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct peer *peer;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
-               bgp_info = object;
-               peer = bgp_info->peer;
+               path = object;
+               peer = path->peer;
 
                if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
                     || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
                    && peer->su_remote
                    && sockunion_family(peer->su_remote) == AF_INET6) {
                        /* Set next hop preference to global */
-                       bgp_info->attr->mp_nexthop_prefer_global = TRUE;
-                       SET_FLAG(bgp_info->attr->rmap_change_flags,
+                       path->attr->mp_nexthop_prefer_global = TRUE;
+                       SET_FLAG(path->attr->rmap_change_flags,
                                 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
                } else {
-                       bgp_info->attr->mp_nexthop_prefer_global = FALSE;
-                       SET_FLAG(bgp_info->attr->rmap_change_flags,
+                       path->attr->mp_nexthop_prefer_global = FALSE;
+                       SET_FLAG(path->attr->rmap_change_flags,
                                 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
                }
        }
@@ -2592,23 +2669,23 @@ static route_map_result_t route_set_ipv6_nexthop_local(void *rule,
                                                       void *object)
 {
        struct in6_addr *address;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                address = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set next hop value. */
-               bgp_info->attr->mp_nexthop_local = *address;
+               path->attr->mp_nexthop_local = *address;
 
                /* Set nexthop length. */
-               if (bgp_info->attr->mp_nexthop_len
+               if (path->attr->mp_nexthop_len
                    != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
-                       bgp_info->attr->mp_nexthop_len =
+                       path->attr->mp_nexthop_len =
                                BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
 
-               SET_FLAG(bgp_info->attr->rmap_change_flags,
+               SET_FLAG(path->attr->rmap_change_flags,
                         BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
        }
 
@@ -2655,13 +2732,13 @@ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule,
                                                      void *object)
 {
        struct in6_addr peer_address;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
        struct peer *peer;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
-               bgp_info = object;
-               peer = bgp_info->peer;
+               path = object;
+               peer = path->peer;
 
                if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
                     || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
@@ -2670,14 +2747,13 @@ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule,
                        peer_address = peer->su_remote->sin6.sin6_addr;
                        /* Set next hop value and length in attribute. */
                        if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
-                               bgp_info->attr->mp_nexthop_local = peer_address;
-                               if (bgp_info->attr->mp_nexthop_len != 32)
-                                       bgp_info->attr->mp_nexthop_len = 32;
+                               path->attr->mp_nexthop_local = peer_address;
+                               if (path->attr->mp_nexthop_len != 32)
+                                       path->attr->mp_nexthop_len = 32;
                        } else {
-                               bgp_info->attr->mp_nexthop_global =
-                                       peer_address;
-                               if (bgp_info->attr->mp_nexthop_len == 0)
-                                       bgp_info->attr->mp_nexthop_len = 16;
+                               path->attr->mp_nexthop_global = peer_address;
+                               if (path->attr->mp_nexthop_len == 0)
+                                       path->attr->mp_nexthop_len = 16;
                        }
 
                } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
@@ -2690,12 +2766,12 @@ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule,
                         * nexthops, whether we send one or both is determined
                         * elsewhere.
                         */
-                       SET_FLAG(bgp_info->attr->rmap_change_flags,
+                       SET_FLAG(path->attr->rmap_change_flags,
                                 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
                        /* clear next hop value. */
-                       memset(&(bgp_info->attr->mp_nexthop_global), 0,
+                       memset(&(path->attr->mp_nexthop_global), 0,
                               sizeof(struct in6_addr));
-                       memset(&(bgp_info->attr->mp_nexthop_local), 0,
+                       memset(&(path->attr->mp_nexthop_local), 0,
                               sizeof(struct in6_addr));
                }
        }
@@ -2734,16 +2810,16 @@ static route_map_result_t route_set_vpnv4_nexthop(void *rule,
                                                  void *object)
 {
        struct in_addr *address;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                address = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set next hop value. */
-               bgp_info->attr->mp_nexthop_global_in = *address;
-               bgp_info->attr->mp_nexthop_len = 4;
+               path->attr->mp_nexthop_global_in = *address;
+               path->attr->mp_nexthop_len = 4;
        }
 
        return RMAP_OKAY;
@@ -2774,17 +2850,17 @@ static route_map_result_t route_set_vpnv6_nexthop(void *rule,
                                                  void *object)
 {
        struct in6_addr *address;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                /* Fetch routemap's rule information. */
                address = rule;
-               bgp_info = object;
+               path = object;
 
                /* Set next hop value. */
-               memcpy(&bgp_info->attr->mp_nexthop_global, address,
+               memcpy(&path->attr->mp_nexthop_global, address,
                       sizeof(struct in6_addr));
-               bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
+               path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
        }
 
        return RMAP_OKAY;
@@ -2830,14 +2906,14 @@ static route_map_result_t route_set_originator_id(void *rule,
                                                  void *object)
 {
        struct in_addr *address;
-       struct bgp_info *bgp_info;
+       struct bgp_path_info *path;
 
        if (type == RMAP_BGP) {
                address = rule;
-               bgp_info = object;
+               path = object;
 
-               bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
-               bgp_info->attr->originator_id = *address;
+               path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
+               path->attr->originator_id = *address;
        }
 
        return RMAP_OKAY;
@@ -3362,7 +3438,7 @@ DEFUN (no_match_evpn_route_type,
 
 DEFUN (match_evpn_vni,
        match_evpn_vni_cmd,
-       "match evpn vni (1-16777215)",
+       "match evpn vni " CMD_VNI_RANGE,
        MATCH_STR
        EVPN_HELP_STR
        "Match VNI\n"
@@ -3374,7 +3450,7 @@ DEFUN (match_evpn_vni,
 
 DEFUN (no_match_evpn_vni,
        no_match_evpn_vni_cmd,
-       "no match evpn vni (1-16777215)",
+       "no match evpn vni " CMD_VNI_RANGE,
        NO_STR
        MATCH_STR
        EVPN_HELP_STR
@@ -4000,6 +4076,11 @@ DEFUN (no_set_aspath_exclude,
        return ret;
 }
 
+ALIAS(no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
+      "no set as-path exclude",
+      NO_STR SET_STR
+      "Transform BGP AS_PATH attribute\n"
+      "Exclude from the as-path\n")
 
 DEFUN (set_community,
        set_community_cmd,
@@ -4095,7 +4176,7 @@ DEFUN (set_community,
                ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
                                      "community", str);
 
-       community_free(com);
+       community_free(&com);
 
        return ret;
 }
@@ -4766,12 +4847,18 @@ void bgp_route_map_init(void)
        route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
        route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ip_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
+
        route_map_match_ipv6_address_hook(generic_match_add);
        route_map_no_match_ipv6_address_hook(generic_match_delete);
 
        route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
        route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ipv6_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
+
        route_map_match_metric_hook(generic_match_add);
        route_map_no_match_metric_hook(generic_match_delete);
 
@@ -4800,6 +4887,7 @@ void bgp_route_map_init(void)
        route_map_install_match(&route_match_ip_route_source_cmd);
        route_map_install_match(&route_match_ip_address_prefix_list_cmd);
        route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
+       route_map_install_match(&route_match_ip_next_hop_type_cmd);
        route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
        route_map_install_match(&route_match_aspath_cmd);
        route_map_install_match(&route_match_community_cmd);
@@ -4882,6 +4970,7 @@ void bgp_route_map_init(void)
        install_element(RMAP_NODE, &set_aspath_exclude_cmd);
        install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
        install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
+       install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
        install_element(RMAP_NODE, &set_origin_cmd);
        install_element(RMAP_NODE, &no_set_origin_cmd);
        install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
@@ -4915,6 +5004,7 @@ void bgp_route_map_init(void)
        route_map_install_match(&route_match_ipv6_address_cmd);
        route_map_install_match(&route_match_ipv6_next_hop_cmd);
        route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
+       route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
        route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
        route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
        route_map_install_set(&route_set_ipv6_nexthop_local_cmd);