Skip to content

bgpd: Add multiple clusters for bgp route-reflectors#22038

Draft
PierreNeltner6WIND wants to merge 9 commits into
FRRouting:masterfrom
PierreNeltner6WIND:multiple_clusters
Draft

bgpd: Add multiple clusters for bgp route-reflectors#22038
PierreNeltner6WIND wants to merge 9 commits into
FRRouting:masterfrom
PierreNeltner6WIND:multiple_clusters

Conversation

@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor

Add several commands that grant the possibility
to configure cluster-id on a per-neighbor basis
for route reflectors.

This allows more possibility in client-to-client
reflection management.

these commands are the following:
neighbor X.X.X.X cluster-id CLUSTER_ID
bgp cluster-id <per neighbor CLUSTER_ID|global>
client-to-client-reflection <true|fase>
show bgp clusters

two other command can change the behavior to be
closer to either juniper or cisco:
bgp cluster-id non-client-to-client prefer-global-cluster-id
bgp cluster-id loose_cluster-list-check

@frrbot frrbot Bot added bgp documentation tests Topotests, make check, etc labels May 22, 2026
@PierreNeltner6WIND PierreNeltner6WIND force-pushed the multiple_clusters branch 25 times, most recently from 45eb1e1 to 4fbaccf Compare May 25, 2026 10:53
Comment thread bgpd/bgpd.c Outdated
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread bgpd/bgpd.c

@riw777 riw777 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just a couple of minor formatting nits, along with the greptile comment

Comment thread bgpd/bgp_attr.c
Comment thread bgpd/bgp_attr.c
Comment thread bgpd/bgp_route.c Outdated
} else if (CHECK_FLAG(cluster1->flags, CLUSTER_FLAG_CLIENT_TO_CLIENT_INTRA_CLUSTER)) {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT)) {
if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CLUSTER_ID))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

should this blank line be here? just looks inconsistent.

Comment thread bgpd/bgp_vty.c Outdated
{ .val_bool = false },
);

