mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 16:57:44 +00:00
bgpd: Match routes by type under route-maps
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
parent
84bc4ef140
commit
61ad901e57
@ -548,6 +548,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
|
||||
@ -2372,6 +2411,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. */
|
||||
@ -4645,12 +4731,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);
|
||||
|
||||
@ -4676,6 +4768,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);
|
||||
@ -4791,6 +4884,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);
|
||||
|
137
lib/routemap.c
137
lib/routemap.c
@ -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,
|
||||
@ -2028,6 +2087,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,
|
||||
@ -2106,6 +2204,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,
|
||||
@ -2873,12 +3004,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);
|
||||
|
||||
|
@ -283,6 +283,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,
|
||||
@ -299,6 +307,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,
|
||||
|
Loading…
Reference in New Issue
Block a user