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_SEND_LARGE_COMMUNITY                                      \
60 	 | PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT            \
61 	 | PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF                   \
62 	 | PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF          \
63 	 | PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED               \
64 	 | PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS     \
65 	 | PEER_FLAG_REMOVE_PRIVATE_AS_ALL                                     \
66 	 | PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE                                 \
67 	 | PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE                             \
68 	 | 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 	uint32_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 	uint32_t join_events;
143 	uint32_t prune_events;
144 	uint32_t merge_events;
145 	uint32_t updgrp_switch_events;
146 	uint32_t peer_refreshes_combined;
147 	uint32_t adj_count;
148 	uint32_t split_events;
149 	uint32_t merge_checks_triggered;
150 
151 	uint32_t subgrps_created;
152 	uint32_t subgrps_deleted;
153 
154 	uint32_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 	uint32_t scount;
212 
213 	/* announcement attribute hash */
214 	struct hash *hash;
215 
216 	struct thread *t_coalesce;
217 	uint32_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 	uint32_t join_events;
240 	uint32_t prune_events;
241 
242 	/*
243 	 * This is bumped up when another subgroup merges into this one.
244 	 */
245 	uint32_t merge_events;
246 	uint32_t updgrp_switch_events;
247 	uint32_t peer_refreshes_combined;
248 	uint32_t adj_count;
249 	uint32_t split_events;
250 	uint32_t merge_checks_triggered;
251 
252 	uint64_t id;
253 
254 	uint16_t sflags;
255 
256 	/* Subgroup flags, see below  */
257 	uint16_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 typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx);
291 
292 /* really a private structure */
293 struct updwalk_context {
294 	struct vty *vty;
295 	struct bgp_dest *dest;
296 	struct bgp_path_info *pi;
297 	uint64_t updgrp_id;
298 	uint64_t subgrp_id;
299 	bgp_policy_type_e policy_type;
300 	const char *policy_name;
301 	int policy_event_start_flag;
302 	int policy_route_update;
303 	updgrp_walkcb cb;
304 	void *context;
305 	uint8_t flags;
306 
307 #define UPDWALK_FLAGS_ADVQUEUE   (1 << 0)
308 #define UPDWALK_FLAGS_ADVERTISED (1 << 1)
309 };
310 
311 #define UPDWALK_CONTINUE HASHWALK_CONTINUE
312 #define UPDWALK_ABORT HASHWALK_ABORT
313 
314 #define PAF_PEER(p)        ((p)->peer)
315 #define PAF_SUBGRP(p)      ((p)->subgroup)
316 #define PAF_UPDGRP(p)      ((p)->subgroup->update_group)
317 #define PAF_PKTQ(f)        SUBGRP_PKTQ((f)->subgroup)
318 
319 #define UPDGRP_PEER(u)     ((u)->conf)
320 #define UPDGRP_AFI(u)      ((u)->afi)
321 #define UPDGRP_SAFI(u)     ((u)->safi)
322 #define UPDGRP_INST(u)     ((u)->bgp)
323 #define UPDGRP_AFFLAGS(u) ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
324 #define UPDGRP_DBG_ON(u)   ((u)->num_dbg_en_peers)
325 #define UPDGRP_PEER_DBG_EN(u)  (((u)->num_dbg_en_peers)++)
326 #define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--)
327 #define UPDGRP_PEER_DBG_OFF(u) (u)->num_dbg_en_peers = 0
328 
329 #define SUBGRP_AFI(s)      UPDGRP_AFI((s)->update_group)
330 #define SUBGRP_SAFI(s)     UPDGRP_SAFI((s)->update_group)
331 #define SUBGRP_PEER(s)     UPDGRP_PEER((s)->update_group)
332 #define SUBGRP_PCOUNT(s)   ((s)->peer_count)
333 #define SUBGRP_PFIRST(s)   LIST_FIRST(&((s)->peers))
334 #define SUBGRP_PKTQ(s)     &((s)->pkt_queue)
335 #define SUBGRP_INST(s)     UPDGRP_INST((s)->update_group)
336 #define SUBGRP_AFFLAGS(s)  UPDGRP_AFFLAGS((s)->update_group)
337 #define SUBGRP_UPDGRP(s)   ((s)->update_group)
338 
339 /*
340  * Walk all subgroups in an update group.
341  */
342 #define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp)                                  \
343 	LIST_FOREACH (subgrp, &((updgrp)->subgrps), updgrp_train)
344 
345 #define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp)                 \
346 	LIST_FOREACH_SAFE (subgrp, &((updgrp)->subgrps), updgrp_train,         \
347 			   tmp_subgrp)
348 
349 #define SUBGRP_FOREACH_PEER(subgrp, paf)                                       \
350 	LIST_FOREACH (paf, &(subgrp->peers), subgrp_train)
351 
352 #define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf)                        \
353 	LIST_FOREACH_SAFE (paf, &(subgrp->peers), subgrp_train, temp_paf)
354 
355 #define SUBGRP_FOREACH_ADJ(subgrp, adj)                                        \
356 	TAILQ_FOREACH (adj, &(subgrp->adjq), subgrp_adj_train)
357 
358 #define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp)                         \
359 	TAILQ_FOREACH_SAFE (adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
360 
361 /* Prototypes.  */
362 /* bgp_updgrp.c */
363 extern void update_bgp_group_init(struct bgp *);
364 extern void udpate_bgp_group_free(struct bgp *);
365 
366 extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
367 			      struct vty *vty, uint64_t subgrp_id);
368 extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
369 extern void update_group_adjust_peer(struct peer_af *paf);
370 extern int update_group_adjust_soloness(struct peer *peer, int set);
371 
372 extern void update_subgroup_remove_peer(struct update_subgroup *,
373 					struct peer_af *);
374 extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
375 extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
376 extern bool update_subgroup_check_merge(struct update_subgroup *, const char *);
377 extern bool update_subgroup_trigger_merge_check(struct update_subgroup *,
378 						int force);
379 extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
380 				       const char *pname, int route_update,
381 				       int start_event);
382 extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
383 				 updgrp_walkcb cb, void *ctx);
384 extern void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx);
385 extern void update_group_periodic_merge(struct bgp *bgp);
386 extern int
387 update_group_refresh_default_originate_route_map(struct thread *thread);
388 extern void update_group_start_advtimer(struct bgp *bgp);
389 
390 extern void update_subgroup_inherit_info(struct update_subgroup *to,
391 					 struct update_subgroup *from);
392 
393 /* bgp_updgrp_packet.c */
394 extern struct bpacket *bpacket_alloc(void);
395 extern void bpacket_free(struct bpacket *pkt);
396 extern void bpacket_queue_init(struct bpacket_queue *q);
397 extern void bpacket_queue_cleanup(struct bpacket_queue *q);
398 extern void bpacket_queue_sanity_check(struct bpacket_queue *q);
399 extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q,
400 					 struct stream *s,
401 					 struct bpacket_attr_vec_arr *vecarr);
402 struct bpacket *bpacket_queue_remove(struct bpacket_queue *q);
403 extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
404 struct bpacket *bpacket_queue_last(struct bpacket_queue *q);
405 unsigned int bpacket_queue_length(struct bpacket_queue *q);
406 unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q);
407 bool bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
408 extern void bpacket_queue_advance_peer(struct peer_af *paf);
409 extern void bpacket_queue_remove_peer(struct peer_af *paf);
410 extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf);
411 unsigned int bpacket_queue_virtual_length(struct peer_af *paf);
412 extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty);
413 bool subgroup_packets_to_build(struct update_subgroup *subgrp);
414 extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
415 extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s);
416 extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
417 						struct peer_af *paf);
418 extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
419 extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
420 					 bpacket_attr_vec_type type,
421 					 struct stream *s, struct attr *attr);
422 extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
423 					   struct attr *attr,
424 					   struct peer *from);
425 extern void subgroup_default_withdraw_packet(struct update_subgroup *subgrp);
426 
427 /* bgp_updgrp_adv.c */
428 extern struct bgp_advertise *
429 bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
430 			     struct bgp_adj_out *adj);
431 extern void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
432 					struct vty *vty, uint64_t id);
433 extern void update_group_show_advertised(struct bgp *bgp, afi_t afi,
434 					 safi_t safi, struct vty *vty,
435 					 uint64_t id);
436 extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi,
437 					   safi_t safi, struct vty *vty,
438 					   uint64_t id);
439 extern void subgroup_announce_route(struct update_subgroup *subgrp);
440 extern void subgroup_announce_all(struct update_subgroup *subgrp);
441 
442 extern void subgroup_default_originate(struct update_subgroup *subgrp,
443 				       int withdraw);
444 extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
445 				 struct bgp_dest *dest,
446 				 struct bgp_path_info *pi);
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_dest *dest,
453 					     uint32_t addpath_tx_id);
454 extern void bgp_adj_out_remove_subgroup(struct bgp_dest *dest,
455 					struct bgp_adj_out *adj,
456 					struct update_subgroup *subgrp);
457 extern void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
458 				     struct update_subgroup *subgrp,
459 				     struct attr *attr,
460 				     struct bgp_path_info *path);
461 extern void bgp_adj_out_unset_subgroup(struct bgp_dest *dest,
462 				       struct update_subgroup *subgrp,
463 				       char withdraw, uint32_t addpath_tx_id);
464 void subgroup_announce_table(struct update_subgroup *subgrp,
465 			     struct bgp_table *table);
466 extern void subgroup_trigger_write(struct update_subgroup *subgrp);
467 
468 extern int update_group_clear_update_dbg(struct update_group *updgrp,
469 					 void *arg);
470 
471 extern void update_bgp_group_free(struct bgp *bgp);
472 extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
473 
474 /*
475  * Inline functions
476  */
477 
478 /*
479  * bpacket_queue_is_empty
480  */
bpacket_queue_is_empty(struct bpacket_queue * queue)481 static inline int bpacket_queue_is_empty(struct bpacket_queue *queue)
482 {
483 
484 	/*
485 	 * The packet queue is empty if it only contains a sentinel.
486 	 */
487 	if (queue->curr_count != 1)
488 		return 0;
489 
490 	assert(bpacket_queue_first(queue)->buffer == NULL);
491 	return 1;
492 }
493 
494 /*
495  * bpacket_next
496  *
497  * Returns the packet after the given packet in a bpacket queue.
498  */
bpacket_next(struct bpacket * pkt)499 static inline struct bpacket *bpacket_next(struct bpacket *pkt)
500 {
501 	return TAILQ_NEXT(pkt, pkt_train);
502 }
503 
504 /*
505  * update_group_adjust_peer_afs
506  *
507  * Adjust all peer_af structures for the given peer.
508  */
update_group_adjust_peer_afs(struct peer * peer)509 static inline void update_group_adjust_peer_afs(struct peer *peer)
510 {
511 	struct peer_af *paf;
512 	int afidx;
513 
514 	for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
515 		paf = peer->peer_af_array[afidx];
516 		if (paf != NULL)
517 			update_group_adjust_peer(paf);
518 	}
519 }
520 
521 /*
522  * update_group_remove_peer_afs
523  *
524  * Remove all peer_af structures for the given peer from their subgroups.
525  */
update_group_remove_peer_afs(struct peer * peer)526 static inline void update_group_remove_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 		paf = peer->peer_af_array[afidx];
533 		if (paf != NULL)
534 			update_subgroup_remove_peer(PAF_SUBGRP(paf), paf);
535 	}
536 }
537 
538 /*
539  * update_subgroup_needs_refresh
540  */
541 static inline int
update_subgroup_needs_refresh(const struct update_subgroup * subgrp)542 update_subgroup_needs_refresh(const struct update_subgroup *subgrp)
543 {
544 	if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
545 		return 1;
546 	else
547 		return 0;
548 }
549 
550 /*
551  * update_subgroup_set_needs_refresh
552  */
553 static inline void
update_subgroup_set_needs_refresh(struct update_subgroup * subgrp,int value)554 update_subgroup_set_needs_refresh(struct update_subgroup *subgrp, int value)
555 {
556 	if (value)
557 		SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
558 	else
559 		UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
560 }
561 
peer_subgroup(struct peer * peer,afi_t afi,safi_t safi)562 static inline struct update_subgroup *peer_subgroup(struct peer *peer,
563 						    afi_t afi, safi_t safi)
564 {
565 	struct peer_af *paf;
566 
567 	paf = peer_af_find(peer, afi, safi);
568 	if (paf)
569 		return PAF_SUBGRP(paf);
570 	return NULL;
571 }
572 
573 /*
574  * update_group_adjust_peer_afs
575  *
576  * Adjust all peer_af structures for the given peer.
577  */
bgp_announce_peer(struct peer * peer)578 static inline void bgp_announce_peer(struct peer *peer)
579 {
580 	struct peer_af *paf;
581 	int afidx;
582 
583 	for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
584 		paf = peer->peer_af_array[afidx];
585 		if (paf != NULL)
586 			subgroup_announce_all(PAF_SUBGRP(paf));
587 	}
588 }
589 
590 /**
591  * advertise_list_is_empty
592  */
advertise_list_is_empty(struct update_subgroup * subgrp)593 static inline int advertise_list_is_empty(struct update_subgroup *subgrp)
594 {
595 	if (bgp_adv_fifo_count(&subgrp->sync->update)
596 	    || bgp_adv_fifo_count(&subgrp->sync->withdraw)
597 	    || bgp_adv_fifo_count(&subgrp->sync->withdraw_low)) {
598 		return 0;
599 	}
600 
601 	return 1;
602 }
603 
604 #endif /* _QUAGGA_BGP_UPDGRP_H */
605