FRR_CFG_DEFAULT_BOOL(BGP_NO_CLIENT_TO_CLIENT,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The double negative here seems like it might be a little confusing (?).

Comment thread bgpd/bgpd.c
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

1 similar comment
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

@greptile-apps

greptile-apps Bot commented Jun 4, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

1 similar comment
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread bgpd/bgpd.c Outdated
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread bgpd/bgpd.c
Comment thread bgpd/bgpd.c Outdated
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread bgpd/bgpd.c Outdated
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread bgpd/bgpd.c
Comment thread bgpd/bgpd.c
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

2 similar comments
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread bgpd/bgp_vty.c
Comment thread bgpd/bgpd.c
Add the command :
neighbor <A.B.C.D|X:X::X:X|WORD> cluster-id CLUSTER_ID
This command can be executed after router bgp AS,
 address-family AFI SAFI.
This command assigns a per-neighbor cluster
for that specific peer and afi safi combination.
If the peer is not previously declared CLUSTER_ID
 that command fails.

For that purpose the peer struct has one new attribute
per_neighbor_cluster that is an in_addr list
the content of which can be accessed through
afi and safi indexes.
This list is associated with a new af_flag that
indicates whether it is configured.

A new structure is added to represent the new per-neighbor
clusters: struct cluster, it contains the cluster-id of the cluster,
flags that define its behavior and a count of how many times a cluster
is referenced in the configuration, when that count goes down to
0 the cluster is deleted. That count doesn't aim at counting how many
peers are part of the cluster but how many times the cluster
is referenced in the config file since it is enough to know when
we don't need to keep the cluster.

The CLUSTER_FLAG_GLOBAL marks any per-neighbor cluster whose cluster-id
is identical to the global cluster-id: the unique historical cluster-id
of route-reflectors.
Whenever a cluster is marked as global,its flags are ignored and
the ones of the global cluster are used instead.

bgp instances have a new attribute:
per_neighbor_clusters: a list that contains cluster objects.

A peer that is part of a per-neighbor cluster and is configured
as a route-reflector-client, behaves as a classic
route-reflector-client peer.
However, prefixes received from that peer will be advertised
to other client and non-client peers with the per-neighbor cluster-id
of that peer in the prefix's cluster-list.
In the same spirit prefix reflected to one such peer from
a non-client peer will have the per-neighbor cluster-id
of the client-peer added to the cluster list.
When a prefix is reflected between two client peers part of
different per-neighbor clusters only the cluster-id of the sender
is added to the cluster-list.

If not configured as route-reflector client, a peer with a per-neighbor
cluster-id behaves as a normal peer.

Because the per-neighbor cluster-ids have an influence on
out-going prefixes, this commit also modifies update-groups
more specificaly ```updgrp_hash_key_make``` and ```updgrp_hash_cmp```
in order to have peers from different per-neighbor clusters sorted in
different update groups.

In the spirit of the rfc4456 any incoming prefix that contains
one of the cluster-ids of the route-reflector clients is dropped.
This implies changes to the
```bgp_cluster_filter``` function in order to check all clusters
and not only the global one.

Information about cluster-ids that are configured on peers
can be found in the running config and
in the display of that peer's information.

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
the topology of the test is the following :

   +------+            +------+
   |  R1--|-          -|--R6  |
   |      | \   R9   / |      |
C1 |      |  \ /  \ /  |      | C3
   |  R2--|---R4--R5---|--R7  |
   +------+  /      \  +------+
   +------+ /        \ +------+
C2 |  R3--|-          -|--R8  | C2
   +------+            +------+

All routers are in AS 100 (IBGP).
R4 and R5 are configured as a route reflector with their neighbors
as clients.
They form with r9 a full-mesh of non-client peers.
They each oversee two clusters of clients

Test that reflection in the default setup works as intended and
that cluster-lists are correct, verifies that client-to-client
configurations works well both in the per-neighbor
and global clusters.
Test that the non-client-to-client prefer-global-cluster-id and
loose-cluster-list-check configuration work as intentded.

These checks are achieved through verifying the prefixes in
the bgp tables of each client router and
on R9 as well as their cluster-lists.

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
Modify style to comply with style guidlines in bgp_route.c

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
Refactor the route-reflector reflection-check in bgp_route.c
in order to prepare for next commit.

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
Add 2 new flags: CLUSTER_FLAG_CLIENT_TO_CLIENT_INTRA_CLUSTER
and CLUSTER_FLAG_CLIENT_TO_CLIENT_INTRA_CLUSTER_CONFIGURED.
These flags represent the three states that are possible
for a cluster configuration and apply to the flags attribute
of the cluster object:
the cluster-to-cluster behavior is not configured,
the cluster-to-cluster behavior is configured and enabled,
the cluster-to-cluster behavior is configured and disabled

Add 2 new flags: BGP_FLAG_CLIENT_TO_CLIENT_GLOBAL_CLUSTER
and BGP_FLAG_CLIENT_TO_CLIENT_GLOBAL_CLUSTER_CONFIGURED.
These flags have same role as the ones described before
but for the global cluster, they apply to bgp->flags.

The behavior of client-to-client reflection is now the
following:
reflection inside of a cluster is always allowed
if it is configured as allowed for that cluster,
it is always forbidden if it is configured
as forbidden for that cluster.
If nothing is configured for that cluster then the legacy
client-to-client reflection configuration applies.
Between two different clusters the legacy
client-to-client reflection configuration applies.
This allows any pattern of reflection to be easily set up.

This configuration is achieved through the new command:
```[no] bgp cluster <per-neighbor X.X.X.X|global> \
 client-to-client-reflection <always|never>```

That command configures client-to-client reflection
on any per-neighbor cluster or the global cluster.
In its negative form it unconfigures
client-to-client reflection.

If it is configured on a per-neighbor cluster then
adds one to the reference of that cluster and
if it doesn't exist creates it in a similar fashion to the
neighbor X.X.X.X cluster-id command.

These configurations are shown in the running config

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
add the command :
```Add command show bgp clusters [json]```
that shows information about all configured or referenced clusters
including the global cluster and per-neighbor clusters
this includes the cluster id, client-to-client reflection policies
inside of each cluster and number of times referenced in the
configuration as well as whether it is overwritten by the global
cluster.
the json format is the following:
{
 "global":{
  "cluster-id":"CLUSTER_ID",
  "client-to-client-reflection":<"always"|"never"|"not-configured">
 },
 "per-neighbor":[
  "cluster-id":"CLUSTER_ID",
  "global":bool,
  "client-to-client-reflection":<"always"|"never"|"not-configured">,
  "refcnt":NUMBER_OF_REFERENCES
 ],
}

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
Add the command :
bgp cluster-id non-client-to-client prefer-global-cluster
This command configures the new flag BGP_FLAG_PREFER_GLOBAL_CLUSTER

When this flag is configured, the global cluster-id is added to the
cluster list of prefixes reflected from non-clients toward client-peers,
default behavior is to add the destination peer's cluster-id instead.
When configured the behavior is similar to the cisco one and further
from a classic cluster-id behavior.

This feature modifies the attributes of outgoing routes and so modifies
the ```bgp_packet_attribute``` function from bgp_attribute.c
This flag can be seen in the running config.

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
add the command:
bgp cluster-id loose-cluster-list-check

This command configures the new bgp flag:
BGP_FLAG_LOOSE_CLUSTER_LIST_CHECK

When this is configured, prefixes that contain one or more of the
cluster-ids of the per neighbor clusters of the router are no
longer dropped when received, they are just not reflected to members
of these clusters.

This implies that the ```bgp_cluster_filter``` function from
bgp_route.c is modified to no longer reject these and that
```subgroup_announce_check``` is modified to reject these prefixes
only when advertising toward a member of that cluster.

When configured this option shows a behavior closer to
juniper behavior while still respecting rfc4456.

This configuration can be seen in the running-config.

Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
Signed-off-by: Pierre Neltner <pierre.neltner@6wind.com>
@PierreNeltner6WIND

Copy link
Copy Markdown
Contributor Author

@greptile review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bgp documentation master rebase PR needs rebase size/XXL tests Topotests, make check, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants