Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

limit community list count #17836

Merged
merged 2 commits into from
Jan 17, 2025

Conversation

pguibert6WIND
Copy link
Member

Add the ability to configure a limit on the number of received community entries.

Copy link
Member

@ton31337 ton31337 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you planning to implement the same for other types of communities (large, extended)?

Also... IMO we should somehow treat well-known communities to be an exception for this limit, what do you think? Imagine I have a limit 5, but my route has 6 communities and one of them is no-export or no-advertise.

doc/user/bgp.rst Outdated
@@ -2693,6 +2693,11 @@ The following commands can be used in route maps:
happen only when BGP updates have completely same communities value
specified in the community list.

.. clicmd:: match community-limit (1-1024)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this is limited to 1k? And why we can't use 0?

Copy link
Member Author

@pguibert6WIND pguibert6WIND Jan 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what I can do is begin at 0 and consider this limit by comparing with <= instead of <.

router = tgen.gears["r3"]
router.vtysh_cmd(
"""
configure terminal\n
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove \n chars, newlines are handled out of the box.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

router = tgen.gears["r3"]
router.vtysh_cmd(
"""
configure terminal\n
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

case community-limit {
when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-community-limit')";
description
"Match eVPN route-distinguisher";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong description.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

if (argc < idx_limit) {
vty_out(vty, "%% BGP limit count not given.\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow the description is not as I would expect... What BGP limit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

DEFPY_YANG(
match_community_limit, match_community_limit_cmd,
"[no$no] match community-limit [(1-1024)$limit]",
NO_STR MATCH_STR "Match BGP community limit\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the format as any other (every new token with a new line). E.g.:

NO_STR
MATCH_STR
...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

struct bgp_path_info *path = NULL;
struct community *picomm = NULL;
uint16_t count = 0;
uint16_t *limit_rule = (uint16_t *)rule;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Casting not needed here.

	uint16_t *limit_rule = rule;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@pguibert6WIND
Copy link
Member Author

Are you planning to implement the same for other types of communities (large, extended)?

I plan to implement extended comm limit and as path limit.

Also... IMO we should somehow treat well-known communities to be an exception for this limit, what do you think? Imagine I have a limit 5, but my route has 6 communities and one of them is no-export or no-advertise.

I would need to know more about those specific communities. Where in frr code, do we add this community dynamically.

At first glance, I don't see any exceptions. I see the limit option as an administrative control in a domain where no device should use more than the defined limitation count. As counter example, which community should I keep if my limit is 1 and I have both no-export an no-advertise ?

@ton31337
Copy link
Member

As counter example, which community should I keep if my limit is 1 and I have both no-export an no-advertise ?

Keep both?

picomm = bgp_attr_get_community(path->attr);
if (picomm)
count = picomm->size;
if (!count)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the limit is 0, it means "no limit"? Or it should be reverse?

Copy link
Member Author

@pguibert6WIND pguibert6WIND Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having 0 communities in the BGP update, it will always match. I simplified code and added comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if I want to deny any routes with any community attached?

@@ -1303,6 +1303,58 @@ static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
route_match_rd_free
};

/* `match community-limit' */

/* Match function should return 1 if match is success else return zero. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified comment.

}

/* Route map commands for community limit matching. */
static const struct route_map_rule_cmd route_match_community_limit_cmd = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you keep formatting for route_map_rule_cmd as others? (ignoring frrbot)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -5708,6 +5760,36 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}

DEFPY_YANG(
match_community_limit, match_community_limit_cmd,
"[no$no] match community-limit [(0-65535)$limit]",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do instead this way, and then checking for idx_limit is not needed.

"[no$no] match community-limit ![(0-65535)$limit]",

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -2693,6 +2693,11 @@ The following commands can be used in route maps:
happen only when BGP updates have completely same communities value
specified in the community list.

.. clicmd:: match community-limit (0-65535)

This command matches BGP updates that use community list, and with a community
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also document what 0 means explicitly. Because what is now, it means unlimited, but me as an operator understand it as "do not accept the route if it has any community attached".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whatever the meaning, I will document it. thanks for advice.

lib/routemap.c Outdated
@@ -1568,7 +1568,6 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
rule->rule_str = XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR, match_arg);
else
rule->rule_str = NULL;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop this change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -11,6 +11,7 @@ router bgp 65003
neighbor 192.168.1.2 soft-reconfiguration inbound
exit-address-family
!
bgp route-map delay-timer 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, u are right.

@pguibert6WIND
Copy link
Member Author

pguibert6WIND commented Jan 14, 2025

As counter example, which community should I keep if my limit is 1 and I have both no-export an no-advertise ?

Keep both?

why those communities are so special ? is there a RFC that describes this?

Add a mechanism in route-map to filter out route-map which have a list
of communities greater than the given number.

Signed-off-by: Philippe Guibert <[email protected]>
Add a test to control the community-list count.

Signed-off-by: Philippe Guibert <[email protected]>
Copy link
Member

@riw777 riw777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this should not apply to well-known communities? I suspect the result would be surprising to operators if we "randomly" choose which of the well-known communities to keep and which to discard, as these do have some pretty strong policy implications?

@pguibert6WIND
Copy link
Member Author

I wonder if this should not apply to well-known communities? I suspect the result would be surprising to operators if we "randomly" choose which of the well-known communities to keep and which to discard, as these do have some pretty strong policy implications?

An optional keyword could be added to relax the default behavior, for all well known attributes.

@pguibert6WIND
Copy link
Member Author

Copy link
Member

@riw777 riw777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good ... waiting on @ton31337 's comments

@donaldsharp
Copy link
Member

Yes, I'm pretty happy with this now. We discussed this during the meeting yesterday. End result of blanket dropping the route when hitting the community limit is reasonable. Just waiting on Donatas's comments

@ton31337 ton31337 merged commit 705e6f8 into FRRouting:master Jan 17, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants