Skip to content

Commit 80dc863

Browse files
authored
Merge pull request #16946 from opensourcerouting/fix/match_src-peer
bgpd: Implement match src-peer ... command
2 parents 40dce0b + 6e4bee2 commit 80dc863

14 files changed

+408
-22
lines changed

bgpd/bgp_conditional_adv.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
3030
dummy_attr = *pi->attr;
3131

3232
/* Fill temp path_info */
33-
prep_for_rmap_apply(&path, &path_extra, dest, pi,
34-
pi->peer, &dummy_attr);
33+
prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL,
34+
&dummy_attr);
3535

3636
RESET_FLAG(dummy_attr.rmap_change_flags);
3737

@@ -99,8 +99,8 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
9999
advmap_attr = *pi->attr;
100100

101101
/* Fill temp path_info */
102-
prep_for_rmap_apply(&path, &path_extra, dest, pi,
103-
pi->peer, &advmap_attr);
102+
prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL,
103+
&advmap_attr);
104104

105105
RESET_FLAG(advmap_attr.rmap_change_flags);
106106

bgpd/bgp_evpn.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -5392,9 +5392,8 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
53925392
tmp_attr = *pi->attr;
53935393

53945394
/* Fill temp path_info */
5395-
prep_for_rmap_apply(&tmp_pi, &tmp_pie,
5396-
dest, pi, pi->peer,
5397-
&tmp_attr);
5395+
prep_for_rmap_apply(&tmp_pi, &tmp_pie, dest, pi, pi->peer,
5396+
NULL, &tmp_attr);
53985397

53995398
RESET_FLAG(tmp_attr.rmap_change_flags);
54005399

bgpd/bgp_route.c

+13-10
Original file line numberDiff line numberDiff line change
@@ -2512,8 +2512,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
25122512
struct attr dummy_attr = *attr;
25132513

25142514
/* Fill temp path_info */
2515-
prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2516-
pi, peer, &dummy_attr);
2515+
prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, pi, peer, NULL,
2516+
&dummy_attr);
25172517

25182518
struct route_map *amap =
25192519
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,
25372537
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
25382538
struct attr dummy_attr = {0};
25392539

2540-
/* Fill temp path_info */
2541-
prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2542-
pi, peer, attr);
2540+
/* Fill temp path_info.
2541+
* Inject the peer structure of the source peer (from).
2542+
* This is useful for e.g. `match peer ...` in outgoing
2543+
* direction.
2544+
*/
2545+
prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, pi, peer, from, attr);
2546+
25432547
/*
25442548
* The route reflector is not allowed to modify the attributes
25452549
* 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,
34263430
dummy_attr = *new_select->attr;
34273431

34283432
/* Fill temp path_info */
3429-
prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3430-
new_select, new_select->peer,
3431-
&dummy_attr);
3433+
prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest, new_select,
3434+
new_select->peer, NULL, &dummy_attr);
34323435

34333436
RESET_FLAG(dummy_attr.rmap_change_flags);
34343437

@@ -11784,8 +11787,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa
1178411787

1178511788
dummy_attr = *pi->attr;
1178611789

11787-
prep_for_rmap_apply(&path, &extra, dest, pi,
11788-
pi->peer, &dummy_attr);
11790+
prep_for_rmap_apply(&path, &extra, dest, pi, pi->peer, NULL,
11791+
&dummy_attr);
1178911792

1179011793
ret = route_map_apply(rmap, dest_p, &path);
1179111794
bgp_attr_flush(&dummy_attr);

