forked from Mirror/frr
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 */
|
/* Extended Community Origin Validation State */
|
||||||
enum ecommunity_origin_validation_states {
|
enum ecommunity_origin_validation_states {
|
||||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED = -1,
|
|
||||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
|
ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
|
||||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
|
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
|
||||||
ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID
|
ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID,
|
||||||
|
ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Extended Communities type flag. */
|
/* 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,
|
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
|
* This is the workhorse routine for processing in/out routemap
|
||||||
* modifications.
|
* modifications.
|
||||||
|
@ -6713,6 +6780,34 @@ DEFUN_YANG (no_set_originator_id,
|
||||||
return nb_cli_apply_changes(vty, NULL);
|
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. */
|
/* Initialization of route map. */
|
||||||
void bgp_route_map_init(void)
|
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_prefer_global_cmd);
|
||||||
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
|
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
|
||||||
route_map_install_set(&route_set_ipv6_nexthop_peer_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_cmd);
|
||||||
install_element(RMAP_NODE, &match_ipv6_next_hop_address_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, &no_set_ipv6_nexthop_prefer_global_cmd);
|
||||||
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
|
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
|
||||||
install_element(RMAP_NODE, &no_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
|
#ifdef HAVE_SCRIPTING
|
||||||
install_element(RMAP_NODE, &match_script_cmd);
|
install_element(RMAP_NODE, &match_script_cmd);
|
||||||
#endif
|
#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,
|
.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",
|
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:probability",
|
||||||
.cbs = {
|
.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_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_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_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_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_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);
|
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;
|
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
|
* 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
|
match rpki valid
|
||||||
set local-preference 500
|
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:
|
.. _debugging:
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,8 @@ DECLARE_QOBJ_TYPE(route_map);
|
||||||
#define IS_MATCH_ORIGIN(C) \
|
#define IS_MATCH_ORIGIN(C) \
|
||||||
(strmatch(C, "frr-bgp-route-map:match-origin"))
|
(strmatch(C, "frr-bgp-route-map:match-origin"))
|
||||||
#define IS_MATCH_RPKI(C) (strmatch(C, "frr-bgp-route-map:rpki"))
|
#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) \
|
#define IS_MATCH_PROBABILITY(C) \
|
||||||
(strmatch(C, "frr-bgp-route-map:probability"))
|
(strmatch(C, "frr-bgp-route-map:probability"))
|
||||||
#define IS_MATCH_SRC_VRF(C) \
|
#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(
|
yang_dnode_get_string(
|
||||||
dnode,
|
dnode,
|
||||||
"./rmap-match-condition/frr-bgp-route-map:rpki"));
|
"./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)) {
|
} else if (IS_MATCH_PROBABILITY(condition)) {
|
||||||
vty_out(vty, " match probability %s\n",
|
vty_out(vty, " match probability %s\n",
|
||||||
yang_dnode_get_string(
|
yang_dnode_get_string(
|
||||||
|
|
|
@ -66,6 +66,12 @@ module frr-bgp-route-map {
|
||||||
"Control rpki specific settings";
|
"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 {
|
identity probability {
|
||||||
base frr-route-map:rmap-match-type;
|
base frr-route-map:rmap-match-type;
|
||||||
description
|
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 {
|
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')";
|
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 {
|
leaf probability {
|
||||||
|
|
Loading…
Reference in a new issue