From: Don Slice Date: Wed, 11 May 2016 15:47:02 +0000 (-0700) Subject: zebra: Add route-map support to ip import-table X-Git-Tag: frr-2.0-rc1~919 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=8902474bd30dd843f0c35424e273718f7079a795;p=mirror%2Ffrr.git zebra: Add route-map support to ip import-table Added the ability to supply a route-map to the ip import-table command, which greatly improves filtering between the kernel prefixes in a non-default table that are imported into the zebra rib. Ticket:CM-8168 Signed-off-by: Donald Slice Reviewed By: Donald Sharp --- diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 03310ad3f0..4d94ddf622 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -36,6 +36,7 @@ #include "zebra/zserv.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" +#include "zebra/zebra_routemap.h" #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/router-id.h" @@ -559,52 +560,64 @@ zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id) } int -zebra_add_import_table_entry (struct route_node *rn, struct rib *rib) +zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char *rmap_name) { struct rib *newrib; struct prefix_ipv4 p4; struct nexthop *nhop; struct in_addr *gate; + route_map_result_t ret = RMAP_MATCH; - if (rn->p.family == AF_INET) + if (rmap_name) + ret = zebra_import_table_route_map_check (AFI_IP, rib->type, &rn->p, rib->nexthop, rib->vrf_id, + rib->tag, rmap_name); + + if (ret == RMAP_MATCH) { - p4.family = AF_INET; - p4.prefixlen = rn->p.prefixlen; - p4.prefix = rn->p.u.prefix4; + if (rn->p.family == AF_INET) + { + p4.family = AF_INET; + p4.prefixlen = rn->p.prefixlen; + p4.prefix = rn->p.u.prefix4; - if (rib->nexthop_num == 1) - { - nhop = rib->nexthop; - if (nhop->type == NEXTHOP_TYPE_IFINDEX) - gate = NULL; - else - gate = &nhop->gate.ipv4; - - rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, - gate, &nhop->src.ipv4, - nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default, - rib->metric, - zebra_import_table_distance[AFI_IP][rib->table], - SAFI_UNICAST); - } - else if (rib->nexthop_num > 1) - { - newrib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - newrib->type = ZEBRA_ROUTE_TABLE; - newrib->distance = zebra_import_table_distance[AFI_IP][rib->table]; - newrib->flags = rib->flags; - newrib->metric = rib->metric; - newrib->table = zebrad.rtm_table_default; - newrib->nexthop_num = 0; - newrib->uptime = time(NULL); - newrib->instance = rib->table; - - /* Assuming these routes are never recursive */ - for (nhop = rib->nexthop; nhop; nhop = nhop->next) - rib_copy_nexthops(newrib, nhop); - - rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST); - } + if (rib->nexthop_num == 1) + { + nhop = rib->nexthop; + if (nhop->type == NEXTHOP_TYPE_IFINDEX) + gate = NULL; + else + gate = &nhop->gate.ipv4; + + rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, + gate, &nhop->src.ipv4, + nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default, + rib->metric, + zebra_import_table_distance[AFI_IP][rib->table], + SAFI_UNICAST); + } + else if (rib->nexthop_num > 1) + { + newrib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); + newrib->type = ZEBRA_ROUTE_TABLE; + newrib->distance = zebra_import_table_distance[AFI_IP][rib->table]; + newrib->flags = rib->flags; + newrib->metric = rib->metric; + newrib->table = zebrad.rtm_table_default; + newrib->nexthop_num = 0; + newrib->uptime = time(NULL); + newrib->instance = rib->table; + + /* Assuming these routes are never recursive */ + for (nhop = rib->nexthop; nhop; nhop = nhop->next) + rib_copy_nexthops(newrib, nhop); + + rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST); + } + } + } + else + { + zebra_del_import_table_entry (rn, rib); } /* DD: Add IPv6 code */ return 0; @@ -631,7 +644,7 @@ zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) /* Assuming no one calls this with the main routing table */ int -zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, int add) +zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, const char *rmap_name, int add) { struct route_table *table; struct rib *rib; @@ -657,6 +670,15 @@ zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, int add) if (add) { + if (rmap_name) + zebra_add_import_table_route_map (afi, rmap_name, table_id); + else + { + rmap_name = zebra_get_import_table_route_map (afi, table_id); + if (rmap_name) + zebra_del_import_table_route_map (afi, table_id); + } + SET_FLAG(zebra_import_table_used[table_id], afi); zebra_import_table_distance[afi][table_id] = distance; } @@ -664,6 +686,10 @@ zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, int add) { UNSET_FLAG(zebra_import_table_used[table_id], (u_char)afi); zebra_import_table_distance[afi][table_id] = ZEBRA_TABLE_DISTANCE_DEFAULT; + + rmap_name = zebra_get_import_table_route_map (afi, table_id); + if (rmap_name) + zebra_del_import_table_route_map (afi, table_id); } for (rn = route_top(table); rn; rn = route_next(rn)) @@ -688,7 +714,7 @@ zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, int add) ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) { if (add) - zebra_add_import_table_entry (rn, rib); + zebra_add_import_table_entry (rn, rib, rmap_name); else zebra_del_import_table_entry (rn, rib); } @@ -703,6 +729,7 @@ zebra_import_table_config (struct vty *vty) afi_t afi; int write = 0; char afi_str[AFI_MAX][6] = {"", "ip", "ipv6"}; + const char *rmap_name; for (afi = AFI_IP; afi < AFI_MAX; afi++) { @@ -712,14 +739,19 @@ zebra_import_table_config (struct vty *vty) { if (zebra_import_table_distance[afi][i] != ZEBRA_TABLE_DISTANCE_DEFAULT) { - vty_out(vty, "%s import-table %d distance %d%s", afi_str[afi], - i, zebra_import_table_distance[afi][i], VTY_NEWLINE); + vty_out(vty, "%s import-table %d distance %d", afi_str[afi], + i, zebra_import_table_distance[afi][i]); } else { - vty_out(vty, "%s import-table %d%s", afi_str[afi], i, - VTY_NEWLINE); + vty_out(vty, "%s import-table %d", afi_str[afi], i); } + + rmap_name = zebra_get_import_table_route_map (afi, i); + if (rmap_name) + vty_out(vty, " route-map %s", rmap_name); + + vty_out(vty, "%s", VTY_NEWLINE); write = 1; } } @@ -727,3 +759,53 @@ zebra_import_table_config (struct vty *vty) return write; } + +void +zebra_import_table_rm_update () +{ + afi_t afi; + int i; + struct route_table *table; + struct rib *rib; + struct route_node *rn; + const char *rmap_name; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + { + for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) + { + if (is_zebra_import_table_enabled(afi, i)) + { + rmap_name = zebra_get_import_table_route_map (afi, i); + if (!rmap_name) + return; + + table = zebra_vrf_other_route_table(afi, i, VRF_DEFAULT); + for (rn = route_top(table); rn; rn = route_next(rn)) + { + /* For each entry in the non-default routing table, + * add the entry in the main table + */ + if (!rn->info) + continue; + + RNODE_FOREACH_RIB (rn, rib) + { + if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) + continue; + break; + } + + if (!rib) + continue; + + if (((afi == AFI_IP) && (rn->p.family == AF_INET)) || + ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) + zebra_add_import_table_entry (rn, rib, rmap_name); + } + } + } + } + + return; +} diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 702fff43f9..5e3cf1bfd3 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -51,17 +51,20 @@ extern void zebra_interface_address_delete_update (struct interface *, struct connected *c); extern void zebra_interface_vrf_update_del (struct interface *, vrf_id_t new_vrf_id); extern void zebra_interface_vrf_update_add (struct interface *, vrf_id_t old_vrf_id); + extern int zebra_import_table (afi_t afi, u_int32_t table_id, - u_int32_t metric, int add); + u_int32_t distance, const char *rmap_name, int add); extern int zebra_add_import_table_entry (struct route_node *rn, - struct rib *rib); + struct rib *rib, const char *rmap_name); extern int zebra_del_import_table_entry (struct route_node *rn, struct rib *rib); extern int is_zebra_import_table_enabled(afi_t, u_int32_t table_id); extern int zebra_import_table_config(struct vty *); +extern void zebra_import_table_rm_update(void); + extern int is_default (struct prefix *); #endif /* _ZEBRA_REDISTRIBUTE_H */ diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c index 17248cdf55..40cb8de18d 100644 --- a/zebra/redistribute_null.c +++ b/zebra/redistribute_null.c @@ -65,11 +65,11 @@ void zebra_interface_vrf_update_del (struct interface *a, vrf_id_t new_vrf_id) void zebra_interface_vrf_update_add (struct interface *a, vrf_id_t old_vrf_id) { return; } -int zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t metric, - int add) +int zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, + const char *rmap_name, int add) { return 0; } -int zebra_add_import_table_entry (struct route_node *rn, struct rib *rib) +int zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char *rmap_name) { return 0; } int zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) @@ -80,3 +80,6 @@ int is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id) int zebra_import_table_config(struct vty *vty) { return 0; } + +void zebra_import_table_rm_update() +{ return; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 7430532364..e34293d552 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -43,6 +43,7 @@ #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" #include "zebra/redistribute.h" +#include "zebra/zebra_routemap.h" #include "zebra/debug.h" #include "zebra/zebra_fpm.h" #include "zebra/zebra_rnh.h" @@ -2130,6 +2131,7 @@ rib_link (struct route_node *rn, struct rib *rib, int process) rib_dest_t *dest; char buf[INET6_ADDRSTRLEN]; afi_t afi; + const char *rmap_name; assert (rib && rn); @@ -2160,7 +2162,10 @@ rib_link (struct route_node *rn, struct rib *rib, int process) afi = (rn->p.family == AF_INET) ? AFI_IP : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; if (is_zebra_import_table_enabled (afi, rib->table)) - zebra_add_import_table_entry(rn, rib); + { + rmap_name = zebra_get_import_table_route_map (afi, rib->table); + zebra_add_import_table_entry(rn, rib, rmap_name); + } else if (process) rib_queue_add (rn); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 0d6728d111..8b76ea65c9 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -46,6 +46,7 @@ #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/zebra_rnh.h" +#include "zebra/zebra_routemap.h" #include "zebra/interface.h" static void free_state(vrf_id_t vrf_id, struct rib *rib, struct route_node *rn); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index f083693e4e..db3e5eaba1 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -32,6 +32,7 @@ #include "vrf.h" #include "zebra/zserv.h" +#include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/zebra_rnh.h" #include "zebra/zebra_routemap.h" @@ -41,6 +42,7 @@ static struct thread *zebra_t_rmap_update = NULL; char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ /* NH Tracking route map */ char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ +char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; struct nh_rmap_obj { @@ -1610,6 +1612,7 @@ zebra_route_map_update_timer (struct thread *thread) zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing", VRF_DEFAULT); + zebra_import_table_rm_update (); rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); @@ -1664,6 +1667,47 @@ zebra_route_map_check (int family, int rib_type, struct prefix *p, return (ret); } +char * +zebra_get_import_table_route_map (afi_t afi, uint32_t table) +{ + return zebra_import_table_routemap[afi][table]; +} + +void +zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table) +{ + zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name); +} + +void +zebra_del_import_table_route_map (afi_t afi, uint32_t table) +{ + XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]); +} + +route_map_result_t +zebra_import_table_route_map_check (int family, int rib_type, struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, u_short tag, const char *rmap_name) +{ + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_DENYMATCH; + struct nh_rmap_obj nh_obj; + + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; + nh_obj.source_protocol = rib_type; + nh_obj.metric = 0; + nh_obj.tag = tag; + + if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name (rmap_name); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } + + return (ret); +} + route_map_result_t zebra_nht_route_map_check (int family, int client_proto, struct prefix *p, struct rib * rib, struct nexthop *nexthop) diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index 0449601280..5eb3740909 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -24,5 +24,28 @@ #define __ZEBRA_ROUTEMAP_H__ extern void zebra_routemap_config_write_protocol(struct vty *vty); +extern char *zebra_get_import_table_route_map (afi_t afi, uint32_t table); +extern void zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table); +extern void zebra_del_import_table_route_map (afi_t afi, uint32_t table); + +extern void zebra_route_map_write_delay_timer(struct vty *); + +extern route_map_result_t zebra_import_table_route_map_check (int family, int rib_type, + struct prefix *p, + struct nexthop *nexthop, + vrf_id_t vrf_id, + u_short tag, + const char *rmap_name); +extern route_map_result_t zebra_route_map_check (int family, int rib_type, + struct prefix *p, + struct nexthop *nexthop, + vrf_id_t vrf_id, + u_short tag); +extern route_map_result_t zebra_nht_route_map_check (int family, + int client_proto, + struct prefix *p, + struct rib *, + struct nexthop *nexthop); + #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 1b5de1dc5d..97cfc16f48 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -5646,13 +5646,9 @@ DEFUN (ip_zebra_import_table_distance, return CMD_WARNING; } - if (is_zebra_import_table_enabled(AFI_IP, table_id)) - return CMD_SUCCESS; - if (argc > 1) VTY_GET_INTEGER_RANGE("distance", distance, argv[1], 1, 255); - - return (zebra_import_table(AFI_IP, table_id, distance, 1)); + return (zebra_import_table(AFI_IP, table_id, distance, NULL, 1)); } @@ -5663,9 +5659,61 @@ ALIAS (ip_zebra_import_table_distance, "import routes from non-main kernel table\n" "kernel routing table id\n") +DEFUN (ip_zebra_import_table_distance_routemap, + ip_zebra_import_table_distance_routemap_cmd, + "ip import-table <1-252> distance <1-255> route-map WORD", + IP_STR + "import routes from non-main kernel table\n" + "kernel routing table id\n" + "Distance for imported routes\n" + "Default distance value\n" + "route-map for filtering\n" + "route-map name\n") +{ + u_int32_t table_id = 0; + int distance = ZEBRA_TABLE_DISTANCE_DEFAULT; + const char *rmap_name; + + if (argc) + VTY_GET_INTEGER("table", table_id, argv[0]); + + if (!is_zebra_valid_kernel_table(table_id)) + { + vty_out(vty, "Invalid routing table ID, %d. Must be in range 1-252%s", + table_id, VTY_NEWLINE); + return CMD_WARNING; + } + + if (is_zebra_main_routing_table(table_id)) + { + vty_out(vty, "Invalid routing table ID, %d. Must be non-default table%s", + table_id, VTY_NEWLINE); + return CMD_WARNING; + } + + if (argc > 2) + { + VTY_GET_INTEGER_RANGE("distance", distance, argv[1], 1, 255); + rmap_name = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[2]); + } + else + rmap_name = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]); + + return (zebra_import_table(AFI_IP, table_id, distance, rmap_name, 1)); +} + +ALIAS (ip_zebra_import_table_distance_routemap, + ip_zebra_import_table_routemap_cmd, + "ip import-table <1-252> route-map WORD", + IP_STR + "import routes from non-main kernel table\n" + "kernel routing table id\n" + "route-map for filtering\n" + "route-map name\n") + DEFUN (no_ip_zebra_import_table, no_ip_zebra_import_table_cmd, - "no ip import-table <1-252>", + "no ip import-table <1-252> {route-map NAME}", NO_STR IP_STR "import routes from non-main kernel table\n" @@ -5693,12 +5741,12 @@ DEFUN (no_ip_zebra_import_table, if (!is_zebra_import_table_enabled(AFI_IP, table_id)) return CMD_SUCCESS; - return (zebra_import_table(AFI_IP, table_id, 0, 0)); + return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0)); } ALIAS (no_ip_zebra_import_table, no_ip_zebra_import_table_distance_cmd, - "no ip import-table <1-252> distance <1-255>", + "no ip import-table <1-252> distance <1-255> {route-map NAME}", IP_STR "import routes from non-main kernel table to main table" "kernel routing table id\n" @@ -5786,6 +5834,8 @@ zebra_vty_init (void) install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance2_cmd); install_element (CONFIG_NODE, &ip_zebra_import_table_cmd); install_element (CONFIG_NODE, &ip_zebra_import_table_distance_cmd); + install_element (CONFIG_NODE, &ip_zebra_import_table_routemap_cmd); + install_element (CONFIG_NODE, &ip_zebra_import_table_distance_routemap_cmd); install_element (CONFIG_NODE, &no_ip_zebra_import_table_cmd); install_element (CONFIG_NODE, &no_ip_zebra_import_table_distance_cmd); diff --git a/zebra/zserv.h b/zebra/zserv.h index e055672990..16700ee523 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -171,16 +171,4 @@ extern void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id) extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const u_char); extern int zebra_server_send_message(struct zserv *client); -extern void zebra_route_map_write_delay_timer(struct vty *); -extern route_map_result_t zebra_route_map_check (int family, int rib_type, - struct prefix *p, - struct nexthop *nexthop, - vrf_id_t vrf_id, - u_short tag); -extern route_map_result_t zebra_nht_route_map_check (int family, - int client_proto, - struct prefix *p, - struct rib *, - struct nexthop *nexthop); - #endif /* _ZEBRA_ZEBRA_H */