From 951745bdabeb4aeb63a968a683dc18df6a744091 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 29 Apr 2019 15:26:01 +0200 Subject: [PATCH 1/3] bgpd: ability to export prefixes entries to a kernel table identifier this table identifier can be used for policy routing. incoming entries are locally exported to that local table identifier. note that so that the user applies the new table identifier to all entries, the user should flush local tables first. Signed-off-by: Philippe Guibert --- bgpd/bgp_attr.c | 2 ++ bgpd/bgp_attr.h | 3 +++ bgpd/bgp_routemap.c | 56 +++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_zebra.c | 5 ++++ doc/user/routemap.rst | 5 ++++ 5 files changed, 71 insertions(+) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index a7cd3fee88..10e78cbc96 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -520,6 +520,7 @@ unsigned int attrhash_key_make(const void *p) key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key); key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key); MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance); + MIX(attr->rmap_table_id); return key; } @@ -546,6 +547,7 @@ bool attrhash_cmp(const void *p1, const void *p2) && attr1->lcommunity == attr2->lcommunity && attr1->cluster == attr2->cluster && attr1->transit == attr2->transit + && attr1->rmap_table_id == attr2->rmap_table_id && (attr1->encap_tunneltype == attr2->encap_tunneltype) && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs) #if ENABLE_BGP_VNC diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index cfa428a796..eacd37b652 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -209,6 +209,9 @@ struct attr { /* Distance as applied by Route map */ uint8_t distance; + + /* rmap set table */ + uint32_t rmap_table_id; }; /* rmap_change_flags definition */ diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index a5286cea69..a038b0e7a9 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -114,6 +114,7 @@ o Cisco route-map origin : Done tag : Done weight : Done + table : Done o Local extensions @@ -1754,6 +1755,32 @@ struct route_map_rule_cmd route_set_metric_cmd = { "metric", route_set_metric, route_value_compile, route_value_free, }; +/* `set table (1-4294967295)' */ + +static enum route_map_cmd_result_t route_set_table_id(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_value *rv; + struct bgp_path_info *path; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + rv = rule; + path = object; + + path->attr->rmap_table_id = rv->value; + } + return RMAP_OKAY; +} + +/* Set table_id rule structure. */ +static struct route_map_rule_cmd route_set_table_id_cmd = { + "table", route_set_table_id, + route_value_compile, route_value_free +}; + /* `set as-path prepend ASPATH' */ /* For AS path prepend mechanism. */ @@ -4058,6 +4085,32 @@ DEFUN (no_match_origin, RMAP_EVENT_MATCH_DELETED); } +DEFUN (set_table_id, + set_table_id_cmd, + "set table (1-4294967295)", + SET_STR + "export route to non-main kernel table\n" + "Kernel routing table id\n") +{ + int idx_id = 2; + + VTY_DECLVAR_CONTEXT(route_map_index, index); + + return generic_set_add(vty, index, "table", argv[idx_id]->arg); +} + +DEFUN (no_set_table_id, + no_set_table_id_cmd, + "no set table", + NO_STR + SET_STR + "export route to non-main kernel table\n") +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + + return generic_set_delete(vty, index, "table", NULL); +} + DEFUN (set_ip_nexthop_peer, set_ip_nexthop_peer_cmd, "[no] set ip next-hop peer-address", @@ -5167,6 +5220,7 @@ void bgp_route_map_init(void) route_map_install_match(&route_match_evpn_default_route_cmd); route_map_install_match(&route_match_vrl_source_vrf_cmd); + route_map_install_set(&route_set_table_id_cmd); route_map_install_set(&route_set_ip_nexthop_cmd); route_map_install_set(&route_set_local_pref_cmd); route_map_install_set(&route_set_weight_cmd); @@ -5223,6 +5277,8 @@ void 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_set_table_id_cmd); + install_element(RMAP_NODE, &set_table_id_cmd); install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd); install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd); install_element(RMAP_NODE, &set_local_pref_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 8970e9d1d1..c9dd0f4bcb 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1228,6 +1228,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); + if (info->attr->rmap_table_id) { + SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID); + api.tableid = info->attr->rmap_table_id; + } + /* Metric is currently based on the best-path only */ metric = info->attr->med; for (mpinfo = info; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) { diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst index e36783d176..5c2b41b63c 100644 --- a/doc/user/routemap.rst +++ b/doc/user/routemap.rst @@ -306,6 +306,11 @@ Route Map Set Command Set BGP route origin. +.. index:: set table (1-4294967295) +.. clicmd:: set table (1-4294967295) + + Set the BGP table to a given table identifier + .. _route-map-call-command: Route Map Call Command From 1276ce38331b2cc190bd67392b07685d1d35d1ff Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 9 Jul 2019 10:59:14 +0200 Subject: [PATCH 2/3] bgpd: withdraw fib entry on appropriate table identifier There are cases where the table identifier is set on a bgp entry, mainly due to route-map, and associate fib entry needs to be removed. This change encompasses also the route-map reconfiguration that leads to removing the previous entry, whereas bgp update had been triggered ( this happens when software inbound reconfiguration is handled). Signed-off-by: Philippe Guibert --- bgpd/bgp_route.c | 7 +++++++ bgpd/bgp_zebra.c | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f0629fca08..3f30441f7b 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3165,6 +3165,13 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, goto filtered; } + if (pi && pi->attr && + pi->attr->rmap_table_id != new_attr.rmap_table_id) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) + /* remove from RIB previous entry */ + bgp_zebra_withdraw(p, pi, bgp, safi); + } + if (peer->sort == BGP_PEER_EBGP) { /* If we receive the graceful-shutdown community from an eBGP diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index c9dd0f4bcb..7923f076c1 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1499,6 +1499,11 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_path_info *info, api.safi = safi; api.prefix = *p; + if (info->attr->rmap_table_id) { + SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID); + api.tableid = info->attr->rmap_table_id; + } + /* If the route's source is EVPN, flag as such. */ if (is_route_parent_evpn(info)) SET_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE); From 60ca3cc27d6d61e7a5a7921d00ed76ca42d44bd7 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 9 Jul 2019 11:09:19 +0200 Subject: [PATCH 3/3] zebra: entries can be pushed in tables, under vrf netns backend initially, vrf backend if vrf-lite, and a specific table identifier is associated to a vrf. here, with netns vrf backend, there is no specific table assigned to except default routing table. use the passed table_id parameter in zapi api, and apply it to the entry to be pushed in, or to be removed. Signed-off-by: Philippe Guibert --- zebra/zapi_msg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index ffdc4dc512..b0488b7559 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1425,7 +1425,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) re->flags = api.flags; re->uptime = monotime(NULL); re->vrf_id = vrf_id; - if (api.tableid && vrf_id == VRF_DEFAULT) + if (api.tableid) re->table = api.tableid; else re->table = zvrf->table_id; @@ -1624,7 +1624,7 @@ static void zread_route_del(ZAPI_HANDLER_ARGS) if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) src_p = &api.src_prefix; - if (api.vrf_id == VRF_DEFAULT && api.tableid != 0) + if (api.tableid) table_id = api.tableid; else table_id = zvrf->table_id;