mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-12 03:44:01 +00:00
bgp: fix case where confederation id same as member-as
currently the following configuration dut: ! interface ntfp2 ip router isis 1 ! router bgp 200 no bgp ebgp-requires-policy bgp confederation identifier 300 bgp confederation peers 300 neighbor 192.168.1.1 remote-as 100 neighbor 192.168.2.2 remote-as 300 ! address-family ipv4 unicast neighbor 192.168.2.2 default-originate exit-address-family ! router isis 1 is-type level-2-only net 49.0001.0002.0002.0002.00 redistribute ipv4 connected level-2 ! end router: ! interface ntfp2 ip router isis 1 isis circuit-type level-2-only ! router bgp 300 no bgp ebgp-requires-policy bgp confederation identifier 300 bgp confederation peers 200 neighbor 192.168.2.1 remote-as 200 neighbor 192.168.3.2 remote-as 400 ! address-family ipv4 unicast network 3.3.3.0/24 exit-address-family ! router isis 1 is-type level-2-only net 49.0001.0003.0003.0003.00 redistribute ipv4 connected level-2 ! end on dut result of show bgp ipv4 unicast command is: show bgp ipv4 unicast BGP table version is 1, local router ID is 192.168.2.1, vrf id 0 Default local pref 100, local AS 200 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path *> 1.1.1.0/24 192.168.1.1 0 0 100 i instead of sho bgp ipv4 unicast BGP table version is 3, local router ID is 192.168.2.1, vrf id 0 Default local pref 100, local AS 200 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path *> 1.1.1.0/24 192.168.1.1 0 0 100 i *> 3.3.3.0/24 192.168.2.2 0 100 0 (300) i *> 4.4.4.0/24 192.168.3.2 0 100 0 (300) 400 i Displayed 3 routes and 3 total paths According to RFC 5065:the usage of one of the member AS number as the confederation identifier is not forbidden. fixes are the following in bgp_route.c: in bgp_update remove the test for presence of confederation id in as_path since, this case is allowed; in bgp_vty.c bgp_confederation_peers, remove the test on peer as value in bgpd.c bgp_confederation_peers_add remove the test on peer as value invert the order of setting peer->sort value and peer->local_as, since peer->sort is depending from current peer->local_as value bgp_confederation_peers_remove invert the order of setting peer->sort value and peer->local_as, since peer->sort is depending from current peer->local_as value Signed-off-by: Francois Dumontet <francois.dumontet@6wind.com>
This commit is contained in:
parent
53317d66d1
commit
b0a8f709a5
@ -1187,6 +1187,33 @@ int aspath_loop_check(struct aspath *aspath, as_t asno)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* AS path loop check. If aspath contains asno
|
||||||
|
* that is a confed id then return >= 1.
|
||||||
|
*/
|
||||||
|
int aspath_loop_check_confed(struct aspath *aspath, as_t asno)
|
||||||
|
{
|
||||||
|
struct assegment *seg;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (aspath == NULL || aspath->segments == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
seg = aspath->segments;
|
||||||
|
|
||||||
|
while (seg) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < seg->length; i++)
|
||||||
|
if (seg->type != AS_CONFED_SEQUENCE &&
|
||||||
|
seg->type != AS_CONFED_SET && seg->as[i] == asno)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
seg = seg->next;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* When all of AS path is private AS return 1. */
|
/* When all of AS path is private AS return 1. */
|
||||||
bool aspath_private_as_check(struct aspath *aspath)
|
bool aspath_private_as_check(struct aspath *aspath)
|
||||||
{
|
{
|
||||||
|
@ -111,6 +111,7 @@ extern unsigned int aspath_key_make(const void *p);
|
|||||||
extern unsigned int aspath_get_first_as(struct aspath *aspath);
|
extern unsigned int aspath_get_first_as(struct aspath *aspath);
|
||||||
extern unsigned int aspath_get_last_as(struct aspath *aspath);
|
extern unsigned int aspath_get_last_as(struct aspath *aspath);
|
||||||
extern int aspath_loop_check(struct aspath *aspath, as_t asno);
|
extern int aspath_loop_check(struct aspath *aspath, as_t asno);
|
||||||
|
extern int aspath_loop_check_confed(struct aspath *aspath, as_t asno);
|
||||||
extern bool aspath_private_as_check(struct aspath *aspath);
|
extern bool aspath_private_as_check(struct aspath *aspath);
|
||||||
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
|
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
|
||||||
as_t target_asn,
|
as_t target_asn,
|
||||||
|
@ -2197,7 +2197,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
|
|||||||
|
|
||||||
/* If we're a CONFED we need to loop check the CONFED ID too */
|
/* If we're a CONFED we need to loop check the CONFED ID too */
|
||||||
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
|
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
|
||||||
if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
|
if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
|
||||||
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
|
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
|
"%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
|
||||||
@ -4113,16 +4113,23 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||||||
|
|
||||||
/* AS path loop check. */
|
/* AS path loop check. */
|
||||||
if (do_loop_check) {
|
if (do_loop_check) {
|
||||||
if (aspath_loop_check(attr->aspath, bgp->as) > allowas_in ||
|
if (aspath_loop_check(attr->aspath, bgp->as) >
|
||||||
(CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) &&
|
peer->allowas_in[afi][safi]) {
|
||||||
(aspath_loop_check(attr->aspath, bgp->confed_id) >
|
|
||||||
allowas_in))) {
|
|
||||||
peer->stat_pfx_aspath_loop++;
|
peer->stat_pfx_aspath_loop++;
|
||||||
reason = "as-path contains our own AS;";
|
reason = "as-path contains our own AS;";
|
||||||
goto filtered;
|
goto filtered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we're a CONFED we need to loop check the CONFED ID too */
|
||||||
|
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
|
||||||
|
if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
|
||||||
|
peer->allowas_in[afi][safi]) {
|
||||||
|
peer->stat_pfx_aspath_loop++;
|
||||||
|
reason = "as-path contains our own confed AS;";
|
||||||
|
goto filtered;
|
||||||
|
}
|
||||||
|
|
||||||
/* Route reflector originator ID check. If ACCEPT_OWN mechanism is
|
/* Route reflector originator ID check. If ACCEPT_OWN mechanism is
|
||||||
* enabled, then take care of that too.
|
* enabled, then take care of that too.
|
||||||
*/
|
*/
|
||||||
|
@ -1917,13 +1917,6 @@ DEFUN (bgp_confederation_peers,
|
|||||||
|
|
||||||
for (i = idx_asn; i < argc; i++) {
|
for (i = idx_asn; i < argc; i++) {
|
||||||
as = strtoul(argv[i]->arg, NULL, 10);
|
as = strtoul(argv[i]->arg, NULL, 10);
|
||||||
|
|
||||||
if (bgp->as == as) {
|
|
||||||
vty_out(vty,
|
|
||||||
"%% Local member-AS not allowed in confed peer list\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bgp_confederation_peers_add(bgp, as);
|
bgp_confederation_peers_add(bgp, as);
|
||||||
}
|
}
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
@ -671,7 +671,7 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
|
|||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
|
|
||||||
if (bgp->as == as)
|
if (!bgp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bgp_confederation_peers_check(bgp, as))
|
if (bgp_confederation_peers_check(bgp, as))
|
||||||
@ -687,8 +687,8 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
|
|||||||
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
|
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
|
||||||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||||||
if (peer->as == as) {
|
if (peer->as == as) {
|
||||||
(void)peer_sort(peer);
|
|
||||||
peer->local_as = bgp->as;
|
peer->local_as = bgp->as;
|
||||||
|
(void)peer_sort(peer);
|
||||||
if (BGP_IS_VALID_STATE_FOR_NOTIF(
|
if (BGP_IS_VALID_STATE_FOR_NOTIF(
|
||||||
peer->status)) {
|
peer->status)) {
|
||||||
peer->last_reset =
|
peer->last_reset =
|
||||||
@ -738,8 +738,8 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
|
|||||||
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
|
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
|
||||||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||||||
if (peer->as == as) {
|
if (peer->as == as) {
|
||||||
(void)peer_sort(peer);
|
|
||||||
peer->local_as = bgp->confed_id;
|
peer->local_as = bgp->confed_id;
|
||||||
|
(void)peer_sort(peer);
|
||||||
if (BGP_IS_VALID_STATE_FOR_NOTIF(
|
if (BGP_IS_VALID_STATE_FOR_NOTIF(
|
||||||
peer->status)) {
|
peer->status)) {
|
||||||
peer->last_reset =
|
peer->last_reset =
|
||||||
|
Loading…
Reference in New Issue
Block a user