diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index 2d96b444b6c5..a99d0201e7e0 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -30,8 +30,8 @@ bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table, dummy_attr = *pi->attr; /* Fill temp path_info */ - prep_for_rmap_apply(&path, &path_extra, dest, pi, - pi->peer, &dummy_attr); + prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL, + &dummy_attr); RESET_FLAG(dummy_attr.rmap_change_flags); @@ -99,8 +99,8 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, advmap_attr = *pi->attr; /* Fill temp path_info */ - prep_for_rmap_apply(&path, &path_extra, dest, pi, - pi->peer, &advmap_attr); + prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL, + &advmap_attr); RESET_FLAG(advmap_attr.rmap_change_flags); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 0a8ce6154855..ad29828adecb 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -5392,9 +5392,8 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, tmp_attr = *pi->attr; /* Fill temp path_info */ - prep_for_rmap_apply(&tmp_pi, &tmp_pie, - dest, pi, pi->peer, - &tmp_attr); + prep_for_rmap_apply(&tmp_pi, &tmp_pie, dest, pi, pi->peer, + NULL, &tmp_attr); RESET_FLAG(tmp_attr.rmap_change_flags); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ace44675369b..9f44e7913a9b 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2512,8 +2512,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, struct attr dummy_attr = *attr; /* Fill temp path_info */ - prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, - pi, peer, &dummy_attr); + prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, pi, peer, NULL, + &dummy_attr); struct route_map *amap = route_map_lookup_by_name(filter->advmap.aname); @@ -2537,9 +2537,13 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, struct bgp_path_info_extra dummy_rmap_path_extra = {0}; struct attr dummy_attr = {0}; - /* Fill temp path_info */ - prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, - pi, peer, attr); + /* Fill temp path_info. + * Inject the peer structure of the source peer (from). + * This is useful for e.g. `match peer ...` in outgoing + * direction. + */ + prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, pi, peer, from, attr); + /* * The route reflector is not allowed to modify the attributes * of the reflected IBGP routes unless explicitly allowed. @@ -3426,9 +3430,8 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi, dummy_attr = *new_select->attr; /* Fill temp path_info */ - prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest, - new_select, new_select->peer, - &dummy_attr); + prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest, new_select, + new_select->peer, NULL, &dummy_attr); RESET_FLAG(dummy_attr.rmap_change_flags); @@ -11784,8 +11787,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa dummy_attr = *pi->attr; - prep_for_rmap_apply(&path, &extra, dest, pi, - pi->peer, &dummy_attr); + prep_for_rmap_apply(&path, &extra, dest, pi, pi->peer, NULL, + &dummy_attr); ret = route_map_apply(rmap, dest_p, &path); bgp_attr_flush(&dummy_attr); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index d71bfd3ebc62..1df0ffd300e1 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -284,6 +284,9 @@ struct bgp_path_info { /* Peer structure. */ struct peer *peer; + /* From peer structure */ + struct peer *from; + /* Attribute structure. */ struct attr *attr; @@ -619,13 +622,13 @@ static inline bool is_pi_family_matching(struct bgp_path_info *pi, } static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi, - struct bgp_path_info_extra *dst_pie, - struct bgp_dest *dest, - struct bgp_path_info *src_pi, - struct peer *peer, struct attr *attr) + struct bgp_path_info_extra *dst_pie, struct bgp_dest *dest, + struct bgp_path_info *src_pi, struct peer *peer, + struct peer *from, struct attr *attr) { memset(dst_pi, 0, sizeof(struct bgp_path_info)); dst_pi->peer = peer; + dst_pi->from = from; dst_pi->attr = attr; dst_pi->net = dest; dst_pi->flags = src_pi->flags; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 23e83f9bddac..e5d6992d1b46 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -347,6 +347,66 @@ static const struct route_map_rule_cmd route_match_peer_cmd = { route_match_peer_free }; +static enum route_map_cmd_result_t route_match_src_peer(void *rule, const struct prefix *prefix, + void *object) +{ + struct bgp_match_peer_compiled *pc; + union sockunion *su; + struct peer_group *group; + struct peer *peer; + struct listnode *node, *nnode; + struct bgp_path_info *bpi; + + pc = rule; + su = &pc->su; + bpi = object; + peer = bpi->from; + + /* Fallback to destination (current) peer. This is mostly + * happens if `match src-peer ...` is used at incoming direction. + */ + if (!peer) + peer = bpi->peer; + + if (!peer) + return RMAP_NOMATCH; + + if (pc->interface) { + if (!peer->conf_if && !peer->group) + return RMAP_NOMATCH; + + if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0) + return RMAP_MATCH; + + if (peer->group && strcmp(peer->group->name, pc->interface) == 0) + return RMAP_MATCH; + + return RMAP_NOMATCH; + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (sockunion_same(su, &peer->connection->su)) + return RMAP_MATCH; + + return RMAP_NOMATCH; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (sockunion_same(su, &peer->connection->su)) + return RMAP_MATCH; + } + + return RMAP_NOMATCH; +} + +static const struct route_map_rule_cmd route_match_src_peer_cmd = { + "src-peer", + route_match_src_peer, + route_match_peer_compile, + route_match_peer_free +}; + #ifdef HAVE_SCRIPTING enum frrlua_rm_status { @@ -5287,6 +5347,52 @@ DEFUN_YANG (no_match_peer, return nb_cli_apply_changes(vty, NULL); } +DEFPY_YANG (match_src_peer, + match_src_peer_cmd, + "match src-peer ", + MATCH_STR + "Match source peer address\n" + "IP address of peer\n" + "IPv6 address of peer\n" + "Interface name of peer or peer group name\n") +{ + const char *xpath = "./match-condition[condition='frr-bgp-route-map:src-peer']"; + 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:src-peer-ipv4-address", xpath); + nb_cli_enqueue_change(vty, xpath_value, addrv4_str ? NB_OP_MODIFY : NB_OP_DESTROY, + addrv4_str); + snprintf(xpath_value, sizeof(xpath_value), + "%s/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address", xpath); + nb_cli_enqueue_change(vty, xpath_value, addrv6_str ? NB_OP_MODIFY : NB_OP_DESTROY, + addrv6_str); + snprintf(xpath_value, sizeof(xpath_value), + "%s/rmap-match-condition/frr-bgp-route-map:src-peer-interface", xpath); + nb_cli_enqueue_change(vty, xpath_value, intf ? NB_OP_MODIFY : NB_OP_DESTROY, intf); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFUN_YANG (no_match_src_peer, + no_match_src_peer_cmd, + "no match src-peer []", + NO_STR + MATCH_STR + "Match peer address\n" + "IP address of peer\n" + "IPv6 address of peer\n" + "Interface name of peer\n") +{ + const char *xpath = "./match-condition[condition='frr-bgp-route-map:src-peer']"; + + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + #ifdef HAVE_SCRIPTING DEFUN_YANG (match_script, match_script_cmd, @@ -7778,6 +7884,7 @@ void bgp_route_map_init(void) route_map_no_set_tag_hook(generic_set_delete); route_map_install_match(&route_match_peer_cmd); + route_map_install_match(&route_match_src_peer_cmd); route_map_install_match(&route_match_alias_cmd); route_map_install_match(&route_match_local_pref_cmd); #ifdef HAVE_SCRIPTING @@ -7845,6 +7952,8 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &match_peer_cmd); install_element(RMAP_NODE, &match_peer_local_cmd); + install_element(RMAP_NODE, &match_src_peer_cmd); + install_element(RMAP_NODE, &no_match_src_peer_cmd); install_element(RMAP_NODE, &no_match_peer_cmd); install_element(RMAP_NODE, &match_ip_route_source_cmd); install_element(RMAP_NODE, &no_match_ip_route_source_cmd); diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c index 096502aaa904..d8fdb4fbc43b 100644 --- a/bgpd/bgp_routemap_nb.c +++ b/bgpd/bgp_routemap_nb.c @@ -109,6 +109,27 @@ const struct frr_yang_module_info frr_bgp_route_map_info = { .destroy = lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy, } }, + { + .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address", + .cbs = { + .modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify, + .destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy, + } + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-interface", + .cbs = { + .modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify, + .destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy, + } + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address", + .cbs = { + .modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify, + .destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy, + } + }, { .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:list-name", .cbs = { diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h index d7f0cea30ea0..f59686f3864b 100644 --- a/bgpd/bgp_routemap_nb.h +++ b/bgpd/bgp_routemap_nb.h @@ -46,6 +46,18 @@ int lib_route_map_entry_match_condition_rmap_match_condition_peer_ipv6_address_m int lib_route_map_entry_match_condition_rmap_match_condition_peer_ipv6_address_destroy(struct nb_cb_destroy_args *args); int lib_route_map_entry_match_condition_rmap_match_condition_peer_local_modify(struct nb_cb_modify_args *args); int lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy(struct nb_cb_destroy_args *args); +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify( + struct nb_cb_modify_args *args); +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy( + struct nb_cb_destroy_args *args); +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify( + struct nb_cb_modify_args *args); +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy( + struct nb_cb_destroy_args *args); +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify( + struct nb_cb_modify_args *args); +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy( + struct nb_cb_destroy_args *args); int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_modify(struct nb_cb_modify_args *args); int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_destroy(struct nb_cb_destroy_args *args); int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_extended_modify(struct nb_cb_modify_args *args); diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index 15c32eaa2856..0dca196ed637 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -808,6 +808,162 @@ lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy( return NB_OK; } +/* + * XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address + */ +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify( + struct nb_cb_modify_args *args) +{ + struct routemap_hook_context *rhc; + const char *peer; + 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); + peer = yang_dnode_get_string(args->dnode, NULL); + + /* Set destroy information. */ + rhc->rhc_mhook = bgp_route_match_delete; + rhc->rhc_rule = "src-peer"; + rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; + + ret = bgp_route_match_add(rhc->rhc_rmi, "src-peer", peer, 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_src_peer_ipv4_address_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:src-peer-interface + */ +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify( + struct nb_cb_modify_args *args) +{ + struct routemap_hook_context *rhc; + const char *peer; + 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); + peer = yang_dnode_get_string(args->dnode, NULL); + + /* Set destroy information. */ + rhc->rhc_mhook = bgp_route_match_delete; + rhc->rhc_rule = "src-peer"; + rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; + + ret = bgp_route_match_add(rhc->rhc_rmi, "src-peer", peer, 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_src_peer_interface_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:src-peer-ipv6-address + */ +int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify( + struct nb_cb_modify_args *args) +{ + struct routemap_hook_context *rhc; + const char *peer; + 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); + peer = yang_dnode_get_string(args->dnode, NULL); + + /* Set destroy information. */ + rhc->rhc_mhook = bgp_route_match_delete; + rhc->rhc_rule = "src-peer"; + rhc->rhc_event = RMAP_EVENT_MATCH_DELETED; + + ret = bgp_route_match_add(rhc->rhc_rmi, "src-peer", peer, 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_src_peer_ipv6_address_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:list-name */ diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst index 02a43bc980b8..60e458a28ae5 100644 --- a/doc/user/routemap.rst +++ b/doc/user/routemap.rst @@ -190,6 +190,12 @@ Route Map Match Command do the exact matching of the communities, while ``any`` - can match any community specified in COMMUNITY_LIST. +.. clicmd:: match src-peer [IPV4_ADDR|IPV6_ADDR|INTERFACE_NAME|PEER_GROUP_NAME] + + This is a BGP specific match command. Matches the source peer if the neighbor + was specified in this manner. Useful to announce the routes that was originated + by the source peer. + .. clicmd:: match peer IPV4_ADDR This is a BGP specific match command. Matches the peer ip address diff --git a/lib/routemap.h b/lib/routemap.h index dfb84ced5bae..ef9b3cb160c7 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -278,6 +278,7 @@ DECLARE_QOBJ_TYPE(route_map); #define IS_MATCH_SRC_VRF(C) \ (strmatch(C, "frr-bgp-route-map:source-vrf")) #define IS_MATCH_PEER(C) (strmatch(C, "frr-bgp-route-map:peer")) +#define IS_MATCH_SRC_PEER(C) (strmatch(C, "frr-bgp-route-map:src-peer")) #define IS_MATCH_AS_LIST(C) \ (strmatch(C, "frr-bgp-route-map:as-path-list")) #define IS_MATCH_MAC_LIST(C) \ diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 432805c8d51a..69b942064b5d 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -756,6 +756,18 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode, acl = "local"; vty_out(vty, " match peer %s\n", acl); + } else if (IS_MATCH_SRC_PEER(condition)) { + acl = NULL; + ln = yang_dnode_get(dnode, + "./rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address"); + if (!ln) + ln = yang_dnode_get(dnode, + "./rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address"); + if (!ln) + ln = yang_dnode_get(dnode, + "./rmap-match-condition/frr-bgp-route-map:src-peer-interface"); + acl = yang_dnode_get_string(ln, NULL); + vty_out(vty, " match src-peer %s\n", acl); } else if (IS_MATCH_AS_LIST(condition)) { vty_out(vty, " match as-path %s\n", yang_dnode_get_string( diff --git a/tests/topotests/bgp_match_peer/r1/frr.conf b/tests/topotests/bgp_match_peer/r1/frr.conf index f30da3b896a2..02fb8ae518e2 100644 --- a/tests/topotests/bgp_match_peer/r1/frr.conf +++ b/tests/topotests/bgp_match_peer/r1/frr.conf @@ -17,6 +17,7 @@ router bgp 65001 neighbor 192.168.1.2 route-map all in neighbor r3 route-map all in neighbor r4 route-map all in + neighbor r4 route-map r4 out exit-address-family ! route-map all permit 5 @@ -24,7 +25,7 @@ route-map all permit 5 set metric 1 ! route-map all permit 10 - match peer 192.168.1.2 + match src-peer 192.168.1.2 set metric 2 ! route-map all permit 15 @@ -35,3 +36,6 @@ route-map all permit 20 match peer r4 set metric 4 ! +route-map r4 permit 10 + match src-peer r3 +! diff --git a/tests/topotests/bgp_match_peer/test_bgp_match_peer.py b/tests/topotests/bgp_match_peer/test_bgp_match_peer.py index 4eb7473df0af..180dbcd08aef 100644 --- a/tests/topotests/bgp_match_peer/test_bgp_match_peer.py +++ b/tests/topotests/bgp_match_peer/test_bgp_match_peer.py @@ -82,6 +82,29 @@ def _bgp_converge(): _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assert result is None, "Can't converge" + def _bgp_show_advertised_routes(): + output = json.loads( + r1.vtysh_cmd("show bgp ipv4 unicast neighbors r4 advertised-routes json") + ) + expected = { + "advertisedRoutes": { + "10.0.0.3/32": { + "network": "10.0.0.3/32", + "nextHop": "192.168.1.3", + "path": "65003", + } + }, + "totalPrefixCounter": 1, + } + + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_show_advertised_routes, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't filter by source peer" + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index 44058ab04ece..4ed80d7d0700 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -94,6 +94,12 @@ module frr-bgp-route-map { "Match peer address"; } + identity src-peer { + base frr-route-map:rmap-match-type; + description + "Match source peer address"; + } + identity mac-address-list { base frr-route-map:rmap-match-type; description @@ -688,6 +694,37 @@ identity set-extcommunity-color { } } + case src-peer { + when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:src-peer')"; + choice peer { + description + "Value of the peer"; + case src-peer-ipv4-address { + description + "IP address of peer"; + leaf src-peer-ipv4-address { + type inet:ipv4-address; + } + } + + case src-peer-interface { + description + "Interface name of peer"; + leaf src-peer-interface { + type string; + } + } + + case src-peer-ipv6-address { + description + "IPv6 address of peer"; + leaf src-peer-ipv6-address { + type inet:ipv6-address; + } + } + } + } + case access-list-name { when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:mac-address-list') or " + "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:as-path-list') or "