From: Dinesh Dutt <[email protected]> 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).
Signed-off-by: Dinesh Dutt <[email protected]> --- bgpd/bgp_attr.h | 1 + bgpd/bgp_route.c | 3 +- bgpd/bgp_route.h | 2 +- bgpd/bgp_routemap.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_zebra.c | 18 ++++++++--- vtysh/extract.pl.in | 2 +- 6 files changed, 109 insertions(+), 8 deletions(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 8018104..e63202c 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 fc84ea6..69811fb 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5556,7 +5556,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; @@ -5574,6 +5574,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 ef7ffe2..a97fe11 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 b41d235..320393d 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 @@ -1005,6 +1005,57 @@ 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' */ @@ -3314,6 +3365,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", @@ -4305,6 +4390,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); @@ -4369,6 +4455,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 bc52ab1..339ed12 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -386,6 +386,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; @@ -410,7 +411,11 @@ 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 */ + } + else + { + ifindex = 0; } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); @@ -431,7 +436,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 @@ -463,6 +468,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)); @@ -487,7 +493,11 @@ 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 */ + } + else + { + ifindex = 0; } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); @@ -514,7 +524,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 diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index f9a6dc6..8415e7e 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -177,7 +177,7 @@ foreach (@ARGV) { } } -my $bad_cli_stomps = 90; +my $bad_cli_stomps = 93; # Currently we have $bad_cli_stomps. This was determined by # running this script and counting up the collisions from what # was returned. -- 1.9.1 _______________________________________________ Quagga-dev mailing list [email protected] https://lists.quagga.net/mailman/listinfo/quagga-dev
