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