]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_updgrp.h
Merge pull request #12920 from sri-mohan1/sri-mohan-ldp
[mirror_frr.git] / bgpd / bgp_updgrp.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
3f9c7369
DS
2/**
3 * bgp_updgrp.c: BGP update group structures
4 *
5 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
6 *
7 * @author Avneesh Sachdev <avneesh@sproute.net>
8 * @author Rajesh Varadarajan <rajesh@sproute.net>
9 * @author Pradosh Mohapatra <pradosh@sproute.net>
3f9c7369
DS
10 */
11
12#ifndef _QUAGGA_BGP_UPDGRP_H
13#define _QUAGGA_BGP_UPDGRP_H
14
15#include "bgp_advertise.h"
16
4961a5a2
QY
17/*
18 * The following three heuristic constants determine how long advertisement to
19 * a subgroup will be delayed after it is created. The intent is to allow
20 * transient changes in peer state (primarily session establishment) to settle,
21 * so that more peers can be grouped together and benefit from sharing
22 * advertisement computations with the subgroup.
23 *
24 * These values have a very large impact on initial convergence time; any
25 * changes should be accompanied by careful performance testing at all scales.
26 *
27 * The coalesce time 'C' for a new subgroup within a particular BGP instance
28 * 'B' with total number of known peers 'P', established or not, is computed as
29 * follows:
30 *
31 * C = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME,
32 * BGP_DEFAULT_SUBGROUP_COALESCE_TIME +
33 * (P*BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME))
34 */
35#define BGP_DEFAULT_SUBGROUP_COALESCE_TIME 1000
36#define BGP_MAX_SUBGROUP_COALESCE_TIME 10000
37#define BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME 50
3f9c7369 38
d62a17ae 39#define PEER_UPDGRP_FLAGS \
40 (PEER_FLAG_LOCAL_AS_NO_PREPEND | PEER_FLAG_LOCAL_AS_REPLACE_AS)
41
42#define PEER_UPDGRP_AF_FLAGS \
43 (PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY \
a78ba1c3 44 | PEER_FLAG_SEND_LARGE_COMMUNITY \
d62a17ae 45 | PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT \
46 | PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF \
47 | PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF \
48 | PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED \
49 | PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS \
50 | PEER_FLAG_REMOVE_PRIVATE_AS_ALL \
51 | PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \
52 | PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \
dcc68b5e 53 | PEER_FLAG_AS_OVERRIDE)
3f9c7369
DS
54
55#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
56
d62a17ae 57#define PEER_UPDGRP_AF_CAP_FLAGS \
58 (PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ORF_PREFIX_SM_OLD_RCV \
59 | PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \
60 | PEER_CAP_ENHE_AF_NEGO)
3f9c7369 61
682abee1 62enum bpacket_attr_vec_type { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX };
3f9c7369 63
d62a17ae 64typedef struct {
d7c0a89a 65 uint32_t flags;
d62a17ae 66 unsigned long offset;
3f9c7369
DS
67} bpacket_attr_vec;
68
3811f1e2
DS
69#define BPKT_ATTRVEC_FLAGS_UPDATED (1 << 0)
70#define BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS (1 << 1)
71#define BPKT_ATTRVEC_FLAGS_REFLECTED (1 << 2)
72#define BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED (1 << 3)
73#define BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED (1 << 4)
74#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5)
75#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6)
6eeb9255
DA
76#define BPKT_ATTRVEC_FLAGS_RMAP_VPNV4_NH_CHANGED (1 << 7)
77#define BPKT_ATTRVEC_FLAGS_RMAP_VPNV6_GNH_CHANGED (1 << 8)
3f9c7369 78
d62a17ae 79typedef struct bpacket_attr_vec_arr {
80 bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
3f9c7369
DS
81} bpacket_attr_vec_arr;
82
d62a17ae 83struct bpacket {
84 /* for being part of an update subgroup's message list */
85 TAILQ_ENTRY(bpacket) pkt_train;
3f9c7369 86
d62a17ae 87 /* list of peers (well, peer_afs) that the packet needs to be sent to */
88 LIST_HEAD(pkt_peer_list, peer_af) peers;
3f9c7369 89
d62a17ae 90 struct stream *buffer;
91 bpacket_attr_vec_arr arr;
3f9c7369 92
d62a17ae 93 unsigned int ver;
3f9c7369
DS
94};
95
d62a17ae 96struct bpacket_queue {
97 TAILQ_HEAD(pkt_queue, bpacket) pkts;
3f9c7369 98
d62a17ae 99 unsigned int conf_max_count;
100 unsigned int curr_count;
101 unsigned int hwm_count;
102 unsigned int max_count_reached_count;
3f9c7369
DS
103};
104
d62a17ae 105struct update_group {
106 /* back pointer to the BGP instance */
107 struct bgp *bgp;
3f9c7369 108
d62a17ae 109 /* list of subgroups that belong to the update group */
110 LIST_HEAD(subgrp_list, update_subgroup) subgrps;
3f9c7369 111
d62a17ae 112 /* lazy way to store configuration common to all peers
113 hash function will compute from this data */
114 struct peer *conf;
3f9c7369 115
d62a17ae 116 afi_t afi;
117 safi_t safi;
118 int afid;
3f9c7369 119
d62a17ae 120 uint64_t id;
121 time_t uptime;
3f9c7369 122
d7c0a89a
QY
123 uint32_t join_events;
124 uint32_t prune_events;
125 uint32_t merge_events;
126 uint32_t updgrp_switch_events;
127 uint32_t peer_refreshes_combined;
128 uint32_t adj_count;
129 uint32_t split_events;
130 uint32_t merge_checks_triggered;
3f9c7369 131
d7c0a89a
QY
132 uint32_t subgrps_created;
133 uint32_t subgrps_deleted;
3f9c7369 134
d7c0a89a 135 uint32_t num_dbg_en_peers;
3f9c7369
DS
136};
137
138/*
139 * Shorthand for a global statistics counter.
140 */
d62a17ae 141#define UPDGRP_GLOBAL_STAT(updgrp, stat) \
142 ((updgrp)->bgp->update_group_stats.stat)
3f9c7369
DS
143
144/*
145 * Add the given value to a counter on an update group and the bgp
146 * instance.
147 */
d62a17ae 148#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
149 do { \
150 (updgrp)->stat += (value); \
151 UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
152 } while (0)
3f9c7369
DS
153
154/*
155 * Increment a counter on a update group and its parent structures.
156 */
d62a17ae 157#define UPDGRP_INCR_STAT(subgrp, stat) UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
3f9c7369 158
d62a17ae 159struct update_subgroup {
160 /* back pointer to the parent update group */
161 struct update_group *update_group;
3f9c7369 162
d62a17ae 163 /* list of peers that belong to the subgroup */
164 LIST_HEAD(peer_list, peer_af) peers;
165 int peer_count;
3f9c7369 166
d62a17ae 167 /* for being part of an update group's subgroup list */
168 LIST_ENTRY(update_subgroup) updgrp_train;
3f9c7369 169
d62a17ae 170 struct bpacket_queue pkt_queue;
3f9c7369 171
d62a17ae 172 /*
173 * List of adj-out structures for this subgroup.
174 * It essentially represents the snapshot of every prefix that
175 * has been advertised to the members of the subgroup
176 */
177 TAILQ_HEAD(adjout_queue, bgp_adj_out) adjq;
3f9c7369 178
d62a17ae 179 /* packet buffer for update generation */
180 struct stream *work;
3f9c7369 181
d62a17ae 182 /* We use a separate stream to encode MP_REACH_NLRI for efficient
424ab01d 183 * NLRI packing. peer->obuf_work stores all the other attributes. The
d62a17ae 184 * actual packet is then constructed by concatenating the two.
185 */
186 struct stream *scratch;
3f9c7369 187
d62a17ae 188 /* synchronization list and time */
189 struct bgp_synchronize *sync;
3f9c7369 190
d62a17ae 191 /* send prefix count */
fde246e8 192 uint32_t scount;
3f9c7369 193
d0bf49ec
LS
194 /* send prefix count prior to packet update */
195 uint32_t pscount;
196
d62a17ae 197 /* announcement attribute hash */
198 struct hash *hash;
3f9c7369 199
d62a17ae 200 struct thread *t_coalesce;
d7c0a89a 201 uint32_t v_coalesce;
3f9c7369 202
d62a17ae 203 struct thread *t_merge_check;
3f9c7369 204
d62a17ae 205 /* table version that the subgroup has caught up to. */
206 uint64_t version;
3f9c7369 207
d62a17ae 208 /* version maintained to record adj changes */
209 uint64_t adj_version;
3f9c7369 210
d62a17ae 211 time_t uptime;
3f9c7369 212
d62a17ae 213 /*
214 * Identifying information about the subgroup that this subgroup was
215 * split
216 * from, if any.
217 */
218 struct {
219 uint64_t update_group_id;
220 uint64_t subgroup_id;
221 } split_from;
3f9c7369 222
d7c0a89a
QY
223 uint32_t join_events;
224 uint32_t prune_events;
3f9c7369 225
d62a17ae 226 /*
227 * This is bumped up when another subgroup merges into this one.
228 */
d7c0a89a
QY
229 uint32_t merge_events;
230 uint32_t updgrp_switch_events;
231 uint32_t peer_refreshes_combined;
232 uint32_t adj_count;
233 uint32_t split_events;
234 uint32_t merge_checks_triggered;
3f9c7369 235
d62a17ae 236 uint64_t id;
3f9c7369 237
d7c0a89a 238 uint16_t sflags;
2adac256
DA
239#define SUBGRP_STATUS_DEFAULT_ORIGINATE (1 << 0)
240#define SUBGRP_STATUS_FORCE_UPDATES (1 << 1)
d0bf49ec 241#define SUBGRP_STATUS_TABLE_REPARSING (1 << 2)
46c4f05b
IS
242/*
243 * This flag has been added to ensure that the SNT counters
244 * gets incremented and decremented only during the creation
245 * and deletion workflows of default originate,
246 * not during the update workflow.
247 */
248#define SUBGRP_STATUS_PEER_DEFAULT_ORIGINATED (1 << 3)
3f9c7369 249
d7c0a89a 250 uint16_t flags;
2adac256 251#define SUBGRP_FLAG_NEEDS_REFRESH (1 << 0)
3f9c7369
DS
252};
253
3f9c7369
DS
254/*
255 * Add the given value to the specified counter on a subgroup and its
256 * parent structures.
257 */
d62a17ae 258#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
259 do { \
260 (subgrp)->stat += (value); \
261 if ((subgrp)->update_group) \
262 UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, \
263 value); \
264 } while (0)
3f9c7369
DS
265
266/*
267 * Increment a counter on a subgroup and its parent structures.
268 */
d62a17ae 269#define SUBGRP_INCR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
3f9c7369
DS
270
271/*
272 * Decrement a counter on a subgroup and its parent structures.
273 */
d62a17ae 274#define SUBGRP_DECR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
3f9c7369 275
d62a17ae 276typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx);
3f9c7369
DS
277
278/* really a private structure */
d62a17ae 279struct updwalk_context {
280 struct vty *vty;
9bcb3eef 281 struct bgp_dest *dest;
40381db7 282 struct bgp_path_info *pi;
d62a17ae 283 uint64_t updgrp_id;
284 uint64_t subgrp_id;
d54f55f2 285 enum bgp_policy_type policy_type;
d62a17ae 286 const char *policy_name;
287 int policy_event_start_flag;
f1aa4929 288 bool policy_route_update;
d62a17ae 289 updgrp_walkcb cb;
290 void *context;
d7c0a89a 291 uint8_t flags;
fa5a9276
AR
292 bool uj;
293 json_object *json_updategrps;
3f9c7369
DS
294
295#define UPDWALK_FLAGS_ADVQUEUE (1 << 0)
296#define UPDWALK_FLAGS_ADVERTISED (1 << 1)
297};
298
299#define UPDWALK_CONTINUE HASHWALK_CONTINUE
300#define UPDWALK_ABORT HASHWALK_ABORT
301
302#define PAF_PEER(p) ((p)->peer)
303#define PAF_SUBGRP(p) ((p)->subgroup)
304#define PAF_UPDGRP(p) ((p)->subgroup->update_group)
305#define PAF_PKTQ(f) SUBGRP_PKTQ((f)->subgroup)
306
307#define UPDGRP_PEER(u) ((u)->conf)
308#define UPDGRP_AFI(u) ((u)->afi)
309#define UPDGRP_SAFI(u) ((u)->safi)
310#define UPDGRP_INST(u) ((u)->bgp)
d62a17ae 311#define UPDGRP_AFFLAGS(u) ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
3f9c7369
DS
312#define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers)
313#define UPDGRP_PEER_DBG_EN(u) (((u)->num_dbg_en_peers)++)
314#define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--)
315#define UPDGRP_PEER_DBG_OFF(u) (u)->num_dbg_en_peers = 0
316
317#define SUBGRP_AFI(s) UPDGRP_AFI((s)->update_group)
318#define SUBGRP_SAFI(s) UPDGRP_SAFI((s)->update_group)
319#define SUBGRP_PEER(s) UPDGRP_PEER((s)->update_group)
320#define SUBGRP_PCOUNT(s) ((s)->peer_count)
321#define SUBGRP_PFIRST(s) LIST_FIRST(&((s)->peers))
322#define SUBGRP_PKTQ(s) &((s)->pkt_queue)
323#define SUBGRP_INST(s) UPDGRP_INST((s)->update_group)
324#define SUBGRP_AFFLAGS(s) UPDGRP_AFFLAGS((s)->update_group)
325#define SUBGRP_UPDGRP(s) ((s)->update_group)
326
327/*
328 * Walk all subgroups in an update group.
329 */
d62a17ae 330#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
996c9314 331 LIST_FOREACH (subgrp, &((updgrp)->subgrps), updgrp_train)
3f9c7369 332
d62a17ae 333#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
996c9314
LB
334 LIST_FOREACH_SAFE (subgrp, &((updgrp)->subgrps), updgrp_train, \
335 tmp_subgrp)
3f9c7369 336
d62a17ae 337#define SUBGRP_FOREACH_PEER(subgrp, paf) \
996c9314 338 LIST_FOREACH (paf, &(subgrp->peers), subgrp_train)
3f9c7369 339
d62a17ae 340#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
996c9314 341 LIST_FOREACH_SAFE (paf, &(subgrp->peers), subgrp_train, temp_paf)
3f9c7369 342
d62a17ae 343#define SUBGRP_FOREACH_ADJ(subgrp, adj) \
996c9314 344 TAILQ_FOREACH (adj, &(subgrp->adjq), subgrp_adj_train)
3f9c7369 345
d62a17ae 346#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
996c9314 347 TAILQ_FOREACH_SAFE (adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
3f9c7369
DS
348
349/* Prototypes. */
350/* bgp_updgrp.c */
d62a17ae 351extern void update_bgp_group_init(struct bgp *);
352extern void udpate_bgp_group_free(struct bgp *);
353
354extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
fa5a9276 355 struct vty *vty, uint64_t subgrp_id, bool uj);
d62a17ae 356extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
357extern void update_group_adjust_peer(struct peer_af *paf);
358extern int update_group_adjust_soloness(struct peer *peer, int set);
359
360extern void update_subgroup_remove_peer(struct update_subgroup *,
361 struct peer_af *);
362extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
363extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
3dc339cd
DA
364extern bool update_subgroup_check_merge(struct update_subgroup *, const char *);
365extern bool update_subgroup_trigger_merge_check(struct update_subgroup *,
366 int force);
d54f55f2
DA
367extern void update_group_policy_update(struct bgp *bgp,
368 enum bgp_policy_type ptype,
f1aa4929 369 const char *pname, bool route_update,
d62a17ae 370 int start_event);
371extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
372 updgrp_walkcb cb, void *ctx);
373extern void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx);
374extern void update_group_periodic_merge(struct bgp *bgp);
cc9f21da 375extern void
d62a17ae 376update_group_refresh_default_originate_route_map(struct thread *thread);
377extern void update_group_start_advtimer(struct bgp *bgp);
378
379extern void update_subgroup_inherit_info(struct update_subgroup *to,
380 struct update_subgroup *from);
3f9c7369
DS
381
382/* bgp_updgrp_packet.c */
d62a17ae 383extern struct bpacket *bpacket_alloc(void);
384extern void bpacket_free(struct bpacket *pkt);
385extern void bpacket_queue_init(struct bpacket_queue *q);
386extern void bpacket_queue_cleanup(struct bpacket_queue *q);
387extern void bpacket_queue_sanity_check(struct bpacket_queue *q);
388extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q,
389 struct stream *s,
390 struct bpacket_attr_vec_arr *vecarr);
391struct bpacket *bpacket_queue_remove(struct bpacket_queue *q);
392extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
393struct bpacket *bpacket_queue_last(struct bpacket_queue *q);
394unsigned int bpacket_queue_length(struct bpacket_queue *q);
395unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q);
3dc339cd 396bool bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
d62a17ae 397extern void bpacket_queue_advance_peer(struct peer_af *paf);
398extern void bpacket_queue_remove_peer(struct peer_af *paf);
399extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf);
400unsigned int bpacket_queue_virtual_length(struct peer_af *paf);
401extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty);
3dc339cd 402bool subgroup_packets_to_build(struct update_subgroup *subgrp);
d62a17ae 403extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
404extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s);
405extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
406 struct peer_af *paf);
407extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
408extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
e8e36ff3 409 enum bpacket_attr_vec_type type,
d62a17ae 410 struct stream *s, struct attr *attr);
411extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
412 struct attr *attr,
413 struct peer *from);
414extern void subgroup_default_withdraw_packet(struct update_subgroup *subgrp);
3f9c7369
DS
415
416/* bgp_updgrp_adv.c */
d62a17ae 417extern struct bgp_advertise *
418bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
419 struct bgp_adj_out *adj);
420extern void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
421 struct vty *vty, uint64_t id);
422extern void update_group_show_advertised(struct bgp *bgp, afi_t afi,
3f9c7369 423 safi_t safi, struct vty *vty,
f43e655e 424 uint64_t id);
d62a17ae 425extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi,
426 safi_t safi, struct vty *vty,
427 uint64_t id);
428extern void subgroup_announce_route(struct update_subgroup *subgrp);
429extern void subgroup_announce_all(struct update_subgroup *subgrp);
430
431extern void subgroup_default_originate(struct update_subgroup *subgrp,
432 int withdraw);
433extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
9bcb3eef
DS
434 struct bgp_dest *dest,
435 struct bgp_path_info *pi);
d62a17ae 436extern void subgroup_clear_table(struct update_subgroup *subgrp);
437extern void update_group_announce(struct bgp *bgp);
438extern void update_group_announce_rrclients(struct bgp *bgp);
439extern void peer_af_announce_route(struct peer_af *paf, int combine);
440extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
9bcb3eef 441 struct bgp_dest *dest,
d7c0a89a 442 uint32_t addpath_tx_id);
9bcb3eef 443extern void bgp_adj_out_remove_subgroup(struct bgp_dest *dest,
d62a17ae 444 struct bgp_adj_out *adj,
445 struct update_subgroup *subgrp);
9bcb3eef 446extern void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
d62a17ae 447 struct update_subgroup *subgrp,
4b7e6066 448 struct attr *attr,
9b6d8fcf 449 struct bgp_path_info *path);
9bcb3eef 450extern void bgp_adj_out_unset_subgroup(struct bgp_dest *dest,
d62a17ae 451 struct update_subgroup *subgrp,
d7c0a89a 452 char withdraw, uint32_t addpath_tx_id);
d62a17ae 453void subgroup_announce_table(struct update_subgroup *subgrp,
454 struct bgp_table *table);
2fc102e1 455extern void subgroup_trigger_write(struct update_subgroup *subgrp);
d62a17ae 456
457extern int update_group_clear_update_dbg(struct update_group *updgrp,
458 void *arg);
3f9c7369 459
88177fe3 460extern void update_bgp_group_free(struct bgp *bgp);
be92fc9f 461extern bool bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
b1dd7180
DA
462extern bool bgp_check_selected(struct bgp_path_info *bpi, struct peer *peer,
463 bool addpath_capable, afi_t afi, safi_t safi);
8ccee4b8
DA
464extern bool bgp_addpath_capable(struct bgp_path_info *bpi, struct peer *peer,
465 afi_t afi, safi_t safi);
88177fe3 466
3f9c7369
DS
467/*
468 * Inline functions
469 */
470
471/*
472 * bpacket_queue_is_empty
473 */
d62a17ae 474static inline int bpacket_queue_is_empty(struct bpacket_queue *queue)
3f9c7369
DS
475{
476
d62a17ae 477 /*
478 * The packet queue is empty if it only contains a sentinel.
479 */
480 if (queue->curr_count != 1)
481 return 0;
3f9c7369 482
d62a17ae 483 assert(bpacket_queue_first(queue)->buffer == NULL);
484 return 1;
3f9c7369
DS
485}
486
487/*
488 * bpacket_next
489 *
490 * Returns the packet after the given packet in a bpacket queue.
491 */
d62a17ae 492static inline struct bpacket *bpacket_next(struct bpacket *pkt)
3f9c7369 493{
d62a17ae 494 return TAILQ_NEXT(pkt, pkt_train);
3f9c7369
DS
495}
496
497/*
498 * update_group_adjust_peer_afs
499 *
500 * Adjust all peer_af structures for the given peer.
501 */
d62a17ae 502static inline void update_group_adjust_peer_afs(struct peer *peer)
3f9c7369 503{
d62a17ae 504 struct peer_af *paf;
505 int afidx;
506
507 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
508 paf = peer->peer_af_array[afidx];
509 if (paf != NULL)
510 update_group_adjust_peer(paf);
511 }
3f9c7369
DS
512}
513
514/*
515 * update_group_remove_peer_afs
516 *
517 * Remove all peer_af structures for the given peer from their subgroups.
518 */
d62a17ae 519static inline void update_group_remove_peer_afs(struct peer *peer)
3f9c7369 520{
d62a17ae 521 struct peer_af *paf;
522 int afidx;
523
524 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
525 paf = peer->peer_af_array[afidx];
526 if (paf != NULL)
527 update_subgroup_remove_peer(PAF_SUBGRP(paf), paf);
528 }
3f9c7369
DS
529}
530
531/*
532 * update_subgroup_needs_refresh
533 */
534static inline int
d62a17ae 535update_subgroup_needs_refresh(const struct update_subgroup *subgrp)
3f9c7369 536{
d62a17ae 537 if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
538 return 1;
539 else
540 return 0;
3f9c7369
DS
541}
542
543/*
544 * update_subgroup_set_needs_refresh
545 */
546static inline void
d62a17ae 547update_subgroup_set_needs_refresh(struct update_subgroup *subgrp, int value)
3f9c7369 548{
d62a17ae 549 if (value)
550 SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
551 else
552 UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
3f9c7369
DS
553}
554
d62a17ae 555static inline struct update_subgroup *peer_subgroup(struct peer *peer,
556 afi_t afi, safi_t safi)
3f9c7369 557{
d62a17ae 558 struct peer_af *paf;
3f9c7369 559
d62a17ae 560 paf = peer_af_find(peer, afi, safi);
561 if (paf)
562 return PAF_SUBGRP(paf);
563 return NULL;
3f9c7369
DS
564}
565
566/*
567 * update_group_adjust_peer_afs
568 *
569 * Adjust all peer_af structures for the given peer.
570 */
d62a17ae 571static inline void bgp_announce_peer(struct peer *peer)
3f9c7369 572{
d62a17ae 573 struct peer_af *paf;
574 int afidx;
575
576 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
577 paf = peer->peer_af_array[afidx];
578 if (paf != NULL)
579 subgroup_announce_all(PAF_SUBGRP(paf));
580 }
3f9c7369
DS
581}
582
583/**
584 * advertise_list_is_empty
585 */
d62a17ae 586static inline int advertise_list_is_empty(struct update_subgroup *subgrp)
3f9c7369 587{
a274fef8
DL
588 if (bgp_adv_fifo_count(&subgrp->sync->update)
589 || bgp_adv_fifo_count(&subgrp->sync->withdraw)
590 || bgp_adv_fifo_count(&subgrp->sync->withdraw_low)) {
d62a17ae 591 return 0;
592 }
593
594 return 1;
3f9c7369
DS
595}
596
597#endif /* _QUAGGA_BGP_UPDGRP_H */