Merge pull request #3102 from ton31337/feature/match_blackhole_nexthops

bgpd: Match routes by type under route-maps
This commit is contained in:
David Lamparter 2018-10-02 11:29:59 +02:00 committed by GitHub
commit a762cf08c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 247 additions and 0 deletions

View File

@ -645,6 +645,45 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
route_match_ip_next_hop_prefix_list_compile,
route_match_ip_next_hop_prefix_list_free};
/* `match ip next-hop type <blackhole>' */
static route_map_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct bgp_info *bgp_info;
if (type == RMAP_BGP && prefix->family == AF_INET) {
bgp_info = (struct bgp_info *)object;
if (!bgp_info || !bgp_info->attr)
return RMAP_DENYMATCH;
/* If nexthop interface's index can't be resolved and nexthop is
set to any address then mark it as type `blackhole`.
This logic works for matching kernel/static routes like:
`ip route add blackhole 10.0.0.1`. */
if (bgp_info->attr->nexthop.s_addr == INADDR_ANY
&& !bgp_info->attr->nh_ifindex)
return RMAP_MATCH;
}
return RMAP_NOMATCH;
}
static void *route_match_ip_next_hop_type_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}
static void route_match_ip_next_hop_type_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
"ip next-hop type", route_match_ip_next_hop_type,
route_match_ip_next_hop_type_compile,
route_match_ip_next_hop_type_free};
/* `match ip route-source prefix-list PREFIX_LIST' */
static route_map_result_t
@ -2469,6 +2508,53 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
route_match_ipv6_address_prefix_list_compile,
route_match_ipv6_address_prefix_list_free};
/* `match ipv6 next-hop type <TYPE>' */
static route_map_result_t
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct bgp_info *bgp_info;
struct in6_addr *addr = rule;
if (type == RMAP_BGP && prefix->family == AF_INET6) {
bgp_info = (struct bgp_info *)object;
if (!bgp_info || !bgp_info->attr)
return RMAP_DENYMATCH;
if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr)
&& !bgp_info->attr->nh_ifindex)
return RMAP_MATCH;
}
return RMAP_NOMATCH;
}
static void *route_match_ipv6_next_hop_type_compile(const char *arg)
{
struct in6_addr *address;
int ret;
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
ret = inet_pton(AF_INET6, "::0", address);
if (!ret) {
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
return NULL;
}
return address;
}
static void route_match_ipv6_next_hop_type_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
"ipv6 next-hop type", route_match_ipv6_next_hop_type,
route_match_ipv6_next_hop_type_compile,
route_match_ipv6_next_hop_type_free};
/* `set ipv6 nexthop global IP_ADDRESS' */
/* Set nexthop to object. ojbect must be pointer to struct attr. */
@ -4766,12 +4852,18 @@ void bgp_route_map_init(void)
route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
route_map_match_ip_next_hop_type_hook(generic_match_add);
route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
route_map_match_ipv6_address_hook(generic_match_add);
route_map_no_match_ipv6_address_hook(generic_match_delete);
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
route_map_match_ipv6_next_hop_type_hook(generic_match_add);
route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
route_map_match_metric_hook(generic_match_add);
route_map_no_match_metric_hook(generic_match_delete);
@ -4800,6 +4892,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_ip_route_source_cmd);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ip_next_hop_type_cmd);
route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
route_map_install_match(&route_match_aspath_cmd);
route_map_install_match(&route_match_community_cmd);
@ -4915,6 +5008,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_next_hop_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);

View File

