diff options
Diffstat (limited to 'bgpd/bgp_routemap.c')
-rw-r--r-- | bgpd/bgp_routemap.c | 1038 |
1 files changed, 878 insertions, 160 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 39fa08c8..18ecc6c8 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -39,12 +39,15 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #endif /* HAVE_LIBPCREPOSIX */ #include "buffer.h" #include "sockunion.h" +#include "hash.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_aspath.h" +#include "bgpd/bgp_packet.h" #include "bgpd/bgp_route.h" +#include "bgpd/bgp_zebra.h" #include "bgpd/bgp_regex.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_clist.h" @@ -52,6 +55,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_vty.h" +#include "bgpd/bgp_debug.h" + /* Memo of route-map commands. @@ -59,7 +64,7 @@ o Cisco route-map match as-path : Done community : Done - interface : Not yet + interface : Done ip address : Done ip next-hop : Done ip route-source : Done @@ -71,7 +76,8 @@ o Cisco route-map length : (This will not be implemented by bgpd) metric : Done route-type : (This will not be implemented by bgpd) - tag : (This will not be implemented by bgpd) + tag : Done + local-preference : Done set as-path prepend : Done as-path tag : Not yet @@ -90,7 +96,7 @@ o Cisco route-map metric : Done metric-type : Not yet origin : Done - tag : (This will not be implemented by bgpd) + tag : Done weight : Done o Local extensions @@ -613,6 +619,72 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = route_match_ip_route_source_prefix_list_free }; +/* `match local-preference LOCAL-PREF' */ + +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_local_pref (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_int32_t *local_pref; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) + { + local_pref = rule; + bgp_info = object; + + if (bgp_info->attr->local_pref == *local_pref) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } + return RMAP_NOMATCH; +} + +/* Route map `match local-preference' match statement. + `arg' is local-pref value */ +static void * +route_match_local_pref_compile (const char *arg) +{ + u_int32_t *local_pref; + char *endptr = NULL; + unsigned long tmpval; + + /* Locpref value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + errno = 0; + tmpval = strtoul (arg, &endptr, 10); + if (*endptr != '\0' || errno || tmpval > UINT32_MAX) + return NULL; + + local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + + if (!local_pref) + return local_pref; + + *local_pref = tmpval; + return local_pref; +} + +/* Free route map's compiled `match local-preference' value. */ +static void +route_match_local_pref_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for metric matching. */ +struct route_map_rule_cmd route_match_local_pref_cmd = +{ + "local-preference", + route_match_local_pref, + route_match_local_pref_compile, + route_match_local_pref_free +}; + /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ @@ -657,9 +729,9 @@ route_match_aspath (void *rule, struct prefix *prefix, as_list = as_list_lookup ((char *) rule); if (as_list == NULL) return RMAP_NOMATCH; - + bgp_info = object; - + /* Perform match. */ return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH); } @@ -933,10 +1005,127 @@ struct route_map_rule_cmd route_match_probability_cmd = route_match_probability_free }; +/* `match interface IFNAME' */ +/* Match function should return 1 if match is success else return + zero. */ +static route_map_result_t +route_match_interface (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct interface *ifp; + struct bgp_info *info; + + if (type == RMAP_BGP) + { + info = object; + + if (!info || !info->attr) + return RMAP_NOMATCH; + + ifp = if_lookup_by_name ((char *)rule); + + if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex) + return RMAP_NOMATCH; + + return RMAP_MATCH; + } + return RMAP_NOMATCH; +} + +/* Route map `interface' match statement. `arg' should be + interface name. */ +static void * +route_match_interface_compile (const char *arg) +{ + return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); +} + +/* Free route map's compiled `interface' value. */ +static void +route_match_interface_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for ip address matching. */ +struct route_map_rule_cmd route_match_interface_cmd = +{ + "interface", + route_match_interface, + route_match_interface_compile, + route_match_interface_free +}; + /* } */ /* `set ip next-hop IP_ADDRESS' */ +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) + { + tag = rule; + bgp_info = object; + + if (!bgp_info->attr->extra) + return RMAP_NOMATCH; + + return ((bgp_info->attr->extra->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); + } + + return RMAP_NOMATCH; +} + + +/* Route map `match tag' match statement. `arg' is TAG value */ +static void * +route_match_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + + +/* Free route map's compiled 'match tag' value. */ +static void +route_match_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag matching. */ +struct route_map_rule_cmd route_match_tag_cmd = +{ + "tag", + route_match_tag, + route_match_tag_compile, + route_match_tag_free, +}; + + /* Set nexthop to object. ojbect must be pointer to struct attr. */ struct rmap_ip_nexthop_set { @@ -1710,6 +1899,73 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = route_set_aggregator_as_free, }; +/* Set tag to object. object must be pointer to struct bgp_info */ +static route_map_result_t +route_set_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct bgp_info *bgp_info; + struct attr_extra *ae; + + if (type == RMAP_BGP) + { + tag = rule; + bgp_info = object; + ae = bgp_attr_extra_get (bgp_info->attr); + + /* Set tag value */ + ae->tag=*tag; + + } + + return RMAP_OKAY; +} + +/* Route map `tag' compile function. Given string is converted to u_short. */ +static void * +route_set_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's tag value. */ +static void +route_set_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + + +/* Route map commands for tag set. */ +struct route_map_rule_cmd route_set_tag_cmd = +{ + "tag", + route_set_tag, + route_set_tag_compile, + route_set_tag_free, +}; + + /* `match ipv6 address IP_ACCESS_LIST' */ static route_map_result_t @@ -2187,7 +2443,8 @@ struct route_map_rule_cmd route_set_originator_id_cmd = /* Add bgp route map rule. */ static int bgp_route_match_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) + const char *command, const char *arg, + route_map_event_t type) { int ret; @@ -2197,36 +2454,71 @@ bgp_route_match_add (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } + + if (type != RMAP_EVENT_MATCH_ADDED) + { + route_map_upd8_dependency (type, arg, index->map->name); + } + return CMD_SUCCESS; } /* Delete bgp route map rule. */ static int bgp_route_match_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) + const char *command, const char *arg, + route_map_event_t type) { int ret; + char *dep_name = (char *)arg; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) + { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) + { + if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); + } - ret = route_map_delete_match (index, command, arg); + ret = route_map_delete_match (index, command, dep_name); if (ret) { switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); - return CMD_WARNING; + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); + break; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); - return CMD_WARNING; + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); + break; } + if (arg == NULL && dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_WARNING; } + + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); + + if (arg == NULL && dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_SUCCESS; } @@ -2243,10 +2535,10 @@ bgp_route_set_add (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } @@ -2266,134 +2558,363 @@ bgp_route_set_delete (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } return CMD_SUCCESS; } -/* Hook function for updating route_map assignment. */ +/* + * This is the workhorse routine for processing in/out/import/export routemap + * modifications. + */ static void -bgp_route_map_update (const char *unused) +bgp_route_map_process_peer (const char *rmap_name, struct peer *peer, + int afi, int safi, int route_update) { - int i; - afi_t afi; - safi_t safi; - int direct; - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; + + int update; struct bgp_filter *filter; - struct bgp_node *bn; - struct bgp_static *bgp_static; if (bm->bgp == NULL) /* may be called during cleanup */ return; - /* For neighbor route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) + if (!peer || !rmap_name) + return; + + filter = &peer->filter[afi][safi]; + /* + * in is for non-route-server clients, + * import/export is for route-server clients, + * out is for all peers + */ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + if (filter->map[RMAP_IN].name && + (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; - - for (direct = RMAP_IN; direct < RMAP_MAX; direct++) - { - if (filter->map[direct].name) - filter->map[direct].map = - route_map_lookup_by_name (filter->map[direct].name); - else - filter->map[direct].map = NULL; - } - - if (filter->usmap.name) - filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); - else - filter->usmap.map = NULL; - } + filter->map[RMAP_IN].map = + route_map_lookup_by_name (filter->map[RMAP_IN].name); + + if (route_update && peer->status == Established) + { + if (CHECK_FLAG (peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + { + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (inbound, soft-reconfig)", + rmap_name, peer->host); + + bgp_soft_reconfig_in (peer, afi, safi); + } + else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + { + + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (inbound, route-refresh)", + rmap_name, peer->host); + bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); + } + } + } + } + + if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) + { + update = 0; + + if (filter->map[RMAP_IMPORT].name && + (strcmp(rmap_name, filter->map[RMAP_IMPORT].name) == 0)) + { + filter->map[RMAP_IMPORT].map = + route_map_lookup_by_name (filter->map[RMAP_IMPORT].name); + update = 1; } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) + + if (filter->map[RMAP_EXPORT].name && + (strcmp(rmap_name, filter->map[RMAP_EXPORT].name) == 0)) { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = RMAP_IN; direct < RMAP_MAX; direct++) - { - if (filter->map[direct].name) - filter->map[direct].map = - route_map_lookup_by_name (filter->map[direct].name); - else - filter->map[direct].map = NULL; - } - - if (filter->usmap.name) - filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); - else - filter->usmap.map = NULL; - } + filter->map[RMAP_EXPORT].map = + route_map_lookup_by_name (filter->map[RMAP_EXPORT].name); + + update = 1; + } + + if (update && route_update && peer->status == Established) + { + if (CHECK_FLAG (peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + { + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (import, soft-reconfig)", + rmap_name, peer->host); + + bgp_soft_reconfig_in (peer, afi, safi); + } + else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + { + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (import, route-refresh)", + rmap_name, peer->host); + bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); + } + /* DD: Else, what else do we do ? Reset peer ? */ } } - /* For default-originate route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + if (filter->map[RMAP_OUT].name && + (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0)) { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (peer->default_rmap[afi][safi].name) - peer->default_rmap[afi][safi].map = - route_map_lookup_by_name (peer->default_rmap[afi][safi].name); - else - peer->default_rmap[afi][safi].map = NULL; - } + filter->map[RMAP_OUT].map = + route_map_lookup_by_name (filter->map[RMAP_OUT].name); + + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("Processing route_map %s update on peer %s (outbound)", + rmap_name, peer->host); + + if (route_update) + bgp_announce_route_all(peer); } + + if (filter->usmap.name && + (strcmp(rmap_name, filter->usmap.name) == 0)) + { + filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); + if (route_update) + bgp_announce_route_all(peer); } +} - /* For network route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) +static void +bgp_route_map_update_peer_group(const char *rmap_name, struct bgp *bgp) +{ + struct peer_group *group; + struct listnode *node, *nnode; + struct bgp_filter *filter; + int afi, safi; + int direct; + + if (!bgp) + return; + + /* All the peers have been updated correctly already. This is + * just updating the placeholder data. No real update required. + */ + for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + filter = &group->conf->filter[afi][safi]; + + for (direct = RMAP_IN; direct < RMAP_MAX; direct++) + { + if ((filter->map[direct].name) && + (strcmp(rmap_name, filter->map[direct].name) == 0)) + filter->map[direct].map = + route_map_lookup_by_name (filter->map[direct].name); + } + + if (filter->usmap.name && + (strcmp(rmap_name, filter->usmap.name) == 0)) + filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); + } +} + +static int +bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update) +{ + int i; + afi_t afi; + safi_t safi; + struct peer *peer; + struct bgp_node *bn; + struct bgp_static *bgp_static; + struct bgp *bgp = (struct bgp *)arg; + struct listnode *node, *nnode; + char buf[INET6_ADDRSTRLEN]; + + if (!bgp) + return -1; + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { + + /* Ignore dummy peer-group structure */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + continue; + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - for (bn = bgp_table_top (bgp->route[afi][safi]); bn; - bn = bgp_route_next (bn)) - if ((bgp_static = bn->info) != NULL) + { + /* Ignore inactive AFI/SAFI */ + if (! peer->afc[afi][safi]) + continue; + + /* process in/out/import/export route-maps */ + bgp_route_map_process_peer(rmap_name, peer, afi, safi, route_update); + + /* process default-originate route-map */ + if (peer->default_rmap[afi][safi].name && + (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0)) { - if (bgp_static->rmap.name) - bgp_static->rmap.map = - route_map_lookup_by_name (bgp_static->rmap.name); - else - bgp_static->rmap.map = NULL; + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name (peer->default_rmap[afi][safi].name); + + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("Processing route_map %s update on " + "default-originate", rmap_name); + + if (route_update) + bgp_default_originate (peer, afi, safi, 0); } + } } + bgp_route_map_update_peer_group(rmap_name, bgp); + + /* For table route-map updates. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + if (bgp->table_map[afi][safi].name && + (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0)) + { + bgp->table_map[afi][safi].map = + route_map_lookup_by_name (bgp->table_map[afi][safi].name); + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Processing route_map %s update on " + "table map", rmap_name); + if (route_update) + bgp_zebra_announce_table(bgp, afi, safi); + } + } + + /* For network route-map updates. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + for (bn = bgp_table_top (bgp->route[afi][safi]); bn; + bn = bgp_route_next (bn)) + if ((bgp_static = bn->info) != NULL) + { + if (bgp_static->rmap.name && + (strcmp(rmap_name, bgp_static->rmap.name) == 0)) + { + bgp_static->rmap.map = + route_map_lookup_by_name (bgp_static->rmap.name); + if (route_update) + if (!bgp_static->backdoor) + { + if (bgp_debug_zebra(&bn->p)) + zlog_debug("Processing route_map %s update on " + "static route %s", rmap_name, + inet_ntop (bn->p.family, &bn->p.u.prefix, + buf, INET6_ADDRSTRLEN)); + bgp_static_update (bgp, &bn->p, bgp_static, afi, safi); + } + } + } + /* For redistribute route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + { + if (bgp->rmap[afi][i].name && + (strcmp(rmap_name, bgp->rmap[afi][i].name) == 0)) + { + bgp->rmap[afi][i].map = + route_map_lookup_by_name (bgp->rmap[afi][i].name); + + if (bgp->redist[afi][i] && route_update) + { + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Processing route_map %s update on " + "redistributed routes", rmap_name); + + bgp_redistribute_resend (bgp, afi, i); + } + } + } + + return 0; +} + +static int +bgp_route_map_process_update_cb (void *arg, char *rmap_name) +{ + return bgp_route_map_process_update (arg, rmap_name, 1); +} + +int +bgp_route_map_update_timer(struct thread *thread) +{ + struct bgp *bgp = THREAD_ARG(thread); + + bgp->t_rmap_update = NULL; + + route_map_walk_update_list((void *)bgp, bgp_route_map_process_update_cb); + + return (0); +} + +static void +bgp_route_map_mark_update (const char *rmap_name) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (bgp->t_rmap_update == NULL) { - if (bgp->rmap[AFI_IP][i].name) - bgp->rmap[AFI_IP][i].map = - route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name); - if (bgp->rmap[AFI_IP6][i].name) - bgp->rmap[AFI_IP6][i].map = - route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name); + /* rmap_update_timer of 0 means don't do route updates */ + if (bgp->rmap_update_timer) + bgp->t_rmap_update = + thread_add_timer(bm->master, bgp_route_map_update_timer, bgp, + bgp->rmap_update_timer); + else + bgp_route_map_process_update((void *)bgp, rmap_name, 0); } } } +static void +bgp_route_map_add (const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 0) == 0) + bgp_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +} + +static void +bgp_route_map_delete (const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 1) == 0) + bgp_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); +} + +static void +bgp_route_map_event (route_map_event_t event, const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 0) == 0) + bgp_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +} + + DEFUN (match_peer, match_peer_cmd, "match peer (A.B.C.D|X:X::X:X)", @@ -2402,7 +2923,8 @@ DEFUN (match_peer, "IPv6 address of peer\n" "IP address of peer\n") { - return bgp_route_match_add (vty, vty->index, "peer", argv[0]); + return bgp_route_match_add (vty, vty->index, "peer", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (match_peer_local, @@ -2412,7 +2934,8 @@ DEFUN (match_peer_local, "Match peer address\n" "Static or Redistributed routes\n") { - return bgp_route_match_add (vty, vty->index, "peer", "local"); + return bgp_route_match_add (vty, vty->index, "peer", "local", + RMAP_EVENT_MATCH_DELETED); } DEFUN (no_match_peer, @@ -2423,9 +2946,11 @@ DEFUN (no_match_peer, "Match peer address\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "peer", NULL); + return bgp_route_match_delete (vty, vty->index, "peer", NULL, + RMAP_EVENT_MATCH_DELETED); - return bgp_route_match_delete (vty, vty->index, "peer", argv[0]); + return bgp_route_match_delete (vty, vty->index, "peer", argv[0], + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_peer, @@ -2455,7 +2980,8 @@ DEFUN (match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip address", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip address", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ip_address, @@ -2467,9 +2993,11 @@ DEFUN (no_match_ip_address, "Match address of route\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip address", NULL); + return bgp_route_match_delete (vty, vty->index, "ip address", NULL, + RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip address", argv[0], + RMAP_EVENT_FILTER_DELETED); } ALIAS (no_match_ip_address, @@ -2493,7 +3021,8 @@ DEFUN (match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ip_next_hop, @@ -2505,9 +3034,11 @@ DEFUN (no_match_ip_next_hop, "Match next-hop address of route\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL); + return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL, + RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0], + RMAP_EVENT_FILTER_DELETED); } ALIAS (no_match_ip_next_hop, @@ -2530,7 +3061,8 @@ DEFUN (match_probability, "Match portion of routes defined by percentage value\n" "Percentage of routes\n") { - return bgp_route_match_add (vty, vty->index, "probability", argv[0]); + return bgp_route_match_add (vty, vty->index, "probability", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_probability, @@ -2540,7 +3072,8 @@ DEFUN (no_match_probability, MATCH_STR "Match portion of routes defined by percentage value\n") { - return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL); + return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL, + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_probability, @@ -2563,7 +3096,8 @@ DEFUN (match_ip_route_source, "IP access-list number (expanded range)\n" "IP standard access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ip_route_source, @@ -2575,9 +3109,11 @@ DEFUN (no_match_ip_route_source, "Match advertising source address of route\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL); + return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL, + RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, vty->index, "ip route-source", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip route-source", + argv[0], RMAP_EVENT_FILTER_DELETED); } ALIAS (no_match_ip_route_source, @@ -2600,7 +3136,8 @@ DEFUN (match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip address prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ip_address_prefix_list, @@ -2612,10 +3149,9 @@ DEFUN (no_match_ip_address_prefix_list, "Match address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL); - - return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_PLIST_DELETED); } ALIAS (no_match_ip_address_prefix_list, @@ -2637,7 +3173,8 @@ DEFUN (match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ip_next_hop_prefix_list, @@ -2649,10 +3186,9 @@ DEFUN (no_match_ip_next_hop_prefix_list, "Match next-hop address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL); - - return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_PLIST_DELETED); } ALIAS (no_match_ip_next_hop_prefix_list, @@ -2674,7 +3210,8 @@ DEFUN (match_ip_route_source_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ip_route_source_prefix_list, @@ -2686,10 +3223,9 @@ DEFUN (no_match_ip_route_source_prefix_list, "Match advertising source address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", NULL); - - return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_PLIST_DELETED); } ALIAS (no_match_ip_route_source_prefix_list, @@ -2709,7 +3245,8 @@ DEFUN (match_metric, "Match metric of route\n" "Metric value\n") { - return bgp_route_match_add (vty, vty->index, "metric", argv[0]); + return bgp_route_match_add (vty, vty->index, "metric", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_metric, @@ -2719,10 +3256,9 @@ DEFUN (no_match_metric, MATCH_STR "Match metric of route\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "metric", NULL); - - return bgp_route_match_delete (vty, vty->index, "metric", argv[0]); + return bgp_route_match_delete (vty, vty->index, "metric", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_metric, @@ -2733,6 +3269,40 @@ ALIAS (no_match_metric, "Match metric of route\n" "Metric value\n") +DEFUN (match_local_pref, + match_local_pref_cmd, + "match local-preference <0-4294967295>", + MATCH_STR + "Match local-preference of route\n" + "Metric value\n") +{ + return bgp_route_match_add (vty, vty->index, "local-preference", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_local_pref, + no_match_local_pref_cmd, + "no match local-preference", + NO_STR + MATCH_STR + "Match local preference of route\n") +{ + return bgp_route_match_delete (vty, vty->index, "local-preference", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "local-preference", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_local_pref, + no_match_local_pref_val_cmd, + "no match local-preference <0-4294967295>", + NO_STR + MATCH_STR + "Match local preference of route\n" + "Local preference value\n") + DEFUN (match_community, match_community_cmd, "match community (<1-99>|<100-500>|WORD)", @@ -2742,7 +3312,8 @@ DEFUN (match_community, "Community-list number (expanded)\n" "Community-list name\n") { - return bgp_route_match_add (vty, vty->index, "community", argv[0]); + return bgp_route_match_add (vty, vty->index, "community", argv[0], + RMAP_EVENT_CLIST_ADDED); } DEFUN (match_community_exact, @@ -2763,7 +3334,8 @@ DEFUN (match_community_exact, sprintf (argstr, "%s exact-match", argv[0]); - ret = bgp_route_match_add (vty, vty->index, "community", argstr); + ret = bgp_route_match_add (vty, vty->index, "community", argstr, + RMAP_EVENT_CLIST_ADDED); XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr); @@ -2777,7 +3349,8 @@ DEFUN (no_match_community, MATCH_STR "Match BGP community list\n") { - return bgp_route_match_delete (vty, vty->index, "community", NULL); + return bgp_route_match_delete (vty, vty->index, "community", NULL, + RMAP_EVENT_CLIST_DELETED); } ALIAS (no_match_community, @@ -2810,7 +3383,8 @@ DEFUN (match_ecommunity, "Extended community-list number (expanded)\n" "Extended community-list name\n") { - return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0]); + return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0], + RMAP_EVENT_ECLIST_ADDED); } DEFUN (no_match_ecommunity, @@ -2820,7 +3394,8 @@ DEFUN (no_match_ecommunity, MATCH_STR "Match BGP/VPN extended community list\n") { - return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL); + return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL, + RMAP_EVENT_ECLIST_DELETED); } ALIAS (no_match_ecommunity, @@ -2840,7 +3415,8 @@ DEFUN (match_aspath, "Match BGP AS path list\n" "AS path access-list name\n") { - return bgp_route_match_add (vty, vty->index, "as-path", argv[0]); + return bgp_route_match_add (vty, vty->index, "as-path", argv[0], + RMAP_EVENT_ASLIST_ADDED); } DEFUN (no_match_aspath, @@ -2850,7 +3426,8 @@ DEFUN (no_match_aspath, MATCH_STR "Match BGP AS path list\n") { - return bgp_route_match_delete (vty, vty->index, "as-path", NULL); + return bgp_route_match_delete (vty, vty->index, "as-path", NULL, + RMAP_EVENT_ASLIST_DELETED); } ALIAS (no_match_aspath, @@ -2871,11 +3448,14 @@ DEFUN (match_origin, "unknown heritage\n") { if (strncmp (argv[0], "igp", 2) == 0) - return bgp_route_match_add (vty, vty->index, "origin", "igp"); + return bgp_route_match_add (vty, vty->index, "origin", "igp", + RMAP_EVENT_MATCH_ADDED); if (strncmp (argv[0], "egp", 1) == 0) - return bgp_route_match_add (vty, vty->index, "origin", "egp"); + return bgp_route_match_add (vty, vty->index, "origin", "egp", + RMAP_EVENT_MATCH_ADDED); if (strncmp (argv[0], "incomplete", 2) == 0) - return bgp_route_match_add (vty, vty->index, "origin", "incomplete"); + return bgp_route_match_add (vty, vty->index, "origin", "incomplete", + RMAP_EVENT_MATCH_ADDED); return CMD_WARNING; } @@ -2887,7 +3467,8 @@ DEFUN (no_match_origin, MATCH_STR "BGP origin code\n") { - return bgp_route_match_delete (vty, vty->index, "origin", NULL); + return bgp_route_match_delete (vty, vty->index, "origin", NULL, + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_origin, @@ -2900,6 +3481,75 @@ ALIAS (no_match_origin, "local IGP\n" "unknown heritage\n") +DEFUN (match_interface, + match_interface_cmd, + "match interface WORD", + MATCH_STR + "Match first hop interface of route\n" + "Interface name\n") +{ + return bgp_route_match_add (vty, vty->index, "interface", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_interface, + no_match_interface_cmd, + "no match interface", + NO_STR + MATCH_STR + "Match first hop interface of route\n") +{ + if (argc == 0) + return bgp_route_match_delete (vty, vty->index, "interface", NULL, + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "interface", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_interface, + no_match_interface_val_cmd, + "no match interface WORD", + NO_STR + MATCH_STR + "Match first hop interface of route\n" + "Interface name\n") + +DEFUN (match_tag, + match_tag_cmd, + "match tag <1-65535>", + MATCH_STR + "Match tag of route\n" + "Tag value\n") +{ + return bgp_route_match_add (vty, vty->index, "tag", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_tag, + no_match_tag_cmd, + "no match tag", + NO_STR + MATCH_STR + "Match tag of route\n") +{ + if (argc == 0) + return bgp_route_match_delete (vty, vty->index, "tag", NULL, + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "tag", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_tag, + no_match_tag_val_cmd, + "no match tag <1-65535>", + NO_STR + MATCH_STR + "Match tag of route\n" + "Tag value\n") + + DEFUN (set_ip_nexthop, set_ip_nexthop_cmd, "set ip next-hop A.B.C.D", @@ -3313,7 +3963,7 @@ DEFUN (set_community_delete, SET_STR "set BGP community list (for deletion)\n" "Community-list number (standard)\n" - "Communitly-list number (expanded)\n" + "Community-list number (expanded)\n" "Community-list name\n" "Delete matching communities\n") { @@ -3346,7 +3996,7 @@ ALIAS (no_set_community_delete, SET_STR "set BGP community list (for deletion)\n" "Community-list number (standard)\n" - "Communitly-list number (expanded)\n" + "Community-list number (expanded)\n" "Community-list name\n" "Delete matching communities\n") @@ -3565,6 +4215,38 @@ ALIAS (no_set_aggregator_as, "AS number\n" "IP address of aggregator\n") +DEFUN (set_tag, + set_tag_cmd, + "set tag <1-65535>", + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") +{ + return bgp_route_set_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_set_tag, + no_set_tag_cmd, + "no set tag", + NO_STR + SET_STR + "Tag value for routing protocol\n") +{ + if (argc == 0) + bgp_route_set_delete(vty, vty->index, "tag", NULL); + + return bgp_route_set_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_set_tag, + no_set_tag_val_cmd, + "no set tag <1-65535>", + NO_STR + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") + + DEFUN (match_ipv6_address, match_ipv6_address_cmd, "match ipv6 address WORD", @@ -3573,7 +4255,8 @@ DEFUN (match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]); + return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ipv6_address, @@ -3585,7 +4268,8 @@ DEFUN (no_match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0], + RMAP_EVENT_FILTER_DELETED); } DEFUN (match_ipv6_next_hop, @@ -3596,7 +4280,8 @@ DEFUN (match_ipv6_next_hop, "Match IPv6 next-hop address of route\n" "IPv6 address of next hop\n") { - return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]); + return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ipv6_next_hop, @@ -3608,7 +4293,8 @@ DEFUN (no_match_ipv6_next_hop, "Match IPv6 next-hop address of route\n" "IPv6 address of next hop\n") { - return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0], + RMAP_EVENT_MATCH_DELETED); } DEFUN (match_ipv6_address_prefix_list, @@ -3620,7 +4306,8 @@ DEFUN (match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ipv6_address_prefix_list, @@ -3633,7 +4320,8 @@ DEFUN (no_match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", + argv[0], RMAP_EVENT_PLIST_DELETED); } DEFUN (set_ipv6_nexthop_peer, @@ -3863,10 +4551,12 @@ bgp_route_map_init (void) { route_map_init (); route_map_init_vty (); - route_map_add_hook (bgp_route_map_update); - route_map_delete_hook (bgp_route_map_update); + route_map_add_hook (bgp_route_map_add); + route_map_delete_hook (bgp_route_map_delete); + route_map_event_hook (bgp_route_map_event); route_map_install_match (&route_match_peer_cmd); + route_map_install_match (&route_match_local_pref_cmd); route_map_install_match (&route_match_ip_address_cmd); route_map_install_match (&route_match_ip_next_hop_cmd); route_map_install_match (&route_match_ip_route_source_cmd); @@ -3876,9 +4566,12 @@ bgp_route_map_init (void) route_map_install_match (&route_match_aspath_cmd); route_map_install_match (&route_match_community_cmd); route_map_install_match (&route_match_ecommunity_cmd); + route_map_install_match (&route_match_local_pref_cmd); route_map_install_match (&route_match_metric_cmd); route_map_install_match (&route_match_origin_cmd); route_map_install_match (&route_match_probability_cmd); + route_map_install_match (&route_match_interface_cmd); + route_map_install_match (&route_match_tag_cmd); route_map_install_set (&route_set_ip_nexthop_cmd); route_map_install_set (&route_set_local_pref_cmd); @@ -3895,6 +4588,7 @@ bgp_route_map_init (void) route_map_install_set (&route_set_originator_id_cmd); route_map_install_set (&route_set_ecommunity_rt_cmd); route_map_install_set (&route_set_ecommunity_soo_cmd); + route_map_install_set (&route_set_tag_cmd); install_element (RMAP_NODE, &match_peer_cmd); install_element (RMAP_NODE, &match_peer_local_cmd); @@ -3926,6 +4620,9 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &match_metric_cmd); install_element (RMAP_NODE, &no_match_metric_cmd); install_element (RMAP_NODE, &no_match_metric_val_cmd); + install_element (RMAP_NODE, &match_local_pref_cmd); + install_element (RMAP_NODE, &no_match_local_pref_cmd); + install_element (RMAP_NODE, &no_match_local_pref_val_cmd); install_element (RMAP_NODE, &match_community_cmd); install_element (RMAP_NODE, &match_community_exact_cmd); install_element (RMAP_NODE, &no_match_community_cmd); @@ -3940,6 +4637,12 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &match_probability_cmd); install_element (RMAP_NODE, &no_match_probability_cmd); install_element (RMAP_NODE, &no_match_probability_val_cmd); + install_element (RMAP_NODE, &match_interface_cmd); + install_element (RMAP_NODE, &no_match_interface_cmd); + install_element (RMAP_NODE, &no_match_interface_val_cmd); + install_element (RMAP_NODE, &match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_val_cmd); install_element (RMAP_NODE, &set_ip_nexthop_cmd); install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd); @@ -3991,6 +4694,9 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &set_originator_id_cmd); install_element (RMAP_NODE, &no_set_originator_id_cmd); install_element (RMAP_NODE, &no_set_originator_id_val_cmd); + install_element (RMAP_NODE, &set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_val_cmd); route_map_install_match (&route_match_ipv6_address_cmd); route_map_install_match (&route_match_ipv6_next_hop_cmd); @@ -4024,3 +4730,15 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &no_match_pathlimit_as_cmd); install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd); } + +void +bgp_route_map_terminate (void) +{ + /* ToDo: Cleanup all the used memory */ + + route_map_add_hook (NULL); + route_map_delete_hook (NULL); + route_map_event_hook (NULL); + route_map_finish(); + +} |