2 * bgp_updgrp.c: BGP update group structures
4 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
6 * @author Avneesh Sachdev <avneesh@sproute.net>
7 * @author Rajesh Varadarajan <rajesh@sproute.net>
8 * @author Pradosh Mohapatra <pradosh@sproute.net>
10 * This file is part of GNU Zebra.
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
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.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU Zebra; see the file COPYING. If not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 #ifndef _QUAGGA_BGP_UPDGRP_H
29 #define _QUAGGA_BGP_UPDGRP_H
31 #include "bgp_advertise.h"
33 #define BGP_DEFAULT_SUBGROUP_COALESCE_TIME 200
35 #define PEER_UPDGRP_FLAGS (PEER_FLAG_LOCAL_AS_NO_PREPEND | \
36 PEER_FLAG_LOCAL_AS_REPLACE_AS)
38 #define PEER_UPDGRP_AF_FLAGS (PEER_FLAG_SEND_COMMUNITY | \
39 PEER_FLAG_SEND_EXT_COMMUNITY | \
40 PEER_FLAG_DEFAULT_ORIGINATE | \
41 PEER_FLAG_REFLECTOR_CLIENT | \
42 PEER_FLAG_NEXTHOP_SELF | \
43 PEER_FLAG_NEXTHOP_UNCHANGED | \
44 PEER_FLAG_AS_PATH_UNCHANGED | \
45 PEER_FLAG_MED_UNCHANGED | \
46 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | \
47 PEER_FLAG_REMOVE_PRIVATE_AS | \
48 PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \
49 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
50 PEER_FLAG_AS_OVERRIDE)
52 #define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
54 #define PEER_UPDGRP_AF_CAP_FLAGS (PEER_CAP_ORF_PREFIX_SM_RCV | \
55 PEER_CAP_ORF_PREFIX_SM_OLD_RCV |\
56 PEER_CAP_ENHE_AF_NEGO)
62 } bpacket_attr_vec_type
;
70 #define BPACKET_ATTRVEC_FLAGS_UPDATED (1 << 0)
71 #define BPACKET_ATTRVEC_FLAGS_RMAP_CHANGED (1 << 1)
72 #define BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS (1 << 2)
73 #define BPACKET_ATTRVEC_FLAGS_REFLECTED (1 << 3)
74 #define BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED (1 << 4)
76 typedef struct bpacket_attr_vec_arr
78 bpacket_attr_vec entries
[BGP_ATTR_VEC_MAX
];
79 } bpacket_attr_vec_arr
;
83 /* for being part of an update subgroup's message list */
84 TAILQ_ENTRY (bpacket
) pkt_train
;
86 /* list of peers (well, peer_afs) that the packet needs to be sent to */
87 LIST_HEAD (pkt_peer_list
, peer_af
) peers
;
89 struct stream
*buffer
;
90 bpacket_attr_vec_arr arr
;
97 TAILQ_HEAD (pkt_queue
, bpacket
) pkts
;
100 /* A dummy packet that is used to thread all peers that have
101 completed their work */
102 struct bpacket sentinel
;
105 unsigned int conf_max_count
;
106 unsigned int curr_count
;
107 unsigned int hwm_count
;
108 unsigned int max_count_reached_count
;
113 /* back pointer to the BGP instance */
116 /* list of subgroups that belong to the update group */
117 LIST_HEAD (subgrp_list
, update_subgroup
) subgrps
;
119 /* lazy way to store configuration common to all peers
120 hash function will compute from this data */
130 u_int32_t join_events
;
131 u_int32_t prune_events
;
132 u_int32_t merge_events
;
133 u_int32_t updgrp_switch_events
;
134 u_int32_t peer_refreshes_combined
;
136 u_int32_t split_events
;
137 u_int32_t merge_checks_triggered
;
139 u_int32_t subgrps_created
;
140 u_int32_t subgrps_deleted
;
142 u_int32_t num_dbg_en_peers
;
146 * Shorthand for a global statistics counter.
148 #define UPDGRP_GLOBAL_STAT(updgrp, stat) \
149 ((updgrp)->bgp->update_group_stats.stat)
152 * Add the given value to a counter on an update group and the bgp
155 #define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
157 (updgrp)->stat += (value); \
158 UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
162 * Increment a counter on a update group and its parent structures.
164 #define UPDGRP_INCR_STAT(subgrp, stat) \
165 UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
167 struct update_subgroup
169 /* back pointer to the parent update group */
170 struct update_group
*update_group
;
172 /* list of peers that belong to the subgroup */
173 LIST_HEAD (peer_list
, peer_af
) peers
;
176 /* for being part of an update group's subgroup list */
177 LIST_ENTRY (update_subgroup
) updgrp_train
;
179 struct bpacket_queue pkt_queue
;
182 * List of adj-out structures for this subgroup.
183 * It essentially represents the snapshot of every prefix that
184 * has been advertised to the members of the subgroup
186 TAILQ_HEAD (adjout_queue
, bgp_adj_out
) adjq
;
188 /* packet buffer for update generation */
191 /* We use a separate stream to encode MP_REACH_NLRI for efficient
192 * NLRI packing. peer->work stores all the other attributes. The
193 * actual packet is then constructed by concatenating the two.
195 struct stream
*scratch
;
197 /* synchronization list and time */
198 struct bgp_synchronize
*sync
;
200 /* send prefix count */
201 unsigned long scount
;
203 /* announcement attribute hash */
206 struct thread
*t_coalesce
;
207 u_int32_t v_coalesce
;
209 struct thread
*t_merge_check
;
211 /* table version that the subgroup has caught up to. */
214 /* version maintained to record adj changes */
215 uint64_t adj_version
;
220 * Identifying information about the subgroup that this subgroup was split
225 u_int64_t update_group_id
;
226 u_int64_t subgroup_id
;
229 u_int32_t join_events
;
230 u_int32_t prune_events
;
233 * This is bumped up when another subgroup merges into this one.
235 u_int32_t merge_events
;
236 u_int32_t updgrp_switch_events
;
237 u_int32_t peer_refreshes_combined
;
239 u_int32_t split_events
;
240 u_int32_t merge_checks_triggered
;
247 /* Subgroup flags, see below */
252 * We need to do an outbound refresh to get this subgroup into a
255 #define SUBGRP_FLAG_NEEDS_REFRESH (1 << 0)
257 #define SUBGRP_STATUS_DEFAULT_ORIGINATE (1 << 0)
260 * Add the given value to the specified counter on a subgroup and its
263 #define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
265 (subgrp)->stat += (value); \
266 if ((subgrp)->update_group) \
267 UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, value); \
271 * Increment a counter on a subgroup and its parent structures.
273 #define SUBGRP_INCR_STAT(subgrp, stat) \
274 SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
277 * Decrement a counter on a subgroup and its parent structures.
279 #define SUBGRP_DECR_STAT(subgrp, stat) \
280 SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
283 typedef int (*updgrp_walkcb
) (struct update_group
* updgrp
, void *ctx
);
285 /* really a private structure */
286 struct updwalk_context
293 bgp_policy_type_e policy_type
;
294 const char *policy_name
;
295 int policy_event_start_flag
;
296 int policy_route_update
;
301 #define UPDWALK_FLAGS_ADVQUEUE (1 << 0)
302 #define UPDWALK_FLAGS_ADVERTISED (1 << 1)
305 #define UPDWALK_CONTINUE HASHWALK_CONTINUE
306 #define UPDWALK_ABORT HASHWALK_ABORT
308 #define PAF_PEER(p) ((p)->peer)
309 #define PAF_SUBGRP(p) ((p)->subgroup)
310 #define PAF_UPDGRP(p) ((p)->subgroup->update_group)
311 #define PAF_PKTQ(f) SUBGRP_PKTQ((f)->subgroup)
313 #define UPDGRP_PEER(u) ((u)->conf)
314 #define UPDGRP_AFI(u) ((u)->afi)
315 #define UPDGRP_SAFI(u) ((u)->safi)
316 #define UPDGRP_INST(u) ((u)->bgp)
317 #define UPDGRP_AFFLAGS(u) \
318 ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
319 #define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers)
320 #define UPDGRP_PEER_DBG_EN(u) (((u)->num_dbg_en_peers)++)
321 #define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--)
322 #define UPDGRP_PEER_DBG_OFF(u) (u)->num_dbg_en_peers = 0
324 #define SUBGRP_AFI(s) UPDGRP_AFI((s)->update_group)
325 #define SUBGRP_SAFI(s) UPDGRP_SAFI((s)->update_group)
326 #define SUBGRP_PEER(s) UPDGRP_PEER((s)->update_group)
327 #define SUBGRP_PCOUNT(s) ((s)->peer_count)
328 #define SUBGRP_PFIRST(s) LIST_FIRST(&((s)->peers))
329 #define SUBGRP_PKTQ(s) &((s)->pkt_queue)
330 #define SUBGRP_INST(s) UPDGRP_INST((s)->update_group)
331 #define SUBGRP_AFFLAGS(s) UPDGRP_AFFLAGS((s)->update_group)
332 #define SUBGRP_UPDGRP(s) ((s)->update_group)
335 * Walk all subgroups in an update group.
337 #define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
338 LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
340 #define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
341 LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, tmp_subgrp)
343 #define SUBGRP_FOREACH_PEER(subgrp, paf) \
344 LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
346 #define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
347 LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
349 #define SUBGRP_FOREACH_ADJ(subgrp, adj) \
350 TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
352 #define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
353 TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
357 extern void update_bgp_group_init (struct bgp
*);
358 extern void udpate_bgp_group_free (struct bgp
*);
361 update_group_show (struct bgp
*bgp
, afi_t afi
, safi_t safi
, struct vty
*vty
, u_int64_t subgrp_id
);
362 extern void update_group_show_stats (struct bgp
*bgp
, struct vty
*vty
);
363 extern void update_group_adjust_peer (struct peer_af
*paf
);
364 extern int update_group_adjust_soloness (struct peer
*peer
, int set
);
367 update_subgroup_remove_peer (struct update_subgroup
*, struct peer_af
*);
368 extern struct bgp_table
*update_subgroup_rib (struct update_subgroup
*);
370 update_subgroup_split_peer (struct peer_af
*, struct update_group
*);
372 update_subgroup_check_merge (struct update_subgroup
*, const char *);
374 update_subgroup_trigger_merge_check (struct update_subgroup
*,
376 extern void update_group_policy_update (struct bgp
*bgp
,
377 bgp_policy_type_e ptype
, const char *pname
,
378 int route_update
, int start_event
);
379 extern void update_group_af_walk (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
380 updgrp_walkcb cb
, void *ctx
);
381 extern void update_group_walk (struct bgp
*bgp
, updgrp_walkcb cb
, void *ctx
);
382 extern void update_group_periodic_merge (struct bgp
*bgp
);
383 extern int update_group_refresh_default_originate_route_map (struct thread
*thread
);
384 extern void update_group_start_advtimer (struct bgp
*bgp
);
386 extern void update_subgroup_inherit_info (struct update_subgroup
*to
,
387 struct update_subgroup
*from
);
389 /* bgp_updgrp_packet.c */
390 extern struct bpacket
*bpacket_alloc (void);
391 extern void bpacket_free (struct bpacket
*pkt
);
392 extern void bpacket_queue_init (struct bpacket_queue
*q
);
393 extern void bpacket_queue_cleanup (struct bpacket_queue
*q
);
394 extern void bpacket_queue_sanity_check (struct bpacket_queue
*q
);
395 extern struct bpacket
*bpacket_queue_add (struct bpacket_queue
*q
,
397 struct bpacket_attr_vec_arr
399 struct bpacket
*bpacket_queue_remove (struct bpacket_queue
*q
);
400 extern struct bpacket
*bpacket_queue_first (struct bpacket_queue
*q
);
401 struct bpacket
*bpacket_queue_last (struct bpacket_queue
*q
);
402 unsigned int bpacket_queue_length (struct bpacket_queue
*q
);
403 unsigned int bpacket_queue_hwm_length (struct bpacket_queue
*q
);
404 int bpacket_queue_is_full (struct bgp
*bgp
, struct bpacket_queue
*q
);
405 extern void bpacket_queue_advance_peer (struct peer_af
*paf
);
406 extern void bpacket_queue_remove_peer (struct peer_af
*paf
);
407 extern void bpacket_add_peer (struct bpacket
*pkt
, struct peer_af
*paf
);
408 unsigned int bpacket_queue_virtual_length (struct peer_af
*paf
);
409 extern void bpacket_queue_show_vty (struct bpacket_queue
*q
, struct vty
*vty
);
410 int subgroup_packets_to_build (struct update_subgroup
*subgrp
);
411 extern struct bpacket
*subgroup_update_packet (struct update_subgroup
*s
);
412 extern struct bpacket
*subgroup_withdraw_packet (struct update_subgroup
*s
);
413 extern struct stream
*bpacket_reformat_for_peer (struct bpacket
*pkt
,
414 struct peer_af
*paf
);
415 extern void bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr
*vecarr
);
416 extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr
*vecarr
,
417 bpacket_attr_vec_type type
,
421 subgroup_default_update_packet (struct update_subgroup
*subgrp
,
422 struct attr
*attr
, struct peer
*from
);
423 extern void subgroup_default_withdraw_packet (struct update_subgroup
*subgrp
);
425 /* bgp_updgrp_adv.c */
426 extern struct bgp_advertise
*bgp_advertise_clean_subgroup (struct
431 extern void update_group_show_adj_queue (struct bgp
*bgp
, afi_t afi
,
432 safi_t safi
, struct vty
*vty
,
434 extern void update_group_show_advertised (struct bgp
*bgp
, afi_t afi
,
435 safi_t safi
, struct vty
*vty
,
437 extern void update_group_show_packet_queue (struct bgp
*bgp
, afi_t afi
,
438 safi_t safi
, struct vty
*vty
,
440 extern void subgroup_announce_route (struct update_subgroup
*subgrp
);
441 extern void subgroup_announce_all (struct update_subgroup
*subgrp
);
444 subgroup_default_originate (struct update_subgroup
*subgrp
, int withdraw
);
446 group_announce_route (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
447 struct bgp_node
*rn
, struct bgp_info
*ri
);
448 extern void subgroup_clear_table (struct update_subgroup
*subgrp
);
449 extern void update_group_announce (struct bgp
*bgp
);
450 extern void update_group_announce_rrclients (struct bgp
*bgp
);
451 extern void peer_af_announce_route (struct peer_af
*paf
, int combine
);
452 extern struct bgp_adj_out
*bgp_adj_out_alloc (struct update_subgroup
*subgrp
,
453 struct bgp_node
*rn
);
454 extern void bgp_adj_out_remove_subgroup (struct bgp_node
*rn
,
455 struct bgp_adj_out
*adj
,
456 struct update_subgroup
*subgrp
);
458 bgp_adj_out_set_subgroup (struct bgp_node
*rn
,
459 struct update_subgroup
*subgrp
,
460 struct attr
*attr
, struct bgp_info
*binfo
);
462 bgp_adj_out_unset_subgroup (struct bgp_node
*rn
,
463 struct update_subgroup
*subgrp
,
466 subgroup_announce_table (struct update_subgroup
*subgrp
,
467 struct bgp_table
*table
, int rsclient
);
469 subgroup_trigger_write (struct update_subgroup
*subgrp
);
472 update_group_clear_update_dbg (struct update_group
*updgrp
, void *arg
);
479 * bpacket_queue_is_empty
482 bpacket_queue_is_empty (struct bpacket_queue
*queue
)
486 * The packet queue is empty if it only contains a sentinel.
488 if (queue
->curr_count
!= 1)
491 assert (bpacket_queue_first (queue
)->buffer
== NULL
);
498 * Returns the packet after the given packet in a bpacket queue.
500 static inline struct bpacket
*
501 bpacket_next (struct bpacket
*pkt
)
503 return TAILQ_NEXT (pkt
, pkt_train
);
507 * update_group_adjust_peer_afs
509 * Adjust all peer_af structures for the given peer.
512 update_group_adjust_peer_afs (struct peer
*peer
)
517 PEERAF_FOREACH (peer
, paf
, afi
) update_group_adjust_peer (paf
);
521 * update_group_remove_peer_afs
523 * Remove all peer_af structures for the given peer from their subgroups.
526 update_group_remove_peer_afs (struct peer
*peer
)
531 PEERAF_FOREACH (peer
, paf
, afi
)
532 update_subgroup_remove_peer (PAF_SUBGRP (paf
), paf
);
536 * update_subgroup_needs_refresh
539 update_subgroup_needs_refresh (const struct update_subgroup
*subgrp
)
541 if (CHECK_FLAG (subgrp
->flags
, SUBGRP_FLAG_NEEDS_REFRESH
))
548 * update_subgroup_set_needs_refresh
551 update_subgroup_set_needs_refresh (struct update_subgroup
*subgrp
, int value
)
554 SET_FLAG (subgrp
->flags
, SUBGRP_FLAG_NEEDS_REFRESH
);
556 UNSET_FLAG (subgrp
->flags
, SUBGRP_FLAG_NEEDS_REFRESH
);
559 static inline struct update_subgroup
*
560 peer_subgroup (struct peer
*peer
, afi_t afi
, safi_t safi
)
564 paf
= peer_af_find (peer
, afi
, safi
);
566 return PAF_SUBGRP (paf
);
571 * update_group_adjust_peer_afs
573 * Adjust all peer_af structures for the given peer.
576 bgp_announce_peer (struct peer
*peer
)
581 PEERAF_FOREACH (peer
, paf
, af
) subgroup_announce_all (PAF_SUBGRP (paf
));
585 * advertise_list_is_empty
588 advertise_list_is_empty (struct update_subgroup
*subgrp
)
590 if (!BGP_ADV_FIFO_EMPTY (&subgrp
->sync
->update
) ||
591 !BGP_ADV_FIFO_EMPTY (&subgrp
->sync
->withdraw
) ||
592 !BGP_ADV_FIFO_EMPTY (&subgrp
->sync
->withdraw_low
))
600 #endif /* _QUAGGA_BGP_UPDGRP_H */