Line data Source code
1 : /* BGP routing information
2 : * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 : * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 : *
5 : * This file is part of GNU Zebra.
6 : *
7 : * GNU Zebra is free software; you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the
9 : * Free Software Foundation; either version 2, or (at your option) any
10 : * later version.
11 : *
12 : * GNU Zebra is distributed in the hope that it will be useful, but
13 : * WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : * General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License along
18 : * with this program; see the file COPYING; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 : */
21 :
22 : #include <zebra.h>
23 : #include <math.h>
24 :
25 : #include "printfrr.h"
26 : #include "frrstr.h"
27 : #include "prefix.h"
28 : #include "linklist.h"
29 : #include "memory.h"
30 : #include "command.h"
31 : #include "stream.h"
32 : #include "filter.h"
33 : #include "log.h"
34 : #include "routemap.h"
35 : #include "buffer.h"
36 : #include "sockunion.h"
37 : #include "plist.h"
38 : #include "thread.h"
39 : #include "workqueue.h"
40 : #include "queue.h"
41 : #include "memory.h"
42 : #include "srv6.h"
43 : #include "lib/json.h"
44 : #include "lib_errors.h"
45 : #include "zclient.h"
46 : #include "bgpd/bgpd.h"
47 : #include "bgpd/bgp_table.h"
48 : #include "bgpd/bgp_route.h"
49 : #include "bgpd/bgp_attr.h"
50 : #include "bgpd/bgp_debug.h"
51 : #include "bgpd/bgp_errors.h"
52 : #include "bgpd/bgp_aspath.h"
53 : #include "bgpd/bgp_regex.h"
54 : #include "bgpd/bgp_community.h"
55 : #include "bgpd/bgp_community_alias.h"
56 : #include "bgpd/bgp_ecommunity.h"
57 : #include "bgpd/bgp_lcommunity.h"
58 : #include "bgpd/bgp_clist.h"
59 : #include "bgpd/bgp_packet.h"
60 : #include "bgpd/bgp_filter.h"
61 : #include "bgpd/bgp_fsm.h"
62 : #include "bgpd/bgp_mplsvpn.h"
63 : #include "bgpd/bgp_nexthop.h"
64 : #include "bgpd/bgp_damp.h"
65 : #include "bgpd/bgp_advertise.h"
66 : #include "bgpd/bgp_zebra.h"
67 : #include "bgpd/bgp_vty.h"
68 : #include "bgpd/bgp_mpath.h"
69 : #include "bgpd/bgp_nht.h"
70 : #include "bgpd/bgp_updgrp.h"
71 : #include "bgpd/bgp_label.h"
72 : #include "bgpd/bgp_addpath.h"
73 : #include "bgpd/bgp_mac.h"
74 : #include "bgpd/bgp_network.h"
75 : #include "bgpd/bgp_trace.h"
76 : #include "bgpd/bgp_rpki.h"
77 :
78 : #ifdef ENABLE_BGP_VNC
79 : #include "bgpd/rfapi/rfapi_backend.h"
80 : #include "bgpd/rfapi/vnc_import_bgp.h"
81 : #include "bgpd/rfapi/vnc_export_bgp.h"
82 : #endif
83 : #include "bgpd/bgp_encap_types.h"
84 : #include "bgpd/bgp_encap_tlv.h"
85 : #include "bgpd/bgp_evpn.h"
86 : #include "bgpd/bgp_evpn_mh.h"
87 : #include "bgpd/bgp_evpn_vty.h"
88 : #include "bgpd/bgp_flowspec.h"
89 : #include "bgpd/bgp_flowspec_util.h"
90 : #include "bgpd/bgp_pbr.h"
91 :
92 : #include "bgpd/bgp_route_clippy.c"
93 :
94 2 : DEFINE_HOOK(bgp_snmp_update_stats,
95 : (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
96 : (rn, pi, added));
97 :
98 0 : DEFINE_HOOK(bgp_rpki_prefix_status,
99 : (struct peer *peer, struct attr *attr,
100 : const struct prefix *prefix),
101 : (peer, attr, prefix));
102 :
103 : /* Extern from bgp_dump.c */
104 : extern const char *bgp_origin_str[];
105 : extern const char *bgp_origin_long_str[];
106 :
107 : /* PMSI strings. */
108 : #define PMSI_TNLTYPE_STR_NO_INFO "No info"
109 : #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
110 : static const struct message bgp_pmsi_tnltype_str[] = {
111 : {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
112 : {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
113 : {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
114 : {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
115 : {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
116 : {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
117 : {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
118 : {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
119 : {0}
120 : };
121 :
122 : #define VRFID_NONE_STR "-"
123 : #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
124 :
125 1 : DEFINE_HOOK(bgp_process,
126 : (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
127 : struct peer *peer, bool withdraw),
128 : (bgp, afi, safi, bn, peer, withdraw));
129 :
130 : /** Test if path is suppressed. */
131 0 : static bool bgp_path_suppressed(struct bgp_path_info *pi)
132 : {
133 0 : if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
134 : return false;
135 :
136 0 : return listcount(pi->extra->aggr_suppressors) > 0;
137 : }
138 :
139 2 : struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
140 : safi_t safi, const struct prefix *p,
141 : struct prefix_rd *prd)
142 : {
143 2 : struct bgp_dest *dest;
144 2 : struct bgp_dest *pdest = NULL;
145 :
146 2 : assert(table);
147 :
148 2 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
149 2 : || (safi == SAFI_EVPN)) {
150 0 : pdest = bgp_node_get(table, (struct prefix *)prd);
151 :
152 0 : if (!bgp_dest_has_bgp_path_info_data(pdest))
153 0 : bgp_dest_set_bgp_table_info(
154 : pdest, bgp_table_init(table->bgp, afi, safi));
155 : else
156 0 : bgp_dest_unlock_node(pdest);
157 0 : table = bgp_dest_get_bgp_table_info(pdest);
158 : }
159 :
160 2 : dest = bgp_node_get(table, p);
161 :
162 2 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
163 : || (safi == SAFI_EVPN))
164 0 : dest->pdest = pdest;
165 :
166 2 : return dest;
167 : }
168 :
169 0 : struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
170 : safi_t safi, const struct prefix *p,
171 : struct prefix_rd *prd)
172 : {
173 0 : struct bgp_dest *dest;
174 0 : struct bgp_dest *pdest = NULL;
175 :
176 0 : if (!table)
177 : return NULL;
178 :
179 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
180 0 : || (safi == SAFI_EVPN)) {
181 0 : pdest = bgp_node_lookup(table, (struct prefix *)prd);
182 0 : if (!pdest)
183 : return NULL;
184 :
185 0 : if (!bgp_dest_has_bgp_path_info_data(pdest)) {
186 0 : bgp_dest_unlock_node(pdest);
187 0 : return NULL;
188 : }
189 :
190 : table = bgp_dest_get_bgp_table_info(pdest);
191 : }
192 :
193 0 : dest = bgp_node_lookup(table, p);
194 :
195 0 : return dest;
196 : }
197 :
198 : /* Allocate bgp_path_info_extra */
199 0 : static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
200 : {
201 0 : struct bgp_path_info_extra *new;
202 0 : new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
203 : sizeof(struct bgp_path_info_extra));
204 0 : new->label[0] = MPLS_INVALID_LABEL;
205 0 : new->num_labels = 0;
206 0 : new->bgp_fs_pbr = NULL;
207 0 : new->bgp_fs_iprule = NULL;
208 0 : return new;
209 : }
210 :
211 1 : void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
212 : {
213 1 : struct bgp_path_info_extra *e;
214 :
215 1 : if (!extra || !*extra)
216 : return;
217 :
218 0 : e = *extra;
219 0 : if (e->damp_info)
220 0 : bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
221 : e->damp_info->safi);
222 :
223 0 : e->damp_info = NULL;
224 0 : if (e->parent) {
225 0 : struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
226 :
227 0 : if (bpi->net) {
228 : /* FIXME: since multiple e may have the same e->parent
229 : * and e->parent->net is holding a refcount for each
230 : * of them, we need to do some fudging here.
231 : *
232 : * WARNING: if bpi->net->lock drops to 0, bpi may be
233 : * freed as well (because bpi->net was holding the
234 : * last reference to bpi) => write after free!
235 : */
236 0 : unsigned refcount;
237 :
238 0 : bpi = bgp_path_info_lock(bpi);
239 0 : refcount = bgp_dest_get_lock_count(bpi->net) - 1;
240 0 : bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
241 0 : if (!refcount)
242 0 : bpi->net = NULL;
243 0 : bgp_path_info_unlock(bpi);
244 : }
245 0 : bgp_path_info_unlock(e->parent);
246 0 : e->parent = NULL;
247 : }
248 :
249 0 : if (e->bgp_orig)
250 0 : bgp_unlock(e->bgp_orig);
251 :
252 0 : if (e->peer_orig)
253 0 : peer_unlock(e->peer_orig);
254 :
255 0 : if (e->aggr_suppressors)
256 0 : list_delete(&e->aggr_suppressors);
257 :
258 0 : if (e->mh_info)
259 0 : bgp_evpn_path_mh_info_free(e->mh_info);
260 :
261 0 : if ((*extra)->bgp_fs_iprule)
262 0 : list_delete(&((*extra)->bgp_fs_iprule));
263 0 : if ((*extra)->bgp_fs_pbr)
264 0 : list_delete(&((*extra)->bgp_fs_pbr));
265 0 : XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
266 : }
267 :
268 : /* Get bgp_path_info extra information for the given bgp_path_info, lazy
269 : * allocated if required.
270 : */
271 0 : struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
272 : {
273 0 : if (!pi->extra)
274 0 : pi->extra = bgp_path_info_extra_new();
275 0 : return pi->extra;
276 : }
277 :
278 : /* Free bgp route information. */
279 1 : void bgp_path_info_free_with_caller(const char *name,
280 : struct bgp_path_info *path)
281 : {
282 1 : frrtrace(2, frr_bgp, bgp_path_info_free, path, name);
283 1 : bgp_attr_unintern(&path->attr);
284 :
285 1 : bgp_unlink_nexthop(path);
286 1 : bgp_path_info_extra_free(&path->extra);
287 1 : bgp_path_info_mpath_free(&path->mpath);
288 1 : if (path->net)
289 1 : bgp_addpath_free_info_data(&path->tx_addpath,
290 : &path->net->tx_addpath);
291 :
292 1 : peer_unlock(path->peer); /* bgp_path_info peer reference */
293 :
294 1 : XFREE(MTYPE_BGP_ROUTE, path);
295 1 : }
296 :
297 1 : struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
298 : {
299 1 : path->lock++;
300 0 : return path;
301 : }
302 :
303 1 : struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
304 : {
305 1 : assert(path && path->lock > 0);
306 1 : path->lock--;
307 :
308 1 : if (path->lock == 0) {
309 1 : bgp_path_info_free(path);
310 1 : return NULL;
311 : }
312 :
313 : return path;
314 : }
315 :
316 : /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
317 1 : static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
318 : {
319 1 : struct peer *peer;
320 1 : struct bgp_path_info *old_pi, *nextpi;
321 1 : bool set_flag = false;
322 1 : struct bgp *bgp = NULL;
323 1 : struct bgp_table *table = NULL;
324 1 : afi_t afi = 0;
325 1 : safi_t safi = 0;
326 :
327 : /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 : * then the route selection is deferred
329 : */
330 1 : if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
331 : return 0;
332 :
333 1 : if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
334 0 : if (BGP_DEBUG(update, UPDATE_OUT))
335 0 : zlog_debug(
336 : "Route %pBD is in workqueue and being processed, not deferred.",
337 : dest);
338 :
339 0 : return 0;
340 : }
341 :
342 1 : table = bgp_dest_table(dest);
343 1 : if (table) {
344 1 : bgp = table->bgp;
345 1 : afi = table->afi;
346 1 : safi = table->safi;
347 : }
348 :
349 1 : for (old_pi = bgp_dest_get_bgp_path_info(dest);
350 2 : (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
351 1 : if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
352 0 : continue;
353 :
354 : /* Route selection is deferred if there is a stale path which
355 : * which indicates peer is in restart mode
356 : */
357 1 : if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
358 0 : && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
359 : set_flag = true;
360 : } else {
361 : /* If the peer is graceful restart capable and peer is
362 : * restarting mode, set the flag BGP_NODE_SELECT_DEFER
363 : */
364 1 : peer = old_pi->peer;
365 1 : if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
366 0 : && BGP_PEER_RESTARTING_MODE(peer)
367 : && (old_pi
368 0 : && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
369 : set_flag = true;
370 : }
371 : }
372 : if (set_flag)
373 : break;
374 : }
375 :
376 : /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
377 : * is active
378 : */
379 1 : if (set_flag && table) {
380 0 : if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
381 0 : if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
382 0 : bgp->gr_info[afi][safi].gr_deferred++;
383 0 : SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
384 0 : if (BGP_DEBUG(update, UPDATE_OUT))
385 0 : zlog_debug("DEFER route %pBD, dest %p", dest,
386 : dest);
387 0 : return 0;
388 : }
389 : }
390 : return -1;
391 : }
392 :
393 1 : void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
394 : struct bgp_path_info *pi)
395 : {
396 1 : frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
397 1 : struct bgp_path_info *top;
398 :
399 1 : top = bgp_dest_get_bgp_path_info(dest);
400 :
401 1 : pi->next = top;
402 1 : pi->prev = NULL;
403 1 : if (top)
404 0 : top->prev = pi;
405 1 : bgp_dest_set_bgp_path_info(dest, pi);
406 :
407 1 : bgp_path_info_lock(pi);
408 1 : bgp_dest_lock_node(dest);
409 1 : peer_lock(pi->peer); /* bgp_path_info peer reference */
410 1 : bgp_dest_set_defer_flag(dest, false);
411 1 : hook_call(bgp_snmp_update_stats, dest, pi, true);
412 1 : }
413 :
414 : /* Do the actual removal of info from RIB, for use by bgp_process
415 : completion callback *only* */
416 1 : void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
417 : {
418 1 : if (pi->next)
419 0 : pi->next->prev = pi->prev;
420 1 : if (pi->prev)
421 0 : pi->prev->next = pi->next;
422 : else
423 1 : bgp_dest_set_bgp_path_info(dest, pi->next);
424 :
425 1 : bgp_path_info_mpath_dequeue(pi);
426 1 : bgp_path_info_unlock(pi);
427 1 : hook_call(bgp_snmp_update_stats, dest, pi, false);
428 1 : bgp_dest_unlock_node(dest);
429 1 : }
430 :
431 0 : void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
432 : {
433 0 : bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
434 : /* set of previous already took care of pcount */
435 0 : UNSET_FLAG(pi->flags, BGP_PATH_VALID);
436 0 : }
437 :
438 : /* undo the effects of a previous call to bgp_path_info_delete; typically
439 : called when a route is deleted and then quickly re-added before the
440 : deletion has been processed */
441 0 : void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
442 : {
443 0 : bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
444 : /* unset of previous already took care of pcount */
445 0 : SET_FLAG(pi->flags, BGP_PATH_VALID);
446 0 : }
447 :
448 : /* Adjust pcount as required */
449 1 : static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
450 : {
451 1 : struct bgp_table *table;
452 :
453 1 : assert(dest && bgp_dest_table(dest));
454 1 : assert(pi && pi->peer && pi->peer->bgp);
455 :
456 1 : table = bgp_dest_table(dest);
457 :
458 1 : if (pi->peer == pi->peer->bgp->peer_self)
459 : return;
460 :
461 1 : if (!BGP_PATH_COUNTABLE(pi)
462 0 : && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
463 :
464 0 : UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
465 :
466 : /* slight hack, but more robust against errors. */
467 0 : if (pi->peer->pcount[table->afi][table->safi])
468 0 : pi->peer->pcount[table->afi][table->safi]--;
469 : else
470 0 : flog_err(EC_LIB_DEVELOPMENT,
471 : "Asked to decrement 0 prefix count for peer");
472 1 : } else if (BGP_PATH_COUNTABLE(pi)
473 1 : && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
474 1 : SET_FLAG(pi->flags, BGP_PATH_COUNTED);
475 1 : pi->peer->pcount[table->afi][table->safi]++;
476 : }
477 : }
478 :
479 0 : static int bgp_label_index_differs(struct bgp_path_info *pi1,
480 : struct bgp_path_info *pi2)
481 : {
482 0 : return (!(pi1->attr->label_index == pi2->attr->label_index));
483 : }
484 :
485 : /* Set/unset bgp_path_info flags, adjusting any other state as needed.
486 : * This is here primarily to keep prefix-count in check.
487 : */
488 1 : void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
489 : uint32_t flag)
490 : {
491 1 : SET_FLAG(pi->flags, flag);
492 :
493 : /* early bath if we know it's not a flag that changes countability state
494 : */
495 0 : if (!CHECK_FLAG(flag,
496 : BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
497 : return;
498 :
499 0 : bgp_pcount_adjust(dest, pi);
500 : }
501 :
502 0 : void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
503 : uint32_t flag)
504 : {
505 0 : UNSET_FLAG(pi->flags, flag);
506 :
507 : /* early bath if we know it's not a flag that changes countability state
508 : */
509 0 : if (!CHECK_FLAG(flag,
510 : BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
511 : return;
512 :
513 0 : bgp_pcount_adjust(dest, pi);
514 : }
515 :
516 : /* Get MED value. If MED value is missing and "bgp bestpath
517 : missing-as-worst" is specified, treat it as the worst value. */
518 0 : static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
519 : {
520 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
521 0 : return attr->med;
522 : else {
523 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
524 : return BGP_MED_MAX;
525 : else
526 0 : return 0;
527 : }
528 : }
529 :
530 0 : void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
531 : size_t buf_len)
532 : {
533 0 : if (pi->addpath_rx_id)
534 0 : snprintf(buf, buf_len, "path %s (addpath rxid %d)",
535 0 : pi->peer->host, pi->addpath_rx_id);
536 : else
537 0 : snprintf(buf, buf_len, "path %s", pi->peer->host);
538 0 : }
539 :
540 :
541 : /*
542 : * Get the ultimate path info.
543 : */
544 1 : struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
545 : {
546 1 : struct bgp_path_info *bpi_ultimate;
547 :
548 1 : if (info->sub_type != BGP_ROUTE_IMPORTED)
549 : return info;
550 :
551 : for (bpi_ultimate = info;
552 0 : bpi_ultimate->extra && bpi_ultimate->extra->parent;
553 : bpi_ultimate = bpi_ultimate->extra->parent)
554 : ;
555 :
556 : return bpi_ultimate;
557 : }
558 :
559 : /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
560 : */
561 0 : static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
562 : struct bgp_path_info *exist, int *paths_eq,
563 : struct bgp_maxpaths_cfg *mpath_cfg, int debug,
564 : char *pfx_buf, afi_t afi, safi_t safi,
565 : enum bgp_path_selection_reason *reason)
566 : {
567 0 : const struct prefix *new_p;
568 0 : struct attr *newattr, *existattr;
569 0 : enum bgp_peer_sort new_sort;
570 0 : enum bgp_peer_sort exist_sort;
571 0 : uint32_t new_pref;
572 0 : uint32_t exist_pref;
573 0 : uint32_t new_med;
574 0 : uint32_t exist_med;
575 0 : uint32_t new_weight;
576 0 : uint32_t exist_weight;
577 0 : uint32_t newm, existm;
578 0 : struct in_addr new_id;
579 0 : struct in_addr exist_id;
580 0 : int new_cluster;
581 0 : int exist_cluster;
582 0 : int internal_as_route;
583 0 : int confed_as_route;
584 0 : int ret = 0;
585 0 : int igp_metric_ret = 0;
586 0 : int peer_sort_ret = -1;
587 0 : char new_buf[PATH_ADDPATH_STR_BUFFER];
588 0 : char exist_buf[PATH_ADDPATH_STR_BUFFER];
589 0 : uint32_t new_mm_seq;
590 0 : uint32_t exist_mm_seq;
591 0 : int nh_cmp;
592 0 : esi_t *exist_esi;
593 0 : esi_t *new_esi;
594 0 : bool same_esi;
595 0 : bool old_proxy;
596 0 : bool new_proxy;
597 0 : bool new_origin, exist_origin;
598 0 : struct bgp_path_info *bpi_ultimate;
599 :
600 0 : *paths_eq = 0;
601 :
602 : /* 0. Null check. */
603 0 : if (new == NULL) {
604 0 : *reason = bgp_path_selection_none;
605 0 : if (debug)
606 0 : zlog_debug("%s: new is NULL", pfx_buf);
607 0 : return 0;
608 : }
609 :
610 0 : if (debug) {
611 0 : bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
612 0 : bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
613 : sizeof(new_buf));
614 : }
615 :
616 0 : if (exist == NULL) {
617 0 : *reason = bgp_path_selection_first;
618 0 : if (debug)
619 0 : zlog_debug("%s(%s): %s is the initial bestpath",
620 : pfx_buf, bgp->name_pretty, new_buf);
621 0 : return 1;
622 : }
623 :
624 0 : if (debug) {
625 0 : bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
626 0 : bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
627 : sizeof(exist_buf));
628 0 : zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
629 : pfx_buf, bgp->name_pretty, new_buf, new->flags,
630 : exist_buf, exist->flags);
631 : }
632 :
633 0 : newattr = new->attr;
634 0 : existattr = exist->attr;
635 :
636 : /* A BGP speaker that has advertised the "Long-lived Graceful Restart
637 : * Capability" to a neighbor MUST perform the following upon receiving
638 : * a route from that neighbor with the "LLGR_STALE" community, or upon
639 : * attaching the "LLGR_STALE" community itself per Section 4.2:
640 : *
641 : * Treat the route as the least-preferred in route selection (see
642 : * below). See the Risks of Depreferencing Routes section (Section 5.2)
643 : * for a discussion of potential risks inherent in doing this.
644 : */
645 0 : if (bgp_attr_get_community(newattr) &&
646 0 : community_include(bgp_attr_get_community(newattr),
647 : COMMUNITY_LLGR_STALE)) {
648 0 : if (debug)
649 0 : zlog_debug(
650 : "%s: %s wins over %s due to LLGR_STALE community",
651 : pfx_buf, new_buf, exist_buf);
652 0 : return 0;
653 : }
654 :
655 0 : if (bgp_attr_get_community(existattr) &&
656 0 : community_include(bgp_attr_get_community(existattr),
657 : COMMUNITY_LLGR_STALE)) {
658 0 : if (debug)
659 0 : zlog_debug(
660 : "%s: %s loses to %s due to LLGR_STALE community",
661 : pfx_buf, new_buf, exist_buf);
662 0 : return 1;
663 : }
664 :
665 0 : new_p = bgp_dest_get_prefix(new->net);
666 :
667 : /* For EVPN routes, we cannot just go by local vs remote, we have to
668 : * look at the MAC mobility sequence number, if present.
669 : */
670 0 : if ((safi == SAFI_EVPN)
671 0 : && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
672 : /* This is an error condition described in RFC 7432 Section
673 : * 15.2. The RFC
674 : * states that in this scenario "the PE MUST alert the operator"
675 : * but it
676 : * does not state what other action to take. In order to provide
677 : * some
678 : * consistency in this scenario we are going to prefer the path
679 : * with the
680 : * sticky flag.
681 : */
682 0 : if (newattr->sticky != existattr->sticky) {
683 0 : if (!debug) {
684 0 : prefix2str(new_p, pfx_buf,
685 : sizeof(*pfx_buf)
686 : * PREFIX2STR_BUFFER);
687 0 : bgp_path_info_path_with_addpath_rx_str(
688 : new, new_buf, sizeof(new_buf));
689 0 : bgp_path_info_path_with_addpath_rx_str(
690 : exist, exist_buf, sizeof(exist_buf));
691 : }
692 :
693 0 : if (newattr->sticky && !existattr->sticky) {
694 0 : *reason = bgp_path_selection_evpn_sticky_mac;
695 0 : if (debug)
696 0 : zlog_debug(
697 : "%s: %s wins over %s due to sticky MAC flag",
698 : pfx_buf, new_buf, exist_buf);
699 0 : return 1;
700 : }
701 :
702 0 : if (!newattr->sticky && existattr->sticky) {
703 0 : *reason = bgp_path_selection_evpn_sticky_mac;
704 0 : if (debug)
705 0 : zlog_debug(
706 : "%s: %s loses to %s due to sticky MAC flag",
707 : pfx_buf, new_buf, exist_buf);
708 0 : return 0;
709 : }
710 : }
711 :
712 0 : new_esi = bgp_evpn_attr_get_esi(newattr);
713 0 : exist_esi = bgp_evpn_attr_get_esi(existattr);
714 0 : if (bgp_evpn_is_esi_valid(new_esi) &&
715 0 : !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
716 : same_esi = true;
717 : } else {
718 : same_esi = false;
719 : }
720 :
721 : /* If both paths have the same non-zero ES and
722 : * one path is local it wins.
723 : * PS: Note the local path wins even if the remote
724 : * has the higher MM seq. The local path's
725 : * MM seq will be fixed up to match the highest
726 : * rem seq, subsequently.
727 : */
728 0 : if (same_esi) {
729 0 : char esi_buf[ESI_STR_LEN];
730 :
731 0 : if (bgp_evpn_is_path_local(bgp, new)) {
732 0 : *reason = bgp_path_selection_evpn_local_path;
733 0 : if (debug)
734 0 : zlog_debug(
735 : "%s: %s wins over %s as ES %s is same and local",
736 : pfx_buf, new_buf, exist_buf,
737 : esi_to_str(new_esi, esi_buf,
738 : sizeof(esi_buf)));
739 0 : return 1;
740 : }
741 0 : if (bgp_evpn_is_path_local(bgp, exist)) {
742 0 : *reason = bgp_path_selection_evpn_local_path;
743 0 : if (debug)
744 0 : zlog_debug(
745 : "%s: %s loses to %s as ES %s is same and local",
746 : pfx_buf, new_buf, exist_buf,
747 : esi_to_str(new_esi, esi_buf,
748 : sizeof(esi_buf)));
749 0 : return 0;
750 : }
751 : }
752 :
753 0 : new_mm_seq = mac_mobility_seqnum(newattr);
754 0 : exist_mm_seq = mac_mobility_seqnum(existattr);
755 :
756 0 : if (new_mm_seq > exist_mm_seq) {
757 0 : *reason = bgp_path_selection_evpn_seq;
758 0 : if (debug)
759 0 : zlog_debug(
760 : "%s: %s wins over %s due to MM seq %u > %u",
761 : pfx_buf, new_buf, exist_buf, new_mm_seq,
762 : exist_mm_seq);
763 0 : return 1;
764 : }
765 :
766 0 : if (new_mm_seq < exist_mm_seq) {
767 0 : *reason = bgp_path_selection_evpn_seq;
768 0 : if (debug)
769 0 : zlog_debug(
770 : "%s: %s loses to %s due to MM seq %u < %u",
771 : pfx_buf, new_buf, exist_buf, new_mm_seq,
772 : exist_mm_seq);
773 0 : return 0;
774 : }
775 :
776 : /* if the sequence numbers and ESI are the same and one path
777 : * is non-proxy it wins (over proxy)
778 : */
779 0 : new_proxy = bgp_evpn_attr_is_proxy(newattr);
780 0 : old_proxy = bgp_evpn_attr_is_proxy(existattr);
781 0 : if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
782 : old_proxy != new_proxy) {
783 0 : if (!new_proxy) {
784 0 : *reason = bgp_path_selection_evpn_non_proxy;
785 0 : if (debug)
786 0 : zlog_debug(
787 : "%s: %s wins over %s, same seq/es and non-proxy",
788 : pfx_buf, new_buf, exist_buf);
789 0 : return 1;
790 : }
791 :
792 0 : *reason = bgp_path_selection_evpn_non_proxy;
793 0 : if (debug)
794 0 : zlog_debug(
795 : "%s: %s loses to %s, same seq/es and non-proxy",
796 : pfx_buf, new_buf, exist_buf);
797 0 : return 0;
798 : }
799 :
800 : /*
801 : * if sequence numbers are the same path with the lowest IP
802 : * wins
803 : */
804 0 : nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
805 0 : if (nh_cmp < 0) {
806 0 : *reason = bgp_path_selection_evpn_lower_ip;
807 0 : if (debug)
808 0 : zlog_debug(
809 : "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
810 : pfx_buf, new_buf, exist_buf, new_mm_seq,
811 : &new->attr->nexthop);
812 0 : return 1;
813 : }
814 0 : if (nh_cmp > 0) {
815 0 : *reason = bgp_path_selection_evpn_lower_ip;
816 0 : if (debug)
817 0 : zlog_debug(
818 : "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
819 : pfx_buf, new_buf, exist_buf, new_mm_seq,
820 : &new->attr->nexthop);
821 0 : return 0;
822 : }
823 : }
824 :
825 : /* 1. Weight check. */
826 0 : new_weight = newattr->weight;
827 0 : exist_weight = existattr->weight;
828 :
829 0 : if (new_weight > exist_weight) {
830 0 : *reason = bgp_path_selection_weight;
831 0 : if (debug)
832 0 : zlog_debug("%s: %s wins over %s due to weight %d > %d",
833 : pfx_buf, new_buf, exist_buf, new_weight,
834 : exist_weight);
835 0 : return 1;
836 : }
837 :
838 0 : if (new_weight < exist_weight) {
839 0 : *reason = bgp_path_selection_weight;
840 0 : if (debug)
841 0 : zlog_debug("%s: %s loses to %s due to weight %d < %d",
842 : pfx_buf, new_buf, exist_buf, new_weight,
843 : exist_weight);
844 0 : return 0;
845 : }
846 :
847 : /* 2. Local preference check. */
848 0 : new_pref = exist_pref = bgp->default_local_pref;
849 :
850 0 : if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
851 0 : new_pref = newattr->local_pref;
852 0 : if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
853 0 : exist_pref = existattr->local_pref;
854 :
855 0 : if (new_pref > exist_pref) {
856 0 : *reason = bgp_path_selection_local_pref;
857 0 : if (debug)
858 0 : zlog_debug(
859 : "%s: %s wins over %s due to localpref %d > %d",
860 : pfx_buf, new_buf, exist_buf, new_pref,
861 : exist_pref);
862 0 : return 1;
863 : }
864 :
865 0 : if (new_pref < exist_pref) {
866 0 : *reason = bgp_path_selection_local_pref;
867 0 : if (debug)
868 0 : zlog_debug(
869 : "%s: %s loses to %s due to localpref %d < %d",
870 : pfx_buf, new_buf, exist_buf, new_pref,
871 : exist_pref);
872 0 : return 0;
873 : }
874 :
875 : /* If a BGP speaker supports ACCEPT_OWN and is configured for the
876 : * extensions defined in this document, the following step is inserted
877 : * after the LOCAL_PREF comparison step in the BGP decision process:
878 : * When comparing a pair of routes for a BGP destination, the
879 : * route with the ACCEPT_OWN community attached is preferred over
880 : * the route that does not have the community.
881 : * This extra step MUST only be invoked during the best path selection
882 : * process of VPN-IP routes.
883 : */
884 0 : if (safi == SAFI_MPLS_VPN &&
885 0 : (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
886 0 : CHECK_FLAG(exist->peer->af_flags[afi][safi],
887 : PEER_FLAG_ACCEPT_OWN))) {
888 0 : bool new_accept_own = false;
889 0 : bool exist_accept_own = false;
890 0 : uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
891 :
892 0 : if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
893 0 : new_accept_own = community_include(
894 : bgp_attr_get_community(newattr), accept_own);
895 0 : if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
896 0 : exist_accept_own = community_include(
897 : bgp_attr_get_community(existattr), accept_own);
898 :
899 0 : if (new_accept_own && !exist_accept_own) {
900 0 : *reason = bgp_path_selection_accept_own;
901 0 : if (debug)
902 0 : zlog_debug(
903 : "%s: %s wins over %s due to accept-own",
904 : pfx_buf, new_buf, exist_buf);
905 0 : return 1;
906 : }
907 :
908 0 : if (!new_accept_own && exist_accept_own) {
909 0 : *reason = bgp_path_selection_accept_own;
910 0 : if (debug)
911 0 : zlog_debug(
912 : "%s: %s loses to %s due to accept-own",
913 : pfx_buf, new_buf, exist_buf);
914 0 : return 0;
915 : }
916 : }
917 :
918 : /* Tie-breaker - AIGP (Metric TLV) attribute */
919 0 : if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
920 0 : CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
921 0 : CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
922 0 : uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
923 0 : uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
924 :
925 0 : if (new_aigp < exist_aigp) {
926 0 : *reason = bgp_path_selection_aigp;
927 0 : if (debug)
928 0 : zlog_debug(
929 : "%s: %s wins over %s due to AIGP %" PRIu64
930 : " < %" PRIu64,
931 : pfx_buf, new_buf, exist_buf, new_aigp,
932 : exist_aigp);
933 0 : return 1;
934 : }
935 :
936 0 : if (new_aigp > exist_aigp) {
937 0 : *reason = bgp_path_selection_aigp;
938 0 : if (debug)
939 0 : zlog_debug(
940 : "%s: %s loses to %s due to AIGP %" PRIu64
941 : " > %" PRIu64,
942 : pfx_buf, new_buf, exist_buf, new_aigp,
943 : exist_aigp);
944 0 : return 0;
945 : }
946 : }
947 :
948 : /* 3. Local route check. We prefer:
949 : * - BGP_ROUTE_STATIC
950 : * - BGP_ROUTE_AGGREGATE
951 : * - BGP_ROUTE_REDISTRIBUTE
952 : */
953 0 : new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
954 : new->sub_type == BGP_ROUTE_IMPORTED);
955 0 : exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
956 : exist->sub_type == BGP_ROUTE_IMPORTED);
957 :
958 0 : if (new_origin && !exist_origin) {
959 0 : *reason = bgp_path_selection_local_route;
960 0 : if (debug)
961 0 : zlog_debug(
962 : "%s: %s wins over %s due to preferred BGP_ROUTE type",
963 : pfx_buf, new_buf, exist_buf);
964 0 : return 1;
965 : }
966 :
967 0 : if (!new_origin && exist_origin) {
968 0 : *reason = bgp_path_selection_local_route;
969 0 : if (debug)
970 0 : zlog_debug(
971 : "%s: %s loses to %s due to preferred BGP_ROUTE type",
972 : pfx_buf, new_buf, exist_buf);
973 0 : return 0;
974 : }
975 :
976 : /* Here if these are imported routes then get ultimate pi for
977 : * path compare.
978 : */
979 0 : new = bgp_get_imported_bpi_ultimate(new);
980 0 : exist = bgp_get_imported_bpi_ultimate(exist);
981 0 : newattr = new->attr;
982 0 : existattr = exist->attr;
983 :
984 : /* 4. AS path length check. */
985 0 : if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
986 0 : int exist_hops = aspath_count_hops(existattr->aspath);
987 0 : int exist_confeds = aspath_count_confeds(existattr->aspath);
988 :
989 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
990 0 : int aspath_hops;
991 :
992 0 : aspath_hops = aspath_count_hops(newattr->aspath);
993 0 : aspath_hops += aspath_count_confeds(newattr->aspath);
994 :
995 0 : if (aspath_hops < (exist_hops + exist_confeds)) {
996 0 : *reason = bgp_path_selection_confed_as_path;
997 0 : if (debug)
998 0 : zlog_debug(
999 : "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
1000 : pfx_buf, new_buf, exist_buf,
1001 : aspath_hops,
1002 : (exist_hops + exist_confeds));
1003 0 : return 1;
1004 : }
1005 :
1006 0 : if (aspath_hops > (exist_hops + exist_confeds)) {
1007 0 : *reason = bgp_path_selection_confed_as_path;
1008 0 : if (debug)
1009 0 : zlog_debug(
1010 : "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
1011 : pfx_buf, new_buf, exist_buf,
1012 : aspath_hops,
1013 : (exist_hops + exist_confeds));
1014 0 : return 0;
1015 : }
1016 : } else {
1017 0 : int newhops = aspath_count_hops(newattr->aspath);
1018 :
1019 0 : if (newhops < exist_hops) {
1020 0 : *reason = bgp_path_selection_as_path;
1021 0 : if (debug)
1022 0 : zlog_debug(
1023 : "%s: %s wins over %s due to aspath hopcount %d < %d",
1024 : pfx_buf, new_buf, exist_buf,
1025 : newhops, exist_hops);
1026 0 : return 1;
1027 : }
1028 :
1029 0 : if (newhops > exist_hops) {
1030 0 : *reason = bgp_path_selection_as_path;
1031 0 : if (debug)
1032 0 : zlog_debug(
1033 : "%s: %s loses to %s due to aspath hopcount %d > %d",
1034 : pfx_buf, new_buf, exist_buf,
1035 : newhops, exist_hops);
1036 0 : return 0;
1037 : }
1038 : }
1039 : }
1040 :
1041 : /* 5. Origin check. */
1042 0 : if (newattr->origin < existattr->origin) {
1043 0 : *reason = bgp_path_selection_origin;
1044 0 : if (debug)
1045 0 : zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
1046 : pfx_buf, new_buf, exist_buf,
1047 : bgp_origin_long_str[newattr->origin],
1048 : bgp_origin_long_str[existattr->origin]);
1049 0 : return 1;
1050 : }
1051 :
1052 0 : if (newattr->origin > existattr->origin) {
1053 0 : *reason = bgp_path_selection_origin;
1054 0 : if (debug)
1055 0 : zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
1056 : pfx_buf, new_buf, exist_buf,
1057 : bgp_origin_long_str[newattr->origin],
1058 : bgp_origin_long_str[existattr->origin]);
1059 0 : return 0;
1060 : }
1061 :
1062 : /* 6. MED check. */
1063 0 : internal_as_route = (aspath_count_hops(newattr->aspath) == 0
1064 0 : && aspath_count_hops(existattr->aspath) == 0);
1065 0 : confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
1066 0 : && aspath_count_confeds(existattr->aspath) > 0
1067 0 : && aspath_count_hops(newattr->aspath) == 0
1068 0 : && aspath_count_hops(existattr->aspath) == 0);
1069 :
1070 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1071 0 : || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
1072 0 : || aspath_cmp_left(newattr->aspath, existattr->aspath)
1073 0 : || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1074 0 : || internal_as_route) {
1075 0 : new_med = bgp_med_value(new->attr, bgp);
1076 0 : exist_med = bgp_med_value(exist->attr, bgp);
1077 :
1078 0 : if (new_med < exist_med) {
1079 0 : *reason = bgp_path_selection_med;
1080 0 : if (debug)
1081 0 : zlog_debug(
1082 : "%s: %s wins over %s due to MED %d < %d",
1083 : pfx_buf, new_buf, exist_buf, new_med,
1084 : exist_med);
1085 0 : return 1;
1086 : }
1087 :
1088 0 : if (new_med > exist_med) {
1089 0 : *reason = bgp_path_selection_med;
1090 0 : if (debug)
1091 0 : zlog_debug(
1092 : "%s: %s loses to %s due to MED %d > %d",
1093 : pfx_buf, new_buf, exist_buf, new_med,
1094 : exist_med);
1095 0 : return 0;
1096 : }
1097 : }
1098 :
1099 : /* 7. Peer type check. */
1100 0 : new_sort = new->peer->sort;
1101 0 : exist_sort = exist->peer->sort;
1102 :
1103 0 : if (new_sort == BGP_PEER_EBGP
1104 0 : && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
1105 0 : *reason = bgp_path_selection_peer;
1106 0 : if (debug)
1107 0 : zlog_debug(
1108 : "%s: %s wins over %s due to eBGP peer > iBGP peer",
1109 : pfx_buf, new_buf, exist_buf);
1110 0 : if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1111 : return 1;
1112 : peer_sort_ret = 1;
1113 : }
1114 :
1115 0 : if (exist_sort == BGP_PEER_EBGP
1116 0 : && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
1117 0 : *reason = bgp_path_selection_peer;
1118 0 : if (debug)
1119 0 : zlog_debug(
1120 : "%s: %s loses to %s due to iBGP peer < eBGP peer",
1121 : pfx_buf, new_buf, exist_buf);
1122 0 : if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1123 : return 0;
1124 : peer_sort_ret = 0;
1125 : }
1126 :
1127 : /* 8. IGP metric check. */
1128 0 : newm = existm = 0;
1129 :
1130 0 : if (new->extra)
1131 0 : newm = new->extra->igpmetric;
1132 0 : if (exist->extra)
1133 0 : existm = exist->extra->igpmetric;
1134 :
1135 0 : if (newm < existm) {
1136 0 : if (debug && peer_sort_ret < 0)
1137 0 : zlog_debug(
1138 : "%s: %s wins over %s due to IGP metric %u < %u",
1139 : pfx_buf, new_buf, exist_buf, newm, existm);
1140 : igp_metric_ret = 1;
1141 : }
1142 :
1143 0 : if (newm > existm) {
1144 0 : if (debug && peer_sort_ret < 0)
1145 0 : zlog_debug(
1146 : "%s: %s loses to %s due to IGP metric %u > %u",
1147 : pfx_buf, new_buf, exist_buf, newm, existm);
1148 : igp_metric_ret = 0;
1149 : }
1150 :
1151 : /* 9. Same IGP metric. Compare the cluster list length as
1152 : representative of IGP hops metric. Rewrite the metric value
1153 : pair (newm, existm) with the cluster list length. Prefer the
1154 : path with smaller cluster list length. */
1155 0 : if (newm == existm) {
1156 0 : if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1157 0 : peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1158 0 : (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
1159 0 : newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1160 0 : existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1161 :
1162 0 : if (newm < existm) {
1163 0 : if (debug && peer_sort_ret < 0)
1164 0 : zlog_debug(
1165 : "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1166 : pfx_buf, new_buf, exist_buf,
1167 : newm, existm);
1168 : igp_metric_ret = 1;
1169 : }
1170 :
1171 0 : if (newm > existm) {
1172 0 : if (debug && peer_sort_ret < 0)
1173 0 : zlog_debug(
1174 : "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1175 : pfx_buf, new_buf, exist_buf,
1176 : newm, existm);
1177 : igp_metric_ret = 0;
1178 : }
1179 : }
1180 : }
1181 :
1182 : /* 10. confed-external vs. confed-internal */
1183 0 : if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1184 0 : if (new_sort == BGP_PEER_CONFED
1185 0 : && exist_sort == BGP_PEER_IBGP) {
1186 0 : *reason = bgp_path_selection_confed;
1187 0 : if (debug)
1188 0 : zlog_debug(
1189 : "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1190 : pfx_buf, new_buf, exist_buf);
1191 0 : if (!CHECK_FLAG(bgp->flags,
1192 : BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1193 : return 1;
1194 : peer_sort_ret = 1;
1195 : }
1196 :
1197 0 : if (exist_sort == BGP_PEER_CONFED
1198 0 : && new_sort == BGP_PEER_IBGP) {
1199 0 : *reason = bgp_path_selection_confed;
1200 0 : if (debug)
1201 0 : zlog_debug(
1202 : "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1203 : pfx_buf, new_buf, exist_buf);
1204 0 : if (!CHECK_FLAG(bgp->flags,
1205 : BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1206 : return 0;
1207 : peer_sort_ret = 0;
1208 : }
1209 : }
1210 :
1211 : /* 11. Maximum path check. */
1212 0 : if (newm == existm) {
1213 : /* If one path has a label but the other does not, do not treat
1214 : * them as equals for multipath
1215 : */
1216 0 : if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
1217 0 : != (exist->extra
1218 0 : && bgp_is_valid_label(&exist->extra->label[0]))) {
1219 0 : if (debug)
1220 0 : zlog_debug(
1221 : "%s: %s and %s cannot be multipath, one has a label while the other does not",
1222 : pfx_buf, new_buf, exist_buf);
1223 0 : } else if (CHECK_FLAG(bgp->flags,
1224 : BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
1225 :
1226 : /*
1227 : * For the two paths, all comparison steps till IGP
1228 : * metric
1229 : * have succeeded - including AS_PATH hop count. Since
1230 : * 'bgp
1231 : * bestpath as-path multipath-relax' knob is on, we
1232 : * don't need
1233 : * an exact match of AS_PATH. Thus, mark the paths are
1234 : * equal.
1235 : * That will trigger both these paths to get into the
1236 : * multipath
1237 : * array.
1238 : */
1239 0 : *paths_eq = 1;
1240 :
1241 0 : if (debug)
1242 0 : zlog_debug(
1243 : "%s: %s and %s are equal via multipath-relax",
1244 : pfx_buf, new_buf, exist_buf);
1245 0 : } else if (new->peer->sort == BGP_PEER_IBGP) {
1246 0 : if (aspath_cmp(new->attr->aspath,
1247 0 : exist->attr->aspath)) {
1248 0 : *paths_eq = 1;
1249 :
1250 0 : if (debug)
1251 0 : zlog_debug(
1252 : "%s: %s and %s are equal via matching aspaths",
1253 : pfx_buf, new_buf, exist_buf);
1254 : }
1255 0 : } else if (new->peer->as == exist->peer->as) {
1256 0 : *paths_eq = 1;
1257 :
1258 0 : if (debug)
1259 0 : zlog_debug(
1260 : "%s: %s and %s are equal via same remote-as",
1261 : pfx_buf, new_buf, exist_buf);
1262 : }
1263 : } else {
1264 : /*
1265 : * TODO: If unequal cost ibgp multipath is enabled we can
1266 : * mark the paths as equal here instead of returning
1267 : */
1268 :
1269 : /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1270 : * if either step 7 or 10 (peer type checks) yielded a winner,
1271 : * that result was returned immediately. Returning from step 10
1272 : * ignored the return value computed in steps 8 and 9 (IGP
1273 : * metric checks). In order to preserve that behavior, if
1274 : * peer_sort_ret is set, return that rather than igp_metric_ret.
1275 : */
1276 0 : ret = peer_sort_ret;
1277 0 : if (peer_sort_ret < 0) {
1278 0 : ret = igp_metric_ret;
1279 0 : if (debug) {
1280 0 : if (ret == 1)
1281 0 : zlog_debug(
1282 : "%s: %s wins over %s after IGP metric comparison",
1283 : pfx_buf, new_buf, exist_buf);
1284 : else
1285 0 : zlog_debug(
1286 : "%s: %s loses to %s after IGP metric comparison",
1287 : pfx_buf, new_buf, exist_buf);
1288 : }
1289 0 : *reason = bgp_path_selection_igp_metric;
1290 : }
1291 0 : return ret;
1292 : }
1293 :
1294 : /*
1295 : * At this point, the decision whether to set *paths_eq = 1 has been
1296 : * completed. If we deferred returning because of bestpath peer-type
1297 : * relax configuration, return now.
1298 : */
1299 0 : if (peer_sort_ret >= 0)
1300 : return peer_sort_ret;
1301 :
1302 : /* 12. If both paths are external, prefer the path that was received
1303 : first (the oldest one). This step minimizes route-flap, since a
1304 : newer path won't displace an older one, even if it was the
1305 : preferred route based on the additional decision criteria below. */
1306 0 : if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
1307 0 : && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1308 0 : if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
1309 0 : *reason = bgp_path_selection_older;
1310 0 : if (debug)
1311 0 : zlog_debug(
1312 : "%s: %s wins over %s due to oldest external",
1313 : pfx_buf, new_buf, exist_buf);
1314 0 : return 1;
1315 : }
1316 :
1317 0 : if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
1318 0 : *reason = bgp_path_selection_older;
1319 0 : if (debug)
1320 0 : zlog_debug(
1321 : "%s: %s loses to %s due to oldest external",
1322 : pfx_buf, new_buf, exist_buf);
1323 0 : return 0;
1324 : }
1325 : }
1326 :
1327 : /* 13. Router-ID comparison. */
1328 : /* If one of the paths is "stale", the corresponding peer router-id will
1329 : * be 0 and would always win over the other path. If originator id is
1330 : * used for the comparison, it will decide which path is better.
1331 : */
1332 0 : if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1333 0 : new_id.s_addr = newattr->originator_id.s_addr;
1334 : else
1335 0 : new_id.s_addr = new->peer->remote_id.s_addr;
1336 0 : if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1337 0 : exist_id.s_addr = existattr->originator_id.s_addr;
1338 : else
1339 0 : exist_id.s_addr = exist->peer->remote_id.s_addr;
1340 :
1341 0 : if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
1342 0 : *reason = bgp_path_selection_router_id;
1343 0 : if (debug)
1344 0 : zlog_debug(
1345 : "%s: %s wins over %s due to Router-ID comparison",
1346 : pfx_buf, new_buf, exist_buf);
1347 0 : return 1;
1348 : }
1349 :
1350 0 : if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
1351 0 : *reason = bgp_path_selection_router_id;
1352 0 : if (debug)
1353 0 : zlog_debug(
1354 : "%s: %s loses to %s due to Router-ID comparison",
1355 : pfx_buf, new_buf, exist_buf);
1356 0 : return 0;
1357 : }
1358 :
1359 : /* 14. Cluster length comparison. */
1360 0 : new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1361 0 : exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1362 :
1363 0 : if (new_cluster < exist_cluster) {
1364 0 : *reason = bgp_path_selection_cluster_length;
1365 0 : if (debug)
1366 0 : zlog_debug(
1367 : "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1368 : pfx_buf, new_buf, exist_buf, new_cluster,
1369 : exist_cluster);
1370 0 : return 1;
1371 : }
1372 :
1373 0 : if (new_cluster > exist_cluster) {
1374 0 : *reason = bgp_path_selection_cluster_length;
1375 0 : if (debug)
1376 0 : zlog_debug(
1377 : "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1378 : pfx_buf, new_buf, exist_buf, new_cluster,
1379 : exist_cluster);
1380 0 : return 0;
1381 : }
1382 :
1383 : /* 15. Neighbor address comparison. */
1384 : /* Do this only if neither path is "stale" as stale paths do not have
1385 : * valid peer information (as the connection may or may not be up).
1386 : */
1387 0 : if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
1388 0 : *reason = bgp_path_selection_stale;
1389 0 : if (debug)
1390 0 : zlog_debug(
1391 : "%s: %s wins over %s due to latter path being STALE",
1392 : pfx_buf, new_buf, exist_buf);
1393 0 : return 1;
1394 : }
1395 :
1396 0 : if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
1397 0 : *reason = bgp_path_selection_stale;
1398 0 : if (debug)
1399 0 : zlog_debug(
1400 : "%s: %s loses to %s due to former path being STALE",
1401 : pfx_buf, new_buf, exist_buf);
1402 0 : return 0;
1403 : }
1404 :
1405 : /* locally configured routes to advertise do not have su_remote */
1406 0 : if (new->peer->su_remote == NULL) {
1407 0 : *reason = bgp_path_selection_local_configured;
1408 0 : return 0;
1409 : }
1410 0 : if (exist->peer->su_remote == NULL) {
1411 0 : *reason = bgp_path_selection_local_configured;
1412 0 : return 1;
1413 : }
1414 :
1415 0 : ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1416 :
1417 0 : if (ret == 1) {
1418 0 : *reason = bgp_path_selection_neighbor_ip;
1419 0 : if (debug)
1420 0 : zlog_debug(
1421 : "%s: %s loses to %s due to Neighor IP comparison",
1422 : pfx_buf, new_buf, exist_buf);
1423 0 : return 0;
1424 : }
1425 :
1426 0 : if (ret == -1) {
1427 0 : *reason = bgp_path_selection_neighbor_ip;
1428 0 : if (debug)
1429 0 : zlog_debug(
1430 : "%s: %s wins over %s due to Neighor IP comparison",
1431 : pfx_buf, new_buf, exist_buf);
1432 0 : return 1;
1433 : }
1434 :
1435 0 : *reason = bgp_path_selection_default;
1436 0 : if (debug)
1437 0 : zlog_debug("%s: %s wins over %s due to nothing left to compare",
1438 : pfx_buf, new_buf, exist_buf);
1439 :
1440 : return 1;
1441 : }
1442 :
1443 :
1444 0 : int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1445 : struct bgp_path_info *exist, int *paths_eq)
1446 : {
1447 0 : enum bgp_path_selection_reason reason;
1448 0 : char pfx_buf[PREFIX2STR_BUFFER];
1449 :
1450 0 : return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1451 : AFI_L2VPN, SAFI_EVPN, &reason);
1452 : }
1453 :
1454 : /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1455 : * is preferred, or 0 if they are the same (usually will only occur if
1456 : * multipath is enabled
1457 : * This version is compatible with */
1458 0 : int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1459 : struct bgp_path_info *exist, char *pfx_buf,
1460 : afi_t afi, safi_t safi,
1461 : enum bgp_path_selection_reason *reason)
1462 : {
1463 0 : int paths_eq;
1464 0 : int ret;
1465 0 : ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
1466 : afi, safi, reason);
1467 :
1468 0 : if (paths_eq)
1469 : ret = 0;
1470 : else {
1471 0 : if (ret == 1)
1472 : ret = -1;
1473 : else
1474 0 : ret = 1;
1475 : }
1476 0 : return ret;
1477 : }
1478 :
1479 1 : static enum filter_type bgp_input_filter(struct peer *peer,
1480 : const struct prefix *p,
1481 : struct attr *attr, afi_t afi,
1482 : safi_t safi)
1483 : {
1484 1 : struct bgp_filter *filter;
1485 1 : enum filter_type ret = FILTER_PERMIT;
1486 :
1487 1 : filter = &peer->filter[afi][safi];
1488 :
1489 : #define FILTER_EXIST_WARN(F, f, filter) \
1490 : if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1491 : zlog_debug("%s: Could not find configured input %s-list %s!", \
1492 : peer->host, #f, F##_IN_NAME(filter));
1493 :
1494 1 : if (DISTRIBUTE_IN_NAME(filter)) {
1495 0 : FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1496 :
1497 0 : if (access_list_apply(DISTRIBUTE_IN(filter), p)
1498 : == FILTER_DENY) {
1499 0 : ret = FILTER_DENY;
1500 0 : goto done;
1501 : }
1502 : }
1503 :
1504 1 : if (PREFIX_LIST_IN_NAME(filter)) {
1505 0 : FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1506 :
1507 0 : if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1508 : == PREFIX_DENY) {
1509 0 : ret = FILTER_DENY;
1510 0 : goto done;
1511 : }
1512 : }
1513 :
1514 1 : if (FILTER_LIST_IN_NAME(filter)) {
1515 0 : FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1516 :
1517 0 : if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1518 : == AS_FILTER_DENY) {
1519 0 : ret = FILTER_DENY;
1520 0 : goto done;
1521 : }
1522 : }
1523 :
1524 1 : done:
1525 1 : if (frrtrace_enabled(frr_bgp, input_filter)) {
1526 1 : char pfxprint[PREFIX2STR_BUFFER];
1527 :
1528 1 : prefix2str(p, pfxprint, sizeof(pfxprint));
1529 1 : frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1530 : ret == FILTER_PERMIT ? "permit" : "deny");
1531 : }
1532 :
1533 1 : return ret;
1534 : #undef FILTER_EXIST_WARN
1535 : }
1536 :
1537 0 : static enum filter_type bgp_output_filter(struct peer *peer,
1538 : const struct prefix *p,
1539 : struct attr *attr, afi_t afi,
1540 : safi_t safi)
1541 : {
1542 0 : struct bgp_filter *filter;
1543 0 : enum filter_type ret = FILTER_PERMIT;
1544 :
1545 0 : filter = &peer->filter[afi][safi];
1546 :
1547 : #define FILTER_EXIST_WARN(F, f, filter) \
1548 : if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1549 : zlog_debug("%s: Could not find configured output %s-list %s!", \
1550 : peer->host, #f, F##_OUT_NAME(filter));
1551 :
1552 0 : if (DISTRIBUTE_OUT_NAME(filter)) {
1553 0 : FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1554 :
1555 0 : if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1556 : == FILTER_DENY) {
1557 0 : ret = FILTER_DENY;
1558 0 : goto done;
1559 : }
1560 : }
1561 :
1562 0 : if (PREFIX_LIST_OUT_NAME(filter)) {
1563 0 : FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1564 :
1565 0 : if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1566 : == PREFIX_DENY) {
1567 0 : ret = FILTER_DENY;
1568 0 : goto done;
1569 : }
1570 : }
1571 :
1572 0 : if (FILTER_LIST_OUT_NAME(filter)) {
1573 0 : FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1574 :
1575 0 : if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1576 : == AS_FILTER_DENY) {
1577 0 : ret = FILTER_DENY;
1578 0 : goto done;
1579 : }
1580 : }
1581 :
1582 0 : if (frrtrace_enabled(frr_bgp, output_filter)) {
1583 0 : char pfxprint[PREFIX2STR_BUFFER];
1584 :
1585 0 : prefix2str(p, pfxprint, sizeof(pfxprint));
1586 0 : frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1587 : ret == FILTER_PERMIT ? "permit" : "deny");
1588 : }
1589 :
1590 0 : done:
1591 0 : return ret;
1592 : #undef FILTER_EXIST_WARN
1593 : }
1594 :
1595 : /* If community attribute includes no_export then return 1. */
1596 0 : static bool bgp_community_filter(struct peer *peer, struct attr *attr)
1597 : {
1598 0 : if (bgp_attr_get_community(attr)) {
1599 : /* NO_ADVERTISE check. */
1600 0 : if (community_include(bgp_attr_get_community(attr),
1601 : COMMUNITY_NO_ADVERTISE))
1602 : return true;
1603 :
1604 : /* NO_EXPORT check. */
1605 0 : if (peer->sort == BGP_PEER_EBGP &&
1606 0 : community_include(bgp_attr_get_community(attr),
1607 : COMMUNITY_NO_EXPORT))
1608 : return true;
1609 :
1610 : /* NO_EXPORT_SUBCONFED check. */
1611 0 : if (peer->sort == BGP_PEER_EBGP
1612 0 : || peer->sort == BGP_PEER_CONFED)
1613 0 : if (community_include(bgp_attr_get_community(attr),
1614 : COMMUNITY_NO_EXPORT_SUBCONFED))
1615 : return true;
1616 : }
1617 : return false;
1618 : }
1619 :
1620 : /* Route reflection loop check. */
1621 1 : static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
1622 : {
1623 1 : struct in_addr cluster_id;
1624 1 : struct cluster_list *cluster = bgp_attr_get_cluster(attr);
1625 :
1626 1 : if (cluster) {
1627 0 : if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1628 0 : cluster_id = peer->bgp->cluster_id;
1629 : else
1630 0 : cluster_id = peer->bgp->router_id;
1631 :
1632 0 : if (cluster_loop_check(cluster, cluster_id))
1633 : return true;
1634 : }
1635 : return false;
1636 : }
1637 :
1638 1 : static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1639 : {
1640 1 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1641 0 : if (peer->local_role == ROLE_PROVIDER ||
1642 : peer->local_role == ROLE_RS_SERVER)
1643 : return true;
1644 0 : if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1645 : return true;
1646 : return false;
1647 : }
1648 1 : if (peer->local_role == ROLE_CUSTOMER ||
1649 1 : peer->local_role == ROLE_PEER ||
1650 : peer->local_role == ROLE_RS_CLIENT) {
1651 0 : attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1652 0 : attr->otc = peer->as;
1653 : }
1654 : return false;
1655 : }
1656 :
1657 0 : static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1658 : {
1659 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1660 0 : if (peer->local_role == ROLE_CUSTOMER ||
1661 0 : peer->local_role == ROLE_RS_CLIENT ||
1662 : peer->local_role == ROLE_PEER)
1663 : return true;
1664 : return false;
1665 : }
1666 0 : if (peer->local_role == ROLE_PROVIDER ||
1667 0 : peer->local_role == ROLE_PEER ||
1668 : peer->local_role == ROLE_RS_SERVER) {
1669 0 : attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1670 0 : attr->otc = peer->bgp->as;
1671 : }
1672 : return false;
1673 : }
1674 :
1675 1 : static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1676 : {
1677 1 : return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1678 : }
1679 :
1680 1 : static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
1681 : struct attr *attr, afi_t afi, safi_t safi,
1682 : const char *rmap_name, mpls_label_t *label,
1683 : uint32_t num_labels, struct bgp_dest *dest)
1684 : {
1685 1 : struct bgp_filter *filter;
1686 1 : struct bgp_path_info rmap_path = { 0 };
1687 1 : struct bgp_path_info_extra extra = { 0 };
1688 1 : route_map_result_t ret;
1689 1 : struct route_map *rmap = NULL;
1690 :
1691 1 : filter = &peer->filter[afi][safi];
1692 :
1693 : /* Apply default weight value. */
1694 1 : if (peer->weight[afi][safi])
1695 0 : attr->weight = peer->weight[afi][safi];
1696 :
1697 1 : if (rmap_name) {
1698 0 : rmap = route_map_lookup_by_name(rmap_name);
1699 :
1700 0 : if (rmap == NULL)
1701 : return RMAP_DENY;
1702 : } else {
1703 1 : if (ROUTE_MAP_IN_NAME(filter)) {
1704 0 : rmap = ROUTE_MAP_IN(filter);
1705 :
1706 0 : if (rmap == NULL)
1707 : return RMAP_DENY;
1708 : }
1709 : }
1710 :
1711 : /* Route map apply. */
1712 : if (rmap) {
1713 0 : memset(&rmap_path, 0, sizeof(rmap_path));
1714 : /* Duplicate current value to new structure for modification. */
1715 0 : rmap_path.peer = peer;
1716 0 : rmap_path.attr = attr;
1717 0 : rmap_path.extra = &extra;
1718 0 : rmap_path.net = dest;
1719 :
1720 0 : extra.num_labels = num_labels;
1721 0 : if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1722 0 : memcpy(extra.label, label,
1723 : num_labels * sizeof(mpls_label_t));
1724 :
1725 0 : SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
1726 :
1727 : /* Apply BGP route map to the attribute. */
1728 0 : ret = route_map_apply(rmap, p, &rmap_path);
1729 :
1730 0 : peer->rmap_type = 0;
1731 :
1732 0 : if (ret == RMAP_DENYMATCH)
1733 : return RMAP_DENY;
1734 : }
1735 : return RMAP_PERMIT;
1736 : }
1737 :
1738 0 : static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
1739 : struct attr *attr, afi_t afi, safi_t safi,
1740 : const char *rmap_name)
1741 : {
1742 0 : struct bgp_path_info rmap_path;
1743 0 : route_map_result_t ret;
1744 0 : struct route_map *rmap = NULL;
1745 0 : uint8_t rmap_type;
1746 :
1747 : /*
1748 : * So if we get to this point and have no rmap_name
1749 : * we want to just show the output as it currently
1750 : * exists.
1751 : */
1752 0 : if (!rmap_name)
1753 : return RMAP_PERMIT;
1754 :
1755 : /* Apply default weight value. */
1756 0 : if (peer->weight[afi][safi])
1757 0 : attr->weight = peer->weight[afi][safi];
1758 :
1759 0 : rmap = route_map_lookup_by_name(rmap_name);
1760 :
1761 : /*
1762 : * If we have a route map name and we do not find
1763 : * the routemap that means we have an implicit
1764 : * deny.
1765 : */
1766 0 : if (rmap == NULL)
1767 : return RMAP_DENY;
1768 :
1769 0 : memset(&rmap_path, 0, sizeof(rmap_path));
1770 : /* Route map apply. */
1771 : /* Duplicate current value to new structure for modification. */
1772 0 : rmap_path.peer = peer;
1773 0 : rmap_path.attr = attr;
1774 :
1775 0 : rmap_type = peer->rmap_type;
1776 0 : SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
1777 :
1778 : /* Apply BGP route map to the attribute. */
1779 0 : ret = route_map_apply(rmap, p, &rmap_path);
1780 :
1781 0 : peer->rmap_type = rmap_type;
1782 :
1783 0 : if (ret == RMAP_DENYMATCH)
1784 : /*
1785 : * caller has multiple error paths with bgp_attr_flush()
1786 : */
1787 : return RMAP_DENY;
1788 :
1789 : return RMAP_PERMIT;
1790 : }
1791 :
1792 : /* If this is an EBGP peer with remove-private-AS */
1793 0 : static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1794 : struct peer *peer, struct attr *attr)
1795 : {
1796 0 : if (peer->sort == BGP_PEER_EBGP
1797 0 : && (peer_af_flag_check(peer, afi, safi,
1798 : PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1799 0 : || peer_af_flag_check(peer, afi, safi,
1800 : PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1801 0 : || peer_af_flag_check(peer, afi, safi,
1802 : PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1803 0 : || peer_af_flag_check(peer, afi, safi,
1804 : PEER_FLAG_REMOVE_PRIVATE_AS))) {
1805 : // Take action on the entire aspath
1806 0 : if (peer_af_flag_check(peer, afi, safi,
1807 : PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1808 0 : || peer_af_flag_check(peer, afi, safi,
1809 : PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1810 0 : if (peer_af_flag_check(
1811 : peer, afi, safi,
1812 : PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1813 0 : attr->aspath = aspath_replace_private_asns(
1814 : attr->aspath, bgp->as, peer->as);
1815 :
1816 : /*
1817 : * Even if the aspath consists of just private ASNs we
1818 : * need to walk the AS-Path to maintain all instances
1819 : * of the peer's ASN to break possible loops.
1820 : */
1821 : else
1822 0 : attr->aspath = aspath_remove_private_asns(
1823 : attr->aspath, peer->as);
1824 : }
1825 :
1826 : // 'all' was not specified so the entire aspath must be private
1827 : // ASNs
1828 : // for us to do anything
1829 0 : else if (aspath_private_as_check(attr->aspath)) {
1830 0 : if (peer_af_flag_check(
1831 : peer, afi, safi,
1832 : PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1833 0 : attr->aspath = aspath_replace_private_asns(
1834 : attr->aspath, bgp->as, peer->as);
1835 : else
1836 : /*
1837 : * Walk the aspath to retain any instances of
1838 : * the peer_asn
1839 : */
1840 0 : attr->aspath = aspath_remove_private_asns(
1841 : attr->aspath, peer->as);
1842 : }
1843 : }
1844 0 : }
1845 :
1846 : /* If this is an EBGP peer with as-override */
1847 0 : static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1848 : struct peer *peer, struct attr *attr)
1849 : {
1850 0 : struct aspath *aspath;
1851 :
1852 0 : if (peer->sort == BGP_PEER_EBGP &&
1853 0 : peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1854 0 : if (attr->aspath->refcnt)
1855 0 : aspath = aspath_dup(attr->aspath);
1856 : else
1857 : aspath = attr->aspath;
1858 :
1859 0 : attr->aspath = aspath_intern(
1860 : aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1861 :
1862 0 : aspath_free(aspath);
1863 : }
1864 0 : }
1865 :
1866 0 : void bgp_attr_add_llgr_community(struct attr *attr)
1867 : {
1868 0 : struct community *old;
1869 0 : struct community *new;
1870 0 : struct community *merge;
1871 0 : struct community *llgr;
1872 :
1873 0 : old = bgp_attr_get_community(attr);
1874 0 : llgr = community_str2com("llgr-stale");
1875 :
1876 0 : assert(llgr);
1877 :
1878 0 : if (old) {
1879 0 : merge = community_merge(community_dup(old), llgr);
1880 :
1881 0 : if (old->refcnt == 0)
1882 0 : community_free(&old);
1883 :
1884 0 : new = community_uniq_sort(merge);
1885 0 : community_free(&merge);
1886 : } else {
1887 0 : new = community_dup(llgr);
1888 : }
1889 :
1890 0 : community_free(&llgr);
1891 :
1892 0 : bgp_attr_set_community(attr, new);
1893 0 : }
1894 :
1895 0 : void bgp_attr_add_gshut_community(struct attr *attr)
1896 : {
1897 0 : struct community *old;
1898 0 : struct community *new;
1899 0 : struct community *merge;
1900 0 : struct community *gshut;
1901 :
1902 0 : old = bgp_attr_get_community(attr);
1903 0 : gshut = community_str2com("graceful-shutdown");
1904 :
1905 0 : assert(gshut);
1906 :
1907 0 : if (old) {
1908 0 : merge = community_merge(community_dup(old), gshut);
1909 :
1910 0 : if (old->refcnt == 0)
1911 0 : community_free(&old);
1912 :
1913 0 : new = community_uniq_sort(merge);
1914 0 : community_free(&merge);
1915 : } else {
1916 0 : new = community_dup(gshut);
1917 : }
1918 :
1919 0 : community_free(&gshut);
1920 0 : bgp_attr_set_community(attr, new);
1921 :
1922 : /* When we add the graceful-shutdown community we must also
1923 : * lower the local-preference */
1924 0 : attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1925 0 : attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1926 0 : }
1927 :
1928 :
1929 : /* Notify BGP Conditional advertisement scanner process. */
1930 0 : void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1931 : {
1932 0 : struct peer *peer = SUBGRP_PEER(subgrp);
1933 0 : afi_t afi = SUBGRP_AFI(subgrp);
1934 0 : safi_t safi = SUBGRP_SAFI(subgrp);
1935 0 : struct bgp_filter *filter = &peer->filter[afi][safi];
1936 :
1937 0 : if (!ADVERTISE_MAP_NAME(filter))
1938 : return;
1939 :
1940 0 : if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1941 : return;
1942 :
1943 0 : peer->advmap_table_change = true;
1944 : }
1945 :
1946 :
1947 0 : void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
1948 : {
1949 0 : if (family == AF_INET) {
1950 0 : attr->nexthop.s_addr = INADDR_ANY;
1951 0 : attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
1952 : }
1953 0 : if (family == AF_INET6)
1954 0 : memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
1955 0 : if (family == AF_EVPN)
1956 0 : memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
1957 0 : }
1958 :
1959 0 : bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
1960 : struct update_subgroup *subgrp,
1961 : const struct prefix *p, struct attr *attr,
1962 : struct attr *post_attr)
1963 : {
1964 0 : struct bgp_filter *filter;
1965 0 : struct peer *from;
1966 0 : struct peer *peer;
1967 0 : struct peer *onlypeer;
1968 0 : struct bgp *bgp;
1969 0 : struct attr *piattr;
1970 0 : route_map_result_t ret;
1971 0 : int transparent;
1972 0 : int reflect;
1973 0 : afi_t afi;
1974 0 : safi_t safi;
1975 0 : int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1976 0 : bool nh_reset = false;
1977 0 : uint64_t cum_bw;
1978 :
1979 0 : if (DISABLE_BGP_ANNOUNCE)
1980 : return false;
1981 :
1982 0 : afi = SUBGRP_AFI(subgrp);
1983 0 : safi = SUBGRP_SAFI(subgrp);
1984 0 : peer = SUBGRP_PEER(subgrp);
1985 0 : onlypeer = NULL;
1986 0 : if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1987 0 : onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1988 :
1989 0 : from = pi->peer;
1990 0 : filter = &peer->filter[afi][safi];
1991 0 : bgp = SUBGRP_INST(subgrp);
1992 0 : piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1993 0 : : pi->attr;
1994 :
1995 0 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1996 0 : peer->pmax_out[afi][safi] != 0 &&
1997 0 : subgrp->pscount >= peer->pmax_out[afi][safi]) {
1998 0 : if (BGP_DEBUG(update, UPDATE_OUT) ||
1999 : BGP_DEBUG(update, UPDATE_PREFIX)) {
2000 0 : zlog_debug("%s reached maximum prefix to be send (%u)",
2001 : peer->host, peer->pmax_out[afi][safi]);
2002 : }
2003 0 : return false;
2004 : }
2005 :
2006 : #ifdef ENABLE_BGP_VNC
2007 0 : if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
2008 0 : && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
2009 0 : || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
2010 :
2011 : /*
2012 : * direct and direct_ext type routes originate internally even
2013 : * though they can have peer pointers that reference other
2014 : * systems
2015 : */
2016 0 : zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
2017 : __func__, p);
2018 0 : samepeer_safe = 1;
2019 : }
2020 : #endif
2021 :
2022 0 : if (((afi == AFI_IP) || (afi == AFI_IP6))
2023 0 : && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
2024 : && (pi->type == ZEBRA_ROUTE_BGP)
2025 0 : && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
2026 :
2027 : /* Applies to routes leaked vpn->vrf and vrf->vpn */
2028 :
2029 0 : samepeer_safe = 1;
2030 : }
2031 :
2032 : /* With addpath we may be asked to TX all kinds of paths so make sure
2033 : * pi is valid */
2034 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
2035 : || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
2036 0 : || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
2037 : return false;
2038 : }
2039 :
2040 : /* If this is not the bestpath then check to see if there is an enabled
2041 : * addpath
2042 : * feature that requires us to advertise it */
2043 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2044 0 : if (!bgp_addpath_capable(pi, peer, afi, safi))
2045 : return false;
2046 :
2047 : /* Aggregate-address suppress check. */
2048 0 : if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
2049 : return false;
2050 :
2051 : /*
2052 : * If we are doing VRF 2 VRF leaking via the import
2053 : * statement, we want to prevent the route going
2054 : * off box as that the RT and RD created are localy
2055 : * significant and globaly useless.
2056 : */
2057 0 : if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
2058 0 : && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
2059 : return false;
2060 :
2061 : /* If it's labeled safi, make sure the route has a valid label. */
2062 0 : if (safi == SAFI_LABELED_UNICAST) {
2063 0 : mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
2064 0 : if (!bgp_is_valid_label(&label)) {
2065 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2066 0 : zlog_debug("u%" PRIu64 ":s%" PRIu64
2067 : " %pFX is filtered - no label (%p)",
2068 : subgrp->update_group->id, subgrp->id,
2069 : p, &label);
2070 0 : return false;
2071 : }
2072 : }
2073 :
2074 : /* Do not send back route to sender. */
2075 0 : if (onlypeer && from == onlypeer) {
2076 : return false;
2077 : }
2078 :
2079 : /* Do not send the default route in the BGP table if the neighbor is
2080 : * configured for default-originate */
2081 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
2082 : PEER_FLAG_DEFAULT_ORIGINATE)) {
2083 0 : if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
2084 : return false;
2085 0 : else if (p->family == AF_INET6 && p->prefixlen == 0)
2086 : return false;
2087 : }
2088 :
2089 : /* Transparency check. */
2090 0 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2091 0 : && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2092 : transparent = 1;
2093 : else
2094 0 : transparent = 0;
2095 :
2096 : /* If community is not disabled check the no-export and local. */
2097 0 : if (!transparent && bgp_community_filter(peer, piattr)) {
2098 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2099 0 : zlog_debug("%s: community filter check fail for %pFX",
2100 : __func__, p);
2101 0 : return false;
2102 : }
2103 :
2104 : /* If the attribute has originator-id and it is same as remote
2105 : peer's id. */
2106 0 : if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2107 0 : && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
2108 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2109 0 : zlog_debug(
2110 : "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2111 : onlypeer, p);
2112 0 : return false;
2113 : }
2114 :
2115 : /* ORF prefix-list filter check */
2116 0 : if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2117 0 : && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2118 0 : || CHECK_FLAG(peer->af_cap[afi][safi],
2119 : PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2120 0 : if (peer->orf_plist[afi][safi]) {
2121 0 : if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2122 : == PREFIX_DENY) {
2123 0 : if (bgp_debug_update(NULL, p,
2124 : subgrp->update_group, 0))
2125 0 : zlog_debug(
2126 : "%pBP [Update:SEND] %pFX is filtered via ORF",
2127 : peer, p);
2128 0 : return false;
2129 : }
2130 : }
2131 :
2132 : /* Output filter check. */
2133 0 : if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
2134 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2135 0 : zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2136 : p);
2137 0 : return false;
2138 : }
2139 :
2140 : /* AS path loop check. */
2141 0 : if (peer->as_path_loop_detection &&
2142 0 : aspath_loop_check(piattr->aspath, peer->as)) {
2143 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2144 0 : zlog_debug(
2145 : "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2146 : peer, peer->as);
2147 0 : return false;
2148 : }
2149 :
2150 : /* If we're a CONFED we need to loop check the CONFED ID too */
2151 0 : if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
2152 0 : if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
2153 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2154 0 : zlog_debug(
2155 : "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2156 : peer, bgp->confed_id);
2157 0 : return false;
2158 : }
2159 : }
2160 :
2161 : /* Route-Reflect check. */
2162 0 : if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2163 : reflect = 1;
2164 : else
2165 0 : reflect = 0;
2166 :
2167 : /* IBGP reflection check. */
2168 0 : if (reflect && !samepeer_safe) {
2169 : /* A route from a Client peer. */
2170 0 : if (CHECK_FLAG(from->af_flags[afi][safi],
2171 : PEER_FLAG_REFLECTOR_CLIENT)) {
2172 : /* Reflect to all the Non-Client peers and also to the
2173 : Client peers other than the originator. Originator
2174 : check
2175 : is already done. So there is noting to do. */
2176 : /* no bgp client-to-client reflection check. */
2177 0 : if (CHECK_FLAG(bgp->flags,
2178 : BGP_FLAG_NO_CLIENT_TO_CLIENT))
2179 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
2180 : PEER_FLAG_REFLECTOR_CLIENT))
2181 : return false;
2182 : } else {
2183 : /* A route from a Non-client peer. Reflect to all other
2184 : clients. */
2185 0 : if (!CHECK_FLAG(peer->af_flags[afi][safi],
2186 : PEER_FLAG_REFLECTOR_CLIENT))
2187 : return false;
2188 : }
2189 : }
2190 :
2191 : /* For modify attribute, copy it to temporary structure.
2192 : * post_attr comes from BGP conditional advertisements, where
2193 : * attributes are already processed by advertise-map route-map,
2194 : * and this needs to be saved instead of overwriting from the
2195 : * path attributes.
2196 : */
2197 0 : if (post_attr)
2198 0 : *attr = *post_attr;
2199 : else
2200 0 : *attr = *piattr;
2201 :
2202 : /* If local-preference is not set. */
2203 0 : if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2204 0 : && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2205 0 : attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2206 0 : attr->local_pref = bgp->default_local_pref;
2207 : }
2208 :
2209 : /* If originator-id is not set and the route is to be reflected,
2210 : set the originator id */
2211 0 : if (reflect
2212 0 : && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2213 0 : IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2214 0 : SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2215 : }
2216 :
2217 : /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2218 : */
2219 0 : if (peer->sort == BGP_PEER_EBGP
2220 0 : && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2221 0 : if (from != bgp->peer_self && !transparent
2222 0 : && !CHECK_FLAG(peer->af_flags[afi][safi],
2223 : PEER_FLAG_MED_UNCHANGED))
2224 0 : attr->flag &=
2225 : ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2226 : }
2227 :
2228 : /* Since the nexthop attribute can vary per peer, it is not explicitly
2229 : * set
2230 : * in announce check, only certain flags and length (or number of
2231 : * nexthops
2232 : * -- for IPv6/MP_REACH) are set here in order to guide the update
2233 : * formation
2234 : * code in setting the nexthop(s) on a per peer basis in
2235 : * reformat_peer().
2236 : * Typically, the source nexthop in the attribute is preserved but in
2237 : * the
2238 : * scenarios where we know it will always be overwritten, we reset the
2239 : * nexthop to "0" in an attempt to achieve better Update packing. An
2240 : * example of this is when a prefix from each of 2 IBGP peers needs to
2241 : * be
2242 : * announced to an EBGP peer (and they have the same attributes barring
2243 : * their nexthop).
2244 : */
2245 0 : if (reflect)
2246 0 : SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2247 :
2248 : #define NEXTHOP_IS_V6 \
2249 : ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2250 : && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2251 : || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2252 : && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2253 :
2254 : /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2255 : * if
2256 : * the peer (group) is configured to receive link-local nexthop
2257 : * unchanged
2258 : * and it is available in the prefix OR we're not reflecting the route,
2259 : * link-local nexthop address is valid and
2260 : * the peer (group) to whom we're going to announce is on a shared
2261 : * network
2262 : * and this is either a self-originated route or the peer is EBGP.
2263 : * By checking if nexthop LL address is valid we are sure that
2264 : * we do not announce LL address as `::`.
2265 : */
2266 0 : if (NEXTHOP_IS_V6) {
2267 0 : attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2268 0 : if ((CHECK_FLAG(peer->af_flags[afi][safi],
2269 : PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2270 0 : && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2271 0 : || (!reflect && !transparent
2272 0 : && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2273 0 : && peer->shared_network
2274 0 : && (from == bgp->peer_self
2275 0 : || peer->sort == BGP_PEER_EBGP))) {
2276 0 : if (safi == SAFI_MPLS_VPN)
2277 0 : attr->mp_nexthop_len =
2278 : BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
2279 : else
2280 0 : attr->mp_nexthop_len =
2281 : BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2282 : }
2283 :
2284 : /* Clear off link-local nexthop in source, whenever it is not
2285 : * needed to
2286 : * ensure more prefixes share the same attribute for
2287 : * announcement.
2288 : */
2289 0 : if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2290 : PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2291 0 : memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2292 : }
2293 :
2294 0 : if (bgp_check_role_applicability(afi, safi) &&
2295 0 : bgp_otc_egress(peer, attr))
2296 : return false;
2297 :
2298 0 : bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2299 0 : bgp_peer_as_override(bgp, afi, safi, peer, attr);
2300 :
2301 0 : if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2302 0 : filter->advmap.aname &&
2303 0 : route_map_lookup_by_name(filter->advmap.aname)) {
2304 0 : struct bgp_path_info rmap_path = {0};
2305 0 : struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2306 0 : struct attr dummy_attr = *attr;
2307 :
2308 : /* Fill temp path_info */
2309 0 : prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2310 : pi, peer, &dummy_attr);
2311 :
2312 0 : struct route_map *amap =
2313 0 : route_map_lookup_by_name(filter->advmap.aname);
2314 :
2315 0 : ret = route_map_apply(amap, p, &rmap_path);
2316 :
2317 0 : bgp_attr_flush(&dummy_attr);
2318 :
2319 : /*
2320 : * The conditional advertisement mode is Withdraw and this
2321 : * prefix is a conditional prefix. Don't advertise it
2322 : */
2323 0 : if (ret == RMAP_PERMITMATCH)
2324 0 : return false;
2325 : }
2326 :
2327 : /* Route map & unsuppress-map apply. */
2328 0 : if (!post_attr &&
2329 0 : (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
2330 0 : struct bgp_path_info rmap_path = {0};
2331 0 : struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2332 0 : struct attr dummy_attr = {0};
2333 :
2334 : /* Fill temp path_info */
2335 0 : prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2336 : pi, peer, attr);
2337 :
2338 : /* don't confuse inbound and outbound setting */
2339 0 : RESET_FLAG(attr->rmap_change_flags);
2340 :
2341 : /*
2342 : * The route reflector is not allowed to modify the attributes
2343 : * of the reflected IBGP routes unless explicitly allowed.
2344 : */
2345 0 : if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2346 0 : && !CHECK_FLAG(bgp->flags,
2347 : BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
2348 0 : dummy_attr = *attr;
2349 0 : rmap_path.attr = &dummy_attr;
2350 : }
2351 :
2352 0 : SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
2353 :
2354 0 : if (bgp_path_suppressed(pi))
2355 0 : ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
2356 : &rmap_path);
2357 : else
2358 0 : ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
2359 : &rmap_path);
2360 :
2361 0 : bgp_attr_flush(&dummy_attr);
2362 0 : peer->rmap_type = 0;
2363 :
2364 0 : if (ret == RMAP_DENYMATCH) {
2365 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2366 0 : zlog_debug(
2367 : "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2368 : peer, p, ROUTE_MAP_OUT_NAME(filter));
2369 0 : bgp_attr_flush(rmap_path.attr);
2370 0 : return false;
2371 : }
2372 : }
2373 :
2374 : /* RFC 8212 to prevent route leaks.
2375 : * This specification intends to improve this situation by requiring the
2376 : * explicit configuration of both BGP Import and Export Policies for any
2377 : * External BGP (EBGP) session such as customers, peers, or
2378 : * confederation boundaries for all enabled address families. Through
2379 : * codification of the aforementioned requirement, operators will
2380 : * benefit from consistent behavior across different BGP
2381 : * implementations.
2382 : */
2383 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
2384 0 : if (!bgp_outbound_policy_exists(peer, filter)) {
2385 0 : if (monotime_since(&bgp->ebgprequirespolicywarning,
2386 0 : NULL) > FIFTEENMINUTE2USEC ||
2387 0 : bgp->ebgprequirespolicywarning.tv_sec == 0) {
2388 0 : zlog_warn(
2389 : "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2390 0 : monotime(&bgp->ebgprequirespolicywarning);
2391 : }
2392 0 : return false;
2393 : }
2394 :
2395 : /* draft-ietf-idr-deprecate-as-set-confed-set
2396 : * Filter routes having AS_SET or AS_CONFED_SET in the path.
2397 : * Eventually, This document (if approved) updates RFC 4271
2398 : * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2399 : * and obsoletes RFC 6472.
2400 : */
2401 0 : if (peer->bgp->reject_as_sets)
2402 0 : if (aspath_check_as_sets(attr->aspath))
2403 : return false;
2404 :
2405 : /* If neighbor soo is configured, then check if the route has
2406 : * SoO extended community and validate against the configured
2407 : * one. If they match, do not announce, to prevent routing
2408 : * loops.
2409 : */
2410 0 : if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2411 0 : peer->soo[afi][safi]) {
2412 0 : struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2413 0 : struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2414 :
2415 0 : if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2416 0 : ECOMMUNITY_SITE_ORIGIN) ||
2417 0 : ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
2418 0 : ECOMMUNITY_SITE_ORIGIN) ||
2419 0 : ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
2420 0 : ECOMMUNITY_SITE_ORIGIN)) &&
2421 0 : ecommunity_include(ecomm, ecomm_soo)) {
2422 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2423 0 : zlog_debug(
2424 : "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2425 : peer, p, ecommunity_str(ecomm_soo));
2426 0 : return false;
2427 : }
2428 : }
2429 :
2430 : /* Codification of AS 0 Processing */
2431 0 : if (aspath_check_as_zero(attr->aspath))
2432 : return false;
2433 :
2434 0 : if (bgp_in_graceful_shutdown(bgp)) {
2435 0 : if (peer->sort == BGP_PEER_IBGP
2436 0 : || peer->sort == BGP_PEER_CONFED) {
2437 0 : attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2438 0 : attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2439 : } else {
2440 0 : bgp_attr_add_gshut_community(attr);
2441 : }
2442 : }
2443 :
2444 : /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2445 : * Capability" to a neighbor MUST perform the following upon receiving
2446 : * a route from that neighbor with the "LLGR_STALE" community, or upon
2447 : * attaching the "LLGR_STALE" community itself per Section 4.2:
2448 : *
2449 : * The route SHOULD NOT be advertised to any neighbor from which the
2450 : * Long-lived Graceful Restart Capability has not been received.
2451 : */
2452 0 : if (bgp_attr_get_community(attr) &&
2453 0 : community_include(bgp_attr_get_community(attr),
2454 : COMMUNITY_LLGR_STALE) &&
2455 0 : !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2456 : !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2457 : return false;
2458 :
2459 : /* After route-map has been applied, we check to see if the nexthop to
2460 : * be carried in the attribute (that is used for the announcement) can
2461 : * be cleared off or not. We do this in all cases where we would be
2462 : * setting the nexthop to "ourselves". For IPv6, we only need to
2463 : * consider
2464 : * the global nexthop here; the link-local nexthop would have been
2465 : * cleared
2466 : * already, and if not, it is required by the update formation code.
2467 : * Also see earlier comments in this function.
2468 : */
2469 : /*
2470 : * If route-map has performed some operation on the nexthop or the peer
2471 : * configuration says to pass it unchanged, we cannot reset the nexthop
2472 : * here, so only attempt to do it if these aren't true. Note that the
2473 : * route-map handler itself might have cleared the nexthop, if for
2474 : * example,
2475 : * it is configured as 'peer-address'.
2476 : */
2477 0 : if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
2478 : piattr->rmap_change_flags)
2479 0 : && !transparent
2480 0 : && !CHECK_FLAG(peer->af_flags[afi][safi],
2481 : PEER_FLAG_NEXTHOP_UNCHANGED)) {
2482 : /* We can reset the nexthop, if setting (or forcing) it to
2483 : * 'self' */
2484 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
2485 : PEER_FLAG_NEXTHOP_SELF)
2486 0 : || CHECK_FLAG(peer->af_flags[afi][safi],
2487 : PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2488 0 : if (!reflect
2489 0 : || CHECK_FLAG(peer->af_flags[afi][safi],
2490 : PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2491 0 : subgroup_announce_reset_nhop(
2492 0 : (peer_cap_enhe(peer, afi, safi)
2493 : ? AF_INET6
2494 0 : : p->family),
2495 : attr);
2496 0 : nh_reset = true;
2497 : }
2498 0 : } else if (peer->sort == BGP_PEER_EBGP) {
2499 : /* Can also reset the nexthop if announcing to EBGP, but
2500 : * only if
2501 : * no peer in the subgroup is on a shared subnet.
2502 : * Note: 3rd party nexthop currently implemented for
2503 : * IPv4 only.
2504 : */
2505 0 : if ((p->family == AF_INET) &&
2506 0 : (!bgp_subgrp_multiaccess_check_v4(
2507 : piattr->nexthop,
2508 : subgrp, from))) {
2509 0 : subgroup_announce_reset_nhop(
2510 0 : (peer_cap_enhe(peer, afi, safi)
2511 : ? AF_INET6
2512 0 : : p->family),
2513 : attr);
2514 0 : nh_reset = true;
2515 : }
2516 :
2517 0 : if ((p->family == AF_INET6) &&
2518 0 : (!bgp_subgrp_multiaccess_check_v6(
2519 : piattr->mp_nexthop_global,
2520 : subgrp, from))) {
2521 0 : subgroup_announce_reset_nhop(
2522 0 : (peer_cap_enhe(peer, afi, safi)
2523 : ? AF_INET6
2524 0 : : p->family),
2525 : attr);
2526 0 : nh_reset = true;
2527 : }
2528 :
2529 :
2530 :
2531 0 : } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
2532 : /*
2533 : * This flag is used for leaked vpn-vrf routes
2534 : */
2535 0 : int family = p->family;
2536 :
2537 0 : if (peer_cap_enhe(peer, afi, safi))
2538 0 : family = AF_INET6;
2539 :
2540 0 : if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2541 0 : zlog_debug(
2542 : "%s: %pFX BGP_PATH_ANNC_NH_SELF, family=%s",
2543 : __func__, p, family2str(family));
2544 0 : subgroup_announce_reset_nhop(family, attr);
2545 0 : nh_reset = true;
2546 : }
2547 : }
2548 :
2549 : /* If IPv6/MP and nexthop does not have any override and happens
2550 : * to
2551 : * be a link-local address, reset it so that we don't pass along
2552 : * the
2553 : * source's link-local IPv6 address to recipients who may not be
2554 : * on
2555 : * the same interface.
2556 : */
2557 0 : if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2558 0 : if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2559 0 : subgroup_announce_reset_nhop(AF_INET6, attr);
2560 0 : nh_reset = true;
2561 : }
2562 : }
2563 :
2564 : /* If this is an iBGP, send Origin Validation State (OVS)
2565 : * extended community (rfc8097).
2566 : */
2567 0 : if (peer->sort == BGP_PEER_IBGP) {
2568 0 : enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2569 :
2570 0 : rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2571 :
2572 0 : if (rpki_state != RPKI_NOT_BEING_USED)
2573 0 : bgp_attr_set_ecommunity(
2574 : attr, ecommunity_add_origin_validation_state(
2575 : rpki_state,
2576 : bgp_attr_get_ecommunity(attr)));
2577 : }
2578 :
2579 : /*
2580 : * When the next hop is set to ourselves, if all multipaths have
2581 : * link-bandwidth announce the cumulative bandwidth as that makes
2582 : * the most sense. However, don't modify if the link-bandwidth has
2583 : * been explicitly set by user policy.
2584 : */
2585 0 : if (nh_reset &&
2586 0 : bgp_path_info_mpath_chkwtd(bgp, pi) &&
2587 0 : (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2588 0 : !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2589 0 : bgp_attr_set_ecommunity(
2590 : attr,
2591 : ecommunity_replace_linkbw(
2592 : bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2593 0 : CHECK_FLAG(
2594 : peer->flags,
2595 : PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
2596 :
2597 : return true;
2598 : }
2599 :
2600 0 : static void bgp_route_select_timer_expire(struct thread *thread)
2601 : {
2602 0 : struct afi_safi_info *info;
2603 0 : afi_t afi;
2604 0 : safi_t safi;
2605 0 : struct bgp *bgp;
2606 :
2607 0 : info = THREAD_ARG(thread);
2608 0 : afi = info->afi;
2609 0 : safi = info->safi;
2610 0 : bgp = info->bgp;
2611 :
2612 0 : bgp->gr_info[afi][safi].t_route_select = NULL;
2613 0 : XFREE(MTYPE_TMP, info);
2614 :
2615 : /* Best path selection */
2616 0 : bgp_best_path_select_defer(bgp, afi, safi);
2617 0 : }
2618 :
2619 0 : void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
2620 : struct bgp_maxpaths_cfg *mpath_cfg,
2621 : struct bgp_path_info_pair *result, afi_t afi,
2622 : safi_t safi)
2623 : {
2624 0 : struct bgp_path_info *new_select;
2625 0 : struct bgp_path_info *old_select;
2626 0 : struct bgp_path_info *pi;
2627 0 : struct bgp_path_info *pi1;
2628 0 : struct bgp_path_info *pi2;
2629 0 : struct bgp_path_info *nextpi = NULL;
2630 0 : int paths_eq, do_mpath, debug;
2631 0 : struct list mp_list;
2632 0 : char pfx_buf[PREFIX2STR_BUFFER];
2633 0 : char path_buf[PATH_ADDPATH_STR_BUFFER];
2634 :
2635 0 : bgp_mp_list_init(&mp_list);
2636 0 : do_mpath =
2637 0 : (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2638 :
2639 0 : debug = bgp_debug_bestpath(dest);
2640 :
2641 0 : if (debug)
2642 0 : prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
2643 :
2644 0 : dest->reason = bgp_path_selection_none;
2645 : /* bgp deterministic-med */
2646 0 : new_select = NULL;
2647 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
2648 :
2649 : /* Clear BGP_PATH_DMED_SELECTED for all paths */
2650 0 : for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2651 0 : pi1 = pi1->next)
2652 0 : bgp_path_info_unset_flag(dest, pi1,
2653 : BGP_PATH_DMED_SELECTED);
2654 :
2655 0 : for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
2656 0 : pi1 = pi1->next) {
2657 0 : if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
2658 0 : continue;
2659 0 : if (BGP_PATH_HOLDDOWN(pi1))
2660 0 : continue;
2661 0 : if (pi1->peer != bgp->peer_self)
2662 0 : if (!peer_established(pi1->peer))
2663 0 : continue;
2664 :
2665 0 : new_select = pi1;
2666 0 : if (pi1->next) {
2667 0 : for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2668 0 : if (CHECK_FLAG(pi2->flags,
2669 : BGP_PATH_DMED_CHECK))
2670 0 : continue;
2671 0 : if (BGP_PATH_HOLDDOWN(pi2))
2672 0 : continue;
2673 0 : if (pi2->peer != bgp->peer_self
2674 0 : && !CHECK_FLAG(
2675 : pi2->peer->sflags,
2676 : PEER_STATUS_NSF_WAIT))
2677 0 : if (pi2->peer->status
2678 : != Established)
2679 0 : continue;
2680 :
2681 0 : if (!aspath_cmp_left(pi1->attr->aspath,
2682 0 : pi2->attr->aspath)
2683 0 : && !aspath_cmp_left_confed(
2684 0 : pi1->attr->aspath,
2685 0 : pi2->attr->aspath))
2686 0 : continue;
2687 :
2688 0 : if (bgp_path_info_cmp(
2689 : bgp, pi2, new_select,
2690 : &paths_eq, mpath_cfg, debug,
2691 : pfx_buf, afi, safi,
2692 : &dest->reason)) {
2693 0 : bgp_path_info_unset_flag(
2694 : dest, new_select,
2695 : BGP_PATH_DMED_SELECTED);
2696 0 : new_select = pi2;
2697 : }
2698 :
2699 0 : bgp_path_info_set_flag(
2700 : dest, pi2, BGP_PATH_DMED_CHECK);
2701 : }
2702 : }
2703 0 : bgp_path_info_set_flag(dest, new_select,
2704 : BGP_PATH_DMED_CHECK);
2705 0 : bgp_path_info_set_flag(dest, new_select,
2706 : BGP_PATH_DMED_SELECTED);
2707 :
2708 0 : if (debug) {
2709 0 : bgp_path_info_path_with_addpath_rx_str(
2710 : new_select, path_buf, sizeof(path_buf));
2711 0 : zlog_debug(
2712 : "%pBD(%s): %s is the bestpath from AS %u",
2713 : dest, bgp->name_pretty, path_buf,
2714 : aspath_get_first_as(
2715 : new_select->attr->aspath));
2716 : }
2717 : }
2718 : }
2719 :
2720 : /* Check old selected route and new selected route. */
2721 0 : old_select = NULL;
2722 0 : new_select = NULL;
2723 0 : for (pi = bgp_dest_get_bgp_path_info(dest);
2724 0 : (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2725 0 : enum bgp_path_selection_reason reason;
2726 :
2727 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2728 0 : old_select = pi;
2729 :
2730 0 : if (BGP_PATH_HOLDDOWN(pi)) {
2731 : /* reap REMOVED routes, if needs be
2732 : * selected route must stay for a while longer though
2733 : */
2734 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2735 0 : && (pi != old_select))
2736 0 : bgp_path_info_reap(dest, pi);
2737 :
2738 0 : if (debug)
2739 0 : zlog_debug("%s: pi %p in holddown", __func__,
2740 : pi);
2741 :
2742 0 : continue;
2743 : }
2744 :
2745 0 : if (pi->peer && pi->peer != bgp->peer_self
2746 0 : && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2747 0 : if (!peer_established(pi->peer)) {
2748 :
2749 0 : if (debug)
2750 0 : zlog_debug(
2751 : "%s: pi %p non self peer %s not estab state",
2752 : __func__, pi, pi->peer->host);
2753 :
2754 0 : continue;
2755 : }
2756 :
2757 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
2758 0 : && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2759 0 : bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2760 0 : if (debug)
2761 0 : zlog_debug("%s: pi %p dmed", __func__, pi);
2762 0 : continue;
2763 : }
2764 :
2765 0 : bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
2766 :
2767 0 : reason = dest->reason;
2768 0 : if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
2769 : debug, pfx_buf, afi, safi,
2770 : &dest->reason)) {
2771 0 : if (new_select == NULL &&
2772 0 : reason != bgp_path_selection_none)
2773 0 : dest->reason = reason;
2774 : new_select = pi;
2775 : }
2776 : }
2777 :
2778 : /* Now that we know which path is the bestpath see if any of the other
2779 : * paths
2780 : * qualify as multipaths
2781 : */
2782 0 : if (debug) {
2783 0 : if (new_select)
2784 0 : bgp_path_info_path_with_addpath_rx_str(
2785 : new_select, path_buf, sizeof(path_buf));
2786 : else
2787 0 : snprintf(path_buf, sizeof(path_buf), "NONE");
2788 0 : zlog_debug(
2789 : "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2790 : dest, bgp->name_pretty, path_buf,
2791 : old_select ? old_select->peer->host : "NONE");
2792 : }
2793 :
2794 0 : if (do_mpath && new_select) {
2795 0 : for (pi = bgp_dest_get_bgp_path_info(dest);
2796 0 : (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
2797 :
2798 0 : if (debug)
2799 0 : bgp_path_info_path_with_addpath_rx_str(
2800 : pi, path_buf, sizeof(path_buf));
2801 :
2802 0 : if (pi == new_select) {
2803 0 : if (debug)
2804 0 : zlog_debug(
2805 : "%pBD(%s): %s is the bestpath, add to the multipath list",
2806 : dest, bgp->name_pretty,
2807 : path_buf);
2808 0 : bgp_mp_list_add(&mp_list, pi);
2809 0 : continue;
2810 : }
2811 :
2812 0 : if (BGP_PATH_HOLDDOWN(pi))
2813 0 : continue;
2814 :
2815 0 : if (pi->peer && pi->peer != bgp->peer_self
2816 0 : && !CHECK_FLAG(pi->peer->sflags,
2817 : PEER_STATUS_NSF_WAIT))
2818 0 : if (!peer_established(pi->peer))
2819 0 : continue;
2820 :
2821 0 : if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
2822 0 : if (debug)
2823 0 : zlog_debug(
2824 : "%pBD: %s has the same nexthop as the bestpath, skip it",
2825 : dest, path_buf);
2826 0 : continue;
2827 : }
2828 :
2829 0 : bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
2830 : mpath_cfg, debug, pfx_buf, afi, safi,
2831 : &dest->reason);
2832 :
2833 0 : if (paths_eq) {
2834 0 : if (debug)
2835 0 : zlog_debug(
2836 : "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2837 : dest, path_buf);
2838 0 : bgp_mp_list_add(&mp_list, pi);
2839 : }
2840 : }
2841 : }
2842 :
2843 0 : bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
2844 : mpath_cfg);
2845 0 : bgp_path_info_mpath_aggregate_update(new_select, old_select);
2846 0 : bgp_mp_list_clear(&mp_list);
2847 :
2848 0 : bgp_addpath_update_ids(bgp, dest, afi, safi);
2849 :
2850 0 : result->old = old_select;
2851 0 : result->new = new_select;
2852 :
2853 0 : return;
2854 : }
2855 :
2856 : /*
2857 : * A new route/change in bestpath of an existing route. Evaluate the path
2858 : * for advertisement to the subgroup.
2859 : */
2860 0 : void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2861 : struct bgp_path_info *selected,
2862 : struct bgp_dest *dest,
2863 : uint32_t addpath_tx_id)
2864 : {
2865 0 : const struct prefix *p;
2866 0 : struct peer *onlypeer;
2867 0 : struct attr attr;
2868 0 : afi_t afi;
2869 0 : safi_t safi;
2870 0 : struct bgp *bgp;
2871 0 : bool advertise;
2872 :
2873 0 : p = bgp_dest_get_prefix(dest);
2874 0 : afi = SUBGRP_AFI(subgrp);
2875 0 : safi = SUBGRP_SAFI(subgrp);
2876 0 : bgp = SUBGRP_INST(subgrp);
2877 0 : onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2878 0 : : NULL);
2879 :
2880 0 : if (BGP_DEBUG(update, UPDATE_OUT))
2881 0 : zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
2882 :
2883 : /* First update is deferred until ORF or ROUTE-REFRESH is received */
2884 0 : if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2885 : PEER_STATUS_ORF_WAIT_REFRESH))
2886 0 : return;
2887 :
2888 0 : memset(&attr, 0, sizeof(attr));
2889 : /* It's initialized in bgp_announce_check() */
2890 :
2891 : /* Announcement to the subgroup. If the route is filtered withdraw it.
2892 : * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2893 : * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2894 : * route
2895 : */
2896 0 : advertise = bgp_check_advertise(bgp, dest);
2897 :
2898 0 : if (selected) {
2899 0 : if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
2900 : NULL)) {
2901 : /* Route is selected, if the route is already installed
2902 : * in FIB, then it is advertised
2903 : */
2904 0 : if (advertise) {
2905 0 : if (!bgp_check_withdrawal(bgp, dest))
2906 0 : bgp_adj_out_set_subgroup(
2907 : dest, subgrp, &attr, selected);
2908 : else
2909 0 : bgp_adj_out_unset_subgroup(
2910 : dest, subgrp, 1, addpath_tx_id);
2911 : }
2912 : } else
2913 0 : bgp_adj_out_unset_subgroup(dest, subgrp, 1,
2914 : addpath_tx_id);
2915 : }
2916 :
2917 : /* If selected is NULL we must withdraw the path using addpath_tx_id */
2918 : else {
2919 0 : bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
2920 : }
2921 : }
2922 :
2923 : /*
2924 : * Clear IGP changed flag and attribute changed flag for a route (all paths).
2925 : * This is called at the end of route processing.
2926 : */
2927 0 : void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
2928 : {
2929 0 : struct bgp_path_info *pi;
2930 :
2931 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2932 0 : if (BGP_PATH_HOLDDOWN(pi))
2933 0 : continue;
2934 0 : UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2935 0 : UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
2936 : }
2937 0 : }
2938 :
2939 : /*
2940 : * Has the route changed from the RIB's perspective? This is invoked only
2941 : * if the route selection returns the same best route as earlier - to
2942 : * determine if we need to update zebra or not.
2943 : */
2944 0 : bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
2945 : {
2946 0 : struct bgp_path_info *mpinfo;
2947 :
2948 : /* If this is multipath, check all selected paths for any nexthop
2949 : * change or attribute change. Some attribute changes (e.g., community)
2950 : * aren't of relevance to the RIB, but we'll update zebra to ensure
2951 : * we handle the case of BGP nexthop change. This is the behavior
2952 : * when the best path has an attribute change anyway.
2953 : */
2954 0 : if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2955 : || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2956 0 : || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
2957 : return true;
2958 :
2959 : /*
2960 : * If this is multipath, check all selected paths for any nexthop change
2961 : */
2962 0 : for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2963 0 : mpinfo = bgp_path_info_mpath_next(mpinfo)) {
2964 0 : if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2965 0 : || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
2966 : return true;
2967 : }
2968 :
2969 : /* Nothing has changed from the RIB's perspective. */
2970 : return false;
2971 : }
2972 :
2973 : struct bgp_process_queue {
2974 : struct bgp *bgp;
2975 : STAILQ_HEAD(, bgp_dest) pqueue;
2976 : #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2977 : unsigned int flags;
2978 : unsigned int queued;
2979 : };
2980 :
2981 0 : static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
2982 : safi_t safi, struct bgp_dest *dest,
2983 : struct bgp_path_info *new_select,
2984 : struct bgp_path_info *old_select)
2985 : {
2986 0 : const struct prefix *p = bgp_dest_get_prefix(dest);
2987 :
2988 0 : if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2989 : return;
2990 :
2991 0 : if (advertise_type5_routes(bgp, afi) && new_select
2992 0 : && is_route_injectable_into_evpn(new_select)) {
2993 :
2994 : /* apply the route-map */
2995 0 : if (bgp->adv_cmd_rmap[afi][safi].map) {
2996 0 : route_map_result_t ret;
2997 0 : struct bgp_path_info rmap_path;
2998 0 : struct bgp_path_info_extra rmap_path_extra;
2999 0 : struct attr dummy_attr;
3000 :
3001 0 : dummy_attr = *new_select->attr;
3002 :
3003 : /* Fill temp path_info */
3004 0 : prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3005 : new_select, new_select->peer,
3006 : &dummy_attr);
3007 :
3008 0 : RESET_FLAG(dummy_attr.rmap_change_flags);
3009 :
3010 0 : ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
3011 : p, &rmap_path);
3012 :
3013 0 : if (ret == RMAP_DENYMATCH) {
3014 0 : bgp_attr_flush(&dummy_attr);
3015 0 : bgp_evpn_withdraw_type5_route(bgp, p, afi,
3016 : safi);
3017 : } else
3018 0 : bgp_evpn_advertise_type5_route(
3019 : bgp, p, &dummy_attr, afi, safi);
3020 : } else {
3021 0 : bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
3022 : afi, safi);
3023 : }
3024 0 : } else if (advertise_type5_routes(bgp, afi) && old_select
3025 0 : && is_route_injectable_into_evpn(old_select))
3026 0 : bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
3027 : }
3028 :
3029 : /*
3030 : * Utility to determine whether a particular path_info should use
3031 : * the IMPLICIT_NULL label. This is pretty specialized: it's only called
3032 : * in a path where we basically _know_ this is a BGP-LU route.
3033 : */
3034 0 : static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
3035 : {
3036 : /* Certain types get imp null; so do paths where the nexthop is
3037 : * not labeled.
3038 : */
3039 0 : if (new_select->sub_type == BGP_ROUTE_STATIC
3040 : || new_select->sub_type == BGP_ROUTE_AGGREGATE
3041 0 : || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
3042 : return true;
3043 0 : else if (new_select->extra == NULL ||
3044 0 : !bgp_is_valid_label(&new_select->extra->label[0]))
3045 : /* TODO -- should be configurable? */
3046 : return true;
3047 : else
3048 0 : return false;
3049 : }
3050 :
3051 : /*
3052 : * old_select = The old best path
3053 : * new_select = the new best path
3054 : *
3055 : * if (!old_select && new_select)
3056 : * We are sending new information on.
3057 : *
3058 : * if (old_select && new_select) {
3059 : * if (new_select != old_select)
3060 : * We have a new best path send a change
3061 : * else
3062 : * We've received a update with new attributes that needs
3063 : * to be passed on.
3064 : * }
3065 : *
3066 : * if (old_select && !new_select)
3067 : * We have no eligible route that we can announce or the rn
3068 : * is being removed.
3069 : */
3070 0 : static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
3071 : afi_t afi, safi_t safi)
3072 : {
3073 0 : struct bgp_path_info *new_select;
3074 0 : struct bgp_path_info *old_select;
3075 0 : struct bgp_path_info_pair old_and_new;
3076 0 : int debug = 0;
3077 :
3078 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
3079 0 : if (dest)
3080 0 : debug = bgp_debug_bestpath(dest);
3081 0 : if (debug)
3082 0 : zlog_debug(
3083 : "%s: bgp delete in progress, ignoring event, p=%pBD",
3084 : __func__, dest);
3085 0 : return;
3086 : }
3087 : /* Is it end of initial update? (after startup) */
3088 0 : if (!dest) {
3089 0 : frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3090 : sizeof(bgp->update_delay_zebra_resume_time));
3091 :
3092 0 : bgp->main_zebra_update_hold = 0;
3093 0 : FOREACH_AFI_SAFI (afi, safi) {
3094 0 : if (bgp_fibupd_safi(safi))
3095 0 : bgp_zebra_announce_table(bgp, afi, safi);
3096 : }
3097 0 : bgp->main_peers_update_hold = 0;
3098 :
3099 0 : bgp_start_routeadv(bgp);
3100 0 : return;
3101 : }
3102 :
3103 0 : const struct prefix *p = bgp_dest_get_prefix(dest);
3104 :
3105 0 : debug = bgp_debug_bestpath(dest);
3106 0 : if (debug)
3107 0 : zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3108 : dest, bgp->name_pretty, afi2str(afi),
3109 : safi2str(safi));
3110 :
3111 : /* The best path calculation for the route is deferred if
3112 : * BGP_NODE_SELECT_DEFER is set
3113 : */
3114 0 : if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3115 0 : if (BGP_DEBUG(update, UPDATE_OUT))
3116 0 : zlog_debug("SELECT_DEFER flag set for route %p", dest);
3117 0 : return;
3118 : }
3119 :
3120 : /* Best path selection. */
3121 0 : bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
3122 : afi, safi);
3123 0 : old_select = old_and_new.old;
3124 0 : new_select = old_and_new.new;
3125 :
3126 : /* Do we need to allocate or free labels?
3127 : * Right now, since we only deal with per-prefix labels, it is not
3128 : * necessary to do this upon changes to best path. Exceptions:
3129 : * - label index has changed -> recalculate resulting label
3130 : * - path_info sub_type changed -> switch to/from implicit-null
3131 : * - no valid label (due to removed static label binding) -> get new one
3132 : */
3133 0 : if (bgp->allocate_mpls_labels[afi][safi]) {
3134 0 : if (new_select) {
3135 0 : if (!old_select
3136 0 : || bgp_label_index_differs(new_select, old_select)
3137 0 : || new_select->sub_type != old_select->sub_type
3138 0 : || !bgp_is_valid_label(&dest->local_label)) {
3139 : /* Enforced penultimate hop popping:
3140 : * implicit-null for local routes, aggregate
3141 : * and redistributed routes
3142 : */
3143 0 : if (bgp_lu_need_imp_null(new_select)) {
3144 0 : if (CHECK_FLAG(
3145 : dest->flags,
3146 : BGP_NODE_REGISTERED_FOR_LABEL)
3147 : || CHECK_FLAG(
3148 : dest->flags,
3149 : BGP_NODE_LABEL_REQUESTED))
3150 0 : bgp_unregister_for_label(dest);
3151 0 : dest->local_label = mpls_lse_encode(
3152 : MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3153 : 1);
3154 0 : bgp_set_valid_label(&dest->local_label);
3155 : } else
3156 0 : bgp_register_for_label(dest,
3157 : new_select);
3158 : }
3159 0 : } else if (CHECK_FLAG(dest->flags,
3160 : BGP_NODE_REGISTERED_FOR_LABEL)
3161 : || CHECK_FLAG(dest->flags,
3162 : BGP_NODE_LABEL_REQUESTED)) {
3163 0 : bgp_unregister_for_label(dest);
3164 : }
3165 0 : } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3166 : || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
3167 0 : bgp_unregister_for_label(dest);
3168 : }
3169 :
3170 0 : if (debug)
3171 0 : zlog_debug(
3172 : "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3173 : __func__, dest, bgp->name_pretty, afi2str(afi),
3174 : safi2str(safi), old_select, new_select);
3175 :
3176 : /* If best route remains the same and this is not due to user-initiated
3177 : * clear, see exactly what needs to be done.
3178 : */
3179 0 : if (old_select && old_select == new_select
3180 0 : && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
3181 0 : && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
3182 0 : && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
3183 0 : if (bgp_zebra_has_route_changed(old_select)) {
3184 : #ifdef ENABLE_BGP_VNC
3185 0 : vnc_import_bgp_add_route(bgp, p, old_select);
3186 0 : vnc_import_bgp_exterior_add_route(bgp, p, old_select);
3187 : #endif
3188 0 : if (bgp_fibupd_safi(safi)
3189 0 : && !bgp_option_check(BGP_OPT_NO_FIB)) {
3190 :
3191 0 : if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3192 0 : && new_select->sub_type == BGP_ROUTE_NORMAL)
3193 0 : SET_FLAG(dest->flags,
3194 : BGP_NODE_FIB_INSTALL_PENDING);
3195 :
3196 0 : if (new_select->type == ZEBRA_ROUTE_BGP
3197 0 : && (new_select->sub_type == BGP_ROUTE_NORMAL
3198 0 : || new_select->sub_type
3199 : == BGP_ROUTE_IMPORTED))
3200 :
3201 0 : bgp_zebra_announce(dest, p, old_select,
3202 : bgp, afi, safi);
3203 : }
3204 : }
3205 :
3206 : /* If there is a change of interest to peers, reannounce the
3207 : * route. */
3208 0 : if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
3209 0 : || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3210 0 : || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3211 0 : group_announce_route(bgp, afi, safi, dest, new_select);
3212 :
3213 : /* unicast routes must also be annouced to
3214 : * labeled-unicast update-groups */
3215 0 : if (safi == SAFI_UNICAST)
3216 0 : group_announce_route(bgp, afi,
3217 : SAFI_LABELED_UNICAST, dest,
3218 : new_select);
3219 :
3220 0 : UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
3221 0 : UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
3222 : }
3223 :
3224 : /* advertise/withdraw type-5 routes */
3225 0 : if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3226 0 : || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3227 0 : bgp_process_evpn_route_injection(
3228 : bgp, afi, safi, dest, old_select, old_select);
3229 :
3230 0 : UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3231 0 : UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
3232 0 : bgp_zebra_clear_route_change_flags(dest);
3233 0 : UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3234 0 : return;
3235 : }
3236 :
3237 : /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3238 : */
3239 0 : UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
3240 :
3241 : /* bestpath has changed; bump version */
3242 0 : if (old_select || new_select) {
3243 0 : bgp_bump_version(dest);
3244 :
3245 0 : if (!bgp->t_rmap_def_originate_eval) {
3246 0 : bgp_lock(bgp);
3247 0 : thread_add_timer(
3248 : bm->master,
3249 : update_group_refresh_default_originate_route_map,
3250 : bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3251 : &bgp->t_rmap_def_originate_eval);
3252 : }
3253 : }
3254 :
3255 0 : if (old_select)
3256 0 : bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
3257 0 : if (new_select) {
3258 0 : if (debug)
3259 0 : zlog_debug("%s: setting SELECTED flag", __func__);
3260 0 : bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3261 0 : bgp_path_info_unset_flag(dest, new_select,
3262 : BGP_PATH_ATTR_CHANGED);
3263 0 : UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
3264 0 : UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
3265 : }
3266 :
3267 : #ifdef ENABLE_BGP_VNC
3268 0 : if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3269 0 : if (old_select != new_select) {
3270 0 : if (old_select) {
3271 0 : vnc_import_bgp_exterior_del_route(bgp, p,
3272 : old_select);
3273 0 : vnc_import_bgp_del_route(bgp, p, old_select);
3274 : }
3275 0 : if (new_select) {
3276 0 : vnc_import_bgp_exterior_add_route(bgp, p,
3277 : new_select);
3278 0 : vnc_import_bgp_add_route(bgp, p, new_select);
3279 : }
3280 : }
3281 : }
3282 : #endif
3283 :
3284 0 : group_announce_route(bgp, afi, safi, dest, new_select);
3285 :
3286 : /* unicast routes must also be annouced to labeled-unicast update-groups
3287 : */
3288 0 : if (safi == SAFI_UNICAST)
3289 0 : group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
3290 : new_select);
3291 :
3292 : /* FIB update. */
3293 0 : if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3294 0 : && !bgp_option_check(BGP_OPT_NO_FIB)) {
3295 :
3296 0 : if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3297 0 : && (new_select->sub_type == BGP_ROUTE_NORMAL
3298 0 : || new_select->sub_type == BGP_ROUTE_AGGREGATE
3299 0 : || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3300 :
3301 0 : if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3302 0 : SET_FLAG(dest->flags,
3303 : BGP_NODE_FIB_INSTALL_PENDING);
3304 :
3305 : /* if this is an evpn imported type-5 prefix,
3306 : * we need to withdraw the route first to clear
3307 : * the nh neigh and the RMAC entry.
3308 : */
3309 0 : if (old_select &&
3310 0 : is_route_parent_evpn(old_select))
3311 0 : bgp_zebra_withdraw(p, old_select, bgp, safi);
3312 :
3313 0 : bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
3314 : } else {
3315 : /* Withdraw the route from the kernel. */
3316 0 : if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3317 0 : && (old_select->sub_type == BGP_ROUTE_NORMAL
3318 0 : || old_select->sub_type == BGP_ROUTE_AGGREGATE
3319 0 : || old_select->sub_type == BGP_ROUTE_IMPORTED))
3320 :
3321 0 : bgp_zebra_withdraw(p, old_select, bgp, safi);
3322 : }
3323 : }
3324 :
3325 0 : bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3326 : old_select);
3327 :
3328 : /* Clear any route change flags. */
3329 0 : bgp_zebra_clear_route_change_flags(dest);
3330 :
3331 : /* Reap old select bgp_path_info, if it has been removed */
3332 0 : if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
3333 0 : bgp_path_info_reap(dest, old_select);
3334 :
3335 0 : UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3336 0 : return;
3337 : }
3338 :
3339 : /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3340 1 : void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3341 : {
3342 1 : struct bgp_dest *dest;
3343 1 : int cnt = 0;
3344 1 : struct afi_safi_info *thread_info;
3345 :
3346 1 : if (bgp->gr_info[afi][safi].t_route_select) {
3347 0 : struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3348 :
3349 0 : thread_info = THREAD_ARG(t);
3350 0 : XFREE(MTYPE_TMP, thread_info);
3351 0 : THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
3352 : }
3353 :
3354 1 : if (BGP_DEBUG(update, UPDATE_OUT)) {
3355 0 : zlog_debug("%s: processing route for %s : cnt %d", __func__,
3356 : get_afi_safi_str(afi, safi, false),
3357 : bgp->gr_info[afi][safi].gr_deferred);
3358 : }
3359 :
3360 : /* Process the route list */
3361 1 : for (dest = bgp_table_top(bgp->rib[afi][safi]);
3362 1 : dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3363 : cnt < BGP_MAX_BEST_ROUTE_SELECT;
3364 0 : dest = bgp_route_next(dest)) {
3365 0 : if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3366 0 : continue;
3367 :
3368 0 : UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3369 0 : bgp->gr_info[afi][safi].gr_deferred--;
3370 0 : bgp_process_main_one(bgp, dest, afi, safi);
3371 0 : cnt++;
3372 : }
3373 : /* If iteration stopped before the entire table was traversed then the
3374 : * node needs to be unlocked.
3375 : */
3376 1 : if (dest) {
3377 1 : bgp_dest_unlock_node(dest);
3378 1 : dest = NULL;
3379 : }
3380 :
3381 : /* Send EOR message when all routes are processed */
3382 1 : if (!bgp->gr_info[afi][safi].gr_deferred) {
3383 1 : bgp_send_delayed_eor(bgp);
3384 : /* Send route processing complete message to RIB */
3385 1 : bgp_zebra_update(afi, safi, bgp->vrf_id,
3386 : ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
3387 1 : return;
3388 : }
3389 :
3390 0 : thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
3391 :
3392 0 : thread_info->afi = afi;
3393 0 : thread_info->safi = safi;
3394 0 : thread_info->bgp = bgp;
3395 :
3396 : /* If there are more routes to be processed, start the
3397 : * selection timer
3398 : */
3399 0 : thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3400 : BGP_ROUTE_SELECT_DELAY,
3401 : &bgp->gr_info[afi][safi].t_route_select);
3402 : }
3403 :
3404 0 : static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
3405 : {
3406 0 : struct bgp_process_queue *pqnode = data;
3407 0 : struct bgp *bgp = pqnode->bgp;
3408 0 : struct bgp_table *table;
3409 0 : struct bgp_dest *dest;
3410 :
3411 : /* eoiu marker */
3412 0 : if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3413 0 : bgp_process_main_one(bgp, NULL, 0, 0);
3414 : /* should always have dedicated wq call */
3415 0 : assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
3416 : return WQ_SUCCESS;
3417 : }
3418 :
3419 0 : while (!STAILQ_EMPTY(&pqnode->pqueue)) {
3420 0 : dest = STAILQ_FIRST(&pqnode->pqueue);
3421 0 : STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
3422 0 : STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3423 0 : table = bgp_dest_table(dest);
3424 : /* note, new DESTs may be added as part of processing */
3425 0 : bgp_process_main_one(bgp, dest, table->afi, table->safi);
3426 :
3427 0 : bgp_dest_unlock_node(dest);
3428 0 : bgp_table_unlock(table);
3429 : }
3430 :
3431 : return WQ_SUCCESS;
3432 : }
3433 :
3434 1 : static void bgp_processq_del(struct work_queue *wq, void *data)
3435 : {
3436 1 : struct bgp_process_queue *pqnode = data;
3437 :
3438 1 : bgp_unlock(pqnode->bgp);
3439 :
3440 1 : XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
3441 1 : }
3442 :
3443 1 : void bgp_process_queue_init(struct bgp *bgp)
3444 : {
3445 1 : if (!bgp->process_queue) {
3446 1 : char name[BUFSIZ];
3447 :
3448 1 : snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3449 1 : bgp->process_queue = work_queue_new(bm->master, name);
3450 : }
3451 :
3452 1 : bgp->process_queue->spec.workfunc = &bgp_process_wq;
3453 1 : bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3454 1 : bgp->process_queue->spec.max_retries = 0;
3455 1 : bgp->process_queue->spec.hold = 50;
3456 : /* Use a higher yield value of 50ms for main queue processing */
3457 1 : bgp->process_queue->spec.yield = 50 * 1000L;
3458 1 : }
3459 :
3460 1 : static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
3461 : {
3462 1 : struct bgp_process_queue *pqnode;
3463 :
3464 1 : pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3465 : sizeof(struct bgp_process_queue));
3466 :
3467 : /* unlocked in bgp_processq_del */
3468 1 : pqnode->bgp = bgp_lock(bgp);
3469 1 : STAILQ_INIT(&pqnode->pqueue);
3470 :
3471 1 : return pqnode;
3472 : }
3473 :
3474 1 : void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
3475 : {
3476 : #define ARBITRARY_PROCESS_QLEN 10000
3477 1 : struct work_queue *wq = bgp->process_queue;
3478 1 : struct bgp_process_queue *pqnode;
3479 1 : int pqnode_reuse = 0;
3480 :
3481 : /* already scheduled for processing? */
3482 1 : if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
3483 : return;
3484 :
3485 : /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3486 : * the workqueue
3487 : */
3488 1 : if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3489 0 : if (BGP_DEBUG(update, UPDATE_OUT))
3490 0 : zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3491 : dest);
3492 0 : return;
3493 : }
3494 :
3495 1 : if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3496 0 : if (BGP_DEBUG(update, UPDATE_OUT))
3497 0 : zlog_debug(
3498 : "Soft reconfigure table in progress for route %p",
3499 : dest);
3500 0 : return;
3501 : }
3502 :
3503 1 : if (wq == NULL)
3504 : return;
3505 :
3506 : /* Add route nodes to an existing work queue item until reaching the
3507 : limit only if is from the same BGP view and it's not an EOIU marker
3508 : */
3509 1 : if (work_queue_item_count(wq)) {
3510 0 : struct work_queue_item *item = work_queue_last_item(wq);
3511 0 : pqnode = item->data;
3512 :
3513 0 : if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3514 0 : || pqnode->bgp != bgp
3515 0 : || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
3516 0 : pqnode = bgp_processq_alloc(bgp);
3517 : else
3518 : pqnode_reuse = 1;
3519 : } else
3520 1 : pqnode = bgp_processq_alloc(bgp);
3521 : /* all unlocked in bgp_process_wq */
3522 1 : bgp_table_lock(bgp_dest_table(dest));
3523 :
3524 1 : SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3525 1 : bgp_dest_lock_node(dest);
3526 :
3527 : /* can't be enqueued twice */
3528 1 : assert(STAILQ_NEXT(dest, pq) == NULL);
3529 1 : STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
3530 1 : pqnode->queued++;
3531 :
3532 1 : if (!pqnode_reuse)
3533 1 : work_queue_add(wq, pqnode);
3534 :
3535 : return;
3536 : }
3537 :
3538 0 : void bgp_add_eoiu_mark(struct bgp *bgp)
3539 : {
3540 0 : struct bgp_process_queue *pqnode;
3541 :
3542 0 : if (bgp->process_queue == NULL)
3543 : return;
3544 :
3545 0 : pqnode = bgp_processq_alloc(bgp);
3546 :
3547 0 : SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
3548 0 : work_queue_add(bgp->process_queue, pqnode);
3549 : }
3550 :
3551 0 : static void bgp_maximum_prefix_restart_timer(struct thread *thread)
3552 : {
3553 0 : struct peer *peer;
3554 :
3555 0 : peer = THREAD_ARG(thread);
3556 0 : peer->t_pmax_restart = NULL;
3557 :
3558 0 : if (bgp_debug_neighbor_events(peer))
3559 0 : zlog_debug(
3560 : "%s Maximum-prefix restart timer expired, restore peering",
3561 : peer->host);
3562 :
3563 0 : if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
3564 0 : zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
3565 0 : }
3566 :
3567 0 : static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3568 : safi_t safi)
3569 : {
3570 0 : uint32_t count = 0;
3571 0 : bool filtered = false;
3572 0 : struct bgp_dest *dest;
3573 0 : struct bgp_adj_in *ain;
3574 0 : struct attr attr = {};
3575 0 : struct bgp_table *table = peer->bgp->rib[afi][safi];
3576 :
3577 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3578 0 : for (ain = dest->adj_in; ain; ain = ain->next) {
3579 0 : const struct prefix *rn_p = bgp_dest_get_prefix(dest);
3580 :
3581 0 : attr = *ain->attr;
3582 :
3583 0 : if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3584 : == FILTER_DENY)
3585 0 : filtered = true;
3586 :
3587 0 : if (bgp_input_modifier(
3588 : peer, rn_p, &attr, afi, safi,
3589 0 : ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3590 : NULL, 0, NULL)
3591 : == RMAP_DENY)
3592 : filtered = true;
3593 :
3594 0 : if (filtered)
3595 0 : count++;
3596 :
3597 0 : bgp_attr_flush(&attr);
3598 : }
3599 : }
3600 :
3601 0 : return count;
3602 : }
3603 :
3604 1 : bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3605 : int always)
3606 : {
3607 1 : iana_afi_t pkt_afi;
3608 1 : iana_safi_t pkt_safi;
3609 2 : uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3610 : PEER_FLAG_MAX_PREFIX_FORCE))
3611 0 : ? bgp_filtered_routes_count(peer, afi, safi)
3612 0 : + peer->pcount[afi][safi]
3613 1 : : peer->pcount[afi][safi];
3614 :
3615 1 : if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3616 : return false;
3617 :
3618 0 : if (pcount > peer->pmax[afi][safi]) {
3619 0 : if (CHECK_FLAG(peer->af_sflags[afi][safi],
3620 : PEER_STATUS_PREFIX_LIMIT)
3621 0 : && !always)
3622 : return false;
3623 :
3624 0 : zlog_info(
3625 : "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3626 : get_afi_safi_str(afi, safi, false), peer, pcount,
3627 : peer->pmax[afi][safi]);
3628 0 : SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3629 :
3630 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
3631 : PEER_FLAG_MAX_PREFIX_WARNING))
3632 : return false;
3633 :
3634 : /* Convert AFI, SAFI to values for packet. */
3635 0 : pkt_afi = afi_int2iana(afi);
3636 0 : pkt_safi = safi_int2iana(safi);
3637 : {
3638 0 : uint8_t ndata[7];
3639 :
3640 0 : ndata[0] = (pkt_afi >> 8);
3641 0 : ndata[1] = pkt_afi;
3642 0 : ndata[2] = pkt_safi;
3643 0 : ndata[3] = (peer->pmax[afi][safi] >> 24);
3644 0 : ndata[4] = (peer->pmax[afi][safi] >> 16);
3645 0 : ndata[5] = (peer->pmax[afi][safi] >> 8);
3646 0 : ndata[6] = (peer->pmax[afi][safi]);
3647 :
3648 0 : SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3649 0 : bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3650 : BGP_NOTIFY_CEASE_MAX_PREFIX,
3651 : ndata, 7);
3652 : }
3653 :
3654 : /* Dynamic peers will just close their connection. */
3655 0 : if (peer_dynamic_neighbor(peer))
3656 : return true;
3657 :
3658 : /* restart timer start */
3659 0 : if (peer->pmax_restart[afi][safi]) {
3660 0 : peer->v_pmax_restart =
3661 0 : peer->pmax_restart[afi][safi] * 60;
3662 :
3663 0 : if (bgp_debug_neighbor_events(peer))
3664 0 : zlog_debug(
3665 : "%pBP Maximum-prefix restart timer started for %d secs",
3666 : peer, peer->v_pmax_restart);
3667 :
3668 0 : BGP_TIMER_ON(peer->t_pmax_restart,
3669 : bgp_maximum_prefix_restart_timer,
3670 : peer->v_pmax_restart);
3671 : }
3672 :
3673 0 : return true;
3674 : } else
3675 0 : UNSET_FLAG(peer->af_sflags[afi][safi],
3676 : PEER_STATUS_PREFIX_LIMIT);
3677 :
3678 0 : if (pcount
3679 0 : > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3680 0 : if (CHECK_FLAG(peer->af_sflags[afi][safi],
3681 : PEER_STATUS_PREFIX_THRESHOLD)
3682 0 : && !always)
3683 : return false;
3684 :
3685 0 : zlog_info(
3686 : "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3687 : get_afi_safi_str(afi, safi, false), peer, pcount,
3688 : peer->pmax[afi][safi]);
3689 0 : SET_FLAG(peer->af_sflags[afi][safi],
3690 : PEER_STATUS_PREFIX_THRESHOLD);
3691 : } else
3692 0 : UNSET_FLAG(peer->af_sflags[afi][safi],
3693 : PEER_STATUS_PREFIX_THRESHOLD);
3694 : return false;
3695 : }
3696 :
3697 : /* Unconditionally remove the route from the RIB, without taking
3698 : * damping into consideration (eg, because the session went down)
3699 : */
3700 0 : void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
3701 : struct peer *peer, afi_t afi, safi_t safi)
3702 : {
3703 :
3704 0 : struct bgp *bgp = NULL;
3705 0 : bool delete_route = false;
3706 :
3707 0 : bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3708 : safi);
3709 :
3710 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
3711 0 : bgp_path_info_delete(dest, pi); /* keep historical info */
3712 :
3713 : /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3714 : * flag
3715 : */
3716 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3717 : delete_route = true;
3718 0 : else if (bgp_dest_set_defer_flag(dest, true) < 0)
3719 : delete_route = true;
3720 : if (delete_route) {
3721 0 : if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3722 0 : UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3723 0 : bgp = pi->peer->bgp;
3724 0 : bgp->gr_info[afi][safi].gr_deferred--;
3725 : }
3726 : }
3727 : }
3728 :
3729 0 : hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3730 0 : bgp_process(peer->bgp, dest, afi, safi);
3731 0 : }
3732 :
3733 0 : static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
3734 : struct peer *peer, afi_t afi, safi_t safi,
3735 : struct prefix_rd *prd)
3736 : {
3737 0 : const struct prefix *p = bgp_dest_get_prefix(dest);
3738 :
3739 : /* apply dampening, if result is suppressed, we'll be retaining
3740 : * the bgp_path_info in the RIB for historical reference.
3741 : */
3742 0 : if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3743 0 : && peer->sort == BGP_PEER_EBGP)
3744 0 : if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3745 : == BGP_DAMP_SUPPRESSED) {
3746 0 : bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3747 : safi);
3748 0 : return;
3749 : }
3750 :
3751 : #ifdef ENABLE_BGP_VNC
3752 0 : if (safi == SAFI_MPLS_VPN) {
3753 0 : struct bgp_dest *pdest = NULL;
3754 0 : struct bgp_table *table = NULL;
3755 :
3756 0 : pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3757 : (struct prefix *)prd);
3758 0 : if (bgp_dest_has_bgp_path_info_data(pdest)) {
3759 0 : table = bgp_dest_get_bgp_table_info(pdest);
3760 :
3761 0 : vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3762 : peer->bgp, prd, table, p, pi);
3763 : }
3764 0 : bgp_dest_unlock_node(pdest);
3765 : }
3766 0 : if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3767 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
3768 :
3769 0 : vnc_import_bgp_del_route(peer->bgp, p, pi);
3770 0 : vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
3771 : }
3772 : }
3773 : #endif
3774 :
3775 : /* If this is an EVPN route, process for un-import. */
3776 0 : if (safi == SAFI_EVPN)
3777 0 : bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
3778 :
3779 0 : bgp_rib_remove(dest, pi, peer, afi, safi);
3780 : }
3781 :
3782 1 : struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3783 : struct peer *peer, struct attr *attr,
3784 : struct bgp_dest *dest)
3785 : {
3786 1 : struct bgp_path_info *new;
3787 :
3788 : /* Make new BGP info. */
3789 1 : new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
3790 1 : new->type = type;
3791 1 : new->instance = instance;
3792 1 : new->sub_type = sub_type;
3793 1 : new->peer = peer;
3794 1 : new->attr = attr;
3795 1 : new->uptime = monotime(NULL);
3796 1 : new->net = dest;
3797 1 : return new;
3798 : }
3799 :
3800 : /* Check if received nexthop is valid or not. */
3801 1 : bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3802 : uint8_t type, uint8_t stype, struct attr *attr,
3803 : struct bgp_dest *dest)
3804 : {
3805 1 : bool ret = false;
3806 1 : bool is_bgp_static_route =
3807 1 : (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3808 1 : : false;
3809 :
3810 : /*
3811 : * Only validated for unicast and multicast currently.
3812 : * Also valid for EVPN where the nexthop is an IP address.
3813 : * If we are a bgp static route being checked then there is
3814 : * no need to check to see if the nexthop is martian as
3815 : * that it should be ok.
3816 : */
3817 1 : if (is_bgp_static_route ||
3818 1 : (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3819 : return false;
3820 :
3821 : /* If NEXT_HOP is present, validate it. */
3822 1 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3823 2 : if (attr->nexthop.s_addr == INADDR_ANY ||
3824 2 : !ipv4_unicast_valid(&attr->nexthop) ||
3825 1 : bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3826 0 : return true;
3827 : }
3828 :
3829 : /* If MP_NEXTHOP is present, validate it. */
3830 : /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3831 : * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3832 : * it is not an IPv6 link-local address.
3833 : *
3834 : * If we receive an UPDATE with nexthop length set to 32 bytes
3835 : * we shouldn't discard an UPDATE if it's set to (::).
3836 : * The link-local (2st) is validated along the code path later.
3837 : */
3838 1 : if (attr->mp_nexthop_len) {
3839 0 : switch (attr->mp_nexthop_len) {
3840 0 : case BGP_ATTR_NHLEN_IPV4:
3841 : case BGP_ATTR_NHLEN_VPNV4:
3842 0 : ret = (attr->mp_nexthop_global_in.s_addr ==
3843 0 : INADDR_ANY ||
3844 0 : !ipv4_unicast_valid(
3845 0 : &attr->mp_nexthop_global_in) ||
3846 0 : bgp_nexthop_self(bgp, afi, type, stype, attr,
3847 : dest));
3848 0 : break;
3849 :
3850 0 : case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3851 : case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3852 0 : ret = (IN6_IS_ADDR_UNSPECIFIED(
3853 : &attr->mp_nexthop_global)
3854 0 : || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3855 0 : || IN6_IS_ADDR_MULTICAST(
3856 : &attr->mp_nexthop_global)
3857 0 : || bgp_nexthop_self(bgp, afi, type, stype, attr,
3858 : dest));
3859 0 : break;
3860 0 : case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3861 0 : ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3862 0 : || IN6_IS_ADDR_MULTICAST(
3863 : &attr->mp_nexthop_global)
3864 0 : || bgp_nexthop_self(bgp, afi, type, stype, attr,
3865 : dest));
3866 0 : break;
3867 :
3868 : default:
3869 : ret = true;
3870 : break;
3871 : }
3872 : }
3873 :
3874 : return ret;
3875 : }
3876 :
3877 0 : static void bgp_attr_add_no_export_community(struct attr *attr)
3878 : {
3879 0 : struct community *old;
3880 0 : struct community *new;
3881 0 : struct community *merge;
3882 0 : struct community *no_export;
3883 :
3884 0 : old = bgp_attr_get_community(attr);
3885 0 : no_export = community_str2com("no-export");
3886 :
3887 0 : assert(no_export);
3888 :
3889 0 : if (old) {
3890 0 : merge = community_merge(community_dup(old), no_export);
3891 :
3892 0 : if (!old->refcnt)
3893 0 : community_free(&old);
3894 :
3895 0 : new = community_uniq_sort(merge);
3896 0 : community_free(&merge);
3897 : } else {
3898 0 : new = community_dup(no_export);
3899 : }
3900 :
3901 0 : community_free(&no_export);
3902 :
3903 0 : bgp_attr_set_community(attr, new);
3904 0 : }
3905 :
3906 0 : static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
3907 : struct attr *attr, const struct prefix *prefix,
3908 : int *sub_type)
3909 : {
3910 0 : struct listnode *node, *nnode;
3911 0 : struct bgp *bgp;
3912 0 : bool accept_own_found = false;
3913 :
3914 0 : if (safi != SAFI_MPLS_VPN)
3915 : return false;
3916 :
3917 : /* Processing of the ACCEPT_OWN community is enabled by configuration */
3918 0 : if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
3919 : return false;
3920 :
3921 : /* The route in question carries the ACCEPT_OWN community */
3922 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
3923 0 : struct community *comm = bgp_attr_get_community(attr);
3924 :
3925 0 : if (community_include(comm, COMMUNITY_ACCEPT_OWN))
3926 0 : accept_own_found = true;
3927 : }
3928 :
3929 : /* The route in question is targeted to one or more destination VRFs
3930 : * on the router (as determined by inspecting the Route Target(s)).
3931 : */
3932 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3933 0 : if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3934 0 : continue;
3935 :
3936 0 : if (accept_own_found &&
3937 0 : ecommunity_include(
3938 : bgp->vpn_policy[afi]
3939 : .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
3940 : bgp_attr_get_ecommunity(attr))) {
3941 0 : if (bgp_debug_update(peer, prefix, NULL, 1))
3942 0 : zlog_debug(
3943 : "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
3944 : peer, prefix);
3945 :
3946 : /* Treat this route as imported, because it's leaked
3947 : * already from another VRF, and we got an updated
3948 : * version from route-reflector with ACCEPT_OWN
3949 : * community.
3950 : */
3951 0 : *sub_type = BGP_ROUTE_IMPORTED;
3952 :
3953 0 : return true;
3954 : }
3955 : }
3956 :
3957 : return false;
3958 : }
3959 :
3960 1 : void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
3961 : struct attr *attr, afi_t afi, safi_t safi, int type,
3962 : int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3963 : uint32_t num_labels, int soft_reconfig,
3964 : struct bgp_route_evpn *evpn)
3965 : {
3966 1 : int ret;
3967 1 : int aspath_loop_count = 0;
3968 1 : struct bgp_dest *dest;
3969 1 : struct bgp *bgp;
3970 1 : struct attr new_attr;
3971 1 : struct attr *attr_new;
3972 1 : struct bgp_path_info *pi;
3973 1 : struct bgp_path_info *new = NULL;
3974 1 : struct bgp_path_info_extra *extra;
3975 1 : const char *reason;
3976 1 : char pfx_buf[BGP_PRD_PATH_STRLEN];
3977 1 : int connected = 0;
3978 1 : int do_loop_check = 1;
3979 1 : int has_valid_label = 0;
3980 1 : afi_t nh_afi;
3981 1 : bool force_evpn_import = false;
3982 1 : safi_t orig_safi = safi;
3983 1 : bool leak_success = true;
3984 1 : int allowas_in = 0;
3985 :
3986 1 : if (frrtrace_enabled(frr_bgp, process_update)) {
3987 1 : char pfxprint[PREFIX2STR_BUFFER];
3988 :
3989 1 : prefix2str(p, pfxprint, sizeof(pfxprint));
3990 1 : frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3991 : afi, safi, attr);
3992 : }
3993 :
3994 : #ifdef ENABLE_BGP_VNC
3995 1 : int vnc_implicit_withdraw = 0;
3996 : #endif
3997 1 : int same_attr = 0;
3998 1 : const struct prefix *bgp_nht_param_prefix;
3999 :
4000 : /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
4001 1 : if (orig_safi == SAFI_LABELED_UNICAST)
4002 0 : safi = SAFI_UNICAST;
4003 :
4004 1 : memset(&new_attr, 0, sizeof(new_attr));
4005 1 : new_attr.label_index = BGP_INVALID_LABEL_INDEX;
4006 1 : new_attr.label = MPLS_INVALID_LABEL;
4007 :
4008 1 : bgp = peer->bgp;
4009 1 : dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4010 : /* TODO: Check to see if we can get rid of "is_valid_label" */
4011 1 : if (afi == AFI_L2VPN && safi == SAFI_EVPN)
4012 0 : has_valid_label = (num_labels > 0) ? 1 : 0;
4013 : else
4014 1 : has_valid_label = bgp_is_valid_label(label);
4015 :
4016 0 : if (has_valid_label)
4017 0 : assert(label != NULL);
4018 :
4019 : /* Update overlay index of the attribute */
4020 1 : if (afi == AFI_L2VPN && evpn)
4021 0 : memcpy(&attr->evpn_overlay, evpn,
4022 : sizeof(struct bgp_route_evpn));
4023 :
4024 : /* When peer's soft reconfiguration enabled. Record input packet in
4025 : Adj-RIBs-In. */
4026 1 : if (!soft_reconfig
4027 1 : && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4028 0 : && peer != bgp->peer_self)
4029 0 : bgp_adj_in_set(dest, peer, attr, addpath_id);
4030 :
4031 : /* Update permitted loop count */
4032 1 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4033 0 : allowas_in = peer->allowas_in[afi][safi];
4034 :
4035 : /* Check previously received route. */
4036 2 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4037 0 : if (pi->peer == peer && pi->type == type
4038 0 : && pi->sub_type == sub_type
4039 0 : && pi->addpath_rx_id == addpath_id)
4040 : break;
4041 :
4042 : /* AS path local-as loop check. */
4043 1 : if (peer->change_local_as) {
4044 0 : if (allowas_in)
4045 : aspath_loop_count = allowas_in;
4046 0 : else if (!CHECK_FLAG(peer->flags,
4047 : PEER_FLAG_LOCAL_AS_NO_PREPEND))
4048 0 : aspath_loop_count = 1;
4049 :
4050 0 : if (aspath_loop_check(attr->aspath, peer->change_local_as)
4051 : > aspath_loop_count) {
4052 0 : peer->stat_pfx_aspath_loop++;
4053 0 : reason = "as-path contains our own AS;";
4054 0 : goto filtered;
4055 : }
4056 : }
4057 :
4058 : /* If the peer is configured for "allowas-in origin" and the last ASN in
4059 : * the
4060 : * as-path is our ASN then we do not need to call aspath_loop_check
4061 : */
4062 1 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
4063 0 : if (aspath_get_last_as(attr->aspath) == bgp->as)
4064 1 : do_loop_check = 0;
4065 :
4066 1 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
4067 : bgp_nht_param_prefix = NULL;
4068 : else
4069 1 : bgp_nht_param_prefix = p;
4070 :
4071 : /* AS path loop check. */
4072 1 : if (do_loop_check) {
4073 1 : if (aspath_loop_check(attr->aspath, bgp->as) >
4074 1 : peer->allowas_in[afi][safi]) {
4075 0 : peer->stat_pfx_aspath_loop++;
4076 0 : reason = "as-path contains our own AS;";
4077 0 : goto filtered;
4078 : }
4079 : }
4080 :
4081 : /* If we're a CONFED we need to loop check the CONFED ID too */
4082 1 : if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
4083 0 : if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
4084 0 : peer->allowas_in[afi][safi]) {
4085 0 : peer->stat_pfx_aspath_loop++;
4086 0 : reason = "as-path contains our own confed AS;";
4087 0 : goto filtered;
4088 : }
4089 :
4090 : /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
4091 : * enabled, then take care of that too.
4092 : */
4093 1 : bool accept_own = false;
4094 :
4095 1 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
4096 0 : && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
4097 0 : accept_own =
4098 0 : bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
4099 0 : if (!accept_own) {
4100 0 : peer->stat_pfx_originator_loop++;
4101 0 : reason = "originator is us;";
4102 0 : goto filtered;
4103 : }
4104 : }
4105 :
4106 : /* Route reflector cluster ID check. */
4107 1 : if (bgp_cluster_filter(peer, attr)) {
4108 0 : peer->stat_pfx_cluster_loop++;
4109 0 : reason = "reflected from the same cluster;";
4110 0 : goto filtered;
4111 : }
4112 :
4113 : /* Apply incoming filter. */
4114 1 : if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
4115 0 : peer->stat_pfx_filter++;
4116 0 : reason = "filter;";
4117 0 : goto filtered;
4118 : }
4119 :
4120 : /* RFC 8212 to prevent route leaks.
4121 : * This specification intends to improve this situation by requiring the
4122 : * explicit configuration of both BGP Import and Export Policies for any
4123 : * External BGP (EBGP) session such as customers, peers, or
4124 : * confederation boundaries for all enabled address families. Through
4125 : * codification of the aforementioned requirement, operators will
4126 : * benefit from consistent behavior across different BGP
4127 : * implementations.
4128 : */
4129 1 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
4130 0 : if (!bgp_inbound_policy_exists(peer,
4131 : &peer->filter[afi][safi])) {
4132 0 : reason = "inbound policy missing";
4133 0 : if (monotime_since(&bgp->ebgprequirespolicywarning,
4134 0 : NULL) > FIFTEENMINUTE2USEC ||
4135 0 : bgp->ebgprequirespolicywarning.tv_sec == 0) {
4136 0 : zlog_warn(
4137 : "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
4138 0 : monotime(&bgp->ebgprequirespolicywarning);
4139 : }
4140 0 : goto filtered;
4141 : }
4142 :
4143 : /* draft-ietf-idr-deprecate-as-set-confed-set
4144 : * Filter routes having AS_SET or AS_CONFED_SET in the path.
4145 : * Eventually, This document (if approved) updates RFC 4271
4146 : * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4147 : * and obsoletes RFC 6472.
4148 : */
4149 1 : if (peer->bgp->reject_as_sets)
4150 0 : if (aspath_check_as_sets(attr->aspath)) {
4151 0 : reason =
4152 : "as-path contains AS_SET or AS_CONFED_SET type;";
4153 0 : goto filtered;
4154 : }
4155 :
4156 1 : new_attr = *attr;
4157 :
4158 : /* Apply incoming route-map.
4159 : * NB: new_attr may now contain newly allocated values from route-map
4160 : * "set"
4161 : * commands, so we need bgp_attr_flush in the error paths, until we
4162 : * intern
4163 : * the attr (which takes over the memory references) */
4164 1 : if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
4165 : num_labels, dest)
4166 : == RMAP_DENY) {
4167 0 : peer->stat_pfx_filter++;
4168 0 : reason = "route-map;";
4169 0 : bgp_attr_flush(&new_attr);
4170 0 : goto filtered;
4171 : }
4172 :
4173 1 : if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
4174 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4175 : /* remove from RIB previous entry */
4176 0 : bgp_zebra_withdraw(p, pi, bgp, safi);
4177 : }
4178 :
4179 1 : if (peer->sort == BGP_PEER_EBGP) {
4180 :
4181 : /* rfc7999:
4182 : * A BGP speaker receiving an announcement tagged with the
4183 : * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4184 : * NO_EXPORT community as defined in RFC1997, or a
4185 : * similar community, to prevent propagation of the
4186 : * prefix outside the local AS. The community to prevent
4187 : * propagation SHOULD be chosen according to the operator's
4188 : * routing policy.
4189 : */
4190 1 : if (bgp_attr_get_community(&new_attr) &&
4191 0 : community_include(bgp_attr_get_community(&new_attr),
4192 : COMMUNITY_BLACKHOLE))
4193 0 : bgp_attr_add_no_export_community(&new_attr);
4194 :
4195 : /* If we receive the graceful-shutdown community from an eBGP
4196 : * peer we must lower local-preference */
4197 1 : if (bgp_attr_get_community(&new_attr) &&
4198 0 : community_include(bgp_attr_get_community(&new_attr),
4199 : COMMUNITY_GSHUT)) {
4200 0 : new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4201 0 : new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4202 :
4203 : /* If graceful-shutdown is configured globally or
4204 : * per neighbor, then add the GSHUT community to
4205 : * all paths received from eBGP peers. */
4206 1 : } else if (bgp_in_graceful_shutdown(peer->bgp) ||
4207 1 : CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_SHUTDOWN))
4208 0 : bgp_attr_add_gshut_community(&new_attr);
4209 : }
4210 :
4211 : /* next hop check. */
4212 2 : if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
4213 1 : bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
4214 : &new_attr, dest)) {
4215 0 : peer->stat_pfx_nh_invalid++;
4216 0 : reason = "martian or self next-hop;";
4217 0 : bgp_attr_flush(&new_attr);
4218 0 : goto filtered;
4219 : }
4220 :
4221 1 : if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
4222 0 : peer->stat_pfx_nh_invalid++;
4223 0 : reason = "self mac;";
4224 0 : bgp_attr_flush(&new_attr);
4225 0 : goto filtered;
4226 : }
4227 :
4228 2 : if (bgp_check_role_applicability(afi, safi) &&
4229 1 : bgp_otc_filter(peer, &new_attr)) {
4230 0 : reason = "failing otc validation";
4231 0 : bgp_attr_flush(&new_attr);
4232 0 : goto filtered;
4233 : }
4234 : /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4235 : * condition :
4236 : * Suppress fib is enabled
4237 : * BGP_OPT_NO_FIB is not enabled
4238 : * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4239 : * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4240 : */
4241 1 : if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4242 0 : && (sub_type == BGP_ROUTE_NORMAL)
4243 0 : && (!bgp_option_check(BGP_OPT_NO_FIB))
4244 0 : && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4245 0 : SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4246 :
4247 : /* If neighbor soo is configured, tag all incoming routes with
4248 : * this SoO tag and then filter out advertisements in
4249 : * subgroup_announce_check() if it matches the configured SoO
4250 : * on the other peer.
4251 : */
4252 1 : if (peer->soo[afi][safi]) {
4253 0 : struct ecommunity *old_ecomm =
4254 0 : bgp_attr_get_ecommunity(&new_attr);
4255 0 : struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4256 0 : struct ecommunity *new_ecomm;
4257 :
4258 0 : if (old_ecomm) {
4259 0 : new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4260 : ecomm_soo);
4261 :
4262 0 : if (!old_ecomm->refcnt)
4263 0 : ecommunity_free(&old_ecomm);
4264 : } else {
4265 0 : new_ecomm = ecommunity_dup(ecomm_soo);
4266 : }
4267 :
4268 0 : bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4269 : }
4270 :
4271 1 : attr_new = bgp_attr_intern(&new_attr);
4272 :
4273 : /* If the update is implicit withdraw. */
4274 1 : if (pi) {
4275 0 : pi->uptime = monotime(NULL);
4276 0 : same_attr = attrhash_cmp(pi->attr, attr_new);
4277 :
4278 0 : hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4279 :
4280 : /* Same attribute comes in. */
4281 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
4282 0 : && same_attr
4283 0 : && (!has_valid_label
4284 0 : || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
4285 : num_labels * sizeof(mpls_label_t))
4286 : == 0)) {
4287 0 : if (CHECK_FLAG(bgp->af_flags[afi][safi],
4288 : BGP_CONFIG_DAMPENING)
4289 0 : && peer->sort == BGP_PEER_EBGP
4290 0 : && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4291 0 : if (bgp_debug_update(peer, p, NULL, 1)) {
4292 0 : bgp_debug_rdpfxpath2str(
4293 : afi, safi, prd, p, label,
4294 : num_labels, addpath_id ? 1 : 0,
4295 : addpath_id, evpn, pfx_buf,
4296 : sizeof(pfx_buf));
4297 0 : zlog_debug("%pBP rcvd %s", peer,
4298 : pfx_buf);
4299 : }
4300 :
4301 0 : if (bgp_damp_update(pi, dest, afi, safi)
4302 : != BGP_DAMP_SUPPRESSED) {
4303 0 : bgp_aggregate_increment(bgp, p, pi, afi,
4304 : safi);
4305 0 : bgp_process(bgp, dest, afi, safi);
4306 : }
4307 : } else /* Duplicate - odd */
4308 : {
4309 0 : if (bgp_debug_update(peer, p, NULL, 1)) {
4310 0 : if (!peer->rcvd_attr_printed) {
4311 0 : zlog_debug(
4312 : "%pBP rcvd UPDATE w/ attr: %s",
4313 : peer,
4314 : peer->rcvd_attr_str);
4315 0 : peer->rcvd_attr_printed = 1;
4316 : }
4317 :
4318 0 : bgp_debug_rdpfxpath2str(
4319 : afi, safi, prd, p, label,
4320 : num_labels, addpath_id ? 1 : 0,
4321 : addpath_id, evpn, pfx_buf,
4322 : sizeof(pfx_buf));
4323 0 : zlog_debug(
4324 : "%pBP rcvd %s...duplicate ignored",
4325 : peer, pfx_buf);
4326 : }
4327 :
4328 : /* graceful restart STALE flag unset. */
4329 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
4330 0 : bgp_path_info_unset_flag(
4331 : dest, pi, BGP_PATH_STALE);
4332 0 : bgp_dest_set_defer_flag(dest, false);
4333 0 : bgp_process(bgp, dest, afi, safi);
4334 : }
4335 : }
4336 :
4337 0 : bgp_dest_unlock_node(dest);
4338 0 : bgp_attr_unintern(&attr_new);
4339 :
4340 0 : return;
4341 : }
4342 :
4343 : /* Withdraw/Announce before we fully processed the withdraw */
4344 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
4345 0 : if (bgp_debug_update(peer, p, NULL, 1)) {
4346 0 : bgp_debug_rdpfxpath2str(
4347 : afi, safi, prd, p, label, num_labels,
4348 : addpath_id ? 1 : 0, addpath_id, evpn,
4349 : pfx_buf, sizeof(pfx_buf));
4350 0 : zlog_debug(
4351 : "%pBP rcvd %s, flapped quicker than processing",
4352 : peer, pfx_buf);
4353 : }
4354 :
4355 0 : bgp_path_info_restore(dest, pi);
4356 :
4357 : /*
4358 : * If the BGP_PATH_REMOVED flag is set, then EVPN
4359 : * routes would have been unimported already when a
4360 : * prior BGP withdraw processing happened. Such routes
4361 : * need to be imported again, so flag accordingly.
4362 : */
4363 0 : force_evpn_import = true;
4364 : } else {
4365 : /* implicit withdraw, decrement aggregate and pcount
4366 : * here. only if update is accepted, they'll increment
4367 : * below.
4368 : */
4369 0 : bgp_aggregate_decrement(bgp, p, pi, afi, safi);
4370 : }
4371 :
4372 : /* Received Logging. */
4373 0 : if (bgp_debug_update(peer, p, NULL, 1)) {
4374 0 : bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4375 : num_labels, addpath_id ? 1 : 0,
4376 : addpath_id, evpn, pfx_buf,
4377 : sizeof(pfx_buf));
4378 0 : zlog_debug("%pBP rcvd %s", peer, pfx_buf);
4379 : }
4380 :
4381 : /* graceful restart STALE flag unset. */
4382 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
4383 0 : bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4384 0 : bgp_dest_set_defer_flag(dest, false);
4385 : }
4386 :
4387 : /* The attribute is changed. */
4388 0 : bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
4389 :
4390 : /* Update bgp route dampening information. */
4391 0 : if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
4392 0 : && peer->sort == BGP_PEER_EBGP) {
4393 : /* This is implicit withdraw so we should update
4394 : dampening
4395 : information. */
4396 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
4397 0 : bgp_damp_withdraw(pi, dest, afi, safi, 1);
4398 : }
4399 : #ifdef ENABLE_BGP_VNC
4400 0 : if (safi == SAFI_MPLS_VPN) {
4401 0 : struct bgp_dest *pdest = NULL;
4402 0 : struct bgp_table *table = NULL;
4403 :
4404 0 : pdest = bgp_node_get(bgp->rib[afi][safi],
4405 : (struct prefix *)prd);
4406 0 : if (bgp_dest_has_bgp_path_info_data(pdest)) {
4407 0 : table = bgp_dest_get_bgp_table_info(pdest);
4408 :
4409 0 : vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
4410 : bgp, prd, table, p, pi);
4411 : }
4412 0 : bgp_dest_unlock_node(pdest);
4413 : }
4414 0 : if ((afi == AFI_IP || afi == AFI_IP6)
4415 0 : && (safi == SAFI_UNICAST)) {
4416 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
4417 : /*
4418 : * Implicit withdraw case.
4419 : */
4420 0 : ++vnc_implicit_withdraw;
4421 0 : vnc_import_bgp_del_route(bgp, p, pi);
4422 0 : vnc_import_bgp_exterior_del_route(bgp, p, pi);
4423 : }
4424 : }
4425 : #endif
4426 :
4427 : /* Special handling for EVPN update of an existing route. If the
4428 : * extended community attribute has changed, we need to
4429 : * un-import
4430 : * the route using its existing extended community. It will be
4431 : * subsequently processed for import with the new extended
4432 : * community.
4433 : */
4434 0 : if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4435 0 : && !same_attr) {
4436 0 : if ((pi->attr->flag
4437 0 : & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4438 0 : && (attr_new->flag
4439 0 : & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4440 0 : int cmp;
4441 :
4442 0 : cmp = ecommunity_cmp(
4443 0 : bgp_attr_get_ecommunity(pi->attr),
4444 0 : bgp_attr_get_ecommunity(attr_new));
4445 0 : if (!cmp) {
4446 0 : if (bgp_debug_update(peer, p, NULL, 1))
4447 0 : zlog_debug(
4448 : "Change in EXT-COMM, existing %s new %s",
4449 : ecommunity_str(
4450 : bgp_attr_get_ecommunity(
4451 : pi->attr)),
4452 : ecommunity_str(
4453 : bgp_attr_get_ecommunity(
4454 : attr_new)));
4455 0 : if (safi == SAFI_EVPN)
4456 0 : bgp_evpn_unimport_route(
4457 : bgp, afi, safi, p, pi);
4458 : else /* SAFI_MPLS_VPN */
4459 0 : vpn_leak_to_vrf_withdraw(pi);
4460 : }
4461 : }
4462 : }
4463 :
4464 : /* Update to new attribute. */
4465 0 : bgp_attr_unintern(&pi->attr);
4466 0 : pi->attr = attr_new;
4467 :
4468 : /* Update MPLS label */
4469 0 : if (has_valid_label) {
4470 0 : extra = bgp_path_info_extra_get(pi);
4471 0 : if (extra->label != label) {
4472 0 : memcpy(&extra->label, label,
4473 : num_labels * sizeof(mpls_label_t));
4474 0 : extra->num_labels = num_labels;
4475 : }
4476 0 : if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4477 0 : bgp_set_valid_label(&extra->label[0]);
4478 : }
4479 :
4480 : /* Update SRv6 SID */
4481 0 : if (attr->srv6_l3vpn) {
4482 0 : extra = bgp_path_info_extra_get(pi);
4483 0 : if (sid_diff(&extra->sid[0].sid,
4484 0 : &attr->srv6_l3vpn->sid)) {
4485 0 : sid_copy(&extra->sid[0].sid,
4486 0 : &attr->srv6_l3vpn->sid);
4487 0 : extra->num_sids = 1;
4488 :
4489 0 : extra->sid[0].loc_block_len = 0;
4490 0 : extra->sid[0].loc_node_len = 0;
4491 0 : extra->sid[0].func_len = 0;
4492 0 : extra->sid[0].arg_len = 0;
4493 0 : extra->sid[0].transposition_len = 0;
4494 0 : extra->sid[0].transposition_offset = 0;
4495 :
4496 0 : if (attr->srv6_l3vpn->loc_block_len != 0) {
4497 0 : extra->sid[0].loc_block_len =
4498 : attr->srv6_l3vpn->loc_block_len;
4499 0 : extra->sid[0].loc_node_len =
4500 0 : attr->srv6_l3vpn->loc_node_len;
4501 0 : extra->sid[0].func_len =
4502 0 : attr->srv6_l3vpn->func_len;
4503 0 : extra->sid[0].arg_len =
4504 0 : attr->srv6_l3vpn->arg_len;
4505 0 : extra->sid[0].transposition_len =
4506 : attr->srv6_l3vpn
4507 0 : ->transposition_len;
4508 0 : extra->sid[0].transposition_offset =
4509 : attr->srv6_l3vpn
4510 0 : ->transposition_offset;
4511 : }
4512 : }
4513 0 : } else if (attr->srv6_vpn) {
4514 0 : extra = bgp_path_info_extra_get(pi);
4515 0 : if (sid_diff(&extra->sid[0].sid,
4516 0 : &attr->srv6_vpn->sid)) {
4517 0 : sid_copy(&extra->sid[0].sid,
4518 0 : &attr->srv6_vpn->sid);
4519 0 : extra->num_sids = 1;
4520 : }
4521 : }
4522 :
4523 : #ifdef ENABLE_BGP_VNC
4524 0 : if ((afi == AFI_IP || afi == AFI_IP6)
4525 0 : && (safi == SAFI_UNICAST)) {
4526 0 : if (vnc_implicit_withdraw) {
4527 : /*
4528 : * Add back the route with its new attributes
4529 : * (e.g., nexthop).
4530 : * The route is still selected, until the route
4531 : * selection
4532 : * queued by bgp_process actually runs. We have
4533 : * to make this
4534 : * update to the VNC side immediately to avoid
4535 : * racing against
4536 : * configuration changes (e.g., route-map
4537 : * changes) which
4538 : * trigger re-importation of the entire RIB.
4539 : */
4540 0 : vnc_import_bgp_add_route(bgp, p, pi);
4541 0 : vnc_import_bgp_exterior_add_route(bgp, p, pi);
4542 : }
4543 : }
4544 : #endif
4545 :
4546 : /* Update bgp route dampening information. */
4547 0 : if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
4548 0 : && peer->sort == BGP_PEER_EBGP) {
4549 : /* Now we do normal update dampening. */
4550 0 : ret = bgp_damp_update(pi, dest, afi, safi);
4551 0 : if (ret == BGP_DAMP_SUPPRESSED) {
4552 0 : bgp_dest_unlock_node(dest);
4553 0 : return;
4554 : }
4555 : }
4556 :
4557 : /* Nexthop reachability check - for unicast and
4558 : * labeled-unicast.. */
4559 0 : if (((afi == AFI_IP || afi == AFI_IP6)
4560 0 : && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4561 0 : || (safi == SAFI_EVPN &&
4562 0 : bgp_evpn_is_prefix_nht_supported(p))) {
4563 0 : if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4564 0 : && peer->ttl == BGP_DEFAULT_TTL
4565 0 : && !CHECK_FLAG(peer->flags,
4566 : PEER_FLAG_DISABLE_CONNECTED_CHECK)
4567 0 : && !CHECK_FLAG(bgp->flags,
4568 : BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4569 : connected = 1;
4570 : else
4571 : connected = 0;
4572 :
4573 0 : struct bgp *bgp_nexthop = bgp;
4574 :
4575 0 : if (pi->extra && pi->extra->bgp_orig)
4576 0 : bgp_nexthop = pi->extra->bgp_orig;
4577 :
4578 0 : nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4579 :
4580 0 : if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4581 : safi, pi, NULL, connected,
4582 0 : bgp_nht_param_prefix) ||
4583 0 : CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4584 0 : bgp_path_info_set_flag(dest, pi,
4585 : BGP_PATH_VALID);
4586 : else {
4587 0 : if (BGP_DEBUG(nht, NHT)) {
4588 0 : zlog_debug("%s(%pI4): NH unresolved",
4589 : __func__,
4590 : (in_addr_t *)&attr_new->nexthop);
4591 : }
4592 0 : bgp_path_info_unset_flag(dest, pi,
4593 : BGP_PATH_VALID);
4594 : }
4595 : } else {
4596 0 : if (accept_own)
4597 0 : bgp_path_info_set_flag(dest, pi,
4598 : BGP_PATH_ACCEPT_OWN);
4599 :
4600 0 : bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
4601 : }
4602 :
4603 : #ifdef ENABLE_BGP_VNC
4604 0 : if (safi == SAFI_MPLS_VPN) {
4605 0 : struct bgp_dest *pdest = NULL;
4606 0 : struct bgp_table *table = NULL;
4607 :
4608 0 : pdest = bgp_node_get(bgp->rib[afi][safi],
4609 : (struct prefix *)prd);
4610 0 : if (bgp_dest_has_bgp_path_info_data(pdest)) {
4611 0 : table = bgp_dest_get_bgp_table_info(pdest);
4612 :
4613 0 : vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4614 : bgp, prd, table, p, pi);
4615 : }
4616 0 : bgp_dest_unlock_node(pdest);
4617 : }
4618 : #endif
4619 :
4620 : /* If this is an EVPN route and some attribute has changed,
4621 : * or we are explicitly told to perform a route import, process
4622 : * route for import. If the extended community has changed, we
4623 : * would
4624 : * have done the un-import earlier and the import would result
4625 : * in the
4626 : * route getting injected into appropriate L2 VNIs. If it is
4627 : * just
4628 : * some other attribute change, the import will result in
4629 : * updating
4630 : * the attributes for the route in the VNI(s).
4631 : */
4632 0 : if (safi == SAFI_EVPN &&
4633 0 : (!same_attr || force_evpn_import) &&
4634 0 : CHECK_FLAG(pi->flags, BGP_PATH_VALID))
4635 0 : bgp_evpn_import_route(bgp, afi, safi, p, pi);
4636 :
4637 : /* Process change. */
4638 0 : bgp_aggregate_increment(bgp, p, pi, afi, safi);
4639 :
4640 0 : bgp_process(bgp, dest, afi, safi);
4641 0 : bgp_dest_unlock_node(dest);
4642 :
4643 0 : if (SAFI_UNICAST == safi
4644 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4645 : || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4646 :
4647 0 : vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
4648 : }
4649 0 : if ((SAFI_MPLS_VPN == safi)
4650 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4651 0 : leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
4652 : }
4653 :
4654 : #ifdef ENABLE_BGP_VNC
4655 0 : if (SAFI_MPLS_VPN == safi) {
4656 0 : mpls_label_t label_decoded = decode_label(label);
4657 :
4658 0 : rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4659 : type, sub_type, &label_decoded);
4660 : }
4661 0 : if (SAFI_ENCAP == safi) {
4662 0 : rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4663 : type, sub_type, NULL);
4664 : }
4665 : #endif
4666 0 : if ((safi == SAFI_MPLS_VPN) &&
4667 0 : !CHECK_FLAG(bgp->af_flags[afi][safi],
4668 0 : BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4669 : !leak_success) {
4670 0 : bgp_unlink_nexthop(pi);
4671 0 : bgp_path_info_delete(dest, pi);
4672 : }
4673 0 : return;
4674 : } // End of implicit withdraw
4675 :
4676 : /* Received Logging. */
4677 1 : if (bgp_debug_update(peer, p, NULL, 1)) {
4678 0 : if (!peer->rcvd_attr_printed) {
4679 0 : zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
4680 : peer->rcvd_attr_str);
4681 0 : peer->rcvd_attr_printed = 1;
4682 : }
4683 :
4684 0 : bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4685 : addpath_id ? 1 : 0, addpath_id, evpn,
4686 : pfx_buf, sizeof(pfx_buf));
4687 0 : zlog_debug("%pBP rcvd %s", peer, pfx_buf);
4688 : }
4689 :
4690 : /* Make new BGP info. */
4691 1 : new = info_make(type, sub_type, 0, peer, attr_new, dest);
4692 :
4693 : /* Update MPLS label */
4694 1 : if (has_valid_label) {
4695 0 : extra = bgp_path_info_extra_get(new);
4696 0 : if (extra->label != label) {
4697 0 : memcpy(&extra->label, label,
4698 : num_labels * sizeof(mpls_label_t));
4699 0 : extra->num_labels = num_labels;
4700 : }
4701 0 : if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4702 0 : bgp_set_valid_label(&extra->label[0]);
4703 : }
4704 :
4705 : /* Update SRv6 SID */
4706 1 : if (safi == SAFI_MPLS_VPN) {
4707 0 : extra = bgp_path_info_extra_get(new);
4708 0 : if (attr->srv6_l3vpn) {
4709 0 : sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
4710 0 : extra->num_sids = 1;
4711 :
4712 0 : extra->sid[0].loc_block_len =
4713 0 : attr->srv6_l3vpn->loc_block_len;
4714 0 : extra->sid[0].loc_node_len =
4715 0 : attr->srv6_l3vpn->loc_node_len;
4716 0 : extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4717 0 : extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4718 0 : extra->sid[0].transposition_len =
4719 0 : attr->srv6_l3vpn->transposition_len;
4720 0 : extra->sid[0].transposition_offset =
4721 0 : attr->srv6_l3vpn->transposition_offset;
4722 0 : } else if (attr->srv6_vpn) {
4723 0 : sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
4724 0 : extra->num_sids = 1;
4725 : }
4726 : }
4727 :
4728 : /* Nexthop reachability check. */
4729 1 : if (((afi == AFI_IP || afi == AFI_IP6)
4730 1 : && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4731 0 : || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
4732 1 : if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4733 1 : && peer->ttl == BGP_DEFAULT_TTL
4734 1 : && !CHECK_FLAG(peer->flags,
4735 : PEER_FLAG_DISABLE_CONNECTED_CHECK)
4736 1 : && !CHECK_FLAG(bgp->flags,
4737 : BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
4738 : connected = 1;
4739 : else
4740 : connected = 0;
4741 :
4742 1 : nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4743 :
4744 1 : if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
4745 0 : connected, bgp_nht_param_prefix) ||
4746 0 : CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
4747 1 : bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4748 : else {
4749 0 : if (BGP_DEBUG(nht, NHT))
4750 0 : zlog_debug("%s(%pI4): NH unresolved", __func__,
4751 : &attr_new->nexthop);
4752 0 : bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
4753 : }
4754 : } else {
4755 0 : if (accept_own)
4756 0 : bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
4757 :
4758 0 : bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
4759 : }
4760 :
4761 : /* If maximum prefix count is configured and current prefix
4762 : * count exeed it.
4763 : */
4764 1 : if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4765 0 : reason = "maximum-prefix overflow";
4766 0 : bgp_attr_flush(&new_attr);
4767 0 : goto filtered;
4768 : }
4769 :
4770 : /* Addpath ID */
4771 1 : new->addpath_rx_id = addpath_id;
4772 :
4773 : /* Increment prefix */
4774 1 : bgp_aggregate_increment(bgp, p, new, afi, safi);
4775 :
4776 : /* Register new BGP information. */
4777 1 : bgp_path_info_add(dest, new);
4778 :
4779 : /* route_node_get lock */
4780 1 : bgp_dest_unlock_node(dest);
4781 :
4782 : #ifdef ENABLE_BGP_VNC
4783 1 : if (safi == SAFI_MPLS_VPN) {
4784 0 : struct bgp_dest *pdest = NULL;
4785 0 : struct bgp_table *table = NULL;
4786 :
4787 0 : pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4788 0 : if (bgp_dest_has_bgp_path_info_data(pdest)) {
4789 0 : table = bgp_dest_get_bgp_table_info(pdest);
4790 :
4791 0 : vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4792 : bgp, prd, table, p, new);
4793 : }
4794 0 : bgp_dest_unlock_node(pdest);
4795 : }
4796 : #endif
4797 :
4798 : /* If this is an EVPN route, process for import. */
4799 1 : if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
4800 0 : bgp_evpn_import_route(bgp, afi, safi, p, new);
4801 :
4802 1 : hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4803 :
4804 : /* Process change. */
4805 1 : bgp_process(bgp, dest, afi, safi);
4806 :
4807 1 : if (SAFI_UNICAST == safi
4808 1 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4809 : || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4810 1 : vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4811 : }
4812 1 : if ((SAFI_MPLS_VPN == safi)
4813 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4814 0 : leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
4815 : }
4816 : #ifdef ENABLE_BGP_VNC
4817 0 : if (SAFI_MPLS_VPN == safi) {
4818 0 : mpls_label_t label_decoded = decode_label(label);
4819 :
4820 0 : rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4821 : sub_type, &label_decoded);
4822 : }
4823 1 : if (SAFI_ENCAP == safi) {
4824 0 : rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4825 : sub_type, NULL);
4826 : }
4827 : #endif
4828 1 : if ((safi == SAFI_MPLS_VPN) &&
4829 0 : !CHECK_FLAG(bgp->af_flags[afi][safi],
4830 0 : BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4831 : !leak_success) {
4832 0 : bgp_unlink_nexthop(new);
4833 0 : bgp_path_info_delete(dest, new);
4834 : }
4835 :
4836 : return;
4837 :
4838 : /* This BGP update is filtered. Log the reason then update BGP
4839 : entry. */
4840 0 : filtered:
4841 0 : if (new) {
4842 0 : bgp_unlink_nexthop(new);
4843 0 : bgp_path_info_delete(dest, new);
4844 0 : bgp_path_info_extra_free(&new->extra);
4845 0 : XFREE(MTYPE_BGP_ROUTE, new);
4846 : }
4847 :
4848 0 : hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4849 :
4850 0 : if (bgp_debug_update(peer, p, NULL, 1)) {
4851 0 : if (!peer->rcvd_attr_printed) {
4852 0 : zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
4853 : peer->rcvd_attr_str);
4854 0 : peer->rcvd_attr_printed = 1;
4855 : }
4856 :
4857 0 : bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4858 : addpath_id ? 1 : 0, addpath_id, evpn,
4859 : pfx_buf, sizeof(pfx_buf));
4860 0 : zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4861 : peer, pfx_buf, reason);
4862 : }
4863 :
4864 0 : if (pi) {
4865 : /* If this is an EVPN route, un-import it as it is now filtered.
4866 : */
4867 0 : if (safi == SAFI_EVPN)
4868 0 : bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
4869 :
4870 0 : if (SAFI_UNICAST == safi
4871 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4872 : || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4873 :
4874 0 : vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4875 : }
4876 0 : if ((SAFI_MPLS_VPN == safi)
4877 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4878 :
4879 0 : vpn_leak_to_vrf_withdraw(pi);
4880 : }
4881 :
4882 0 : bgp_rib_remove(dest, pi, peer, afi, safi);
4883 : }
4884 :
4885 0 : bgp_dest_unlock_node(dest);
4886 :
4887 : #ifdef ENABLE_BGP_VNC
4888 : /*
4889 : * Filtered update is treated as an implicit withdrawal (see
4890 : * bgp_rib_remove()
4891 : * a few lines above)
4892 : */
4893 0 : if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4894 0 : rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4895 : 0);
4896 : }
4897 : #endif
4898 :
4899 : return;
4900 : }
4901 :
4902 1 : void bgp_withdraw(struct peer *peer, const struct prefix *p,
4903 : uint32_t addpath_id, struct attr *attr, afi_t afi,
4904 : safi_t safi, int type, int sub_type, struct prefix_rd *prd,
4905 : mpls_label_t *label, uint32_t num_labels,
4906 : struct bgp_route_evpn *evpn)
4907 : {
4908 1 : struct bgp *bgp;
4909 1 : char pfx_buf[BGP_PRD_PATH_STRLEN];
4910 1 : struct bgp_dest *dest;
4911 1 : struct bgp_path_info *pi;
4912 :
4913 : #ifdef ENABLE_BGP_VNC
4914 1 : if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4915 0 : rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4916 : 0);
4917 : }
4918 : #endif
4919 :
4920 1 : bgp = peer->bgp;
4921 :
4922 : /* Lookup node. */
4923 1 : dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4924 :
4925 : /* If peer is soft reconfiguration enabled. Record input packet for
4926 : * further calculation.
4927 : *
4928 : * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4929 : * routes that are filtered. This tanks out Quagga RS pretty badly due
4930 : * to
4931 : * the iteration over all RS clients.
4932 : * Since we need to remove the entry from adj_in anyway, do that first
4933 : * and
4934 : * if there was no entry, we don't need to do anything more.
4935 : */
4936 1 : if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4937 0 : && peer != bgp->peer_self)
4938 0 : if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
4939 0 : peer->stat_pfx_dup_withdraw++;
4940 :
4941 0 : if (bgp_debug_update(peer, p, NULL, 1)) {
4942 0 : bgp_debug_rdpfxpath2str(
4943 : afi, safi, prd, p, label, num_labels,
4944 : addpath_id ? 1 : 0, addpath_id, NULL,
4945 : pfx_buf, sizeof(pfx_buf));
4946 0 : zlog_debug(
4947 : "%s withdrawing route %s not in adj-in",
4948 : peer->host, pfx_buf);
4949 : }
4950 0 : bgp_dest_unlock_node(dest);
4951 0 : return;
4952 : }
4953 :
4954 : /* Lookup withdrawn route. */
4955 2 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4956 0 : if (pi->peer == peer && pi->type == type
4957 0 : && pi->sub_type == sub_type
4958 0 : && pi->addpath_rx_id == addpath_id)
4959 : break;
4960 :
4961 : /* Logging. */
4962 1 : if (bgp_debug_update(peer, p, NULL, 1)) {
4963 0 : bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4964 : addpath_id ? 1 : 0, addpath_id, NULL,
4965 : pfx_buf, sizeof(pfx_buf));
4966 0 : zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
4967 : pfx_buf);
4968 : }
4969 :
4970 : /* Withdraw specified route from routing table. */
4971 1 : if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4972 0 : bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
4973 0 : if (SAFI_UNICAST == safi
4974 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4975 : || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4976 0 : vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
4977 : }
4978 0 : if ((SAFI_MPLS_VPN == safi)
4979 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4980 :
4981 0 : vpn_leak_to_vrf_withdraw(pi);
4982 : }
4983 1 : } else if (bgp_debug_update(peer, p, NULL, 1)) {
4984 0 : bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
4985 : addpath_id ? 1 : 0, addpath_id, NULL,
4986 : pfx_buf, sizeof(pfx_buf));
4987 0 : zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4988 : }
4989 :
4990 : /* Unlock bgp_node_get() lock. */
4991 1 : bgp_dest_unlock_node(dest);
4992 :
4993 1 : return;
4994 : }
4995 :
4996 0 : void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4997 : int withdraw)
4998 : {
4999 0 : struct update_subgroup *subgrp;
5000 0 : subgrp = peer_subgroup(peer, afi, safi);
5001 0 : subgroup_default_originate(subgrp, withdraw);
5002 0 : }
5003 :
5004 :
5005 : /*
5006 : * bgp_stop_announce_route_timer
5007 : */
5008 2 : void bgp_stop_announce_route_timer(struct peer_af *paf)
5009 : {
5010 2 : if (!paf->t_announce_route)
5011 : return;
5012 :
5013 0 : THREAD_OFF(paf->t_announce_route);
5014 : }
5015 :
5016 : /*
5017 : * bgp_announce_route_timer_expired
5018 : *
5019 : * Callback that is invoked when the route announcement timer for a
5020 : * peer_af expires.
5021 : */
5022 0 : static void bgp_announce_route_timer_expired(struct thread *t)
5023 : {
5024 0 : struct peer_af *paf;
5025 0 : struct peer *peer;
5026 :
5027 0 : paf = THREAD_ARG(t);
5028 0 : peer = paf->peer;
5029 :
5030 0 : if (!peer_established(peer))
5031 : return;
5032 :
5033 0 : if (!peer->afc_nego[paf->afi][paf->safi])
5034 : return;
5035 :
5036 0 : peer_af_announce_route(paf, 1);
5037 :
5038 : /* Notify BGP conditional advertisement scanner percess */
5039 0 : peer->advmap_config_change[paf->afi][paf->safi] = true;
5040 : }
5041 :
5042 : /*
5043 : * bgp_announce_route
5044 : *
5045 : * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
5046 : *
5047 : * if force is true we will force an update even if the update
5048 : * limiting code is attempted to kick in.
5049 : */
5050 0 : void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
5051 : {
5052 0 : struct peer_af *paf;
5053 0 : struct update_subgroup *subgrp;
5054 :
5055 0 : paf = peer_af_find(peer, afi, safi);
5056 0 : if (!paf)
5057 : return;
5058 0 : subgrp = PAF_SUBGRP(paf);
5059 :
5060 : /*
5061 : * Ignore if subgroup doesn't exist (implies AF is not negotiated)
5062 : * or a refresh has already been triggered.
5063 : */
5064 0 : if (!subgrp || paf->t_announce_route)
5065 : return;
5066 :
5067 0 : if (force)
5068 0 : SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
5069 :
5070 : /*
5071 : * Start a timer to stagger/delay the announce. This serves
5072 : * two purposes - announcement can potentially be combined for
5073 : * multiple peers and the announcement doesn't happen in the
5074 : * vty context.
5075 : */
5076 0 : thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
5077 : (subgrp->peer_count == 1)
5078 : ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
5079 : : BGP_ANNOUNCE_ROUTE_DELAY_MS,
5080 : &paf->t_announce_route);
5081 : }
5082 :
5083 : /*
5084 : * Announce routes from all AF tables to a peer.
5085 : *
5086 : * This should ONLY be called when there is a need to refresh the
5087 : * routes to the peer based on a policy change for this peer alone
5088 : * or a route refresh request received from the peer.
5089 : * The operation will result in splitting the peer from its existing
5090 : * subgroups and putting it in new subgroups.
5091 : */
5092 0 : void bgp_announce_route_all(struct peer *peer)
5093 : {
5094 0 : afi_t afi;
5095 0 : safi_t safi;
5096 :
5097 0 : FOREACH_AFI_SAFI (afi, safi)
5098 0 : bgp_announce_route(peer, afi, safi, false);
5099 0 : }
5100 :
5101 : /* Flag or unflag bgp_dest to determine whether it should be treated by
5102 : * bgp_soft_reconfig_table_task.
5103 : * Flag if flag is true. Unflag if flag is false.
5104 : */
5105 0 : static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
5106 : {
5107 0 : struct bgp_dest *dest;
5108 0 : struct bgp_adj_in *ain;
5109 :
5110 0 : if (!table)
5111 : return;
5112 :
5113 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5114 0 : for (ain = dest->adj_in; ain; ain = ain->next) {
5115 0 : if (ain->peer != NULL)
5116 : break;
5117 : }
5118 0 : if (flag && ain != NULL && ain->peer != NULL)
5119 0 : SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5120 : else
5121 0 : UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5122 : }
5123 : }
5124 :
5125 0 : static void bgp_soft_reconfig_table_update(struct peer *peer,
5126 : struct bgp_dest *dest,
5127 : struct bgp_adj_in *ain, afi_t afi,
5128 : safi_t safi, struct prefix_rd *prd)
5129 : {
5130 0 : struct bgp_path_info *pi;
5131 0 : uint32_t num_labels = 0;
5132 0 : mpls_label_t *label_pnt = NULL;
5133 0 : struct bgp_route_evpn evpn;
5134 :
5135 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5136 0 : if (pi->peer == peer)
5137 : break;
5138 :
5139 0 : if (pi && pi->extra)
5140 0 : num_labels = pi->extra->num_labels;
5141 0 : if (num_labels)
5142 0 : label_pnt = &pi->extra->label[0];
5143 0 : if (pi)
5144 0 : memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
5145 : sizeof(evpn));
5146 : else
5147 0 : memset(&evpn, 0, sizeof(evpn));
5148 :
5149 0 : bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
5150 : ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
5151 : label_pnt, num_labels, 1, &evpn);
5152 0 : }
5153 :
5154 0 : static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5155 : struct bgp_table *table,
5156 : struct prefix_rd *prd)
5157 : {
5158 0 : struct bgp_dest *dest;
5159 0 : struct bgp_adj_in *ain;
5160 :
5161 0 : if (!table)
5162 0 : table = peer->bgp->rib[afi][safi];
5163 :
5164 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5165 0 : for (ain = dest->adj_in; ain; ain = ain->next) {
5166 0 : if (ain->peer != peer)
5167 0 : continue;
5168 :
5169 0 : bgp_soft_reconfig_table_update(peer, dest, ain, afi,
5170 : safi, prd);
5171 : }
5172 0 : }
5173 :
5174 : /* Do soft reconfig table per bgp table.
5175 : * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5176 : * when BGP_NODE_SOFT_RECONFIG is set,
5177 : * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5178 : * Schedule a new thread to continue the job.
5179 : * Without splitting the full job into several part,
5180 : * vtysh waits for the job to finish before responding to a BGP command
5181 : */
5182 0 : static void bgp_soft_reconfig_table_task(struct thread *thread)
5183 : {
5184 0 : uint32_t iter, max_iter;
5185 0 : struct bgp_dest *dest;
5186 0 : struct bgp_adj_in *ain;
5187 0 : struct peer *peer;
5188 0 : struct bgp_table *table;
5189 0 : struct prefix_rd *prd;
5190 0 : struct listnode *node, *nnode;
5191 :
5192 0 : table = THREAD_ARG(thread);
5193 0 : prd = NULL;
5194 :
5195 0 : max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5196 0 : if (table->soft_reconfig_init) {
5197 : /* first call of the function with a new srta structure.
5198 : * Don't do any treatment this time on nodes
5199 : * in order vtysh to respond quickly
5200 : */
5201 0 : max_iter = 0;
5202 : }
5203 :
5204 0 : for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5205 0 : dest = bgp_route_next(dest)) {
5206 0 : if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5207 0 : continue;
5208 :
5209 0 : UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5210 :
5211 0 : for (ain = dest->adj_in; ain; ain = ain->next) {
5212 0 : for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5213 : nnode, peer)) {
5214 0 : if (ain->peer != peer)
5215 0 : continue;
5216 :
5217 0 : bgp_soft_reconfig_table_update(
5218 : peer, dest, ain, table->afi,
5219 : table->safi, prd);
5220 0 : iter++;
5221 : }
5222 : }
5223 : }
5224 :
5225 : /* we're either starting the initial iteration,
5226 : * or we're going to continue an ongoing iteration
5227 : */
5228 0 : if (dest || table->soft_reconfig_init) {
5229 0 : table->soft_reconfig_init = false;
5230 0 : thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5231 : table, 0, &table->soft_reconfig_thread);
5232 0 : return;
5233 : }
5234 : /* we're done, clean up the background iteration context info and
5235 : schedule route annoucement
5236 : */
5237 0 : for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5238 0 : listnode_delete(table->soft_reconfig_peers, peer);
5239 0 : bgp_announce_route(peer, table->afi, table->safi, false);
5240 : }
5241 :
5242 0 : list_delete(&table->soft_reconfig_peers);
5243 : }
5244 :
5245 :
5246 : /* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5247 : * and peer.
5248 : * - bgp cannot be NULL
5249 : * - if table and peer are NULL, cancel all threads within the bgp instance
5250 : * - if table is NULL and peer is not,
5251 : * remove peer in all threads within the bgp instance
5252 : * - if peer is NULL, cancel all threads matching table within the bgp instance
5253 : */
5254 6 : void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5255 : const struct bgp_table *table,
5256 : const struct peer *peer)
5257 : {
5258 6 : struct peer *npeer;
5259 6 : struct listnode *node, *nnode;
5260 6 : int afi, safi;
5261 6 : struct bgp_table *ntable;
5262 :
5263 6 : if (!bgp)
5264 : return;
5265 :
5266 150 : FOREACH_AFI_SAFI (afi, safi) {
5267 126 : ntable = bgp->rib[afi][safi];
5268 126 : if (!ntable)
5269 0 : continue;
5270 126 : if (table && table != ntable)
5271 40 : continue;
5272 :
5273 172 : for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5274 : npeer)) {
5275 0 : if (peer && peer != npeer)
5276 0 : continue;
5277 0 : listnode_delete(ntable->soft_reconfig_peers, npeer);
5278 : }
5279 :
5280 86 : if (!ntable->soft_reconfig_peers
5281 0 : || !list_isempty(ntable->soft_reconfig_peers))
5282 86 : continue;
5283 :
5284 0 : list_delete(&ntable->soft_reconfig_peers);
5285 0 : bgp_soft_reconfig_table_flag(ntable, false);
5286 126 : THREAD_OFF(ntable->soft_reconfig_thread);
5287 : }
5288 : }
5289 :
5290 : /*
5291 : * Returns false if the peer is not configured for soft reconfig in
5292 : */
5293 0 : bool bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
5294 : {
5295 0 : struct bgp_dest *dest;
5296 0 : struct bgp_table *table;
5297 0 : struct listnode *node, *nnode;
5298 0 : struct peer *npeer;
5299 0 : struct peer_af *paf;
5300 :
5301 0 : if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5302 : return false;
5303 :
5304 0 : if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
5305 0 : && (safi != SAFI_EVPN)) {
5306 0 : table = peer->bgp->rib[afi][safi];
5307 0 : if (!table)
5308 : return true;
5309 :
5310 0 : table->soft_reconfig_init = true;
5311 :
5312 0 : if (!table->soft_reconfig_peers)
5313 0 : table->soft_reconfig_peers = list_new();
5314 0 : npeer = NULL;
5315 : /* add peer to the table soft_reconfig_peers if not already
5316 : * there
5317 : */
5318 0 : for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5319 : npeer)) {
5320 0 : if (peer == npeer)
5321 : break;
5322 : }
5323 0 : if (peer != npeer)
5324 0 : listnode_add(table->soft_reconfig_peers, peer);
5325 :
5326 : /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5327 : * on table would start back at the beginning.
5328 : */
5329 0 : bgp_soft_reconfig_table_flag(table, true);
5330 :
5331 0 : if (!table->soft_reconfig_thread)
5332 0 : thread_add_event(bm->master,
5333 : bgp_soft_reconfig_table_task, table, 0,
5334 : &table->soft_reconfig_thread);
5335 : /* Cancel bgp_announce_route_timer_expired threads.
5336 : * bgp_announce_route_timer_expired threads have been scheduled
5337 : * to announce routes as soon as the soft_reconfigure process
5338 : * finishes.
5339 : * In this case, soft_reconfigure is also scheduled by using
5340 : * a thread but is planned after the
5341 : * bgp_announce_route_timer_expired threads. It means that,
5342 : * without cancelling the threads, the route announcement task
5343 : * would run before the soft reconfiguration one. That would
5344 : * useless and would block vtysh during several seconds. Route
5345 : * announcements are rescheduled as soon as the soft_reconfigure
5346 : * process finishes.
5347 : */
5348 0 : paf = peer_af_find(peer, afi, safi);
5349 0 : if (paf)
5350 0 : bgp_stop_announce_route_timer(paf);
5351 : } else
5352 0 : for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5353 0 : dest = bgp_route_next(dest)) {
5354 0 : table = bgp_dest_get_bgp_table_info(dest);
5355 :
5356 0 : if (table == NULL)
5357 0 : continue;
5358 :
5359 0 : const struct prefix *p = bgp_dest_get_prefix(dest);
5360 0 : struct prefix_rd prd;
5361 :
5362 0 : prd.family = AF_UNSPEC;
5363 0 : prd.prefixlen = 64;
5364 0 : memcpy(&prd.val, p->u.val, 8);
5365 :
5366 0 : bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
5367 : }
5368 :
5369 : return true;
5370 : }
5371 :
5372 :
5373 : struct bgp_clear_node_queue {
5374 : struct bgp_dest *dest;
5375 : };
5376 :
5377 0 : static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
5378 : {
5379 0 : struct bgp_clear_node_queue *cnq = data;
5380 0 : struct bgp_dest *dest = cnq->dest;
5381 0 : struct peer *peer = wq->spec.data;
5382 0 : struct bgp_path_info *pi;
5383 0 : struct bgp *bgp;
5384 0 : afi_t afi = bgp_dest_table(dest)->afi;
5385 0 : safi_t safi = bgp_dest_table(dest)->safi;
5386 :
5387 0 : assert(dest && peer);
5388 0 : bgp = peer->bgp;
5389 :
5390 : /* It is possible that we have multiple paths for a prefix from a peer
5391 : * if that peer is using AddPath.
5392 : */
5393 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
5394 0 : if (pi->peer != peer)
5395 0 : continue;
5396 :
5397 : /* graceful restart STALE flag set. */
5398 0 : if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5399 0 : && peer->nsf[afi][safi])
5400 0 : || CHECK_FLAG(peer->af_sflags[afi][safi],
5401 : PEER_STATUS_ENHANCED_REFRESH))
5402 : && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5403 0 : && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
5404 0 : bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
5405 : else {
5406 : /* If this is an EVPN route, process for
5407 : * un-import. */
5408 0 : if (safi == SAFI_EVPN)
5409 0 : bgp_evpn_unimport_route(
5410 : bgp, afi, safi,
5411 : bgp_dest_get_prefix(dest), pi);
5412 : /* Handle withdraw for VRF route-leaking and L3VPN */
5413 0 : if (SAFI_UNICAST == safi
5414 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
5415 : bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5416 0 : vpn_leak_from_vrf_withdraw(bgp_get_default(),
5417 : bgp, pi);
5418 : }
5419 0 : if (SAFI_MPLS_VPN == safi &&
5420 0 : bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5421 0 : vpn_leak_to_vrf_withdraw(pi);
5422 : }
5423 :
5424 0 : bgp_rib_remove(dest, pi, peer, afi, safi);
5425 : }
5426 : }
5427 0 : return WQ_SUCCESS;
5428 : }
5429 :
5430 0 : static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
5431 : {
5432 0 : struct bgp_clear_node_queue *cnq = data;
5433 0 : struct bgp_dest *dest = cnq->dest;
5434 0 : struct bgp_table *table = bgp_dest_table(dest);
5435 :
5436 0 : bgp_dest_unlock_node(dest);
5437 0 : bgp_table_unlock(table);
5438 0 : XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
5439 0 : }
5440 :
5441 0 : static void bgp_clear_node_complete(struct work_queue *wq)
5442 : {
5443 0 : struct peer *peer = wq->spec.data;
5444 :
5445 : /* Tickle FSM to start moving again */
5446 0 : BGP_EVENT_ADD(peer, Clearing_Completed);
5447 :
5448 0 : peer_unlock(peer); /* bgp_clear_route */
5449 0 : }
5450 :
5451 3 : static void bgp_clear_node_queue_init(struct peer *peer)
5452 : {
5453 3 : char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5454 :
5455 3 : snprintf(wname, sizeof(wname), "clear %s", peer->host);
5456 : #undef CLEAR_QUEUE_NAME_LEN
5457 :
5458 3 : peer->clear_node_queue = work_queue_new(bm->master, wname);
5459 3 : peer->clear_node_queue->spec.hold = 10;
5460 3 : peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5461 3 : peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5462 3 : peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5463 3 : peer->clear_node_queue->spec.max_retries = 0;
5464 :
5465 : /* we only 'lock' this peer reference when the queue is actually active
5466 : */
5467 3 : peer->clear_node_queue->spec.data = peer;
5468 3 : }
5469 :
5470 36 : static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5471 : struct bgp_table *table)
5472 : {
5473 36 : struct bgp_dest *dest;
5474 36 : int force = peer->bgp->process_queue ? 0 : 1;
5475 :
5476 36 : if (!table)
5477 36 : table = peer->bgp->rib[afi][safi];
5478 :
5479 : /* If still no table => afi/safi isn't configured at all or smth. */
5480 36 : if (!table)
5481 : return;
5482 :
5483 74 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5484 2 : struct bgp_path_info *pi, *next;
5485 2 : struct bgp_adj_in *ain;
5486 2 : struct bgp_adj_in *ain_next;
5487 :
5488 : /* XXX:TODO: This is suboptimal, every non-empty route_node is
5489 : * queued for every clearing peer, regardless of whether it is
5490 : * relevant to the peer at hand.
5491 : *
5492 : * Overview: There are 3 different indices which need to be
5493 : * scrubbed, potentially, when a peer is removed:
5494 : *
5495 : * 1 peer's routes visible via the RIB (ie accepted routes)
5496 : * 2 peer's routes visible by the (optional) peer's adj-in index
5497 : * 3 other routes visible by the peer's adj-out index
5498 : *
5499 : * 3 there is no hurry in scrubbing, once the struct peer is
5500 : * removed from bgp->peer, we could just GC such deleted peer's
5501 : * adj-outs at our leisure.
5502 : *
5503 : * 1 and 2 must be 'scrubbed' in some way, at least made
5504 : * invisible via RIB index before peer session is allowed to be
5505 : * brought back up. So one needs to know when such a 'search' is
5506 : * complete.
5507 : *
5508 : * Ideally:
5509 : *
5510 : * - there'd be a single global queue or a single RIB walker
5511 : * - rather than tracking which route_nodes still need to be
5512 : * examined on a peer basis, we'd track which peers still
5513 : * aren't cleared
5514 : *
5515 : * Given that our per-peer prefix-counts now should be reliable,
5516 : * this may actually be achievable. It doesn't seem to be a huge
5517 : * problem at this time,
5518 : *
5519 : * It is possible that we have multiple paths for a prefix from
5520 : * a peer
5521 : * if that peer is using AddPath.
5522 : */
5523 2 : ain = dest->adj_in;
5524 2 : while (ain) {
5525 0 : ain_next = ain->next;
5526 :
5527 0 : if (ain->peer == peer)
5528 0 : bgp_adj_in_remove(dest, ain);
5529 :
5530 : ain = ain_next;
5531 : }
5532 :
5533 3 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5534 2 : next = pi->next;
5535 2 : if (pi->peer != peer)
5536 1 : continue;
5537 :
5538 1 : if (force)
5539 0 : bgp_path_info_reap(dest, pi);
5540 : else {
5541 1 : struct bgp_clear_node_queue *cnq;
5542 :
5543 : /* both unlocked in bgp_clear_node_queue_del */
5544 1 : bgp_table_lock(bgp_dest_table(dest));
5545 1 : bgp_dest_lock_node(dest);
5546 1 : cnq = XCALLOC(
5547 : MTYPE_BGP_CLEAR_NODE_QUEUE,
5548 : sizeof(struct bgp_clear_node_queue));
5549 1 : cnq->dest = dest;
5550 1 : work_queue_add(peer->clear_node_queue, cnq);
5551 1 : break;
5552 : }
5553 : }
5554 : }
5555 : return;
5556 : }
5557 :
5558 63 : void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5559 : {
5560 63 : struct bgp_dest *dest;
5561 63 : struct bgp_table *table;
5562 :
5563 63 : if (peer->clear_node_queue == NULL)
5564 3 : bgp_clear_node_queue_init(peer);
5565 :
5566 : /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5567 : * Idle until it receives a Clearing_Completed event. This protects
5568 : * against peers which flap faster than we can we clear, which could
5569 : * lead to:
5570 : *
5571 : * a) race with routes from the new session being installed before
5572 : * clear_route_node visits the node (to delete the route of that
5573 : * peer)
5574 : * b) resource exhaustion, clear_route_node likely leads to an entry
5575 : * on the process_main queue. Fast-flapping could cause that queue
5576 : * to grow and grow.
5577 : */
5578 :
5579 : /* lock peer in assumption that clear-node-queue will get nodes; if so,
5580 : * the unlock will happen upon work-queue completion; other wise, the
5581 : * unlock happens at the end of this function.
5582 : */
5583 63 : if (!peer->clear_node_queue->thread)
5584 43 : peer_lock(peer);
5585 :
5586 63 : if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5587 36 : bgp_clear_route_table(peer, afi, safi, NULL);
5588 : else
5589 54 : for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5590 0 : dest = bgp_route_next(dest)) {
5591 0 : table = bgp_dest_get_bgp_table_info(dest);
5592 0 : if (!table)
5593 0 : continue;
5594 :
5595 0 : bgp_clear_route_table(peer, afi, safi, table);
5596 : }
5597 :
5598 : /* unlock if no nodes got added to the clear-node-queue. */
5599 63 : if (!peer->clear_node_queue->thread)
5600 42 : peer_unlock(peer);
5601 63 : }
5602 :
5603 3 : void bgp_clear_route_all(struct peer *peer)
5604 : {
5605 3 : afi_t afi;
5606 3 : safi_t safi;
5607 :
5608 75 : FOREACH_AFI_SAFI (afi, safi)
5609 63 : bgp_clear_route(peer, afi, safi);
5610 :
5611 : #ifdef ENABLE_BGP_VNC
5612 3 : rfapiProcessPeerDown(peer);
5613 : #endif
5614 3 : }
5615 :
5616 0 : void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
5617 : {
5618 0 : struct bgp_table *table;
5619 0 : struct bgp_dest *dest;
5620 0 : struct bgp_adj_in *ain;
5621 0 : struct bgp_adj_in *ain_next;
5622 :
5623 0 : table = peer->bgp->rib[afi][safi];
5624 :
5625 : /* It is possible that we have multiple paths for a prefix from a peer
5626 : * if that peer is using AddPath.
5627 : */
5628 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5629 0 : ain = dest->adj_in;
5630 :
5631 0 : while (ain) {
5632 0 : ain_next = ain->next;
5633 :
5634 0 : if (ain->peer == peer)
5635 0 : bgp_adj_in_remove(dest, ain);
5636 :
5637 : ain = ain_next;
5638 : }
5639 : }
5640 0 : }
5641 :
5642 : /* If any of the routes from the peer have been marked with the NO_LLGR
5643 : * community, either as sent by the peer, or as the result of a configured
5644 : * policy, they MUST NOT be retained, but MUST be removed as per the normal
5645 : * operation of [RFC4271].
5646 : */
5647 0 : void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5648 : {
5649 0 : struct bgp_dest *dest;
5650 0 : struct bgp_path_info *pi;
5651 0 : struct bgp_table *table;
5652 :
5653 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5654 0 : for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5655 0 : dest = bgp_route_next(dest)) {
5656 0 : struct bgp_dest *rm;
5657 :
5658 : /* look for neighbor in tables */
5659 0 : table = bgp_dest_get_bgp_table_info(dest);
5660 0 : if (!table)
5661 0 : continue;
5662 :
5663 0 : for (rm = bgp_table_top(table); rm;
5664 0 : rm = bgp_route_next(rm))
5665 0 : for (pi = bgp_dest_get_bgp_path_info(rm); pi;
5666 0 : pi = pi->next) {
5667 0 : if (pi->peer != peer)
5668 0 : continue;
5669 0 : if (CHECK_FLAG(
5670 : peer->af_sflags[afi][safi],
5671 0 : PEER_STATUS_LLGR_WAIT) &&
5672 0 : bgp_attr_get_community(pi->attr) &&
5673 0 : !community_include(
5674 : bgp_attr_get_community(
5675 0 : pi->attr),
5676 : COMMUNITY_NO_LLGR))
5677 0 : continue;
5678 0 : if (!CHECK_FLAG(pi->flags,
5679 : BGP_PATH_STALE))
5680 0 : continue;
5681 :
5682 : /*
5683 : * If this is VRF leaked route
5684 : * process for withdraw.
5685 : */
5686 0 : if (pi->sub_type ==
5687 0 : BGP_ROUTE_IMPORTED &&
5688 0 : peer->bgp->inst_type ==
5689 : BGP_INSTANCE_TYPE_DEFAULT)
5690 0 : vpn_leak_to_vrf_withdraw(pi);
5691 :
5692 0 : bgp_rib_remove(rm, pi, peer, afi, safi);
5693 0 : break;
5694 : }
5695 : }
5696 : } else {
5697 0 : for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5698 0 : dest = bgp_route_next(dest))
5699 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5700 0 : pi = pi->next) {
5701 0 : if (pi->peer != peer)
5702 0 : continue;
5703 0 : if (CHECK_FLAG(peer->af_sflags[afi][safi],
5704 0 : PEER_STATUS_LLGR_WAIT) &&
5705 0 : bgp_attr_get_community(pi->attr) &&
5706 0 : !community_include(
5707 0 : bgp_attr_get_community(pi->attr),
5708 : COMMUNITY_NO_LLGR))
5709 0 : continue;
5710 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
5711 0 : continue;
5712 0 : if (safi == SAFI_UNICAST &&
5713 0 : (peer->bgp->inst_type ==
5714 : BGP_INSTANCE_TYPE_VRF ||
5715 : peer->bgp->inst_type ==
5716 : BGP_INSTANCE_TYPE_DEFAULT))
5717 0 : vpn_leak_from_vrf_withdraw(
5718 : bgp_get_default(), peer->bgp,
5719 : pi);
5720 :
5721 0 : bgp_rib_remove(dest, pi, peer, afi, safi);
5722 0 : break;
5723 : }
5724 : }
5725 0 : }
5726 :
5727 0 : void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5728 : {
5729 0 : struct bgp_dest *dest, *ndest;
5730 0 : struct bgp_path_info *pi;
5731 0 : struct bgp_table *table;
5732 :
5733 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5734 0 : for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5735 0 : dest = bgp_route_next(dest)) {
5736 0 : table = bgp_dest_get_bgp_table_info(dest);
5737 0 : if (!table)
5738 0 : continue;
5739 :
5740 0 : for (ndest = bgp_table_top(table); ndest;
5741 0 : ndest = bgp_route_next(ndest)) {
5742 0 : for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5743 0 : pi = pi->next) {
5744 0 : if (pi->peer != peer)
5745 0 : continue;
5746 :
5747 0 : if ((CHECK_FLAG(
5748 : peer->af_sflags[afi][safi],
5749 : PEER_STATUS_ENHANCED_REFRESH))
5750 : && !CHECK_FLAG(pi->flags,
5751 : BGP_PATH_STALE)
5752 0 : && !CHECK_FLAG(
5753 : pi->flags,
5754 : BGP_PATH_UNUSEABLE)) {
5755 0 : if (bgp_debug_neighbor_events(
5756 : peer))
5757 0 : zlog_debug(
5758 : "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5759 : peer,
5760 : afi2str(afi),
5761 : safi2str(safi),
5762 : bgp_dest_get_prefix(
5763 : ndest));
5764 :
5765 0 : bgp_path_info_set_flag(
5766 : ndest, pi,
5767 : BGP_PATH_STALE);
5768 : }
5769 : }
5770 : }
5771 : }
5772 : } else {
5773 0 : for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5774 0 : dest = bgp_route_next(dest)) {
5775 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5776 0 : pi = pi->next) {
5777 0 : if (pi->peer != peer)
5778 0 : continue;
5779 :
5780 0 : if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5781 : PEER_STATUS_ENHANCED_REFRESH))
5782 : && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5783 0 : && !CHECK_FLAG(pi->flags,
5784 : BGP_PATH_UNUSEABLE)) {
5785 0 : if (bgp_debug_neighbor_events(peer))
5786 0 : zlog_debug(
5787 : "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5788 : peer, afi2str(afi),
5789 : safi2str(safi),
5790 : bgp_dest_get_prefix(
5791 : dest));
5792 :
5793 0 : bgp_path_info_set_flag(dest, pi,
5794 : BGP_PATH_STALE);
5795 : }
5796 : }
5797 : }
5798 : }
5799 0 : }
5800 :
5801 0 : bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5802 : {
5803 0 : if (peer->sort == BGP_PEER_IBGP)
5804 : return true;
5805 :
5806 0 : if (peer->sort == BGP_PEER_EBGP
5807 0 : && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5808 0 : || FILTER_LIST_OUT_NAME(filter)
5809 0 : || DISTRIBUTE_OUT_NAME(filter)))
5810 0 : return true;
5811 : return false;
5812 : }
5813 :
5814 0 : bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
5815 : {
5816 0 : if (peer->sort == BGP_PEER_IBGP)
5817 : return true;
5818 :
5819 0 : if (peer->sort == BGP_PEER_EBGP
5820 0 : && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5821 0 : || FILTER_LIST_IN_NAME(filter)
5822 0 : || DISTRIBUTE_IN_NAME(filter)))
5823 0 : return true;
5824 : return false;
5825 : }
5826 :
5827 2 : static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5828 : safi_t safi)
5829 : {
5830 2 : struct bgp_dest *dest;
5831 2 : struct bgp_path_info *pi;
5832 2 : struct bgp_path_info *next;
5833 :
5834 5 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5835 2 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5836 1 : const struct prefix *p = bgp_dest_get_prefix(dest);
5837 :
5838 1 : next = pi->next;
5839 :
5840 : /* Unimport EVPN routes from VRFs */
5841 1 : if (safi == SAFI_EVPN)
5842 0 : bgp_evpn_unimport_route(bgp, AFI_L2VPN,
5843 : SAFI_EVPN, p, pi);
5844 :
5845 1 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5846 0 : && pi->type == ZEBRA_ROUTE_BGP
5847 0 : && (pi->sub_type == BGP_ROUTE_NORMAL
5848 0 : || pi->sub_type == BGP_ROUTE_AGGREGATE
5849 0 : || pi->sub_type == BGP_ROUTE_IMPORTED)) {
5850 :
5851 0 : if (bgp_fibupd_safi(safi))
5852 0 : bgp_zebra_withdraw(p, pi, bgp, safi);
5853 : }
5854 :
5855 1 : bgp_path_info_reap(dest, pi);
5856 : }
5857 2 : }
5858 :
5859 : /* Delete all kernel routes. */
5860 1 : void bgp_cleanup_routes(struct bgp *bgp)
5861 : {
5862 1 : afi_t afi;
5863 1 : struct bgp_dest *dest;
5864 1 : struct bgp_table *table;
5865 :
5866 4 : for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5867 3 : if (afi == AFI_L2VPN)
5868 1 : continue;
5869 2 : bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5870 : SAFI_UNICAST);
5871 : /*
5872 : * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5873 : */
5874 2 : if (afi != AFI_L2VPN) {
5875 2 : safi_t safi;
5876 2 : safi = SAFI_MPLS_VPN;
5877 4 : for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5878 0 : dest = bgp_route_next(dest)) {
5879 0 : table = bgp_dest_get_bgp_table_info(dest);
5880 0 : if (table != NULL) {
5881 0 : bgp_cleanup_table(bgp, table, safi);
5882 0 : bgp_table_finish(&table);
5883 0 : bgp_dest_set_bgp_table_info(dest, NULL);
5884 0 : bgp_dest_unlock_node(dest);
5885 : }
5886 : }
5887 2 : safi = SAFI_ENCAP;
5888 4 : for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5889 0 : dest = bgp_route_next(dest)) {
5890 0 : table = bgp_dest_get_bgp_table_info(dest);
5891 0 : if (table != NULL) {
5892 0 : bgp_cleanup_table(bgp, table, safi);
5893 0 : bgp_table_finish(&table);
5894 0 : bgp_dest_set_bgp_table_info(dest, NULL);
5895 0 : bgp_dest_unlock_node(dest);
5896 : }
5897 : }
5898 : }
5899 : }
5900 2 : for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5901 0 : dest = bgp_route_next(dest)) {
5902 0 : table = bgp_dest_get_bgp_table_info(dest);
5903 0 : if (table != NULL) {
5904 0 : bgp_cleanup_table(bgp, table, SAFI_EVPN);
5905 0 : bgp_table_finish(&table);
5906 0 : bgp_dest_set_bgp_table_info(dest, NULL);
5907 0 : bgp_dest_unlock_node(dest);
5908 : }
5909 : }
5910 1 : }
5911 :
5912 0 : void bgp_reset(void)
5913 : {
5914 0 : vty_reset();
5915 0 : bgp_zclient_reset();
5916 0 : access_list_reset();
5917 0 : prefix_list_reset();
5918 0 : }
5919 :
5920 2 : bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
5921 : {
5922 2 : return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5923 2 : && CHECK_FLAG(peer->af_cap[afi][safi],
5924 : PEER_CAP_ADDPATH_AF_TX_RCV));
5925 : }
5926 :
5927 : /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5928 : value. */
5929 2 : int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5930 : struct bgp_nlri *packet)
5931 : {
5932 2 : uint8_t *pnt;
5933 2 : uint8_t *lim;
5934 2 : struct prefix p;
5935 2 : int psize;
5936 2 : afi_t afi;
5937 2 : safi_t safi;
5938 2 : bool addpath_capable;
5939 2 : uint32_t addpath_id;
5940 :
5941 2 : pnt = packet->nlri;
5942 2 : lim = pnt + packet->length;
5943 2 : afi = packet->afi;
5944 2 : safi = packet->safi;
5945 2 : addpath_id = 0;
5946 2 : addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
5947 :
5948 : /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5949 : syntactic validity. If the field is syntactically incorrect,
5950 : then the Error Subcode is set to Invalid Network Field. */
5951 4 : for (; pnt < lim; pnt += psize) {
5952 : /* Clear prefix structure. */
5953 2 : memset(&p, 0, sizeof(p));
5954 :
5955 2 : if (addpath_capable) {
5956 :
5957 : /* When packet overflow occurs return immediately. */
5958 0 : if (pnt + BGP_ADDPATH_ID_LEN >= lim)
5959 : return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5960 :
5961 0 : memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
5962 0 : addpath_id = ntohl(addpath_id);
5963 0 : pnt += BGP_ADDPATH_ID_LEN;
5964 : }
5965 :
5966 : /* Fetch prefix length. */
5967 2 : p.prefixlen = *pnt++;
5968 : /* afi/safi validity already verified by caller,
5969 : * bgp_update_receive */
5970 2 : p.family = afi2family(afi);
5971 :
5972 : /* Prefix length check. */
5973 2 : if (p.prefixlen > prefix_blen(&p) * 8) {
5974 0 : flog_err(
5975 : EC_BGP_UPDATE_RCV,
5976 : "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5977 : peer->host, p.prefixlen, packet->afi);
5978 0 : return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
5979 : }
5980 :
5981 : /* Packet size overflow check. */
5982 2 : psize = PSIZE(p.prefixlen);
5983 :
5984 : /* When packet overflow occur return immediately. */
5985 2 : if (pnt + psize > lim) {
5986 0 : flog_err(
5987 : EC_BGP_UPDATE_RCV,
5988 : "%s [Error] Update packet error (prefix length %d overflows packet)",
5989 : peer->host, p.prefixlen);
5990 0 : return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
5991 : }
5992 :
5993 : /* Defensive coding, double-check the psize fits in a struct
5994 : * prefix for the v4 and v6 afi's and unicast/multicast */
5995 2 : if (psize > (ssize_t)sizeof(p.u.val)) {
5996 0 : flog_err(
5997 : EC_BGP_UPDATE_RCV,
5998 : "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5999 : peer->host, p.prefixlen, sizeof(p.u.val));
6000 0 : return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
6001 : }
6002 :
6003 : /* Fetch prefix from NLRI packet. */
6004 2 : memcpy(p.u.val, pnt, psize);
6005 :
6006 : /* Check address. */
6007 2 : if (afi == AFI_IP && safi == SAFI_UNICAST) {
6008 2 : if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
6009 : /* From RFC4271 Section 6.3:
6010 : *
6011 : * If a prefix in the NLRI field is semantically
6012 : * incorrect
6013 : * (e.g., an unexpected multicast IP address),
6014 : * an error SHOULD
6015 : * be logged locally, and the prefix SHOULD be
6016 : * ignored.
6017 : */
6018 0 : flog_err(
6019 : EC_BGP_UPDATE_RCV,
6020 : "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
6021 : peer->host, &p.u.prefix4);
6022 0 : continue;
6023 : }
6024 : }
6025 :
6026 : /* Check address. */
6027 2 : if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
6028 0 : if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6029 0 : flog_err(
6030 : EC_BGP_UPDATE_RCV,
6031 : "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
6032 : peer->host, &p.u.prefix6);
6033 :
6034 0 : continue;
6035 : }
6036 0 : if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
6037 0 : flog_err(
6038 : EC_BGP_UPDATE_RCV,
6039 : "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
6040 : peer->host, &p.u.prefix6);
6041 :
6042 0 : continue;
6043 : }
6044 : }
6045 :
6046 : /* Normal process. */
6047 2 : if (attr)
6048 1 : bgp_update(peer, &p, addpath_id, attr, afi, safi,
6049 : ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6050 : NULL, 0, 0, NULL);
6051 : else
6052 1 : bgp_withdraw(peer, &p, addpath_id, attr, afi, safi,
6053 : ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
6054 : NULL, 0, NULL);
6055 :
6056 : /* Do not send BGP notification twice when maximum-prefix count
6057 : * overflow. */
6058 2 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6059 : return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
6060 : }
6061 :
6062 : /* Packet length consistency check. */
6063 2 : if (pnt != lim) {
6064 0 : flog_err(
6065 : EC_BGP_UPDATE_RCV,
6066 : "%s [Error] Update packet error (prefix length mismatch with total length)",
6067 : peer->host);
6068 0 : return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
6069 : }
6070 :
6071 : return BGP_NLRI_PARSE_OK;
6072 : }
6073 :
6074 0 : static struct bgp_static *bgp_static_new(void)
6075 : {
6076 0 : return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
6077 : }
6078 :
6079 0 : static void bgp_static_free(struct bgp_static *bgp_static)
6080 : {
6081 0 : XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6082 0 : route_map_counter_decrement(bgp_static->rmap.map);
6083 :
6084 0 : XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
6085 0 : XFREE(MTYPE_BGP_STATIC, bgp_static);
6086 0 : }
6087 :
6088 0 : void bgp_static_update(struct bgp *bgp, const struct prefix *p,
6089 : struct bgp_static *bgp_static, afi_t afi, safi_t safi)
6090 : {
6091 0 : struct bgp_dest *dest;
6092 0 : struct bgp_path_info *pi;
6093 0 : struct bgp_path_info *new;
6094 0 : struct bgp_path_info rmap_path;
6095 0 : struct attr attr;
6096 0 : struct attr *attr_new;
6097 0 : route_map_result_t ret;
6098 : #ifdef ENABLE_BGP_VNC
6099 0 : int vnc_implicit_withdraw = 0;
6100 : #endif
6101 :
6102 0 : assert(bgp_static);
6103 :
6104 0 : dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
6105 :
6106 0 : bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
6107 :
6108 0 : attr.nexthop = bgp_static->igpnexthop;
6109 0 : attr.med = bgp_static->igpmetric;
6110 0 : attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6111 :
6112 0 : if (afi == AFI_IP)
6113 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
6114 :
6115 0 : if (bgp_static->igpmetric)
6116 0 : bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
6117 :
6118 0 : if (bgp_static->atomic)
6119 0 : attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6120 :
6121 : /* Store label index, if required. */
6122 0 : if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
6123 0 : attr.label_index = bgp_static->label_index;
6124 0 : attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
6125 : }
6126 :
6127 : /* Apply route-map. */
6128 0 : if (bgp_static->rmap.name) {
6129 0 : struct attr attr_tmp = attr;
6130 :
6131 0 : memset(&rmap_path, 0, sizeof(rmap_path));
6132 0 : rmap_path.peer = bgp->peer_self;
6133 0 : rmap_path.attr = &attr_tmp;
6134 :
6135 0 : SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
6136 :
6137 0 : ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
6138 :
6139 0 : bgp->peer_self->rmap_type = 0;
6140 :
6141 0 : if (ret == RMAP_DENYMATCH) {
6142 : /* Free uninterned attribute. */
6143 0 : bgp_attr_flush(&attr_tmp);
6144 :
6145 : /* Unintern original. */
6146 0 : aspath_unintern(&attr.aspath);
6147 0 : bgp_static_withdraw(bgp, p, afi, safi);
6148 0 : bgp_dest_unlock_node(dest);
6149 0 : return;
6150 : }
6151 :
6152 0 : if (bgp_in_graceful_shutdown(bgp))
6153 0 : bgp_attr_add_gshut_community(&attr_tmp);
6154 :
6155 0 : attr_new = bgp_attr_intern(&attr_tmp);
6156 : } else {
6157 :
6158 0 : if (bgp_in_graceful_shutdown(bgp))
6159 0 : bgp_attr_add_gshut_community(&attr);
6160 :
6161 0 : attr_new = bgp_attr_intern(&attr);
6162 : }
6163 :
6164 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6165 0 : if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6166 0 : && pi->sub_type == BGP_ROUTE_STATIC)
6167 : break;
6168 :
6169 0 : if (pi) {
6170 0 : if (attrhash_cmp(pi->attr, attr_new)
6171 0 : && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
6172 0 : && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
6173 0 : bgp_dest_unlock_node(dest);
6174 0 : bgp_attr_unintern(&attr_new);
6175 0 : aspath_unintern(&attr.aspath);
6176 0 : return;
6177 : } else {
6178 : /* The attribute is changed. */
6179 0 : bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
6180 :
6181 : /* Rewrite BGP route information. */
6182 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
6183 0 : bgp_path_info_restore(dest, pi);
6184 : else
6185 0 : bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6186 : #ifdef ENABLE_BGP_VNC
6187 0 : if ((afi == AFI_IP || afi == AFI_IP6)
6188 0 : && (safi == SAFI_UNICAST)) {
6189 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
6190 : /*
6191 : * Implicit withdraw case.
6192 : * We have to do this before pi is
6193 : * changed
6194 : */
6195 0 : ++vnc_implicit_withdraw;
6196 0 : vnc_import_bgp_del_route(bgp, p, pi);
6197 0 : vnc_import_bgp_exterior_del_route(
6198 : bgp, p, pi);
6199 : }
6200 : }
6201 : #endif
6202 0 : bgp_attr_unintern(&pi->attr);
6203 0 : pi->attr = attr_new;
6204 0 : pi->uptime = monotime(NULL);
6205 : #ifdef ENABLE_BGP_VNC
6206 0 : if ((afi == AFI_IP || afi == AFI_IP6)
6207 0 : && (safi == SAFI_UNICAST)) {
6208 0 : if (vnc_implicit_withdraw) {
6209 0 : vnc_import_bgp_add_route(bgp, p, pi);
6210 0 : vnc_import_bgp_exterior_add_route(
6211 : bgp, p, pi);
6212 : }
6213 : }
6214 : #endif
6215 :
6216 : /* Nexthop reachability check. */
6217 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
6218 0 : && (safi == SAFI_UNICAST
6219 0 : || safi == SAFI_LABELED_UNICAST)) {
6220 :
6221 0 : struct bgp *bgp_nexthop = bgp;
6222 :
6223 0 : if (pi->extra && pi->extra->bgp_orig)
6224 0 : bgp_nexthop = pi->extra->bgp_orig;
6225 :
6226 0 : if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
6227 : afi, safi, pi, NULL,
6228 : 0, p))
6229 0 : bgp_path_info_set_flag(dest, pi,
6230 : BGP_PATH_VALID);
6231 : else {
6232 0 : if (BGP_DEBUG(nht, NHT)) {
6233 0 : char buf1[INET6_ADDRSTRLEN];
6234 0 : inet_ntop(p->family,
6235 0 : &p->u.prefix, buf1,
6236 : sizeof(buf1));
6237 0 : zlog_debug(
6238 : "%s(%s): Route not in table, not advertising",
6239 : __func__, buf1);
6240 : }
6241 0 : bgp_path_info_unset_flag(
6242 : dest, pi, BGP_PATH_VALID);
6243 : }
6244 : } else {
6245 : /* Delete the NHT structure if any, if we're
6246 : * toggling between
6247 : * enabling/disabling import check. We
6248 : * deregister the route
6249 : * from NHT to avoid overloading NHT and the
6250 : * process interaction
6251 : */
6252 0 : bgp_unlink_nexthop(pi);
6253 0 : bgp_path_info_set_flag(dest, pi,
6254 : BGP_PATH_VALID);
6255 : }
6256 : /* Process change. */
6257 0 : bgp_aggregate_increment(bgp, p, pi, afi, safi);
6258 0 : bgp_process(bgp, dest, afi, safi);
6259 :
6260 0 : if (SAFI_UNICAST == safi
6261 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6262 : || bgp->inst_type
6263 : == BGP_INSTANCE_TYPE_DEFAULT)) {
6264 0 : vpn_leak_from_vrf_update(bgp_get_default(), bgp,
6265 : pi);
6266 : }
6267 :
6268 0 : bgp_dest_unlock_node(dest);
6269 0 : aspath_unintern(&attr.aspath);
6270 0 : return;
6271 : }
6272 : }
6273 :
6274 : /* Make new BGP info. */
6275 0 : new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
6276 : attr_new, dest);
6277 : /* Nexthop reachability check. */
6278 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
6279 0 : && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
6280 0 : if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6281 : p))
6282 0 : bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
6283 : else {
6284 0 : if (BGP_DEBUG(nht, NHT)) {
6285 0 : char buf1[INET6_ADDRSTRLEN];
6286 :
6287 0 : inet_ntop(p->family, &p->u.prefix, buf1,
6288 : sizeof(buf1));
6289 0 : zlog_debug(
6290 : "%s(%s): Route not in table, not advertising",
6291 : __func__, buf1);
6292 : }
6293 0 : bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
6294 : }
6295 : } else {
6296 : /* Delete the NHT structure if any, if we're toggling between
6297 : * enabling/disabling import check. We deregister the route
6298 : * from NHT to avoid overloading NHT and the process interaction
6299 : */
6300 0 : bgp_unlink_nexthop(new);
6301 :
6302 0 : bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
6303 : }
6304 :
6305 : /* Aggregate address increment. */
6306 0 : bgp_aggregate_increment(bgp, p, new, afi, safi);
6307 :
6308 : /* Register new BGP information. */
6309 0 : bgp_path_info_add(dest, new);
6310 :
6311 : /* route_node_get lock */
6312 0 : bgp_dest_unlock_node(dest);
6313 :
6314 : /* Process change. */
6315 0 : bgp_process(bgp, dest, afi, safi);
6316 :
6317 0 : if (SAFI_UNICAST == safi
6318 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6319 : || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6320 0 : vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6321 : }
6322 :
6323 : /* Unintern original. */
6324 0 : aspath_unintern(&attr.aspath);
6325 : }
6326 :
6327 0 : void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
6328 : safi_t safi)
6329 : {
6330 0 : struct bgp_dest *dest;
6331 0 : struct bgp_path_info *pi;
6332 :
6333 0 : dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
6334 :
6335 : /* Check selected route and self inserted route. */
6336 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6337 0 : if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6338 0 : && pi->sub_type == BGP_ROUTE_STATIC)
6339 : break;
6340 :
6341 : /* Withdraw static BGP route from routing table. */
6342 0 : if (pi) {
6343 0 : if (SAFI_UNICAST == safi
6344 0 : && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6345 : || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6346 0 : vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
6347 : }
6348 0 : bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6349 0 : bgp_unlink_nexthop(pi);
6350 0 : bgp_path_info_delete(dest, pi);
6351 0 : bgp_process(bgp, dest, afi, safi);
6352 : }
6353 :
6354 : /* Unlock bgp_node_lookup. */
6355 0 : bgp_dest_unlock_node(dest);
6356 0 : }
6357 :
6358 : /*
6359 : * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6360 : */
6361 0 : static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
6362 : afi_t afi, safi_t safi,
6363 : struct prefix_rd *prd)
6364 : {
6365 0 : struct bgp_dest *dest;
6366 0 : struct bgp_path_info *pi;
6367 :
6368 0 : dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
6369 :
6370 : /* Check selected route and self inserted route. */
6371 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6372 0 : if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6373 0 : && pi->sub_type == BGP_ROUTE_STATIC)
6374 : break;
6375 :
6376 : /* Withdraw static BGP route from routing table. */
6377 0 : if (pi) {
6378 : #ifdef ENABLE_BGP_VNC
6379 0 : rfapiProcessWithdraw(
6380 0 : pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
6381 : 1); /* Kill, since it is an administrative change */
6382 : #endif
6383 0 : if (SAFI_MPLS_VPN == safi
6384 0 : && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6385 0 : vpn_leak_to_vrf_withdraw(pi);
6386 : }
6387 0 : bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6388 0 : bgp_path_info_delete(dest, pi);
6389 0 : bgp_process(bgp, dest, afi, safi);
6390 : }
6391 :
6392 : /* Unlock bgp_node_lookup. */
6393 0 : bgp_dest_unlock_node(dest);
6394 0 : }
6395 :
6396 0 : static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
6397 : struct bgp_static *bgp_static, afi_t afi,
6398 : safi_t safi)
6399 : {
6400 0 : struct bgp_dest *dest;
6401 0 : struct bgp_path_info *new;
6402 0 : struct attr *attr_new;
6403 0 : struct attr attr = {0};
6404 0 : struct bgp_path_info *pi;
6405 : #ifdef ENABLE_BGP_VNC
6406 0 : mpls_label_t label = 0;
6407 : #endif
6408 0 : uint32_t num_labels = 0;
6409 :
6410 0 : assert(bgp_static);
6411 :
6412 0 : if (bgp_static->label != MPLS_INVALID_LABEL)
6413 0 : num_labels = 1;
6414 0 : dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6415 : &bgp_static->prd);
6416 :
6417 0 : bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
6418 :
6419 0 : attr.nexthop = bgp_static->igpnexthop;
6420 0 : attr.med = bgp_static->igpmetric;
6421 0 : attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6422 :
6423 0 : if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6424 0 : || (safi == SAFI_ENCAP)) {
6425 0 : if (afi == AFI_IP) {
6426 0 : attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6427 0 : attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6428 : }
6429 : }
6430 0 : if (afi == AFI_L2VPN) {
6431 0 : if (bgp_static->gatewayIp.family == AF_INET) {
6432 0 : SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6433 0 : memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
6434 : &bgp_static->gatewayIp.u.prefix4,
6435 : IPV4_MAX_BYTELEN);
6436 0 : } else if (bgp_static->gatewayIp.family == AF_INET6) {
6437 0 : SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6438 0 : memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
6439 : &bgp_static->gatewayIp.u.prefix6,
6440 : IPV6_MAX_BYTELEN);
6441 : }
6442 0 : memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
6443 0 : if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6444 0 : struct bgp_encap_type_vxlan bet;
6445 0 : memset(&bet, 0, sizeof(bet));
6446 0 : bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
6447 0 : bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6448 : }
6449 0 : if (bgp_static->router_mac) {
6450 0 : bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6451 : }
6452 : }
6453 : /* Apply route-map. */
6454 0 : if (bgp_static->rmap.name) {
6455 0 : struct attr attr_tmp = attr;
6456 0 : struct bgp_path_info rmap_path;
6457 0 : route_map_result_t ret;
6458 :
6459 0 : rmap_path.peer = bgp->peer_self;
6460 0 : rmap_path.attr = &attr_tmp;
6461 :
6462 0 : SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
6463 :
6464 0 : ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
6465 :
6466 0 : bgp->peer_self->rmap_type = 0;
6467 :
6468 0 : if (ret == RMAP_DENYMATCH) {
6469 : /* Free uninterned attribute. */
6470 0 : bgp_attr_flush(&attr_tmp);
6471 :
6472 : /* Unintern original. */
6473 0 : aspath_unintern(&attr.aspath);
6474 0 : bgp_static_withdraw_safi(bgp, p, afi, safi,
6475 : &bgp_static->prd);
6476 0 : bgp_dest_unlock_node(dest);
6477 0 : return;
6478 : }
6479 :
6480 0 : attr_new = bgp_attr_intern(&attr_tmp);
6481 : } else {
6482 0 : attr_new = bgp_attr_intern(&attr);
6483 : }
6484 :
6485 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
6486 0 : if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6487 0 : && pi->sub_type == BGP_ROUTE_STATIC)
6488 : break;
6489 :
6490 0 : if (pi) {
6491 0 : if (attrhash_cmp(pi->attr, attr_new)
6492 0 : && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
6493 0 : bgp_dest_unlock_node(dest);
6494 0 : bgp_attr_unintern(&attr_new);
6495 0 : aspath_unintern(&attr.aspath);
6496 0 : return;
6497 : } else {
6498 : /* The attribute is changed. */
6499 0 : bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
6500 :
6501 : /* Rewrite BGP route information. */
6502 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
6503 0 : bgp_path_info_restore(dest, pi);
6504 : else
6505 0 : bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6506 0 : bgp_attr_unintern(&pi->attr);
6507 0 : pi->attr = attr_new;
6508 0 : pi->uptime = monotime(NULL);
6509 : #ifdef ENABLE_BGP_VNC
6510 0 : if (pi->extra)
6511 0 : label = decode_label(&pi->extra->label[0]);
6512 : #endif
6513 :
6514 : /* Process change. */
6515 0 : bgp_aggregate_increment(bgp, p, pi, afi, safi);
6516 0 : bgp_process(bgp, dest, afi, safi);
6517 :
6518 0 : if (SAFI_MPLS_VPN == safi
6519 0 : && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6520 0 : vpn_leak_to_vrf_update(bgp, pi,
6521 : &bgp_static->prd);
6522 : }
6523 : #ifdef ENABLE_BGP_VNC
6524 0 : rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6525 0 : pi->attr, afi, safi, pi->type,
6526 0 : pi->sub_type, &label);
6527 : #endif
6528 0 : bgp_dest_unlock_node(dest);
6529 0 : aspath_unintern(&attr.aspath);
6530 0 : return;
6531 : }
6532 : }
6533 :
6534 :
6535 : /* Make new BGP info. */
6536 0 : new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
6537 : attr_new, dest);
6538 0 : SET_FLAG(new->flags, BGP_PATH_VALID);
6539 0 : bgp_path_info_extra_get(new);
6540 0 : if (num_labels) {
6541 0 : new->extra->label[0] = bgp_static->label;
6542 0 : new->extra->num_labels = num_labels;
6543 : }
6544 : #ifdef ENABLE_BGP_VNC
6545 0 : label = decode_label(&bgp_static->label);
6546 : #endif
6547 :
6548 : /* Aggregate address increment. */
6549 0 : bgp_aggregate_increment(bgp, p, new, afi, safi);
6550 :
6551 : /* Register new BGP information. */
6552 0 : bgp_path_info_add(dest, new);
6553 : /* route_node_get lock */
6554 0 : bgp_dest_unlock_node(dest);
6555 :
6556 : /* Process change. */
6557 0 : bgp_process(bgp, dest, afi, safi);
6558 :
6559 0 : if (SAFI_MPLS_VPN == safi
6560 0 : && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6561 0 : vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
6562 : }
6563 : #ifdef ENABLE_BGP_VNC
6564 0 : rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6565 0 : safi, new->type, new->sub_type, &label);
6566 : #endif
6567 :
6568 : /* Unintern original. */
6569 0 : aspath_unintern(&attr.aspath);
6570 : }
6571 :
6572 : /* Configure static BGP network. When user don't run zebra, static
6573 : route should be installed as valid. */
6574 0 : static int bgp_static_set(struct vty *vty, const char *negate,
6575 : const char *ip_str, afi_t afi, safi_t safi,
6576 : const char *rmap, int backdoor, uint32_t label_index)
6577 : {
6578 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
6579 0 : int ret;
6580 0 : struct prefix p;
6581 0 : struct bgp_static *bgp_static;
6582 0 : struct bgp_dest *dest;
6583 0 : uint8_t need_update = 0;
6584 :
6585 : /* Convert IP prefix string to struct prefix. */
6586 0 : ret = str2prefix(ip_str, &p);
6587 0 : if (!ret) {
6588 0 : vty_out(vty, "%% Malformed prefix\n");
6589 0 : return CMD_WARNING_CONFIG_FAILED;
6590 : }
6591 0 : if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6592 0 : vty_out(vty, "%% Malformed prefix (link-local address)\n");
6593 0 : return CMD_WARNING_CONFIG_FAILED;
6594 : }
6595 :
6596 0 : apply_mask(&p);
6597 :
6598 0 : if (negate) {
6599 :
6600 : /* Set BGP static route configuration. */
6601 0 : dest = bgp_node_lookup(bgp->route[afi][safi], &p);
6602 :
6603 0 : if (!dest) {
6604 0 : vty_out(vty, "%% Can't find static route specified\n");
6605 0 : return CMD_WARNING_CONFIG_FAILED;
6606 : }
6607 :
6608 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
6609 :
6610 0 : if ((label_index != BGP_INVALID_LABEL_INDEX)
6611 0 : && (label_index != bgp_static->label_index)) {
6612 0 : vty_out(vty,
6613 : "%% label-index doesn't match static route\n");
6614 0 : bgp_dest_unlock_node(dest);
6615 0 : return CMD_WARNING_CONFIG_FAILED;
6616 : }
6617 :
6618 0 : if ((rmap && bgp_static->rmap.name)
6619 0 : && strcmp(rmap, bgp_static->rmap.name)) {
6620 0 : vty_out(vty,
6621 : "%% route-map name doesn't match static route\n");
6622 0 : bgp_dest_unlock_node(dest);
6623 0 : return CMD_WARNING_CONFIG_FAILED;
6624 : }
6625 :
6626 : /* Update BGP RIB. */
6627 0 : if (!bgp_static->backdoor)
6628 0 : bgp_static_withdraw(bgp, &p, afi, safi);
6629 :
6630 : /* Clear configuration. */
6631 0 : bgp_static_free(bgp_static);
6632 0 : bgp_dest_set_bgp_static_info(dest, NULL);
6633 0 : bgp_dest_unlock_node(dest);
6634 0 : bgp_dest_unlock_node(dest);
6635 : } else {
6636 :
6637 : /* Set BGP static route configuration. */
6638 0 : dest = bgp_node_get(bgp->route[afi][safi], &p);
6639 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
6640 0 : if (bgp_static) {
6641 : /* Configuration change. */
6642 : /* Label index cannot be changed. */
6643 0 : if (bgp_static->label_index != label_index) {
6644 0 : vty_out(vty, "%% cannot change label-index\n");
6645 0 : bgp_dest_unlock_node(dest);
6646 0 : return CMD_WARNING_CONFIG_FAILED;
6647 : }
6648 :
6649 : /* Check previous routes are installed into BGP. */
6650 0 : if (bgp_static->valid
6651 0 : && bgp_static->backdoor != backdoor)
6652 0 : need_update = 1;
6653 :
6654 0 : bgp_static->backdoor = backdoor;
6655 :
6656 0 : if (rmap) {
6657 0 : XFREE(MTYPE_ROUTE_MAP_NAME,
6658 : bgp_static->rmap.name);
6659 0 : route_map_counter_decrement(
6660 : bgp_static->rmap.map);
6661 0 : bgp_static->rmap.name =
6662 0 : XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6663 0 : bgp_static->rmap.map =
6664 0 : route_map_lookup_by_name(rmap);
6665 0 : route_map_counter_increment(
6666 : bgp_static->rmap.map);
6667 : } else {
6668 0 : XFREE(MTYPE_ROUTE_MAP_NAME,
6669 : bgp_static->rmap.name);
6670 0 : route_map_counter_decrement(
6671 : bgp_static->rmap.map);
6672 0 : bgp_static->rmap.map = NULL;
6673 0 : bgp_static->valid = 0;
6674 : }
6675 0 : bgp_dest_unlock_node(dest);
6676 : } else {
6677 : /* New configuration. */
6678 0 : bgp_static = bgp_static_new();
6679 0 : bgp_static->backdoor = backdoor;
6680 0 : bgp_static->valid = 0;
6681 0 : bgp_static->igpmetric = 0;
6682 0 : bgp_static->igpnexthop.s_addr = INADDR_ANY;
6683 0 : bgp_static->label_index = label_index;
6684 :
6685 0 : if (rmap) {
6686 0 : XFREE(MTYPE_ROUTE_MAP_NAME,
6687 : bgp_static->rmap.name);
6688 0 : route_map_counter_decrement(
6689 : bgp_static->rmap.map);
6690 0 : bgp_static->rmap.name =
6691 0 : XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6692 0 : bgp_static->rmap.map =
6693 0 : route_map_lookup_by_name(rmap);
6694 0 : route_map_counter_increment(
6695 : bgp_static->rmap.map);
6696 : }
6697 0 : bgp_dest_set_bgp_static_info(dest, bgp_static);
6698 : }
6699 :
6700 0 : bgp_static->valid = 1;
6701 0 : if (need_update)
6702 0 : bgp_static_withdraw(bgp, &p, afi, safi);
6703 :
6704 0 : if (!bgp_static->backdoor)
6705 0 : bgp_static_update(bgp, &p, bgp_static, afi, safi);
6706 : }
6707 :
6708 : return CMD_SUCCESS;
6709 : }
6710 :
6711 0 : void bgp_static_add(struct bgp *bgp)
6712 : {
6713 0 : afi_t afi;
6714 0 : safi_t safi;
6715 0 : struct bgp_dest *dest;
6716 0 : struct bgp_dest *rm;
6717 0 : struct bgp_table *table;
6718 0 : struct bgp_static *bgp_static;
6719 :
6720 0 : SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6721 0 : FOREACH_AFI_SAFI (afi, safi)
6722 0 : for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6723 0 : dest = bgp_route_next(dest)) {
6724 0 : if (!bgp_dest_has_bgp_path_info_data(dest))
6725 0 : continue;
6726 :
6727 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6728 0 : || (safi == SAFI_EVPN)) {
6729 0 : table = bgp_dest_get_bgp_table_info(dest);
6730 :
6731 0 : for (rm = bgp_table_top(table); rm;
6732 0 : rm = bgp_route_next(rm)) {
6733 0 : bgp_static =
6734 0 : bgp_dest_get_bgp_static_info(
6735 : rm);
6736 0 : bgp_static_update_safi(
6737 : bgp, bgp_dest_get_prefix(rm),
6738 : bgp_static, afi, safi);
6739 : }
6740 : } else {
6741 0 : bgp_static_update(
6742 : bgp, bgp_dest_get_prefix(dest),
6743 : bgp_dest_get_bgp_static_info(dest), afi,
6744 : safi);
6745 : }
6746 : }
6747 0 : UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6748 0 : }
6749 :
6750 : /* Called from bgp_delete(). Delete all static routes from the BGP
6751 : instance. */
6752 1 : void bgp_static_delete(struct bgp *bgp)
6753 : {
6754 1 : afi_t afi;
6755 1 : safi_t safi;
6756 1 : struct bgp_dest *dest;
6757 1 : struct bgp_dest *rm;
6758 1 : struct bgp_table *table;
6759 1 : struct bgp_static *bgp_static;
6760 :
6761 25 : FOREACH_AFI_SAFI (afi, safi)
6762 42 : for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6763 0 : dest = bgp_route_next(dest)) {
6764 0 : if (!bgp_dest_has_bgp_path_info_data(dest))
6765 0 : continue;
6766 :
6767 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6768 0 : || (safi == SAFI_EVPN)) {
6769 0 : table = bgp_dest_get_bgp_table_info(dest);
6770 :
6771 0 : for (rm = bgp_table_top(table); rm;
6772 0 : rm = bgp_route_next(rm)) {
6773 0 : bgp_static =
6774 0 : bgp_dest_get_bgp_static_info(
6775 : rm);
6776 0 : if (!bgp_static)
6777 0 : continue;
6778 :
6779 0 : bgp_static_withdraw_safi(
6780 : bgp, bgp_dest_get_prefix(rm),
6781 : AFI_IP, safi,
6782 : (struct prefix_rd *)
6783 0 : bgp_dest_get_prefix(
6784 : dest));
6785 0 : bgp_static_free(bgp_static);
6786 0 : bgp_dest_set_bgp_static_info(rm,
6787 : NULL);
6788 0 : bgp_dest_unlock_node(rm);
6789 : }
6790 : } else {
6791 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
6792 0 : bgp_static_withdraw(bgp,
6793 : bgp_dest_get_prefix(dest),
6794 : afi, safi);
6795 0 : bgp_static_free(bgp_static);
6796 0 : bgp_dest_set_bgp_static_info(dest, NULL);
6797 0 : bgp_dest_unlock_node(dest);
6798 : }
6799 : }
6800 1 : }
6801 :
6802 0 : void bgp_static_redo_import_check(struct bgp *bgp)
6803 : {
6804 0 : afi_t afi;
6805 0 : safi_t safi;
6806 0 : struct bgp_dest *dest;
6807 0 : struct bgp_dest *rm;
6808 0 : struct bgp_table *table;
6809 0 : struct bgp_static *bgp_static;
6810 :
6811 : /* Use this flag to force reprocessing of the route */
6812 0 : SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6813 0 : FOREACH_AFI_SAFI (afi, safi) {
6814 0 : for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6815 0 : dest = bgp_route_next(dest)) {
6816 0 : if (!bgp_dest_has_bgp_path_info_data(dest))
6817 0 : continue;
6818 :
6819 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6820 0 : || (safi == SAFI_EVPN)) {
6821 0 : table = bgp_dest_get_bgp_table_info(dest);
6822 :
6823 0 : for (rm = bgp_table_top(table); rm;
6824 0 : rm = bgp_route_next(rm)) {
6825 0 : bgp_static =
6826 0 : bgp_dest_get_bgp_static_info(
6827 : rm);
6828 0 : bgp_static_update_safi(
6829 : bgp, bgp_dest_get_prefix(rm),
6830 : bgp_static, afi, safi);
6831 : }
6832 : } else {
6833 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
6834 0 : bgp_static_update(bgp,
6835 : bgp_dest_get_prefix(dest),
6836 : bgp_static, afi, safi);
6837 : }
6838 : }
6839 : }
6840 0 : UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6841 0 : }
6842 :
6843 0 : static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6844 : safi_t safi)
6845 : {
6846 0 : struct bgp_table *table;
6847 0 : struct bgp_dest *dest;
6848 0 : struct bgp_path_info *pi;
6849 :
6850 : /* Do not install the aggregate route if BGP is in the
6851 : * process of termination.
6852 : */
6853 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6854 0 : || (bgp->peer_self == NULL))
6855 : return;
6856 :
6857 0 : table = bgp->rib[afi][safi];
6858 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6859 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6860 0 : if (pi->peer == bgp->peer_self
6861 0 : && ((pi->type == ZEBRA_ROUTE_BGP
6862 0 : && pi->sub_type == BGP_ROUTE_STATIC)
6863 0 : || (pi->type != ZEBRA_ROUTE_BGP
6864 0 : && pi->sub_type
6865 : == BGP_ROUTE_REDISTRIBUTE))) {
6866 0 : bgp_aggregate_decrement(
6867 : bgp, bgp_dest_get_prefix(dest), pi, afi,
6868 : safi);
6869 0 : bgp_unlink_nexthop(pi);
6870 0 : bgp_path_info_delete(dest, pi);
6871 0 : bgp_process(bgp, dest, afi, safi);
6872 : }
6873 : }
6874 : }
6875 : }
6876 :
6877 : /*
6878 : * Purge all networks and redistributed routes from routing table.
6879 : * Invoked upon the instance going down.
6880 : */
6881 0 : void bgp_purge_static_redist_routes(struct bgp *bgp)
6882 : {
6883 0 : afi_t afi;
6884 0 : safi_t safi;
6885 :
6886 0 : FOREACH_AFI_SAFI (afi, safi)
6887 0 : bgp_purge_af_static_redist_routes(bgp, afi, safi);
6888 0 : }
6889 :
6890 : /*
6891 : * gpz 110624
6892 : * Currently this is used to set static routes for VPN and ENCAP.
6893 : * I think it can probably be factored with bgp_static_set.
6894 : */
6895 0 : int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6896 : const char *ip_str, const char *rd_str,
6897 : const char *label_str, const char *rmap_str,
6898 : int evpn_type, const char *esi, const char *gwip,
6899 : const char *ethtag, const char *routermac)
6900 : {
6901 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
6902 0 : int ret;
6903 0 : struct prefix p;
6904 0 : struct prefix_rd prd;
6905 0 : struct bgp_dest *pdest;
6906 0 : struct bgp_dest *dest;
6907 0 : struct bgp_table *table;
6908 0 : struct bgp_static *bgp_static;
6909 0 : mpls_label_t label = MPLS_INVALID_LABEL;
6910 0 : struct prefix gw_ip;
6911 :
6912 : /* validate ip prefix */
6913 0 : ret = str2prefix(ip_str, &p);
6914 0 : if (!ret) {
6915 0 : vty_out(vty, "%% Malformed prefix\n");
6916 0 : return CMD_WARNING_CONFIG_FAILED;
6917 : }
6918 0 : apply_mask(&p);
6919 0 : if ((afi == AFI_L2VPN)
6920 0 : && (bgp_build_evpn_prefix(evpn_type,
6921 0 : ethtag != NULL ? atol(ethtag) : 0, &p))) {
6922 0 : vty_out(vty, "%% L2VPN prefix could not be forged\n");
6923 0 : return CMD_WARNING_CONFIG_FAILED;
6924 : }
6925 :
6926 0 : ret = str2prefix_rd(rd_str, &prd);
6927 0 : if (!ret) {
6928 0 : vty_out(vty, "%% Malformed rd\n");
6929 0 : return CMD_WARNING_CONFIG_FAILED;
6930 : }
6931 :
6932 0 : if (label_str) {
6933 0 : unsigned long label_val;
6934 0 : label_val = strtoul(label_str, NULL, 10);
6935 0 : encode_label(label_val, &label);
6936 : }
6937 :
6938 0 : if (safi == SAFI_EVPN) {
6939 0 : if (esi && str2esi(esi, NULL) == 0) {
6940 0 : vty_out(vty, "%% Malformed ESI\n");
6941 0 : return CMD_WARNING_CONFIG_FAILED;
6942 : }
6943 0 : if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6944 0 : vty_out(vty, "%% Malformed Router MAC\n");
6945 0 : return CMD_WARNING_CONFIG_FAILED;
6946 : }
6947 0 : if (gwip) {
6948 0 : memset(&gw_ip, 0, sizeof(gw_ip));
6949 0 : ret = str2prefix(gwip, &gw_ip);
6950 0 : if (!ret) {
6951 0 : vty_out(vty, "%% Malformed GatewayIp\n");
6952 0 : return CMD_WARNING_CONFIG_FAILED;
6953 : }
6954 0 : if ((gw_ip.family == AF_INET
6955 0 : && is_evpn_prefix_ipaddr_v6(
6956 : (struct prefix_evpn *)&p))
6957 0 : || (gw_ip.family == AF_INET6
6958 0 : && is_evpn_prefix_ipaddr_v4(
6959 : (struct prefix_evpn *)&p))) {
6960 0 : vty_out(vty,
6961 : "%% GatewayIp family differs with IP prefix\n");
6962 0 : return CMD_WARNING_CONFIG_FAILED;
6963 : }
6964 : }
6965 : }
6966 0 : pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6967 0 : if (!bgp_dest_has_bgp_path_info_data(pdest))
6968 0 : bgp_dest_set_bgp_table_info(pdest,
6969 : bgp_table_init(bgp, afi, safi));
6970 0 : table = bgp_dest_get_bgp_table_info(pdest);
6971 :
6972 0 : dest = bgp_node_get(table, &p);
6973 :
6974 0 : if (bgp_dest_has_bgp_path_info_data(dest)) {
6975 0 : vty_out(vty, "%% Same network configuration exists\n");
6976 0 : bgp_dest_unlock_node(dest);
6977 : } else {
6978 : /* New configuration. */
6979 0 : bgp_static = bgp_static_new();
6980 0 : bgp_static->backdoor = 0;
6981 0 : bgp_static->valid = 0;
6982 0 : bgp_static->igpmetric = 0;
6983 0 : bgp_static->igpnexthop.s_addr = INADDR_ANY;
6984 0 : bgp_static->label = label;
6985 0 : bgp_static->prd = prd;
6986 :
6987 0 : if (rmap_str) {
6988 0 : XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
6989 0 : route_map_counter_decrement(bgp_static->rmap.map);
6990 0 : bgp_static->rmap.name =
6991 0 : XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6992 0 : bgp_static->rmap.map =
6993 0 : route_map_lookup_by_name(rmap_str);
6994 0 : route_map_counter_increment(bgp_static->rmap.map);
6995 : }
6996 :
6997 0 : if (safi == SAFI_EVPN) {
6998 0 : if (esi) {
6999 0 : bgp_static->eth_s_id =
7000 0 : XCALLOC(MTYPE_ATTR,
7001 : sizeof(esi_t));
7002 0 : str2esi(esi, bgp_static->eth_s_id);
7003 : }
7004 0 : if (routermac) {
7005 0 : bgp_static->router_mac =
7006 0 : XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
7007 0 : (void)prefix_str2mac(routermac,
7008 : bgp_static->router_mac);
7009 : }
7010 0 : if (gwip)
7011 0 : prefix_copy(&bgp_static->gatewayIp, &gw_ip);
7012 : }
7013 0 : bgp_dest_set_bgp_static_info(dest, bgp_static);
7014 :
7015 0 : bgp_static->valid = 1;
7016 0 : bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
7017 : }
7018 :
7019 : return CMD_SUCCESS;
7020 : }
7021 :
7022 : /* Configure static BGP network. */
7023 0 : int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
7024 : const char *ip_str, const char *rd_str,
7025 : const char *label_str, int evpn_type, const char *esi,
7026 : const char *gwip, const char *ethtag)
7027 : {
7028 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
7029 0 : int ret;
7030 0 : struct prefix p;
7031 0 : struct prefix_rd prd;
7032 0 : struct bgp_dest *pdest;
7033 0 : struct bgp_dest *dest;
7034 0 : struct bgp_table *table;
7035 0 : struct bgp_static *bgp_static;
7036 0 : mpls_label_t label = MPLS_INVALID_LABEL;
7037 :
7038 : /* Convert IP prefix string to struct prefix. */
7039 0 : ret = str2prefix(ip_str, &p);
7040 0 : if (!ret) {
7041 0 : vty_out(vty, "%% Malformed prefix\n");
7042 0 : return CMD_WARNING_CONFIG_FAILED;
7043 : }
7044 0 : apply_mask(&p);
7045 0 : if ((afi == AFI_L2VPN)
7046 0 : && (bgp_build_evpn_prefix(evpn_type,
7047 0 : ethtag != NULL ? atol(ethtag) : 0, &p))) {
7048 0 : vty_out(vty, "%% L2VPN prefix could not be forged\n");
7049 0 : return CMD_WARNING_CONFIG_FAILED;
7050 : }
7051 0 : ret = str2prefix_rd(rd_str, &prd);
7052 0 : if (!ret) {
7053 0 : vty_out(vty, "%% Malformed rd\n");
7054 0 : return CMD_WARNING_CONFIG_FAILED;
7055 : }
7056 :
7057 0 : if (label_str) {
7058 0 : unsigned long label_val;
7059 0 : label_val = strtoul(label_str, NULL, 10);
7060 0 : encode_label(label_val, &label);
7061 : }
7062 :
7063 0 : pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
7064 0 : if (!bgp_dest_has_bgp_path_info_data(pdest))
7065 0 : bgp_dest_set_bgp_table_info(pdest,
7066 : bgp_table_init(bgp, afi, safi));
7067 : else
7068 0 : bgp_dest_unlock_node(pdest);
7069 0 : table = bgp_dest_get_bgp_table_info(pdest);
7070 :
7071 0 : dest = bgp_node_lookup(table, &p);
7072 :
7073 0 : if (dest) {
7074 0 : bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
7075 :
7076 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
7077 0 : bgp_static_free(bgp_static);
7078 0 : bgp_dest_set_bgp_static_info(dest, NULL);
7079 0 : bgp_dest_unlock_node(dest);
7080 0 : bgp_dest_unlock_node(dest);
7081 : } else
7082 0 : vty_out(vty, "%% Can't find the route\n");
7083 :
7084 : return CMD_SUCCESS;
7085 : }
7086 :
7087 0 : static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
7088 : const char *rmap_name)
7089 : {
7090 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
7091 0 : struct bgp_rmap *rmap;
7092 :
7093 0 : rmap = &bgp->table_map[afi][safi];
7094 0 : if (rmap_name) {
7095 0 : XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
7096 0 : route_map_counter_decrement(rmap->map);
7097 0 : rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
7098 0 : rmap->map = route_map_lookup_by_name(rmap_name);
7099 0 : route_map_counter_increment(rmap->map);
7100 : } else {
7101 0 : XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
7102 0 : route_map_counter_decrement(rmap->map);
7103 0 : rmap->map = NULL;
7104 : }
7105 :
7106 0 : if (bgp_fibupd_safi(safi))
7107 0 : bgp_zebra_announce_table(bgp, afi, safi);
7108 :
7109 : return CMD_SUCCESS;
7110 : }
7111 :
7112 0 : static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
7113 : const char *rmap_name)
7114 : {
7115 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
7116 0 : struct bgp_rmap *rmap;
7117 :
7118 0 : rmap = &bgp->table_map[afi][safi];
7119 0 : XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
7120 0 : route_map_counter_decrement(rmap->map);
7121 0 : rmap->map = NULL;
7122 :
7123 0 : if (bgp_fibupd_safi(safi))
7124 0 : bgp_zebra_announce_table(bgp, afi, safi);
7125 :
7126 : return CMD_SUCCESS;
7127 : }
7128 :
7129 0 : void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
7130 : safi_t safi)
7131 : {
7132 0 : if (bgp->table_map[afi][safi].name) {
7133 0 : vty_out(vty, " table-map %s\n",
7134 : bgp->table_map[afi][safi].name);
7135 : }
7136 0 : }
7137 :
7138 0 : DEFUN (bgp_table_map,
7139 : bgp_table_map_cmd,
7140 : "table-map WORD",
7141 : "BGP table to RIB route download filter\n"
7142 : "Name of the route map\n")
7143 : {
7144 0 : int idx_word = 1;
7145 0 : return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7146 0 : argv[idx_word]->arg);
7147 : }
7148 0 : DEFUN (no_bgp_table_map,
7149 : no_bgp_table_map_cmd,
7150 : "no table-map WORD",
7151 : NO_STR
7152 : "BGP table to RIB route download filter\n"
7153 : "Name of the route map\n")
7154 : {
7155 0 : int idx_word = 2;
7156 0 : return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7157 0 : argv[idx_word]->arg);
7158 : }
7159 :
7160 0 : DEFPY(bgp_network,
7161 : bgp_network_cmd,
7162 : "[no] network \
7163 : <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
7164 : [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
7165 : backdoor$backdoor}]",
7166 : NO_STR
7167 : "Specify a network to announce via BGP\n"
7168 : "IPv4 prefix\n"
7169 : "Network number\n"
7170 : "Network mask\n"
7171 : "Network mask\n"
7172 : "Route-map to modify the attributes\n"
7173 : "Name of the route map\n"
7174 : "Label index to associate with the prefix\n"
7175 : "Label index value\n"
7176 : "Specify a BGP backdoor route\n")
7177 : {
7178 0 : char addr_prefix_str[BUFSIZ];
7179 :
7180 0 : if (address_str) {
7181 0 : int ret;
7182 :
7183 0 : ret = netmask_str2prefix_str(address_str, netmask_str,
7184 : addr_prefix_str,
7185 : sizeof(addr_prefix_str));
7186 0 : if (!ret) {
7187 0 : vty_out(vty, "%% Inconsistent address and mask\n");
7188 0 : return CMD_WARNING_CONFIG_FAILED;
7189 : }
7190 : }
7191 :
7192 0 : return bgp_static_set(
7193 : vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7194 : bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7195 : label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
7196 : }
7197 :
7198 0 : DEFPY(ipv6_bgp_network,
7199 : ipv6_bgp_network_cmd,
7200 : "[no] network X:X::X:X/M$prefix \
7201 : [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
7202 : NO_STR
7203 : "Specify a network to announce via BGP\n"
7204 : "IPv6 prefix\n"
7205 : "Route-map to modify the attributes\n"
7206 : "Name of the route map\n"
7207 : "Label index to associate with the prefix\n"
7208 : "Label index value\n")
7209 : {
7210 0 : return bgp_static_set(
7211 : vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7212 : label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
7213 : }
7214 :
7215 0 : static struct bgp_aggregate *bgp_aggregate_new(void)
7216 : {
7217 0 : return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
7218 : }
7219 :
7220 0 : static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
7221 : {
7222 0 : XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7223 0 : route_map_counter_decrement(aggregate->suppress_map);
7224 0 : XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7225 0 : route_map_counter_decrement(aggregate->rmap.map);
7226 0 : XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7227 0 : }
7228 :
7229 : /**
7230 : * Helper function to avoid repeated code: prepare variables for a
7231 : * `route_map_apply` call.
7232 : *
7233 : * \returns `true` on route map match, otherwise `false`.
7234 : */
7235 0 : static bool aggr_suppress_map_test(struct bgp *bgp,
7236 : struct bgp_aggregate *aggregate,
7237 : struct bgp_path_info *pi)
7238 : {
7239 0 : const struct prefix *p = bgp_dest_get_prefix(pi->net);
7240 0 : route_map_result_t rmr = RMAP_DENYMATCH;
7241 0 : struct bgp_path_info rmap_path = {};
7242 0 : struct attr attr = {};
7243 :
7244 : /* No route map entries created, just don't match. */
7245 0 : if (aggregate->suppress_map == NULL)
7246 : return false;
7247 :
7248 : /* Call route map matching and return result. */
7249 0 : attr.aspath = aspath_empty();
7250 0 : rmap_path.peer = bgp->peer_self;
7251 0 : rmap_path.attr = &attr;
7252 :
7253 0 : SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
7254 0 : rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
7255 0 : bgp->peer_self->rmap_type = 0;
7256 :
7257 0 : bgp_attr_flush(&attr);
7258 0 : aspath_unintern(&attr.aspath);
7259 :
7260 0 : return rmr == RMAP_PERMITMATCH;
7261 : }
7262 :
7263 : /** Test whether the aggregation has suppressed this path or not. */
7264 0 : static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7265 : struct bgp_path_info *pi)
7266 : {
7267 0 : if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7268 : return false;
7269 :
7270 0 : return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7271 : }
7272 :
7273 : /**
7274 : * Suppress this path and keep the reference.
7275 : *
7276 : * \returns `true` if needs processing otherwise `false`.
7277 : */
7278 0 : static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7279 : struct bgp_path_info *pi)
7280 : {
7281 0 : struct bgp_path_info_extra *pie;
7282 :
7283 : /* Path is already suppressed by this aggregation. */
7284 0 : if (aggr_suppress_exists(aggregate, pi))
7285 : return false;
7286 :
7287 0 : pie = bgp_path_info_extra_get(pi);
7288 :
7289 : /* This is the first suppression, allocate memory and list it. */
7290 0 : if (pie->aggr_suppressors == NULL)
7291 0 : pie->aggr_suppressors = list_new();
7292 :
7293 0 : listnode_add(pie->aggr_suppressors, aggregate);
7294 :
7295 : /* Only mark for processing if suppressed. */
7296 0 : if (listcount(pie->aggr_suppressors) == 1) {
7297 0 : if (BGP_DEBUG(update, UPDATE_OUT))
7298 0 : zlog_debug("aggregate-address suppressing: %pFX",
7299 : bgp_dest_get_prefix(pi->net));
7300 :
7301 0 : bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7302 0 : return true;
7303 : }
7304 :
7305 : return false;
7306 : }
7307 :
7308 : /**
7309 : * Unsuppress this path and remove the reference.
7310 : *
7311 : * \returns `true` if needs processing otherwise `false`.
7312 : */
7313 0 : static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7314 : struct bgp_path_info *pi)
7315 : {
7316 : /* Path wasn't suppressed. */
7317 0 : if (!aggr_suppress_exists(aggregate, pi))
7318 : return false;
7319 :
7320 0 : listnode_delete(pi->extra->aggr_suppressors, aggregate);
7321 :
7322 : /* Unsuppress and free extra memory if last item. */
7323 0 : if (listcount(pi->extra->aggr_suppressors) == 0) {
7324 0 : if (BGP_DEBUG(update, UPDATE_OUT))
7325 0 : zlog_debug("aggregate-address unsuppressing: %pFX",
7326 : bgp_dest_get_prefix(pi->net));
7327 :
7328 0 : list_delete(&pi->extra->aggr_suppressors);
7329 0 : bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7330 0 : return true;
7331 : }
7332 :
7333 : return false;
7334 : }
7335 :
7336 0 : static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7337 : struct aspath *aspath,
7338 : struct community *comm,
7339 : struct ecommunity *ecomm,
7340 : struct lcommunity *lcomm)
7341 : {
7342 0 : static struct aspath *ae = NULL;
7343 :
7344 0 : if (!ae)
7345 0 : ae = aspath_empty();
7346 :
7347 0 : if (!pi)
7348 : return false;
7349 :
7350 0 : if (origin != pi->attr->origin)
7351 : return false;
7352 :
7353 0 : if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
7354 : return false;
7355 :
7356 0 : if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
7357 : return false;
7358 :
7359 0 : if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
7360 : return false;
7361 :
7362 0 : if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
7363 : return false;
7364 :
7365 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7366 : return false;
7367 :
7368 : return true;
7369 : }
7370 :
7371 0 : static void bgp_aggregate_install(
7372 : struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7373 : uint8_t origin, struct aspath *aspath, struct community *community,
7374 : struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7375 : uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
7376 : {
7377 0 : struct bgp_dest *dest;
7378 0 : struct bgp_table *table;
7379 0 : struct bgp_path_info *pi, *orig, *new;
7380 0 : struct attr *attr;
7381 :
7382 0 : table = bgp->rib[afi][safi];
7383 :
7384 0 : dest = bgp_node_get(table, p);
7385 :
7386 0 : for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
7387 0 : if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7388 0 : && pi->sub_type == BGP_ROUTE_AGGREGATE)
7389 : break;
7390 :
7391 : /*
7392 : * If we have paths with different MEDs, then don't install
7393 : * (or uninstall) the aggregate route.
7394 : */
7395 0 : if (aggregate->match_med && aggregate->med_mismatched)
7396 0 : goto uninstall_aggregate_route;
7397 :
7398 0 : if (aggregate->count > 0) {
7399 : /*
7400 : * If the aggregate information has not changed
7401 : * no need to re-install it again.
7402 : */
7403 0 : if (bgp_aggregate_info_same(orig, origin, aspath, community,
7404 : ecommunity, lcommunity)) {
7405 0 : bgp_dest_unlock_node(dest);
7406 :
7407 0 : if (aspath)
7408 0 : aspath_free(aspath);
7409 0 : if (community)
7410 0 : community_free(&community);
7411 0 : if (ecommunity)
7412 0 : ecommunity_free(&ecommunity);
7413 0 : if (lcommunity)
7414 0 : lcommunity_free(&lcommunity);
7415 :
7416 0 : return;
7417 : }
7418 :
7419 : /*
7420 : * Mark the old as unusable
7421 : */
7422 0 : if (pi)
7423 0 : bgp_path_info_delete(dest, pi);
7424 :
7425 0 : attr = bgp_attr_aggregate_intern(
7426 : bgp, origin, aspath, community, ecommunity, lcommunity,
7427 : aggregate, atomic_aggregate, p);
7428 :
7429 0 : if (!attr) {
7430 0 : bgp_dest_unlock_node(dest);
7431 0 : bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
7432 0 : if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7433 0 : zlog_debug("%s: %pFX null attribute", __func__,
7434 : p);
7435 0 : return;
7436 : }
7437 :
7438 0 : new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
7439 : bgp->peer_self, attr, dest);
7440 :
7441 0 : SET_FLAG(new->flags, BGP_PATH_VALID);
7442 :
7443 0 : bgp_path_info_add(dest, new);
7444 0 : bgp_process(bgp, dest, afi, safi);
7445 : } else {
7446 0 : uninstall_aggregate_route:
7447 0 : for (pi = orig; pi; pi = pi->next)
7448 0 : if (pi->peer == bgp->peer_self
7449 : && pi->type == ZEBRA_ROUTE_BGP
7450 0 : && pi->sub_type == BGP_ROUTE_AGGREGATE)
7451 : break;
7452 :
7453 : /* Withdraw static BGP route from routing table. */
7454 0 : if (pi) {
7455 0 : bgp_path_info_delete(dest, pi);
7456 0 : bgp_process(bgp, dest, afi, safi);
7457 : }
7458 : }
7459 :
7460 0 : bgp_dest_unlock_node(dest);
7461 : }
7462 :
7463 : /**
7464 : * Check if the current path has different MED than other known paths.
7465 : *
7466 : * \returns `true` if the MED matched the others else `false`.
7467 : */
7468 0 : static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7469 : struct bgp *bgp, struct bgp_path_info *pi)
7470 : {
7471 0 : uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7472 :
7473 : /* This is the first route being analyzed. */
7474 0 : if (!aggregate->med_initialized) {
7475 0 : aggregate->med_initialized = true;
7476 0 : aggregate->med_mismatched = false;
7477 0 : aggregate->med_matched_value = cur_med;
7478 : } else {
7479 : /* Check if routes with different MED showed up. */
7480 0 : if (cur_med != aggregate->med_matched_value)
7481 0 : aggregate->med_mismatched = true;
7482 : }
7483 :
7484 0 : return !aggregate->med_mismatched;
7485 : }
7486 :
7487 : /**
7488 : * Initializes and tests all routes in the aggregate address path for MED
7489 : * values.
7490 : *
7491 : * \returns `true` if all MEDs are the same otherwise `false`.
7492 : */
7493 0 : static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7494 : struct bgp *bgp, const struct prefix *p,
7495 : afi_t afi, safi_t safi)
7496 : {
7497 0 : struct bgp_table *table = bgp->rib[afi][safi];
7498 0 : const struct prefix *dest_p;
7499 0 : struct bgp_dest *dest, *top;
7500 0 : struct bgp_path_info *pi;
7501 0 : bool med_matched = true;
7502 :
7503 0 : aggregate->med_initialized = false;
7504 :
7505 0 : top = bgp_node_get(table, p);
7506 0 : for (dest = bgp_node_get(table, p); dest;
7507 0 : dest = bgp_route_next_until(dest, top)) {
7508 0 : dest_p = bgp_dest_get_prefix(dest);
7509 0 : if (dest_p->prefixlen <= p->prefixlen)
7510 0 : continue;
7511 :
7512 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7513 0 : if (BGP_PATH_HOLDDOWN(pi))
7514 0 : continue;
7515 0 : if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7516 0 : continue;
7517 0 : if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7518 : med_matched = false;
7519 : break;
7520 : }
7521 : }
7522 0 : if (!med_matched)
7523 : break;
7524 : }
7525 0 : bgp_dest_unlock_node(top);
7526 :
7527 0 : return med_matched;
7528 : }
7529 :
7530 : /**
7531 : * Toggles the route suppression status for this aggregate address
7532 : * configuration.
7533 : */
7534 0 : void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7535 : struct bgp *bgp, const struct prefix *p,
7536 : afi_t afi, safi_t safi, bool suppress)
7537 : {
7538 0 : struct bgp_table *table = bgp->rib[afi][safi];
7539 0 : const struct prefix *dest_p;
7540 0 : struct bgp_dest *dest, *top;
7541 0 : struct bgp_path_info *pi;
7542 0 : bool toggle_suppression;
7543 :
7544 : /* We've found a different MED we must revert any suppressed routes. */
7545 0 : top = bgp_node_get(table, p);
7546 0 : for (dest = bgp_node_get(table, p); dest;
7547 0 : dest = bgp_route_next_until(dest, top)) {
7548 0 : dest_p = bgp_dest_get_prefix(dest);
7549 0 : if (dest_p->prefixlen <= p->prefixlen)
7550 0 : continue;
7551 :
7552 0 : toggle_suppression = false;
7553 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7554 0 : if (BGP_PATH_HOLDDOWN(pi))
7555 0 : continue;
7556 0 : if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7557 0 : continue;
7558 :
7559 : /* We are toggling suppression back. */
7560 0 : if (suppress) {
7561 : /* Suppress route if not suppressed already. */
7562 0 : if (aggr_suppress_path(aggregate, pi))
7563 0 : toggle_suppression = true;
7564 0 : continue;
7565 : }
7566 :
7567 : /* Install route if there is no more suppression. */
7568 0 : if (aggr_unsuppress_path(aggregate, pi))
7569 0 : toggle_suppression = true;
7570 : }
7571 :
7572 0 : if (toggle_suppression)
7573 0 : bgp_process(bgp, dest, afi, safi);
7574 : }
7575 0 : bgp_dest_unlock_node(top);
7576 0 : }
7577 :
7578 : /**
7579 : * Aggregate address MED matching incremental test: this function is called
7580 : * when the initial aggregation occurred and we are only testing a single
7581 : * new path.
7582 : *
7583 : * In addition to testing and setting the MED validity it also installs back
7584 : * suppressed routes (if summary is configured).
7585 : *
7586 : * Must not be called in `bgp_aggregate_route`.
7587 : */
7588 0 : static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7589 : struct bgp *bgp, const struct prefix *p,
7590 : afi_t afi, safi_t safi,
7591 : struct bgp_path_info *pi)
7592 : {
7593 : /* MED matching disabled. */
7594 0 : if (!aggregate->match_med)
7595 : return;
7596 :
7597 : /* Aggregation with different MED, recheck if we have got equal MEDs
7598 : * now.
7599 : */
7600 0 : if (aggregate->med_mismatched &&
7601 0 : bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7602 0 : aggregate->summary_only)
7603 0 : bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7604 : true);
7605 : else
7606 0 : bgp_aggregate_med_match(aggregate, bgp, pi);
7607 :
7608 : /* No mismatches, just quit. */
7609 0 : if (!aggregate->med_mismatched)
7610 : return;
7611 :
7612 : /* Route summarization is disabled. */
7613 0 : if (!aggregate->summary_only)
7614 : return;
7615 :
7616 0 : bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7617 : }
7618 :
7619 : /* Update an aggregate as routes are added/removed from the BGP table */
7620 0 : void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7621 : safi_t safi, struct bgp_aggregate *aggregate)
7622 : {
7623 0 : struct bgp_table *table;
7624 0 : struct bgp_dest *top;
7625 0 : struct bgp_dest *dest;
7626 0 : uint8_t origin;
7627 0 : struct aspath *aspath = NULL;
7628 0 : struct community *community = NULL;
7629 0 : struct ecommunity *ecommunity = NULL;
7630 0 : struct lcommunity *lcommunity = NULL;
7631 0 : struct bgp_path_info *pi;
7632 0 : unsigned long match = 0;
7633 0 : uint8_t atomic_aggregate = 0;
7634 :
7635 : /* If the bgp instance is being deleted or self peer is deleted
7636 : * then do not create aggregate route
7637 : */
7638 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7639 0 : || (bgp->peer_self == NULL))
7640 : return;
7641 :
7642 : /* Initialize and test routes for MED difference. */
7643 0 : if (aggregate->match_med)
7644 0 : bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7645 :
7646 : /*
7647 : * Reset aggregate count: we might've been called from route map
7648 : * update so in that case we must retest all more specific routes.
7649 : *
7650 : * \see `bgp_route_map_process_update`.
7651 : */
7652 0 : aggregate->count = 0;
7653 0 : aggregate->incomplete_origin_count = 0;
7654 0 : aggregate->incomplete_origin_count = 0;
7655 0 : aggregate->egp_origin_count = 0;
7656 :
7657 : /* ORIGIN attribute: If at least one route among routes that are
7658 : aggregated has ORIGIN with the value INCOMPLETE, then the
7659 : aggregated route must have the ORIGIN attribute with the value
7660 : INCOMPLETE. Otherwise, if at least one route among routes that
7661 : are aggregated has ORIGIN with the value EGP, then the aggregated
7662 : route must have the origin attribute with the value EGP. In all
7663 : other case the value of the ORIGIN attribute of the aggregated
7664 : route is INTERNAL. */
7665 0 : origin = BGP_ORIGIN_IGP;
7666 :
7667 0 : table = bgp->rib[afi][safi];
7668 :
7669 0 : top = bgp_node_get(table, p);
7670 0 : for (dest = bgp_node_get(table, p); dest;
7671 0 : dest = bgp_route_next_until(dest, top)) {
7672 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7673 :
7674 0 : if (dest_p->prefixlen <= p->prefixlen)
7675 0 : continue;
7676 :
7677 : /* If suppress fib is enabled and route not installed
7678 : * in FIB, skip the route
7679 : */
7680 0 : if (!bgp_check_advertise(bgp, dest))
7681 0 : continue;
7682 :
7683 0 : match = 0;
7684 :
7685 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7686 0 : if (BGP_PATH_HOLDDOWN(pi))
7687 0 : continue;
7688 :
7689 0 : if (pi->attr->flag
7690 0 : & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7691 0 : atomic_aggregate = 1;
7692 :
7693 0 : if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7694 0 : continue;
7695 :
7696 : /*
7697 : * summary-only aggregate route suppress
7698 : * aggregated route announcements.
7699 : *
7700 : * MED matching:
7701 : * Don't create summaries if MED didn't match
7702 : * otherwise neither the specific routes and the
7703 : * aggregation will be announced.
7704 : */
7705 0 : if (aggregate->summary_only
7706 0 : && AGGREGATE_MED_VALID(aggregate)) {
7707 0 : if (aggr_suppress_path(aggregate, pi))
7708 0 : match++;
7709 : }
7710 :
7711 : /*
7712 : * Suppress more specific routes that match the route
7713 : * map results.
7714 : *
7715 : * MED matching:
7716 : * Don't suppress routes if MED matching is enabled and
7717 : * it mismatched otherwise we might end up with no
7718 : * routes for this path.
7719 : */
7720 0 : if (aggregate->suppress_map_name
7721 0 : && AGGREGATE_MED_VALID(aggregate)
7722 0 : && aggr_suppress_map_test(bgp, aggregate, pi)) {
7723 0 : if (aggr_suppress_path(aggregate, pi))
7724 0 : match++;
7725 : }
7726 :
7727 0 : aggregate->count++;
7728 :
7729 : /*
7730 : * If at least one route among routes that are
7731 : * aggregated has ORIGIN with the value INCOMPLETE,
7732 : * then the aggregated route MUST have the ORIGIN
7733 : * attribute with the value INCOMPLETE. Otherwise, if
7734 : * at least one route among routes that are aggregated
7735 : * has ORIGIN with the value EGP, then the aggregated
7736 : * route MUST have the ORIGIN attribute with the value
7737 : * EGP.
7738 : */
7739 0 : switch (pi->attr->origin) {
7740 0 : case BGP_ORIGIN_INCOMPLETE:
7741 0 : aggregate->incomplete_origin_count++;
7742 0 : break;
7743 0 : case BGP_ORIGIN_EGP:
7744 0 : aggregate->egp_origin_count++;
7745 0 : break;
7746 : default:
7747 : /*Do nothing.
7748 : */
7749 : break;
7750 : }
7751 :
7752 0 : if (!aggregate->as_set)
7753 0 : continue;
7754 :
7755 : /*
7756 : * as-set aggregate route generate origin, as path,
7757 : * and community aggregation.
7758 : */
7759 : /* Compute aggregate route's as-path.
7760 : */
7761 0 : bgp_compute_aggregate_aspath_hash(aggregate,
7762 : pi->attr->aspath);
7763 :
7764 : /* Compute aggregate route's community.
7765 : */
7766 0 : if (bgp_attr_get_community(pi->attr))
7767 0 : bgp_compute_aggregate_community_hash(
7768 : aggregate,
7769 0 : bgp_attr_get_community(pi->attr));
7770 :
7771 : /* Compute aggregate route's extended community.
7772 : */
7773 0 : if (bgp_attr_get_ecommunity(pi->attr))
7774 0 : bgp_compute_aggregate_ecommunity_hash(
7775 : aggregate,
7776 0 : bgp_attr_get_ecommunity(pi->attr));
7777 :
7778 : /* Compute aggregate route's large community.
7779 : */
7780 0 : if (bgp_attr_get_lcommunity(pi->attr))
7781 0 : bgp_compute_aggregate_lcommunity_hash(
7782 : aggregate,
7783 0 : bgp_attr_get_lcommunity(pi->attr));
7784 : }
7785 0 : if (match)
7786 0 : bgp_process(bgp, dest, afi, safi);
7787 : }
7788 0 : if (aggregate->as_set) {
7789 0 : bgp_compute_aggregate_aspath_val(aggregate);
7790 0 : bgp_compute_aggregate_community_val(aggregate);
7791 0 : bgp_compute_aggregate_ecommunity_val(aggregate);
7792 0 : bgp_compute_aggregate_lcommunity_val(aggregate);
7793 : }
7794 :
7795 :
7796 0 : bgp_dest_unlock_node(top);
7797 :
7798 :
7799 0 : if (aggregate->incomplete_origin_count > 0)
7800 : origin = BGP_ORIGIN_INCOMPLETE;
7801 0 : else if (aggregate->egp_origin_count > 0)
7802 0 : origin = BGP_ORIGIN_EGP;
7803 :
7804 0 : if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7805 0 : origin = aggregate->origin;
7806 :
7807 0 : if (aggregate->as_set) {
7808 0 : if (aggregate->aspath)
7809 : /* Retrieve aggregate route's as-path.
7810 : */
7811 0 : aspath = aspath_dup(aggregate->aspath);
7812 :
7813 0 : if (aggregate->community)
7814 : /* Retrieve aggregate route's community.
7815 : */
7816 0 : community = community_dup(aggregate->community);
7817 :
7818 0 : if (aggregate->ecommunity)
7819 : /* Retrieve aggregate route's ecommunity.
7820 : */
7821 0 : ecommunity = ecommunity_dup(aggregate->ecommunity);
7822 :
7823 0 : if (aggregate->lcommunity)
7824 : /* Retrieve aggregate route's lcommunity.
7825 : */
7826 0 : lcommunity = lcommunity_dup(aggregate->lcommunity);
7827 : }
7828 :
7829 0 : bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
7830 : ecommunity, lcommunity, atomic_aggregate,
7831 : aggregate);
7832 : }
7833 :
7834 0 : void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7835 : safi_t safi, struct bgp_aggregate *aggregate)
7836 : {
7837 0 : struct bgp_table *table;
7838 0 : struct bgp_dest *top;
7839 0 : struct bgp_dest *dest;
7840 0 : struct bgp_path_info *pi;
7841 0 : unsigned long match;
7842 :
7843 0 : table = bgp->rib[afi][safi];
7844 :
7845 : /* If routes exists below this node, generate aggregate routes. */
7846 0 : top = bgp_node_get(table, p);
7847 0 : for (dest = bgp_node_get(table, p); dest;
7848 0 : dest = bgp_route_next_until(dest, top)) {
7849 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
7850 :
7851 0 : if (dest_p->prefixlen <= p->prefixlen)
7852 0 : continue;
7853 0 : match = 0;
7854 :
7855 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7856 0 : if (BGP_PATH_HOLDDOWN(pi))
7857 0 : continue;
7858 :
7859 0 : if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7860 0 : continue;
7861 :
7862 : /*
7863 : * This route is suppressed: attempt to unsuppress it.
7864 : *
7865 : * `aggr_unsuppress_path` will fail if this particular
7866 : * aggregate route was not the suppressor.
7867 : */
7868 0 : if (pi->extra && pi->extra->aggr_suppressors &&
7869 0 : listcount(pi->extra->aggr_suppressors)) {
7870 0 : if (aggr_unsuppress_path(aggregate, pi))
7871 0 : match++;
7872 : }
7873 :
7874 0 : aggregate->count--;
7875 :
7876 0 : if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7877 0 : aggregate->incomplete_origin_count--;
7878 0 : else if (pi->attr->origin == BGP_ORIGIN_EGP)
7879 0 : aggregate->egp_origin_count--;
7880 :
7881 0 : if (aggregate->as_set) {
7882 : /* Remove as-path from aggregate.
7883 : */
7884 0 : bgp_remove_aspath_from_aggregate_hash(
7885 : aggregate,
7886 : pi->attr->aspath);
7887 :
7888 0 : if (bgp_attr_get_community(pi->attr))
7889 : /* Remove community from aggregate.
7890 : */
7891 0 : bgp_remove_comm_from_aggregate_hash(
7892 : aggregate,
7893 : bgp_attr_get_community(
7894 0 : pi->attr));
7895 :
7896 0 : if (bgp_attr_get_ecommunity(pi->attr))
7897 : /* Remove ecommunity from aggregate.
7898 : */
7899 0 : bgp_remove_ecomm_from_aggregate_hash(
7900 : aggregate,
7901 : bgp_attr_get_ecommunity(
7902 0 : pi->attr));
7903 :
7904 0 : if (bgp_attr_get_lcommunity(pi->attr))
7905 : /* Remove lcommunity from aggregate.
7906 : */
7907 0 : bgp_remove_lcomm_from_aggregate_hash(
7908 : aggregate,
7909 : bgp_attr_get_lcommunity(
7910 0 : pi->attr));
7911 : }
7912 : }
7913 :
7914 : /* If this node was suppressed, process the change. */
7915 0 : if (match)
7916 0 : bgp_process(bgp, dest, afi, safi);
7917 : }
7918 0 : if (aggregate->as_set) {
7919 0 : aspath_free(aggregate->aspath);
7920 0 : aggregate->aspath = NULL;
7921 0 : if (aggregate->community)
7922 0 : community_free(&aggregate->community);
7923 0 : if (aggregate->ecommunity)
7924 0 : ecommunity_free(&aggregate->ecommunity);
7925 0 : if (aggregate->lcommunity)
7926 0 : lcommunity_free(&aggregate->lcommunity);
7927 : }
7928 :
7929 0 : bgp_dest_unlock_node(top);
7930 0 : }
7931 :
7932 0 : static void bgp_add_route_to_aggregate(struct bgp *bgp,
7933 : const struct prefix *aggr_p,
7934 : struct bgp_path_info *pinew, afi_t afi,
7935 : safi_t safi,
7936 : struct bgp_aggregate *aggregate)
7937 : {
7938 0 : uint8_t origin;
7939 0 : struct aspath *aspath = NULL;
7940 0 : uint8_t atomic_aggregate = 0;
7941 0 : struct community *community = NULL;
7942 0 : struct ecommunity *ecommunity = NULL;
7943 0 : struct lcommunity *lcommunity = NULL;
7944 :
7945 : /* If the bgp instance is being deleted or self peer is deleted
7946 : * then do not create aggregate route
7947 : */
7948 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7949 0 : || (bgp->peer_self == NULL))
7950 : return;
7951 :
7952 : /* ORIGIN attribute: If at least one route among routes that are
7953 : * aggregated has ORIGIN with the value INCOMPLETE, then the
7954 : * aggregated route must have the ORIGIN attribute with the value
7955 : * INCOMPLETE. Otherwise, if at least one route among routes that
7956 : * are aggregated has ORIGIN with the value EGP, then the aggregated
7957 : * route must have the origin attribute with the value EGP. In all
7958 : * other case the value of the ORIGIN attribute of the aggregated
7959 : * route is INTERNAL.
7960 : */
7961 0 : origin = BGP_ORIGIN_IGP;
7962 :
7963 0 : aggregate->count++;
7964 :
7965 : /*
7966 : * This must be called before `summary` check to avoid
7967 : * "suppressing" twice.
7968 : */
7969 0 : if (aggregate->match_med)
7970 0 : bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7971 : pinew);
7972 :
7973 0 : if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7974 0 : aggr_suppress_path(aggregate, pinew);
7975 :
7976 0 : if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7977 0 : && aggr_suppress_map_test(bgp, aggregate, pinew))
7978 0 : aggr_suppress_path(aggregate, pinew);
7979 :
7980 0 : switch (pinew->attr->origin) {
7981 0 : case BGP_ORIGIN_INCOMPLETE:
7982 0 : aggregate->incomplete_origin_count++;
7983 0 : break;
7984 0 : case BGP_ORIGIN_EGP:
7985 0 : aggregate->egp_origin_count++;
7986 0 : break;
7987 : default:
7988 : /* Do nothing.
7989 : */
7990 : break;
7991 : }
7992 :
7993 0 : if (aggregate->incomplete_origin_count > 0)
7994 : origin = BGP_ORIGIN_INCOMPLETE;
7995 0 : else if (aggregate->egp_origin_count > 0)
7996 0 : origin = BGP_ORIGIN_EGP;
7997 :
7998 0 : if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7999 0 : origin = aggregate->origin;
8000 :
8001 0 : if (aggregate->as_set) {
8002 : /* Compute aggregate route's as-path.
8003 : */
8004 0 : bgp_compute_aggregate_aspath(aggregate,
8005 : pinew->attr->aspath);
8006 :
8007 : /* Compute aggregate route's community.
8008 : */
8009 0 : if (bgp_attr_get_community(pinew->attr))
8010 0 : bgp_compute_aggregate_community(
8011 0 : aggregate, bgp_attr_get_community(pinew->attr));
8012 :
8013 : /* Compute aggregate route's extended community.
8014 : */
8015 0 : if (bgp_attr_get_ecommunity(pinew->attr))
8016 0 : bgp_compute_aggregate_ecommunity(
8017 : aggregate,
8018 0 : bgp_attr_get_ecommunity(pinew->attr));
8019 :
8020 : /* Compute aggregate route's large community.
8021 : */
8022 0 : if (bgp_attr_get_lcommunity(pinew->attr))
8023 0 : bgp_compute_aggregate_lcommunity(
8024 : aggregate,
8025 0 : bgp_attr_get_lcommunity(pinew->attr));
8026 :
8027 : /* Retrieve aggregate route's as-path.
8028 : */
8029 0 : if (aggregate->aspath)
8030 0 : aspath = aspath_dup(aggregate->aspath);
8031 :
8032 : /* Retrieve aggregate route's community.
8033 : */
8034 0 : if (aggregate->community)
8035 0 : community = community_dup(aggregate->community);
8036 :
8037 : /* Retrieve aggregate route's ecommunity.
8038 : */
8039 0 : if (aggregate->ecommunity)
8040 0 : ecommunity = ecommunity_dup(aggregate->ecommunity);
8041 :
8042 : /* Retrieve aggregate route's lcommunity.
8043 : */
8044 0 : if (aggregate->lcommunity)
8045 0 : lcommunity = lcommunity_dup(aggregate->lcommunity);
8046 : }
8047 :
8048 0 : bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8049 : aspath, community, ecommunity,
8050 : lcommunity, atomic_aggregate, aggregate);
8051 : }
8052 :
8053 0 : static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
8054 : safi_t safi,
8055 : struct bgp_path_info *pi,
8056 : struct bgp_aggregate *aggregate,
8057 : const struct prefix *aggr_p)
8058 : {
8059 0 : uint8_t origin;
8060 0 : struct aspath *aspath = NULL;
8061 0 : uint8_t atomic_aggregate = 0;
8062 0 : struct community *community = NULL;
8063 0 : struct ecommunity *ecommunity = NULL;
8064 0 : struct lcommunity *lcommunity = NULL;
8065 0 : unsigned long match = 0;
8066 :
8067 : /* If the bgp instance is being deleted or self peer is deleted
8068 : * then do not create aggregate route
8069 : */
8070 0 : if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
8071 0 : || (bgp->peer_self == NULL))
8072 : return;
8073 :
8074 0 : if (BGP_PATH_HOLDDOWN(pi))
8075 : return;
8076 :
8077 0 : if (pi->sub_type == BGP_ROUTE_AGGREGATE)
8078 : return;
8079 :
8080 0 : if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
8081 0 : if (aggr_unsuppress_path(aggregate, pi))
8082 0 : match++;
8083 :
8084 0 : if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
8085 0 : && aggr_suppress_map_test(bgp, aggregate, pi))
8086 0 : if (aggr_unsuppress_path(aggregate, pi))
8087 0 : match++;
8088 :
8089 : /*
8090 : * This must be called after `summary`, `suppress-map` check to avoid
8091 : * "unsuppressing" twice.
8092 : */
8093 0 : if (aggregate->match_med)
8094 0 : bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
8095 :
8096 0 : if (aggregate->count > 0)
8097 0 : aggregate->count--;
8098 :
8099 0 : if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
8100 0 : aggregate->incomplete_origin_count--;
8101 0 : else if (pi->attr->origin == BGP_ORIGIN_EGP)
8102 0 : aggregate->egp_origin_count--;
8103 :
8104 0 : if (aggregate->as_set) {
8105 : /* Remove as-path from aggregate.
8106 : */
8107 0 : bgp_remove_aspath_from_aggregate(aggregate,
8108 : pi->attr->aspath);
8109 :
8110 0 : if (bgp_attr_get_community(pi->attr))
8111 : /* Remove community from aggregate.
8112 : */
8113 0 : bgp_remove_community_from_aggregate(
8114 0 : aggregate, bgp_attr_get_community(pi->attr));
8115 :
8116 0 : if (bgp_attr_get_ecommunity(pi->attr))
8117 : /* Remove ecommunity from aggregate.
8118 : */
8119 0 : bgp_remove_ecommunity_from_aggregate(
8120 0 : aggregate, bgp_attr_get_ecommunity(pi->attr));
8121 :
8122 0 : if (bgp_attr_get_lcommunity(pi->attr))
8123 : /* Remove lcommunity from aggregate.
8124 : */
8125 0 : bgp_remove_lcommunity_from_aggregate(
8126 0 : aggregate, bgp_attr_get_lcommunity(pi->attr));
8127 : }
8128 :
8129 : /* If this node was suppressed, process the change. */
8130 0 : if (match)
8131 0 : bgp_process(bgp, pi->net, afi, safi);
8132 :
8133 0 : origin = BGP_ORIGIN_IGP;
8134 0 : if (aggregate->incomplete_origin_count > 0)
8135 : origin = BGP_ORIGIN_INCOMPLETE;
8136 0 : else if (aggregate->egp_origin_count > 0)
8137 0 : origin = BGP_ORIGIN_EGP;
8138 :
8139 0 : if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8140 0 : origin = aggregate->origin;
8141 :
8142 0 : if (aggregate->as_set) {
8143 : /* Retrieve aggregate route's as-path.
8144 : */
8145 0 : if (aggregate->aspath)
8146 0 : aspath = aspath_dup(aggregate->aspath);
8147 :
8148 : /* Retrieve aggregate route's community.
8149 : */
8150 0 : if (aggregate->community)
8151 0 : community = community_dup(aggregate->community);
8152 :
8153 : /* Retrieve aggregate route's ecommunity.
8154 : */
8155 0 : if (aggregate->ecommunity)
8156 0 : ecommunity = ecommunity_dup(aggregate->ecommunity);
8157 :
8158 : /* Retrieve aggregate route's lcommunity.
8159 : */
8160 0 : if (aggregate->lcommunity)
8161 0 : lcommunity = lcommunity_dup(aggregate->lcommunity);
8162 : }
8163 :
8164 0 : bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8165 : aspath, community, ecommunity,
8166 : lcommunity, atomic_aggregate, aggregate);
8167 : }
8168 :
8169 1 : void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
8170 : struct bgp_path_info *pi, afi_t afi, safi_t safi)
8171 : {
8172 1 : struct bgp_dest *child;
8173 1 : struct bgp_dest *dest;
8174 1 : struct bgp_aggregate *aggregate;
8175 1 : struct bgp_table *table;
8176 :
8177 1 : table = bgp->aggregate[afi][safi];
8178 :
8179 : /* No aggregates configured. */
8180 1 : if (bgp_table_top_nolock(table) == NULL)
8181 : return;
8182 :
8183 0 : if (p->prefixlen == 0)
8184 : return;
8185 :
8186 0 : if (BGP_PATH_HOLDDOWN(pi))
8187 : return;
8188 :
8189 : /* If suppress fib is enabled and route not installed
8190 : * in FIB, do not update the aggregate route
8191 : */
8192 0 : if (!bgp_check_advertise(bgp, pi->net))
8193 : return;
8194 :
8195 0 : child = bgp_node_get(table, p);
8196 :
8197 : /* Aggregate address configuration check. */
8198 0 : for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8199 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
8200 :
8201 0 : aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8202 0 : if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8203 0 : bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
8204 : aggregate);
8205 : }
8206 : }
8207 0 : bgp_dest_unlock_node(child);
8208 : }
8209 :
8210 0 : void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
8211 : struct bgp_path_info *del, afi_t afi, safi_t safi)
8212 : {
8213 0 : struct bgp_dest *child;
8214 0 : struct bgp_dest *dest;
8215 0 : struct bgp_aggregate *aggregate;
8216 0 : struct bgp_table *table;
8217 :
8218 0 : table = bgp->aggregate[afi][safi];
8219 :
8220 : /* No aggregates configured. */
8221 0 : if (bgp_table_top_nolock(table) == NULL)
8222 : return;
8223 :
8224 0 : if (p->prefixlen == 0)
8225 : return;
8226 :
8227 0 : child = bgp_node_get(table, p);
8228 :
8229 : /* Aggregate address configuration check. */
8230 0 : for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8231 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
8232 :
8233 0 : aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8234 0 : if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8235 0 : bgp_remove_route_from_aggregate(bgp, afi, safi, del,
8236 : aggregate, dest_p);
8237 : }
8238 : }
8239 0 : bgp_dest_unlock_node(child);
8240 : }
8241 :
8242 : /* Aggregate route attribute. */
8243 : #define AGGREGATE_SUMMARY_ONLY 1
8244 : #define AGGREGATE_AS_SET 1
8245 : #define AGGREGATE_AS_UNSET 0
8246 :
8247 0 : static const char *bgp_origin2str(uint8_t origin)
8248 : {
8249 0 : switch (origin) {
8250 : case BGP_ORIGIN_IGP:
8251 : return "igp";
8252 0 : case BGP_ORIGIN_EGP:
8253 0 : return "egp";
8254 0 : case BGP_ORIGIN_INCOMPLETE:
8255 0 : return "incomplete";
8256 : }
8257 0 : return "n/a";
8258 : }
8259 :
8260 0 : static const char *bgp_rpki_validation2str(enum rpki_states v_state)
8261 : {
8262 0 : switch (v_state) {
8263 : case RPKI_NOT_BEING_USED:
8264 : return "not used";
8265 0 : case RPKI_VALID:
8266 0 : return "valid";
8267 0 : case RPKI_NOTFOUND:
8268 0 : return "not found";
8269 0 : case RPKI_INVALID:
8270 0 : return "invalid";
8271 : }
8272 :
8273 0 : assert(!"We should never get here this is a dev escape");
8274 : return "ERROR";
8275 : }
8276 :
8277 0 : static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8278 : afi_t afi, safi_t safi)
8279 : {
8280 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
8281 0 : int ret;
8282 0 : struct prefix p;
8283 0 : struct bgp_dest *dest;
8284 0 : struct bgp_aggregate *aggregate;
8285 :
8286 : /* Convert string to prefix structure. */
8287 0 : ret = str2prefix(prefix_str, &p);
8288 0 : if (!ret) {
8289 0 : vty_out(vty, "Malformed prefix\n");
8290 0 : return CMD_WARNING_CONFIG_FAILED;
8291 : }
8292 0 : apply_mask(&p);
8293 :
8294 : /* Old configuration check. */
8295 0 : dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
8296 0 : if (!dest) {
8297 0 : vty_out(vty,
8298 : "%% There is no aggregate-address configuration.\n");
8299 0 : return CMD_WARNING_CONFIG_FAILED;
8300 : }
8301 :
8302 0 : aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8303 0 : bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8304 0 : bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8305 : NULL, NULL, 0, aggregate);
8306 :
8307 : /* Unlock aggregate address configuration. */
8308 0 : bgp_dest_set_bgp_aggregate_info(dest, NULL);
8309 :
8310 0 : if (aggregate->community)
8311 0 : community_free(&aggregate->community);
8312 :
8313 0 : if (aggregate->community_hash) {
8314 : /* Delete all communities in the hash.
8315 : */
8316 0 : hash_clean(aggregate->community_hash,
8317 : bgp_aggr_community_remove);
8318 : /* Free up the community_hash.
8319 : */
8320 0 : hash_free(aggregate->community_hash);
8321 : }
8322 :
8323 0 : if (aggregate->ecommunity)
8324 0 : ecommunity_free(&aggregate->ecommunity);
8325 :
8326 0 : if (aggregate->ecommunity_hash) {
8327 : /* Delete all ecommunities in the hash.
8328 : */
8329 0 : hash_clean(aggregate->ecommunity_hash,
8330 : bgp_aggr_ecommunity_remove);
8331 : /* Free up the ecommunity_hash.
8332 : */
8333 0 : hash_free(aggregate->ecommunity_hash);
8334 : }
8335 :
8336 0 : if (aggregate->lcommunity)
8337 0 : lcommunity_free(&aggregate->lcommunity);
8338 :
8339 0 : if (aggregate->lcommunity_hash) {
8340 : /* Delete all lcommunities in the hash.
8341 : */
8342 0 : hash_clean(aggregate->lcommunity_hash,
8343 : bgp_aggr_lcommunity_remove);
8344 : /* Free up the lcommunity_hash.
8345 : */
8346 0 : hash_free(aggregate->lcommunity_hash);
8347 : }
8348 :
8349 0 : if (aggregate->aspath)
8350 0 : aspath_free(aggregate->aspath);
8351 :
8352 0 : if (aggregate->aspath_hash) {
8353 : /* Delete all as-paths in the hash.
8354 : */
8355 0 : hash_clean(aggregate->aspath_hash,
8356 : bgp_aggr_aspath_remove);
8357 : /* Free up the aspath_hash.
8358 : */
8359 0 : hash_free(aggregate->aspath_hash);
8360 : }
8361 :
8362 0 : bgp_aggregate_free(aggregate);
8363 0 : bgp_dest_unlock_node(dest);
8364 0 : bgp_dest_unlock_node(dest);
8365 :
8366 0 : return CMD_SUCCESS;
8367 : }
8368 :
8369 0 : static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8370 : safi_t safi, const char *rmap,
8371 : uint8_t summary_only, uint8_t as_set,
8372 : uint8_t origin, bool match_med,
8373 : const char *suppress_map)
8374 : {
8375 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
8376 0 : int ret;
8377 0 : struct prefix p;
8378 0 : struct bgp_dest *dest;
8379 0 : struct bgp_aggregate *aggregate;
8380 0 : uint8_t as_set_new = as_set;
8381 :
8382 0 : if (suppress_map && summary_only) {
8383 0 : vty_out(vty,
8384 : "'summary-only' and 'suppress-map' can't be used at the same time\n");
8385 0 : return CMD_WARNING_CONFIG_FAILED;
8386 : }
8387 :
8388 : /* Convert string to prefix structure. */
8389 0 : ret = str2prefix(prefix_str, &p);
8390 0 : if (!ret) {
8391 0 : vty_out(vty, "Malformed prefix\n");
8392 0 : return CMD_WARNING_CONFIG_FAILED;
8393 : }
8394 0 : apply_mask(&p);
8395 :
8396 0 : if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8397 0 : (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8398 0 : vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8399 : prefix_str);
8400 0 : return CMD_WARNING_CONFIG_FAILED;
8401 : }
8402 :
8403 : /* Old configuration check. */
8404 0 : dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
8405 0 : aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8406 :
8407 0 : if (aggregate) {
8408 0 : vty_out(vty, "There is already same aggregate network.\n");
8409 : /* try to remove the old entry */
8410 0 : ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
8411 0 : if (ret) {
8412 0 : vty_out(vty, "Error deleting aggregate.\n");
8413 0 : bgp_dest_unlock_node(dest);
8414 0 : return CMD_WARNING_CONFIG_FAILED;
8415 : }
8416 : }
8417 :
8418 : /* Make aggregate address structure. */
8419 0 : aggregate = bgp_aggregate_new();
8420 0 : aggregate->summary_only = summary_only;
8421 0 : aggregate->match_med = match_med;
8422 :
8423 : /* Network operators MUST NOT locally generate any new
8424 : * announcements containing AS_SET or AS_CONFED_SET. If they have
8425 : * announced routes with AS_SET or AS_CONFED_SET in them, then they
8426 : * SHOULD withdraw those routes and re-announce routes for the
8427 : * aggregate or component prefixes (i.e., the more-specific routes
8428 : * subsumed by the previously aggregated route) without AS_SET
8429 : * or AS_CONFED_SET in the updates.
8430 : */
8431 0 : if (bgp->reject_as_sets) {
8432 0 : if (as_set == AGGREGATE_AS_SET) {
8433 0 : as_set_new = AGGREGATE_AS_UNSET;
8434 0 : zlog_warn(
8435 : "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
8436 : __func__);
8437 0 : vty_out(vty,
8438 : "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8439 : }
8440 : }
8441 :
8442 0 : aggregate->as_set = as_set_new;
8443 0 : aggregate->safi = safi;
8444 : /* Override ORIGIN attribute if defined.
8445 : * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8446 : * to IGP which is not what rfc4271 says.
8447 : * This enables the same behavior, optionally.
8448 : */
8449 0 : aggregate->origin = origin;
8450 :
8451 0 : if (rmap) {
8452 0 : XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8453 0 : route_map_counter_decrement(aggregate->rmap.map);
8454 0 : aggregate->rmap.name =
8455 0 : XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8456 0 : aggregate->rmap.map = route_map_lookup_by_name(rmap);
8457 0 : route_map_counter_increment(aggregate->rmap.map);
8458 : }
8459 :
8460 0 : if (suppress_map) {
8461 0 : XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8462 0 : route_map_counter_decrement(aggregate->suppress_map);
8463 :
8464 0 : aggregate->suppress_map_name =
8465 0 : XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8466 0 : aggregate->suppress_map =
8467 0 : route_map_lookup_by_name(aggregate->suppress_map_name);
8468 0 : route_map_counter_increment(aggregate->suppress_map);
8469 : }
8470 :
8471 0 : bgp_dest_set_bgp_aggregate_info(dest, aggregate);
8472 :
8473 : /* Aggregate address insert into BGP routing table. */
8474 0 : bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
8475 :
8476 0 : return CMD_SUCCESS;
8477 : }
8478 :
8479 0 : DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8480 : "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8481 : "as-set$as_set_s"
8482 : "|summary-only$summary_only"
8483 : "|route-map RMAP_NAME$rmap_name"
8484 : "|origin <egp|igp|incomplete>$origin_s"
8485 : "|matching-MED-only$match_med"
8486 : "|suppress-map RMAP_NAME$suppress_map"
8487 : "}]",
8488 : NO_STR
8489 : "Configure BGP aggregate entries\n"
8490 : "Aggregate prefix\n"
8491 : "Aggregate address\n"
8492 : "Aggregate mask\n"
8493 : "Generate AS set path information\n"
8494 : "Filter more specific routes from updates\n"
8495 : "Apply route map to aggregate network\n"
8496 : "Route map name\n"
8497 : "BGP origin code\n"
8498 : "Remote EGP\n"
8499 : "Local IGP\n"
8500 : "Unknown heritage\n"
8501 : "Only aggregate routes with matching MED\n"
8502 : "Suppress the selected more specific routes\n"
8503 : "Route map with the route selectors\n")
8504 : {
8505 0 : const char *prefix_s = NULL;
8506 0 : safi_t safi = bgp_node_safi(vty);
8507 0 : uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8508 0 : int as_set = AGGREGATE_AS_UNSET;
8509 0 : char prefix_buf[PREFIX2STR_BUFFER];
8510 :
8511 0 : if (addr_str) {
8512 0 : if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8513 : sizeof(prefix_buf))
8514 : == 0) {
8515 0 : vty_out(vty, "%% Inconsistent address and mask\n");
8516 0 : return CMD_WARNING_CONFIG_FAILED;
8517 : }
8518 : prefix_s = prefix_buf;
8519 : } else
8520 : prefix_s = prefix_str;
8521 :
8522 0 : if (origin_s) {
8523 0 : if (strcmp(origin_s, "egp") == 0)
8524 : origin = BGP_ORIGIN_EGP;
8525 0 : else if (strcmp(origin_s, "igp") == 0)
8526 : origin = BGP_ORIGIN_IGP;
8527 0 : else if (strcmp(origin_s, "incomplete") == 0)
8528 0 : origin = BGP_ORIGIN_INCOMPLETE;
8529 : }
8530 :
8531 0 : if (as_set_s)
8532 0 : as_set = AGGREGATE_AS_SET;
8533 :
8534 : /* Handle configuration removal, otherwise installation. */
8535 0 : if (no)
8536 0 : return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8537 :
8538 0 : return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8539 : summary_only != NULL, as_set, origin,
8540 : match_med != NULL, suppress_map);
8541 : }
8542 :
8543 0 : DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8544 : "[no] aggregate-address X:X::X:X/M$prefix [{"
8545 : "as-set$as_set_s"
8546 : "|summary-only$summary_only"
8547 : "|route-map RMAP_NAME$rmap_name"
8548 : "|origin <egp|igp|incomplete>$origin_s"
8549 : "|matching-MED-only$match_med"
8550 : "|suppress-map RMAP_NAME$suppress_map"
8551 : "}]",
8552 : NO_STR
8553 : "Configure BGP aggregate entries\n"
8554 : "Aggregate prefix\n"
8555 : "Generate AS set path information\n"
8556 : "Filter more specific routes from updates\n"
8557 : "Apply route map to aggregate network\n"
8558 : "Route map name\n"
8559 : "BGP origin code\n"
8560 : "Remote EGP\n"
8561 : "Local IGP\n"
8562 : "Unknown heritage\n"
8563 : "Only aggregate routes with matching MED\n"
8564 : "Suppress the selected more specific routes\n"
8565 : "Route map with the route selectors\n")
8566 : {
8567 0 : uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8568 0 : int as_set = AGGREGATE_AS_UNSET;
8569 :
8570 0 : if (origin_s) {
8571 0 : if (strcmp(origin_s, "egp") == 0)
8572 : origin = BGP_ORIGIN_EGP;
8573 0 : else if (strcmp(origin_s, "igp") == 0)
8574 : origin = BGP_ORIGIN_IGP;
8575 0 : else if (strcmp(origin_s, "incomplete") == 0)
8576 0 : origin = BGP_ORIGIN_INCOMPLETE;
8577 : }
8578 :
8579 0 : if (as_set_s)
8580 0 : as_set = AGGREGATE_AS_SET;
8581 :
8582 : /* Handle configuration removal, otherwise installation. */
8583 0 : if (no)
8584 0 : return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8585 : SAFI_UNICAST);
8586 :
8587 0 : return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8588 : rmap_name, summary_only != NULL, as_set,
8589 : origin, match_med != NULL, suppress_map);
8590 : }
8591 :
8592 : /* Redistribute route treatment. */
8593 0 : void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
8594 : const union g_addr *nexthop, ifindex_t ifindex,
8595 : enum nexthop_types_t nhtype, uint8_t distance,
8596 : enum blackhole_type bhtype, uint32_t metric,
8597 : uint8_t type, unsigned short instance,
8598 : route_tag_t tag)
8599 : {
8600 0 : struct bgp_path_info *new;
8601 0 : struct bgp_path_info *bpi;
8602 0 : struct bgp_path_info rmap_path;
8603 0 : struct bgp_dest *bn;
8604 0 : struct attr attr;
8605 0 : struct attr *new_attr;
8606 0 : afi_t afi;
8607 0 : route_map_result_t ret;
8608 0 : struct bgp_redist *red;
8609 :
8610 : /* Make default attribute. */
8611 0 : bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
8612 : /*
8613 : * This must not be NULL to satisfy Coverity SA
8614 : */
8615 0 : assert(attr.aspath);
8616 :
8617 0 : switch (nhtype) {
8618 0 : case NEXTHOP_TYPE_IFINDEX:
8619 0 : switch (p->family) {
8620 0 : case AF_INET:
8621 0 : attr.nexthop.s_addr = INADDR_ANY;
8622 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8623 0 : break;
8624 0 : case AF_INET6:
8625 0 : memset(&attr.mp_nexthop_global, 0,
8626 : sizeof(attr.mp_nexthop_global));
8627 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8628 0 : break;
8629 : }
8630 : break;
8631 0 : case NEXTHOP_TYPE_IPV4:
8632 : case NEXTHOP_TYPE_IPV4_IFINDEX:
8633 0 : attr.nexthop = nexthop->ipv4;
8634 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8635 0 : break;
8636 0 : case NEXTHOP_TYPE_IPV6:
8637 : case NEXTHOP_TYPE_IPV6_IFINDEX:
8638 0 : attr.mp_nexthop_global = nexthop->ipv6;
8639 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8640 0 : break;
8641 0 : case NEXTHOP_TYPE_BLACKHOLE:
8642 0 : switch (p->family) {
8643 0 : case AF_INET:
8644 0 : attr.nexthop.s_addr = INADDR_ANY;
8645 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8646 0 : break;
8647 0 : case AF_INET6:
8648 0 : memset(&attr.mp_nexthop_global, 0,
8649 : sizeof(attr.mp_nexthop_global));
8650 0 : attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8651 0 : break;
8652 : }
8653 0 : attr.bh_type = bhtype;
8654 0 : break;
8655 : }
8656 0 : attr.nh_type = nhtype;
8657 0 : attr.nh_ifindex = ifindex;
8658 :
8659 0 : attr.med = metric;
8660 0 : attr.distance = distance;
8661 0 : attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8662 0 : attr.tag = tag;
8663 :
8664 0 : if (metric)
8665 0 : bgp_attr_set_aigp_metric(&attr, metric);
8666 :
8667 0 : afi = family2afi(p->family);
8668 :
8669 0 : red = bgp_redist_lookup(bgp, afi, type, instance);
8670 0 : if (red) {
8671 0 : struct attr attr_new;
8672 :
8673 : /* Copy attribute for modification. */
8674 0 : attr_new = attr;
8675 :
8676 0 : if (red->redist_metric_flag) {
8677 0 : attr_new.med = red->redist_metric;
8678 0 : bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
8679 : }
8680 :
8681 : /* Apply route-map. */
8682 0 : if (red->rmap.name) {
8683 0 : memset(&rmap_path, 0, sizeof(rmap_path));
8684 0 : rmap_path.peer = bgp->peer_self;
8685 0 : rmap_path.attr = &attr_new;
8686 :
8687 0 : SET_FLAG(bgp->peer_self->rmap_type,
8688 : PEER_RMAP_TYPE_REDISTRIBUTE);
8689 :
8690 0 : ret = route_map_apply(red->rmap.map, p, &rmap_path);
8691 :
8692 0 : bgp->peer_self->rmap_type = 0;
8693 :
8694 0 : if (ret == RMAP_DENYMATCH) {
8695 : /* Free uninterned attribute. */
8696 0 : bgp_attr_flush(&attr_new);
8697 :
8698 : /* Unintern original. */
8699 0 : aspath_unintern(&attr.aspath);
8700 0 : bgp_redistribute_delete(bgp, p, type, instance);
8701 0 : return;
8702 : }
8703 : }
8704 :
8705 0 : if (bgp_in_graceful_shutdown(bgp))
8706 0 : bgp_attr_add_gshut_community(&attr_new);
8707 :
8708 0 : bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8709 : SAFI_UNICAST, p, NULL);
8710 :
8711 0 : new_attr = bgp_attr_intern(&attr_new);
8712 :
8713 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
8714 0 : if (bpi->peer == bgp->peer_self
8715 0 : && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
8716 : break;
8717 :
8718 0 : if (bpi) {
8719 : /* Ensure the (source route) type is updated. */
8720 0 : bpi->type = type;
8721 0 : if (attrhash_cmp(bpi->attr, new_attr)
8722 0 : && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
8723 0 : bgp_attr_unintern(&new_attr);
8724 0 : aspath_unintern(&attr.aspath);
8725 0 : bgp_dest_unlock_node(bn);
8726 0 : return;
8727 : } else {
8728 : /* The attribute is changed. */
8729 0 : bgp_path_info_set_flag(bn, bpi,
8730 : BGP_PATH_ATTR_CHANGED);
8731 :
8732 : /* Rewrite BGP route information. */
8733 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8734 0 : bgp_path_info_restore(bn, bpi);
8735 : else
8736 0 : bgp_aggregate_decrement(
8737 : bgp, p, bpi, afi, SAFI_UNICAST);
8738 0 : bgp_attr_unintern(&bpi->attr);
8739 0 : bpi->attr = new_attr;
8740 0 : bpi->uptime = monotime(NULL);
8741 :
8742 : /* Process change. */
8743 0 : bgp_aggregate_increment(bgp, p, bpi, afi,
8744 : SAFI_UNICAST);
8745 0 : bgp_process(bgp, bn, afi, SAFI_UNICAST);
8746 0 : bgp_dest_unlock_node(bn);
8747 0 : aspath_unintern(&attr.aspath);
8748 :
8749 0 : if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8750 : || (bgp->inst_type
8751 : == BGP_INSTANCE_TYPE_DEFAULT)) {
8752 :
8753 0 : vpn_leak_from_vrf_update(
8754 : bgp_get_default(), bgp, bpi);
8755 : }
8756 0 : return;
8757 : }
8758 : }
8759 :
8760 0 : new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8761 : bgp->peer_self, new_attr, bn);
8762 0 : SET_FLAG(new->flags, BGP_PATH_VALID);
8763 :
8764 0 : bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
8765 0 : bgp_path_info_add(bn, new);
8766 0 : bgp_dest_unlock_node(bn);
8767 0 : SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
8768 0 : bgp_process(bgp, bn, afi, SAFI_UNICAST);
8769 :
8770 0 : if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8771 : || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8772 :
8773 0 : vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8774 : }
8775 : }
8776 :
8777 : /* Unintern original. */
8778 0 : aspath_unintern(&attr.aspath);
8779 : }
8780 :
8781 0 : void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8782 : unsigned short instance)
8783 : {
8784 0 : afi_t afi;
8785 0 : struct bgp_dest *dest;
8786 0 : struct bgp_path_info *pi;
8787 0 : struct bgp_redist *red;
8788 :
8789 0 : afi = family2afi(p->family);
8790 :
8791 0 : red = bgp_redist_lookup(bgp, afi, type, instance);
8792 0 : if (red) {
8793 0 : dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8794 : SAFI_UNICAST, p, NULL);
8795 :
8796 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8797 0 : if (pi->peer == bgp->peer_self && pi->type == type)
8798 : break;
8799 :
8800 0 : if (pi) {
8801 0 : if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8802 : || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8803 :
8804 0 : vpn_leak_from_vrf_withdraw(bgp_get_default(),
8805 : bgp, pi);
8806 : }
8807 0 : bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
8808 0 : bgp_path_info_delete(dest, pi);
8809 0 : bgp_process(bgp, dest, afi, SAFI_UNICAST);
8810 : }
8811 0 : bgp_dest_unlock_node(dest);
8812 : }
8813 0 : }
8814 :
8815 : /* Withdraw specified route type's route. */
8816 0 : void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
8817 : unsigned short instance)
8818 : {
8819 0 : struct bgp_dest *dest;
8820 0 : struct bgp_path_info *pi;
8821 0 : struct bgp_table *table;
8822 :
8823 0 : table = bgp->rib[afi][SAFI_UNICAST];
8824 :
8825 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8826 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
8827 0 : if (pi->peer == bgp->peer_self && pi->type == type
8828 0 : && pi->instance == instance)
8829 : break;
8830 :
8831 0 : if (pi) {
8832 0 : if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8833 : || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8834 :
8835 0 : vpn_leak_from_vrf_withdraw(bgp_get_default(),
8836 : bgp, pi);
8837 : }
8838 0 : bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
8839 : pi, afi, SAFI_UNICAST);
8840 0 : bgp_path_info_delete(dest, pi);
8841 0 : if (!CHECK_FLAG(bgp->flags,
8842 : BGP_FLAG_DELETE_IN_PROGRESS))
8843 0 : bgp_process(bgp, dest, afi, SAFI_UNICAST);
8844 : else
8845 0 : bgp_path_info_reap(dest, pi);
8846 : }
8847 : }
8848 0 : }
8849 :
8850 : /* Static function to display route. */
8851 1 : static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8852 : struct vty *vty, json_object *json, bool wide)
8853 : {
8854 1 : int len = 0;
8855 1 : char buf[INET6_ADDRSTRLEN];
8856 :
8857 1 : if (p->family == AF_INET) {
8858 1 : if (!json) {
8859 0 : len = vty_out(vty, "%pFX", p);
8860 : } else {
8861 1 : json_object_string_add(json, "prefix",
8862 : inet_ntop(p->family,
8863 1 : &p->u.prefix, buf,
8864 : sizeof(buf)));
8865 1 : json_object_int_add(json, "prefixLen", p->prefixlen);
8866 1 : json_object_string_addf(json, "network", "%pFX", p);
8867 1 : json_object_int_add(json, "version", dest->version);
8868 : }
8869 0 : } else if (p->family == AF_ETHERNET) {
8870 0 : len = vty_out(vty, "%pFX", p);
8871 0 : } else if (p->family == AF_EVPN) {
8872 0 : if (!json)
8873 0 : len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
8874 : else
8875 0 : bgp_evpn_route2json((struct prefix_evpn *)p, json);
8876 0 : } else if (p->family == AF_FLOWSPEC) {
8877 0 : route_vty_out_flowspec(vty, p, NULL,
8878 : json ?
8879 : NLRI_STRING_FORMAT_JSON_SIMPLE :
8880 : NLRI_STRING_FORMAT_MIN, json);
8881 : } else {
8882 0 : if (!json)
8883 0 : len = vty_out(vty, "%pFX", p);
8884 : else {
8885 0 : json_object_string_add(json, "prefix",
8886 : inet_ntop(p->family,
8887 0 : &p->u.prefix, buf,
8888 : sizeof(buf)));
8889 0 : json_object_int_add(json, "prefixLen", p->prefixlen);
8890 0 : json_object_string_addf(json, "network", "%pFX", p);
8891 0 : json_object_int_add(json, "version", dest->version);
8892 : }
8893 : }
8894 :
8895 1 : if (!json) {
8896 0 : len = wide ? (45 - len) : (17 - len);
8897 0 : if (len < 1)
8898 0 : vty_out(vty, "\n%*s", 20, " ");
8899 : else
8900 0 : vty_out(vty, "%*s", len, " ");
8901 : }
8902 1 : }
8903 :
8904 : enum bgp_display_type {
8905 : normal_list,
8906 : };
8907 :
8908 0 : const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8909 : {
8910 0 : switch (reason) {
8911 : case bgp_path_selection_none:
8912 : return "Nothing to Select";
8913 0 : case bgp_path_selection_first:
8914 0 : return "First path received";
8915 0 : case bgp_path_selection_evpn_sticky_mac:
8916 0 : return "EVPN Sticky Mac";
8917 0 : case bgp_path_selection_evpn_seq:
8918 0 : return "EVPN sequence number";
8919 0 : case bgp_path_selection_evpn_lower_ip:
8920 0 : return "EVPN lower IP";
8921 0 : case bgp_path_selection_evpn_local_path:
8922 0 : return "EVPN local ES path";
8923 0 : case bgp_path_selection_evpn_non_proxy:
8924 0 : return "EVPN non proxy";
8925 0 : case bgp_path_selection_weight:
8926 0 : return "Weight";
8927 0 : case bgp_path_selection_local_pref:
8928 0 : return "Local Pref";
8929 0 : case bgp_path_selection_accept_own:
8930 0 : return "Accept Own";
8931 0 : case bgp_path_selection_local_route:
8932 0 : return "Local Route";
8933 0 : case bgp_path_selection_aigp:
8934 0 : return "AIGP";
8935 0 : case bgp_path_selection_confed_as_path:
8936 0 : return "Confederation based AS Path";
8937 0 : case bgp_path_selection_as_path:
8938 0 : return "AS Path";
8939 0 : case bgp_path_selection_origin:
8940 0 : return "Origin";
8941 0 : case bgp_path_selection_med:
8942 0 : return "MED";
8943 0 : case bgp_path_selection_peer:
8944 0 : return "Peer Type";
8945 0 : case bgp_path_selection_confed:
8946 0 : return "Confed Peer Type";
8947 0 : case bgp_path_selection_igp_metric:
8948 0 : return "IGP Metric";
8949 0 : case bgp_path_selection_older:
8950 0 : return "Older Path";
8951 0 : case bgp_path_selection_router_id:
8952 0 : return "Router ID";
8953 0 : case bgp_path_selection_cluster_length:
8954 0 : return "Cluster length";
8955 0 : case bgp_path_selection_stale:
8956 0 : return "Path Staleness";
8957 0 : case bgp_path_selection_local_configured:
8958 0 : return "Locally configured route";
8959 0 : case bgp_path_selection_neighbor_ip:
8960 0 : return "Neighbor IP";
8961 0 : case bgp_path_selection_default:
8962 0 : return "Nothing left to compare";
8963 : }
8964 0 : return "Invalid (internal error)";
8965 : }
8966 :
8967 : /* Print the short form route status for a bgp_path_info */
8968 1 : static void route_vty_short_status_out(struct vty *vty,
8969 : struct bgp_path_info *path,
8970 : const struct prefix *p,
8971 : json_object *json_path)
8972 : {
8973 1 : enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8974 :
8975 1 : if (json_path) {
8976 :
8977 : /* Route status display. */
8978 1 : if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
8979 0 : json_object_boolean_true_add(json_path, "removed");
8980 :
8981 1 : if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
8982 0 : json_object_boolean_true_add(json_path, "stale");
8983 :
8984 1 : if (path->extra && bgp_path_suppressed(path))
8985 0 : json_object_boolean_true_add(json_path, "suppressed");
8986 :
8987 1 : if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8988 1 : && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8989 1 : json_object_boolean_true_add(json_path, "valid");
8990 :
8991 : /* Selected */
8992 1 : if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
8993 0 : json_object_boolean_true_add(json_path, "history");
8994 :
8995 1 : if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
8996 0 : json_object_boolean_true_add(json_path, "damped");
8997 :
8998 1 : if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
8999 0 : json_object_boolean_true_add(json_path, "bestpath");
9000 0 : json_object_string_add(json_path, "selectionReason",
9001 : bgp_path_selection_reason2str(
9002 0 : path->net->reason));
9003 : }
9004 :
9005 1 : if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
9006 0 : json_object_boolean_true_add(json_path, "multipath");
9007 :
9008 : /* Internal route. */
9009 1 : if ((path->peer->as)
9010 1 : && (path->peer->as == path->peer->local_as))
9011 0 : json_object_string_add(json_path, "pathFrom",
9012 : "internal");
9013 : else
9014 1 : json_object_string_add(json_path, "pathFrom",
9015 : "external");
9016 :
9017 1 : return;
9018 : }
9019 :
9020 : /* RPKI validation state */
9021 0 : rpki_state =
9022 0 : hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
9023 :
9024 0 : if (rpki_state == RPKI_VALID)
9025 0 : vty_out(vty, "V");
9026 0 : else if (rpki_state == RPKI_INVALID)
9027 0 : vty_out(vty, "I");
9028 0 : else if (rpki_state == RPKI_NOTFOUND)
9029 0 : vty_out(vty, "N");
9030 : else
9031 0 : vty_out(vty, " ");
9032 :
9033 : /* Route status display. */
9034 0 : if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
9035 0 : vty_out(vty, "R");
9036 0 : else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
9037 0 : vty_out(vty, "S");
9038 0 : else if (bgp_path_suppressed(path))
9039 0 : vty_out(vty, "s");
9040 0 : else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
9041 0 : && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9042 0 : vty_out(vty, "*");
9043 : else
9044 0 : vty_out(vty, " ");
9045 :
9046 : /* Selected */
9047 0 : if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9048 0 : vty_out(vty, "h");
9049 0 : else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
9050 0 : vty_out(vty, "d");
9051 0 : else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
9052 0 : vty_out(vty, ">");
9053 0 : else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
9054 0 : vty_out(vty, "=");
9055 : else
9056 0 : vty_out(vty, " ");
9057 :
9058 : /* Internal route. */
9059 0 : if (path->peer && (path->peer->as)
9060 0 : && (path->peer->as == path->peer->local_as))
9061 0 : vty_out(vty, "i");
9062 : else
9063 0 : vty_out(vty, " ");
9064 : }
9065 :
9066 1 : static char *bgp_nexthop_hostname(struct peer *peer,
9067 : struct bgp_nexthop_cache *bnc)
9068 : {
9069 1 : if (peer->hostname
9070 0 : && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
9071 : return peer->hostname;
9072 : return NULL;
9073 : }
9074 :
9075 : /* called from terminal list command */
9076 1 : void route_vty_out(struct vty *vty, const struct prefix *p,
9077 : struct bgp_path_info *path, int display, safi_t safi,
9078 : json_object *json_paths, bool wide)
9079 : {
9080 1 : int len;
9081 1 : struct attr *attr = path->attr;
9082 1 : json_object *json_path = NULL;
9083 1 : json_object *json_nexthops = NULL;
9084 1 : json_object *json_nexthop_global = NULL;
9085 1 : json_object *json_nexthop_ll = NULL;
9086 1 : json_object *json_ext_community = NULL;
9087 1 : char vrf_id_str[VRF_NAMSIZ] = {0};
9088 1 : bool nexthop_self =
9089 1 : CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9090 1 : bool nexthop_othervrf = false;
9091 1 : vrf_id_t nexthop_vrfid = VRF_DEFAULT;
9092 1 : const char *nexthop_vrfname = VRF_DEFAULT_NAME;
9093 1 : char *nexthop_hostname =
9094 1 : bgp_nexthop_hostname(path->peer, path->nexthop);
9095 1 : char esi_buf[ESI_STR_LEN];
9096 :
9097 1 : if (json_paths)
9098 1 : json_path = json_object_new_object();
9099 :
9100 : /* short status lead text */
9101 1 : route_vty_short_status_out(vty, path, p, json_path);
9102 :
9103 1 : if (!json_paths) {
9104 : /* print prefix and mask */
9105 0 : if (!display)
9106 0 : route_vty_out_route(path->net, p, vty, json_path, wide);
9107 : else
9108 0 : vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9109 : } else {
9110 1 : route_vty_out_route(path->net, p, vty, json_path, wide);
9111 : }
9112 :
9113 : /*
9114 : * If vrf id of nexthop is different from that of prefix,
9115 : * set up printable string to append
9116 : */
9117 1 : if (path->extra && path->extra->bgp_orig) {
9118 0 : const char *self = "";
9119 :
9120 0 : if (nexthop_self)
9121 0 : self = "<";
9122 :
9123 0 : nexthop_othervrf = true;
9124 0 : nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9125 :
9126 0 : if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9127 0 : snprintf(vrf_id_str, sizeof(vrf_id_str),
9128 : "@%s%s", VRFID_NONE_STR, self);
9129 : else
9130 0 : snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9131 : path->extra->bgp_orig->vrf_id, self);
9132 :
9133 0 : if (path->extra->bgp_orig->inst_type
9134 : != BGP_INSTANCE_TYPE_DEFAULT)
9135 :
9136 0 : nexthop_vrfname = path->extra->bgp_orig->name;
9137 : } else {
9138 1 : const char *self = "";
9139 :
9140 1 : if (nexthop_self)
9141 0 : self = "<";
9142 :
9143 1 : snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
9144 : }
9145 :
9146 : /*
9147 : * For ENCAP and EVPN routes, nexthop address family is not
9148 : * neccessarily the same as the prefix address family.
9149 : * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9150 : * EVPN routes are also exchanged with a MP nexthop. Currently,
9151 : * this
9152 : * is only IPv4, the value will be present in either
9153 : * attr->nexthop or
9154 : * attr->mp_nexthop_global_in
9155 : */
9156 1 : if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
9157 0 : char nexthop[128];
9158 0 : int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9159 :
9160 0 : switch (af) {
9161 : case AF_INET:
9162 0 : snprintfrr(nexthop, sizeof(nexthop), "%pI4",
9163 : &attr->mp_nexthop_global_in);
9164 0 : break;
9165 0 : case AF_INET6:
9166 0 : snprintfrr(nexthop, sizeof(nexthop), "%pI6",
9167 : &attr->mp_nexthop_global);
9168 0 : break;
9169 : default:
9170 0 : snprintf(nexthop, sizeof(nexthop), "?");
9171 0 : break;
9172 : }
9173 :
9174 0 : if (json_paths) {
9175 0 : json_nexthop_global = json_object_new_object();
9176 :
9177 0 : json_object_string_add(json_nexthop_global, "ip",
9178 : nexthop);
9179 :
9180 0 : if (path->peer->hostname)
9181 0 : json_object_string_add(json_nexthop_global,
9182 : "hostname",
9183 : path->peer->hostname);
9184 :
9185 0 : json_object_string_add(json_nexthop_global, "afi",
9186 : (af == AF_INET) ? "ipv4"
9187 : : "ipv6");
9188 0 : json_object_boolean_true_add(json_nexthop_global,
9189 : "used");
9190 : } else {
9191 0 : if (nexthop_hostname)
9192 0 : len = vty_out(vty, "%s(%s)%s", nexthop,
9193 : nexthop_hostname, vrf_id_str);
9194 : else
9195 0 : len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9196 :
9197 0 : len = wide ? (41 - len) : (16 - len);
9198 0 : if (len < 1)
9199 0 : vty_out(vty, "\n%*s", 36, " ");
9200 : else
9201 0 : vty_out(vty, "%*s", len, " ");
9202 : }
9203 1 : } else if (safi == SAFI_EVPN) {
9204 0 : if (json_paths) {
9205 0 : json_nexthop_global = json_object_new_object();
9206 :
9207 0 : json_object_string_addf(json_nexthop_global, "ip",
9208 : "%pI4",
9209 : &attr->mp_nexthop_global_in);
9210 :
9211 0 : if (path->peer->hostname)
9212 0 : json_object_string_add(json_nexthop_global,
9213 : "hostname",
9214 : path->peer->hostname);
9215 :
9216 0 : json_object_string_add(json_nexthop_global, "afi",
9217 : "ipv4");
9218 0 : json_object_boolean_true_add(json_nexthop_global,
9219 : "used");
9220 : } else {
9221 0 : if (nexthop_hostname)
9222 0 : len = vty_out(vty, "%pI4(%s)%s",
9223 : &attr->mp_nexthop_global_in,
9224 : nexthop_hostname, vrf_id_str);
9225 : else
9226 0 : len = vty_out(vty, "%pI4%s",
9227 : &attr->mp_nexthop_global_in,
9228 : vrf_id_str);
9229 :
9230 0 : len = wide ? (41 - len) : (16 - len);
9231 0 : if (len < 1)
9232 0 : vty_out(vty, "\n%*s", 36, " ");
9233 : else
9234 0 : vty_out(vty, "%*s", len, " ");
9235 : }
9236 1 : } else if (safi == SAFI_FLOWSPEC) {
9237 0 : if (attr->nexthop.s_addr != INADDR_ANY) {
9238 0 : if (json_paths) {
9239 0 : json_nexthop_global = json_object_new_object();
9240 :
9241 0 : json_object_string_add(json_nexthop_global,
9242 : "afi", "ipv4");
9243 0 : json_object_string_addf(json_nexthop_global,
9244 : "ip", "%pI4",
9245 : &attr->nexthop);
9246 :
9247 0 : if (path->peer->hostname)
9248 0 : json_object_string_add(
9249 : json_nexthop_global, "hostname",
9250 : path->peer->hostname);
9251 :
9252 0 : json_object_boolean_true_add(
9253 : json_nexthop_global,
9254 : "used");
9255 : } else {
9256 0 : if (nexthop_hostname)
9257 0 : len = vty_out(vty, "%pI4(%s)%s",
9258 : &attr->nexthop,
9259 : nexthop_hostname,
9260 : vrf_id_str);
9261 : else
9262 0 : len = vty_out(vty, "%pI4%s",
9263 : &attr->nexthop,
9264 : vrf_id_str);
9265 :
9266 0 : len = wide ? (41 - len) : (16 - len);
9267 0 : if (len < 1)
9268 0 : vty_out(vty, "\n%*s", 36, " ");
9269 : else
9270 0 : vty_out(vty, "%*s", len, " ");
9271 : }
9272 : }
9273 1 : } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9274 1 : if (json_paths) {
9275 1 : json_nexthop_global = json_object_new_object();
9276 :
9277 1 : json_object_string_addf(json_nexthop_global, "ip",
9278 : "%pI4", &attr->nexthop);
9279 :
9280 1 : if (path->peer->hostname)
9281 0 : json_object_string_add(json_nexthop_global,
9282 : "hostname",
9283 : path->peer->hostname);
9284 :
9285 1 : json_object_string_add(json_nexthop_global, "afi",
9286 : "ipv4");
9287 1 : json_object_boolean_true_add(json_nexthop_global,
9288 : "used");
9289 : } else {
9290 0 : if (nexthop_hostname)
9291 0 : len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9292 : nexthop_hostname, vrf_id_str);
9293 : else
9294 0 : len = vty_out(vty, "%pI4%s", &attr->nexthop,
9295 : vrf_id_str);
9296 :
9297 0 : len = wide ? (41 - len) : (16 - len);
9298 0 : if (len < 1)
9299 0 : vty_out(vty, "\n%*s", 36, " ");
9300 : else
9301 0 : vty_out(vty, "%*s", len, " ");
9302 : }
9303 : }
9304 :
9305 : /* IPv6 Next Hop */
9306 0 : else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9307 0 : if (json_paths) {
9308 0 : json_nexthop_global = json_object_new_object();
9309 0 : json_object_string_addf(json_nexthop_global, "ip",
9310 : "%pI6",
9311 : &attr->mp_nexthop_global);
9312 :
9313 0 : if (path->peer->hostname)
9314 0 : json_object_string_add(json_nexthop_global,
9315 : "hostname",
9316 : path->peer->hostname);
9317 :
9318 0 : json_object_string_add(json_nexthop_global, "afi",
9319 : "ipv6");
9320 0 : json_object_string_add(json_nexthop_global, "scope",
9321 : "global");
9322 :
9323 : /* We display both LL & GL if both have been
9324 : * received */
9325 0 : if ((attr->mp_nexthop_len
9326 : == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9327 0 : || (path->peer->conf_if)) {
9328 0 : json_nexthop_ll = json_object_new_object();
9329 0 : json_object_string_addf(
9330 : json_nexthop_ll, "ip", "%pI6",
9331 : &attr->mp_nexthop_local);
9332 :
9333 0 : if (path->peer->hostname)
9334 0 : json_object_string_add(
9335 : json_nexthop_ll, "hostname",
9336 : path->peer->hostname);
9337 :
9338 0 : json_object_string_add(json_nexthop_ll, "afi",
9339 : "ipv6");
9340 0 : json_object_string_add(json_nexthop_ll, "scope",
9341 : "link-local");
9342 :
9343 0 : if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9344 : &attr->mp_nexthop_local)
9345 : != 0)
9346 0 : && !attr->mp_nexthop_prefer_global)
9347 0 : json_object_boolean_true_add(
9348 : json_nexthop_ll, "used");
9349 : else
9350 0 : json_object_boolean_true_add(
9351 : json_nexthop_global, "used");
9352 : } else
9353 0 : json_object_boolean_true_add(
9354 : json_nexthop_global, "used");
9355 : } else {
9356 : /* Display LL if LL/Global both in table unless
9357 : * prefer-global is set */
9358 0 : if (((attr->mp_nexthop_len
9359 : == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9360 0 : && !attr->mp_nexthop_prefer_global)
9361 0 : || (path->peer->conf_if)) {
9362 0 : if (path->peer->conf_if) {
9363 0 : len = vty_out(vty, "%s",
9364 : path->peer->conf_if);
9365 : /* len of IPv6 addr + max len of def
9366 : * ifname */
9367 0 : len = wide ? (41 - len) : (16 - len);
9368 :
9369 0 : if (len < 1)
9370 0 : vty_out(vty, "\n%*s", 36, " ");
9371 : else
9372 0 : vty_out(vty, "%*s", len, " ");
9373 : } else {
9374 0 : if (nexthop_hostname)
9375 0 : len = vty_out(
9376 : vty, "%pI6(%s)%s",
9377 : &attr->mp_nexthop_local,
9378 : nexthop_hostname,
9379 : vrf_id_str);
9380 : else
9381 0 : len = vty_out(
9382 : vty, "%pI6%s",
9383 : &attr->mp_nexthop_local,
9384 : vrf_id_str);
9385 :
9386 0 : len = wide ? (41 - len) : (16 - len);
9387 :
9388 0 : if (len < 1)
9389 0 : vty_out(vty, "\n%*s", 36, " ");
9390 : else
9391 0 : vty_out(vty, "%*s", len, " ");
9392 : }
9393 : } else {
9394 0 : if (nexthop_hostname)
9395 0 : len = vty_out(vty, "%pI6(%s)%s",
9396 : &attr->mp_nexthop_global,
9397 : nexthop_hostname,
9398 : vrf_id_str);
9399 : else
9400 0 : len = vty_out(vty, "%pI6%s",
9401 : &attr->mp_nexthop_global,
9402 : vrf_id_str);
9403 :
9404 0 : len = wide ? (41 - len) : (16 - len);
9405 :
9406 0 : if (len < 1)
9407 0 : vty_out(vty, "\n%*s", 36, " ");
9408 : else
9409 0 : vty_out(vty, "%*s", len, " ");
9410 : }
9411 : }
9412 : }
9413 :
9414 : /* MED/Metric */
9415 1 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9416 0 : if (json_paths)
9417 0 : json_object_int_add(json_path, "metric", attr->med);
9418 0 : else if (wide)
9419 0 : vty_out(vty, "%7u", attr->med);
9420 : else
9421 0 : vty_out(vty, "%10u", attr->med);
9422 1 : else if (!json_paths) {
9423 0 : if (wide)
9424 0 : vty_out(vty, "%*s", 7, " ");
9425 : else
9426 0 : vty_out(vty, "%*s", 10, " ");
9427 : }
9428 :
9429 : /* Local Pref */
9430 1 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9431 0 : if (json_paths)
9432 0 : json_object_int_add(json_path, "locPrf",
9433 0 : attr->local_pref);
9434 : else
9435 0 : vty_out(vty, "%7u", attr->local_pref);
9436 1 : else if (!json_paths)
9437 0 : vty_out(vty, " ");
9438 :
9439 0 : if (json_paths)
9440 1 : json_object_int_add(json_path, "weight", attr->weight);
9441 : else
9442 0 : vty_out(vty, "%7u ", attr->weight);
9443 :
9444 1 : if (json_paths)
9445 1 : json_object_string_addf(json_path, "peerId", "%pSU",
9446 1 : &path->peer->su);
9447 :
9448 : /* Print aspath */
9449 1 : if (attr->aspath) {
9450 1 : if (json_paths)
9451 1 : json_object_string_add(json_path, "path",
9452 1 : attr->aspath->str);
9453 : else
9454 0 : aspath_print_vty(vty, attr->aspath);
9455 : }
9456 :
9457 : /* Print origin */
9458 1 : if (json_paths)
9459 1 : json_object_string_add(json_path, "origin",
9460 1 : bgp_origin_long_str[attr->origin]);
9461 : else
9462 0 : vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9463 :
9464 1 : if (json_paths) {
9465 1 : if (bgp_evpn_is_esi_valid(&attr->esi)) {
9466 0 : json_object_string_add(json_path, "esi",
9467 0 : esi_to_str(&attr->esi,
9468 : esi_buf, sizeof(esi_buf)));
9469 : }
9470 1 : if (safi == SAFI_EVPN &&
9471 0 : attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9472 0 : json_ext_community = json_object_new_object();
9473 0 : json_object_string_add(
9474 : json_ext_community, "string",
9475 0 : bgp_attr_get_ecommunity(attr)->str);
9476 0 : json_object_object_add(json_path,
9477 : "extendedCommunity",
9478 : json_ext_community);
9479 : }
9480 :
9481 1 : if (nexthop_self)
9482 0 : json_object_boolean_true_add(json_path,
9483 : "announceNexthopSelf");
9484 1 : if (nexthop_othervrf) {
9485 0 : json_object_string_add(json_path, "nhVrfName",
9486 : nexthop_vrfname);
9487 :
9488 0 : json_object_int_add(json_path, "nhVrfId",
9489 : ((nexthop_vrfid == VRF_UNKNOWN)
9490 : ? -1
9491 0 : : (int)nexthop_vrfid));
9492 : }
9493 : }
9494 :
9495 1 : if (json_paths) {
9496 1 : if (json_nexthop_global || json_nexthop_ll) {
9497 1 : json_nexthops = json_object_new_array();
9498 :
9499 1 : if (json_nexthop_global)
9500 1 : json_object_array_add(json_nexthops,
9501 : json_nexthop_global);
9502 :
9503 1 : if (json_nexthop_ll)
9504 0 : json_object_array_add(json_nexthops,
9505 : json_nexthop_ll);
9506 :
9507 1 : json_object_object_add(json_path, "nexthops",
9508 : json_nexthops);
9509 : }
9510 :
9511 1 : json_object_array_add(json_paths, json_path);
9512 : } else {
9513 0 : vty_out(vty, "\n");
9514 :
9515 0 : if (safi == SAFI_EVPN) {
9516 0 : if (bgp_evpn_is_esi_valid(&attr->esi)) {
9517 : /* XXX - add these params to the json out */
9518 0 : vty_out(vty, "%*s", 20, " ");
9519 0 : vty_out(vty, "ESI:%s",
9520 : esi_to_str(&attr->esi, esi_buf,
9521 : sizeof(esi_buf)));
9522 :
9523 0 : vty_out(vty, "\n");
9524 : }
9525 0 : if (attr->flag &
9526 : ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9527 0 : vty_out(vty, "%*s", 20, " ");
9528 0 : vty_out(vty, "%s\n",
9529 0 : bgp_attr_get_ecommunity(attr)->str);
9530 : }
9531 : }
9532 :
9533 : #ifdef ENABLE_BGP_VNC
9534 : /* prints an additional line, indented, with VNC info, if
9535 : * present */
9536 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9537 0 : rfapi_vty_out_vncinfo(vty, p, path, safi);
9538 : #endif
9539 : }
9540 1 : }
9541 :
9542 : /* called from terminal list command */
9543 0 : void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9544 : const struct prefix *p, struct attr *attr, safi_t safi,
9545 : bool use_json, json_object *json_ar, bool wide)
9546 : {
9547 0 : json_object *json_status = NULL;
9548 0 : json_object *json_net = NULL;
9549 0 : int len;
9550 0 : char buff[BUFSIZ];
9551 :
9552 : /* Route status display. */
9553 0 : if (use_json) {
9554 0 : json_status = json_object_new_object();
9555 0 : json_net = json_object_new_object();
9556 : } else {
9557 0 : vty_out(vty, " *");
9558 0 : vty_out(vty, ">");
9559 0 : vty_out(vty, " ");
9560 : }
9561 :
9562 : /* print prefix and mask */
9563 0 : if (use_json) {
9564 0 : if (safi == SAFI_EVPN)
9565 0 : bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9566 0 : else if (p->family == AF_INET || p->family == AF_INET6) {
9567 0 : json_object_string_add(
9568 : json_net, "addrPrefix",
9569 0 : inet_ntop(p->family, &p->u.prefix, buff,
9570 : BUFSIZ));
9571 0 : json_object_int_add(json_net, "prefixLen",
9572 0 : p->prefixlen);
9573 0 : json_object_string_addf(json_net, "network", "%pFX", p);
9574 : }
9575 : } else
9576 0 : route_vty_out_route(dest, p, vty, NULL, wide);
9577 :
9578 : /* Print attribute */
9579 0 : if (attr) {
9580 0 : if (use_json) {
9581 0 : if (p->family == AF_INET &&
9582 0 : (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9583 0 : !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9584 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
9585 0 : json_object_string_addf(
9586 : json_net, "nextHop", "%pI4",
9587 : &attr->mp_nexthop_global_in);
9588 : else
9589 0 : json_object_string_addf(
9590 : json_net, "nextHop", "%pI4",
9591 : &attr->nexthop);
9592 0 : } else if (p->family == AF_INET6 ||
9593 0 : BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9594 0 : json_object_string_addf(
9595 : json_net, "nextHopGlobal", "%pI6",
9596 : &attr->mp_nexthop_global);
9597 0 : } else if (p->family == AF_EVPN &&
9598 : !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9599 0 : json_object_string_addf(
9600 : json_net, "nextHop", "%pI4",
9601 : &attr->mp_nexthop_global_in);
9602 : }
9603 :
9604 0 : if (attr->flag
9605 0 : & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9606 0 : json_object_int_add(json_net, "metric",
9607 0 : attr->med);
9608 :
9609 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9610 0 : json_object_int_add(json_net, "locPrf",
9611 0 : attr->local_pref);
9612 :
9613 0 : json_object_int_add(json_net, "weight", attr->weight);
9614 :
9615 : /* Print aspath */
9616 0 : if (attr->aspath)
9617 0 : json_object_string_add(json_net, "path",
9618 0 : attr->aspath->str);
9619 :
9620 : /* Print origin */
9621 : #if CONFDATE > 20231208
9622 : CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
9623 : #endif
9624 0 : json_object_string_add(json_net, "bgpOriginCode",
9625 0 : bgp_origin_str[attr->origin]);
9626 0 : json_object_string_add(
9627 : json_net, "origin",
9628 0 : bgp_origin_long_str[attr->origin]);
9629 : } else {
9630 0 : if (p->family == AF_INET &&
9631 0 : (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9632 0 : safi == SAFI_EVPN ||
9633 0 : !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9634 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9635 : || safi == SAFI_EVPN)
9636 0 : vty_out(vty, "%-16pI4",
9637 : &attr->mp_nexthop_global_in);
9638 0 : else if (wide)
9639 0 : vty_out(vty, "%-41pI4", &attr->nexthop);
9640 : else
9641 0 : vty_out(vty, "%-16pI4", &attr->nexthop);
9642 0 : } else if (p->family == AF_INET6 ||
9643 0 : BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
9644 0 : len = vty_out(vty, "%pI6",
9645 : &attr->mp_nexthop_global);
9646 0 : len = wide ? (41 - len) : (16 - len);
9647 0 : if (len < 1)
9648 0 : vty_out(vty, "\n%*s", 36, " ");
9649 : else
9650 0 : vty_out(vty, "%*s", len, " ");
9651 : }
9652 0 : if (attr->flag
9653 0 : & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9654 0 : if (wide)
9655 0 : vty_out(vty, "%7u", attr->med);
9656 : else
9657 0 : vty_out(vty, "%10u", attr->med);
9658 0 : else if (wide)
9659 0 : vty_out(vty, " ");
9660 : else
9661 0 : vty_out(vty, " ");
9662 :
9663 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9664 0 : vty_out(vty, "%7u", attr->local_pref);
9665 : else
9666 0 : vty_out(vty, " ");
9667 :
9668 0 : vty_out(vty, "%7u ", attr->weight);
9669 :
9670 : /* Print aspath */
9671 0 : if (attr->aspath)
9672 0 : aspath_print_vty(vty, attr->aspath);
9673 :
9674 : /* Print origin */
9675 0 : vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9676 : }
9677 : }
9678 0 : if (use_json) {
9679 0 : struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
9680 :
9681 : #if CONFDATE > 20231208
9682 : CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
9683 : #endif
9684 0 : json_object_boolean_true_add(json_status, "*");
9685 0 : json_object_boolean_true_add(json_status, ">");
9686 0 : json_object_boolean_true_add(json_net, "valid");
9687 0 : json_object_boolean_true_add(json_net, "best");
9688 :
9689 0 : if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
9690 0 : json_object_boolean_true_add(json_status, "=");
9691 0 : json_object_boolean_true_add(json_net, "multipath");
9692 : }
9693 0 : json_object_object_add(json_net, "appliedStatusSymbols",
9694 : json_status);
9695 0 : json_object_object_addf(json_ar, json_net, "%pFX", p);
9696 : } else
9697 0 : vty_out(vty, "\n");
9698 0 : }
9699 :
9700 0 : void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9701 : struct bgp_path_info *path, int display, safi_t safi,
9702 : json_object *json)
9703 : {
9704 0 : json_object *json_out = NULL;
9705 0 : struct attr *attr;
9706 0 : mpls_label_t label = MPLS_INVALID_LABEL;
9707 :
9708 0 : if (!path->extra)
9709 0 : return;
9710 :
9711 0 : if (json)
9712 0 : json_out = json_object_new_object();
9713 :
9714 : /* short status lead text */
9715 0 : route_vty_short_status_out(vty, path, p, json_out);
9716 :
9717 : /* print prefix and mask */
9718 0 : if (json == NULL) {
9719 0 : if (!display)
9720 0 : route_vty_out_route(path->net, p, vty, NULL, false);
9721 : else
9722 0 : vty_out(vty, "%*s", 17, " ");
9723 : }
9724 :
9725 : /* Print attribute */
9726 0 : attr = path->attr;
9727 0 : if (((p->family == AF_INET) &&
9728 0 : ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9729 0 : (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9730 0 : (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9731 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9732 0 : || safi == SAFI_EVPN) {
9733 0 : if (json)
9734 0 : json_object_string_addf(
9735 : json_out, "mpNexthopGlobalIn", "%pI4",
9736 : &attr->mp_nexthop_global_in);
9737 : else
9738 0 : vty_out(vty, "%-16pI4",
9739 : &attr->mp_nexthop_global_in);
9740 : } else {
9741 0 : if (json)
9742 0 : json_object_string_addf(json_out, "nexthop",
9743 : "%pI4", &attr->nexthop);
9744 : else
9745 0 : vty_out(vty, "%-16pI4", &attr->nexthop);
9746 : }
9747 0 : } else if (((p->family == AF_INET6) &&
9748 0 : ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9749 0 : (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9750 0 : (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
9751 0 : char buf_a[512];
9752 :
9753 0 : if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9754 0 : if (json)
9755 0 : json_object_string_addf(
9756 : json_out, "mpNexthopGlobalIn", "%pI6",
9757 : &attr->mp_nexthop_global);
9758 : else
9759 0 : vty_out(vty, "%s",
9760 : inet_ntop(AF_INET6,
9761 0 : &attr->mp_nexthop_global,
9762 : buf_a, sizeof(buf_a)));
9763 0 : } else if (attr->mp_nexthop_len
9764 : == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9765 0 : snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9766 : &attr->mp_nexthop_global,
9767 : &attr->mp_nexthop_local);
9768 0 : if (json)
9769 0 : json_object_string_add(json_out,
9770 : "mpNexthopGlobalLocal",
9771 : buf_a);
9772 : else
9773 0 : vty_out(vty, "%s", buf_a);
9774 : }
9775 : }
9776 :
9777 0 : label = decode_label(&path->extra->label[0]);
9778 :
9779 0 : if (bgp_is_valid_label(&label)) {
9780 0 : if (json) {
9781 0 : json_object_int_add(json_out, "notag", label);
9782 0 : json_object_array_add(json, json_out);
9783 : } else {
9784 0 : vty_out(vty, "notag/%d", label);
9785 0 : vty_out(vty, "\n");
9786 : }
9787 0 : } else if (!json)
9788 0 : vty_out(vty, "\n");
9789 : }
9790 :
9791 0 : void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9792 : struct bgp_path_info *path, int display,
9793 : json_object *json_paths)
9794 : {
9795 0 : struct attr *attr;
9796 0 : json_object *json_path = NULL;
9797 0 : json_object *json_nexthop = NULL;
9798 0 : json_object *json_overlay = NULL;
9799 :
9800 0 : if (!path->extra)
9801 : return;
9802 :
9803 0 : if (json_paths) {
9804 0 : json_path = json_object_new_object();
9805 0 : json_overlay = json_object_new_object();
9806 0 : json_nexthop = json_object_new_object();
9807 : }
9808 :
9809 : /* short status lead text */
9810 0 : route_vty_short_status_out(vty, path, p, json_path);
9811 :
9812 : /* print prefix and mask */
9813 0 : if (!display)
9814 0 : route_vty_out_route(path->net, p, vty, json_path, false);
9815 : else
9816 0 : vty_out(vty, "%*s", 17, " ");
9817 :
9818 : /* Print attribute */
9819 0 : attr = path->attr;
9820 0 : int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9821 :
9822 0 : switch (af) {
9823 : case AF_INET:
9824 0 : if (!json_path) {
9825 0 : vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
9826 : } else {
9827 0 : json_object_string_addf(json_nexthop, "ip", "%pI4",
9828 : &attr->mp_nexthop_global_in);
9829 :
9830 0 : json_object_string_add(json_nexthop, "afi", "ipv4");
9831 :
9832 0 : json_object_object_add(json_path, "nexthop",
9833 : json_nexthop);
9834 : }
9835 : break;
9836 0 : case AF_INET6:
9837 0 : if (!json_path) {
9838 0 : vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9839 : &attr->mp_nexthop_local);
9840 : } else {
9841 0 : json_object_string_addf(json_nexthop, "ipv6Global",
9842 : "%pI6",
9843 : &attr->mp_nexthop_global);
9844 :
9845 0 : json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9846 : "%pI6",
9847 : &attr->mp_nexthop_local);
9848 :
9849 0 : json_object_string_add(json_nexthop, "afi", "ipv6");
9850 :
9851 0 : json_object_object_add(json_path, "nexthop",
9852 : json_nexthop);
9853 : }
9854 : break;
9855 : default:
9856 0 : if (!json_path) {
9857 0 : vty_out(vty, "?");
9858 : } else {
9859 0 : json_object_string_add(json_nexthop, "error",
9860 : "Unsupported address-family");
9861 : }
9862 : }
9863 :
9864 0 : const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9865 :
9866 0 : if (!json_path)
9867 0 : vty_out(vty, "/%pIA", &eo->gw_ip);
9868 : else
9869 0 : json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
9870 :
9871 0 : if (bgp_attr_get_ecommunity(attr)) {
9872 0 : char *mac = NULL;
9873 0 : struct ecommunity_val *routermac = ecommunity_lookup(
9874 0 : bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
9875 : ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9876 :
9877 0 : if (routermac)
9878 0 : mac = ecom_mac2str((char *)routermac->val);
9879 0 : if (mac) {
9880 0 : if (!json_path) {
9881 0 : vty_out(vty, "/%s", mac);
9882 : } else {
9883 0 : json_object_string_add(json_overlay, "rmac",
9884 : mac);
9885 : }
9886 0 : XFREE(MTYPE_TMP, mac);
9887 : }
9888 : }
9889 :
9890 0 : if (!json_path) {
9891 0 : vty_out(vty, "\n");
9892 : } else {
9893 0 : json_object_object_add(json_path, "overlay", json_overlay);
9894 :
9895 0 : json_object_array_add(json_paths, json_path);
9896 : }
9897 : }
9898 :
9899 : /* dampening route */
9900 0 : static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9901 : struct bgp_path_info *path, int display,
9902 : afi_t afi, safi_t safi, bool use_json,
9903 : json_object *json_paths)
9904 : {
9905 0 : struct attr *attr = path->attr;
9906 0 : int len;
9907 0 : char timebuf[BGP_UPTIME_LEN];
9908 0 : json_object *json_path = NULL;
9909 :
9910 0 : if (use_json)
9911 0 : json_path = json_object_new_object();
9912 :
9913 : /* short status lead text */
9914 0 : route_vty_short_status_out(vty, path, p, json_path);
9915 :
9916 : /* print prefix and mask */
9917 0 : if (!use_json) {
9918 0 : if (!display)
9919 0 : route_vty_out_route(path->net, p, vty, NULL, false);
9920 : else
9921 0 : vty_out(vty, "%*s", 17, " ");
9922 :
9923 0 : len = vty_out(vty, "%s", path->peer->host);
9924 0 : len = 17 - len;
9925 :
9926 0 : if (len < 1)
9927 0 : vty_out(vty, "\n%*s", 34, " ");
9928 : else
9929 0 : vty_out(vty, "%*s", len, " ");
9930 :
9931 0 : vty_out(vty, "%s ",
9932 : bgp_damp_reuse_time_vty(vty, path, timebuf,
9933 : BGP_UPTIME_LEN, afi, safi,
9934 : use_json, NULL));
9935 :
9936 0 : if (attr->aspath)
9937 0 : aspath_print_vty(vty, attr->aspath);
9938 :
9939 0 : vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9940 :
9941 0 : vty_out(vty, "\n");
9942 : } else {
9943 0 : bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9944 : safi, use_json, json_path);
9945 :
9946 0 : if (attr->aspath)
9947 0 : json_object_string_add(json_path, "asPath",
9948 0 : attr->aspath->str);
9949 :
9950 0 : json_object_string_add(json_path, "origin",
9951 0 : bgp_origin_str[attr->origin]);
9952 0 : json_object_string_add(json_path, "peerHost", path->peer->host);
9953 :
9954 0 : json_object_array_add(json_paths, json_path);
9955 : }
9956 0 : }
9957 :
9958 : /* flap route */
9959 0 : static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9960 : struct bgp_path_info *path, int display,
9961 : afi_t afi, safi_t safi, bool use_json,
9962 : json_object *json_paths)
9963 : {
9964 0 : struct attr *attr = path->attr;
9965 0 : struct bgp_damp_info *bdi;
9966 0 : char timebuf[BGP_UPTIME_LEN];
9967 0 : int len;
9968 0 : json_object *json_path = NULL;
9969 :
9970 0 : if (!path->extra)
9971 0 : return;
9972 :
9973 0 : if (use_json)
9974 0 : json_path = json_object_new_object();
9975 :
9976 0 : bdi = path->extra->damp_info;
9977 :
9978 : /* short status lead text */
9979 0 : route_vty_short_status_out(vty, path, p, json_path);
9980 :
9981 0 : if (!use_json) {
9982 0 : if (!display)
9983 0 : route_vty_out_route(path->net, p, vty, NULL, false);
9984 : else
9985 0 : vty_out(vty, "%*s", 17, " ");
9986 :
9987 0 : len = vty_out(vty, "%s", path->peer->host);
9988 0 : len = 16 - len;
9989 0 : if (len < 1)
9990 0 : vty_out(vty, "\n%*s", 33, " ");
9991 : else
9992 0 : vty_out(vty, "%*s", len, " ");
9993 :
9994 0 : len = vty_out(vty, "%d", bdi->flap);
9995 0 : len = 5 - len;
9996 0 : if (len < 1)
9997 0 : vty_out(vty, " ");
9998 : else
9999 0 : vty_out(vty, "%*s", len, " ");
10000 :
10001 0 : vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
10002 : BGP_UPTIME_LEN, 0, NULL));
10003 :
10004 0 : if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10005 0 : && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10006 0 : vty_out(vty, "%s ",
10007 : bgp_damp_reuse_time_vty(vty, path, timebuf,
10008 : BGP_UPTIME_LEN, afi,
10009 : safi, use_json, NULL));
10010 : else
10011 0 : vty_out(vty, "%*s ", 8, " ");
10012 :
10013 0 : if (attr->aspath)
10014 0 : aspath_print_vty(vty, attr->aspath);
10015 :
10016 0 : vty_out(vty, "%s", bgp_origin_str[attr->origin]);
10017 :
10018 0 : vty_out(vty, "\n");
10019 : } else {
10020 0 : json_object_string_add(json_path, "peerHost", path->peer->host);
10021 0 : json_object_int_add(json_path, "bdiFlap", bdi->flap);
10022 :
10023 0 : peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
10024 : json_path);
10025 :
10026 0 : if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
10027 0 : && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
10028 0 : bgp_damp_reuse_time_vty(vty, path, timebuf,
10029 : BGP_UPTIME_LEN, afi, safi,
10030 : use_json, json_path);
10031 :
10032 0 : if (attr->aspath)
10033 0 : json_object_string_add(json_path, "asPath",
10034 0 : attr->aspath->str);
10035 :
10036 0 : json_object_string_add(json_path, "origin",
10037 0 : bgp_origin_str[attr->origin]);
10038 :
10039 0 : json_object_array_add(json_paths, json_path);
10040 : }
10041 : }
10042 :
10043 0 : static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
10044 : int *first, const char *header,
10045 : json_object *json_adv_to)
10046 : {
10047 0 : json_object *json_peer = NULL;
10048 :
10049 0 : if (json_adv_to) {
10050 : /* 'advertised-to' is a dictionary of peers we have advertised
10051 : * this
10052 : * prefix too. The key is the peer's IP or swpX, the value is
10053 : * the
10054 : * hostname if we know it and "" if not.
10055 : */
10056 0 : json_peer = json_object_new_object();
10057 :
10058 0 : if (peer->hostname)
10059 0 : json_object_string_add(json_peer, "hostname",
10060 : peer->hostname);
10061 :
10062 0 : if (peer->conf_if)
10063 0 : json_object_object_add(json_adv_to, peer->conf_if,
10064 : json_peer);
10065 : else
10066 0 : json_object_object_addf(json_adv_to, json_peer, "%pSU",
10067 : &peer->su);
10068 : } else {
10069 0 : if (*first) {
10070 0 : vty_out(vty, "%s", header);
10071 0 : *first = 0;
10072 : }
10073 :
10074 0 : if (peer->hostname
10075 0 : && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
10076 0 : if (peer->conf_if)
10077 0 : vty_out(vty, " %s(%s)", peer->hostname,
10078 : peer->conf_if);
10079 : else
10080 0 : vty_out(vty, " %s(%pSU)", peer->hostname,
10081 : &peer->su);
10082 : } else {
10083 0 : if (peer->conf_if)
10084 0 : vty_out(vty, " %s", peer->conf_if);
10085 : else
10086 0 : vty_out(vty, " %pSU", &peer->su);
10087 : }
10088 : }
10089 0 : }
10090 :
10091 0 : static void route_vty_out_tx_ids(struct vty *vty,
10092 : struct bgp_addpath_info_data *d)
10093 : {
10094 0 : int i;
10095 :
10096 0 : for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10097 0 : vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
10098 : d->addpath_tx_id[i],
10099 : i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
10100 : }
10101 0 : }
10102 :
10103 0 : static void route_vty_out_detail_es_info(struct vty *vty,
10104 : struct bgp_path_info *pi,
10105 : struct attr *attr,
10106 : json_object *json_path)
10107 : {
10108 0 : char esi_buf[ESI_STR_LEN];
10109 0 : bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
10110 0 : bool peer_router = !!CHECK_FLAG(attr->es_flags,
10111 : ATTR_ES_PEER_ROUTER);
10112 0 : bool peer_active = !!CHECK_FLAG(attr->es_flags,
10113 : ATTR_ES_PEER_ACTIVE);
10114 0 : bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
10115 : ATTR_ES_PEER_PROXY);
10116 0 : esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
10117 0 : if (json_path) {
10118 0 : json_object *json_es_info = NULL;
10119 :
10120 0 : json_object_string_add(
10121 : json_path, "esi",
10122 : esi_buf);
10123 0 : if (es_local || bgp_evpn_attr_is_sync(attr)) {
10124 0 : json_es_info = json_object_new_object();
10125 0 : if (es_local)
10126 0 : json_object_boolean_true_add(
10127 : json_es_info, "localEs");
10128 0 : if (peer_active)
10129 0 : json_object_boolean_true_add(
10130 : json_es_info, "peerActive");
10131 0 : if (peer_proxy)
10132 0 : json_object_boolean_true_add(
10133 : json_es_info, "peerProxy");
10134 0 : if (peer_router)
10135 0 : json_object_boolean_true_add(
10136 : json_es_info, "peerRouter");
10137 0 : if (attr->mm_sync_seqnum)
10138 0 : json_object_int_add(
10139 : json_es_info, "peerSeq",
10140 : attr->mm_sync_seqnum);
10141 0 : json_object_object_add(
10142 : json_path, "es_info",
10143 : json_es_info);
10144 : }
10145 : } else {
10146 0 : if (bgp_evpn_attr_is_sync(attr))
10147 0 : vty_out(vty,
10148 : " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
10149 : esi_buf,
10150 : es_local ? "local-es":"",
10151 : peer_proxy ? "proxy " : "",
10152 : peer_active ? "active ":"",
10153 : peer_router ? "router ":"",
10154 : attr->mm_sync_seqnum);
10155 : else
10156 0 : vty_out(vty, " ESI %s %s\n",
10157 : esi_buf,
10158 : es_local ? "local-es":"");
10159 : }
10160 0 : }
10161 :
10162 0 : void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
10163 : const struct prefix *p, struct bgp_path_info *path,
10164 : afi_t afi, safi_t safi,
10165 : enum rpki_states rpki_curr_state,
10166 : json_object *json_paths)
10167 : {
10168 0 : char buf[INET6_ADDRSTRLEN];
10169 0 : char tag_buf[30];
10170 0 : struct attr *attr = path->attr;
10171 0 : time_t tbuf;
10172 0 : json_object *json_bestpath = NULL;
10173 0 : json_object *json_cluster_list = NULL;
10174 0 : json_object *json_cluster_list_list = NULL;
10175 0 : json_object *json_ext_community = NULL;
10176 0 : json_object *json_last_update = NULL;
10177 0 : json_object *json_pmsi = NULL;
10178 0 : json_object *json_nexthop_global = NULL;
10179 0 : json_object *json_nexthop_ll = NULL;
10180 0 : json_object *json_nexthops = NULL;
10181 0 : json_object *json_path = NULL;
10182 0 : json_object *json_peer = NULL;
10183 0 : json_object *json_string = NULL;
10184 0 : json_object *json_adv_to = NULL;
10185 0 : int first = 0;
10186 0 : struct listnode *node, *nnode;
10187 0 : struct peer *peer;
10188 0 : bool addpath_capable;
10189 0 : int has_adj;
10190 0 : unsigned int first_as;
10191 0 : bool nexthop_self =
10192 0 : CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
10193 0 : int i;
10194 0 : char *nexthop_hostname =
10195 0 : bgp_nexthop_hostname(path->peer, path->nexthop);
10196 0 : uint32_t ttl = 0;
10197 0 : uint32_t bos = 0;
10198 0 : uint32_t exp = 0;
10199 0 : mpls_label_t label = MPLS_INVALID_LABEL;
10200 0 : tag_buf[0] = '\0';
10201 0 : struct bgp_path_info *bpi_ultimate =
10202 0 : bgp_get_imported_bpi_ultimate(path);
10203 :
10204 0 : if (json_paths) {
10205 0 : json_path = json_object_new_object();
10206 0 : json_peer = json_object_new_object();
10207 0 : json_nexthop_global = json_object_new_object();
10208 : }
10209 :
10210 0 : if (safi == SAFI_EVPN) {
10211 0 : if (!json_paths)
10212 0 : vty_out(vty, " Route %pFX", p);
10213 : }
10214 :
10215 0 : if (path->extra) {
10216 0 : if (path->extra && path->extra->num_labels) {
10217 0 : bgp_evpn_label2str(path->extra->label,
10218 : path->extra->num_labels, tag_buf,
10219 : sizeof(tag_buf));
10220 : }
10221 0 : if (safi == SAFI_EVPN) {
10222 0 : if (!json_paths) {
10223 0 : if (tag_buf[0] != '\0')
10224 0 : vty_out(vty, " VNI %s", tag_buf);
10225 : } else {
10226 0 : if (tag_buf[0])
10227 0 : json_object_string_add(json_path, "vni",
10228 : tag_buf);
10229 : }
10230 : }
10231 : }
10232 :
10233 0 : if (safi == SAFI_EVPN
10234 0 : && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10235 0 : char gwip_buf[INET6_ADDRSTRLEN];
10236 :
10237 0 : ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10238 : sizeof(gwip_buf));
10239 :
10240 0 : if (json_paths)
10241 0 : json_object_string_add(json_path, "gatewayIP",
10242 : gwip_buf);
10243 : else
10244 0 : vty_out(vty, " Gateway IP %s", gwip_buf);
10245 : }
10246 :
10247 0 : if (safi == SAFI_EVPN && !json_path)
10248 0 : vty_out(vty, "\n");
10249 :
10250 :
10251 0 : if (path->extra && path->extra->parent && !json_paths) {
10252 0 : struct bgp_path_info *parent_ri;
10253 0 : struct bgp_dest *dest, *pdest;
10254 :
10255 0 : parent_ri = (struct bgp_path_info *)path->extra->parent;
10256 0 : dest = parent_ri->net;
10257 0 : if (dest && dest->pdest) {
10258 0 : pdest = dest->pdest;
10259 0 : if (is_pi_family_evpn(parent_ri)) {
10260 0 : vty_out(vty,
10261 : " Imported from %pRD:%pFX, VNI %s",
10262 0 : (struct prefix_rd *)bgp_dest_get_prefix(
10263 : pdest),
10264 : (struct prefix_evpn *)
10265 0 : bgp_dest_get_prefix(dest),
10266 : tag_buf);
10267 0 : if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
10268 0 : vty_out(vty, ", L3NHG %s",
10269 : CHECK_FLAG(
10270 : attr->es_flags,
10271 : ATTR_ES_L3_NHG_ACTIVE)
10272 : ? "active"
10273 : : "inactive");
10274 0 : vty_out(vty, "\n");
10275 :
10276 : } else
10277 0 : vty_out(vty, " Imported from %pRD:%pFX\n",
10278 0 : (struct prefix_rd *)bgp_dest_get_prefix(
10279 : pdest),
10280 : (struct prefix_evpn *)
10281 0 : bgp_dest_get_prefix(dest));
10282 : }
10283 : }
10284 :
10285 : /* Line1 display AS-path, Aggregator */
10286 0 : if (attr->aspath) {
10287 0 : if (json_paths) {
10288 0 : if (!attr->aspath->json)
10289 0 : aspath_str_update(attr->aspath, true);
10290 0 : json_object_lock(attr->aspath->json);
10291 0 : json_object_object_add(json_path, "aspath",
10292 0 : attr->aspath->json);
10293 : } else {
10294 0 : if (attr->aspath->segments)
10295 0 : vty_out(vty, " %s", attr->aspath->str);
10296 : else
10297 0 : vty_out(vty, " Local");
10298 : }
10299 : }
10300 :
10301 0 : if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10302 0 : if (json_paths)
10303 0 : json_object_boolean_true_add(json_path, "removed");
10304 : else
10305 0 : vty_out(vty, ", (removed)");
10306 : }
10307 :
10308 0 : if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10309 0 : if (json_paths)
10310 0 : json_object_boolean_true_add(json_path, "stale");
10311 : else
10312 0 : vty_out(vty, ", (stale)");
10313 : }
10314 :
10315 0 : if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10316 0 : if (json_paths) {
10317 0 : json_object_int_add(json_path, "aggregatorAs",
10318 0 : attr->aggregator_as);
10319 0 : json_object_string_addf(json_path, "aggregatorId",
10320 : "%pI4", &attr->aggregator_addr);
10321 : } else {
10322 0 : vty_out(vty, ", (aggregated by %u %pI4)",
10323 : attr->aggregator_as, &attr->aggregator_addr);
10324 : }
10325 : }
10326 :
10327 0 : if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10328 : PEER_FLAG_REFLECTOR_CLIENT)) {
10329 0 : if (json_paths)
10330 0 : json_object_boolean_true_add(json_path,
10331 : "rxedFromRrClient");
10332 : else
10333 0 : vty_out(vty, ", (Received from a RR-client)");
10334 : }
10335 :
10336 0 : if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10337 : PEER_FLAG_RSERVER_CLIENT)) {
10338 0 : if (json_paths)
10339 0 : json_object_boolean_true_add(json_path,
10340 : "rxedFromRsClient");
10341 : else
10342 0 : vty_out(vty, ", (Received from a RS-client)");
10343 : }
10344 :
10345 0 : if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10346 0 : if (json_paths)
10347 0 : json_object_boolean_true_add(json_path,
10348 : "dampeningHistoryEntry");
10349 : else
10350 0 : vty_out(vty, ", (history entry)");
10351 0 : } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10352 0 : if (json_paths)
10353 0 : json_object_boolean_true_add(json_path,
10354 : "dampeningSuppressed");
10355 : else
10356 0 : vty_out(vty, ", (suppressed due to dampening)");
10357 : }
10358 :
10359 0 : if (!json_paths)
10360 0 : vty_out(vty, "\n");
10361 :
10362 : /* Line2 display Next-hop, Neighbor, Router-id */
10363 : /* Display the nexthop */
10364 :
10365 0 : if ((p->family == AF_INET || p->family == AF_ETHERNET ||
10366 0 : p->family == AF_EVPN) &&
10367 0 : (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10368 0 : !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
10369 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10370 : || safi == SAFI_EVPN) {
10371 0 : if (json_paths) {
10372 0 : json_object_string_addf(
10373 : json_nexthop_global, "ip", "%pI4",
10374 : &attr->mp_nexthop_global_in);
10375 :
10376 0 : if (path->peer->hostname)
10377 0 : json_object_string_add(
10378 : json_nexthop_global, "hostname",
10379 : path->peer->hostname);
10380 : } else {
10381 0 : if (nexthop_hostname)
10382 0 : vty_out(vty, " %pI4(%s)",
10383 : &attr->mp_nexthop_global_in,
10384 : nexthop_hostname);
10385 : else
10386 0 : vty_out(vty, " %pI4",
10387 : &attr->mp_nexthop_global_in);
10388 : }
10389 : } else {
10390 0 : if (json_paths) {
10391 0 : json_object_string_addf(json_nexthop_global,
10392 : "ip", "%pI4",
10393 : &attr->nexthop);
10394 :
10395 0 : if (path->peer->hostname)
10396 0 : json_object_string_add(
10397 : json_nexthop_global, "hostname",
10398 : path->peer->hostname);
10399 : } else {
10400 0 : if (nexthop_hostname)
10401 0 : vty_out(vty, " %pI4(%s)",
10402 : &attr->nexthop,
10403 : nexthop_hostname);
10404 : else
10405 0 : vty_out(vty, " %pI4",
10406 : &attr->nexthop);
10407 : }
10408 : }
10409 :
10410 0 : if (json_paths)
10411 0 : json_object_string_add(json_nexthop_global, "afi",
10412 : "ipv4");
10413 : } else {
10414 0 : if (json_paths) {
10415 0 : json_object_string_addf(json_nexthop_global, "ip",
10416 : "%pI6",
10417 : &attr->mp_nexthop_global);
10418 :
10419 0 : if (path->peer->hostname)
10420 0 : json_object_string_add(json_nexthop_global,
10421 : "hostname",
10422 : path->peer->hostname);
10423 :
10424 0 : json_object_string_add(json_nexthop_global, "afi",
10425 : "ipv6");
10426 0 : json_object_string_add(json_nexthop_global, "scope",
10427 : "global");
10428 : } else {
10429 0 : if (nexthop_hostname)
10430 0 : vty_out(vty, " %pI6(%s)",
10431 : &attr->mp_nexthop_global,
10432 : nexthop_hostname);
10433 : else
10434 0 : vty_out(vty, " %pI6",
10435 : &attr->mp_nexthop_global);
10436 : }
10437 : }
10438 :
10439 : /* Display the IGP cost or 'inaccessible' */
10440 0 : if (!CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_VALID)) {
10441 0 : bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10442 :
10443 0 : if (json_paths) {
10444 0 : json_object_boolean_false_add(json_nexthop_global,
10445 : "accessible");
10446 0 : json_object_boolean_add(json_nexthop_global,
10447 : "importCheckEnabled", import);
10448 : } else {
10449 0 : vty_out(vty, " (inaccessible%s)",
10450 : import ? ", import-check enabled" : "");
10451 : }
10452 : } else {
10453 0 : if (bpi_ultimate->extra && bpi_ultimate->extra->igpmetric) {
10454 0 : if (json_paths)
10455 0 : json_object_int_add(
10456 : json_nexthop_global, "metric",
10457 : bpi_ultimate->extra->igpmetric);
10458 : else
10459 0 : vty_out(vty, " (metric %u)",
10460 : bpi_ultimate->extra->igpmetric);
10461 : }
10462 :
10463 : /* IGP cost is 0, display this only for json */
10464 : else {
10465 0 : if (json_paths)
10466 0 : json_object_int_add(json_nexthop_global,
10467 : "metric", 0);
10468 : }
10469 :
10470 0 : if (json_paths)
10471 0 : json_object_boolean_true_add(json_nexthop_global,
10472 : "accessible");
10473 : }
10474 :
10475 : /* Display peer "from" output */
10476 : /* This path was originated locally */
10477 0 : if (path->peer == bgp->peer_self) {
10478 :
10479 0 : if (safi == SAFI_EVPN || (p->family == AF_INET &&
10480 0 : !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
10481 0 : if (json_paths)
10482 0 : json_object_string_add(json_peer, "peerId",
10483 : "0.0.0.0");
10484 : else
10485 0 : vty_out(vty, " from 0.0.0.0 ");
10486 : } else {
10487 0 : if (json_paths)
10488 0 : json_object_string_add(json_peer, "peerId",
10489 : "::");
10490 : else
10491 0 : vty_out(vty, " from :: ");
10492 : }
10493 :
10494 0 : if (json_paths)
10495 0 : json_object_string_addf(json_peer, "routerId", "%pI4",
10496 : &bgp->router_id);
10497 : else
10498 0 : vty_out(vty, "(%pI4)", &bgp->router_id);
10499 : }
10500 :
10501 : /* We RXed this path from one of our peers */
10502 : else {
10503 :
10504 0 : if (json_paths) {
10505 0 : json_object_string_addf(json_peer, "peerId", "%pSU",
10506 : &path->peer->su);
10507 0 : json_object_string_addf(json_peer, "routerId", "%pI4",
10508 0 : &path->peer->remote_id);
10509 :
10510 0 : if (path->peer->hostname)
10511 0 : json_object_string_add(json_peer, "hostname",
10512 : path->peer->hostname);
10513 :
10514 0 : if (path->peer->domainname)
10515 0 : json_object_string_add(json_peer, "domainname",
10516 : path->peer->domainname);
10517 :
10518 0 : if (path->peer->conf_if)
10519 0 : json_object_string_add(json_peer, "interface",
10520 : path->peer->conf_if);
10521 : } else {
10522 0 : if (path->peer->conf_if) {
10523 0 : if (path->peer->hostname
10524 0 : && CHECK_FLAG(path->peer->bgp->flags,
10525 : BGP_FLAG_SHOW_HOSTNAME))
10526 0 : vty_out(vty, " from %s(%s)",
10527 : path->peer->hostname,
10528 : path->peer->conf_if);
10529 : else
10530 0 : vty_out(vty, " from %s",
10531 : path->peer->conf_if);
10532 : } else {
10533 0 : if (path->peer->hostname
10534 0 : && CHECK_FLAG(path->peer->bgp->flags,
10535 : BGP_FLAG_SHOW_HOSTNAME))
10536 0 : vty_out(vty, " from %s(%s)",
10537 : path->peer->hostname,
10538 : path->peer->host);
10539 : else
10540 0 : vty_out(vty, " from %pSU",
10541 : &path->peer->su);
10542 : }
10543 :
10544 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10545 0 : vty_out(vty, " (%pI4)", &attr->originator_id);
10546 : else
10547 0 : vty_out(vty, " (%pI4)", &path->peer->remote_id);
10548 : }
10549 : }
10550 :
10551 : /*
10552 : * Note when vrfid of nexthop is different from that of prefix
10553 : */
10554 0 : if (path->extra && path->extra->bgp_orig) {
10555 0 : vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
10556 :
10557 0 : if (json_paths) {
10558 0 : const char *vn;
10559 :
10560 0 : if (path->extra->bgp_orig->inst_type
10561 : == BGP_INSTANCE_TYPE_DEFAULT)
10562 0 : vn = VRF_DEFAULT_NAME;
10563 : else
10564 0 : vn = path->extra->bgp_orig->name;
10565 :
10566 0 : json_object_string_add(json_path, "nhVrfName", vn);
10567 :
10568 0 : if (nexthop_vrfid == VRF_UNKNOWN) {
10569 0 : json_object_int_add(json_path, "nhVrfId", -1);
10570 : } else {
10571 0 : json_object_int_add(json_path, "nhVrfId",
10572 0 : (int)nexthop_vrfid);
10573 : }
10574 : } else {
10575 0 : if (nexthop_vrfid == VRF_UNKNOWN)
10576 0 : vty_out(vty, " vrf ?");
10577 : else {
10578 0 : struct vrf *vrf;
10579 :
10580 0 : vrf = vrf_lookup_by_id(nexthop_vrfid);
10581 0 : vty_out(vty, " vrf %s(%u)",
10582 : VRF_LOGNAME(vrf), nexthop_vrfid);
10583 : }
10584 : }
10585 : }
10586 :
10587 0 : if (nexthop_self) {
10588 0 : if (json_paths) {
10589 0 : json_object_boolean_true_add(json_path,
10590 : "announceNexthopSelf");
10591 : } else {
10592 0 : vty_out(vty, " announce-nh-self");
10593 : }
10594 : }
10595 :
10596 0 : if (!json_paths)
10597 0 : vty_out(vty, "\n");
10598 :
10599 : /* display the link-local nexthop */
10600 0 : if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10601 0 : if (json_paths) {
10602 0 : json_nexthop_ll = json_object_new_object();
10603 0 : json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10604 : &attr->mp_nexthop_local);
10605 :
10606 0 : if (path->peer->hostname)
10607 0 : json_object_string_add(json_nexthop_ll,
10608 : "hostname",
10609 : path->peer->hostname);
10610 :
10611 0 : json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10612 0 : json_object_string_add(json_nexthop_ll, "scope",
10613 : "link-local");
10614 :
10615 0 : json_object_boolean_true_add(json_nexthop_ll,
10616 : "accessible");
10617 :
10618 0 : if (!attr->mp_nexthop_prefer_global)
10619 0 : json_object_boolean_true_add(json_nexthop_ll,
10620 : "used");
10621 : else
10622 0 : json_object_boolean_true_add(
10623 : json_nexthop_global, "used");
10624 : } else {
10625 0 : vty_out(vty, " (%s) %s\n",
10626 0 : inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10627 : buf, INET6_ADDRSTRLEN),
10628 0 : attr->mp_nexthop_prefer_global
10629 : ? "(prefer-global)"
10630 : : "(used)");
10631 : }
10632 : }
10633 : /* If we do not have a link-local nexthop then we must flag the
10634 : global as "used" */
10635 : else {
10636 0 : if (json_paths)
10637 0 : json_object_boolean_true_add(json_nexthop_global,
10638 : "used");
10639 : }
10640 :
10641 0 : if (safi == SAFI_EVPN &&
10642 0 : bgp_evpn_is_esi_valid(&attr->esi)) {
10643 0 : route_vty_out_detail_es_info(vty, path, attr, json_path);
10644 : }
10645 :
10646 : /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10647 : * Int/Ext/Local, Atomic, best */
10648 0 : if (json_paths)
10649 0 : json_object_string_add(json_path, "origin",
10650 0 : bgp_origin_long_str[attr->origin]);
10651 : else
10652 0 : vty_out(vty, " Origin %s",
10653 0 : bgp_origin_long_str[attr->origin]);
10654 :
10655 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
10656 0 : if (json_paths)
10657 0 : json_object_int_add(json_path, "metric", attr->med);
10658 : else
10659 0 : vty_out(vty, ", metric %u", attr->med);
10660 : }
10661 :
10662 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10663 0 : if (json_paths)
10664 0 : json_object_int_add(json_path, "locPrf",
10665 0 : attr->local_pref);
10666 : else
10667 0 : vty_out(vty, ", localpref %u", attr->local_pref);
10668 : }
10669 :
10670 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
10671 0 : if (json_paths)
10672 0 : json_object_int_add(json_path, "aigpMetric",
10673 0 : bgp_attr_get_aigp_metric(attr));
10674 : else
10675 0 : vty_out(vty, ", aigp-metric %" PRIu64,
10676 : bgp_attr_get_aigp_metric(attr));
10677 : }
10678 :
10679 0 : if (attr->weight != 0) {
10680 0 : if (json_paths)
10681 0 : json_object_int_add(json_path, "weight", attr->weight);
10682 : else
10683 0 : vty_out(vty, ", weight %u", attr->weight);
10684 : }
10685 :
10686 0 : if (attr->tag != 0) {
10687 0 : if (json_paths)
10688 0 : json_object_int_add(json_path, "tag", attr->tag);
10689 : else
10690 0 : vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10691 : }
10692 :
10693 0 : if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10694 0 : if (json_paths)
10695 0 : json_object_boolean_false_add(json_path, "valid");
10696 : else
10697 0 : vty_out(vty, ", invalid");
10698 0 : } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10699 0 : if (json_paths)
10700 0 : json_object_boolean_true_add(json_path, "valid");
10701 : else
10702 0 : vty_out(vty, ", valid");
10703 : }
10704 :
10705 0 : if (json_paths)
10706 0 : json_object_int_add(json_path, "version", bn->version);
10707 :
10708 0 : if (path->peer != bgp->peer_self) {
10709 0 : if (path->peer->as == path->peer->local_as) {
10710 0 : if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10711 0 : if (json_paths)
10712 0 : json_object_string_add(
10713 : json_peer, "type",
10714 : "confed-internal");
10715 : else
10716 0 : vty_out(vty, ", confed-internal");
10717 : } else {
10718 0 : if (json_paths)
10719 0 : json_object_string_add(
10720 : json_peer, "type", "internal");
10721 : else
10722 0 : vty_out(vty, ", internal");
10723 : }
10724 : } else {
10725 0 : if (bgp_confederation_peers_check(bgp,
10726 : path->peer->as)) {
10727 0 : if (json_paths)
10728 0 : json_object_string_add(
10729 : json_peer, "type",
10730 : "confed-external");
10731 : else
10732 0 : vty_out(vty, ", confed-external");
10733 : } else {
10734 0 : if (json_paths)
10735 0 : json_object_string_add(
10736 : json_peer, "type", "external");
10737 : else
10738 0 : vty_out(vty, ", external");
10739 : }
10740 : }
10741 0 : } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10742 0 : if (json_paths) {
10743 0 : json_object_boolean_true_add(json_path, "aggregated");
10744 0 : json_object_boolean_true_add(json_path, "local");
10745 : } else {
10746 0 : vty_out(vty, ", aggregated, local");
10747 : }
10748 0 : } else if (path->type != ZEBRA_ROUTE_BGP) {
10749 0 : if (json_paths)
10750 0 : json_object_boolean_true_add(json_path, "sourced");
10751 : else
10752 0 : vty_out(vty, ", sourced");
10753 : } else {
10754 0 : if (json_paths) {
10755 0 : json_object_boolean_true_add(json_path, "sourced");
10756 0 : json_object_boolean_true_add(json_path, "local");
10757 : } else {
10758 0 : vty_out(vty, ", sourced, local");
10759 : }
10760 : }
10761 :
10762 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
10763 0 : if (json_paths)
10764 0 : json_object_boolean_true_add(json_path,
10765 : "atomicAggregate");
10766 : else
10767 0 : vty_out(vty, ", atomic-aggregate");
10768 : }
10769 :
10770 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10771 0 : if (json_paths)
10772 0 : json_object_int_add(json_path, "otc", attr->otc);
10773 : else
10774 0 : vty_out(vty, ", otc %u", attr->otc);
10775 : }
10776 :
10777 0 : if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10778 0 : || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10779 0 : && bgp_path_info_mpath_count(path))) {
10780 0 : if (json_paths)
10781 0 : json_object_boolean_true_add(json_path, "multipath");
10782 : else
10783 0 : vty_out(vty, ", multipath");
10784 : }
10785 :
10786 : // Mark the bestpath(s)
10787 0 : if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10788 0 : first_as = aspath_get_first_as(attr->aspath);
10789 :
10790 0 : if (json_paths) {
10791 0 : if (!json_bestpath)
10792 0 : json_bestpath = json_object_new_object();
10793 0 : json_object_int_add(json_bestpath, "bestpathFromAs",
10794 : first_as);
10795 : } else {
10796 0 : if (first_as)
10797 0 : vty_out(vty, ", bestpath-from-AS %u", first_as);
10798 : else
10799 0 : vty_out(vty, ", bestpath-from-AS Local");
10800 : }
10801 : }
10802 :
10803 0 : if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10804 0 : if (json_paths) {
10805 0 : if (!json_bestpath)
10806 0 : json_bestpath = json_object_new_object();
10807 0 : json_object_boolean_true_add(json_bestpath, "overall");
10808 0 : json_object_string_add(
10809 : json_bestpath, "selectionReason",
10810 : bgp_path_selection_reason2str(bn->reason));
10811 : } else {
10812 0 : vty_out(vty, ", best");
10813 0 : vty_out(vty, " (%s)",
10814 : bgp_path_selection_reason2str(bn->reason));
10815 : }
10816 : }
10817 :
10818 0 : if (rpki_curr_state != RPKI_NOT_BEING_USED) {
10819 0 : if (json_paths)
10820 0 : json_object_string_add(
10821 : json_path, "rpkiValidationState",
10822 : bgp_rpki_validation2str(rpki_curr_state));
10823 : else
10824 0 : vty_out(vty, ", rpki validation-state: %s",
10825 : bgp_rpki_validation2str(rpki_curr_state));
10826 : }
10827 :
10828 0 : if (json_bestpath)
10829 0 : json_object_object_add(json_path, "bestpath", json_bestpath);
10830 :
10831 0 : if (!json_paths)
10832 0 : vty_out(vty, "\n");
10833 :
10834 : /* Line 4 display Community */
10835 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
10836 0 : if (json_paths) {
10837 0 : if (!bgp_attr_get_community(attr)->json)
10838 0 : community_str(bgp_attr_get_community(attr),
10839 : true, true);
10840 0 : json_object_lock(bgp_attr_get_community(attr)->json);
10841 0 : json_object_object_add(
10842 : json_path, "community",
10843 0 : bgp_attr_get_community(attr)->json);
10844 : } else {
10845 0 : vty_out(vty, " Community: %s\n",
10846 0 : bgp_attr_get_community(attr)->str);
10847 : }
10848 : }
10849 :
10850 : /* Line 5 display Extended-community */
10851 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10852 0 : if (json_paths) {
10853 0 : json_ext_community = json_object_new_object();
10854 0 : json_object_string_add(
10855 : json_ext_community, "string",
10856 0 : bgp_attr_get_ecommunity(attr)->str);
10857 0 : json_object_object_add(json_path, "extendedCommunity",
10858 : json_ext_community);
10859 : } else {
10860 0 : vty_out(vty, " Extended Community: %s\n",
10861 0 : bgp_attr_get_ecommunity(attr)->str);
10862 : }
10863 : }
10864 :
10865 : /* Line 6 display Large community */
10866 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10867 0 : if (json_paths) {
10868 0 : if (!bgp_attr_get_lcommunity(attr)->json)
10869 0 : lcommunity_str(bgp_attr_get_lcommunity(attr),
10870 : true, true);
10871 0 : json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10872 0 : json_object_object_add(
10873 : json_path, "largeCommunity",
10874 0 : bgp_attr_get_lcommunity(attr)->json);
10875 : } else {
10876 0 : vty_out(vty, " Large Community: %s\n",
10877 0 : bgp_attr_get_lcommunity(attr)->str);
10878 : }
10879 : }
10880 :
10881 : /* Line 7 display Originator, Cluster-id */
10882 0 : if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10883 0 : || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
10884 0 : char buf[BUFSIZ] = {0};
10885 :
10886 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
10887 0 : if (json_paths)
10888 0 : json_object_string_addf(json_path,
10889 : "originatorId", "%pI4",
10890 : &attr->originator_id);
10891 : else
10892 0 : vty_out(vty, " Originator: %pI4",
10893 : &attr->originator_id);
10894 : }
10895 :
10896 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10897 0 : struct cluster_list *cluster =
10898 0 : bgp_attr_get_cluster(attr);
10899 0 : int i;
10900 :
10901 0 : if (json_paths) {
10902 0 : json_cluster_list = json_object_new_object();
10903 0 : json_cluster_list_list =
10904 0 : json_object_new_array();
10905 :
10906 0 : for (i = 0; i < cluster->length / 4; i++) {
10907 0 : json_string = json_object_new_string(
10908 : inet_ntop(AF_INET,
10909 0 : &cluster->list[i],
10910 : buf, sizeof(buf)));
10911 0 : json_object_array_add(
10912 : json_cluster_list_list,
10913 : json_string);
10914 : }
10915 :
10916 : /*
10917 : * struct cluster_list does not have
10918 : * "str" variable like aspath and community
10919 : * do. Add this someday if someone asks
10920 : * for it.
10921 : * json_object_string_add(json_cluster_list,
10922 : * "string", cluster->str);
10923 : */
10924 0 : json_object_object_add(json_cluster_list,
10925 : "list",
10926 : json_cluster_list_list);
10927 0 : json_object_object_add(json_path, "clusterList",
10928 : json_cluster_list);
10929 : } else {
10930 0 : vty_out(vty, ", Cluster list: ");
10931 :
10932 0 : for (i = 0; i < cluster->length / 4; i++) {
10933 0 : vty_out(vty, "%pI4 ",
10934 0 : &cluster->list[i]);
10935 : }
10936 : }
10937 : }
10938 :
10939 0 : if (!json_paths)
10940 0 : vty_out(vty, "\n");
10941 : }
10942 :
10943 0 : if (path->extra && path->extra->damp_info)
10944 0 : bgp_damp_info_vty(vty, path, afi, safi, json_path);
10945 :
10946 : /* Remote Label */
10947 0 : if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10948 0 : && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10949 0 : mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10950 : &bos);
10951 :
10952 0 : if (json_paths)
10953 0 : json_object_int_add(json_path, "remoteLabel", label);
10954 : else
10955 0 : vty_out(vty, " Remote label: %d\n", label);
10956 : }
10957 :
10958 : /* Remote SID */
10959 0 : if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10960 0 : if (json_paths)
10961 0 : json_object_string_addf(json_path, "remoteSid", "%pI6",
10962 : &path->extra->sid[0].sid);
10963 : else
10964 0 : vty_out(vty, " Remote SID: %pI6\n",
10965 : &path->extra->sid[0].sid);
10966 : }
10967 :
10968 : /* Label Index */
10969 0 : if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10970 0 : if (json_paths)
10971 0 : json_object_int_add(json_path, "labelIndex",
10972 : attr->label_index);
10973 : else
10974 0 : vty_out(vty, " Label Index: %d\n",
10975 : attr->label_index);
10976 : }
10977 :
10978 : /* Line 8 display Addpath IDs */
10979 0 : if (path->addpath_rx_id
10980 0 : || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10981 0 : if (json_paths) {
10982 0 : json_object_int_add(json_path, "addpathRxId",
10983 0 : path->addpath_rx_id);
10984 :
10985 : /* Keep backwards compatibility with the old API
10986 : * by putting TX All's ID in the old field
10987 : */
10988 0 : json_object_int_add(
10989 : json_path, "addpathTxId",
10990 : path->tx_addpath
10991 0 : .addpath_tx_id[BGP_ADDPATH_ALL]);
10992 :
10993 : /* ... but create a specific field for each
10994 : * strategy
10995 : */
10996 0 : for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10997 0 : json_object_int_add(
10998 : json_path,
10999 0 : bgp_addpath_names(i)->id_json_name,
11000 0 : path->tx_addpath.addpath_tx_id[i]);
11001 : }
11002 : } else {
11003 0 : vty_out(vty, " AddPath ID: RX %u, ",
11004 : path->addpath_rx_id);
11005 :
11006 0 : route_vty_out_tx_ids(vty, &path->tx_addpath);
11007 : }
11008 : }
11009 :
11010 : /* If we used addpath to TX a non-bestpath we need to display
11011 : * "Advertised to" on a path-by-path basis
11012 : */
11013 0 : if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11014 0 : first = 1;
11015 :
11016 0 : for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11017 0 : addpath_capable =
11018 0 : bgp_addpath_encode_tx(peer, afi, safi);
11019 0 : has_adj = bgp_adj_out_lookup(
11020 : peer, path->net,
11021 : bgp_addpath_id_for_peer(peer, afi, safi,
11022 : &path->tx_addpath));
11023 :
11024 0 : if ((addpath_capable && has_adj)
11025 0 : || (!addpath_capable && has_adj
11026 0 : && CHECK_FLAG(path->flags,
11027 : BGP_PATH_SELECTED))) {
11028 0 : if (json_path && !json_adv_to)
11029 0 : json_adv_to = json_object_new_object();
11030 :
11031 0 : route_vty_out_advertised_to(
11032 : vty, peer, &first,
11033 : " Advertised to:", json_adv_to);
11034 : }
11035 : }
11036 :
11037 0 : if (json_path) {
11038 0 : if (json_adv_to) {
11039 0 : json_object_object_add(
11040 : json_path, "advertisedTo", json_adv_to);
11041 : }
11042 : } else {
11043 0 : if (!first) {
11044 0 : vty_out(vty, "\n");
11045 : }
11046 : }
11047 : }
11048 :
11049 : /* Line 9 display Uptime */
11050 0 : tbuf = time(NULL) - (monotime(NULL) - path->uptime);
11051 0 : if (json_paths) {
11052 0 : json_last_update = json_object_new_object();
11053 0 : json_object_int_add(json_last_update, "epoch", tbuf);
11054 0 : json_object_string_add(json_last_update, "string",
11055 0 : ctime(&tbuf));
11056 0 : json_object_object_add(json_path, "lastUpdate",
11057 : json_last_update);
11058 : } else
11059 0 : vty_out(vty, " Last update: %s", ctime(&tbuf));
11060 :
11061 : /* Line 10 display PMSI tunnel attribute, if present */
11062 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
11063 0 : const char *str = lookup_msg(bgp_pmsi_tnltype_str,
11064 0 : bgp_attr_get_pmsi_tnl_type(attr),
11065 : PMSI_TNLTYPE_STR_DEFAULT);
11066 :
11067 0 : if (json_paths) {
11068 0 : json_pmsi = json_object_new_object();
11069 0 : json_object_string_add(json_pmsi, "tunnelType", str);
11070 0 : json_object_int_add(json_pmsi, "label",
11071 0 : label2vni(&attr->label));
11072 0 : json_object_object_add(json_path, "pmsi", json_pmsi);
11073 : } else
11074 0 : vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
11075 : str, label2vni(&attr->label));
11076 : }
11077 :
11078 0 : if (path->peer->t_gr_restart &&
11079 0 : CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
11080 0 : unsigned long gr_remaining =
11081 0 : thread_timer_remain_second(path->peer->t_gr_restart);
11082 :
11083 0 : if (json_paths) {
11084 0 : json_object_int_add(json_path,
11085 : "gracefulRestartSecondsRemaining",
11086 : gr_remaining);
11087 : } else
11088 0 : vty_out(vty,
11089 : " Time until Graceful Restart stale route deleted: %lu\n",
11090 : gr_remaining);
11091 : }
11092 :
11093 0 : if (path->peer->t_llgr_stale[afi][safi] &&
11094 0 : bgp_attr_get_community(attr) &&
11095 0 : community_include(bgp_attr_get_community(attr),
11096 : COMMUNITY_LLGR_STALE)) {
11097 0 : unsigned long llgr_remaining = thread_timer_remain_second(
11098 0 : path->peer->t_llgr_stale[afi][safi]);
11099 :
11100 0 : if (json_paths) {
11101 0 : json_object_int_add(json_path, "llgrSecondsRemaining",
11102 : llgr_remaining);
11103 : } else
11104 0 : vty_out(vty,
11105 : " Time until Long-lived stale route deleted: %lu\n",
11106 : llgr_remaining);
11107 : }
11108 :
11109 : /* Output some debug about internal state of the dest flags */
11110 0 : if (json_paths) {
11111 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
11112 0 : json_object_boolean_true_add(json_path, "processScheduled");
11113 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
11114 0 : json_object_boolean_true_add(json_path, "userCleared");
11115 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
11116 0 : json_object_boolean_true_add(json_path, "labelChanged");
11117 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
11118 0 : json_object_boolean_true_add(json_path, "registeredForLabel");
11119 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
11120 0 : json_object_boolean_true_add(json_path, "selectDefered");
11121 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
11122 0 : json_object_boolean_true_add(json_path, "fibInstalled");
11123 0 : if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
11124 0 : json_object_boolean_true_add(json_path, "fibPending");
11125 :
11126 0 : if (json_nexthop_global || json_nexthop_ll) {
11127 0 : json_nexthops = json_object_new_array();
11128 :
11129 0 : if (json_nexthop_global)
11130 0 : json_object_array_add(json_nexthops,
11131 : json_nexthop_global);
11132 :
11133 0 : if (json_nexthop_ll)
11134 0 : json_object_array_add(json_nexthops,
11135 : json_nexthop_ll);
11136 :
11137 0 : json_object_object_add(json_path, "nexthops",
11138 : json_nexthops);
11139 : }
11140 :
11141 0 : json_object_object_add(json_path, "peer", json_peer);
11142 0 : json_object_array_add(json_paths, json_path);
11143 : }
11144 0 : }
11145 :
11146 : #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
11147 : #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
11148 : #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
11149 :
11150 : static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
11151 : afi_t afi, safi_t safi, enum bgp_show_type type,
11152 : bool use_json);
11153 : static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11154 : const char *comstr, int exact, afi_t afi,
11155 : safi_t safi, uint16_t show_flags);
11156 :
11157 1 : static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
11158 : struct bgp_table *table, enum bgp_show_type type,
11159 : void *output_arg, const char *rd, int is_last,
11160 : unsigned long *output_cum, unsigned long *total_cum,
11161 : unsigned long *json_header_depth, uint16_t show_flags,
11162 : enum rpki_states rpki_target_state)
11163 : {
11164 1 : struct bgp_path_info *pi;
11165 1 : struct bgp_dest *dest;
11166 1 : bool header = true;
11167 1 : bool json_detail_header = false;
11168 1 : int display;
11169 1 : unsigned long output_count = 0;
11170 1 : unsigned long total_count = 0;
11171 1 : struct prefix *p;
11172 1 : json_object *json_paths = NULL;
11173 1 : int first = 1;
11174 1 : bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11175 1 : bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11176 1 : bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11177 1 : bool detail_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
11178 1 : bool detail_routes = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
11179 :
11180 1 : if (output_cum && *output_cum != 0)
11181 1 : header = false;
11182 :
11183 1 : if (use_json && !*json_header_depth) {
11184 1 : if (all)
11185 0 : *json_header_depth = 1;
11186 : else {
11187 1 : vty_out(vty, "{\n");
11188 1 : *json_header_depth = 2;
11189 : }
11190 :
11191 1 : vty_out(vty,
11192 : " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11193 : ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
11194 : " \"localAS\": %u,\n \"routes\": { ",
11195 1 : bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
11196 1 : bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
11197 1 : ? VRF_DEFAULT_NAME
11198 : : bgp->name,
11199 : table->version, &bgp->router_id,
11200 : bgp->default_local_pref, bgp->as);
11201 1 : if (rd) {
11202 0 : vty_out(vty, " \"routeDistinguishers\" : {");
11203 0 : ++*json_header_depth;
11204 : }
11205 : }
11206 :
11207 1 : if (use_json && rd) {
11208 0 : vty_out(vty, " \"%s\" : { ", rd);
11209 : }
11210 :
11211 : /* Check for 'json detail', where we need header output once per dest */
11212 1 : if (use_json && detail_json && type != bgp_show_type_dampend_paths &&
11213 : type != bgp_show_type_damp_neighbor &&
11214 0 : type != bgp_show_type_flap_statistics &&
11215 : type != bgp_show_type_flap_neighbor)
11216 1 : json_detail_header = true;
11217 :
11218 : /* Start processing of routes. */
11219 3 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11220 1 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11221 1 : enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
11222 1 : bool json_detail = json_detail_header;
11223 :
11224 1 : pi = bgp_dest_get_bgp_path_info(dest);
11225 1 : if (pi == NULL)
11226 0 : continue;
11227 :
11228 1 : display = 0;
11229 1 : if (use_json)
11230 1 : json_paths = json_object_new_array();
11231 : else
11232 1 : json_paths = NULL;
11233 :
11234 2 : for (; pi; pi = pi->next) {
11235 1 : struct community *picomm = NULL;
11236 :
11237 1 : picomm = bgp_attr_get_community(pi->attr);
11238 :
11239 1 : total_count++;
11240 :
11241 1 : if (type == bgp_show_type_prefix_version) {
11242 0 : uint32_t version =
11243 0 : strtoul(output_arg, NULL, 10);
11244 0 : if (dest->version < version)
11245 0 : continue;
11246 : }
11247 :
11248 1 : if (type == bgp_show_type_community_alias) {
11249 0 : char *alias = output_arg;
11250 0 : char **communities;
11251 0 : int num;
11252 0 : bool found = false;
11253 :
11254 0 : if (picomm) {
11255 0 : frrstr_split(picomm->str, " ",
11256 : &communities, &num);
11257 0 : for (int i = 0; i < num; i++) {
11258 0 : const char *com2alias =
11259 0 : bgp_community2alias(
11260 0 : communities[i]);
11261 0 : if (!found
11262 0 : && strcmp(alias, com2alias)
11263 : == 0)
11264 0 : found = true;
11265 0 : XFREE(MTYPE_TMP,
11266 : communities[i]);
11267 : }
11268 0 : XFREE(MTYPE_TMP, communities);
11269 : }
11270 :
11271 0 : if (!found &&
11272 0 : bgp_attr_get_lcommunity(pi->attr)) {
11273 0 : frrstr_split(bgp_attr_get_lcommunity(
11274 0 : pi->attr)
11275 0 : ->str,
11276 : " ", &communities, &num);
11277 0 : for (int i = 0; i < num; i++) {
11278 0 : const char *com2alias =
11279 0 : bgp_community2alias(
11280 0 : communities[i]);
11281 0 : if (!found
11282 0 : && strcmp(alias, com2alias)
11283 : == 0)
11284 0 : found = true;
11285 0 : XFREE(MTYPE_TMP,
11286 : communities[i]);
11287 : }
11288 0 : XFREE(MTYPE_TMP, communities);
11289 : }
11290 :
11291 0 : if (!found)
11292 0 : continue;
11293 : }
11294 :
11295 1 : if (type == bgp_show_type_rpki) {
11296 0 : if (dest_p->family == AF_INET
11297 0 : || dest_p->family == AF_INET6)
11298 0 : rpki_curr_state = hook_call(
11299 : bgp_rpki_prefix_status,
11300 : pi->peer, pi->attr, dest_p);
11301 0 : if (rpki_target_state != RPKI_NOT_BEING_USED
11302 0 : && rpki_curr_state != rpki_target_state)
11303 0 : continue;
11304 : }
11305 :
11306 1 : if (type == bgp_show_type_flap_statistics
11307 : || type == bgp_show_type_flap_neighbor
11308 : || type == bgp_show_type_dampend_paths
11309 1 : || type == bgp_show_type_damp_neighbor) {
11310 0 : if (!(pi->extra && pi->extra->damp_info))
11311 0 : continue;
11312 : }
11313 1 : if (type == bgp_show_type_regexp) {
11314 0 : regex_t *regex = output_arg;
11315 :
11316 0 : if (bgp_regexec(regex, pi->attr->aspath)
11317 : == REG_NOMATCH)
11318 0 : continue;
11319 : }
11320 1 : if (type == bgp_show_type_prefix_list) {
11321 0 : struct prefix_list *plist = output_arg;
11322 :
11323 0 : if (prefix_list_apply(plist, dest_p)
11324 : != PREFIX_PERMIT)
11325 0 : continue;
11326 : }
11327 1 : if (type == bgp_show_type_access_list) {
11328 0 : struct access_list *alist = output_arg;
11329 :
11330 0 : if (access_list_apply(alist, dest_p) !=
11331 : FILTER_PERMIT)
11332 0 : continue;
11333 : }
11334 1 : if (type == bgp_show_type_filter_list) {
11335 0 : struct as_list *as_list = output_arg;
11336 :
11337 0 : if (as_list_apply(as_list, pi->attr->aspath)
11338 : != AS_FILTER_PERMIT)
11339 0 : continue;
11340 : }
11341 1 : if (type == bgp_show_type_route_map) {
11342 0 : struct route_map *rmap = output_arg;
11343 0 : struct bgp_path_info path;
11344 0 : struct bgp_path_info_extra extra;
11345 0 : struct attr dummy_attr = {};
11346 0 : route_map_result_t ret;
11347 :
11348 0 : dummy_attr = *pi->attr;
11349 :
11350 0 : prep_for_rmap_apply(&path, &extra, dest, pi,
11351 : pi->peer, &dummy_attr);
11352 :
11353 0 : ret = route_map_apply(rmap, dest_p, &path);
11354 0 : bgp_attr_flush(&dummy_attr);
11355 0 : if (ret == RMAP_DENYMATCH)
11356 0 : continue;
11357 : }
11358 1 : if (type == bgp_show_type_neighbor
11359 1 : || type == bgp_show_type_flap_neighbor
11360 1 : || type == bgp_show_type_damp_neighbor) {
11361 0 : union sockunion *su = output_arg;
11362 :
11363 0 : if (pi->peer == NULL
11364 0 : || pi->peer->su_remote == NULL
11365 0 : || !sockunion_same(pi->peer->su_remote, su))
11366 0 : continue;
11367 : }
11368 1 : if (type == bgp_show_type_cidr_only) {
11369 0 : uint32_t destination;
11370 :
11371 0 : destination = ntohl(dest_p->u.prefix4.s_addr);
11372 0 : if (IN_CLASSC(destination)
11373 0 : && dest_p->prefixlen == 24)
11374 0 : continue;
11375 0 : if (IN_CLASSB(destination)
11376 0 : && dest_p->prefixlen == 16)
11377 0 : continue;
11378 0 : if (IN_CLASSA(destination)
11379 0 : && dest_p->prefixlen == 8)
11380 0 : continue;
11381 : }
11382 1 : if (type == bgp_show_type_prefix_longer) {
11383 0 : p = output_arg;
11384 0 : if (!prefix_match(p, dest_p))
11385 0 : continue;
11386 : }
11387 1 : if (type == bgp_show_type_community_all) {
11388 0 : if (!picomm)
11389 0 : continue;
11390 : }
11391 1 : if (type == bgp_show_type_community) {
11392 0 : struct community *com = output_arg;
11393 :
11394 0 : if (!picomm || !community_match(picomm, com))
11395 0 : continue;
11396 : }
11397 1 : if (type == bgp_show_type_community_exact) {
11398 0 : struct community *com = output_arg;
11399 :
11400 0 : if (!picomm || !community_cmp(picomm, com))
11401 0 : continue;
11402 : }
11403 1 : if (type == bgp_show_type_community_list) {
11404 0 : struct community_list *list = output_arg;
11405 :
11406 0 : if (!community_list_match(picomm, list))
11407 0 : continue;
11408 : }
11409 1 : if (type == bgp_show_type_community_list_exact) {
11410 0 : struct community_list *list = output_arg;
11411 :
11412 0 : if (!community_list_exact_match(picomm, list))
11413 0 : continue;
11414 : }
11415 1 : if (type == bgp_show_type_lcommunity) {
11416 0 : struct lcommunity *lcom = output_arg;
11417 :
11418 0 : if (!bgp_attr_get_lcommunity(pi->attr) ||
11419 0 : !lcommunity_match(
11420 0 : bgp_attr_get_lcommunity(pi->attr),
11421 : lcom))
11422 0 : continue;
11423 : }
11424 :
11425 1 : if (type == bgp_show_type_lcommunity_exact) {
11426 0 : struct lcommunity *lcom = output_arg;
11427 :
11428 0 : if (!bgp_attr_get_lcommunity(pi->attr) ||
11429 0 : !lcommunity_cmp(
11430 0 : bgp_attr_get_lcommunity(pi->attr),
11431 : lcom))
11432 0 : continue;
11433 : }
11434 1 : if (type == bgp_show_type_lcommunity_list) {
11435 0 : struct community_list *list = output_arg;
11436 :
11437 0 : if (!lcommunity_list_match(
11438 0 : bgp_attr_get_lcommunity(pi->attr),
11439 : list))
11440 0 : continue;
11441 : }
11442 1 : if (type
11443 : == bgp_show_type_lcommunity_list_exact) {
11444 0 : struct community_list *list = output_arg;
11445 :
11446 0 : if (!lcommunity_list_exact_match(
11447 0 : bgp_attr_get_lcommunity(pi->attr),
11448 : list))
11449 0 : continue;
11450 : }
11451 1 : if (type == bgp_show_type_lcommunity_all) {
11452 0 : if (!bgp_attr_get_lcommunity(pi->attr))
11453 0 : continue;
11454 : }
11455 1 : if (type == bgp_show_type_dampend_paths
11456 1 : || type == bgp_show_type_damp_neighbor) {
11457 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11458 0 : || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11459 0 : continue;
11460 : }
11461 :
11462 1 : if (!use_json && header) {
11463 0 : vty_out(vty,
11464 : "BGP table version is %" PRIu64
11465 : ", local router ID is %pI4, vrf id ",
11466 : table->version, &bgp->router_id);
11467 0 : if (bgp->vrf_id == VRF_UNKNOWN)
11468 0 : vty_out(vty, "%s", VRFID_NONE_STR);
11469 : else
11470 0 : vty_out(vty, "%u", bgp->vrf_id);
11471 0 : vty_out(vty, "\n");
11472 0 : vty_out(vty, "Default local pref %u, ",
11473 : bgp->default_local_pref);
11474 0 : vty_out(vty, "local AS %u\n", bgp->as);
11475 0 : if (!detail_routes) {
11476 0 : vty_out(vty, BGP_SHOW_SCODE_HEADER);
11477 0 : vty_out(vty, BGP_SHOW_NCODE_HEADER);
11478 0 : vty_out(vty, BGP_SHOW_OCODE_HEADER);
11479 0 : vty_out(vty, BGP_SHOW_RPKI_HEADER);
11480 : }
11481 0 : if (type == bgp_show_type_dampend_paths
11482 : || type == bgp_show_type_damp_neighbor)
11483 0 : vty_out(vty, BGP_SHOW_DAMP_HEADER);
11484 0 : else if (type == bgp_show_type_flap_statistics
11485 : || type == bgp_show_type_flap_neighbor)
11486 0 : vty_out(vty, BGP_SHOW_FLAP_HEADER);
11487 0 : else if (!detail_routes)
11488 0 : vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11489 : : BGP_SHOW_HEADER));
11490 : header = false;
11491 :
11492 1 : } else if (json_detail && json_paths != NULL) {
11493 0 : const struct prefix_rd *prd;
11494 0 : json_object *jtemp;
11495 :
11496 : /* Use common detail header, for most types;
11497 : * need a json 'object'.
11498 : */
11499 :
11500 0 : jtemp = json_object_new_object();
11501 0 : prd = bgp_rd_from_dest(dest, safi);
11502 :
11503 0 : route_vty_out_detail_header(
11504 : vty, bgp, dest,
11505 : bgp_dest_get_prefix(dest), prd,
11506 : table->afi, safi, jtemp);
11507 :
11508 0 : json_object_array_add(json_paths, jtemp);
11509 :
11510 0 : json_detail = false;
11511 : }
11512 :
11513 1 : if (rd != NULL && !display && !output_count) {
11514 0 : if (!use_json)
11515 0 : vty_out(vty,
11516 : "Route Distinguisher: %s\n",
11517 : rd);
11518 : }
11519 1 : if (type == bgp_show_type_dampend_paths
11520 : || type == bgp_show_type_damp_neighbor)
11521 0 : damp_route_vty_out(vty, dest_p, pi, display,
11522 : AFI_IP, safi, use_json,
11523 : json_paths);
11524 1 : else if (type == bgp_show_type_flap_statistics
11525 : || type == bgp_show_type_flap_neighbor)
11526 0 : flap_route_vty_out(vty, dest_p, pi, display,
11527 : AFI_IP, safi, use_json,
11528 : json_paths);
11529 : else {
11530 1 : if (detail_routes || detail_json) {
11531 0 : const struct prefix_rd *prd = NULL;
11532 :
11533 0 : if (dest->pdest)
11534 0 : prd = bgp_rd_from_dest(
11535 : dest->pdest, safi);
11536 :
11537 0 : if (!use_json)
11538 0 : route_vty_out_detail_header(
11539 : vty, bgp, dest,
11540 : bgp_dest_get_prefix(
11541 : dest),
11542 : prd, table->afi, safi,
11543 : NULL);
11544 :
11545 0 : route_vty_out_detail(
11546 : vty, bgp, dest, dest_p, pi,
11547 0 : family2afi(dest_p->family),
11548 : safi, RPKI_NOT_BEING_USED,
11549 : json_paths);
11550 : } else {
11551 1 : route_vty_out(vty, dest_p, pi, display,
11552 : safi, json_paths, wide);
11553 : }
11554 : }
11555 1 : display++;
11556 : }
11557 :
11558 1 : if (display) {
11559 1 : output_count++;
11560 1 : if (!use_json)
11561 0 : continue;
11562 :
11563 : /* encode prefix */
11564 1 : if (dest_p->family == AF_FLOWSPEC) {
11565 0 : char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11566 :
11567 :
11568 0 : bgp_fs_nlri_get_string(
11569 : (unsigned char *)
11570 0 : dest_p->u.prefix_flowspec.ptr,
11571 0 : dest_p->u.prefix_flowspec.prefixlen,
11572 : retstr, NLRI_STRING_FORMAT_MIN, NULL,
11573 : family2afi(dest_p->u
11574 0 : .prefix_flowspec.family));
11575 0 : if (first)
11576 0 : vty_out(vty, "\"%s/%d\": ", retstr,
11577 : dest_p->u.prefix_flowspec
11578 0 : .prefixlen);
11579 : else
11580 0 : vty_out(vty, ",\"%s/%d\": ", retstr,
11581 : dest_p->u.prefix_flowspec
11582 0 : .prefixlen);
11583 : } else {
11584 1 : if (first)
11585 1 : vty_out(vty, "\"%pFX\": ", dest_p);
11586 : else
11587 0 : vty_out(vty, ",\"%pFX\": ", dest_p);
11588 : }
11589 : /*
11590 : * We are using no_pretty here because under
11591 : * extremely high settings( say lots and lots of
11592 : * routes with lots and lots of ways to reach
11593 : * that route via different paths ) this can
11594 : * save several minutes of output when FRR
11595 : * is run on older cpu's or more underperforming
11596 : * routers out there
11597 : */
11598 1 : vty_json_no_pretty(vty, json_paths);
11599 1 : json_paths = NULL;
11600 1 : first = 0;
11601 : } else
11602 0 : json_object_free(json_paths);
11603 : }
11604 :
11605 1 : if (output_cum) {
11606 0 : output_count += *output_cum;
11607 0 : *output_cum = output_count;
11608 : }
11609 1 : if (total_cum) {
11610 0 : total_count += *total_cum;
11611 0 : *total_cum = total_count;
11612 : }
11613 1 : if (use_json) {
11614 1 : if (rd) {
11615 0 : vty_out(vty, " }%s ", (is_last ? "" : ","));
11616 : }
11617 1 : if (is_last) {
11618 : unsigned long i;
11619 3 : for (i = 0; i < *json_header_depth; ++i)
11620 2 : vty_out(vty, " } ");
11621 1 : if (!all)
11622 1 : vty_out(vty, "\n");
11623 : }
11624 : } else {
11625 0 : if (is_last) {
11626 : /* No route is displayed */
11627 0 : if (output_count == 0) {
11628 0 : if (type == bgp_show_type_normal)
11629 0 : vty_out(vty,
11630 : "No BGP prefixes displayed, %ld exist\n",
11631 : total_count);
11632 : } else
11633 0 : vty_out(vty,
11634 : "\nDisplayed %ld routes and %ld total paths\n",
11635 : output_count, total_count);
11636 : }
11637 : }
11638 :
11639 1 : return CMD_SUCCESS;
11640 : }
11641 :
11642 0 : int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11643 : struct bgp_table *table, struct prefix_rd *prd_match,
11644 : enum bgp_show_type type, void *output_arg,
11645 : uint16_t show_flags)
11646 : {
11647 0 : struct bgp_dest *dest, *next;
11648 0 : unsigned long output_cum = 0;
11649 0 : unsigned long total_cum = 0;
11650 0 : unsigned long json_header_depth = 0;
11651 0 : struct bgp_table *itable;
11652 0 : bool show_msg;
11653 0 : bool use_json = !!CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11654 :
11655 0 : show_msg = (!use_json && type == bgp_show_type_normal);
11656 :
11657 0 : for (dest = bgp_table_top(table); dest; dest = next) {
11658 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
11659 :
11660 0 : next = bgp_route_next(dest);
11661 0 : if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
11662 0 : continue;
11663 :
11664 0 : itable = bgp_dest_get_bgp_table_info(dest);
11665 0 : if (itable != NULL) {
11666 0 : struct prefix_rd prd;
11667 0 : char rd[RD_ADDRSTRLEN];
11668 :
11669 0 : memcpy(&prd, dest_p, sizeof(struct prefix_rd));
11670 0 : prefix_rd2str(&prd, rd, sizeof(rd));
11671 0 : bgp_show_table(vty, bgp, safi, itable, type, output_arg,
11672 : rd, next == NULL, &output_cum,
11673 : &total_cum, &json_header_depth,
11674 : show_flags, RPKI_NOT_BEING_USED);
11675 0 : if (next == NULL)
11676 0 : show_msg = false;
11677 : }
11678 : }
11679 0 : if (show_msg) {
11680 0 : if (output_cum == 0)
11681 0 : vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11682 : total_cum);
11683 : else
11684 0 : vty_out(vty,
11685 : "\nDisplayed %ld routes and %ld total paths\n",
11686 : output_cum, total_cum);
11687 : } else {
11688 0 : if (use_json && output_cum == 0)
11689 0 : vty_out(vty, "{}\n");
11690 : }
11691 0 : return CMD_SUCCESS;
11692 : }
11693 :
11694 1 : static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
11695 : enum bgp_show_type type, void *output_arg,
11696 : uint16_t show_flags, enum rpki_states rpki_target_state)
11697 : {
11698 1 : struct bgp_table *table;
11699 1 : unsigned long json_header_depth = 0;
11700 1 : bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11701 :
11702 1 : if (bgp == NULL) {
11703 0 : bgp = bgp_get_default();
11704 : }
11705 :
11706 0 : if (bgp == NULL) {
11707 0 : if (!use_json)
11708 0 : vty_out(vty, "No BGP process is configured\n");
11709 : else
11710 0 : vty_out(vty, "{}\n");
11711 0 : return CMD_WARNING;
11712 : }
11713 :
11714 : /* Labeled-unicast routes live in the unicast table. */
11715 1 : if (safi == SAFI_LABELED_UNICAST)
11716 0 : safi = SAFI_UNICAST;
11717 :
11718 1 : table = bgp->rib[afi][safi];
11719 : /* use MPLS and ENCAP specific shows until they are merged */
11720 1 : if (safi == SAFI_MPLS_VPN) {
11721 0 : return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11722 : output_arg, show_flags);
11723 : }
11724 :
11725 1 : if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11726 0 : return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11727 : output_arg, use_json,
11728 : 1, NULL, NULL);
11729 : }
11730 :
11731 1 : if (safi == SAFI_EVPN)
11732 0 : return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
11733 :
11734 1 : return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
11735 : NULL, NULL, &json_header_depth, show_flags,
11736 : rpki_target_state);
11737 : }
11738 :
11739 0 : static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
11740 : safi_t safi, uint16_t show_flags)
11741 : {
11742 0 : struct listnode *node, *nnode;
11743 0 : struct bgp *bgp;
11744 0 : int is_first = 1;
11745 0 : bool route_output = false;
11746 0 : bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11747 :
11748 0 : if (use_json)
11749 0 : vty_out(vty, "{\n");
11750 :
11751 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
11752 0 : route_output = true;
11753 0 : if (use_json) {
11754 0 : if (!is_first)
11755 0 : vty_out(vty, ",\n");
11756 : else
11757 : is_first = 0;
11758 :
11759 0 : vty_out(vty, "\"%s\":",
11760 0 : (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11761 0 : ? VRF_DEFAULT_NAME
11762 : : bgp->name);
11763 : } else {
11764 0 : vty_out(vty, "\nInstance %s:\n",
11765 0 : (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11766 0 : ? VRF_DEFAULT_NAME
11767 : : bgp->name);
11768 : }
11769 0 : bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
11770 : show_flags, RPKI_NOT_BEING_USED);
11771 : }
11772 :
11773 0 : if (use_json)
11774 0 : vty_out(vty, "}\n");
11775 0 : else if (!route_output)
11776 0 : vty_out(vty, "%% BGP instance not found\n");
11777 0 : }
11778 :
11779 : /* Header of detailed BGP route information */
11780 0 : void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
11781 : struct bgp_dest *dest, const struct prefix *p,
11782 : const struct prefix_rd *prd, afi_t afi,
11783 : safi_t safi, json_object *json)
11784 : {
11785 0 : struct bgp_path_info *pi;
11786 0 : struct peer *peer;
11787 0 : struct listnode *node, *nnode;
11788 0 : char buf1[RD_ADDRSTRLEN];
11789 0 : int count = 0;
11790 0 : int best = 0;
11791 0 : int suppress = 0;
11792 0 : int accept_own = 0;
11793 0 : int route_filter_translated_v4 = 0;
11794 0 : int route_filter_v4 = 0;
11795 0 : int route_filter_translated_v6 = 0;
11796 0 : int route_filter_v6 = 0;
11797 0 : int llgr_stale = 0;
11798 0 : int no_llgr = 0;
11799 0 : int accept_own_nexthop = 0;
11800 0 : int blackhole = 0;
11801 0 : int no_export = 0;
11802 0 : int no_advertise = 0;
11803 0 : int local_as = 0;
11804 0 : int no_peer = 0;
11805 0 : int first = 1;
11806 0 : int has_valid_label = 0;
11807 0 : mpls_label_t label = 0;
11808 0 : json_object *json_adv_to = NULL;
11809 0 : uint32_t ttl = 0;
11810 0 : uint32_t bos = 0;
11811 0 : uint32_t exp = 0;
11812 :
11813 0 : mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
11814 :
11815 0 : has_valid_label = bgp_is_valid_label(&label);
11816 :
11817 0 : if (safi == SAFI_EVPN) {
11818 0 : if (!json) {
11819 0 : vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
11820 0 : prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
11821 : : "",
11822 : prd ? ":" : "", (struct prefix_evpn *)p);
11823 : } else {
11824 0 : json_object_string_add(json, "rd",
11825 0 : prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11826 : "");
11827 0 : bgp_evpn_route2json((struct prefix_evpn *)p, json);
11828 : }
11829 : } else {
11830 0 : if (!json) {
11831 0 : vty_out(vty,
11832 : "BGP routing table entry for %s%s%pFX, version %" PRIu64
11833 : "\n",
11834 0 : ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
11835 0 : ? prefix_rd2str(prd, buf1,
11836 : sizeof(buf1))
11837 : : ""),
11838 : safi == SAFI_MPLS_VPN ? ":" : "", p,
11839 : dest->version);
11840 :
11841 : } else {
11842 0 : json_object_string_addf(json, "prefix", "%pFX", p);
11843 0 : json_object_int_add(json, "version", dest->version);
11844 :
11845 : }
11846 : }
11847 :
11848 0 : if (has_valid_label) {
11849 0 : if (json)
11850 0 : json_object_int_add(json, "localLabel", label);
11851 : else
11852 0 : vty_out(vty, "Local label: %d\n", label);
11853 : }
11854 :
11855 0 : if (!json)
11856 0 : if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
11857 0 : vty_out(vty, "not allocated\n");
11858 :
11859 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
11860 0 : struct community *picomm = NULL;
11861 :
11862 0 : picomm = bgp_attr_get_community(pi->attr);
11863 :
11864 0 : count++;
11865 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
11866 0 : best = count;
11867 0 : if (bgp_path_suppressed(pi))
11868 0 : suppress = 1;
11869 :
11870 0 : if (!picomm)
11871 0 : continue;
11872 :
11873 0 : no_advertise += community_include(
11874 : picomm, COMMUNITY_NO_ADVERTISE);
11875 0 : no_export +=
11876 0 : community_include(picomm, COMMUNITY_NO_EXPORT);
11877 0 : local_as +=
11878 0 : community_include(picomm, COMMUNITY_LOCAL_AS);
11879 0 : accept_own +=
11880 0 : community_include(picomm, COMMUNITY_ACCEPT_OWN);
11881 0 : route_filter_translated_v4 += community_include(
11882 : picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11883 0 : route_filter_translated_v6 += community_include(
11884 : picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11885 0 : route_filter_v4 += community_include(
11886 : picomm, COMMUNITY_ROUTE_FILTER_v4);
11887 0 : route_filter_v6 += community_include(
11888 : picomm, COMMUNITY_ROUTE_FILTER_v6);
11889 0 : llgr_stale +=
11890 0 : community_include(picomm, COMMUNITY_LLGR_STALE);
11891 0 : no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11892 0 : accept_own_nexthop += community_include(
11893 : picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11894 0 : blackhole +=
11895 0 : community_include(picomm, COMMUNITY_BLACKHOLE);
11896 0 : no_peer += community_include(picomm, COMMUNITY_NO_PEER);
11897 : }
11898 : }
11899 :
11900 0 : if (!json) {
11901 0 : vty_out(vty, "Paths: (%d available", count);
11902 0 : if (best) {
11903 0 : vty_out(vty, ", best #%d", best);
11904 0 : if (safi == SAFI_UNICAST) {
11905 0 : if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11906 0 : vty_out(vty, ", table %s",
11907 : VRF_DEFAULT_NAME);
11908 : else
11909 0 : vty_out(vty, ", vrf %s",
11910 : bgp->name);
11911 : }
11912 : } else
11913 0 : vty_out(vty, ", no best path");
11914 :
11915 0 : if (accept_own)
11916 0 : vty_out(vty,
11917 : ", accept own local route exported and imported in different VRF");
11918 0 : else if (route_filter_translated_v4)
11919 0 : vty_out(vty,
11920 : ", mark translated RTs for VPNv4 route filtering");
11921 0 : else if (route_filter_v4)
11922 0 : vty_out(vty,
11923 : ", attach RT as-is for VPNv4 route filtering");
11924 0 : else if (route_filter_translated_v6)
11925 0 : vty_out(vty,
11926 : ", mark translated RTs for VPNv6 route filtering");
11927 0 : else if (route_filter_v6)
11928 0 : vty_out(vty,
11929 : ", attach RT as-is for VPNv6 route filtering");
11930 0 : else if (llgr_stale)
11931 0 : vty_out(vty,
11932 : ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
11933 0 : else if (no_llgr)
11934 0 : vty_out(vty,
11935 : ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11936 0 : else if (accept_own_nexthop)
11937 0 : vty_out(vty,
11938 : ", accept local nexthop");
11939 0 : else if (blackhole)
11940 0 : vty_out(vty, ", inform peer to blackhole prefix");
11941 0 : else if (no_export)
11942 0 : vty_out(vty, ", not advertised to EBGP peer");
11943 0 : else if (no_advertise)
11944 0 : vty_out(vty, ", not advertised to any peer");
11945 0 : else if (local_as)
11946 0 : vty_out(vty, ", not advertised outside local AS");
11947 0 : else if (no_peer)
11948 0 : vty_out(vty,
11949 : ", inform EBGP peer not to advertise to their EBGP peers");
11950 :
11951 0 : if (suppress)
11952 0 : vty_out(vty,
11953 : ", Advertisements suppressed by an aggregate.");
11954 0 : vty_out(vty, ")\n");
11955 : }
11956 :
11957 : /* If we are not using addpath then we can display Advertised to and
11958 : * that will
11959 : * show what peers we advertised the bestpath to. If we are using
11960 : * addpath
11961 : * though then we must display Advertised to on a path-by-path basis. */
11962 0 : if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
11963 0 : for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
11964 0 : if (bgp_adj_out_lookup(peer, dest, 0)) {
11965 0 : if (json && !json_adv_to)
11966 0 : json_adv_to = json_object_new_object();
11967 :
11968 0 : route_vty_out_advertised_to(
11969 : vty, peer, &first,
11970 : " Advertised to non peer-group peers:\n ",
11971 : json_adv_to);
11972 : }
11973 : }
11974 :
11975 0 : if (json) {
11976 0 : if (json_adv_to) {
11977 0 : json_object_object_add(json, "advertisedTo",
11978 : json_adv_to);
11979 : }
11980 : } else {
11981 0 : if (first)
11982 0 : vty_out(vty, " Not advertised to any peer");
11983 0 : vty_out(vty, "\n");
11984 : }
11985 : }
11986 0 : }
11987 :
11988 0 : static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
11989 : struct bgp_dest *bgp_node, struct vty *vty,
11990 : struct bgp *bgp, afi_t afi, safi_t safi,
11991 : json_object *json, enum bgp_path_type pathtype,
11992 : int *display, enum rpki_states rpki_target_state)
11993 : {
11994 0 : struct bgp_path_info *pi;
11995 0 : int header = 1;
11996 0 : json_object *json_header = NULL;
11997 0 : json_object *json_paths = NULL;
11998 0 : const struct prefix *p = bgp_dest_get_prefix(bgp_node);
11999 :
12000 0 : for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
12001 0 : enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
12002 :
12003 0 : if (p->family == AF_INET || p->family == AF_INET6)
12004 0 : rpki_curr_state = hook_call(bgp_rpki_prefix_status,
12005 : pi->peer, pi->attr, p);
12006 :
12007 0 : if (rpki_target_state != RPKI_NOT_BEING_USED
12008 0 : && rpki_curr_state != rpki_target_state)
12009 0 : continue;
12010 :
12011 0 : if (json && !json_paths) {
12012 : /* Instantiate json_paths only if path is valid */
12013 0 : json_paths = json_object_new_array();
12014 0 : if (pfx_rd)
12015 0 : json_header = json_object_new_object();
12016 : else
12017 : json_header = json;
12018 : }
12019 :
12020 0 : if (header) {
12021 0 : route_vty_out_detail_header(
12022 : vty, bgp, bgp_node,
12023 : bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
12024 : safi, json_header);
12025 0 : header = 0;
12026 : }
12027 0 : (*display)++;
12028 :
12029 0 : if (pathtype == BGP_PATH_SHOW_ALL
12030 0 : || (pathtype == BGP_PATH_SHOW_BESTPATH
12031 0 : && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12032 0 : || (pathtype == BGP_PATH_SHOW_MULTIPATH
12033 0 : && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
12034 0 : || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
12035 0 : route_vty_out_detail(vty, bgp, bgp_node,
12036 : bgp_dest_get_prefix(bgp_node), pi,
12037 : AFI_IP, safi, rpki_curr_state,
12038 : json_paths);
12039 : }
12040 :
12041 0 : if (json && json_paths) {
12042 0 : json_object_object_add(json_header, "paths", json_paths);
12043 :
12044 0 : if (pfx_rd)
12045 0 : json_object_object_addf(json, json_header, "%pRD",
12046 : pfx_rd);
12047 : }
12048 0 : }
12049 :
12050 : /*
12051 : * Return rd based on safi
12052 : */
12053 0 : const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
12054 : safi_t safi)
12055 : {
12056 0 : switch (safi) {
12057 : case SAFI_MPLS_VPN:
12058 : case SAFI_ENCAP:
12059 : case SAFI_EVPN:
12060 0 : return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
12061 : case SAFI_UNSPEC:
12062 : case SAFI_UNICAST:
12063 : case SAFI_MULTICAST:
12064 : case SAFI_LABELED_UNICAST:
12065 : case SAFI_FLOWSPEC:
12066 : case SAFI_MAX:
12067 : return NULL;
12068 : }
12069 :
12070 0 : assert(!"Reached end of function when we were not expecting it");
12071 : }
12072 :
12073 : /* Display specified route of BGP table. */
12074 0 : static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
12075 : struct bgp_table *rib, const char *ip_str,
12076 : afi_t afi, safi_t safi,
12077 : enum rpki_states rpki_target_state,
12078 : struct prefix_rd *prd, int prefix_check,
12079 : enum bgp_path_type pathtype, bool use_json)
12080 : {
12081 0 : int ret;
12082 0 : int display = 0;
12083 0 : struct prefix match;
12084 0 : struct bgp_dest *dest;
12085 0 : struct bgp_dest *rm;
12086 0 : struct bgp_table *table;
12087 0 : json_object *json = NULL;
12088 0 : json_object *json_paths = NULL;
12089 :
12090 : /* Check IP address argument. */
12091 0 : ret = str2prefix(ip_str, &match);
12092 0 : if (!ret) {
12093 0 : vty_out(vty, "address is malformed\n");
12094 0 : return CMD_WARNING;
12095 : }
12096 :
12097 0 : match.family = afi2family(afi);
12098 :
12099 0 : if (use_json)
12100 0 : json = json_object_new_object();
12101 :
12102 0 : if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
12103 0 : for (dest = bgp_table_top(rib); dest;
12104 0 : dest = bgp_route_next(dest)) {
12105 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
12106 :
12107 0 : if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
12108 0 : continue;
12109 0 : table = bgp_dest_get_bgp_table_info(dest);
12110 0 : if (!table)
12111 0 : continue;
12112 :
12113 0 : rm = bgp_node_match(table, &match);
12114 0 : if (rm == NULL)
12115 0 : continue;
12116 :
12117 0 : const struct prefix *rm_p = bgp_dest_get_prefix(rm);
12118 0 : if (prefix_check
12119 0 : && rm_p->prefixlen != match.prefixlen) {
12120 0 : bgp_dest_unlock_node(rm);
12121 0 : continue;
12122 : }
12123 :
12124 0 : bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
12125 : bgp, afi, safi, json, pathtype,
12126 : &display, rpki_target_state);
12127 :
12128 0 : bgp_dest_unlock_node(rm);
12129 : }
12130 0 : } else if (safi == SAFI_EVPN) {
12131 0 : struct bgp_dest *longest_pfx;
12132 0 : bool is_exact_pfxlen_match = false;
12133 :
12134 0 : for (dest = bgp_table_top(rib); dest;
12135 0 : dest = bgp_route_next(dest)) {
12136 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
12137 :
12138 0 : if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
12139 0 : continue;
12140 0 : table = bgp_dest_get_bgp_table_info(dest);
12141 0 : if (!table)
12142 0 : continue;
12143 :
12144 0 : longest_pfx = NULL;
12145 0 : is_exact_pfxlen_match = false;
12146 : /*
12147 : * Search through all the prefixes for a match. The
12148 : * pfx's are enumerated in ascending order of pfxlens.
12149 : * So, the last pfx match is the longest match. Set
12150 : * is_exact_pfxlen_match when we get exact pfxlen match
12151 : */
12152 0 : for (rm = bgp_table_top(table); rm;
12153 0 : rm = bgp_route_next(rm)) {
12154 0 : const struct prefix *rm_p =
12155 0 : bgp_dest_get_prefix(rm);
12156 : /*
12157 : * Get prefixlen of the ip-prefix within type5
12158 : * evpn route
12159 : */
12160 0 : if (evpn_type5_prefix_match(rm_p, &match)
12161 0 : && rm->info) {
12162 0 : longest_pfx = rm;
12163 0 : int type5_pfxlen =
12164 0 : bgp_evpn_get_type5_prefixlen(
12165 : rm_p);
12166 0 : if (type5_pfxlen == match.prefixlen) {
12167 0 : is_exact_pfxlen_match = true;
12168 0 : bgp_dest_unlock_node(rm);
12169 0 : break;
12170 : }
12171 : }
12172 : }
12173 :
12174 0 : if (!longest_pfx)
12175 0 : continue;
12176 :
12177 0 : if (prefix_check && !is_exact_pfxlen_match)
12178 0 : continue;
12179 :
12180 0 : rm = longest_pfx;
12181 0 : bgp_dest_lock_node(rm);
12182 :
12183 0 : bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
12184 : bgp, afi, safi, json, pathtype,
12185 : &display, rpki_target_state);
12186 :
12187 0 : bgp_dest_unlock_node(rm);
12188 : }
12189 0 : } else if (safi == SAFI_FLOWSPEC) {
12190 0 : if (use_json)
12191 0 : json_paths = json_object_new_array();
12192 :
12193 0 : display = bgp_flowspec_display_match_per_ip(afi, rib,
12194 : &match, prefix_check,
12195 : vty,
12196 : use_json,
12197 : json_paths);
12198 0 : if (use_json) {
12199 0 : if (display)
12200 0 : json_object_object_add(json, "paths",
12201 : json_paths);
12202 : else
12203 0 : json_object_free(json_paths);
12204 : }
12205 : } else {
12206 0 : dest = bgp_node_match(rib, &match);
12207 0 : if (dest != NULL) {
12208 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
12209 0 : if (!prefix_check
12210 0 : || dest_p->prefixlen == match.prefixlen) {
12211 0 : bgp_show_path_info(NULL, dest, vty, bgp, afi,
12212 : safi, json, pathtype,
12213 : &display, rpki_target_state);
12214 : }
12215 :
12216 0 : bgp_dest_unlock_node(dest);
12217 : }
12218 : }
12219 :
12220 0 : if (use_json) {
12221 0 : vty_json(vty, json);
12222 : } else {
12223 0 : if (!display) {
12224 0 : vty_out(vty, "%% Network not in table\n");
12225 0 : return CMD_WARNING;
12226 : }
12227 : }
12228 :
12229 : return CMD_SUCCESS;
12230 : }
12231 :
12232 : /* Display specified route of Main RIB */
12233 0 : static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12234 : afi_t afi, safi_t safi, struct prefix_rd *prd,
12235 : int prefix_check, enum bgp_path_type pathtype,
12236 : enum rpki_states rpki_target_state, bool use_json)
12237 : {
12238 0 : if (!bgp) {
12239 0 : bgp = bgp_get_default();
12240 0 : if (!bgp) {
12241 0 : if (!use_json)
12242 0 : vty_out(vty, "No BGP process is configured\n");
12243 : else
12244 0 : vty_out(vty, "{}\n");
12245 0 : return CMD_WARNING;
12246 : }
12247 : }
12248 :
12249 : /* labeled-unicast routes live in the unicast table */
12250 0 : if (safi == SAFI_LABELED_UNICAST)
12251 0 : safi = SAFI_UNICAST;
12252 :
12253 0 : return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
12254 : afi, safi, rpki_target_state, prd,
12255 : prefix_check, pathtype, use_json);
12256 : }
12257 :
12258 0 : static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
12259 : struct cmd_token **argv, bool exact, afi_t afi,
12260 : safi_t safi, bool uj)
12261 : {
12262 0 : struct lcommunity *lcom;
12263 0 : struct buffer *b;
12264 0 : int i;
12265 0 : char *str;
12266 0 : int first = 0;
12267 0 : uint16_t show_flags = 0;
12268 0 : int ret;
12269 :
12270 0 : if (uj)
12271 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12272 :
12273 0 : b = buffer_new(1024);
12274 0 : for (i = 0; i < argc; i++) {
12275 0 : if (first)
12276 0 : buffer_putc(b, ' ');
12277 : else {
12278 0 : if (strmatch(argv[i]->text, "AA:BB:CC")) {
12279 0 : first = 1;
12280 0 : buffer_putstr(b, argv[i]->arg);
12281 : }
12282 : }
12283 : }
12284 0 : buffer_putc(b, '\0');
12285 :
12286 0 : str = buffer_getstr(b);
12287 0 : buffer_free(b);
12288 :
12289 0 : lcom = lcommunity_str2com(str);
12290 0 : XFREE(MTYPE_TMP, str);
12291 0 : if (!lcom) {
12292 0 : vty_out(vty, "%% Large-community malformed\n");
12293 0 : return CMD_WARNING;
12294 : }
12295 :
12296 0 : ret = bgp_show(vty, bgp, afi, safi,
12297 : (exact ? bgp_show_type_lcommunity_exact
12298 : : bgp_show_type_lcommunity),
12299 : lcom, show_flags, RPKI_NOT_BEING_USED);
12300 :
12301 0 : lcommunity_free(&lcom);
12302 0 : return ret;
12303 : }
12304 :
12305 0 : static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
12306 : const char *lcom, bool exact, afi_t afi,
12307 : safi_t safi, bool uj)
12308 : {
12309 0 : struct community_list *list;
12310 0 : uint16_t show_flags = 0;
12311 :
12312 0 : if (uj)
12313 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12314 :
12315 :
12316 0 : list = community_list_lookup(bgp_clist, lcom, 0,
12317 : LARGE_COMMUNITY_LIST_MASTER);
12318 0 : if (list == NULL) {
12319 0 : vty_out(vty, "%% %s is not a valid large-community-list name\n",
12320 : lcom);
12321 0 : return CMD_WARNING;
12322 : }
12323 :
12324 0 : return bgp_show(vty, bgp, afi, safi,
12325 : (exact ? bgp_show_type_lcommunity_list_exact
12326 : : bgp_show_type_lcommunity_list),
12327 : list, show_flags, RPKI_NOT_BEING_USED);
12328 : }
12329 :
12330 0 : DEFUN (show_ip_bgp_large_community_list,
12331 : show_ip_bgp_large_community_list_cmd,
12332 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
12333 : SHOW_STR
12334 : IP_STR
12335 : BGP_STR
12336 : BGP_INSTANCE_HELP_STR
12337 : BGP_AFI_HELP_STR
12338 : BGP_SAFI_WITH_LABEL_HELP_STR
12339 : "Display routes matching the large-community-list\n"
12340 : "large-community-list number\n"
12341 : "large-community-list name\n"
12342 : "Exact match of the large-communities\n"
12343 : JSON_STR)
12344 : {
12345 0 : afi_t afi = AFI_IP6;
12346 0 : safi_t safi = SAFI_UNICAST;
12347 0 : int idx = 0;
12348 0 : bool exact_match = 0;
12349 0 : struct bgp *bgp = NULL;
12350 0 : bool uj = use_json(argc, argv);
12351 :
12352 0 : if (uj)
12353 0 : argc--;
12354 :
12355 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12356 : &bgp, uj);
12357 0 : if (!idx)
12358 : return CMD_WARNING;
12359 :
12360 0 : argv_find(argv, argc, "large-community-list", &idx);
12361 :
12362 0 : const char *clist_number_or_name = argv[++idx]->arg;
12363 :
12364 0 : if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12365 0 : exact_match = 1;
12366 :
12367 0 : return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12368 : exact_match, afi, safi, uj);
12369 : }
12370 0 : DEFUN (show_ip_bgp_large_community,
12371 : show_ip_bgp_large_community_cmd,
12372 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
12373 : SHOW_STR
12374 : IP_STR
12375 : BGP_STR
12376 : BGP_INSTANCE_HELP_STR
12377 : BGP_AFI_HELP_STR
12378 : BGP_SAFI_WITH_LABEL_HELP_STR
12379 : "Display routes matching the large-communities\n"
12380 : "List of large-community numbers\n"
12381 : "Exact match of the large-communities\n"
12382 : JSON_STR)
12383 : {
12384 0 : afi_t afi = AFI_IP6;
12385 0 : safi_t safi = SAFI_UNICAST;
12386 0 : int idx = 0;
12387 0 : bool exact_match = 0;
12388 0 : struct bgp *bgp = NULL;
12389 0 : bool uj = use_json(argc, argv);
12390 0 : uint16_t show_flags = 0;
12391 :
12392 0 : if (uj) {
12393 0 : argc--;
12394 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12395 : }
12396 :
12397 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12398 : &bgp, uj);
12399 0 : if (!idx)
12400 : return CMD_WARNING;
12401 :
12402 0 : if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12403 0 : if (argv_find(argv, argc, "exact-match", &idx)) {
12404 0 : argc--;
12405 0 : exact_match = 1;
12406 : }
12407 0 : return bgp_show_lcommunity(vty, bgp, argc, argv,
12408 : exact_match, afi, safi, uj);
12409 : } else
12410 0 : return bgp_show(vty, bgp, afi, safi,
12411 : bgp_show_type_lcommunity_all, NULL, show_flags,
12412 : RPKI_NOT_BEING_USED);
12413 : }
12414 :
12415 : static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12416 : safi_t safi, struct json_object *json_array);
12417 : static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12418 : safi_t safi, struct json_object *json);
12419 :
12420 :
12421 0 : DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12422 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12423 : SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12424 : "Display number of prefixes for all afi/safi\n" JSON_STR)
12425 : {
12426 0 : bool uj = use_json(argc, argv);
12427 0 : struct bgp *bgp = NULL;
12428 0 : safi_t safi = SAFI_UNICAST;
12429 0 : afi_t afi = AFI_IP6;
12430 0 : int idx = 0;
12431 0 : struct json_object *json_all = NULL;
12432 0 : struct json_object *json_afi_safi = NULL;
12433 :
12434 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12435 : &bgp, false);
12436 0 : if (!idx)
12437 : return CMD_WARNING;
12438 :
12439 0 : if (uj)
12440 0 : json_all = json_object_new_object();
12441 :
12442 0 : FOREACH_AFI_SAFI (afi, safi) {
12443 : /*
12444 : * So limit output to those afi/safi pairs that
12445 : * actually have something interesting in them
12446 : */
12447 0 : if (strmatch(get_afi_safi_str(afi, safi, true),
12448 : "Unknown")) {
12449 0 : continue;
12450 : }
12451 0 : if (uj) {
12452 0 : json_afi_safi = json_object_new_array();
12453 0 : json_object_object_add(
12454 : json_all,
12455 : get_afi_safi_str(afi, safi, true),
12456 : json_afi_safi);
12457 : } else {
12458 : json_afi_safi = NULL;
12459 : }
12460 :
12461 0 : bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12462 : }
12463 :
12464 0 : if (uj)
12465 0 : vty_json(vty, json_all);
12466 :
12467 : return CMD_SUCCESS;
12468 : }
12469 :
12470 : /* BGP route print out function without JSON */
12471 0 : DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12472 : show_ip_bgp_l2vpn_evpn_statistics_cmd,
12473 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
12474 : SHOW_STR
12475 : IP_STR
12476 : BGP_STR
12477 : BGP_INSTANCE_HELP_STR
12478 : L2VPN_HELP_STR
12479 : EVPN_HELP_STR
12480 : "BGP RIB advertisement statistics\n"
12481 : JSON_STR)
12482 : {
12483 0 : afi_t afi = AFI_IP6;
12484 0 : safi_t safi = SAFI_UNICAST;
12485 0 : struct bgp *bgp = NULL;
12486 0 : int idx = 0, ret;
12487 0 : bool uj = use_json(argc, argv);
12488 0 : struct json_object *json_afi_safi = NULL, *json = NULL;
12489 :
12490 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12491 : &bgp, false);
12492 0 : if (!idx)
12493 : return CMD_WARNING;
12494 :
12495 0 : if (uj)
12496 0 : json_afi_safi = json_object_new_array();
12497 : else
12498 : json_afi_safi = NULL;
12499 :
12500 0 : ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12501 :
12502 0 : if (uj) {
12503 0 : json = json_object_new_object();
12504 0 : json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12505 : json_afi_safi);
12506 0 : vty_json(vty, json);
12507 : }
12508 : return ret;
12509 : }
12510 :
12511 : /* BGP route print out function without JSON */
12512 0 : DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12513 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12514 : " [" BGP_SAFI_WITH_LABEL_CMD_STR
12515 : "]]\
12516 : statistics [json]",
12517 : SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12518 : BGP_SAFI_WITH_LABEL_HELP_STR
12519 : "BGP RIB advertisement statistics\n" JSON_STR)
12520 : {
12521 0 : afi_t afi = AFI_IP6;
12522 0 : safi_t safi = SAFI_UNICAST;
12523 0 : struct bgp *bgp = NULL;
12524 0 : int idx = 0, ret;
12525 0 : bool uj = use_json(argc, argv);
12526 0 : struct json_object *json_afi_safi = NULL, *json = NULL;
12527 :
12528 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12529 : &bgp, false);
12530 0 : if (!idx)
12531 : return CMD_WARNING;
12532 :
12533 0 : if (uj)
12534 0 : json_afi_safi = json_object_new_array();
12535 : else
12536 : json_afi_safi = NULL;
12537 :
12538 0 : ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12539 :
12540 0 : if (uj) {
12541 0 : json = json_object_new_object();
12542 0 : json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12543 : json_afi_safi);
12544 0 : vty_json(vty, json);
12545 : }
12546 : return ret;
12547 : }
12548 :
12549 0 : DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
12550 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12551 : " [" BGP_SAFI_WITH_LABEL_CMD_STR
12552 : "]] [all$all] dampening parameters [json]",
12553 : SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12554 : BGP_SAFI_WITH_LABEL_HELP_STR
12555 : "Display the entries for all address families\n"
12556 : "Display detailed information about dampening\n"
12557 : "Display detail of configured dampening parameters\n"
12558 : JSON_STR)
12559 : {
12560 0 : afi_t afi = AFI_IP6;
12561 0 : safi_t safi = SAFI_UNICAST;
12562 0 : struct bgp *bgp = NULL;
12563 0 : int idx = 0;
12564 0 : uint16_t show_flags = 0;
12565 0 : bool uj = use_json(argc, argv);
12566 :
12567 0 : if (uj) {
12568 0 : argc--;
12569 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12570 : }
12571 :
12572 : /* [<ipv4|ipv6> [all]] */
12573 0 : if (all) {
12574 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12575 0 : if (argv_find(argv, argc, "ipv4", &idx))
12576 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12577 :
12578 0 : if (argv_find(argv, argc, "ipv6", &idx))
12579 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12580 : }
12581 :
12582 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12583 : &bgp, false);
12584 0 : if (!idx)
12585 : return CMD_WARNING;
12586 :
12587 0 : return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
12588 : }
12589 :
12590 : /* BGP route print out function */
12591 1 : DEFPY(show_ip_bgp, show_ip_bgp_cmd,
12592 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12593 : " [" BGP_SAFI_WITH_LABEL_CMD_STR
12594 : "]]\
12595 : [all$all]\
12596 : [cidr-only\
12597 : |dampening <flap-statistics|dampened-paths>\
12598 : |community [AA:NN|local-AS|no-advertise|no-export\
12599 : |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12600 : |accept-own|accept-own-nexthop|route-filter-v6\
12601 : |route-filter-v4|route-filter-translated-v6\
12602 : |route-filter-translated-v4] [exact-match]\
12603 : |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
12604 : |filter-list AS_PATH_FILTER_NAME\
12605 : |prefix-list WORD\
12606 : |access-list ACCESSLIST_NAME\
12607 : |route-map RMAP_NAME\
12608 : |rpki <invalid|valid|notfound>\
12609 : |version (1-4294967295)\
12610 : |alias ALIAS_NAME\
12611 : |A.B.C.D/M longer-prefixes\
12612 : |X:X::X:X/M longer-prefixes\
12613 : |detail-routes$detail_routes\
12614 : ] [json$uj [detail$detail_json] | wide$wide]",
12615 : SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12616 : BGP_SAFI_WITH_LABEL_HELP_STR
12617 : "Display the entries for all address families\n"
12618 : "Display only routes with non-natural netmasks\n"
12619 : "Display detailed information about dampening\n"
12620 : "Display flap statistics of routes\n"
12621 : "Display paths suppressed due to dampening\n"
12622 : "Display routes matching the communities\n" COMMUNITY_AANN_STR
12623 : "Do not send outside local AS (well-known community)\n"
12624 : "Do not advertise to any peer (well-known community)\n"
12625 : "Do not export to next AS (well-known community)\n"
12626 : "Graceful shutdown (well-known community)\n"
12627 : "Do not export to any peer (well-known community)\n"
12628 : "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12629 : "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12630 : "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12631 : "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12632 : "Should accept VPN route with local nexthop (well-known community)\n"
12633 : "RT VPNv6 route filtering (well-known community)\n"
12634 : "RT VPNv4 route filtering (well-known community)\n"
12635 : "RT translated VPNv6 route filtering (well-known community)\n"
12636 : "RT translated VPNv4 route filtering (well-known community)\n"
12637 : "Exact match of the communities\n"
12638 : "Community-list number\n"
12639 : "Community-list name\n"
12640 : "Display routes matching the community-list\n"
12641 : "Exact match of the communities\n"
12642 : "Display routes conforming to the filter-list\n"
12643 : "Regular expression access list name\n"
12644 : "Display routes conforming to the prefix-list\n"
12645 : "Prefix-list name\n"
12646 : "Display routes conforming to the access-list\n"
12647 : "Access-list name\n"
12648 : "Display routes matching the route-map\n"
12649 : "A route-map to match on\n"
12650 : "RPKI route types\n"
12651 : "A valid path as determined by rpki\n"
12652 : "A invalid path as determined by rpki\n"
12653 : "A path that has no rpki data\n"
12654 : "Display prefixes with matching version numbers\n"
12655 : "Version number and above\n"
12656 : "Display prefixes with matching BGP community alias\n"
12657 : "BGP community alias\n"
12658 : "IPv4 prefix\n"
12659 : "Display route and more specific routes\n"
12660 : "IPv6 prefix\n"
12661 : "Display route and more specific routes\n"
12662 : "Display detailed version of all routes\n"
12663 : JSON_STR
12664 : "Display detailed version of JSON output\n"
12665 : "Increase table width for longer prefixes\n")
12666 : {
12667 1 : afi_t afi = AFI_IP6;
12668 1 : safi_t safi = SAFI_UNICAST;
12669 1 : enum bgp_show_type sh_type = bgp_show_type_normal;
12670 1 : void *output_arg = NULL;
12671 1 : struct bgp *bgp = NULL;
12672 1 : int idx = 0;
12673 1 : int exact_match = 0;
12674 1 : char *community = NULL;
12675 1 : bool first = true;
12676 1 : uint16_t show_flags = 0;
12677 1 : enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
12678 1 : struct prefix p;
12679 :
12680 1 : if (uj) {
12681 1 : argc--;
12682 1 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12683 : }
12684 :
12685 1 : if (detail_json)
12686 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON_DETAIL);
12687 :
12688 1 : if (detail_routes)
12689 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
12690 :
12691 : /* [<ipv4|ipv6> [all]] */
12692 1 : if (all) {
12693 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12694 :
12695 0 : if (argv_find(argv, argc, "ipv4", &idx))
12696 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12697 :
12698 0 : if (argv_find(argv, argc, "ipv6", &idx))
12699 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12700 : }
12701 :
12702 1 : if (wide)
12703 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
12704 :
12705 1 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12706 : &bgp, uj);
12707 1 : if (!idx)
12708 : return CMD_WARNING;
12709 :
12710 1 : if (argv_find(argv, argc, "cidr-only", &idx))
12711 0 : sh_type = bgp_show_type_cidr_only;
12712 :
12713 1 : if (argv_find(argv, argc, "dampening", &idx)) {
12714 0 : if (argv_find(argv, argc, "dampened-paths", &idx))
12715 : sh_type = bgp_show_type_dampend_paths;
12716 0 : else if (argv_find(argv, argc, "flap-statistics", &idx))
12717 1 : sh_type = bgp_show_type_flap_statistics;
12718 : }
12719 :
12720 1 : if (argv_find(argv, argc, "community", &idx)) {
12721 0 : char *maybecomm = NULL;
12722 :
12723 0 : if (idx + 1 < argc) {
12724 0 : if (argv[idx + 1]->type == VARIABLE_TKN)
12725 0 : maybecomm = argv[idx + 1]->arg;
12726 : else
12727 0 : maybecomm = argv[idx + 1]->text;
12728 : }
12729 :
12730 0 : if (maybecomm && !strmatch(maybecomm, "json")
12731 0 : && !strmatch(maybecomm, "exact-match"))
12732 0 : community = maybecomm;
12733 :
12734 0 : if (argv_find(argv, argc, "exact-match", &idx))
12735 0 : exact_match = 1;
12736 :
12737 0 : if (!community)
12738 0 : sh_type = bgp_show_type_community_all;
12739 : }
12740 :
12741 1 : if (argv_find(argv, argc, "community-list", &idx)) {
12742 0 : const char *clist_number_or_name = argv[++idx]->arg;
12743 0 : struct community_list *list;
12744 :
12745 0 : if (argv_find(argv, argc, "exact-match", &idx))
12746 0 : exact_match = 1;
12747 :
12748 0 : list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12749 : COMMUNITY_LIST_MASTER);
12750 0 : if (list == NULL) {
12751 0 : vty_out(vty, "%% %s community-list not found\n",
12752 : clist_number_or_name);
12753 0 : return CMD_WARNING;
12754 : }
12755 :
12756 0 : if (exact_match)
12757 : sh_type = bgp_show_type_community_list_exact;
12758 : else
12759 0 : sh_type = bgp_show_type_community_list;
12760 : output_arg = list;
12761 : }
12762 :
12763 1 : if (argv_find(argv, argc, "filter-list", &idx)) {
12764 0 : const char *filter = argv[++idx]->arg;
12765 0 : struct as_list *as_list;
12766 :
12767 0 : as_list = as_list_lookup(filter);
12768 0 : if (as_list == NULL) {
12769 0 : vty_out(vty, "%% %s AS-path access-list not found\n",
12770 : filter);
12771 0 : return CMD_WARNING;
12772 : }
12773 :
12774 : sh_type = bgp_show_type_filter_list;
12775 : output_arg = as_list;
12776 : }
12777 :
12778 1 : if (argv_find(argv, argc, "prefix-list", &idx)) {
12779 0 : const char *prefix_list_str = argv[++idx]->arg;
12780 0 : struct prefix_list *plist;
12781 :
12782 0 : plist = prefix_list_lookup(afi, prefix_list_str);
12783 0 : if (plist == NULL) {
12784 0 : vty_out(vty, "%% %s prefix-list not found\n",
12785 : prefix_list_str);
12786 0 : return CMD_WARNING;
12787 : }
12788 :
12789 : sh_type = bgp_show_type_prefix_list;
12790 : output_arg = plist;
12791 : }
12792 :
12793 1 : if (argv_find(argv, argc, "access-list", &idx)) {
12794 0 : const char *access_list_str = argv[++idx]->arg;
12795 0 : struct access_list *alist;
12796 :
12797 0 : alist = access_list_lookup(afi, access_list_str);
12798 0 : if (!alist) {
12799 0 : vty_out(vty, "%% %s access-list not found\n",
12800 : access_list_str);
12801 0 : return CMD_WARNING;
12802 : }
12803 :
12804 : sh_type = bgp_show_type_access_list;
12805 : output_arg = alist;
12806 : }
12807 :
12808 1 : if (argv_find(argv, argc, "route-map", &idx)) {
12809 0 : const char *rmap_str = argv[++idx]->arg;
12810 0 : struct route_map *rmap;
12811 :
12812 0 : rmap = route_map_lookup_by_name(rmap_str);
12813 0 : if (!rmap) {
12814 0 : vty_out(vty, "%% %s route-map not found\n", rmap_str);
12815 0 : return CMD_WARNING;
12816 : }
12817 :
12818 : sh_type = bgp_show_type_route_map;
12819 : output_arg = rmap;
12820 : }
12821 :
12822 1 : if (argv_find(argv, argc, "rpki", &idx)) {
12823 0 : sh_type = bgp_show_type_rpki;
12824 0 : if (argv_find(argv, argc, "valid", &idx))
12825 : rpki_target_state = RPKI_VALID;
12826 0 : else if (argv_find(argv, argc, "invalid", &idx))
12827 0 : rpki_target_state = RPKI_INVALID;
12828 : }
12829 :
12830 : /* Display prefixes with matching version numbers */
12831 1 : if (argv_find(argv, argc, "version", &idx)) {
12832 0 : sh_type = bgp_show_type_prefix_version;
12833 0 : output_arg = argv[idx + 1]->arg;
12834 : }
12835 :
12836 : /* Display prefixes with matching BGP community alias */
12837 1 : if (argv_find(argv, argc, "alias", &idx)) {
12838 0 : sh_type = bgp_show_type_community_alias;
12839 0 : output_arg = argv[idx + 1]->arg;
12840 : }
12841 :
12842 : /* prefix-longer */
12843 1 : if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12844 1 : || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12845 0 : const char *prefix_str = argv[idx]->arg;
12846 :
12847 0 : if (!str2prefix(prefix_str, &p)) {
12848 0 : vty_out(vty, "%% Malformed Prefix\n");
12849 0 : return CMD_WARNING;
12850 : }
12851 :
12852 : sh_type = bgp_show_type_prefix_longer;
12853 : output_arg = &p;
12854 : }
12855 :
12856 1 : if (!all) {
12857 : /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
12858 1 : if (community)
12859 0 : return bgp_show_community(vty, bgp, community,
12860 : exact_match, afi, safi,
12861 : show_flags);
12862 : else
12863 1 : return bgp_show(vty, bgp, afi, safi, sh_type,
12864 : output_arg, show_flags,
12865 : rpki_target_state);
12866 : } else {
12867 0 : struct listnode *node;
12868 0 : struct bgp *abgp;
12869 : /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12870 : * AFI_IP6 */
12871 :
12872 0 : if (uj)
12873 0 : vty_out(vty, "{\n");
12874 :
12875 0 : if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12876 : || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12877 0 : afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12878 : ? AFI_IP
12879 0 : : AFI_IP6;
12880 0 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12881 0 : FOREACH_SAFI (safi) {
12882 0 : if (!bgp_afi_safi_peer_exists(abgp, afi,
12883 : safi))
12884 0 : continue;
12885 :
12886 0 : if (uj) {
12887 0 : if (first)
12888 : first = false;
12889 : else
12890 0 : vty_out(vty, ",\n");
12891 0 : vty_out(vty, "\"%s\":{\n",
12892 : get_afi_safi_str(afi,
12893 : safi,
12894 : true));
12895 : } else
12896 0 : vty_out(vty,
12897 : "\nFor address family: %s\n",
12898 : get_afi_safi_str(
12899 : afi, safi,
12900 : false));
12901 :
12902 0 : if (community)
12903 0 : bgp_show_community(
12904 : vty, abgp, community,
12905 : exact_match, afi, safi,
12906 : show_flags);
12907 : else
12908 0 : bgp_show(vty, abgp, afi, safi,
12909 : sh_type, output_arg,
12910 : show_flags,
12911 : rpki_target_state);
12912 0 : if (uj)
12913 0 : vty_out(vty, "}\n");
12914 : }
12915 : }
12916 : } else {
12917 : /* show <ip> bgp all: for each AFI and SAFI*/
12918 0 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12919 0 : FOREACH_AFI_SAFI (afi, safi) {
12920 0 : if (!bgp_afi_safi_peer_exists(abgp, afi,
12921 : safi))
12922 0 : continue;
12923 :
12924 0 : if (uj) {
12925 0 : if (first)
12926 : first = false;
12927 : else
12928 0 : vty_out(vty, ",\n");
12929 :
12930 0 : vty_out(vty, "\"%s\":{\n",
12931 : get_afi_safi_str(afi,
12932 : safi,
12933 : true));
12934 : } else
12935 0 : vty_out(vty,
12936 : "\nFor address family: %s\n",
12937 : get_afi_safi_str(
12938 : afi, safi,
12939 : false));
12940 :
12941 0 : if (community)
12942 0 : bgp_show_community(
12943 : vty, abgp, community,
12944 : exact_match, afi, safi,
12945 : show_flags);
12946 : else
12947 0 : bgp_show(vty, abgp, afi, safi,
12948 : sh_type, output_arg,
12949 : show_flags,
12950 : rpki_target_state);
12951 0 : if (uj)
12952 0 : vty_out(vty, "}\n");
12953 : }
12954 : }
12955 : }
12956 0 : if (uj)
12957 0 : vty_out(vty, "}\n");
12958 : }
12959 : return CMD_SUCCESS;
12960 : }
12961 :
12962 0 : DEFUN (show_ip_bgp_route,
12963 : show_ip_bgp_route_cmd,
12964 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [rpki <valid|invalid|notfound>] [json]",
12965 : SHOW_STR
12966 : IP_STR
12967 : BGP_STR
12968 : BGP_INSTANCE_HELP_STR
12969 : BGP_AFI_HELP_STR
12970 : BGP_SAFI_WITH_LABEL_HELP_STR
12971 : "Network in the BGP routing table to display\n"
12972 : "IPv4 prefix\n"
12973 : "Network in the BGP routing table to display\n"
12974 : "IPv6 prefix\n"
12975 : "Display only the bestpath\n"
12976 : "Display only multipaths\n"
12977 : "Display only paths that match the specified rpki state\n"
12978 : "A valid path as determined by rpki\n"
12979 : "A invalid path as determined by rpki\n"
12980 : "A path that has no rpki data\n"
12981 : JSON_STR)
12982 : {
12983 0 : int prefix_check = 0;
12984 :
12985 0 : afi_t afi = AFI_IP6;
12986 0 : safi_t safi = SAFI_UNICAST;
12987 0 : char *prefix = NULL;
12988 0 : struct bgp *bgp = NULL;
12989 0 : enum bgp_path_type path_type;
12990 0 : bool uj = use_json(argc, argv);
12991 :
12992 0 : int idx = 0;
12993 :
12994 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12995 : &bgp, uj);
12996 0 : if (!idx)
12997 : return CMD_WARNING;
12998 :
12999 0 : if (!bgp) {
13000 0 : vty_out(vty,
13001 : "Specified 'all' vrf's but this command currently only works per view/vrf\n");
13002 0 : return CMD_WARNING;
13003 : }
13004 :
13005 : /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
13006 0 : if (argv_find(argv, argc, "A.B.C.D", &idx)
13007 0 : || argv_find(argv, argc, "X:X::X:X", &idx))
13008 : prefix_check = 0;
13009 0 : else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
13010 0 : || argv_find(argv, argc, "X:X::X:X/M", &idx))
13011 : prefix_check = 1;
13012 :
13013 0 : if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
13014 0 : && afi != AFI_IP6) {
13015 0 : vty_out(vty,
13016 : "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
13017 0 : return CMD_WARNING;
13018 : }
13019 0 : if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
13020 0 : && afi != AFI_IP) {
13021 0 : vty_out(vty,
13022 : "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
13023 0 : return CMD_WARNING;
13024 : }
13025 :
13026 0 : prefix = argv[idx]->arg;
13027 :
13028 : /* [<bestpath|multipath>] */
13029 0 : if (argv_find(argv, argc, "bestpath", &idx))
13030 : path_type = BGP_PATH_SHOW_BESTPATH;
13031 0 : else if (argv_find(argv, argc, "multipath", &idx))
13032 : path_type = BGP_PATH_SHOW_MULTIPATH;
13033 : else
13034 0 : path_type = BGP_PATH_SHOW_ALL;
13035 :
13036 0 : return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
13037 : path_type, RPKI_NOT_BEING_USED, uj);
13038 : }
13039 :
13040 0 : DEFUN (show_ip_bgp_regexp,
13041 : show_ip_bgp_regexp_cmd,
13042 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
13043 : SHOW_STR
13044 : IP_STR
13045 : BGP_STR
13046 : BGP_INSTANCE_HELP_STR
13047 : BGP_AFI_HELP_STR
13048 : BGP_SAFI_WITH_LABEL_HELP_STR
13049 : "Display routes matching the AS path regular expression\n"
13050 : "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
13051 : JSON_STR)
13052 : {
13053 0 : afi_t afi = AFI_IP6;
13054 0 : safi_t safi = SAFI_UNICAST;
13055 0 : struct bgp *bgp = NULL;
13056 0 : bool uj = use_json(argc, argv);
13057 0 : char *regstr = NULL;
13058 :
13059 0 : int idx = 0;
13060 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13061 : &bgp, false);
13062 0 : if (!idx)
13063 : return CMD_WARNING;
13064 :
13065 : // get index of regex
13066 0 : if (argv_find(argv, argc, "REGEX", &idx))
13067 0 : regstr = argv[idx]->arg;
13068 :
13069 0 : assert(regstr);
13070 0 : return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
13071 : bgp_show_type_regexp, uj);
13072 : }
13073 :
13074 0 : DEFPY (show_ip_bgp_instance_all,
13075 : show_ip_bgp_instance_all_cmd,
13076 : "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
13077 : SHOW_STR
13078 : IP_STR
13079 : BGP_STR
13080 : BGP_INSTANCE_ALL_HELP_STR
13081 : BGP_AFI_HELP_STR
13082 : BGP_SAFI_WITH_LABEL_HELP_STR
13083 : JSON_STR
13084 : "Increase table width for longer prefixes\n")
13085 : {
13086 0 : afi_t afi = AFI_IP6;
13087 0 : safi_t safi = SAFI_UNICAST;
13088 0 : struct bgp *bgp = NULL;
13089 0 : int idx = 0;
13090 0 : uint16_t show_flags = 0;
13091 :
13092 0 : if (uj) {
13093 0 : argc--;
13094 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13095 : }
13096 :
13097 0 : if (wide)
13098 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13099 :
13100 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13101 : &bgp, uj);
13102 0 : if (!idx)
13103 : return CMD_WARNING;
13104 :
13105 0 : bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
13106 0 : return CMD_SUCCESS;
13107 : }
13108 :
13109 0 : static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
13110 : afi_t afi, safi_t safi, enum bgp_show_type type,
13111 : bool use_json)
13112 : {
13113 0 : regex_t *regex;
13114 0 : int rc;
13115 0 : uint16_t show_flags = 0;
13116 :
13117 0 : if (use_json)
13118 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13119 :
13120 0 : if (!config_bgp_aspath_validate(regstr)) {
13121 0 : vty_out(vty, "Invalid character in REGEX %s\n",
13122 : regstr);
13123 0 : return CMD_WARNING_CONFIG_FAILED;
13124 : }
13125 :
13126 0 : regex = bgp_regcomp(regstr);
13127 0 : if (!regex) {
13128 0 : vty_out(vty, "Can't compile regexp %s\n", regstr);
13129 0 : return CMD_WARNING;
13130 : }
13131 :
13132 0 : rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
13133 : RPKI_NOT_BEING_USED);
13134 0 : bgp_regex_free(regex);
13135 0 : return rc;
13136 : }
13137 :
13138 0 : static int bgp_show_community(struct vty *vty, struct bgp *bgp,
13139 : const char *comstr, int exact, afi_t afi,
13140 : safi_t safi, uint16_t show_flags)
13141 : {
13142 0 : struct community *com;
13143 0 : int ret = 0;
13144 :
13145 0 : com = community_str2com(comstr);
13146 0 : if (!com) {
13147 0 : vty_out(vty, "%% Community malformed: %s\n", comstr);
13148 0 : return CMD_WARNING;
13149 : }
13150 :
13151 0 : ret = bgp_show(vty, bgp, afi, safi,
13152 : (exact ? bgp_show_type_community_exact
13153 : : bgp_show_type_community),
13154 : com, show_flags, RPKI_NOT_BEING_USED);
13155 0 : community_free(&com);
13156 :
13157 0 : return ret;
13158 : }
13159 :
13160 : enum bgp_stats {
13161 : BGP_STATS_MAXBITLEN = 0,
13162 : BGP_STATS_RIB,
13163 : BGP_STATS_PREFIXES,
13164 : BGP_STATS_TOTPLEN,
13165 : BGP_STATS_UNAGGREGATEABLE,
13166 : BGP_STATS_MAX_AGGREGATEABLE,
13167 : BGP_STATS_AGGREGATES,
13168 : BGP_STATS_SPACE,
13169 : BGP_STATS_ASPATH_COUNT,
13170 : BGP_STATS_ASPATH_MAXHOPS,
13171 : BGP_STATS_ASPATH_TOTHOPS,
13172 : BGP_STATS_ASPATH_MAXSIZE,
13173 : BGP_STATS_ASPATH_TOTSIZE,
13174 : BGP_STATS_ASN_HIGHEST,
13175 : BGP_STATS_MAX,
13176 : };
13177 :
13178 : #define TABLE_STATS_IDX_VTY 0
13179 : #define TABLE_STATS_IDX_JSON 1
13180 :
13181 : static const char *table_stats_strs[][2] = {
13182 : [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
13183 : [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
13184 : [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
13185 : [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
13186 : "unaggregateablePrefixes"},
13187 : [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
13188 : "maximumAggregateablePrefixes"},
13189 : [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
13190 : "bgpAggregateAdvertisements"},
13191 : [BGP_STATS_SPACE] = {"Address space advertised",
13192 : "addressSpaceAdvertised"},
13193 : [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
13194 : "advertisementsWithPaths"},
13195 : [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
13196 : "longestAsPath"},
13197 : [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
13198 : "largestAsPath"},
13199 : [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
13200 : "averageAsPathLengthHops"},
13201 : [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
13202 : "averageAsPathSizeBytes"},
13203 : [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
13204 : [BGP_STATS_MAX] = {NULL, NULL}
13205 : };
13206 :
13207 : struct bgp_table_stats {
13208 : struct bgp_table *table;
13209 : unsigned long long counts[BGP_STATS_MAX];
13210 :
13211 : unsigned long long
13212 : prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13213 : 1];
13214 :
13215 : double total_space;
13216 : };
13217 :
13218 0 : static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
13219 : struct bgp_table_stats *ts, unsigned int space)
13220 : {
13221 0 : struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
13222 0 : struct bgp_path_info *pi;
13223 0 : const struct prefix *rn_p;
13224 :
13225 0 : if (!bgp_dest_has_bgp_path_info_data(dest))
13226 : return;
13227 :
13228 0 : rn_p = bgp_dest_get_prefix(dest);
13229 0 : ts->counts[BGP_STATS_PREFIXES]++;
13230 0 : ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
13231 :
13232 0 : ts->prefix_len_count[rn_p->prefixlen]++;
13233 : /* check if the prefix is included by any other announcements */
13234 0 : while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13235 0 : pdest = bgp_dest_parent_nolock(pdest);
13236 :
13237 0 : if (pdest == NULL || pdest == top) {
13238 0 : ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13239 : /* announced address space */
13240 0 : if (space)
13241 0 : ts->total_space += pow(2.0, space - rn_p->prefixlen);
13242 0 : } else if (bgp_dest_has_bgp_path_info_data(pdest))
13243 0 : ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
13244 :
13245 :
13246 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
13247 0 : ts->counts[BGP_STATS_RIB]++;
13248 :
13249 0 : if (CHECK_FLAG(pi->attr->flag,
13250 : ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
13251 0 : ts->counts[BGP_STATS_AGGREGATES]++;
13252 :
13253 : /* as-path stats */
13254 0 : if (pi->attr->aspath) {
13255 0 : unsigned int hops = aspath_count_hops(pi->attr->aspath);
13256 0 : unsigned int size = aspath_size(pi->attr->aspath);
13257 0 : as_t highest = aspath_highest(pi->attr->aspath);
13258 :
13259 0 : ts->counts[BGP_STATS_ASPATH_COUNT]++;
13260 :
13261 0 : if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13262 0 : ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13263 :
13264 0 : if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13265 0 : ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13266 :
13267 0 : ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13268 0 : ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
13269 0 : if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13270 0 : ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13271 : }
13272 : }
13273 : }
13274 :
13275 0 : static void bgp_table_stats_walker(struct thread *t)
13276 : {
13277 0 : struct bgp_dest *dest, *ndest;
13278 0 : struct bgp_dest *top;
13279 0 : struct bgp_table_stats *ts = THREAD_ARG(t);
13280 0 : unsigned int space = 0;
13281 :
13282 0 : if (!(top = bgp_table_top(ts->table)))
13283 : return;
13284 :
13285 0 : switch (ts->table->afi) {
13286 0 : case AFI_IP:
13287 0 : space = IPV4_MAX_BITLEN;
13288 0 : break;
13289 0 : case AFI_IP6:
13290 0 : space = IPV6_MAX_BITLEN;
13291 0 : break;
13292 0 : case AFI_L2VPN:
13293 0 : space = EVPN_ROUTE_PREFIXLEN;
13294 0 : break;
13295 : case AFI_UNSPEC:
13296 : case AFI_MAX:
13297 : return;
13298 : }
13299 :
13300 0 : ts->counts[BGP_STATS_MAXBITLEN] = space;
13301 :
13302 0 : for (dest = top; dest; dest = bgp_route_next(dest)) {
13303 0 : if (ts->table->safi == SAFI_MPLS_VPN
13304 : || ts->table->safi == SAFI_ENCAP
13305 0 : || ts->table->safi == SAFI_EVPN) {
13306 0 : struct bgp_table *table;
13307 :
13308 0 : table = bgp_dest_get_bgp_table_info(dest);
13309 0 : if (!table)
13310 0 : continue;
13311 :
13312 0 : top = bgp_table_top(table);
13313 0 : for (ndest = bgp_table_top(table); ndest;
13314 0 : ndest = bgp_route_next(ndest))
13315 0 : bgp_table_stats_rn(ndest, top, ts, space);
13316 : } else {
13317 0 : bgp_table_stats_rn(dest, top, ts, space);
13318 : }
13319 : }
13320 : }
13321 :
13322 0 : static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13323 : struct json_object *json_array)
13324 : {
13325 0 : struct listnode *node, *nnode;
13326 0 : struct bgp *bgp;
13327 :
13328 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13329 0 : bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13330 0 : }
13331 :
13332 0 : static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13333 : safi_t safi, struct json_object *json_array)
13334 : {
13335 0 : struct bgp_table_stats ts;
13336 0 : unsigned int i;
13337 0 : int ret = CMD_SUCCESS;
13338 0 : char temp_buf[20];
13339 0 : struct json_object *json = NULL;
13340 0 : uint32_t bitlen = 0;
13341 0 : struct json_object *json_bitlen;
13342 :
13343 0 : if (json_array)
13344 0 : json = json_object_new_object();
13345 :
13346 0 : if (!bgp->rib[afi][safi]) {
13347 0 : char warning_msg[50];
13348 :
13349 0 : snprintf(warning_msg, sizeof(warning_msg),
13350 : "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13351 : safi);
13352 :
13353 0 : if (!json)
13354 0 : vty_out(vty, "%s\n", warning_msg);
13355 : else
13356 0 : json_object_string_add(json, "warning", warning_msg);
13357 :
13358 0 : ret = CMD_WARNING;
13359 0 : goto end_table_stats;
13360 : }
13361 :
13362 0 : if (!json)
13363 0 : vty_out(vty, "BGP %s RIB statistics (%s)\n",
13364 : get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13365 : else
13366 0 : json_object_string_add(json, "instance", bgp->name_pretty);
13367 :
13368 : /* labeled-unicast routes live in the unicast table */
13369 0 : if (safi == SAFI_LABELED_UNICAST)
13370 0 : safi = SAFI_UNICAST;
13371 :
13372 0 : memset(&ts, 0, sizeof(ts));
13373 0 : ts.table = bgp->rib[afi][safi];
13374 0 : thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
13375 :
13376 0 : for (i = 0; i < BGP_STATS_MAX; i++) {
13377 0 : if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13378 0 : || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
13379 0 : continue;
13380 :
13381 0 : switch (i) {
13382 0 : case BGP_STATS_ASPATH_TOTHOPS:
13383 : case BGP_STATS_ASPATH_TOTSIZE:
13384 0 : if (!json) {
13385 0 : snprintf(
13386 : temp_buf, sizeof(temp_buf), "%12.2f",
13387 0 : ts.counts[i]
13388 0 : ? (float)ts.counts[i]
13389 0 : / (float)ts.counts
13390 0 : [BGP_STATS_ASPATH_COUNT]
13391 : : 0);
13392 0 : vty_out(vty, "%-30s: %s",
13393 : table_stats_strs[i]
13394 : [TABLE_STATS_IDX_VTY],
13395 : temp_buf);
13396 : } else {
13397 0 : json_object_double_add(
13398 : json,
13399 : table_stats_strs[i]
13400 : [TABLE_STATS_IDX_JSON],
13401 0 : ts.counts[i]
13402 0 : ? (double)ts.counts[i]
13403 0 : / (double)ts.counts
13404 0 : [BGP_STATS_ASPATH_COUNT]
13405 : : 0);
13406 : }
13407 : break;
13408 0 : case BGP_STATS_TOTPLEN:
13409 0 : if (!json) {
13410 0 : snprintf(
13411 : temp_buf, sizeof(temp_buf), "%12.2f",
13412 0 : ts.counts[i]
13413 0 : ? (float)ts.counts[i]
13414 0 : / (float)ts.counts
13415 0 : [BGP_STATS_PREFIXES]
13416 : : 0);
13417 0 : vty_out(vty, "%-30s: %s",
13418 : table_stats_strs[i]
13419 : [TABLE_STATS_IDX_VTY],
13420 : temp_buf);
13421 : } else {
13422 0 : json_object_double_add(
13423 : json,
13424 : table_stats_strs[i]
13425 : [TABLE_STATS_IDX_JSON],
13426 0 : ts.counts[i]
13427 0 : ? (double)ts.counts[i]
13428 0 : / (double)ts.counts
13429 0 : [BGP_STATS_PREFIXES]
13430 : : 0);
13431 : }
13432 : break;
13433 0 : case BGP_STATS_SPACE:
13434 0 : if (!json) {
13435 0 : snprintf(temp_buf, sizeof(temp_buf), "%12g",
13436 : ts.total_space);
13437 0 : vty_out(vty, "%-30s: %s\n",
13438 : table_stats_strs[i]
13439 : [TABLE_STATS_IDX_VTY],
13440 : temp_buf);
13441 : } else {
13442 0 : json_object_double_add(
13443 : json,
13444 : table_stats_strs[i]
13445 : [TABLE_STATS_IDX_JSON],
13446 : (double)ts.total_space);
13447 : }
13448 0 : if (afi == AFI_IP6) {
13449 0 : if (!json) {
13450 0 : snprintf(temp_buf, sizeof(temp_buf),
13451 : "%12g",
13452 0 : ts.total_space
13453 : * pow(2.0, -128 + 32));
13454 0 : vty_out(vty, "%30s: %s\n",
13455 : "/32 equivalent %s\n",
13456 : temp_buf);
13457 : } else {
13458 0 : json_object_double_add(
13459 : json, "/32equivalent",
13460 0 : (double)(ts.total_space
13461 : * pow(2.0,
13462 : -128 + 32)));
13463 : }
13464 0 : if (!json) {
13465 0 : snprintf(temp_buf, sizeof(temp_buf),
13466 : "%12g",
13467 0 : ts.total_space
13468 : * pow(2.0, -128 + 48));
13469 0 : vty_out(vty, "%30s: %s\n",
13470 : "/48 equivalent %s\n",
13471 : temp_buf);
13472 : } else {
13473 0 : json_object_double_add(
13474 : json, "/48equivalent",
13475 0 : (double)(ts.total_space
13476 : * pow(2.0,
13477 : -128 + 48)));
13478 : }
13479 : } else {
13480 0 : if (!json) {
13481 0 : snprintf(temp_buf, sizeof(temp_buf),
13482 : "%12.2f",
13483 0 : ts.total_space * 100.
13484 : * pow(2.0, -32));
13485 0 : vty_out(vty, "%30s: %s\n",
13486 : "% announced ", temp_buf);
13487 : } else {
13488 0 : json_object_double_add(
13489 : json, "%announced",
13490 0 : (double)(ts.total_space * 100.
13491 : * pow(2.0, -32)));
13492 : }
13493 0 : if (!json) {
13494 0 : snprintf(temp_buf, sizeof(temp_buf),
13495 : "%12.2f",
13496 0 : ts.total_space
13497 : * pow(2.0, -32 + 8));
13498 0 : vty_out(vty, "%30s: %s\n",
13499 : "/8 equivalent ", temp_buf);
13500 : } else {
13501 0 : json_object_double_add(
13502 : json, "/8equivalent",
13503 0 : (double)(ts.total_space
13504 : * pow(2.0, -32 + 8)));
13505 : }
13506 0 : if (!json) {
13507 0 : snprintf(temp_buf, sizeof(temp_buf),
13508 : "%12.2f",
13509 0 : ts.total_space
13510 : * pow(2.0, -32 + 24));
13511 0 : vty_out(vty, "%30s: %s\n",
13512 : "/24 equivalent ", temp_buf);
13513 : } else {
13514 0 : json_object_double_add(
13515 : json, "/24equivalent",
13516 0 : (double)(ts.total_space
13517 : * pow(2.0, -32 + 24)));
13518 : }
13519 : }
13520 : break;
13521 0 : default:
13522 0 : if (!json) {
13523 0 : snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13524 : ts.counts[i]);
13525 0 : vty_out(vty, "%-30s: %s",
13526 : table_stats_strs[i]
13527 : [TABLE_STATS_IDX_VTY],
13528 : temp_buf);
13529 : } else {
13530 0 : json_object_int_add(
13531 : json,
13532 : table_stats_strs[i]
13533 : [TABLE_STATS_IDX_JSON],
13534 0 : ts.counts[i]);
13535 : }
13536 : }
13537 0 : if (!json)
13538 0 : vty_out(vty, "\n");
13539 : }
13540 :
13541 0 : switch (afi) {
13542 : case AFI_IP:
13543 : bitlen = IPV4_MAX_BITLEN;
13544 : break;
13545 : case AFI_IP6:
13546 : bitlen = IPV6_MAX_BITLEN;
13547 : break;
13548 : case AFI_L2VPN:
13549 : bitlen = EVPN_ROUTE_PREFIXLEN;
13550 : break;
13551 : case AFI_UNSPEC:
13552 : case AFI_MAX:
13553 : break;
13554 : }
13555 :
13556 0 : if (json) {
13557 0 : json_bitlen = json_object_new_array();
13558 :
13559 0 : for (i = 0; i <= bitlen; i++) {
13560 0 : struct json_object *ind_bit = json_object_new_object();
13561 :
13562 0 : if (!ts.prefix_len_count[i])
13563 0 : continue;
13564 :
13565 0 : snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13566 0 : json_object_int_add(ind_bit, temp_buf,
13567 0 : ts.prefix_len_count[i]);
13568 0 : json_object_array_add(json_bitlen, ind_bit);
13569 : }
13570 0 : json_object_object_add(json, "prefixLength", json_bitlen);
13571 : }
13572 :
13573 0 : end_table_stats:
13574 0 : if (json)
13575 0 : json_object_array_add(json_array, json);
13576 0 : return ret;
13577 : }
13578 :
13579 0 : static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13580 : safi_t safi, struct json_object *json_array)
13581 : {
13582 0 : if (!bgp) {
13583 0 : bgp_table_stats_all(vty, afi, safi, json_array);
13584 0 : return CMD_SUCCESS;
13585 : }
13586 :
13587 0 : return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13588 : }
13589 :
13590 : enum bgp_pcounts {
13591 : PCOUNT_ADJ_IN = 0,
13592 : PCOUNT_DAMPED,
13593 : PCOUNT_REMOVED,
13594 : PCOUNT_HISTORY,
13595 : PCOUNT_STALE,
13596 : PCOUNT_VALID,
13597 : PCOUNT_ALL,
13598 : PCOUNT_COUNTED,
13599 : PCOUNT_BPATH_SELECTED,
13600 : PCOUNT_PFCNT, /* the figure we display to users */
13601 : PCOUNT_MAX,
13602 : };
13603 :
13604 : static const char *const pcount_strs[] = {
13605 : [PCOUNT_ADJ_IN] = "Adj-in",
13606 : [PCOUNT_DAMPED] = "Damped",
13607 : [PCOUNT_REMOVED] = "Removed",
13608 : [PCOUNT_HISTORY] = "History",
13609 : [PCOUNT_STALE] = "Stale",
13610 : [PCOUNT_VALID] = "Valid",
13611 : [PCOUNT_ALL] = "All RIB",
13612 : [PCOUNT_COUNTED] = "PfxCt counted",
13613 : [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
13614 : [PCOUNT_PFCNT] = "Useable",
13615 : [PCOUNT_MAX] = NULL,
13616 : };
13617 :
13618 : struct peer_pcounts {
13619 : unsigned int count[PCOUNT_MAX];
13620 : const struct peer *peer;
13621 : const struct bgp_table *table;
13622 : safi_t safi;
13623 : };
13624 :
13625 0 : static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
13626 : {
13627 0 : const struct bgp_adj_in *ain;
13628 0 : const struct bgp_path_info *pi;
13629 0 : const struct peer *peer = pc->peer;
13630 :
13631 0 : for (ain = rn->adj_in; ain; ain = ain->next)
13632 0 : if (ain->peer == peer)
13633 0 : pc->count[PCOUNT_ADJ_IN]++;
13634 :
13635 0 : for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
13636 :
13637 0 : if (pi->peer != peer)
13638 0 : continue;
13639 :
13640 0 : pc->count[PCOUNT_ALL]++;
13641 :
13642 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13643 0 : pc->count[PCOUNT_DAMPED]++;
13644 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13645 0 : pc->count[PCOUNT_HISTORY]++;
13646 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13647 0 : pc->count[PCOUNT_REMOVED]++;
13648 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13649 0 : pc->count[PCOUNT_STALE]++;
13650 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13651 0 : pc->count[PCOUNT_VALID]++;
13652 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13653 0 : pc->count[PCOUNT_PFCNT]++;
13654 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13655 0 : pc->count[PCOUNT_BPATH_SELECTED]++;
13656 :
13657 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13658 0 : pc->count[PCOUNT_COUNTED]++;
13659 0 : if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13660 0 : flog_err(
13661 : EC_LIB_DEVELOPMENT,
13662 : "Attempting to count but flags say it is unusable");
13663 : } else {
13664 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13665 0 : flog_err(
13666 : EC_LIB_DEVELOPMENT,
13667 : "Not counted but flags say we should");
13668 : }
13669 : }
13670 0 : }
13671 :
13672 0 : static void bgp_peer_count_walker(struct thread *t)
13673 : {
13674 0 : struct bgp_dest *rn, *rm;
13675 0 : const struct bgp_table *table;
13676 0 : struct peer_pcounts *pc = THREAD_ARG(t);
13677 :
13678 0 : if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13679 0 : || pc->safi == SAFI_EVPN) {
13680 : /* Special handling for 2-level routing tables. */
13681 0 : for (rn = bgp_table_top(pc->table); rn;
13682 0 : rn = bgp_route_next(rn)) {
13683 0 : table = bgp_dest_get_bgp_table_info(rn);
13684 0 : if (table != NULL)
13685 0 : for (rm = bgp_table_top(table); rm;
13686 0 : rm = bgp_route_next(rm))
13687 0 : bgp_peer_count_proc(rm, pc);
13688 : }
13689 : } else
13690 0 : for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13691 0 : bgp_peer_count_proc(rn, pc);
13692 0 : }
13693 :
13694 0 : static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
13695 : safi_t safi, bool use_json)
13696 : {
13697 0 : struct peer_pcounts pcounts = {.peer = peer};
13698 0 : unsigned int i;
13699 0 : json_object *json = NULL;
13700 0 : json_object *json_loop = NULL;
13701 :
13702 0 : if (use_json) {
13703 0 : json = json_object_new_object();
13704 0 : json_loop = json_object_new_object();
13705 : }
13706 :
13707 0 : if (!peer || !peer->bgp || !peer->afc[afi][safi]
13708 0 : || !peer->bgp->rib[afi][safi]) {
13709 0 : if (use_json) {
13710 0 : json_object_string_add(
13711 : json, "warning",
13712 : "No such neighbor or address family");
13713 0 : vty_out(vty, "%s\n", json_object_to_json_string(json));
13714 0 : json_object_free(json);
13715 0 : json_object_free(json_loop);
13716 : } else
13717 0 : vty_out(vty, "%% No such neighbor or address family\n");
13718 :
13719 0 : return CMD_WARNING;
13720 : }
13721 :
13722 0 : memset(&pcounts, 0, sizeof(pcounts));
13723 0 : pcounts.peer = peer;
13724 0 : pcounts.table = peer->bgp->rib[afi][safi];
13725 0 : pcounts.safi = safi;
13726 :
13727 : /* in-place call via thread subsystem so as to record execution time
13728 : * stats for the thread-walk (i.e. ensure this can't be blamed on
13729 : * on just vty_read()).
13730 : */
13731 0 : thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13732 :
13733 0 : if (use_json) {
13734 0 : json_object_string_add(json, "prefixCountsFor", peer->host);
13735 0 : json_object_string_add(json, "multiProtocol",
13736 : get_afi_safi_str(afi, safi, true));
13737 0 : json_object_int_add(json, "pfxCounter",
13738 0 : peer->pcount[afi][safi]);
13739 :
13740 0 : for (i = 0; i < PCOUNT_MAX; i++)
13741 0 : json_object_int_add(json_loop, pcount_strs[i],
13742 0 : pcounts.count[i]);
13743 :
13744 0 : json_object_object_add(json, "ribTableWalkCounters", json_loop);
13745 :
13746 0 : if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13747 0 : json_object_string_add(json, "pfxctDriftFor",
13748 0 : peer->host);
13749 0 : json_object_string_add(
13750 : json, "recommended",
13751 : "Please report this bug, with the above command output");
13752 : }
13753 0 : vty_json(vty, json);
13754 : } else {
13755 :
13756 0 : if (peer->hostname
13757 0 : && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
13758 0 : vty_out(vty, "Prefix counts for %s/%s, %s\n",
13759 : peer->hostname, peer->host,
13760 : get_afi_safi_str(afi, safi, false));
13761 : } else {
13762 0 : vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
13763 : get_afi_safi_str(afi, safi, false));
13764 : }
13765 :
13766 0 : vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
13767 0 : vty_out(vty, "\nCounts from RIB table walk:\n\n");
13768 :
13769 0 : for (i = 0; i < PCOUNT_MAX; i++)
13770 0 : vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13771 : pcounts.count[i]);
13772 :
13773 0 : if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13774 0 : vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13775 0 : vty_out(vty,
13776 : "Please report this bug, with the above command output\n");
13777 : }
13778 : }
13779 :
13780 : return CMD_SUCCESS;
13781 : }
13782 :
13783 0 : DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13784 : show_ip_bgp_instance_neighbor_prefix_counts_cmd,
13785 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13786 : SHOW_STR
13787 : IP_STR
13788 : BGP_STR
13789 : BGP_INSTANCE_HELP_STR
13790 : BGP_AFI_HELP_STR
13791 : BGP_SAFI_HELP_STR
13792 : "Detailed information on TCP and BGP neighbor connections\n"
13793 : "Neighbor to display information about\n"
13794 : "Neighbor to display information about\n"
13795 : "Neighbor on BGP configured interface\n"
13796 : "Display detailed prefix count information\n"
13797 : JSON_STR)
13798 : {
13799 0 : afi_t afi = AFI_IP6;
13800 0 : safi_t safi = SAFI_UNICAST;
13801 0 : struct peer *peer;
13802 0 : int idx = 0;
13803 0 : struct bgp *bgp = NULL;
13804 0 : bool uj = use_json(argc, argv);
13805 :
13806 0 : if (uj)
13807 0 : argc--;
13808 :
13809 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13810 : &bgp, uj);
13811 0 : if (!idx)
13812 : return CMD_WARNING;
13813 :
13814 0 : argv_find(argv, argc, "neighbors", &idx);
13815 0 : peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13816 0 : if (!peer)
13817 : return CMD_WARNING;
13818 :
13819 0 : return bgp_peer_counts(vty, peer, afi, safi, uj);
13820 : }
13821 :
13822 : #ifdef KEEP_OLD_VPN_COMMANDS
13823 : DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13824 : show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13825 : "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
13826 : SHOW_STR
13827 : IP_STR
13828 : BGP_STR
13829 : BGP_VPNVX_HELP_STR
13830 : "Display information about all VPNv4 NLRIs\n"
13831 : "Detailed information on TCP and BGP neighbor connections\n"
13832 : "Neighbor to display information about\n"
13833 : "Neighbor to display information about\n"
13834 : "Neighbor on BGP configured interface\n"
13835 : "Display detailed prefix count information\n"
13836 : JSON_STR)
13837 : {
13838 : int idx_peer = 6;
13839 : struct peer *peer;
13840 : bool uj = use_json(argc, argv);
13841 :
13842 : peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13843 : if (!peer)
13844 : return CMD_WARNING;
13845 :
13846 : return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
13847 : }
13848 :
13849 : DEFUN (show_ip_bgp_vpn_all_route_prefix,
13850 : show_ip_bgp_vpn_all_route_prefix_cmd,
13851 : "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
13852 : SHOW_STR
13853 : IP_STR
13854 : BGP_STR
13855 : BGP_VPNVX_HELP_STR
13856 : "Display information about all VPNv4 NLRIs\n"
13857 : "Network in the BGP routing table to display\n"
13858 : "Network in the BGP routing table to display\n"
13859 : JSON_STR)
13860 : {
13861 : int idx = 0;
13862 : char *network = NULL;
13863 : struct bgp *bgp = bgp_get_default();
13864 : if (!bgp) {
13865 : vty_out(vty, "Can't find default instance\n");
13866 : return CMD_WARNING;
13867 : }
13868 :
13869 : if (argv_find(argv, argc, "A.B.C.D", &idx))
13870 : network = argv[idx]->arg;
13871 : else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13872 : network = argv[idx]->arg;
13873 : else {
13874 : vty_out(vty, "Unable to figure out Network\n");
13875 : return CMD_WARNING;
13876 : }
13877 :
13878 : return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
13879 : BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13880 : use_json(argc, argv));
13881 : }
13882 : #endif /* KEEP_OLD_VPN_COMMANDS */
13883 :
13884 0 : DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13885 : show_bgp_l2vpn_evpn_route_prefix_cmd,
13886 : "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13887 : SHOW_STR
13888 : BGP_STR
13889 : L2VPN_HELP_STR
13890 : EVPN_HELP_STR
13891 : "Network in the BGP routing table to display\n"
13892 : "Network in the BGP routing table to display\n"
13893 : "Network in the BGP routing table to display\n"
13894 : "Network in the BGP routing table to display\n"
13895 : JSON_STR)
13896 : {
13897 0 : int idx = 0;
13898 0 : char *network = NULL;
13899 0 : int prefix_check = 0;
13900 :
13901 0 : if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13902 0 : argv_find(argv, argc, "X:X::X:X", &idx))
13903 0 : network = argv[idx]->arg;
13904 0 : else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
13905 0 : argv_find(argv, argc, "X:X::X:X/M", &idx)) {
13906 0 : network = argv[idx]->arg;
13907 0 : prefix_check = 1;
13908 : } else {
13909 0 : vty_out(vty, "Unable to figure out Network\n");
13910 0 : return CMD_WARNING;
13911 : }
13912 0 : return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13913 : prefix_check, BGP_PATH_SHOW_ALL,
13914 0 : RPKI_NOT_BEING_USED, use_json(argc, argv));
13915 : }
13916 :
13917 0 : static void show_adj_route_header(struct vty *vty, struct peer *peer,
13918 : struct bgp_table *table, int *header1,
13919 : int *header2, json_object *json,
13920 : json_object *json_scode,
13921 : json_object *json_ocode, bool wide,
13922 : bool detail)
13923 : {
13924 0 : uint64_t version = table ? table->version : 0;
13925 :
13926 0 : if (*header1) {
13927 0 : if (json) {
13928 0 : json_object_int_add(json, "bgpTableVersion", version);
13929 0 : json_object_string_addf(json, "bgpLocalRouterId",
13930 0 : "%pI4", &peer->bgp->router_id);
13931 0 : json_object_int_add(json, "defaultLocPrf",
13932 0 : peer->bgp->default_local_pref);
13933 0 : json_object_int_add(json, "localAS",
13934 0 : peer->change_local_as
13935 : ? peer->change_local_as
13936 0 : : peer->local_as);
13937 0 : json_object_object_add(json, "bgpStatusCodes",
13938 : json_scode);
13939 0 : json_object_object_add(json, "bgpOriginCodes",
13940 : json_ocode);
13941 : } else {
13942 0 : vty_out(vty,
13943 : "BGP table version is %" PRIu64
13944 : ", local router ID is %pI4, vrf id ",
13945 0 : version, &peer->bgp->router_id);
13946 0 : if (peer->bgp->vrf_id == VRF_UNKNOWN)
13947 0 : vty_out(vty, "%s", VRFID_NONE_STR);
13948 : else
13949 0 : vty_out(vty, "%u", peer->bgp->vrf_id);
13950 0 : vty_out(vty, "\n");
13951 0 : vty_out(vty, "Default local pref %u, ",
13952 0 : peer->bgp->default_local_pref);
13953 0 : vty_out(vty, "local AS %u\n",
13954 0 : peer->change_local_as ? peer->change_local_as
13955 : : peer->local_as);
13956 0 : if (!detail) {
13957 0 : vty_out(vty, BGP_SHOW_SCODE_HEADER);
13958 0 : vty_out(vty, BGP_SHOW_NCODE_HEADER);
13959 0 : vty_out(vty, BGP_SHOW_OCODE_HEADER);
13960 0 : vty_out(vty, BGP_SHOW_RPKI_HEADER);
13961 : }
13962 : }
13963 0 : *header1 = 0;
13964 : }
13965 0 : if (*header2) {
13966 0 : if (!json && !detail)
13967 0 : vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13968 : : BGP_SHOW_HEADER));
13969 0 : *header2 = 0;
13970 : }
13971 0 : }
13972 :
13973 : static void
13974 0 : show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13975 : afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13976 : const char *rmap_name, json_object *json, json_object *json_ar,
13977 : json_object *json_scode, json_object *json_ocode,
13978 : uint16_t show_flags, int *header1, int *header2, char *rd_str,
13979 : const struct prefix *match, unsigned long *output_count,
13980 : unsigned long *filtered_count)
13981 : {
13982 0 : struct bgp_adj_in *ain = NULL;
13983 0 : struct bgp_adj_out *adj = NULL;
13984 0 : struct bgp_dest *dest;
13985 0 : struct bgp *bgp;
13986 0 : struct attr attr;
13987 0 : int ret;
13988 0 : struct update_subgroup *subgrp;
13989 0 : struct peer_af *paf = NULL;
13990 0 : bool route_filtered;
13991 0 : bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
13992 0 : bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13993 0 : bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
13994 0 : bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13995 0 : || (safi == SAFI_EVPN))
13996 : ? true
13997 : : false;
13998 0 : int display = 0;
13999 0 : json_object *json_net = NULL;
14000 :
14001 0 : bgp = peer->bgp;
14002 :
14003 : /* If the user supplied a prefix, look for a matching route instead
14004 : * of walking the whole table.
14005 : */
14006 0 : if (match) {
14007 0 : dest = bgp_node_match(table, match);
14008 0 : if (!dest) {
14009 0 : if (!use_json)
14010 0 : vty_out(vty, "Network not in table\n");
14011 0 : return;
14012 : }
14013 :
14014 0 : const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14015 :
14016 0 : if (rn_p->prefixlen != match->prefixlen) {
14017 0 : if (!use_json)
14018 0 : vty_out(vty, "Network not in table\n");
14019 0 : bgp_dest_unlock_node(dest);
14020 0 : return;
14021 : }
14022 :
14023 0 : if (type == bgp_show_adj_route_received ||
14024 : type == bgp_show_adj_route_filtered) {
14025 0 : for (ain = dest->adj_in; ain; ain = ain->next) {
14026 0 : if (ain->peer == peer) {
14027 0 : attr = *ain->attr;
14028 0 : break;
14029 : }
14030 : }
14031 : /* bail out if if adj_out is empty, or
14032 : * if the prefix isn't in this peer's
14033 : * adj_in
14034 : */
14035 0 : if (!ain || ain->peer != peer) {
14036 0 : if (!use_json)
14037 0 : vty_out(vty, "Network not in table\n");
14038 0 : bgp_dest_unlock_node(dest);
14039 0 : return;
14040 : }
14041 0 : } else if (type == bgp_show_adj_route_advertised) {
14042 0 : bool peer_found = false;
14043 :
14044 0 : RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
14045 0 : SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14046 0 : if (paf->peer == peer && adj->attr) {
14047 0 : attr = *adj->attr;
14048 0 : peer_found = true;
14049 0 : break;
14050 : }
14051 : }
14052 0 : if (peer_found)
14053 : break;
14054 : }
14055 : /* bail out if if adj_out is empty, or
14056 : * if the prefix isn't in this peer's
14057 : * adj_out
14058 : */
14059 0 : if (!paf || !peer_found) {
14060 0 : if (!use_json)
14061 0 : vty_out(vty, "Network not in table\n");
14062 0 : bgp_dest_unlock_node(dest);
14063 0 : return;
14064 : }
14065 : }
14066 :
14067 0 : ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
14068 : rmap_name);
14069 :
14070 0 : if (ret != RMAP_DENY) {
14071 0 : show_adj_route_header(vty, peer, table, header1,
14072 : header2, json, json_scode,
14073 : json_ocode, wide, detail);
14074 :
14075 0 : if (use_json)
14076 0 : json_net = json_object_new_object();
14077 :
14078 0 : bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
14079 : afi, safi, json_net,
14080 : BGP_PATH_SHOW_ALL, &display,
14081 : RPKI_NOT_BEING_USED);
14082 0 : if (use_json)
14083 0 : json_object_object_addf(json_ar, json_net,
14084 : "%pFX", rn_p);
14085 0 : (*output_count)++;
14086 : } else
14087 0 : (*filtered_count)++;
14088 :
14089 0 : bgp_attr_flush(&attr);
14090 0 : bgp_dest_unlock_node(dest);
14091 0 : return;
14092 : }
14093 :
14094 :
14095 0 : subgrp = peer_subgroup(peer, afi, safi);
14096 :
14097 0 : if (type == bgp_show_adj_route_advertised && subgrp
14098 0 : && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
14099 0 : if (use_json) {
14100 0 : json_object_int_add(json, "bgpTableVersion",
14101 0 : table->version);
14102 0 : json_object_string_addf(json, "bgpLocalRouterId",
14103 : "%pI4", &bgp->router_id);
14104 0 : json_object_int_add(json, "defaultLocPrf",
14105 0 : bgp->default_local_pref);
14106 0 : json_object_int_add(json, "localAS",
14107 0 : peer->change_local_as
14108 : ? peer->change_local_as
14109 0 : : peer->local_as);
14110 0 : json_object_object_add(json, "bgpStatusCodes",
14111 : json_scode);
14112 0 : json_object_object_add(json, "bgpOriginCodes",
14113 : json_ocode);
14114 0 : json_object_string_add(
14115 : json, "bgpOriginatingDefaultNetwork",
14116 : (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
14117 : } else {
14118 0 : vty_out(vty,
14119 : "BGP table version is %" PRIu64
14120 : ", local router ID is %pI4, vrf id ",
14121 : table->version, &bgp->router_id);
14122 0 : if (bgp->vrf_id == VRF_UNKNOWN)
14123 0 : vty_out(vty, "%s", VRFID_NONE_STR);
14124 : else
14125 0 : vty_out(vty, "%u", bgp->vrf_id);
14126 0 : vty_out(vty, "\n");
14127 0 : vty_out(vty, "Default local pref %u, ",
14128 : bgp->default_local_pref);
14129 0 : vty_out(vty, "local AS %u\n",
14130 0 : peer->change_local_as ? peer->change_local_as
14131 : : peer->local_as);
14132 0 : if (!detail) {
14133 0 : vty_out(vty, BGP_SHOW_SCODE_HEADER);
14134 0 : vty_out(vty, BGP_SHOW_NCODE_HEADER);
14135 0 : vty_out(vty, BGP_SHOW_OCODE_HEADER);
14136 0 : vty_out(vty, BGP_SHOW_RPKI_HEADER);
14137 : }
14138 :
14139 0 : vty_out(vty, "Originating default network %s\n\n",
14140 : (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
14141 : }
14142 0 : (*output_count)++;
14143 0 : *header1 = 0;
14144 : }
14145 :
14146 0 : for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
14147 0 : if (type == bgp_show_adj_route_received
14148 0 : || type == bgp_show_adj_route_filtered) {
14149 0 : for (ain = dest->adj_in; ain; ain = ain->next) {
14150 0 : if (ain->peer != peer)
14151 0 : continue;
14152 :
14153 0 : show_adj_route_header(vty, peer, table, header1,
14154 : header2, json, json_scode,
14155 : json_ocode, wide, detail);
14156 :
14157 0 : if ((safi == SAFI_MPLS_VPN)
14158 : || (safi == SAFI_ENCAP)
14159 : || (safi == SAFI_EVPN)) {
14160 0 : if (use_json)
14161 0 : json_object_string_add(
14162 : json_ar, "rd", rd_str);
14163 0 : else if (show_rd && rd_str) {
14164 0 : vty_out(vty,
14165 : "Route Distinguisher: %s\n",
14166 : rd_str);
14167 0 : show_rd = false;
14168 : }
14169 : }
14170 :
14171 0 : attr = *ain->attr;
14172 0 : route_filtered = false;
14173 :
14174 : /* Filter prefix using distribute list,
14175 : * filter list or prefix list
14176 : */
14177 0 : const struct prefix *rn_p =
14178 0 : bgp_dest_get_prefix(dest);
14179 0 : if ((bgp_input_filter(peer, rn_p, &attr, afi,
14180 : safi))
14181 : == FILTER_DENY)
14182 0 : route_filtered = true;
14183 :
14184 : /* Filter prefix using route-map */
14185 0 : ret = bgp_input_modifier(peer, rn_p, &attr, afi,
14186 : safi, rmap_name, NULL,
14187 : 0, NULL);
14188 :
14189 0 : if (type == bgp_show_adj_route_filtered &&
14190 0 : !route_filtered && ret != RMAP_DENY) {
14191 0 : bgp_attr_flush(&attr);
14192 0 : continue;
14193 : }
14194 :
14195 0 : if (type == bgp_show_adj_route_received
14196 0 : && (route_filtered || ret == RMAP_DENY))
14197 0 : (*filtered_count)++;
14198 :
14199 0 : if (detail) {
14200 0 : if (use_json)
14201 0 : json_net =
14202 0 : json_object_new_object();
14203 0 : bgp_show_path_info(
14204 : NULL /* prefix_rd */, dest, vty,
14205 : bgp, afi, safi, json_net,
14206 : BGP_PATH_SHOW_ALL, &display,
14207 : RPKI_NOT_BEING_USED);
14208 0 : if (use_json)
14209 0 : json_object_object_addf(
14210 : json_ar, json_net,
14211 : "%pFX", rn_p);
14212 : } else
14213 0 : route_vty_out_tmp(vty, dest, rn_p,
14214 : &attr, safi, use_json,
14215 : json_ar, wide);
14216 0 : bgp_attr_flush(&attr);
14217 0 : (*output_count)++;
14218 : }
14219 0 : } else if (type == bgp_show_adj_route_advertised) {
14220 0 : RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
14221 0 : SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
14222 0 : if (paf->peer != peer || !adj->attr)
14223 0 : continue;
14224 :
14225 0 : show_adj_route_header(
14226 : vty, peer, table, header1,
14227 : header2, json, json_scode,
14228 : json_ocode, wide, detail);
14229 :
14230 0 : const struct prefix *rn_p =
14231 0 : bgp_dest_get_prefix(dest);
14232 :
14233 0 : attr = *adj->attr;
14234 0 : ret = bgp_output_modifier(
14235 : peer, rn_p, &attr, afi, safi,
14236 : rmap_name);
14237 :
14238 0 : if (ret != RMAP_DENY) {
14239 0 : if ((safi == SAFI_MPLS_VPN)
14240 : || (safi == SAFI_ENCAP)
14241 : || (safi == SAFI_EVPN)) {
14242 0 : if (use_json)
14243 0 : json_object_string_add(
14244 : json_ar,
14245 : "rd",
14246 : rd_str);
14247 0 : else if (show_rd
14248 0 : && rd_str) {
14249 0 : vty_out(vty,
14250 : "Route Distinguisher: %s\n",
14251 : rd_str);
14252 0 : show_rd = false;
14253 : }
14254 : }
14255 0 : if (detail) {
14256 0 : if (use_json)
14257 0 : json_net =
14258 0 : json_object_new_object();
14259 0 : bgp_show_path_info(
14260 : NULL /* prefix_rd
14261 : */
14262 : ,
14263 : dest, vty, bgp,
14264 : afi, safi,
14265 : json_net,
14266 : BGP_PATH_SHOW_ALL,
14267 : &display,
14268 : RPKI_NOT_BEING_USED);
14269 0 : if (use_json)
14270 0 : json_object_object_addf(
14271 : json_ar,
14272 : json_net,
14273 : "%pFX",
14274 : rn_p);
14275 : } else
14276 0 : route_vty_out_tmp(
14277 : vty, dest, rn_p,
14278 : &attr, safi,
14279 : use_json,
14280 : json_ar, wide);
14281 0 : (*output_count)++;
14282 : } else {
14283 0 : (*filtered_count)++;
14284 : }
14285 :
14286 0 : bgp_attr_flush(&attr);
14287 : }
14288 0 : } else if (type == bgp_show_adj_route_bestpath) {
14289 0 : struct bgp_path_info *pi;
14290 :
14291 0 : show_adj_route_header(vty, peer, table, header1,
14292 : header2, json, json_scode,
14293 : json_ocode, wide, detail);
14294 :
14295 0 : const struct prefix *rn_p = bgp_dest_get_prefix(dest);
14296 :
14297 0 : for (pi = bgp_dest_get_bgp_path_info(dest); pi;
14298 0 : pi = pi->next) {
14299 0 : if (pi->peer != peer)
14300 0 : continue;
14301 :
14302 0 : if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
14303 0 : continue;
14304 :
14305 0 : if (detail) {
14306 0 : if (use_json)
14307 0 : json_net =
14308 0 : json_object_new_object();
14309 0 : bgp_show_path_info(
14310 : NULL /* prefix_rd */, dest, vty,
14311 : bgp, afi, safi, json_net,
14312 : BGP_PATH_SHOW_BESTPATH,
14313 : &display, RPKI_NOT_BEING_USED);
14314 0 : if (use_json)
14315 0 : json_object_object_addf(
14316 : json_ar, json_net,
14317 : "%pFX", rn_p);
14318 : } else
14319 0 : route_vty_out_tmp(
14320 : vty, dest, rn_p, pi->attr, safi,
14321 : use_json, json_ar, wide);
14322 0 : (*output_count)++;
14323 : }
14324 : }
14325 : }
14326 : }
14327 :
14328 0 : static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
14329 : safi_t safi, enum bgp_show_adj_route_type type,
14330 : const char *rmap_name, const struct prefix *match,
14331 : uint16_t show_flags)
14332 : {
14333 0 : struct bgp *bgp;
14334 0 : struct bgp_table *table;
14335 0 : json_object *json = NULL;
14336 0 : json_object *json_scode = NULL;
14337 0 : json_object *json_ocode = NULL;
14338 0 : json_object *json_ar = NULL;
14339 0 : bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14340 :
14341 : /* Init BGP headers here so they're only displayed once
14342 : * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
14343 : */
14344 0 : int header1 = 1;
14345 0 : int header2 = 1;
14346 :
14347 : /*
14348 : * Initialize variables for each RD
14349 : * All prefixes under an RD is aggregated within "json_routes"
14350 : */
14351 0 : char rd_str[BUFSIZ] = {0};
14352 0 : json_object *json_routes = NULL;
14353 :
14354 :
14355 : /* For 2-tier tables, prefix counts need to be
14356 : * maintained across multiple runs of show_adj_route()
14357 : */
14358 0 : unsigned long output_count_per_rd;
14359 0 : unsigned long filtered_count_per_rd;
14360 0 : unsigned long output_count = 0;
14361 0 : unsigned long filtered_count = 0;
14362 :
14363 0 : if (use_json) {
14364 0 : json = json_object_new_object();
14365 0 : json_ar = json_object_new_object();
14366 0 : json_scode = json_object_new_object();
14367 0 : json_ocode = json_object_new_object();
14368 : #if CONFDATE > 20231208
14369 : CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
14370 : #endif
14371 0 : json_object_string_add(json_scode, "suppressed", "s");
14372 0 : json_object_string_add(json_scode, "damped", "d");
14373 0 : json_object_string_add(json_scode, "history", "h");
14374 0 : json_object_string_add(json_scode, "valid", "*");
14375 0 : json_object_string_add(json_scode, "best", ">");
14376 0 : json_object_string_add(json_scode, "multipath", "=");
14377 0 : json_object_string_add(json_scode, "internal", "i");
14378 0 : json_object_string_add(json_scode, "ribFailure", "r");
14379 0 : json_object_string_add(json_scode, "stale", "S");
14380 0 : json_object_string_add(json_scode, "removed", "R");
14381 :
14382 : #if CONFDATE > 20231208
14383 : CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
14384 : #endif
14385 0 : json_object_string_add(json_ocode, "igp", "i");
14386 0 : json_object_string_add(json_ocode, "egp", "e");
14387 0 : json_object_string_add(json_ocode, "incomplete", "?");
14388 : }
14389 :
14390 0 : if (!peer || !peer->afc[afi][safi]) {
14391 0 : if (use_json) {
14392 0 : json_object_string_add(
14393 : json, "warning",
14394 : "No such neighbor or address family");
14395 0 : vty_out(vty, "%s\n", json_object_to_json_string(json));
14396 0 : json_object_free(json);
14397 0 : json_object_free(json_ar);
14398 0 : json_object_free(json_scode);
14399 0 : json_object_free(json_ocode);
14400 : } else
14401 0 : vty_out(vty, "%% No such neighbor or address family\n");
14402 :
14403 0 : return CMD_WARNING;
14404 : }
14405 :
14406 0 : if ((type == bgp_show_adj_route_received
14407 0 : || type == bgp_show_adj_route_filtered)
14408 0 : && !CHECK_FLAG(peer->af_flags[afi][safi],
14409 : PEER_FLAG_SOFT_RECONFIG)) {
14410 0 : if (use_json) {
14411 0 : json_object_string_add(
14412 : json, "warning",
14413 : "Inbound soft reconfiguration not enabled");
14414 0 : vty_out(vty, "%s\n", json_object_to_json_string(json));
14415 0 : json_object_free(json);
14416 0 : json_object_free(json_ar);
14417 0 : json_object_free(json_scode);
14418 0 : json_object_free(json_ocode);
14419 : } else
14420 0 : vty_out(vty,
14421 : "%% Inbound soft reconfiguration not enabled\n");
14422 :
14423 0 : return CMD_WARNING;
14424 : }
14425 :
14426 0 : bgp = peer->bgp;
14427 :
14428 : /* labeled-unicast routes live in the unicast table */
14429 0 : if (safi == SAFI_LABELED_UNICAST)
14430 0 : table = bgp->rib[afi][SAFI_UNICAST];
14431 : else
14432 0 : table = bgp->rib[afi][safi];
14433 :
14434 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14435 0 : || (safi == SAFI_EVPN)) {
14436 :
14437 0 : struct bgp_dest *dest;
14438 :
14439 0 : for (dest = bgp_table_top(table); dest;
14440 0 : dest = bgp_route_next(dest)) {
14441 0 : table = bgp_dest_get_bgp_table_info(dest);
14442 0 : if (!table)
14443 0 : continue;
14444 :
14445 0 : output_count_per_rd = 0;
14446 0 : filtered_count_per_rd = 0;
14447 :
14448 0 : if (use_json)
14449 0 : json_routes = json_object_new_object();
14450 :
14451 0 : const struct prefix_rd *prd;
14452 0 : prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14453 : dest);
14454 :
14455 0 : prefix_rd2str(prd, rd_str, sizeof(rd_str));
14456 :
14457 0 : show_adj_route(
14458 : vty, peer, table, afi, safi, type, rmap_name,
14459 : json, json_routes, json_scode, json_ocode,
14460 : show_flags, &header1, &header2, rd_str, match,
14461 : &output_count_per_rd, &filtered_count_per_rd);
14462 :
14463 : /* Don't include an empty RD in the output! */
14464 0 : if (json_routes && (output_count_per_rd > 0))
14465 0 : json_object_object_add(json_ar, rd_str,
14466 : json_routes);
14467 :
14468 0 : output_count += output_count_per_rd;
14469 0 : filtered_count += filtered_count_per_rd;
14470 : }
14471 : } else
14472 0 : show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14473 : json, json_ar, json_scode, json_ocode,
14474 : show_flags, &header1, &header2, rd_str, match,
14475 : &output_count, &filtered_count);
14476 :
14477 0 : if (use_json) {
14478 0 : if (type == bgp_show_adj_route_advertised)
14479 0 : json_object_object_add(json, "advertisedRoutes",
14480 : json_ar);
14481 : else
14482 0 : json_object_object_add(json, "receivedRoutes", json_ar);
14483 0 : json_object_int_add(json, "totalPrefixCounter", output_count);
14484 0 : json_object_int_add(json, "filteredPrefixCounter",
14485 : filtered_count);
14486 :
14487 : /*
14488 : * These fields only give up ownership to `json` when `header1`
14489 : * is used (set to zero). See code in `show_adj_route` and
14490 : * `show_adj_route_header`.
14491 : */
14492 0 : if (header1 == 1) {
14493 0 : json_object_free(json_scode);
14494 0 : json_object_free(json_ocode);
14495 : }
14496 :
14497 0 : vty_json(vty, json);
14498 0 : } else if (output_count > 0) {
14499 0 : if (!match && filtered_count > 0)
14500 0 : vty_out(vty,
14501 : "\nTotal number of prefixes %ld (%ld filtered)\n",
14502 : output_count, filtered_count);
14503 : else
14504 0 : vty_out(vty, "\nTotal number of prefixes %ld\n",
14505 : output_count);
14506 : }
14507 :
14508 : return CMD_SUCCESS;
14509 : }
14510 :
14511 0 : DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14512 : show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14513 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
14514 : SHOW_STR
14515 : IP_STR
14516 : BGP_STR
14517 : BGP_INSTANCE_HELP_STR
14518 : BGP_AFI_HELP_STR
14519 : BGP_SAFI_WITH_LABEL_HELP_STR
14520 : "Detailed information on TCP and BGP neighbor connections\n"
14521 : "Neighbor to display information about\n"
14522 : "Neighbor to display information about\n"
14523 : "Neighbor on BGP configured interface\n"
14524 : "Display the routes selected by best path\n"
14525 : "Display detailed version of routes\n"
14526 : JSON_STR
14527 : "Increase table width for longer prefixes\n")
14528 : {
14529 0 : afi_t afi = AFI_IP6;
14530 0 : safi_t safi = SAFI_UNICAST;
14531 0 : char *rmap_name = NULL;
14532 0 : char *peerstr = NULL;
14533 0 : struct bgp *bgp = NULL;
14534 0 : struct peer *peer;
14535 0 : enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14536 0 : int idx = 0;
14537 0 : uint16_t show_flags = 0;
14538 :
14539 0 : if (detail)
14540 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14541 :
14542 0 : if (uj)
14543 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14544 :
14545 0 : if (wide)
14546 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
14547 :
14548 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14549 : &bgp, uj);
14550 :
14551 0 : if (!idx)
14552 : return CMD_WARNING;
14553 :
14554 0 : argv_find(argv, argc, "neighbors", &idx);
14555 0 : peerstr = argv[++idx]->arg;
14556 :
14557 0 : peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14558 0 : if (!peer)
14559 : return CMD_WARNING;
14560 :
14561 0 : return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
14562 : show_flags);
14563 : }
14564 :
14565 0 : DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
14566 : show_ip_bgp_instance_neighbor_advertised_route_cmd,
14567 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
14568 : SHOW_STR
14569 : IP_STR
14570 : BGP_STR
14571 : BGP_INSTANCE_HELP_STR
14572 : BGP_AFI_HELP_STR
14573 : BGP_SAFI_WITH_LABEL_HELP_STR
14574 : "Display the entries for all address families\n"
14575 : "Detailed information on TCP and BGP neighbor connections\n"
14576 : "Neighbor to display information about\n"
14577 : "Neighbor to display information about\n"
14578 : "Neighbor on BGP configured interface\n"
14579 : "Display the routes advertised to a BGP neighbor\n"
14580 : "Display the received routes from neighbor\n"
14581 : "Display the filtered routes received from neighbor\n"
14582 : "Route-map to modify the attributes\n"
14583 : "Name of the route map\n"
14584 : "IPv4 prefix\n"
14585 : "IPv6 prefix\n"
14586 : "Display detailed version of routes\n"
14587 : JSON_STR
14588 : "Increase table width for longer prefixes\n")
14589 : {
14590 0 : afi_t afi = AFI_IP6;
14591 0 : safi_t safi = SAFI_UNICAST;
14592 0 : char *peerstr = NULL;
14593 0 : struct bgp *bgp = NULL;
14594 0 : struct peer *peer;
14595 0 : enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
14596 0 : int idx = 0;
14597 0 : bool first = true;
14598 0 : uint16_t show_flags = 0;
14599 0 : struct listnode *node;
14600 0 : struct bgp *abgp;
14601 :
14602 0 : if (detail || prefix_str)
14603 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
14604 :
14605 0 : if (uj) {
14606 0 : argc--;
14607 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14608 : }
14609 :
14610 0 : if (all) {
14611 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14612 0 : if (argv_find(argv, argc, "ipv4", &idx))
14613 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14614 :
14615 0 : if (argv_find(argv, argc, "ipv6", &idx))
14616 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14617 : }
14618 :
14619 0 : if (wide)
14620 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
14621 :
14622 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14623 : &bgp, uj);
14624 0 : if (!idx)
14625 : return CMD_WARNING;
14626 :
14627 : /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14628 0 : argv_find(argv, argc, "neighbors", &idx);
14629 0 : peerstr = argv[++idx]->arg;
14630 :
14631 0 : peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14632 0 : if (!peer)
14633 : return CMD_WARNING;
14634 :
14635 0 : if (argv_find(argv, argc, "advertised-routes", &idx))
14636 : type = bgp_show_adj_route_advertised;
14637 0 : else if (argv_find(argv, argc, "received-routes", &idx))
14638 : type = bgp_show_adj_route_received;
14639 0 : else if (argv_find(argv, argc, "filtered-routes", &idx))
14640 0 : type = bgp_show_adj_route_filtered;
14641 :
14642 0 : if (!all)
14643 0 : return peer_adj_routes(vty, peer, afi, safi, type, route_map,
14644 : prefix_str ? prefix : NULL, show_flags);
14645 0 : if (uj)
14646 0 : vty_out(vty, "{\n");
14647 :
14648 0 : if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14649 : || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14650 0 : afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14651 0 : : AFI_IP6;
14652 0 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14653 0 : FOREACH_SAFI (safi) {
14654 0 : if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14655 0 : continue;
14656 :
14657 0 : if (uj) {
14658 0 : if (first)
14659 : first = false;
14660 : else
14661 0 : vty_out(vty, ",\n");
14662 0 : vty_out(vty, "\"%s\":",
14663 : get_afi_safi_str(afi, safi,
14664 : true));
14665 : } else
14666 0 : vty_out(vty,
14667 : "\nFor address family: %s\n",
14668 : get_afi_safi_str(afi, safi,
14669 : false));
14670 :
14671 0 : peer_adj_routes(vty, peer, afi, safi, type,
14672 : route_map, prefix, show_flags);
14673 : }
14674 : }
14675 : } else {
14676 0 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14677 0 : FOREACH_AFI_SAFI (afi, safi) {
14678 0 : if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14679 0 : continue;
14680 :
14681 0 : if (uj) {
14682 0 : if (first)
14683 : first = false;
14684 : else
14685 0 : vty_out(vty, ",\n");
14686 0 : vty_out(vty, "\"%s\":",
14687 : get_afi_safi_str(afi, safi,
14688 : true));
14689 : } else
14690 0 : vty_out(vty,
14691 : "\nFor address family: %s\n",
14692 : get_afi_safi_str(afi, safi,
14693 : false));
14694 :
14695 0 : peer_adj_routes(vty, peer, afi, safi, type,
14696 : route_map, prefix, show_flags);
14697 : }
14698 : }
14699 : }
14700 0 : if (uj)
14701 0 : vty_out(vty, "}\n");
14702 :
14703 : return CMD_SUCCESS;
14704 : }
14705 :
14706 0 : DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14707 : show_ip_bgp_neighbor_received_prefix_filter_cmd,
14708 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
14709 : SHOW_STR
14710 : IP_STR
14711 : BGP_STR
14712 : BGP_INSTANCE_HELP_STR
14713 : BGP_AF_STR
14714 : BGP_AF_STR
14715 : BGP_AF_MODIFIER_STR
14716 : "Detailed information on TCP and BGP neighbor connections\n"
14717 : "Neighbor to display information about\n"
14718 : "Neighbor to display information about\n"
14719 : "Neighbor on BGP configured interface\n"
14720 : "Display information received from a BGP neighbor\n"
14721 : "Display the prefixlist filter\n"
14722 : JSON_STR)
14723 : {
14724 0 : afi_t afi = AFI_IP6;
14725 0 : safi_t safi = SAFI_UNICAST;
14726 0 : char *peerstr = NULL;
14727 0 : char name[BUFSIZ];
14728 0 : struct peer *peer;
14729 0 : int count;
14730 0 : int idx = 0;
14731 0 : struct bgp *bgp = NULL;
14732 0 : bool uj = use_json(argc, argv);
14733 :
14734 0 : if (uj)
14735 0 : argc--;
14736 :
14737 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14738 : &bgp, uj);
14739 0 : if (!idx)
14740 : return CMD_WARNING;
14741 :
14742 : /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14743 0 : argv_find(argv, argc, "neighbors", &idx);
14744 0 : peerstr = argv[++idx]->arg;
14745 :
14746 0 : peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14747 0 : if (!peer)
14748 : return CMD_WARNING;
14749 :
14750 0 : snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
14751 0 : count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14752 0 : if (count) {
14753 0 : if (!uj)
14754 0 : vty_out(vty, "Address Family: %s\n",
14755 : get_afi_safi_str(afi, safi, false));
14756 0 : prefix_bgp_show_prefix_list(vty, afi, name, uj);
14757 : } else {
14758 0 : if (uj)
14759 0 : vty_out(vty, "{}\n");
14760 : else
14761 0 : vty_out(vty, "No functional output\n");
14762 : }
14763 :
14764 : return CMD_SUCCESS;
14765 : }
14766 :
14767 0 : static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14768 : afi_t afi, safi_t safi,
14769 : enum bgp_show_type type, bool use_json)
14770 : {
14771 0 : uint16_t show_flags = 0;
14772 :
14773 0 : if (use_json)
14774 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14775 :
14776 0 : if (!peer || !peer->afc[afi][safi]) {
14777 0 : if (use_json) {
14778 0 : json_object *json_no = NULL;
14779 0 : json_no = json_object_new_object();
14780 0 : json_object_string_add(
14781 : json_no, "warning",
14782 : "No such neighbor or address family");
14783 0 : vty_out(vty, "%s\n",
14784 : json_object_to_json_string(json_no));
14785 0 : json_object_free(json_no);
14786 : } else
14787 0 : vty_out(vty, "%% No such neighbor or address family\n");
14788 0 : return CMD_WARNING;
14789 : }
14790 :
14791 : /* labeled-unicast routes live in the unicast table */
14792 0 : if (safi == SAFI_LABELED_UNICAST)
14793 0 : safi = SAFI_UNICAST;
14794 :
14795 0 : return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14796 : RPKI_NOT_BEING_USED);
14797 : }
14798 :
14799 0 : DEFUN (show_ip_bgp_flowspec_routes_detailed,
14800 : show_ip_bgp_flowspec_routes_detailed_cmd,
14801 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14802 : SHOW_STR
14803 : IP_STR
14804 : BGP_STR
14805 : BGP_INSTANCE_HELP_STR
14806 : BGP_AFI_HELP_STR
14807 : "SAFI Flowspec\n"
14808 : "Detailed information on flowspec entries\n"
14809 : JSON_STR)
14810 : {
14811 0 : afi_t afi = AFI_IP6;
14812 0 : safi_t safi = SAFI_UNICAST;
14813 0 : struct bgp *bgp = NULL;
14814 0 : int idx = 0;
14815 0 : bool uj = use_json(argc, argv);
14816 0 : uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
14817 :
14818 0 : if (uj) {
14819 0 : argc--;
14820 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14821 : }
14822 :
14823 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14824 : &bgp, uj);
14825 0 : if (!idx)
14826 : return CMD_WARNING;
14827 :
14828 0 : return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
14829 : show_flags, RPKI_NOT_BEING_USED);
14830 : }
14831 :
14832 0 : DEFUN (show_ip_bgp_neighbor_routes,
14833 : show_ip_bgp_neighbor_routes_cmd,
14834 : "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
14835 : SHOW_STR
14836 : IP_STR
14837 : BGP_STR
14838 : BGP_INSTANCE_HELP_STR
14839 : BGP_AFI_HELP_STR
14840 : BGP_SAFI_WITH_LABEL_HELP_STR
14841 : "Detailed information on TCP and BGP neighbor connections\n"
14842 : "Neighbor to display information about\n"
14843 : "Neighbor to display information about\n"
14844 : "Neighbor on BGP configured interface\n"
14845 : "Display flap statistics of the routes learned from neighbor\n"
14846 : "Display the dampened routes received from neighbor\n"
14847 : "Display routes learned from neighbor\n"
14848 : JSON_STR)
14849 : {
14850 0 : char *peerstr = NULL;
14851 0 : struct bgp *bgp = NULL;
14852 0 : afi_t afi = AFI_IP6;
14853 0 : safi_t safi = SAFI_UNICAST;
14854 0 : struct peer *peer;
14855 0 : enum bgp_show_type sh_type = bgp_show_type_neighbor;
14856 0 : int idx = 0;
14857 0 : bool uj = use_json(argc, argv);
14858 :
14859 0 : if (uj)
14860 0 : argc--;
14861 :
14862 0 : bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14863 : &bgp, uj);
14864 0 : if (!idx)
14865 : return CMD_WARNING;
14866 :
14867 : /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14868 0 : argv_find(argv, argc, "neighbors", &idx);
14869 0 : peerstr = argv[++idx]->arg;
14870 :
14871 0 : peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14872 0 : if (!peer)
14873 : return CMD_WARNING;
14874 :
14875 0 : if (argv_find(argv, argc, "flap-statistics", &idx))
14876 : sh_type = bgp_show_type_flap_neighbor;
14877 0 : else if (argv_find(argv, argc, "dampened-routes", &idx))
14878 : sh_type = bgp_show_type_damp_neighbor;
14879 0 : else if (argv_find(argv, argc, "routes", &idx))
14880 : sh_type = bgp_show_type_neighbor;
14881 :
14882 0 : return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
14883 : }
14884 :
14885 : struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
14886 :
14887 : struct bgp_distance {
14888 : /* Distance value for the IP source prefix. */
14889 : uint8_t distance;
14890 :
14891 : /* Name of the access-list to be matched. */
14892 : char *access_list;
14893 : };
14894 :
14895 0 : DEFUN (show_bgp_afi_vpn_rd_route,
14896 : show_bgp_afi_vpn_rd_route_cmd,
14897 : "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
14898 : SHOW_STR
14899 : BGP_STR
14900 : BGP_AFI_HELP_STR
14901 : BGP_AF_MODIFIER_STR
14902 : "Display information for a route distinguisher\n"
14903 : "Route Distinguisher\n"
14904 : "All Route Distinguishers\n"
14905 : "Network in the BGP routing table to display\n"
14906 : "Network in the BGP routing table to display\n"
14907 : JSON_STR)
14908 : {
14909 0 : int ret;
14910 0 : struct prefix_rd prd;
14911 0 : afi_t afi = AFI_MAX;
14912 0 : int idx = 0;
14913 :
14914 0 : if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14915 0 : vty_out(vty, "%% Malformed Address Family\n");
14916 0 : return CMD_WARNING;
14917 : }
14918 :
14919 0 : if (!strcmp(argv[5]->arg, "all"))
14920 0 : return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14921 : SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14922 : RPKI_NOT_BEING_USED,
14923 0 : use_json(argc, argv));
14924 :
14925 0 : ret = str2prefix_rd(argv[5]->arg, &prd);
14926 0 : if (!ret) {
14927 0 : vty_out(vty, "%% Malformed Route Distinguisher\n");
14928 0 : return CMD_WARNING;
14929 : }
14930 :
14931 0 : return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
14932 : 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14933 0 : use_json(argc, argv));
14934 : }
14935 :
14936 0 : static struct bgp_distance *bgp_distance_new(void)
14937 : {
14938 0 : return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
14939 : }
14940 :
14941 0 : static void bgp_distance_free(struct bgp_distance *bdistance)
14942 : {
14943 0 : XFREE(MTYPE_BGP_DISTANCE, bdistance);
14944 : }
14945 :
14946 0 : static int bgp_distance_set(struct vty *vty, const char *distance_str,
14947 : const char *ip_str, const char *access_list_str)
14948 : {
14949 0 : int ret;
14950 0 : afi_t afi;
14951 0 : safi_t safi;
14952 0 : struct prefix p;
14953 0 : uint8_t distance;
14954 0 : struct bgp_dest *dest;
14955 0 : struct bgp_distance *bdistance;
14956 :
14957 0 : afi = bgp_node_afi(vty);
14958 0 : safi = bgp_node_safi(vty);
14959 :
14960 0 : ret = str2prefix(ip_str, &p);
14961 0 : if (ret == 0) {
14962 0 : vty_out(vty, "Malformed prefix\n");
14963 0 : return CMD_WARNING_CONFIG_FAILED;
14964 : }
14965 :
14966 0 : distance = atoi(distance_str);
14967 :
14968 : /* Get BGP distance node. */
14969 0 : dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14970 0 : bdistance = bgp_dest_get_bgp_distance_info(dest);
14971 0 : if (bdistance)
14972 0 : bgp_dest_unlock_node(dest);
14973 : else {
14974 0 : bdistance = bgp_distance_new();
14975 0 : bgp_dest_set_bgp_distance_info(dest, bdistance);
14976 : }
14977 :
14978 : /* Set distance value. */
14979 0 : bdistance->distance = distance;
14980 :
14981 : /* Reset access-list configuration. */
14982 0 : XFREE(MTYPE_AS_LIST, bdistance->access_list);
14983 0 : if (access_list_str)
14984 0 : bdistance->access_list =
14985 0 : XSTRDUP(MTYPE_AS_LIST, access_list_str);
14986 :
14987 : return CMD_SUCCESS;
14988 : }
14989 :
14990 0 : static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14991 : const char *ip_str, const char *access_list_str)
14992 : {
14993 0 : int ret;
14994 0 : afi_t afi;
14995 0 : safi_t safi;
14996 0 : struct prefix p;
14997 0 : int distance;
14998 0 : struct bgp_dest *dest;
14999 0 : struct bgp_distance *bdistance;
15000 :
15001 0 : afi = bgp_node_afi(vty);
15002 0 : safi = bgp_node_safi(vty);
15003 :
15004 0 : ret = str2prefix(ip_str, &p);
15005 0 : if (ret == 0) {
15006 0 : vty_out(vty, "Malformed prefix\n");
15007 0 : return CMD_WARNING_CONFIG_FAILED;
15008 : }
15009 :
15010 0 : dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
15011 0 : if (!dest) {
15012 0 : vty_out(vty, "Can't find specified prefix\n");
15013 0 : return CMD_WARNING_CONFIG_FAILED;
15014 : }
15015 :
15016 0 : bdistance = bgp_dest_get_bgp_distance_info(dest);
15017 0 : distance = atoi(distance_str);
15018 :
15019 0 : if (bdistance->distance != distance) {
15020 0 : vty_out(vty, "Distance does not match configured\n");
15021 0 : bgp_dest_unlock_node(dest);
15022 0 : return CMD_WARNING_CONFIG_FAILED;
15023 : }
15024 :
15025 0 : XFREE(MTYPE_AS_LIST, bdistance->access_list);
15026 0 : bgp_distance_free(bdistance);
15027 :
15028 0 : bgp_dest_set_bgp_path_info(dest, NULL);
15029 0 : bgp_dest_unlock_node(dest);
15030 0 : bgp_dest_unlock_node(dest);
15031 :
15032 0 : return CMD_SUCCESS;
15033 : }
15034 :
15035 : /* Apply BGP information to distance method. */
15036 0 : uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
15037 : afi_t afi, safi_t safi, struct bgp *bgp)
15038 : {
15039 0 : struct bgp_dest *dest;
15040 0 : struct prefix q = {0};
15041 0 : struct peer *peer;
15042 0 : struct bgp_distance *bdistance;
15043 0 : struct access_list *alist;
15044 0 : struct bgp_static *bgp_static;
15045 0 : struct bgp_path_info *bpi_ultimate;
15046 :
15047 0 : if (!bgp)
15048 : return 0;
15049 :
15050 0 : peer = pinfo->peer;
15051 :
15052 0 : if (pinfo->attr->distance)
15053 : return pinfo->attr->distance;
15054 :
15055 : /* get peer origin to calculate appropriate distance */
15056 0 : if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
15057 0 : bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
15058 0 : peer = bpi_ultimate->peer;
15059 : }
15060 :
15061 : /* Check source address.
15062 : * Note: for aggregate route, peer can have unspec af type.
15063 : */
15064 0 : if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
15065 0 : && !sockunion2hostprefix(&peer->su, &q))
15066 : return 0;
15067 :
15068 0 : dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
15069 0 : if (dest) {
15070 0 : bdistance = bgp_dest_get_bgp_distance_info(dest);
15071 0 : bgp_dest_unlock_node(dest);
15072 :
15073 0 : if (bdistance->access_list) {
15074 0 : alist = access_list_lookup(afi, bdistance->access_list);
15075 0 : if (alist
15076 0 : && access_list_apply(alist, p) == FILTER_PERMIT)
15077 0 : return bdistance->distance;
15078 : } else
15079 0 : return bdistance->distance;
15080 : }
15081 :
15082 : /* Backdoor check. */
15083 0 : dest = bgp_node_lookup(bgp->route[afi][safi], p);
15084 0 : if (dest) {
15085 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
15086 0 : bgp_dest_unlock_node(dest);
15087 :
15088 0 : if (bgp_static->backdoor) {
15089 0 : if (bgp->distance_local[afi][safi])
15090 : return bgp->distance_local[afi][safi];
15091 : else
15092 : return ZEBRA_IBGP_DISTANCE_DEFAULT;
15093 : }
15094 : }
15095 :
15096 0 : if (peer->sort == BGP_PEER_EBGP) {
15097 0 : if (bgp->distance_ebgp[afi][safi])
15098 : return bgp->distance_ebgp[afi][safi];
15099 0 : return ZEBRA_EBGP_DISTANCE_DEFAULT;
15100 0 : } else if (peer->sort == BGP_PEER_IBGP) {
15101 0 : if (bgp->distance_ibgp[afi][safi])
15102 : return bgp->distance_ibgp[afi][safi];
15103 : return ZEBRA_IBGP_DISTANCE_DEFAULT;
15104 : } else {
15105 0 : if (bgp->distance_local[afi][safi])
15106 : return bgp->distance_local[afi][safi];
15107 : return ZEBRA_IBGP_DISTANCE_DEFAULT;
15108 : }
15109 : }
15110 :
15111 : /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
15112 : * we should tell ZEBRA update the routes for a specific
15113 : * AFI/SAFI to reflect changes in RIB.
15114 : */
15115 0 : static void bgp_announce_routes_distance_update(struct bgp *bgp,
15116 : afi_t update_afi,
15117 : safi_t update_safi)
15118 : {
15119 0 : afi_t afi;
15120 0 : safi_t safi;
15121 :
15122 0 : FOREACH_AFI_SAFI (afi, safi) {
15123 0 : if (!bgp_fibupd_safi(safi))
15124 0 : continue;
15125 :
15126 0 : if (afi != update_afi && safi != update_safi)
15127 0 : continue;
15128 :
15129 0 : if (BGP_DEBUG(zebra, ZEBRA))
15130 0 : zlog_debug(
15131 : "%s: Announcing routes due to distance change afi/safi (%d/%d)",
15132 : __func__, afi, safi);
15133 0 : bgp_zebra_announce_table(bgp, afi, safi);
15134 : }
15135 0 : }
15136 :
15137 0 : DEFUN (bgp_distance,
15138 : bgp_distance_cmd,
15139 : "distance bgp (1-255) (1-255) (1-255)",
15140 : "Define an administrative distance\n"
15141 : "BGP distance\n"
15142 : "Distance for routes external to the AS\n"
15143 : "Distance for routes internal to the AS\n"
15144 : "Distance for local routes\n")
15145 : {
15146 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
15147 0 : int idx_number = 2;
15148 0 : int idx_number_2 = 3;
15149 0 : int idx_number_3 = 4;
15150 0 : int distance_ebgp = atoi(argv[idx_number]->arg);
15151 0 : int distance_ibgp = atoi(argv[idx_number_2]->arg);
15152 0 : int distance_local = atoi(argv[idx_number_3]->arg);
15153 0 : afi_t afi;
15154 0 : safi_t safi;
15155 :
15156 0 : afi = bgp_node_afi(vty);
15157 0 : safi = bgp_node_safi(vty);
15158 :
15159 0 : if (bgp->distance_ebgp[afi][safi] != distance_ebgp
15160 0 : || bgp->distance_ibgp[afi][safi] != distance_ibgp
15161 0 : || bgp->distance_local[afi][safi] != distance_local) {
15162 0 : bgp->distance_ebgp[afi][safi] = distance_ebgp;
15163 0 : bgp->distance_ibgp[afi][safi] = distance_ibgp;
15164 0 : bgp->distance_local[afi][safi] = distance_local;
15165 0 : bgp_announce_routes_distance_update(bgp, afi, safi);
15166 : }
15167 : return CMD_SUCCESS;
15168 : }
15169 :
15170 0 : DEFUN (no_bgp_distance,
15171 : no_bgp_distance_cmd,
15172 : "no distance bgp [(1-255) (1-255) (1-255)]",
15173 : NO_STR
15174 : "Define an administrative distance\n"
15175 : "BGP distance\n"
15176 : "Distance for routes external to the AS\n"
15177 : "Distance for routes internal to the AS\n"
15178 : "Distance for local routes\n")
15179 : {
15180 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
15181 0 : afi_t afi;
15182 0 : safi_t safi;
15183 :
15184 0 : afi = bgp_node_afi(vty);
15185 0 : safi = bgp_node_safi(vty);
15186 :
15187 0 : if (bgp->distance_ebgp[afi][safi] != 0
15188 0 : || bgp->distance_ibgp[afi][safi] != 0
15189 0 : || bgp->distance_local[afi][safi] != 0) {
15190 0 : bgp->distance_ebgp[afi][safi] = 0;
15191 0 : bgp->distance_ibgp[afi][safi] = 0;
15192 0 : bgp->distance_local[afi][safi] = 0;
15193 0 : bgp_announce_routes_distance_update(bgp, afi, safi);
15194 : }
15195 : return CMD_SUCCESS;
15196 : }
15197 :
15198 :
15199 0 : DEFUN (bgp_distance_source,
15200 : bgp_distance_source_cmd,
15201 : "distance (1-255) A.B.C.D/M",
15202 : "Define an administrative distance\n"
15203 : "Administrative distance\n"
15204 : "IP source prefix\n")
15205 : {
15206 0 : int idx_number = 1;
15207 0 : int idx_ipv4_prefixlen = 2;
15208 0 : bgp_distance_set(vty, argv[idx_number]->arg,
15209 0 : argv[idx_ipv4_prefixlen]->arg, NULL);
15210 0 : return CMD_SUCCESS;
15211 : }
15212 :
15213 0 : DEFUN (no_bgp_distance_source,
15214 : no_bgp_distance_source_cmd,
15215 : "no distance (1-255) A.B.C.D/M",
15216 : NO_STR
15217 : "Define an administrative distance\n"
15218 : "Administrative distance\n"
15219 : "IP source prefix\n")
15220 : {
15221 0 : int idx_number = 2;
15222 0 : int idx_ipv4_prefixlen = 3;
15223 0 : bgp_distance_unset(vty, argv[idx_number]->arg,
15224 0 : argv[idx_ipv4_prefixlen]->arg, NULL);
15225 0 : return CMD_SUCCESS;
15226 : }
15227 :
15228 0 : DEFUN (bgp_distance_source_access_list,
15229 : bgp_distance_source_access_list_cmd,
15230 : "distance (1-255) A.B.C.D/M WORD",
15231 : "Define an administrative distance\n"
15232 : "Administrative distance\n"
15233 : "IP source prefix\n"
15234 : "Access list name\n")
15235 : {
15236 0 : int idx_number = 1;
15237 0 : int idx_ipv4_prefixlen = 2;
15238 0 : int idx_word = 3;
15239 0 : bgp_distance_set(vty, argv[idx_number]->arg,
15240 0 : argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15241 0 : return CMD_SUCCESS;
15242 : }
15243 :
15244 0 : DEFUN (no_bgp_distance_source_access_list,
15245 : no_bgp_distance_source_access_list_cmd,
15246 : "no distance (1-255) A.B.C.D/M WORD",
15247 : NO_STR
15248 : "Define an administrative distance\n"
15249 : "Administrative distance\n"
15250 : "IP source prefix\n"
15251 : "Access list name\n")
15252 : {
15253 0 : int idx_number = 2;
15254 0 : int idx_ipv4_prefixlen = 3;
15255 0 : int idx_word = 4;
15256 0 : bgp_distance_unset(vty, argv[idx_number]->arg,
15257 0 : argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
15258 0 : return CMD_SUCCESS;
15259 : }
15260 :
15261 0 : DEFUN (ipv6_bgp_distance_source,
15262 : ipv6_bgp_distance_source_cmd,
15263 : "distance (1-255) X:X::X:X/M",
15264 : "Define an administrative distance\n"
15265 : "Administrative distance\n"
15266 : "IP source prefix\n")
15267 : {
15268 0 : bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
15269 0 : return CMD_SUCCESS;
15270 : }
15271 :
15272 0 : DEFUN (no_ipv6_bgp_distance_source,
15273 : no_ipv6_bgp_distance_source_cmd,
15274 : "no distance (1-255) X:X::X:X/M",
15275 : NO_STR
15276 : "Define an administrative distance\n"
15277 : "Administrative distance\n"
15278 : "IP source prefix\n")
15279 : {
15280 0 : bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
15281 0 : return CMD_SUCCESS;
15282 : }
15283 :
15284 0 : DEFUN (ipv6_bgp_distance_source_access_list,
15285 : ipv6_bgp_distance_source_access_list_cmd,
15286 : "distance (1-255) X:X::X:X/M WORD",
15287 : "Define an administrative distance\n"
15288 : "Administrative distance\n"
15289 : "IP source prefix\n"
15290 : "Access list name\n")
15291 : {
15292 0 : bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
15293 0 : return CMD_SUCCESS;
15294 : }
15295 :
15296 0 : DEFUN (no_ipv6_bgp_distance_source_access_list,
15297 : no_ipv6_bgp_distance_source_access_list_cmd,
15298 : "no distance (1-255) X:X::X:X/M WORD",
15299 : NO_STR
15300 : "Define an administrative distance\n"
15301 : "Administrative distance\n"
15302 : "IP source prefix\n"
15303 : "Access list name\n")
15304 : {
15305 0 : bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
15306 0 : return CMD_SUCCESS;
15307 : }
15308 :
15309 0 : DEFUN (bgp_damp_set,
15310 : bgp_damp_set_cmd,
15311 : "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15312 : "BGP Specific commands\n"
15313 : "Enable route-flap dampening\n"
15314 : "Half-life time for the penalty\n"
15315 : "Value to start reusing a route\n"
15316 : "Value to start suppressing a route\n"
15317 : "Maximum duration to suppress a stable route\n")
15318 : {
15319 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
15320 0 : int idx_half_life = 2;
15321 0 : int idx_reuse = 3;
15322 0 : int idx_suppress = 4;
15323 0 : int idx_max_suppress = 5;
15324 0 : int half = DEFAULT_HALF_LIFE * 60;
15325 0 : int reuse = DEFAULT_REUSE;
15326 0 : int suppress = DEFAULT_SUPPRESS;
15327 0 : int max = 4 * half;
15328 :
15329 0 : if (argc == 6) {
15330 0 : half = atoi(argv[idx_half_life]->arg) * 60;
15331 0 : reuse = atoi(argv[idx_reuse]->arg);
15332 0 : suppress = atoi(argv[idx_suppress]->arg);
15333 0 : max = atoi(argv[idx_max_suppress]->arg) * 60;
15334 0 : } else if (argc == 3) {
15335 0 : half = atoi(argv[idx_half_life]->arg) * 60;
15336 0 : max = 4 * half;
15337 : }
15338 :
15339 : /*
15340 : * These can't be 0 but our SA doesn't understand the
15341 : * way our cli is constructed
15342 : */
15343 0 : assert(reuse);
15344 0 : assert(half);
15345 0 : if (suppress < reuse) {
15346 0 : vty_out(vty,
15347 : "Suppress value cannot be less than reuse value \n");
15348 0 : return 0;
15349 : }
15350 :
15351 0 : return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
15352 : reuse, suppress, max);
15353 : }
15354 :
15355 0 : DEFUN (bgp_damp_unset,
15356 : bgp_damp_unset_cmd,
15357 : "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
15358 : NO_STR
15359 : "BGP Specific commands\n"
15360 : "Enable route-flap dampening\n"
15361 : "Half-life time for the penalty\n"
15362 : "Value to start reusing a route\n"
15363 : "Value to start suppressing a route\n"
15364 : "Maximum duration to suppress a stable route\n")
15365 : {
15366 0 : VTY_DECLVAR_CONTEXT(bgp, bgp);
15367 0 : return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
15368 : }
15369 :
15370 : /* Display specified route of BGP table. */
15371 0 : static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
15372 : const char *ip_str, afi_t afi, safi_t safi,
15373 : struct prefix_rd *prd, int prefix_check)
15374 : {
15375 0 : int ret;
15376 0 : struct prefix match;
15377 0 : struct bgp_dest *dest;
15378 0 : struct bgp_dest *rm;
15379 0 : struct bgp_path_info *pi;
15380 0 : struct bgp_path_info *pi_temp;
15381 0 : struct bgp *bgp;
15382 0 : struct bgp_table *table;
15383 :
15384 : /* BGP structure lookup. */
15385 0 : if (view_name) {
15386 0 : bgp = bgp_lookup_by_name(view_name);
15387 0 : if (bgp == NULL) {
15388 0 : vty_out(vty, "%% Can't find BGP instance %s\n",
15389 : view_name);
15390 0 : return CMD_WARNING;
15391 : }
15392 : } else {
15393 0 : bgp = bgp_get_default();
15394 0 : if (bgp == NULL) {
15395 0 : vty_out(vty, "%% No BGP process is configured\n");
15396 0 : return CMD_WARNING;
15397 : }
15398 : }
15399 :
15400 : /* Check IP address argument. */
15401 0 : ret = str2prefix(ip_str, &match);
15402 0 : if (!ret) {
15403 0 : vty_out(vty, "%% address is malformed\n");
15404 0 : return CMD_WARNING;
15405 : }
15406 :
15407 0 : match.family = afi2family(afi);
15408 :
15409 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15410 0 : || (safi == SAFI_EVPN)) {
15411 0 : for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15412 0 : dest = bgp_route_next(dest)) {
15413 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
15414 :
15415 0 : if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
15416 0 : continue;
15417 0 : table = bgp_dest_get_bgp_table_info(dest);
15418 0 : if (!table)
15419 0 : continue;
15420 0 : rm = bgp_node_match(table, &match);
15421 0 : if (rm == NULL)
15422 0 : continue;
15423 :
15424 0 : const struct prefix *rm_p = bgp_dest_get_prefix(dest);
15425 :
15426 0 : if (!prefix_check
15427 0 : || rm_p->prefixlen == match.prefixlen) {
15428 0 : pi = bgp_dest_get_bgp_path_info(rm);
15429 0 : while (pi) {
15430 0 : if (pi->extra && pi->extra->damp_info) {
15431 0 : pi_temp = pi->next;
15432 0 : bgp_damp_info_free(
15433 : pi->extra->damp_info,
15434 : 1, afi, safi);
15435 0 : pi = pi_temp;
15436 : } else
15437 0 : pi = pi->next;
15438 : }
15439 : }
15440 :
15441 0 : bgp_dest_unlock_node(rm);
15442 : }
15443 : } else {
15444 0 : dest = bgp_node_match(bgp->rib[afi][safi], &match);
15445 0 : if (dest != NULL) {
15446 0 : const struct prefix *dest_p = bgp_dest_get_prefix(dest);
15447 :
15448 0 : if (!prefix_check
15449 0 : || dest_p->prefixlen == match.prefixlen) {
15450 0 : pi = bgp_dest_get_bgp_path_info(dest);
15451 0 : while (pi) {
15452 0 : if (pi->extra && pi->extra->damp_info) {
15453 0 : pi_temp = pi->next;
15454 0 : bgp_damp_info_free(
15455 : pi->extra->damp_info,
15456 : 1, afi, safi);
15457 0 : pi = pi_temp;
15458 : } else
15459 0 : pi = pi->next;
15460 : }
15461 : }
15462 :
15463 0 : bgp_dest_unlock_node(dest);
15464 : }
15465 : }
15466 :
15467 : return CMD_SUCCESS;
15468 : }
15469 :
15470 0 : DEFUN (clear_ip_bgp_dampening,
15471 : clear_ip_bgp_dampening_cmd,
15472 : "clear ip bgp dampening",
15473 : CLEAR_STR
15474 : IP_STR
15475 : BGP_STR
15476 : "Clear route flap dampening information\n")
15477 : {
15478 0 : bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
15479 0 : return CMD_SUCCESS;
15480 : }
15481 :
15482 0 : DEFUN (clear_ip_bgp_dampening_prefix,
15483 : clear_ip_bgp_dampening_prefix_cmd,
15484 : "clear ip bgp dampening A.B.C.D/M",
15485 : CLEAR_STR
15486 : IP_STR
15487 : BGP_STR
15488 : "Clear route flap dampening information\n"
15489 : "IPv4 prefix\n")
15490 : {
15491 0 : int idx_ipv4_prefixlen = 4;
15492 0 : return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15493 : AFI_IP, SAFI_UNICAST, NULL, 1);
15494 : }
15495 :
15496 0 : DEFUN (clear_ip_bgp_dampening_address,
15497 : clear_ip_bgp_dampening_address_cmd,
15498 : "clear ip bgp dampening A.B.C.D",
15499 : CLEAR_STR
15500 : IP_STR
15501 : BGP_STR
15502 : "Clear route flap dampening information\n"
15503 : "Network to clear damping information\n")
15504 : {
15505 0 : int idx_ipv4 = 4;
15506 0 : return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15507 : SAFI_UNICAST, NULL, 0);
15508 : }
15509 :
15510 0 : DEFUN (clear_ip_bgp_dampening_address_mask,
15511 : clear_ip_bgp_dampening_address_mask_cmd,
15512 : "clear ip bgp dampening A.B.C.D A.B.C.D",
15513 : CLEAR_STR
15514 : IP_STR
15515 : BGP_STR
15516 : "Clear route flap dampening information\n"
15517 : "Network to clear damping information\n"
15518 : "Network mask\n")
15519 : {
15520 0 : int idx_ipv4 = 4;
15521 0 : int idx_ipv4_2 = 5;
15522 0 : int ret;
15523 0 : char prefix_str[BUFSIZ];
15524 :
15525 0 : ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
15526 : prefix_str, sizeof(prefix_str));
15527 0 : if (!ret) {
15528 0 : vty_out(vty, "%% Inconsistent address and mask\n");
15529 0 : return CMD_WARNING;
15530 : }
15531 :
15532 0 : return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15533 : NULL, 0);
15534 : }
15535 :
15536 0 : static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
15537 : {
15538 0 : struct vty *vty = arg;
15539 0 : struct peer *peer = bucket->data;
15540 :
15541 0 : vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
15542 0 : }
15543 :
15544 0 : DEFUN (show_bgp_listeners,
15545 : show_bgp_listeners_cmd,
15546 : "show bgp listeners",
15547 : SHOW_STR
15548 : BGP_STR
15549 : "Display Listen Sockets and who created them\n")
15550 : {
15551 0 : bgp_dump_listener_info(vty);
15552 :
15553 0 : return CMD_SUCCESS;
15554 : }
15555 :
15556 0 : DEFUN (show_bgp_peerhash,
15557 : show_bgp_peerhash_cmd,
15558 : "show bgp peerhash",
15559 : SHOW_STR
15560 : BGP_STR
15561 : "Display information about the BGP peerhash\n")
15562 : {
15563 0 : struct list *instances = bm->bgp;
15564 0 : struct listnode *node;
15565 0 : struct bgp *bgp;
15566 :
15567 0 : for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15568 0 : vty_out(vty, "BGP: %s\n", bgp->name);
15569 0 : hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15570 : vty);
15571 : }
15572 :
15573 0 : return CMD_SUCCESS;
15574 : }
15575 :
15576 : /* also used for encap safi */
15577 0 : static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15578 : afi_t afi, safi_t safi)
15579 : {
15580 0 : struct bgp_dest *pdest;
15581 0 : struct bgp_dest *dest;
15582 0 : struct bgp_table *table;
15583 0 : const struct prefix *p;
15584 0 : const struct prefix_rd *prd;
15585 0 : struct bgp_static *bgp_static;
15586 0 : mpls_label_t label;
15587 :
15588 : /* Network configuration. */
15589 0 : for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15590 0 : pdest = bgp_route_next(pdest)) {
15591 0 : table = bgp_dest_get_bgp_table_info(pdest);
15592 0 : if (!table)
15593 0 : continue;
15594 :
15595 0 : for (dest = bgp_table_top(table); dest;
15596 0 : dest = bgp_route_next(dest)) {
15597 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
15598 0 : if (bgp_static == NULL)
15599 0 : continue;
15600 :
15601 0 : p = bgp_dest_get_prefix(dest);
15602 0 : prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15603 : pdest);
15604 :
15605 : /* "network" configuration display. */
15606 0 : label = decode_label(&bgp_static->label);
15607 :
15608 0 : vty_out(vty, " network %pFX rd %pRD", p, prd);
15609 0 : if (safi == SAFI_MPLS_VPN)
15610 0 : vty_out(vty, " label %u", label);
15611 :
15612 0 : if (bgp_static->rmap.name)
15613 0 : vty_out(vty, " route-map %s",
15614 : bgp_static->rmap.name);
15615 :
15616 0 : if (bgp_static->backdoor)
15617 0 : vty_out(vty, " backdoor");
15618 :
15619 0 : vty_out(vty, "\n");
15620 : }
15621 : }
15622 0 : }
15623 :
15624 0 : static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15625 : afi_t afi, safi_t safi)
15626 : {
15627 0 : struct bgp_dest *pdest;
15628 0 : struct bgp_dest *dest;
15629 0 : struct bgp_table *table;
15630 0 : const struct prefix *p;
15631 0 : const struct prefix_rd *prd;
15632 0 : struct bgp_static *bgp_static;
15633 0 : char buf[PREFIX_STRLEN * 2];
15634 0 : char buf2[SU_ADDRSTRLEN];
15635 0 : char esi_buf[ESI_STR_LEN];
15636 :
15637 : /* Network configuration. */
15638 0 : for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15639 0 : pdest = bgp_route_next(pdest)) {
15640 0 : table = bgp_dest_get_bgp_table_info(pdest);
15641 0 : if (!table)
15642 0 : continue;
15643 :
15644 0 : for (dest = bgp_table_top(table); dest;
15645 0 : dest = bgp_route_next(dest)) {
15646 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
15647 0 : if (bgp_static == NULL)
15648 0 : continue;
15649 :
15650 0 : char *macrouter = NULL;
15651 :
15652 0 : if (bgp_static->router_mac)
15653 0 : macrouter = prefix_mac2str(
15654 : bgp_static->router_mac, NULL, 0);
15655 0 : if (bgp_static->eth_s_id)
15656 0 : esi_to_str(bgp_static->eth_s_id,
15657 : esi_buf, sizeof(esi_buf));
15658 0 : p = bgp_dest_get_prefix(dest);
15659 0 : prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
15660 :
15661 : /* "network" configuration display. */
15662 0 : if (p->u.prefix_evpn.route_type == 5) {
15663 0 : char local_buf[PREFIX_STRLEN];
15664 :
15665 0 : uint8_t family = is_evpn_prefix_ipaddr_v4((
15666 : struct prefix_evpn *)p)
15667 : ? AF_INET
15668 : : AF_INET6;
15669 0 : inet_ntop(family,
15670 0 : &p->u.prefix_evpn.prefix_addr.ip.ip
15671 : .addr,
15672 : local_buf, sizeof(local_buf));
15673 0 : snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15674 : p->u.prefix_evpn.prefix_addr
15675 0 : .ip_prefix_length);
15676 : } else {
15677 0 : prefix2str(p, buf, sizeof(buf));
15678 : }
15679 :
15680 0 : if (bgp_static->gatewayIp.family == AF_INET
15681 0 : || bgp_static->gatewayIp.family == AF_INET6)
15682 0 : inet_ntop(bgp_static->gatewayIp.family,
15683 0 : &bgp_static->gatewayIp.u.prefix, buf2,
15684 : sizeof(buf2));
15685 0 : vty_out(vty,
15686 : " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15687 0 : buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
15688 : decode_label(&bgp_static->label), esi_buf, buf2,
15689 : macrouter);
15690 :
15691 0 : XFREE(MTYPE_TMP, macrouter);
15692 : }
15693 : }
15694 0 : }
15695 :
15696 : /* Configuration of static route announcement and aggregate
15697 : information. */
15698 0 : void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15699 : safi_t safi)
15700 : {
15701 0 : struct bgp_dest *dest;
15702 0 : const struct prefix *p;
15703 0 : struct bgp_static *bgp_static;
15704 0 : struct bgp_aggregate *bgp_aggregate;
15705 :
15706 0 : if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15707 0 : bgp_config_write_network_vpn(vty, bgp, afi, safi);
15708 0 : return;
15709 : }
15710 :
15711 0 : if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15712 0 : bgp_config_write_network_evpn(vty, bgp, afi, safi);
15713 0 : return;
15714 : }
15715 :
15716 : /* Network configuration. */
15717 0 : for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15718 0 : dest = bgp_route_next(dest)) {
15719 0 : bgp_static = bgp_dest_get_bgp_static_info(dest);
15720 0 : if (bgp_static == NULL)
15721 0 : continue;
15722 :
15723 0 : p = bgp_dest_get_prefix(dest);
15724 :
15725 0 : vty_out(vty, " network %pFX", p);
15726 :
15727 0 : if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15728 0 : vty_out(vty, " label-index %u",
15729 : bgp_static->label_index);
15730 :
15731 0 : if (bgp_static->rmap.name)
15732 0 : vty_out(vty, " route-map %s", bgp_static->rmap.name);
15733 :
15734 0 : if (bgp_static->backdoor)
15735 0 : vty_out(vty, " backdoor");
15736 :
15737 0 : vty_out(vty, "\n");
15738 : }
15739 :
15740 : /* Aggregate-address configuration. */
15741 0 : for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15742 0 : dest = bgp_route_next(dest)) {
15743 0 : bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
15744 0 : if (bgp_aggregate == NULL)
15745 0 : continue;
15746 :
15747 0 : p = bgp_dest_get_prefix(dest);
15748 :
15749 0 : vty_out(vty, " aggregate-address %pFX", p);
15750 :
15751 0 : if (bgp_aggregate->as_set)
15752 0 : vty_out(vty, " as-set");
15753 :
15754 0 : if (bgp_aggregate->summary_only)
15755 0 : vty_out(vty, " summary-only");
15756 :
15757 0 : if (bgp_aggregate->rmap.name)
15758 0 : vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15759 :
15760 0 : if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15761 0 : vty_out(vty, " origin %s",
15762 : bgp_origin2str(bgp_aggregate->origin));
15763 :
15764 0 : if (bgp_aggregate->match_med)
15765 0 : vty_out(vty, " matching-MED-only");
15766 :
15767 0 : if (bgp_aggregate->suppress_map_name)
15768 0 : vty_out(vty, " suppress-map %s",
15769 : bgp_aggregate->suppress_map_name);
15770 :
15771 0 : vty_out(vty, "\n");
15772 : }
15773 : }
15774 :
15775 0 : void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
15776 : safi_t safi)
15777 : {
15778 0 : struct bgp_dest *dest;
15779 0 : struct bgp_distance *bdistance;
15780 :
15781 : /* Distance configuration. */
15782 0 : if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15783 0 : && bgp->distance_local[afi][safi]
15784 0 : && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15785 0 : || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15786 0 : || bgp->distance_local[afi][safi]
15787 : != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
15788 0 : vty_out(vty, " distance bgp %d %d %d\n",
15789 : bgp->distance_ebgp[afi][safi],
15790 : bgp->distance_ibgp[afi][safi],
15791 : bgp->distance_local[afi][safi]);
15792 : }
15793 :
15794 0 : for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15795 0 : dest = bgp_route_next(dest)) {
15796 0 : bdistance = bgp_dest_get_bgp_distance_info(dest);
15797 0 : if (bdistance != NULL)
15798 0 : vty_out(vty, " distance %d %pBD %s\n",
15799 0 : bdistance->distance, dest,
15800 0 : bdistance->access_list ? bdistance->access_list
15801 : : "");
15802 : }
15803 0 : }
15804 :
15805 : /* Allocate routing table structure and install commands. */
15806 2 : void bgp_route_init(void)
15807 : {
15808 2 : afi_t afi;
15809 2 : safi_t safi;
15810 :
15811 : /* Init BGP distance table. */
15812 50 : FOREACH_AFI_SAFI (afi, safi)
15813 42 : bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
15814 :
15815 : /* IPv4 BGP commands. */
15816 2 : install_element(BGP_NODE, &bgp_table_map_cmd);
15817 2 : install_element(BGP_NODE, &bgp_network_cmd);
15818 2 : install_element(BGP_NODE, &no_bgp_table_map_cmd);
15819 :
15820 2 : install_element(BGP_NODE, &aggregate_addressv4_cmd);
15821 :
15822 : /* IPv4 unicast configuration. */
15823 2 : install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15824 2 : install_element(BGP_IPV4_NODE, &bgp_network_cmd);
15825 2 : install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
15826 :
15827 2 : install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
15828 :
15829 : /* IPv4 multicast configuration. */
15830 2 : install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15831 2 : install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
15832 2 : install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
15833 2 : install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
15834 :
15835 : /* IPv4 labeled-unicast configuration. */
15836 2 : install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
15837 2 : install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
15838 :
15839 2 : install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15840 2 : install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
15841 2 : install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
15842 2 : install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15843 2 : install_element(VIEW_NODE, &show_ip_bgp_cmd);
15844 2 : install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15845 2 : install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
15846 2 : install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
15847 :
15848 2 : install_element(VIEW_NODE,
15849 : &show_ip_bgp_instance_neighbor_advertised_route_cmd);
15850 2 : install_element(VIEW_NODE,
15851 : &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
15852 2 : install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15853 2 : install_element(VIEW_NODE,
15854 : &show_ip_bgp_neighbor_received_prefix_filter_cmd);
15855 : #ifdef KEEP_OLD_VPN_COMMANDS
15856 : install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
15857 : #endif /* KEEP_OLD_VPN_COMMANDS */
15858 2 : install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15859 2 : install_element(VIEW_NODE,
15860 : &show_bgp_l2vpn_evpn_route_prefix_cmd);
15861 :
15862 : /* BGP dampening clear commands */
15863 2 : install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15864 2 : install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
15865 :
15866 2 : install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15867 2 : install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15868 :
15869 : /* prefix count */
15870 2 : install_element(ENABLE_NODE,
15871 : &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
15872 : #ifdef KEEP_OLD_VPN_COMMANDS
15873 : install_element(ENABLE_NODE,
15874 : &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
15875 : #endif /* KEEP_OLD_VPN_COMMANDS */
15876 :
15877 : /* New config IPv6 BGP commands. */
15878 2 : install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15879 2 : install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
15880 2 : install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
15881 :
15882 2 : install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
15883 :
15884 2 : install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
15885 :
15886 : /* IPv6 labeled unicast address family. */
15887 2 : install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
15888 2 : install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
15889 :
15890 2 : install_element(BGP_NODE, &bgp_distance_cmd);
15891 2 : install_element(BGP_NODE, &no_bgp_distance_cmd);
15892 2 : install_element(BGP_NODE, &bgp_distance_source_cmd);
15893 2 : install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15894 2 : install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15895 2 : install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
15896 2 : install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15897 2 : install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15898 2 : install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
15899 2 : install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15900 2 : install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15901 2 : install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
15902 2 : install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15903 2 : install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15904 2 : install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
15905 2 : install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15906 2 : install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15907 2 : install_element(BGP_IPV4M_NODE,
15908 : &no_bgp_distance_source_access_list_cmd);
15909 2 : install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15910 2 : install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
15911 2 : install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15912 2 : install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15913 2 : install_element(BGP_IPV6_NODE,
15914 : &ipv6_bgp_distance_source_access_list_cmd);
15915 2 : install_element(BGP_IPV6_NODE,
15916 : &no_ipv6_bgp_distance_source_access_list_cmd);
15917 2 : install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15918 2 : install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
15919 2 : install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15920 2 : install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15921 2 : install_element(BGP_IPV6M_NODE,
15922 : &ipv6_bgp_distance_source_access_list_cmd);
15923 2 : install_element(BGP_IPV6M_NODE,
15924 : &no_ipv6_bgp_distance_source_access_list_cmd);
15925 :
15926 : /* BGP dampening */
15927 2 : install_element(BGP_NODE, &bgp_damp_set_cmd);
15928 2 : install_element(BGP_NODE, &bgp_damp_unset_cmd);
15929 2 : install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15930 2 : install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15931 2 : install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15932 2 : install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15933 2 : install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15934 2 : install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15935 2 : install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15936 2 : install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15937 2 : install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15938 2 : install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15939 2 : install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15940 2 : install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
15941 :
15942 : /* Large Communities */
15943 2 : install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15944 2 : install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
15945 :
15946 : /* show bgp ipv4 flowspec detailed */
15947 2 : install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15948 :
15949 2 : install_element(VIEW_NODE, &show_bgp_listeners_cmd);
15950 2 : install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
15951 2 : }
15952 :
15953 2 : void bgp_route_finish(void)
15954 : {
15955 2 : afi_t afi;
15956 2 : safi_t safi;
15957 :
15958 50 : FOREACH_AFI_SAFI (afi, safi) {
15959 42 : bgp_table_unlock(bgp_distance_table[afi][safi]);
15960 42 : bgp_distance_table[afi][safi] = NULL;
15961 : }
15962 2 : }
|