bgpd/bgp_route.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ struct bgp_path_info {
284284
/* Peer structure. */
285285
struct peer *peer;
286286

287+
/* From peer structure */
288+
struct peer *from;
289+
287290
/* Attribute structure. */
288291
struct attr *attr;
289292

@@ -619,13 +622,13 @@ static inline bool is_pi_family_matching(struct bgp_path_info *pi,
619622
}
620623

621624
static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi,
622-
struct bgp_path_info_extra *dst_pie,
623-
struct bgp_dest *dest,
624-
struct bgp_path_info *src_pi,
625-
struct peer *peer, struct attr *attr)
625+
struct bgp_path_info_extra *dst_pie, struct bgp_dest *dest,
626+
struct bgp_path_info *src_pi, struct peer *peer,
627+
struct peer *from, struct attr *attr)
626628
{
627629
memset(dst_pi, 0, sizeof(struct bgp_path_info));
628630
dst_pi->peer = peer;
631+
dst_pi->from = from;
629632
dst_pi->attr = attr;
630633
dst_pi->net = dest;
631634
dst_pi->flags = src_pi->flags;

bgpd/bgp_routemap.c

+109
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,66 @@ static const struct route_map_rule_cmd route_match_peer_cmd = {
347347
route_match_peer_free
348348
};
349349

350+
static enum route_map_cmd_result_t route_match_src_peer(void *rule, const struct prefix *prefix,
351+
void *object)
352+
{
353+
struct bgp_match_peer_compiled *pc;
354+
union sockunion *su;
355+
struct peer_group *group;
356+
struct peer *peer;
357+
struct listnode *node, *nnode;
358+
struct bgp_path_info *bpi;
359+
360+
pc = rule;
361+
su = &pc->su;
362+
bpi = object;
363+
peer = bpi->from;
364+
365+
/* Fallback to destination (current) peer. This is mostly
366+
* happens if `match src-peer ...` is used at incoming direction.
367+
*/
368+
if (!peer)
369+
peer = bpi->peer;
370+
371+
if (!peer)
372+
return RMAP_NOMATCH;
373+
374+
if (pc->interface) {
375+
if (!peer->conf_if && !peer->group)
376+
return RMAP_NOMATCH;
377+
378+
if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
379+
return RMAP_MATCH;
380+
381+
if (peer->group && strcmp(peer->group->name, pc->interface) == 0)
382+
return RMAP_MATCH;
383+
384+
return RMAP_NOMATCH;
385+
}
386+
387+
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
388+
if (sockunion_same(su, &peer->connection->su))
389+
return RMAP_MATCH;
390+
391+
return RMAP_NOMATCH;
392+
}
393+
394+
group = peer->group;
395+
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
396+
if (sockunion_same(su, &peer->connection->su))
397+
return RMAP_MATCH;
398+
}
399+
400+
return RMAP_NOMATCH;
401+
}
402+
403+
static const struct route_map_rule_cmd route_match_src_peer_cmd = {
404+
"src-peer",
405+
route_match_src_peer,
406+
route_match_peer_compile,
407+
route_match_peer_free
408+
};
409+
350410
#ifdef HAVE_SCRIPTING
351411

