2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2002-12-13 21:15:29 +01:00
|
|
|
/* BGP advertisement and adjacency
|
2017-05-13 10:25:29 +02:00
|
|
|
* Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "command.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "hash.h"
|
2023-03-07 20:22:48 +01:00
|
|
|
#include "frrevent.h"
|
2015-05-20 03:03:47 +02:00
|
|
|
#include "queue.h"
|
2016-01-07 16:03:01 +01:00
|
|
|
#include "filter.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "bgpd/bgpd.h"
|
|
|
|
#include "bgpd/bgp_table.h"
|
|
|
|
#include "bgpd/bgp_route.h"
|
|
|
|
#include "bgpd/bgp_advertise.h"
|
|
|
|
#include "bgpd/bgp_attr.h"
|
2015-05-20 02:58:12 +02:00
|
|
|
#include "bgpd/bgp_debug.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "bgpd/bgp_aspath.h"
|
|
|
|
#include "bgpd/bgp_packet.h"
|
|
|
|
#include "bgpd/bgp_fsm.h"
|
|
|
|
#include "bgpd/bgp_mplsvpn.h"
|
2015-05-20 03:03:47 +02:00
|
|
|
#include "bgpd/bgp_updgrp.h"
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* BGP advertise attribute is used for pack same attribute update into
|
|
|
|
one packet. To do that we maintain attribute hash in struct
|
|
|
|
peer. */
|
2022-07-25 15:37:17 +02:00
|
|
|
struct bgp_advertise_attr *bgp_advertise_attr_new(void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2019-02-25 21:30:31 +01:00
|
|
|
return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR,
|
|
|
|
sizeof(struct bgp_advertise_attr));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
void bgp_advertise_attr_free(struct bgp_advertise_attr *baa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2023-10-06 18:48:38 +02:00
|
|
|
bgp_advertise_attr_fifo_fini(&baa->fifo);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
|
|
|
|
}
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
static void *bgp_advertise_attr_hash_alloc(void *p)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
[bgpd] Fix warnings: hash callbacks should match hash API declarations
2007-04-22 Sebastien Tandel <sebastien@tandel.be>
* bgp_advertise.c : (baa_hash_alloc, baa_hash_key, baa_hash_cmp)
conforms to quagga hash API. Defines _hash_[alloc|key|cmp] with
void * arguments as defined by the API.
* bgp_aspath.c,h : (aspath_key_make) conforms to quagga hash API.
Defines _hash_[alloc|key|cmp] with void * arguments as defined by
the API.
* bgp_attr.c,h : (cluster_hash_alloc, cluster_hash_key_make,
cluster_hash_cmp, transit_hash_alloc, transit_hash_key_make,
transit_hash_cmp, attrhash_key_make, attrhash_cmp,
bgp_attr_hash_alloc) conforms to quagga hash API. Defines
_hash_[alloc|key|cmp] with void * arguments as defined by the API.
2007-04-29 20:25:17 +02:00
|
|
|
struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct bgp_advertise_attr *baa;
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
baa = bgp_advertise_attr_new();
|
2002-12-13 21:15:29 +01:00
|
|
|
baa->attr = ref->attr;
|
2023-10-06 18:48:38 +02:00
|
|
|
|
|
|
|
bgp_advertise_attr_fifo_init(&baa->fifo);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return baa;
|
|
|
|
}
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
unsigned int bgp_advertise_attr_hash_key(const void *p)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2019-05-14 22:19:07 +02:00
|
|
|
const struct bgp_advertise_attr *baa = p;
|
[bgpd] Fix warnings: hash callbacks should match hash API declarations
2007-04-22 Sebastien Tandel <sebastien@tandel.be>
* bgp_advertise.c : (baa_hash_alloc, baa_hash_key, baa_hash_cmp)
conforms to quagga hash API. Defines _hash_[alloc|key|cmp] with
void * arguments as defined by the API.
* bgp_aspath.c,h : (aspath_key_make) conforms to quagga hash API.
Defines _hash_[alloc|key|cmp] with void * arguments as defined by
the API.
* bgp_attr.c,h : (cluster_hash_alloc, cluster_hash_key_make,
cluster_hash_cmp, transit_hash_alloc, transit_hash_key_make,
transit_hash_cmp, attrhash_key_make, attrhash_cmp,
bgp_attr_hash_alloc) conforms to quagga hash API. Defines
_hash_[alloc|key|cmp] with void * arguments as defined by the API.
2007-04-29 20:25:17 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return attrhash_key_make(baa->attr);
|
|
|
|
}
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
bool bgp_advertise_attr_hash_cmp(const void *p1, const void *p2)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2008-08-14 17:25:25 +02:00
|
|
|
const struct bgp_advertise_attr *baa1 = p1;
|
|
|
|
const struct bgp_advertise_attr *baa2 = p2;
|
[bgpd] Fix warnings: hash callbacks should match hash API declarations
2007-04-22 Sebastien Tandel <sebastien@tandel.be>
* bgp_advertise.c : (baa_hash_alloc, baa_hash_key, baa_hash_cmp)
conforms to quagga hash API. Defines _hash_[alloc|key|cmp] with
void * arguments as defined by the API.
* bgp_aspath.c,h : (aspath_key_make) conforms to quagga hash API.
Defines _hash_[alloc|key|cmp] with void * arguments as defined by
the API.
* bgp_attr.c,h : (cluster_hash_alloc, cluster_hash_key_make,
cluster_hash_cmp, transit_hash_alloc, transit_hash_key_make,
transit_hash_cmp, attrhash_key_make, attrhash_cmp,
bgp_attr_hash_alloc) conforms to quagga hash API. Defines
_hash_[alloc|key|cmp] with void * arguments as defined by the API.
2007-04-29 20:25:17 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return attrhash_cmp(baa1->attr, baa2->attr);
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* BGP update and withdraw information is stored in BGP advertise
|
|
|
|
structure. This structure is referred from BGP adjacency
|
|
|
|
information. */
|
2009-02-09 19:14:16 +01:00
|
|
|
struct bgp_advertise *bgp_advertise_new(void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2019-02-25 21:30:31 +01:00
|
|
|
return XCALLOC(MTYPE_BGP_ADVERTISE, sizeof(struct bgp_advertise));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void bgp_advertise_free(struct bgp_advertise *adv)
|
|
|
|
{
|
2018-10-03 00:34:03 +02:00
|
|
|
if (adv->pathi)
|
|
|
|
/* bgp_advertise bgp_path_info reference */
|
|
|
|
bgp_path_info_unlock(adv->pathi);
|
2002-12-13 21:15:29 +01:00
|
|
|
XFREE(MTYPE_BGP_ADVERTISE, adv);
|
|
|
|
}
|
|
|
|
|
|
|
|
void bgp_advertise_add(struct bgp_advertise_attr *baa,
|
|
|
|
struct bgp_advertise *adv)
|
|
|
|
{
|
2023-10-06 18:48:38 +02:00
|
|
|
bgp_advertise_attr_fifo_add_tail(&baa->fifo, adv);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void bgp_advertise_delete(struct bgp_advertise_attr *baa,
|
|
|
|
struct bgp_advertise *adv)
|
|
|
|
{
|
2023-10-06 18:48:38 +02:00
|
|
|
bgp_advertise_attr_fifo_del(&baa->fifo, adv);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
struct bgp_advertise_attr *bgp_advertise_attr_intern(struct hash *hash,
|
|
|
|
struct attr *attr)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_advertise_attr ref;
|
|
|
|
struct bgp_advertise_attr *baa;
|
|
|
|
|
|
|
|
ref.attr = bgp_attr_intern(attr);
|
2022-07-25 15:37:17 +02:00
|
|
|
baa = (struct bgp_advertise_attr *)hash_get(
|
|
|
|
hash, &ref, bgp_advertise_attr_hash_alloc);
|
2002-12-13 21:15:29 +01:00
|
|
|
baa->refcnt++;
|
|
|
|
|
|
|
|
return baa;
|
|
|
|
}
|
|
|
|
|
2022-07-25 15:37:17 +02:00
|
|
|
void bgp_advertise_attr_unintern(struct hash *hash,
|
|
|
|
struct bgp_advertise_attr *baa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
if (baa->refcnt)
|
|
|
|
baa->refcnt--;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (baa->refcnt && baa->attr)
|
bgpd: Try fix extcommunity resource allocation probs, particularly with 'set extcom..'
* Extended communities has some kind of resource allocation problem which
causes a double-free if the 'set extcommunity ...' command is used.
Try fix by properly interning extcommunities.
Also, more generally, make unintern functions take a double pointer
so they can NULL out callers references - a usefully defensive programming
pattern for functions which make refs invalid.
Sadly, this patch doesn't fix the problem entirely - crashes still
occur on session clear.
* bgp_ecommunity.h: (ecommunity_{free,unintern}) take double pointer
args.
* bgp_community.h: (community_unintern) ditto
* bgp_attr.h: (bgp_attr_intern) ditto
* bgp_aspath.h: (bgp_aspath.h) ditto
* (general) update all callers of above
* bgp_routemap.c: (route_set_ecommunity_{rt,soo}) intern the new extcom added
to the attr, and unintern any old one.
(route_set_ecommunity_{rt,soo}_compile) intern the extcom to be used
for the route-map set.
(route_set_ecommunity_*_free) unintern to match, instead of free
(route_set_ecommunity_soo) Do as _rt does and don't just leak
any pre-existing community, add to it (is additive right though?)
2010-11-23 22:28:03 +01:00
|
|
|
bgp_attr_unintern(&baa->attr);
|
2002-12-13 21:15:29 +01:00
|
|
|
else {
|
|
|
|
if (baa->attr) {
|
|
|
|
hash_release(hash, baa);
|
bgpd: Try fix extcommunity resource allocation probs, particularly with 'set extcom..'
* Extended communities has some kind of resource allocation problem which
causes a double-free if the 'set extcommunity ...' command is used.
Try fix by properly interning extcommunities.
Also, more generally, make unintern functions take a double pointer
so they can NULL out callers references - a usefully defensive programming
pattern for functions which make refs invalid.
Sadly, this patch doesn't fix the problem entirely - crashes still
occur on session clear.
* bgp_ecommunity.h: (ecommunity_{free,unintern}) take double pointer
args.
* bgp_community.h: (community_unintern) ditto
* bgp_attr.h: (bgp_attr_intern) ditto
* bgp_aspath.h: (bgp_aspath.h) ditto
* (general) update all callers of above
* bgp_routemap.c: (route_set_ecommunity_{rt,soo}) intern the new extcom added
to the attr, and unintern any old one.
(route_set_ecommunity_{rt,soo}_compile) intern the extcom to be used
for the route-map set.
(route_set_ecommunity_*_free) unintern to match, instead of free
(route_set_ecommunity_soo) Do as _rt does and don't just leak
any pre-existing community, add to it (is additive right though?)
2010-11-23 22:28:03 +01:00
|
|
|
bgp_attr_unintern(&baa->attr);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2022-07-25 15:37:17 +02:00
|
|
|
bgp_advertise_attr_free(baa);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
|
2020-03-20 10:57:54 +01:00
|
|
|
uint32_t addpath_tx_id)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_adj_out *adj;
|
2015-05-20 03:03:47 +02:00
|
|
|
struct peer_af *paf;
|
BGP: support for addpath TX
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Vivek Venkataraman <vivek@cumulusnetworks.com
Ticket: CM-8014
This implements addpath TX with the first feature to use it
being "neighbor x.x.x.x addpath-tx-all-paths".
One change to show output is 'show ip bgp x.x.x.x'. If no addpath-tx
features are configured for any peers then everything looks the same
as it is today in that "Advertised to" is at the top and refers to
which peers the bestpath was advertise to.
root@superm-redxp-05[quagga-stash5]# vtysh -c 'show ip bgp 1.1.1.1'
BGP routing table entry for 1.1.1.1/32
Paths: (6 available, best #6, table Default-IP-Routing-Table)
Advertised to non peer-group peers:
r1(10.0.0.1) r2(10.0.0.2) r3(10.0.0.3) r4(10.0.0.4) r5(10.0.0.5) r6(10.0.0.6) r8(10.0.0.8)
Local, (Received from a RR-client)
12.12.12.12 (metric 20) from r2(10.0.0.2) (10.0.0.2)
Origin IGP, metric 0, localpref 100, valid, internal
AddPath ID: RX 0, TX 8
Last update: Fri Oct 30 18:26:44 2015
[snip]
but once you enable an addpath feature we must display "Advertised to" on a path-by-path basis:
superm-redxp-05# show ip bgp 1.1.1.1/32
BGP routing table entry for 1.1.1.1/32
Paths: (6 available, best #6, table Default-IP-Routing-Table)
Local, (Received from a RR-client)
12.12.12.12 (metric 20) from r2(10.0.0.2) (10.0.0.2)
Origin IGP, metric 0, localpref 100, valid, internal
AddPath ID: RX 0, TX 8
Advertised to: r8(10.0.0.8)
Last update: Fri Oct 30 18:26:44 2015
Local, (Received from a RR-client)
34.34.34.34 (metric 20) from r3(10.0.0.3) (10.0.0.3)
Origin IGP, metric 0, localpref 100, valid, internal
AddPath ID: RX 0, TX 7
Advertised to: r8(10.0.0.8)
Last update: Fri Oct 30 18:26:39 2015
Local, (Received from a RR-client)
56.56.56.56 (metric 20) from r6(10.0.0.6) (10.0.0.6)
Origin IGP, metric 0, localpref 100, valid, internal
AddPath ID: RX 0, TX 6
Advertised to: r8(10.0.0.8)
Last update: Fri Oct 30 18:26:39 2015
Local, (Received from a RR-client)
56.56.56.56 (metric 20) from r5(10.0.0.5) (10.0.0.5)
Origin IGP, metric 0, localpref 100, valid, internal
AddPath ID: RX 0, TX 5
Advertised to: r8(10.0.0.8)
Last update: Fri Oct 30 18:26:39 2015
Local, (Received from a RR-client)
34.34.34.34 (metric 20) from r4(10.0.0.4) (10.0.0.4)
Origin IGP, metric 0, localpref 100, valid, internal
AddPath ID: RX 0, TX 4
Advertised to: r8(10.0.0.8)
Last update: Fri Oct 30 18:26:39 2015
Local, (Received from a RR-client)
12.12.12.12 (metric 20) from r1(10.0.0.1) (10.0.0.1)
Origin IGP, metric 0, localpref 100, valid, internal, best
AddPath ID: RX 0, TX 3
Advertised to: r1(10.0.0.1) r2(10.0.0.2) r3(10.0.0.3) r4(10.0.0.4) r5(10.0.0.5) r6(10.0.0.6) r8(10.0.0.8)
Last update: Fri Oct 30 18:26:34 2015
superm-redxp-05#
2015-11-05 18:29:43 +01:00
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
2022-01-27 08:51:59 +01:00
|
|
|
bool addpath_capable;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
|
2017-09-15 17:47:35 +02:00
|
|
|
SUBGRP_FOREACH_PEER (adj->subgroup, paf)
|
|
|
|
if (paf->peer == peer) {
|
|
|
|
afi = SUBGRP_AFI(adj->subgroup);
|
|
|
|
safi = SUBGRP_SAFI(adj->subgroup);
|
|
|
|
addpath_capable =
|
|
|
|
bgp_addpath_encode_tx(peer, afi, safi);
|
|
|
|
|
|
|
|
/* Match on a specific addpath_tx_id if we are
|
|
|
|
* using addpath for
|
|
|
|
* this
|
|
|
|
* peer and if an addpath_tx_id was specified */
|
|
|
|
if (addpath_capable && addpath_tx_id
|
|
|
|
&& adj->addpath_tx_id != addpath_tx_id)
|
|
|
|
continue;
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
return (adj->adv
|
|
|
|
? (adj->adv->baa ? true : false)
|
|
|
|
: (adj->attr ? true : false));
|
2017-09-15 17:47:35 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
return false;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
|
bgpd: fix labels in adj-rib-in
In a BGP L3VPN context using ADJ-RIB-IN (ie. enabled with
'soft-reconfiguration inbound'), after applying a deny route-map and
removing it, the remote MPLS label information is lost. As a result, BGP
is unable to re-install the related routes in the RIB.
For example,
> router bgp 65500
> [..]
> neighbor 192.0.2.2 remote-as 65501
> address-family ipv4 vpn
> neighbor 192.0.2.2 activate
> neighbor 192.0.2.2 soft-reconfiguration inbound
The 192.168.0.0/24 prefix has a remote label value of 102 in the BGP
RIB.
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
> Remote label: 102
A route-map now filter all incoming BGP updates:
> route-map rmap deny 1
> router bgp 65500
> address-family ipv4 vpn
> neighbor 192.0.2.2 route-map rmap in
The prefix is now filtered:
> # show bgp ipv4 vpn 192.168.0.0/24
> #
The route-map is detached:
> router bgp 65500
> address-family ipv4 vpn
> no neighbor 192.168.0.1 route-map rmap in
The BGP RIB entry is present but the remote label is lost:
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
The reason for the loose is that labels are stored within struct attr ->
struct extra -> struct bgp_labels but not in the struct bgp_adj_in.
Reference the bgp_labels pointer in struct bgp_adj_in and use its values
when doing a soft reconfiguration of the BGP table.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2023-01-13 15:59:52 +01:00
|
|
|
uint32_t addpath_id, struct bgp_labels *labels)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_adj_in *adj;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
for (adj = dest->adj_in; adj; adj = adj->next) {
|
2015-05-20 03:04:01 +02:00
|
|
|
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
|
2024-01-30 15:18:43 +01:00
|
|
|
if (!attrhash_cmp(adj->attr, attr)) {
|
bgpd: Try fix extcommunity resource allocation probs, particularly with 'set extcom..'
* Extended communities has some kind of resource allocation problem which
causes a double-free if the 'set extcommunity ...' command is used.
Try fix by properly interning extcommunities.
Also, more generally, make unintern functions take a double pointer
so they can NULL out callers references - a usefully defensive programming
pattern for functions which make refs invalid.
Sadly, this patch doesn't fix the problem entirely - crashes still
occur on session clear.
* bgp_ecommunity.h: (ecommunity_{free,unintern}) take double pointer
args.
* bgp_community.h: (community_unintern) ditto
* bgp_attr.h: (bgp_attr_intern) ditto
* bgp_aspath.h: (bgp_aspath.h) ditto
* (general) update all callers of above
* bgp_routemap.c: (route_set_ecommunity_{rt,soo}) intern the new extcom added
to the attr, and unintern any old one.
(route_set_ecommunity_{rt,soo}_compile) intern the extcom to be used
for the route-map set.
(route_set_ecommunity_*_free) unintern to match, instead of free
(route_set_ecommunity_soo) Do as _rt does and don't just leak
any pre-existing community, add to it (is additive right though?)
2010-11-23 22:28:03 +01:00
|
|
|
bgp_attr_unintern(&adj->attr);
|
2002-12-13 21:15:29 +01:00
|
|
|
adj->attr = bgp_attr_intern(attr);
|
|
|
|
}
|
bgpd: fix labels in adj-rib-in
In a BGP L3VPN context using ADJ-RIB-IN (ie. enabled with
'soft-reconfiguration inbound'), after applying a deny route-map and
removing it, the remote MPLS label information is lost. As a result, BGP
is unable to re-install the related routes in the RIB.
For example,
> router bgp 65500
> [..]
> neighbor 192.0.2.2 remote-as 65501
> address-family ipv4 vpn
> neighbor 192.0.2.2 activate
> neighbor 192.0.2.2 soft-reconfiguration inbound
The 192.168.0.0/24 prefix has a remote label value of 102 in the BGP
RIB.
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
> Remote label: 102
A route-map now filter all incoming BGP updates:
> route-map rmap deny 1
> router bgp 65500
> address-family ipv4 vpn
> neighbor 192.0.2.2 route-map rmap in
The prefix is now filtered:
> # show bgp ipv4 vpn 192.168.0.0/24
> #
The route-map is detached:
> router bgp 65500
> address-family ipv4 vpn
> no neighbor 192.168.0.1 route-map rmap in
The BGP RIB entry is present but the remote label is lost:
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
The reason for the loose is that labels are stored within struct attr ->
struct extra -> struct bgp_labels but not in the struct bgp_adj_in.
Reference the bgp_labels pointer in struct bgp_adj_in and use its values
when doing a soft reconfiguration of the BGP table.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2023-01-13 15:59:52 +01:00
|
|
|
if (!bgp_labels_cmp(adj->labels, labels)) {
|
|
|
|
bgp_labels_unintern(&adj->labels);
|
|
|
|
adj->labels = bgp_labels_intern(labels);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
adj->peer = peer_lock(peer); /* adj_in peer reference */
|
2002-12-13 21:15:29 +01:00
|
|
|
adj->attr = bgp_attr_intern(attr);
|
2022-08-18 00:27:54 +02:00
|
|
|
adj->uptime = monotime(NULL);
|
2015-05-20 03:04:01 +02:00
|
|
|
adj->addpath_rx_id = addpath_id;
|
bgpd: fix labels in adj-rib-in
In a BGP L3VPN context using ADJ-RIB-IN (ie. enabled with
'soft-reconfiguration inbound'), after applying a deny route-map and
removing it, the remote MPLS label information is lost. As a result, BGP
is unable to re-install the related routes in the RIB.
For example,
> router bgp 65500
> [..]
> neighbor 192.0.2.2 remote-as 65501
> address-family ipv4 vpn
> neighbor 192.0.2.2 activate
> neighbor 192.0.2.2 soft-reconfiguration inbound
The 192.168.0.0/24 prefix has a remote label value of 102 in the BGP
RIB.
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
> Remote label: 102
A route-map now filter all incoming BGP updates:
> route-map rmap deny 1
> router bgp 65500
> address-family ipv4 vpn
> neighbor 192.0.2.2 route-map rmap in
The prefix is now filtered:
> # show bgp ipv4 vpn 192.168.0.0/24
> #
The route-map is detached:
> router bgp 65500
> address-family ipv4 vpn
> no neighbor 192.168.0.1 route-map rmap in
The BGP RIB entry is present but the remote label is lost:
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
The reason for the loose is that labels are stored within struct attr ->
struct extra -> struct bgp_labels but not in the struct bgp_adj_in.
Reference the bgp_labels pointer in struct bgp_adj_in and use its values
when doing a soft reconfiguration of the BGP table.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2023-01-13 15:59:52 +01:00
|
|
|
adj->labels = bgp_labels_intern(labels);
|
2020-03-27 00:11:58 +01:00
|
|
|
BGP_ADJ_IN_ADD(dest, adj);
|
2024-04-25 16:53:21 +02:00
|
|
|
peer->stat_pfx_adj_rib_in++;
|
2020-03-27 00:11:58 +01:00
|
|
|
bgp_dest_lock_node(dest);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2023-09-10 14:53:36 +02:00
|
|
|
void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
bgpd: Try fix extcommunity resource allocation probs, particularly with 'set extcom..'
* Extended communities has some kind of resource allocation problem which
causes a double-free if the 'set extcommunity ...' command is used.
Try fix by properly interning extcommunities.
Also, more generally, make unintern functions take a double pointer
so they can NULL out callers references - a usefully defensive programming
pattern for functions which make refs invalid.
Sadly, this patch doesn't fix the problem entirely - crashes still
occur on session clear.
* bgp_ecommunity.h: (ecommunity_{free,unintern}) take double pointer
args.
* bgp_community.h: (community_unintern) ditto
* bgp_attr.h: (bgp_attr_intern) ditto
* bgp_aspath.h: (bgp_aspath.h) ditto
* (general) update all callers of above
* bgp_routemap.c: (route_set_ecommunity_{rt,soo}) intern the new extcom added
to the attr, and unintern any old one.
(route_set_ecommunity_{rt,soo}_compile) intern the extcom to be used
for the route-map set.
(route_set_ecommunity_*_free) unintern to match, instead of free
(route_set_ecommunity_soo) Do as _rt does and don't just leak
any pre-existing community, add to it (is additive right though?)
2010-11-23 22:28:03 +01:00
|
|
|
bgp_attr_unintern(&bai->attr);
|
bgpd: fix labels in adj-rib-in
In a BGP L3VPN context using ADJ-RIB-IN (ie. enabled with
'soft-reconfiguration inbound'), after applying a deny route-map and
removing it, the remote MPLS label information is lost. As a result, BGP
is unable to re-install the related routes in the RIB.
For example,
> router bgp 65500
> [..]
> neighbor 192.0.2.2 remote-as 65501
> address-family ipv4 vpn
> neighbor 192.0.2.2 activate
> neighbor 192.0.2.2 soft-reconfiguration inbound
The 192.168.0.0/24 prefix has a remote label value of 102 in the BGP
RIB.
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
> Remote label: 102
A route-map now filter all incoming BGP updates:
> route-map rmap deny 1
> router bgp 65500
> address-family ipv4 vpn
> neighbor 192.0.2.2 route-map rmap in
The prefix is now filtered:
> # show bgp ipv4 vpn 192.168.0.0/24
> #
The route-map is detached:
> router bgp 65500
> address-family ipv4 vpn
> no neighbor 192.168.0.1 route-map rmap in
The BGP RIB entry is present but the remote label is lost:
> # show bgp ipv4 vpn 192.168.0.0/24
> BGP routing table entry for 444:1:192.168.0.0/24, version 2
> [..]
> 192.168.0.0 from 192.0.2.2
> Origin incomplete, metric 0, valid, external, best (First path received)
> Extended Community: RT:52:100
The reason for the loose is that labels are stored within struct attr ->
struct extra -> struct bgp_labels but not in the struct bgp_adj_in.
Reference the bgp_labels pointer in struct bgp_adj_in and use its values
when doing a soft reconfiguration of the BGP table.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
2023-01-13 15:59:52 +01:00
|
|
|
bgp_labels_unintern(&bai->labels);
|
2024-04-25 16:53:21 +02:00
|
|
|
if (bai->peer)
|
|
|
|
bai->peer->stat_pfx_adj_rib_in--;
|
2023-09-10 14:53:36 +02:00
|
|
|
BGP_ADJ_IN_DEL(*dest, bai);
|
|
|
|
*dest = bgp_dest_unlock_node(*dest);
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
peer_unlock(bai->peer); /* adj_in peer reference */
|
2002-12-13 21:15:29 +01:00
|
|
|
XFREE(MTYPE_BGP_ADJ_IN, bai);
|
|
|
|
}
|
|
|
|
|
2023-09-10 15:27:51 +02:00
|
|
|
bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
|
2020-03-20 10:57:54 +01:00
|
|
|
uint32_t addpath_id)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_adj_in *adj;
|
2015-05-20 03:04:01 +02:00
|
|
|
struct bgp_adj_in *adj_next;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2023-09-10 15:27:51 +02:00
|
|
|
adj = (*dest)->adj_in;
|
2015-04-13 09:50:00 +02:00
|
|
|
|
|
|
|
if (!adj)
|
2020-03-20 10:57:54 +01:00
|
|
|
return false;
|
2015-04-13 09:50:00 +02:00
|
|
|
|
2015-05-20 03:04:01 +02:00
|
|
|
while (adj) {
|
|
|
|
adj_next = adj->next;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2021-06-11 08:17:05 +02:00
|
|
|
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
|
2023-09-10 15:27:51 +02:00
|
|
|
bgp_adj_in_remove(dest, adj);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2015-05-20 03:04:01 +02:00
|
|
|
adj = adj_next;
|
2023-09-10 14:53:36 +02:00
|
|
|
|
2023-09-10 15:27:51 +02:00
|
|
|
assert(*dest);
|
2015-05-20 03:04:01 +02:00
|
|
|
}
|
2015-04-13 09:50:00 +02:00
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|