diff options
| -rw-r--r-- | bgpd/bgp_routemap.c | 79 | ||||
| -rw-r--r-- | bgpd/bgp_routemap_nb.c | 7 | ||||
| -rw-r--r-- | bgpd/bgp_routemap_nb.h | 4 | ||||
| -rw-r--r-- | bgpd/bgp_routemap_nb_config.c | 54 | ||||
| -rw-r--r-- | lib/routemap.h | 2 | ||||
| -rw-r--r-- | lib/routemap_cli.c | 7 | ||||
| -rw-r--r-- | yang/frr-bgp-route-map.yang | 17 |
7 files changed, 168 insertions, 2 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 10fc3ecda4..7db110be93 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -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 diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c index 6e8439cc26..282ebe9116 100644 --- a/bgpd/bgp_routemap_nb.c +++ b/bgpd/bgp_routemap_nb.c @@ -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 = { diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h index bcd1e837e8..7066fdb419 100644 --- a/bgpd/bgp_routemap_nb.h +++ b/bgpd/bgp_routemap_nb.h @@ -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); diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index 938a5ec31b..02564b0004 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -369,6 +369,60 @@ 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: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 */ int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify( diff --git a/lib/routemap.h b/lib/routemap.h index 9b2e18b4a7..7277744dc5 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -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 */ diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 419086c4c6..0ccc78e838 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -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( diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index 23e5b0227c..b557cabb22 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -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" { |
