1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP advertisement and adjacency
3 * Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
16 #include "bgpd/bgpd.h"
17 #include "bgpd/bgp_table.h"
18 #include "bgpd/bgp_route.h"
19 #include "bgpd/bgp_advertise.h"
20 #include "bgpd/bgp_attr.h"
21 #include "bgpd/bgp_debug.h"
22 #include "bgpd/bgp_aspath.h"
23 #include "bgpd/bgp_packet.h"
24 #include "bgpd/bgp_fsm.h"
25 #include "bgpd/bgp_mplsvpn.h"
26 #include "bgpd/bgp_updgrp.h"
28 /* BGP advertise attribute is used for pack same attribute update into
29 one packet. To do that we maintain attribute hash in struct
31 struct bgp_advertise_attr
*bgp_advertise_attr_new(void)
33 return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR
,
34 sizeof(struct bgp_advertise_attr
));
37 void bgp_advertise_attr_free(struct bgp_advertise_attr
*baa
)
39 XFREE(MTYPE_BGP_ADVERTISE_ATTR
, baa
);
42 static void *bgp_advertise_attr_hash_alloc(void *p
)
44 struct bgp_advertise_attr
*ref
= (struct bgp_advertise_attr
*)p
;
45 struct bgp_advertise_attr
*baa
;
47 baa
= bgp_advertise_attr_new();
48 baa
->attr
= ref
->attr
;
52 unsigned int bgp_advertise_attr_hash_key(const void *p
)
54 const struct bgp_advertise_attr
*baa
= p
;
56 return attrhash_key_make(baa
->attr
);
59 bool bgp_advertise_attr_hash_cmp(const void *p1
, const void *p2
)
61 const struct bgp_advertise_attr
*baa1
= p1
;
62 const struct bgp_advertise_attr
*baa2
= p2
;
64 return attrhash_cmp(baa1
->attr
, baa2
->attr
);
67 /* BGP update and withdraw information is stored in BGP advertise
68 structure. This structure is referred from BGP adjacency
70 struct bgp_advertise
*bgp_advertise_new(void)
72 return XCALLOC(MTYPE_BGP_ADVERTISE
, sizeof(struct bgp_advertise
));
75 void bgp_advertise_free(struct bgp_advertise
*adv
)
78 /* bgp_advertise bgp_path_info reference */
79 bgp_path_info_unlock(adv
->pathi
);
80 XFREE(MTYPE_BGP_ADVERTISE
, adv
);
83 void bgp_advertise_add(struct bgp_advertise_attr
*baa
,
84 struct bgp_advertise
*adv
)
92 void bgp_advertise_delete(struct bgp_advertise_attr
*baa
,
93 struct bgp_advertise
*adv
)
96 adv
->next
->prev
= adv
->prev
;
98 adv
->prev
->next
= adv
->next
;
100 baa
->adv
= adv
->next
;
103 struct bgp_advertise_attr
*bgp_advertise_attr_intern(struct hash
*hash
,
106 struct bgp_advertise_attr ref
;
107 struct bgp_advertise_attr
*baa
;
109 ref
.attr
= bgp_attr_intern(attr
);
110 baa
= (struct bgp_advertise_attr
*)hash_get(
111 hash
, &ref
, bgp_advertise_attr_hash_alloc
);
117 void bgp_advertise_attr_unintern(struct hash
*hash
,
118 struct bgp_advertise_attr
*baa
)
123 if (baa
->refcnt
&& baa
->attr
)
124 bgp_attr_unintern(&baa
->attr
);
127 hash_release(hash
, baa
);
128 bgp_attr_unintern(&baa
->attr
);
130 bgp_advertise_attr_free(baa
);
134 bool bgp_adj_out_lookup(struct peer
*peer
, struct bgp_dest
*dest
,
135 uint32_t addpath_tx_id
)
137 struct bgp_adj_out
*adj
;
141 bool addpath_capable
;
143 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
144 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
)
145 if (paf
->peer
== peer
) {
146 afi
= SUBGRP_AFI(adj
->subgroup
);
147 safi
= SUBGRP_SAFI(adj
->subgroup
);
149 bgp_addpath_encode_tx(peer
, afi
, safi
);
151 /* Match on a specific addpath_tx_id if we are
154 * peer and if an addpath_tx_id was specified */
155 if (addpath_capable
&& addpath_tx_id
156 && adj
->addpath_tx_id
!= addpath_tx_id
)
160 ? (adj
->adv
->baa
? true : false)
161 : (adj
->attr
? true : false));
168 void bgp_adj_in_set(struct bgp_dest
*dest
, struct peer
*peer
, struct attr
*attr
,
171 struct bgp_adj_in
*adj
;
173 for (adj
= dest
->adj_in
; adj
; adj
= adj
->next
) {
174 if (adj
->peer
== peer
&& adj
->addpath_rx_id
== addpath_id
) {
175 if (adj
->attr
!= attr
) {
176 bgp_attr_unintern(&adj
->attr
);
177 adj
->attr
= bgp_attr_intern(attr
);
182 adj
= XCALLOC(MTYPE_BGP_ADJ_IN
, sizeof(struct bgp_adj_in
));
183 adj
->peer
= peer_lock(peer
); /* adj_in peer reference */
184 adj
->attr
= bgp_attr_intern(attr
);
185 adj
->uptime
= monotime(NULL
);
186 adj
->addpath_rx_id
= addpath_id
;
187 BGP_ADJ_IN_ADD(dest
, adj
);
188 bgp_dest_lock_node(dest
);
191 void bgp_adj_in_remove(struct bgp_dest
*dest
, struct bgp_adj_in
*bai
)
193 bgp_attr_unintern(&bai
->attr
);
194 BGP_ADJ_IN_DEL(dest
, bai
);
195 bgp_dest_unlock_node(dest
);
196 peer_unlock(bai
->peer
); /* adj_in peer reference */
197 XFREE(MTYPE_BGP_ADJ_IN
, bai
);
200 bool bgp_adj_in_unset(struct bgp_dest
*dest
, struct peer
*peer
,
203 struct bgp_adj_in
*adj
;
204 struct bgp_adj_in
*adj_next
;
212 adj_next
= adj
->next
;
214 if (adj
->peer
== peer
&& adj
->addpath_rx_id
== addpath_id
)
215 bgp_adj_in_remove(dest
, adj
);
223 void bgp_sync_init(struct peer
*peer
)
227 struct bgp_synchronize
*sync
;
229 FOREACH_AFI_SAFI (afi
, safi
) {
230 sync
= XCALLOC(MTYPE_BGP_SYNCHRONISE
,
231 sizeof(struct bgp_synchronize
));
232 bgp_adv_fifo_init(&sync
->update
);
233 bgp_adv_fifo_init(&sync
->withdraw
);
234 bgp_adv_fifo_init(&sync
->withdraw_low
);
235 peer
->sync
[afi
][safi
] = sync
;
239 void bgp_sync_delete(struct peer
*peer
)
244 FOREACH_AFI_SAFI (afi
, safi
) {
245 XFREE(MTYPE_BGP_SYNCHRONISE
, peer
->sync
[afi
][safi
]);