]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_updgrp.h
Merge remote-tracking branch 'origin/stable/2.0'
[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 #define BGP_DEFAULT_SUBGROUP_COALESCE_TIME 200
33
34 #define PEER_UPDGRP_FLAGS (PEER_FLAG_LOCAL_AS_NO_PREPEND | \
35 PEER_FLAG_LOCAL_AS_REPLACE_AS)
36
37 #define PEER_UPDGRP_AF_FLAGS (PEER_FLAG_SEND_COMMUNITY | \
38 PEER_FLAG_SEND_EXT_COMMUNITY | \
39 PEER_FLAG_DEFAULT_ORIGINATE | \
40 PEER_FLAG_REFLECTOR_CLIENT | \
41 PEER_FLAG_RSERVER_CLIENT | \
42 PEER_FLAG_NEXTHOP_SELF | \
43 PEER_FLAG_NEXTHOP_UNCHANGED | \
44 PEER_FLAG_FORCE_NEXTHOP_SELF | \
45 PEER_FLAG_AS_PATH_UNCHANGED | \
46 PEER_FLAG_MED_UNCHANGED | \
47 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | \
48 PEER_FLAG_REMOVE_PRIVATE_AS | \
49 PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \
50 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
51 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \
52 PEER_FLAG_ADDPATH_TX_ALL_PATHS | \
53 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | \
54 PEER_FLAG_AS_OVERRIDE)
55
56 #define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
57
58 #define PEER_UPDGRP_AF_CAP_FLAGS (PEER_CAP_ORF_PREFIX_SM_RCV | \
59 PEER_CAP_ORF_PREFIX_SM_OLD_RCV |\
60 PEER_CAP_ADDPATH_AF_TX_ADV |\
61 PEER_CAP_ADDPATH_AF_RX_RCV |\
62 PEER_CAP_ENHE_AF_NEGO)
63
64 typedef enum
65 {
66 BGP_ATTR_VEC_NH = 0,
67 BGP_ATTR_VEC_MAX
68 } bpacket_attr_vec_type;
69
70 typedef struct
71 {
72 u_int32_t flags;
73 unsigned long offset;
74 } bpacket_attr_vec;
75
76 #define BPKT_ATTRVEC_FLAGS_UPDATED (1 << 0)
77 #define BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS (1 << 1)
78 #define BPKT_ATTRVEC_FLAGS_REFLECTED (1 << 2)
79 #define BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED (1 << 3)
80 #define BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED (1 << 4)
81 #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5)
82 #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6)
83
84 typedef struct bpacket_attr_vec_arr
85 {
86 bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
87 } bpacket_attr_vec_arr;
88
89 struct bpacket
90 {
91 /* for being part of an update subgroup's message list */
92 TAILQ_ENTRY (bpacket) pkt_train;
93
94 /* list of peers (well, peer_afs) that the packet needs to be sent to */
95 LIST_HEAD (pkt_peer_list, peer_af) peers;
96
97 struct stream *buffer;
98 bpacket_attr_vec_arr arr;
99
100 unsigned int ver;
101 };
102
103 struct bpacket_queue
104 {
105 TAILQ_HEAD (pkt_queue, bpacket) pkts;
106
107 #if 0
108 /* A dummy packet that is used to thread all peers that have
109 completed their work */
110 struct bpacket sentinel;
111 #endif
112
113 unsigned int conf_max_count;
114 unsigned int curr_count;
115 unsigned int hwm_count;
116 unsigned int max_count_reached_count;
117 };
118
119 struct update_group
120 {
121 /* back pointer to the BGP instance */
122 struct bgp *bgp;
123
124 /* list of subgroups that belong to the update group */
125 LIST_HEAD (subgrp_list, update_subgroup) subgrps;
126
127 /* lazy way to store configuration common to all peers
128 hash function will compute from this data */
129 struct peer *conf;
130
131 afi_t afi;
132 safi_t safi;
133 int afid;
134
135 uint64_t id;
136 time_t uptime;
137
138 u_int32_t join_events;
139 u_int32_t prune_events;
140 u_int32_t merge_events;
141 u_int32_t updgrp_switch_events;
142 u_int32_t peer_refreshes_combined;
143 u_int32_t adj_count;
144 u_int32_t split_events;
145 u_int32_t merge_checks_triggered;
146
147 u_int32_t subgrps_created;
148 u_int32_t subgrps_deleted;
149
150 u_int32_t num_dbg_en_peers;
151 };
152
153 /*
154 * Shorthand for a global statistics counter.
155 */
156 #define UPDGRP_GLOBAL_STAT(updgrp, stat) \
157 ((updgrp)->bgp->update_group_stats.stat)
158
159 /*
160 * Add the given value to a counter on an update group and the bgp
161 * instance.
162 */
163 #define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
164 do { \
165 (updgrp)->stat += (value); \
166 UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
167 } while (0)
168
169 /*
170 * Increment a counter on a update group and its parent structures.
171 */
172 #define UPDGRP_INCR_STAT(subgrp, stat) \
173 UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
174
175 struct update_subgroup
176 {
177 /* back pointer to the parent update group */
178 struct update_group *update_group;
179
180 /* list of peers that belong to the subgroup */
181 LIST_HEAD (peer_list, peer_af) peers;
182 int peer_count;
183
184 /* for being part of an update group's subgroup list */
185 LIST_ENTRY (update_subgroup) updgrp_train;
186
187 struct bpacket_queue pkt_queue;
188
189 /*
190 * List of adj-out structures for this subgroup.
191 * It essentially represents the snapshot of every prefix that
192 * has been advertised to the members of the subgroup
193 */
194 TAILQ_HEAD (adjout_queue, bgp_adj_out) adjq;
195
196 /* packet buffer for update generation */
197 struct stream *work;
198
199 /* We use a separate stream to encode MP_REACH_NLRI for efficient
200 * NLRI packing. peer->work stores all the other attributes. The
201 * actual packet is then constructed by concatenating the two.
202 */
203 struct stream *scratch;
204
205 /* synchronization list and time */
206 struct bgp_synchronize *sync;
207
208 /* send prefix count */
209 unsigned long scount;
210
211 /* announcement attribute hash */
212 struct hash *hash;
213
214 struct thread *t_coalesce;
215 u_int32_t v_coalesce;
216
217 struct thread *t_merge_check;
218
219 /* table version that the subgroup has caught up to. */
220 uint64_t version;
221
222 /* version maintained to record adj changes */
223 uint64_t adj_version;
224
225 time_t uptime;
226
227 /*
228 * Identifying information about the subgroup that this subgroup was split
229 * from, if any.
230 */
231 struct
232 {
233 uint64_t update_group_id;
234 uint64_t subgroup_id;
235 } split_from;
236
237 u_int32_t join_events;
238 u_int32_t prune_events;
239
240 /*
241 * This is bumped up when another subgroup merges into this one.
242 */
243 u_int32_t merge_events;
244 u_int32_t updgrp_switch_events;
245 u_int32_t peer_refreshes_combined;
246 u_int32_t adj_count;
247 u_int32_t split_events;
248 u_int32_t merge_checks_triggered;
249
250 uint64_t id;
251
252 u_int16_t sflags;
253
254 /* Subgroup flags, see below */
255 u_int16_t flags;
256 };
257
258 /*
259 * We need to do an outbound refresh to get this subgroup into a
260 * consistent state.
261 */
262 #define SUBGRP_FLAG_NEEDS_REFRESH (1 << 0)
263
264 #define SUBGRP_STATUS_DEFAULT_ORIGINATE (1 << 0)
265
266 /*
267 * Add the given value to the specified counter on a subgroup and its
268 * parent structures.
269 */
270 #define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
271 do { \
272 (subgrp)->stat += (value); \
273 if ((subgrp)->update_group) \
274 UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, value); \
275 } while (0)
276
277 /*
278 * Increment a counter on a subgroup and its parent structures.
279 */
280 #define SUBGRP_INCR_STAT(subgrp, stat) \
281 SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
282
283 /*
284 * Decrement a counter on a subgroup and its parent structures.
285 */
286 #define SUBGRP_DECR_STAT(subgrp, stat) \
287 SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
288
289
290 typedef int (*updgrp_walkcb) (struct update_group * updgrp, void *ctx);
291
292 /* really a private structure */
293 struct updwalk_context
294 {
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) \
325 ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
326 #define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers)
327 #define UPDGRP_PEER_DBG_EN(u) (((u)->num_dbg_en_peers)++)
328 #define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--)
329 #define UPDGRP_PEER_DBG_OFF(u) (u)->num_dbg_en_peers = 0
330
331 #define SUBGRP_AFI(s) UPDGRP_AFI((s)->update_group)
332 #define SUBGRP_SAFI(s) UPDGRP_SAFI((s)->update_group)
333 #define SUBGRP_PEER(s) UPDGRP_PEER((s)->update_group)
334 #define SUBGRP_PCOUNT(s) ((s)->peer_count)
335 #define SUBGRP_PFIRST(s) LIST_FIRST(&((s)->peers))
336 #define SUBGRP_PKTQ(s) &((s)->pkt_queue)
337 #define SUBGRP_INST(s) UPDGRP_INST((s)->update_group)
338 #define SUBGRP_AFFLAGS(s) UPDGRP_AFFLAGS((s)->update_group)
339 #define SUBGRP_UPDGRP(s) ((s)->update_group)
340
341 /*
342 * Walk all subgroups in an update group.
343 */
344 #define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
345 LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
346
347 #define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
348 LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, 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
368 update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, 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
374 update_subgroup_remove_peer (struct update_subgroup *, struct peer_af *);
375 extern struct bgp_table *update_subgroup_rib (struct update_subgroup *);
376 extern void
377 update_subgroup_split_peer (struct peer_af *, struct update_group *);
378 extern int
379 update_subgroup_check_merge (struct update_subgroup *, const char *);
380 extern int
381 update_subgroup_trigger_merge_check (struct update_subgroup *,
382 int force);
383 extern void update_group_policy_update (struct bgp *bgp,
384 bgp_policy_type_e ptype, const char *pname,
385 int route_update, int start_event);
386 extern void update_group_af_walk (struct bgp *bgp, afi_t afi, safi_t safi,
387 updgrp_walkcb cb, void *ctx);
388 extern void update_group_walk (struct bgp *bgp, updgrp_walkcb cb, void *ctx);
389 extern void update_group_periodic_merge (struct bgp *bgp);
390 extern int update_group_refresh_default_originate_route_map (struct thread *thread);
391 extern void update_group_start_advtimer (struct bgp *bgp);
392
393 extern void update_subgroup_inherit_info (struct update_subgroup *to,
394 struct update_subgroup *from);
395
396 /* bgp_updgrp_packet.c */
397 extern struct bpacket *bpacket_alloc (void);
398 extern void bpacket_free (struct bpacket *pkt);
399 extern void bpacket_queue_init (struct bpacket_queue *q);
400 extern void bpacket_queue_cleanup (struct bpacket_queue *q);
401 extern void bpacket_queue_sanity_check (struct bpacket_queue *q);
402 extern struct bpacket *bpacket_queue_add (struct bpacket_queue *q,
403 struct stream *s,
404 struct bpacket_attr_vec_arr
405 *vecarr);
406 struct bpacket *bpacket_queue_remove (struct bpacket_queue *q);
407 extern struct bpacket *bpacket_queue_first (struct bpacket_queue *q);
408 struct bpacket *bpacket_queue_last (struct bpacket_queue *q);
409 unsigned int bpacket_queue_length (struct bpacket_queue *q);
410 unsigned int bpacket_queue_hwm_length (struct bpacket_queue *q);
411 int bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q);
412 extern void bpacket_queue_advance_peer (struct peer_af *paf);
413 extern void bpacket_queue_remove_peer (struct peer_af *paf);
414 extern void bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf);
415 unsigned int bpacket_queue_virtual_length (struct peer_af *paf);
416 extern void bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty);
417 int subgroup_packets_to_build (struct update_subgroup *subgrp);
418 extern struct bpacket *subgroup_update_packet (struct update_subgroup *s);
419 extern struct bpacket *subgroup_withdraw_packet (struct update_subgroup *s);
420 extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt,
421 struct peer_af *paf);
422 extern void bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr);
423 extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr,
424 bpacket_attr_vec_type type,
425 struct stream *s,
426 struct attr *attr);
427 extern void
428 subgroup_default_update_packet (struct update_subgroup *subgrp,
429 struct attr *attr, struct peer *from);
430 extern void subgroup_default_withdraw_packet (struct update_subgroup *subgrp);
431
432 /* bgp_updgrp_adv.c */
433 extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct
434 update_subgroup
435 *subgrp,
436 struct bgp_adj_out
437 *adj);
438 extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi,
439 safi_t safi, struct vty *vty,
440 uint64_t id);
441 extern void update_group_show_advertised (struct bgp *bgp, afi_t afi,
442 safi_t safi, struct vty *vty,
443 uint64_t id);
444 extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi,
445 safi_t safi, struct vty *vty,
446 uint64_t id);
447 extern void subgroup_announce_route (struct update_subgroup *subgrp);
448 extern void subgroup_announce_all (struct update_subgroup *subgrp);
449
450 extern void
451 subgroup_default_originate (struct update_subgroup *subgrp, int withdraw);
452 extern void
453 group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi,
454 struct bgp_node *rn, struct bgp_info *ri);
455 extern void subgroup_clear_table (struct update_subgroup *subgrp);
456 extern void update_group_announce (struct bgp *bgp);
457 extern void update_group_announce_rrclients (struct bgp *bgp);
458 extern void peer_af_announce_route (struct peer_af *paf, int combine);
459 extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp,
460 struct bgp_node *rn,
461 u_int32_t addpath_tx_id);
462 extern void bgp_adj_out_remove_subgroup (struct bgp_node *rn,
463 struct bgp_adj_out *adj,
464 struct update_subgroup *subgrp);
465 extern void
466 bgp_adj_out_set_subgroup (struct bgp_node *rn,
467 struct update_subgroup *subgrp,
468 struct attr *attr, struct bgp_info *binfo);
469 extern void
470 bgp_adj_out_unset_subgroup (struct bgp_node *rn,
471 struct update_subgroup *subgrp,
472 char withdraw,
473 u_int32_t addpath_tx_id);
474 void
475 subgroup_announce_table (struct update_subgroup *subgrp,
476 struct bgp_table *table);
477 extern void
478 subgroup_trigger_write (struct update_subgroup *subgrp);
479
480 extern int
481 update_group_clear_update_dbg (struct update_group *updgrp, void *arg);
482
483 extern void update_bgp_group_free(struct bgp *bgp);
484 extern int bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi);
485 extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi,
486 struct bgp_info *ri);
487
488 /*
489 * Inline functions
490 */
491
492 /*
493 * bpacket_queue_is_empty
494 */
495 static inline int
496 bpacket_queue_is_empty (struct bpacket_queue *queue)
497 {
498
499 /*
500 * The packet queue is empty if it only contains a sentinel.
501 */
502 if (queue->curr_count != 1)
503 return 0;
504
505 assert (bpacket_queue_first (queue)->buffer == NULL);
506 return 1;
507 }
508
509 /*
510 * bpacket_next
511 *
512 * Returns the packet after the given packet in a bpacket queue.
513 */
514 static inline struct bpacket *
515 bpacket_next (struct bpacket *pkt)
516 {
517 return TAILQ_NEXT (pkt, pkt_train);
518 }
519
520 /*
521 * update_group_adjust_peer_afs
522 *
523 * Adjust all peer_af structures for the given peer.
524 */
525 static inline void
526 update_group_adjust_peer_afs (struct peer *peer)
527 {
528 struct peer_af *paf;
529 int afidx;
530
531 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
532 {
533 paf = peer->peer_af_array[afidx];
534 if (paf != NULL)
535 update_group_adjust_peer (paf);
536 }
537 }
538
539 /*
540 * update_group_remove_peer_afs
541 *
542 * Remove all peer_af structures for the given peer from their subgroups.
543 */
544 static inline void
545 update_group_remove_peer_afs (struct peer *peer)
546 {
547 struct peer_af *paf;
548 int afidx;
549
550 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
551 {
552 paf = peer->peer_af_array[afidx];
553 if (paf != NULL)
554 update_subgroup_remove_peer (PAF_SUBGRP (paf), paf);
555 }
556 }
557
558 /*
559 * update_subgroup_needs_refresh
560 */
561 static inline int
562 update_subgroup_needs_refresh (const struct update_subgroup *subgrp)
563 {
564 if (CHECK_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
565 return 1;
566 else
567 return 0;
568 }
569
570 /*
571 * update_subgroup_set_needs_refresh
572 */
573 static inline void
574 update_subgroup_set_needs_refresh (struct update_subgroup *subgrp, int value)
575 {
576 if (value)
577 SET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
578 else
579 UNSET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
580 }
581
582 static inline struct update_subgroup *
583 peer_subgroup (struct peer *peer, afi_t afi, safi_t safi)
584 {
585 struct peer_af *paf;
586
587 paf = peer_af_find (peer, afi, safi);
588 if (paf)
589 return PAF_SUBGRP (paf);
590 return NULL;
591 }
592
593 /*
594 * update_group_adjust_peer_afs
595 *
596 * Adjust all peer_af structures for the given peer.
597 */
598 static inline void
599 bgp_announce_peer (struct peer *peer)
600 {
601 struct peer_af *paf;
602 int afidx;
603
604 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
605 {
606 paf = peer->peer_af_array[afidx];
607 if (paf != NULL)
608 subgroup_announce_all (PAF_SUBGRP (paf));
609 }
610 }
611
612 /**
613 * advertise_list_is_empty
614 */
615 static inline int
616 advertise_list_is_empty (struct update_subgroup *subgrp)
617 {
618 if (!BGP_ADV_FIFO_EMPTY (&subgrp->sync->update) ||
619 !BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) ||
620 !BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low))
621 {
622 return 0;
623 }
624
625 return 1;
626 }
627
628 #endif /* _QUAGGA_BGP_UPDGRP_H */