mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 15:36:25 +00:00
bgpd: Handle Origin Validation State extended community via route-map match
Add an ability to match via route-maps. An additional route-map command `match rpki-extcommunity <invalid|notfound|valid>` added. Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
parent
7b27cf7bbd
commit
324e8b1f79
@ -104,10 +104,10 @@
|
||||
|
||||
/* Extended Community Origin Validation State */
|
||||
enum ecommunity_origin_validation_states {
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED = -1,
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID,
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED
|
||||
};
|
||||
|
||||
/* Extended Communities type flag. */
|
||||
|
@ -3738,6 +3738,73 @@ static const struct route_map_rule_cmd route_set_originator_id_cmd = {
|
||||
route_set_originator_id_free,
|
||||
};
|
||||
|
||||
static enum route_map_cmd_result_t
|
||||
route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
|
||||
void *object)
|
||||
{
|
||||
struct bgp_path_info *path;
|
||||
struct ecommunity *ecomm;
|
||||
struct ecommunity_val *ecomm_val;
|
||||
enum rpki_states *rpki_status = rule;
|
||||
enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
|
||||
|
||||
path = object;
|
||||
|
||||
ecomm = bgp_attr_get_ecommunity(path->attr);
|
||||
if (!ecomm)
|
||||
return RMAP_NOMATCH;
|
||||
|
||||
ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
|
||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE);
|
||||
if (!ecomm_val)
|
||||
return RMAP_NOMATCH;
|
||||
|
||||
/* The Origin Validation State is encoded in the last octet of
|
||||
* the extended community.
|
||||
*/
|
||||
switch (ecomm_val->val[7]) {
|
||||
case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
|
||||
ecomm_rpki_status = RPKI_VALID;
|
||||
break;
|
||||
case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
|
||||
ecomm_rpki_status = RPKI_NOTFOUND;
|
||||
break;
|
||||
case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
|
||||
ecomm_rpki_status = RPKI_INVALID;
|
||||
break;
|
||||
case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ecomm_rpki_status == *rpki_status)
|
||||
return RMAP_MATCH;
|
||||
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
static void *route_match_extcommunity_compile(const char *arg)
|
||||
{
|
||||
int *rpki_status;
|
||||
|
||||
rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
|
||||
|
||||
if (strcmp(arg, "valid") == 0)
|
||||
*rpki_status = RPKI_VALID;
|
||||
else if (strcmp(arg, "invalid") == 0)
|
||||
*rpki_status = RPKI_INVALID;
|
||||
else
|
||||
*rpki_status = RPKI_NOTFOUND;
|
||||
|
||||
return rpki_status;
|
||||
}
|
||||
|
||||
static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
|
||||
"rpki-extcommunity",
|
||||
route_match_rpki_extcommunity,
|
||||
route_match_extcommunity_compile,
|
||||
route_value_free
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the workhorse routine for processing in/out routemap
|
||||
* modifications.
|
||||
@ -6713,6 +6780,34 @@ DEFUN_YANG (no_set_originator_id,
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY_YANG (match_rpki_extcommunity,
|
||||
match_rpki_extcommunity_cmd,
|
||||
"[no$no] match rpki-extcommunity <valid|invalid|notfound>",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
"BGP RPKI (Origin Validation State) extended community attribute\n"
|
||||
"Valid prefix\n"
|
||||
"Invalid prefix\n"
|
||||
"Prefix not found\n")
|
||||
{
|
||||
const char *xpath =
|
||||
"./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
|
||||
if (!no) {
|
||||
snprintf(
|
||||
xpath_value, sizeof(xpath_value),
|
||||
"%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
|
||||
xpath);
|
||||
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
|
||||
argv[2]->arg);
|
||||
}
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
/* Initialization of route map. */
|
||||
void bgp_route_map_init(void)
|
||||
{
|
||||
@ -6949,6 +7044,7 @@ void bgp_route_map_init(void)
|
||||
route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
|
||||
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
|
||||
route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
|
||||
route_map_install_match(&route_match_rpki_extcommunity_cmd);
|
||||
|
||||
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
|
||||
install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
|
||||
@ -6966,6 +7062,7 @@ void bgp_route_map_init(void)
|
||||
install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
|
||||
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);
|
||||
#ifdef HAVE_SCRIPTING
|
||||
install_element(RMAP_NODE, &match_script_cmd);
|
||||
#endif
|
||||
|
@ -66,6 +66,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
|
||||
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_rpki_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
|
||||
.cbs = {
|
||||
.modify = lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify,
|
||||
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:probability",
|
||||
.cbs = {
|
||||
|
@ -39,6 +39,10 @@ int lib_route_map_entry_match_condition_rmap_match_condition_origin_modify(struc
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_origin_destroy(struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_modify(struct nb_cb_modify_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_destroy(struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify(
|
||||
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_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);
|
||||
|
@ -380,6 +380,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:rpki-extcommunity
|
||||
*/
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify(
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct routemap_hook_context *rhc;
|
||||
const char *rpki;
|
||||
enum rmap_compile_rets ret;
|
||||
|
||||
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);
|
||||
rpki = yang_dnode_get_string(args->dnode, NULL);
|
||||
|
||||
/* Set destroy information. */
|
||||
rhc->rhc_mhook = bgp_route_match_delete;
|
||||
rhc->rhc_rule = "rpki-extcommunity";
|
||||
rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
|
||||
|
||||
ret = bgp_route_match_add(rhc->rhc_rmi, "rpki-extcommunity",
|
||||
rpki, 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_rpki_extcommunity_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:probability
|
||||
*/
|
||||
|
@ -178,6 +178,12 @@ Validating BGP Updates
|
||||
match rpki valid
|
||||
set local-preference 500
|
||||
|
||||
.. clicmd:: match rpki-extcommunity notfound|invalid|valid
|
||||
|
||||
Create a clause for a route map to match prefixes with the specified RPKI
|
||||
state, that is derived from the Origin Validation State extended community
|
||||
attribute (OVS). OVS extended community is non-transitive and is exchanged
|
||||
only between iBGP peers.
|
||||
|
||||
.. _debugging:
|
||||
|
||||
|
@ -280,6 +280,8 @@ DECLARE_QOBJ_TYPE(route_map);
|
||||
#define IS_MATCH_ORIGIN(C) \
|
||||
(strmatch(C, "frr-bgp-route-map:match-origin"))
|
||||
#define IS_MATCH_RPKI(C) (strmatch(C, "frr-bgp-route-map:rpki"))
|
||||
#define IS_MATCH_RPKI_EXTCOMMUNITY(C) \
|
||||
(strmatch(C, "frr-bgp-route-map:rpki-extcommunity"))
|
||||
#define IS_MATCH_PROBABILITY(C) \
|
||||
(strmatch(C, "frr-bgp-route-map:probability"))
|
||||
#define IS_MATCH_SRC_VRF(C) \
|
||||
|
@ -650,6 +650,11 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
|
||||
yang_dnode_get_string(
|
||||
dnode,
|
||||
"./rmap-match-condition/frr-bgp-route-map:rpki"));
|
||||
} else if (IS_MATCH_RPKI_EXTCOMMUNITY(condition)) {
|
||||
vty_out(vty, " match rpki-extcommunity %s\n",
|
||||
yang_dnode_get_string(
|
||||
dnode,
|
||||
"./rmap-match-condition/frr-bgp-route-map:rpki-extcommunity"));
|
||||
} else if (IS_MATCH_PROBABILITY(condition)) {
|
||||
vty_out(vty, " match probability %s\n",
|
||||
yang_dnode_get_string(
|
||||
|
@ -66,6 +66,12 @@ module frr-bgp-route-map {
|
||||
"Control rpki specific settings";
|
||||
}
|
||||
|
||||
identity rpki-extcommunity {
|
||||
base frr-route-map:rmap-match-type;
|
||||
description
|
||||
"Control rpki specific settings derived from extended community";
|
||||
}
|
||||
|
||||
identity probability {
|
||||
base frr-route-map:rmap-match-type;
|
||||
description
|
||||
@ -430,6 +436,29 @@ module frr-bgp-route-map {
|
||||
}
|
||||
}
|
||||
|
||||
case rpki-extcommunity {
|
||||
when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:rpki-extcommunity')";
|
||||
leaf rpki-extcommunity {
|
||||
type enumeration {
|
||||
enum "valid" {
|
||||
value 0;
|
||||
description
|
||||
"Valid prefix";
|
||||
}
|
||||
enum "notfound" {
|
||||
value 1;
|
||||
description
|
||||
"Prefix not found";
|
||||
}
|
||||
enum "invalid" {
|
||||
value 2;
|
||||
description
|
||||
"Invalid prefix";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case probability {
|
||||
when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:probability')";
|
||||
leaf probability {
|
||||
|
Loading…
Reference in New Issue
Block a user