From bc4131433590f605da05dd9f9d6d385dbbd1c1d0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 19 May 2015 17:40:47 -0700 Subject: [PATCH] bgpd: bgpd-route-map-match-interface.patch BGP: Add match interface support to BGP route-map. Currently, BGP route maps don't support interface match. This is a problem for commands such as redistribite connected that cannot exclude routes from specific interfaces (such as mgmt interfaces). --- bgpd/bgp_attr.h | 1 + bgpd/bgp_route.c | 3 +- bgpd/bgp_route.h | 2 +- bgpd/bgp_routemap.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_zebra.c | 10 +++-- 5 files changed, 101 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 2d796b5b70..5aa0c39f95 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -109,6 +109,7 @@ struct attr struct in_addr nexthop; u_int32_t med; u_int32_t local_pref; + u_int32_t nh_ifindex; /* Path origin attribute */ u_char origin; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index da9903a2a4..be6cb3b259 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5592,7 +5592,7 @@ ALIAS (no_ipv6_aggregate_address_summary_only, /* Redistribute route treatment. */ void bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, - const struct in6_addr *nexthop6, + const struct in6_addr *nexthop6, unsigned int ifindex, u_int32_t metric, u_char type) { struct bgp *bgp; @@ -5610,6 +5610,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); if (nexthop) attr.nexthop = *nexthop; + attr.nh_ifindex = ifindex; #ifdef HAVE_IPV6 if (nexthop6) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 23337961ec..905295b94e 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -216,7 +216,7 @@ extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add (struct prefix *, const struct in_addr *, - const struct in6_addr *, + const struct in6_addr *, unsigned int ifindex, u_int32_t, u_char); extern void bgp_redistribute_delete (struct prefix *, u_char); extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 3204daba51..49cde8ea95 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -64,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 @@ -951,6 +951,58 @@ 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 nexthop *nexthop; + 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' */ @@ -3361,6 +3413,40 @@ 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 (set_ip_nexthop, set_ip_nexthop_cmd, "set ip next-hop A.B.C.D", @@ -4334,6 +4420,7 @@ bgp_route_map_init (void) 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_set (&route_set_ip_nexthop_cmd); route_map_install_set (&route_set_local_pref_cmd); @@ -4398,6 +4485,9 @@ 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, &set_ip_nexthop_cmd); install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index c109eaba93..9391030c1e 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -380,6 +380,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) struct zapi_ipv4 api; struct in_addr nexthop; struct prefix_ipv4 p; + unsigned int ifindex; s = zclient->ibuf; nexthop.s_addr = 0; @@ -404,7 +405,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); - stream_getl (s); /* ifindex, unused */ + ifindex = stream_getl (s); /* ifindex, unused */ } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); @@ -425,7 +426,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), api.metric); } - bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, + bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex, api.metric, api.type); } else @@ -456,6 +457,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) struct zapi_ipv6 api; struct in6_addr nexthop; struct prefix_ipv6 p; + unsigned int ifindex; s = zclient->ibuf; memset (&nexthop, 0, sizeof (struct in6_addr)); @@ -480,7 +482,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); - stream_getl (s); /* ifindex, unused */ + ifindex = stream_getl (s); /* ifindex, unused */ } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); @@ -507,7 +509,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), api.metric); } - bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, + bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex, api.metric, api.type); } else -- 2.39.5