mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 11:50:21 +00:00
bgpd: Implement match source-protocol
for route-maps
The main idea is to filter routes by matching source (originating) protocol for outgoing direction. For instance, filter outgoing routes to an arbitrary router that are static only. Or filter out only routes learned from RIP. Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
parent
052fa79dd2
commit
1c035c8c2c
@ -872,6 +872,46 @@ static const struct route_map_rule_cmd
|
||||
route_match_ip_next_hop_type_free
|
||||
};
|
||||
|
||||
/* `match source-protocol` */
|
||||
static enum route_map_cmd_result_t
|
||||
route_match_source_protocol(void *rule, const struct prefix *prefix,
|
||||
void *object)
|
||||
{
|
||||
struct bgp_path_info *path = object;
|
||||
int *protocol = rule;
|
||||
|
||||
if (!path)
|
||||
return RMAP_NOMATCH;
|
||||
|
||||
if (path->type == *protocol)
|
||||
return RMAP_MATCH;
|
||||
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
static void *route_match_source_protocol_compile(const char *arg)
|
||||
{
|
||||
int *protocol;
|
||||
|
||||
protocol = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*protocol));
|
||||
*protocol = proto_name2num(arg);
|
||||
|
||||
return protocol;
|
||||
}
|
||||
|
||||
static void route_match_source_protocol_free(void *rule)
|
||||
{
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
|
||||
"source-protocol",
|
||||
route_match_source_protocol,
|
||||
route_match_source_protocol_compile,
|
||||
route_match_source_protocol_free
|
||||
};
|
||||
|
||||
|
||||
/* `match ip route-source prefix-list PREFIX_LIST' */
|
||||
|
||||
static enum route_map_cmd_result_t
|
||||
@ -7177,6 +7217,42 @@ DEFPY_YANG (match_rpki_extcommunity,
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY_YANG (match_source_protocol,
|
||||
match_source_protocol_cmd,
|
||||
"match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
|
||||
MATCH_STR
|
||||
"Match protocol via which the route was learnt\n"
|
||||
FRR_REDIST_HELP_STR_ZEBRA)
|
||||
{
|
||||
const char *xpath =
|
||||
"./match-condition[condition='frr-bgp-route-map:source-protocol']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
snprintf(xpath_value, sizeof(xpath_value),
|
||||
"%s/rmap-match-condition/frr-bgp-route-map:source-protocol",
|
||||
xpath);
|
||||
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY_YANG (no_match_source_protocol,
|
||||
no_match_source_protocol_cmd,
|
||||
"no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
"Match protocol via which the route was learnt\n"
|
||||
FRR_REDIST_HELP_STR_ZEBRA)
|
||||
{
|
||||
const char *xpath =
|
||||
"./match-condition[condition='frr-bgp-route-map:source-protocol']";
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
/* Initialization of route map. */
|
||||
void bgp_route_map_init(void)
|
||||
{
|
||||
@ -7252,6 +7328,7 @@ void bgp_route_map_init(void)
|
||||
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_source_protocol_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);
|
||||
@ -7441,6 +7518,8 @@ void bgp_route_map_init(void)
|
||||
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
|
||||
install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
|
||||
install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
|
||||
install_element(RMAP_NODE, &match_source_protocol_cmd);
|
||||
install_element(RMAP_NODE, &no_match_source_protocol_cmd);
|
||||
#ifdef HAVE_SCRIPTING
|
||||
install_element(RMAP_NODE, &match_script_cmd);
|
||||
#endif
|
||||
|
@ -74,6 +74,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
|
||||
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_source_vrf_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:source-protocol",
|
||||
.cbs = {
|
||||
.modify = lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_modify,
|
||||
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
|
||||
.cbs = {
|
||||
|
@ -30,6 +30,10 @@ int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_m
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_probability_modify(struct nb_cb_modify_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_probability_destroy(struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_source_vrf_modify(struct nb_cb_modify_args *args);
|
||||
|
@ -367,6 +367,60 @@ lib_route_map_entry_match_condition_rmap_match_condition_rpki_destroy(
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:source-protocol
|
||||
*/
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_modify(
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct routemap_hook_context *rhc;
|
||||
enum rmap_compile_rets ret;
|
||||
const char *proto;
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
/* Add configuration. */
|
||||
rhc = nb_running_get_entry(args->dnode, NULL, true);
|
||||
proto = yang_dnode_get_string(args->dnode, NULL);
|
||||
|
||||
/* Set destroy information. */
|
||||
rhc->rhc_mhook = bgp_route_match_delete;
|
||||
rhc->rhc_rule = "source-protocol";
|
||||
rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
|
||||
|
||||
ret = bgp_route_match_add(rhc->rhc_rmi, "source-protocol",
|
||||
proto, RMAP_EVENT_MATCH_ADDED,
|
||||
args->errmsg, args->errmsg_len);
|
||||
|
||||
if (ret != RMAP_COMPILE_SUCCESS) {
|
||||
rhc->rhc_mhook = NULL;
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_destroy(
|
||||
struct nb_cb_destroy_args *args)
|
||||
{
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
return lib_route_map_entry_match_destroy(args);
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity
|
||||
|
@ -259,6 +259,8 @@ DECLARE_QOBJ_TYPE(route_map);
|
||||
(strmatch(C, "frr-zebra-route-map:ipv4-next-hop-prefix-length"))
|
||||
#define IS_MATCH_SRC_PROTO(C) \
|
||||
(strmatch(C, "frr-zebra-route-map:source-protocol"))
|
||||
#define IS_MATCH_BGP_SRC_PROTO(C) \
|
||||
(strmatch(C, "frr-bgp-route-map:source-protocol"))
|
||||
#define IS_MATCH_SRC_INSTANCE(C) \
|
||||
(strmatch(C, "frr-zebra-route-map:source-instance"))
|
||||
/* BGP route-map match conditions */
|
||||
|
@ -599,11 +599,14 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
|
||||
yang_dnode_get_string(
|
||||
dnode,
|
||||
"./rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length"));
|
||||
} else if (IS_MATCH_SRC_PROTO(condition)) {
|
||||
} else if (IS_MATCH_SRC_PROTO(condition) ||
|
||||
IS_MATCH_BGP_SRC_PROTO(condition)) {
|
||||
vty_out(vty, " match source-protocol %s\n",
|
||||
yang_dnode_get_string(
|
||||
dnode,
|
||||
"./rmap-match-condition/frr-zebra-route-map:source-protocol"));
|
||||
IS_MATCH_SRC_PROTO(condition)
|
||||
? "./rmap-match-condition/frr-zebra-route-map:source-protocol"
|
||||
: "./rmap-match-condition/frr-bgp-route-map:source-protocol"));
|
||||
} else if (IS_MATCH_SRC_INSTANCE(condition)) {
|
||||
vty_out(vty, " match source-instance %s\n",
|
||||
yang_dnode_get_string(
|
||||
|
@ -23,6 +23,10 @@ module frr-bgp-route-map {
|
||||
prefix rt-types;
|
||||
}
|
||||
|
||||
import frr-route-types {
|
||||
prefix frr-route-types;
|
||||
}
|
||||
|
||||
organization
|
||||
"Free Range Routing";
|
||||
contact
|
||||
@ -168,6 +172,12 @@ module frr-bgp-route-map {
|
||||
"Match IPv6 next hop address";
|
||||
}
|
||||
|
||||
identity source-protocol {
|
||||
base frr-route-map:rmap-match-type;
|
||||
description
|
||||
"Match protocol via which the route was learnt";
|
||||
}
|
||||
|
||||
identity distance {
|
||||
base frr-route-map:rmap-set-type;
|
||||
description
|
||||
@ -759,6 +769,13 @@ module frr-bgp-route-map {
|
||||
"IPv6 address";
|
||||
}
|
||||
}
|
||||
|
||||
case source-protocol {
|
||||
when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:source-protocol')";
|
||||
leaf source-protocol {
|
||||
type frr-route-types:frr-route-types;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" {
|
||||
|
Loading…
Reference in New Issue
Block a user