@ -111,6 +111,20 @@ struct route_map_match_set_hooks {
const char *arg,
route_map_event_t type);
/* match ip next hop type */
int (*match_ip_next_hop_type)(struct vty *vty,
struct route_map_index *index,
const char *command,
const char *arg,
route_map_event_t type);
/* no match ip next hop type */
int (*no_match_ip_next_hop_type)(struct vty *vty,
struct route_map_index *index,
const char *command,
const char *arg,
route_map_event_t type);
/* match ipv6 address */
int (*match_ipv6_address)(struct vty *vty,
struct route_map_index *index,
@ -138,6 +152,19 @@ struct route_map_match_set_hooks {
const char *arg,
route_map_event_t type);
/* match ipv6 next-hop type */
int (*match_ipv6_next_hop_type)(struct vty *vty,
struct route_map_index *index,
const char *command,
const char *arg,
route_map_event_t type);
/* no match ipv6next-hop type */
int (*no_match_ipv6_next_hop_type)(struct vty *vty,
struct route_map_index *index,
const char *command, const char *arg,
route_map_event_t type);
/* match metric */
int (*match_metric)(struct vty *vty, struct route_map_index *index,
const char *command, const char *arg,
@ -275,6 +302,22 @@ void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)(
rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func;
}
/* match ip next hop type */
void route_map_match_ip_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type))
{
rmap_match_set_hook.match_ip_next_hop_type = func;
}
/* no match ip next hop type */
void route_map_no_match_ip_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type))
{
rmap_match_set_hook.no_match_ip_next_hop_type = func;
}
/* match ipv6 address */
void route_map_match_ipv6_address_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
@ -308,6 +351,22 @@ void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)(
rmap_match_set_hook.no_match_ipv6_address_prefix_list = func;
}
/* match ipv6 next-hop type */
void route_map_match_ipv6_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type))
{
rmap_match_set_hook.match_ipv6_next_hop_type = func;
}
/* no match ipv6 next-hop type */
void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type))
{
rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
}
/* match metric */
void route_map_match_metric_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
@ -2034,6 +2093,45 @@ DEFUN (no_match_ip_next_hop_prefix_list,
return CMD_SUCCESS;
}
DEFUN(match_ip_next_hop_type, match_ip_next_hop_type_cmd,
"match ip next-hop type <blackhole>",
MATCH_STR IP_STR
"Match next-hop address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
int idx_word = 4;
VTY_DECLVAR_CONTEXT(route_map_index, index);
if (rmap_match_set_hook.match_ip_next_hop_type)
return rmap_match_set_hook.match_ip_next_hop_type(
vty, index, "ip next-hop type", argv[idx_word]->arg,
RMAP_EVENT_MATCH_ADDED);
return CMD_SUCCESS;
}
DEFUN(no_match_ip_next_hop_type, no_match_ip_next_hop_type_cmd,
"no match ip next-hop type [<blackhole>]",
NO_STR MATCH_STR IP_STR
"Match next-hop address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
int idx_word = 5;
VTY_DECLVAR_CONTEXT(route_map_index, index);
if (rmap_match_set_hook.no_match_ip_next_hop) {
if (argc <= idx_word)
return rmap_match_set_hook.no_match_ip_next_hop(
vty, index, "ip next-hop type", NULL,
RMAP_EVENT_MATCH_DELETED);
return rmap_match_set_hook.no_match_ip_next_hop(
vty, index, "ip next-hop type", argv[idx_word]->arg,
RMAP_EVENT_MATCH_DELETED);
}
return CMD_SUCCESS;
}
DEFUN (match_ipv6_address,
match_ipv6_address_cmd,
@ -2112,6 +2210,39 @@ DEFUN (no_match_ipv6_address_prefix_list,
return CMD_SUCCESS;
}
DEFUN(match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd,
"match ipv6 next-hop type <blackhole>",
MATCH_STR IPV6_STR
"Match address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
int idx_word = 4;
VTY_DECLVAR_CONTEXT(route_map_index, index);
if (rmap_match_set_hook.match_ipv6_next_hop_type)
return rmap_match_set_hook.match_ipv6_next_hop_type(
vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
RMAP_EVENT_MATCH_ADDED);
return CMD_SUCCESS;
}
DEFUN(no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd,
"no match ipv6 next-hop type [<blackhole>]",
NO_STR MATCH_STR IPV6_STR
"Match address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
int idx_word = 5;
VTY_DECLVAR_CONTEXT(route_map_index, index);
if (rmap_match_set_hook.no_match_ipv6_next_hop_type)
return rmap_match_set_hook.no_match_ipv6_next_hop_type(
vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
RMAP_EVENT_MATCH_DELETED);
return CMD_SUCCESS;
}
DEFUN (match_metric,
match_metric_cmd,
@ -2879,12 +3010,18 @@ void route_map_init(void)
install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &match_ip_next_hop_type_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_type_cmd);
install_element(RMAP_NODE, &match_ipv6_address_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_type_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_type_cmd);
install_element(RMAP_NODE, &match_metric_cmd);
install_element(RMAP_NODE, &no_match_metric_cmd);

View File

@ -289,6 +289,14 @@ extern void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
extern void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
/* match ip next hop type */
extern void route_map_match_ip_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
/* no match ip next hop type */
extern void route_map_no_match_ip_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
/* match ipv6 address */
extern void route_map_match_ipv6_address_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
@ -305,6 +313,14 @@ extern void route_map_match_ipv6_address_prefix_list_hook(int (*func)(
extern void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
/* match ipv6 next-hop type */
extern void route_map_match_ipv6_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
/* no match ipv6 next-hop type */
extern void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
/* match metric */
extern void route_map_match_metric_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,