352412
enum frrlua_rm_status {
@@ -5287,6 +5347,52 @@ DEFUN_YANG (no_match_peer,
52875347
return nb_cli_apply_changes(vty, NULL);
52885348
}
52895349

5350+
DEFPY_YANG (match_src_peer,
5351+
match_src_peer_cmd,
5352+
"match src-peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
5353+
MATCH_STR
5354+
"Match source peer address\n"
5355+
"IP address of peer\n"
5356+
"IPv6 address of peer\n"
5357+
"Interface name of peer or peer group name\n")
5358+
{
5359+
const char *xpath = "./match-condition[condition='frr-bgp-route-map:src-peer']";
5360+
char xpath_value[XPATH_MAXLEN];
5361+
5362+
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5363+
5364+
snprintf(xpath_value, sizeof(xpath_value),
5365+
"%s/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address", xpath);
5366+
nb_cli_enqueue_change(vty, xpath_value, addrv4_str ? NB_OP_MODIFY : NB_OP_DESTROY,
5367+
addrv4_str);
5368+
snprintf(xpath_value, sizeof(xpath_value),
5369+
"%s/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address", xpath);
5370+
nb_cli_enqueue_change(vty, xpath_value, addrv6_str ? NB_OP_MODIFY : NB_OP_DESTROY,
5371+
addrv6_str);
5372+
snprintf(xpath_value, sizeof(xpath_value),
5373+
"%s/rmap-match-condition/frr-bgp-route-map:src-peer-interface", xpath);
5374+
nb_cli_enqueue_change(vty, xpath_value, intf ? NB_OP_MODIFY : NB_OP_DESTROY, intf);
5375+
5376+
return nb_cli_apply_changes(vty, NULL);
5377+
}
5378+
5379+
DEFUN_YANG (no_match_src_peer,
5380+
no_match_src_peer_cmd,
5381+
"no match src-peer [<A.B.C.D|X:X::X:X|WORD>]",
5382+
NO_STR
5383+
MATCH_STR
5384+
"Match peer address\n"
5385+
"IP address of peer\n"
5386+
"IPv6 address of peer\n"
5387+
"Interface name of peer\n")
5388+
{
5389+
const char *xpath = "./match-condition[condition='frr-bgp-route-map:src-peer']";
5390+
5391+
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5392+
5393+
return nb_cli_apply_changes(vty, NULL);
5394+
}
5395+
52905396
#ifdef HAVE_SCRIPTING
52915397
DEFUN_YANG (match_script,
52925398
match_script_cmd,
@@ -7778,6 +7884,7 @@ void bgp_route_map_init(void)
77787884
route_map_no_set_tag_hook(generic_set_delete);
77797885

77807886
route_map_install_match(&route_match_peer_cmd);
7887+
route_map_install_match(&route_match_src_peer_cmd);
77817888
route_map_install_match(&route_match_alias_cmd);
77827889
route_map_install_match(&route_match_local_pref_cmd);
77837890
#ifdef HAVE_SCRIPTING
@@ -7845,6 +7952,8 @@ void bgp_route_map_init(void)
78457952

78467953
install_element(RMAP_NODE, &match_peer_cmd);
78477954
install_element(RMAP_NODE, &match_peer_local_cmd);
7955+
install_element(RMAP_NODE, &match_src_peer_cmd);
7956+
install_element(RMAP_NODE, &no_match_src_peer_cmd);
78487957
install_element(RMAP_NODE, &no_match_peer_cmd);
78497958
install_element(RMAP_NODE, &match_ip_route_source_cmd);
78507959
install_element(RMAP_NODE, &no_match_ip_route_source_cmd);

bgpd/bgp_routemap_nb.c

+21
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,27 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
109109
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy,
110110
}
111111
},
112+
{
113+
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address",
114+
.cbs = {
115+
.modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify,
116+
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy,
117+
}
118+
},
119+
{
120+
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-interface",
121+
.cbs = {
122+
.modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify,
123+
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy,
124+
}
125+
},
126+
{
127+
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address",
128+
.cbs = {
129+
.modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify,
130+
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy,
131+
}
132+
},
112133
{
113134
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:list-name",
114135
.cbs = {

bgpd/bgp_routemap_nb.h

+12
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ int lib_route_map_entry_match_condition_rmap_match_condition_peer_ipv6_address_m
4646
int lib_route_map_entry_match_condition_rmap_match_condition_peer_ipv6_address_destroy(struct nb_cb_destroy_args *args);
4747
int lib_route_map_entry_match_condition_rmap_match_condition_peer_local_modify(struct nb_cb_modify_args *args);
4848
int lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy(struct nb_cb_destroy_args *args);
49+
int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify(
50+
struct nb_cb_modify_args *args);
51+
int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy(
52+
struct nb_cb_destroy_args *args);
53+
int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify(
54+
struct nb_cb_modify_args *args);
55+
int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy(
56+
struct nb_cb_destroy_args *args);
57+
int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify(
58+
struct nb_cb_modify_args *args);
59+
int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy(
60+
struct nb_cb_destroy_args *args);
4961
int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_modify(struct nb_cb_modify_args *args);
5062
int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_destroy(struct nb_cb_destroy_args *args);
5163
int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_extended_modify(struct nb_cb_modify_args *args);

0 commit comments

Comments
 (0)