]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: first variable is set but never used.
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
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 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
25#include "prefix.h"
26#include "linklist.h"
27#include "memory.h"
28#include "command.h"
29#include "stream.h"
30#include "filter.h"
718e3744 31#include "log.h"
32#include "routemap.h"
33#include "buffer.h"
34#include "sockunion.h"
35#include "plist.h"
36#include "thread.h"
200df115 37#include "workqueue.h"
3f9c7369 38#include "queue.h"
6e919709 39#include "memory.h"
4dcadbef 40#include "lib/json.h"
718e3744 41
42#include "bgpd/bgpd.h"
43#include "bgpd/bgp_table.h"
44#include "bgpd/bgp_route.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_debug.h"
47#include "bgpd/bgp_aspath.h"
48#include "bgpd/bgp_regex.h"
49#include "bgpd/bgp_community.h"
50#include "bgpd/bgp_ecommunity.h"
57d187bc 51#include "bgpd/bgp_lcommunity.h"
718e3744 52#include "bgpd/bgp_clist.h"
53#include "bgpd/bgp_packet.h"
54#include "bgpd/bgp_filter.h"
55#include "bgpd/bgp_fsm.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_nexthop.h"
58#include "bgpd/bgp_damp.h"
59#include "bgpd/bgp_advertise.h"
60#include "bgpd/bgp_zebra.h"
0a486e5f 61#include "bgpd/bgp_vty.h"
96450faf 62#include "bgpd/bgp_mpath.h"
fc9a856f 63#include "bgpd/bgp_nht.h"
3f9c7369 64#include "bgpd/bgp_updgrp.h"
cd1964ff 65#include "bgpd/bgp_label.h"
718e3744 66
65efcfce 67#if ENABLE_BGP_VNC
f8b6f499
LB
68#include "bgpd/rfapi/rfapi_backend.h"
69#include "bgpd/rfapi/vnc_import_bgp.h"
70#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 71#endif
aee875b5
PG
72#include "bgpd/bgp_encap_types.h"
73#include "bgpd/bgp_encap_tlv.h"
684a7227 74#include "bgpd/bgp_evpn.h"
3da6fcd5 75#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 76#include "bgpd/bgp_flowspec.h"
98a9dbc7 77#include "bgpd/bgp_flowspec_util.h"
45918cfb 78#include "bgpd/bgp_pbr.h"
65efcfce 79
e2a86ad9
DS
80#ifndef VTYSH_EXTRACT_PL
81#include "bgpd/bgp_route_clippy.c"
82#endif
aee875b5 83
718e3744 84/* Extern from bgp_dump.c */
dde72586
SH
85extern const char *bgp_origin_str[];
86extern const char *bgp_origin_long_str[];
6b0655a2 87
b7d08f5a 88/* PMSI strings. */
89#define PMSI_TNLTYPE_STR_NO_INFO "No info"
90#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
91static const struct message bgp_pmsi_tnltype_str[] = {
92 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
93 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
94 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
95 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
96 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
97 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
98 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
99 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 100 {0}
101};
b7d08f5a 102
9df8b37c
PZ
103#define VRFID_NONE_STR "-"
104
d62a17ae 105struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
106 safi_t safi, struct prefix *p,
107 struct prefix_rd *prd)
108{
109 struct bgp_node *rn;
110 struct bgp_node *prn = NULL;
111
112 assert(table);
113 if (!table)
114 return NULL;
115
116 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
117 || (safi == SAFI_EVPN)) {
118 prn = bgp_node_get(table, (struct prefix *)prd);
119
120 if (prn->info == NULL)
960035b2 121 prn->info = bgp_table_init(table->bgp, afi, safi);
d62a17ae 122 else
123 bgp_unlock_node(prn);
124 table = prn->info;
125 }
718e3744 126
d62a17ae 127 rn = bgp_node_get(table, p);
718e3744 128
d62a17ae 129 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
130 || (safi == SAFI_EVPN))
131 rn->prn = prn;
718e3744 132
d62a17ae 133 return rn;
718e3744 134}
6b0655a2 135
d62a17ae 136struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
137 safi_t safi, struct prefix *p,
138 struct prefix_rd *prd)
128ea8ab 139{
d62a17ae 140 struct bgp_node *rn;
141 struct bgp_node *prn = NULL;
128ea8ab 142
d62a17ae 143 if (!table)
144 return NULL;
128ea8ab 145
d62a17ae 146 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
147 || (safi == SAFI_EVPN)) {
148 prn = bgp_node_lookup(table, (struct prefix *)prd);
149 if (!prn)
150 return NULL;
128ea8ab 151
d62a17ae 152 if (prn->info == NULL) {
153 bgp_unlock_node(prn);
154 return NULL;
155 }
128ea8ab 156
d62a17ae 157 table = prn->info;
158 }
128ea8ab 159
d62a17ae 160 rn = bgp_node_lookup(table, p);
128ea8ab 161
d62a17ae 162 return rn;
128ea8ab 163}
164
fb982c25 165/* Allocate bgp_info_extra */
d62a17ae 166static struct bgp_info_extra *bgp_info_extra_new(void)
fb982c25 167{
d62a17ae 168 struct bgp_info_extra *new;
169 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA, sizeof(struct bgp_info_extra));
b57ba6d2
MK
170 new->label[0] = MPLS_INVALID_LABEL;
171 new->num_labels = 0;
d62a17ae 172 return new;
fb982c25
PJ
173}
174
d62a17ae 175static void bgp_info_extra_free(struct bgp_info_extra **extra)
fb982c25 176{
d62a17ae 177 if (extra && *extra) {
178 if ((*extra)->damp_info)
179 bgp_damp_info_free((*extra)->damp_info, 0);
180
181 (*extra)->damp_info = NULL;
182
183 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
184
185 *extra = NULL;
186 }
fb982c25
PJ
187}
188
189/* Get bgp_info extra information for the given bgp_info, lazy allocated
190 * if required.
191 */
d62a17ae 192struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *ri)
fb982c25 193{
d62a17ae 194 if (!ri->extra)
195 ri->extra = bgp_info_extra_new();
196 return ri->extra;
fb982c25
PJ
197}
198
65efcfce 199/* Allocate new bgp info structure. */
d62a17ae 200struct bgp_info *bgp_info_new(void)
65efcfce 201{
d62a17ae 202 return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info));
65efcfce
LB
203}
204
718e3744 205/* Free bgp route information. */
d62a17ae 206static void bgp_info_free(struct bgp_info *binfo)
718e3744 207{
7c82b312
DS
208 /* unlink reference to parent, if any. */
209 if (binfo->extra && binfo->extra->parent) {
210 bgp_info_unlock((struct bgp_info *)binfo->extra->parent);
211 bgp_unlock_node((struct bgp_node *)((struct bgp_info *)binfo
212 ->extra->parent)->net);
213 binfo->extra->parent = NULL;
214 }
215
d62a17ae 216 if (binfo->attr)
217 bgp_attr_unintern(&binfo->attr);
fb018d25 218
d62a17ae 219 bgp_unlink_nexthop(binfo);
220 bgp_info_extra_free(&binfo->extra);
221 bgp_info_mpath_free(&binfo->mpath);
718e3744 222
d62a17ae 223 peer_unlock(binfo->peer); /* bgp_info peer reference */
200df115 224
d62a17ae 225 XFREE(MTYPE_BGP_ROUTE, binfo);
718e3744 226}
227
d62a17ae 228struct bgp_info *bgp_info_lock(struct bgp_info *binfo)
200df115 229{
d62a17ae 230 binfo->lock++;
231 return binfo;
200df115 232}
233
d62a17ae 234struct bgp_info *bgp_info_unlock(struct bgp_info *binfo)
200df115 235{
d62a17ae 236 assert(binfo && binfo->lock > 0);
237 binfo->lock--;
238
239 if (binfo->lock == 0) {
200df115 240#if 0
241 zlog_debug ("%s: unlocked and freeing", __func__);
242 zlog_backtrace (LOG_DEBUG);
243#endif
d62a17ae 244 bgp_info_free(binfo);
245 return NULL;
246 }
200df115 247
248#if 0
249 if (binfo->lock == 1)
250 {
251 zlog_debug ("%s: unlocked to 1", __func__);
252 zlog_backtrace (LOG_DEBUG);
253 }
254#endif
d62a17ae 255
256 return binfo;
200df115 257}
258
d62a17ae 259void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri)
718e3744 260{
d62a17ae 261 struct bgp_info *top;
718e3744 262
d62a17ae 263 top = rn->info;
264
265 ri->next = rn->info;
266 ri->prev = NULL;
267 if (top)
268 top->prev = ri;
269 rn->info = ri;
270
271 bgp_info_lock(ri);
272 bgp_lock_node(rn);
273 peer_lock(ri->peer); /* bgp_info peer reference */
718e3744 274}
275
d62a17ae 276/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 277 completion callback *only* */
d62a17ae 278void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri)
718e3744 279{
d62a17ae 280 if (ri->next)
281 ri->next->prev = ri->prev;
282 if (ri->prev)
283 ri->prev->next = ri->next;
284 else
285 rn->info = ri->next;
286
287 bgp_info_mpath_dequeue(ri);
288 bgp_info_unlock(ri);
289 bgp_unlock_node(rn);
718e3744 290}
291
d62a17ae 292void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri)
b40d939b 293{
d62a17ae 294 bgp_info_set_flag(rn, ri, BGP_INFO_REMOVED);
295 /* set of previous already took care of pcount */
296 UNSET_FLAG(ri->flags, BGP_INFO_VALID);
b40d939b 297}
298
8d45210e
AS
299/* undo the effects of a previous call to bgp_info_delete; typically
300 called when a route is deleted and then quickly re-added before the
301 deletion has been processed */
d62a17ae 302void bgp_info_restore(struct bgp_node *rn, struct bgp_info *ri)
8d45210e 303{
d62a17ae 304 bgp_info_unset_flag(rn, ri, BGP_INFO_REMOVED);
305 /* unset of previous already took care of pcount */
306 SET_FLAG(ri->flags, BGP_INFO_VALID);
8d45210e
AS
307}
308
d62a17ae 309/* Adjust pcount as required */
310static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)
1a392d46 311{
d62a17ae 312 struct bgp_table *table;
67174041 313
d62a17ae 314 assert(rn && bgp_node_table(rn));
315 assert(ri && ri->peer && ri->peer->bgp);
6f58544d 316
d62a17ae 317 table = bgp_node_table(rn);
67174041 318
d62a17ae 319 if (ri->peer == ri->peer->bgp->peer_self)
320 return;
321
322 if (!BGP_INFO_COUNTABLE(ri)
323 && CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
324
325 UNSET_FLAG(ri->flags, BGP_INFO_COUNTED);
326
327 /* slight hack, but more robust against errors. */
328 if (ri->peer->pcount[table->afi][table->safi])
329 ri->peer->pcount[table->afi][table->safi]--;
330 else {
331 zlog_warn(
332 "%s: Asked to decrement 0 prefix count for peer %s",
333 __func__, ri->peer->host);
334 zlog_backtrace(LOG_WARNING);
335 zlog_warn("%s: Please report to Quagga bugzilla",
336 __func__);
337 }
338 } else if (BGP_INFO_COUNTABLE(ri)
339 && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
340 SET_FLAG(ri->flags, BGP_INFO_COUNTED);
341 ri->peer->pcount[table->afi][table->safi]++;
342 }
1a392d46
PJ
343}
344
d62a17ae 345static int bgp_label_index_differs(struct bgp_info *ri1, struct bgp_info *ri2)
28d58fd7 346{
d62a17ae 347 return (!(ri1->attr->label_index == ri2->attr->label_index));
28d58fd7 348}
1a392d46
PJ
349
350/* Set/unset bgp_info flags, adjusting any other state as needed.
351 * This is here primarily to keep prefix-count in check.
352 */
d7c0a89a 353void bgp_info_set_flag(struct bgp_node *rn, struct bgp_info *ri, uint32_t flag)
1a392d46 354{
d62a17ae 355 SET_FLAG(ri->flags, flag);
356
357 /* early bath if we know it's not a flag that changes countability state
358 */
359 if (!CHECK_FLAG(flag,
360 BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED))
361 return;
362
363 bgp_pcount_adjust(rn, ri);
1a392d46
PJ
364}
365
d62a17ae 366void bgp_info_unset_flag(struct bgp_node *rn, struct bgp_info *ri,
d7c0a89a 367 uint32_t flag)
1a392d46 368{
d62a17ae 369 UNSET_FLAG(ri->flags, flag);
370
371 /* early bath if we know it's not a flag that changes countability state
372 */
373 if (!CHECK_FLAG(flag,
374 BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED))
375 return;
376
377 bgp_pcount_adjust(rn, ri);
1a392d46
PJ
378}
379
718e3744 380/* Get MED value. If MED value is missing and "bgp bestpath
381 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 382static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 383{
384 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
385 return attr->med;
386 else {
387 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
388 return BGP_MED_MAX;
389 else
390 return 0;
391 }
718e3744 392}
393
d62a17ae 394void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf)
2ec1e66f 395{
d62a17ae 396 if (ri->addpath_rx_id)
397 sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host,
398 ri->addpath_rx_id);
399 else
400 sprintf(buf, "path %s", ri->peer->host);
401}
9fbdd100 402
d62a17ae 403/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
404 */
405static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new,
406 struct bgp_info *exist, int *paths_eq,
407 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
408 char *pfx_buf, afi_t afi, safi_t safi)
409{
410 struct attr *newattr, *existattr;
411 bgp_peer_sort_t new_sort;
412 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
413 uint32_t new_pref;
414 uint32_t exist_pref;
415 uint32_t new_med;
416 uint32_t exist_med;
417 uint32_t new_weight;
418 uint32_t exist_weight;
d62a17ae 419 uint32_t newm, existm;
420 struct in_addr new_id;
421 struct in_addr exist_id;
422 int new_cluster;
423 int exist_cluster;
424 int internal_as_route;
425 int confed_as_route;
04d14c8b 426 int ret = 0;
d62a17ae 427 char new_buf[PATH_ADDPATH_STR_BUFFER];
428 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
429 uint32_t new_mm_seq;
430 uint32_t exist_mm_seq;
d62a17ae 431
432 *paths_eq = 0;
433
434 /* 0. Null check. */
435 if (new == NULL) {
436 if (debug)
437 zlog_debug("%s: new is NULL", pfx_buf);
438 return 0;
439 }
2ec1e66f 440
d62a17ae 441 if (debug)
442 bgp_info_path_with_addpath_rx_str(new, new_buf);
718e3744 443
d62a17ae 444 if (exist == NULL) {
445 if (debug)
446 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
447 new_buf);
448 return 1;
449 }
2ec1e66f 450
d62a17ae 451 if (debug) {
452 bgp_info_path_with_addpath_rx_str(exist, exist_buf);
453 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
454 pfx_buf, new_buf, new->flags, exist_buf,
455 exist->flags);
456 }
8ff56318 457
d62a17ae 458 newattr = new->attr;
459 existattr = exist->attr;
460
461 /* For EVPN routes, we cannot just go by local vs remote, we have to
462 * look at the MAC mobility sequence number, if present.
463 */
464 if (safi == SAFI_EVPN) {
465 /* This is an error condition described in RFC 7432 Section
466 * 15.2. The RFC
467 * states that in this scenario "the PE MUST alert the operator"
468 * but it
469 * does not state what other action to take. In order to provide
470 * some
471 * consistency in this scenario we are going to prefer the path
472 * with the
473 * sticky flag.
474 */
475 if (newattr->sticky != existattr->sticky) {
476 if (!debug) {
477 prefix2str(&new->net->p, pfx_buf,
478 sizeof(*pfx_buf)
479 * PREFIX2STR_BUFFER);
480 bgp_info_path_with_addpath_rx_str(new, new_buf);
481 bgp_info_path_with_addpath_rx_str(exist,
482 exist_buf);
483 }
484
485 if (newattr->sticky && !existattr->sticky) {
486 zlog_warn(
487 "%s: %s wins over %s due to sticky MAC flag",
488 pfx_buf, new_buf, exist_buf);
489 return 1;
490 }
491
492 if (!newattr->sticky && existattr->sticky) {
493 zlog_warn(
494 "%s: %s loses to %s due to sticky MAC flag",
495 pfx_buf, new_buf, exist_buf);
496 return 0;
497 }
498 }
128ea8ab 499
d62a17ae 500 new_mm_seq = mac_mobility_seqnum(newattr);
501 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 502
d62a17ae 503 if (new_mm_seq > exist_mm_seq) {
504 if (debug)
505 zlog_debug(
506 "%s: %s wins over %s due to MM seq %u > %u",
507 pfx_buf, new_buf, exist_buf, new_mm_seq,
508 exist_mm_seq);
509 return 1;
510 }
8ff56318 511
d62a17ae 512 if (new_mm_seq < exist_mm_seq) {
513 if (debug)
514 zlog_debug(
515 "%s: %s loses to %s due to MM seq %u < %u",
516 pfx_buf, new_buf, exist_buf, new_mm_seq,
517 exist_mm_seq);
518 return 0;
519 }
520 }
9fbdd100 521
d62a17ae 522 /* 1. Weight check. */
d62a17ae 523 new_weight = newattr->weight;
524 exist_weight = existattr->weight;
8ff56318 525
d62a17ae 526 if (new_weight > exist_weight) {
527 if (debug)
528 zlog_debug("%s: %s wins over %s due to weight %d > %d",
529 pfx_buf, new_buf, exist_buf, new_weight,
530 exist_weight);
531 return 1;
532 }
718e3744 533
d62a17ae 534 if (new_weight < exist_weight) {
535 if (debug)
536 zlog_debug("%s: %s loses to %s due to weight %d < %d",
537 pfx_buf, new_buf, exist_buf, new_weight,
538 exist_weight);
539 return 0;
540 }
9fbdd100 541
d62a17ae 542 /* 2. Local preference check. */
543 new_pref = exist_pref = bgp->default_local_pref;
544
545 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
546 new_pref = newattr->local_pref;
547 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
548 exist_pref = existattr->local_pref;
549
550 if (new_pref > exist_pref) {
551 if (debug)
552 zlog_debug(
553 "%s: %s wins over %s due to localpref %d > %d",
554 pfx_buf, new_buf, exist_buf, new_pref,
555 exist_pref);
556 return 1;
557 }
718e3744 558
d62a17ae 559 if (new_pref < exist_pref) {
560 if (debug)
561 zlog_debug(
562 "%s: %s loses to %s due to localpref %d < %d",
563 pfx_buf, new_buf, exist_buf, new_pref,
564 exist_pref);
565 return 0;
566 }
9fbdd100 567
d62a17ae 568 /* 3. Local route check. We prefer:
569 * - BGP_ROUTE_STATIC
570 * - BGP_ROUTE_AGGREGATE
571 * - BGP_ROUTE_REDISTRIBUTE
572 */
90f4f482 573 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
574 new->sub_type == BGP_ROUTE_IMPORTED)) {
d62a17ae 575 if (debug)
576 zlog_debug(
577 "%s: %s wins over %s due to preferred BGP_ROUTE type",
578 pfx_buf, new_buf, exist_buf);
579 return 1;
580 }
718e3744 581
90f4f482 582 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 583 exist->sub_type == BGP_ROUTE_IMPORTED)) {
d62a17ae 584 if (debug)
585 zlog_debug(
586 "%s: %s loses to %s due to preferred BGP_ROUTE type",
587 pfx_buf, new_buf, exist_buf);
588 return 0;
6811845b 589 }
718e3744 590
d62a17ae 591 /* 4. AS path length check. */
592 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
593 int exist_hops = aspath_count_hops(existattr->aspath);
594 int exist_confeds = aspath_count_confeds(existattr->aspath);
595
596 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
597 int aspath_hops;
598
599 aspath_hops = aspath_count_hops(newattr->aspath);
600 aspath_hops += aspath_count_confeds(newattr->aspath);
601
602 if (aspath_hops < (exist_hops + exist_confeds)) {
603 if (debug)
604 zlog_debug(
605 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
606 pfx_buf, new_buf, exist_buf,
607 aspath_hops,
608 (exist_hops + exist_confeds));
609 return 1;
610 }
611
612 if (aspath_hops > (exist_hops + exist_confeds)) {
613 if (debug)
614 zlog_debug(
615 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
616 pfx_buf, new_buf, exist_buf,
617 aspath_hops,
618 (exist_hops + exist_confeds));
619 return 0;
620 }
621 } else {
622 int newhops = aspath_count_hops(newattr->aspath);
623
624 if (newhops < exist_hops) {
625 if (debug)
626 zlog_debug(
627 "%s: %s wins over %s due to aspath hopcount %d < %d",
628 pfx_buf, new_buf, exist_buf,
629 newhops, exist_hops);
630 return 1;
631 }
632
633 if (newhops > exist_hops) {
634 if (debug)
635 zlog_debug(
636 "%s: %s loses to %s due to aspath hopcount %d > %d",
637 pfx_buf, new_buf, exist_buf,
638 newhops, exist_hops);
639 return 0;
640 }
641 }
642 }
9fbdd100 643
d62a17ae 644 /* 5. Origin check. */
645 if (newattr->origin < existattr->origin) {
646 if (debug)
647 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
648 pfx_buf, new_buf, exist_buf,
649 bgp_origin_long_str[newattr->origin],
650 bgp_origin_long_str[existattr->origin]);
651 return 1;
652 }
718e3744 653
d62a17ae 654 if (newattr->origin > existattr->origin) {
655 if (debug)
656 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
657 pfx_buf, new_buf, exist_buf,
658 bgp_origin_long_str[newattr->origin],
659 bgp_origin_long_str[existattr->origin]);
660 return 0;
661 }
718e3744 662
d62a17ae 663 /* 6. MED check. */
664 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
665 && aspath_count_hops(existattr->aspath) == 0);
666 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
667 && aspath_count_confeds(existattr->aspath) > 0
668 && aspath_count_hops(newattr->aspath) == 0
669 && aspath_count_hops(existattr->aspath) == 0);
670
671 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
672 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
673 || aspath_cmp_left(newattr->aspath, existattr->aspath)
674 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
675 || internal_as_route) {
676 new_med = bgp_med_value(new->attr, bgp);
677 exist_med = bgp_med_value(exist->attr, bgp);
678
679 if (new_med < exist_med) {
680 if (debug)
681 zlog_debug(
682 "%s: %s wins over %s due to MED %d < %d",
683 pfx_buf, new_buf, exist_buf, new_med,
684 exist_med);
685 return 1;
686 }
8ff56318 687
d62a17ae 688 if (new_med > exist_med) {
689 if (debug)
690 zlog_debug(
691 "%s: %s loses to %s due to MED %d > %d",
692 pfx_buf, new_buf, exist_buf, new_med,
693 exist_med);
694 return 0;
695 }
696 }
9fbdd100 697
d62a17ae 698 /* 7. Peer type check. */
699 new_sort = new->peer->sort;
700 exist_sort = exist->peer->sort;
701
702 if (new_sort == BGP_PEER_EBGP
703 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
704 if (debug)
705 zlog_debug(
706 "%s: %s wins over %s due to eBGP peer > iBGP peer",
707 pfx_buf, new_buf, exist_buf);
708 return 1;
709 }
718e3744 710
d62a17ae 711 if (exist_sort == BGP_PEER_EBGP
712 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
713 if (debug)
714 zlog_debug(
715 "%s: %s loses to %s due to iBGP peer < eBGP peer",
716 pfx_buf, new_buf, exist_buf);
717 return 0;
718 }
8ff56318 719
d62a17ae 720 /* 8. IGP metric check. */
721 newm = existm = 0;
8ff56318 722
d62a17ae 723 if (new->extra)
724 newm = new->extra->igpmetric;
725 if (exist->extra)
726 existm = exist->extra->igpmetric;
9fbdd100 727
d62a17ae 728 if (newm < existm) {
729 if (debug)
730 zlog_debug(
731 "%s: %s wins over %s due to IGP metric %d < %d",
732 pfx_buf, new_buf, exist_buf, newm, existm);
733 ret = 1;
734 }
718e3744 735
d62a17ae 736 if (newm > existm) {
737 if (debug)
738 zlog_debug(
739 "%s: %s loses to %s due to IGP metric %d > %d",
740 pfx_buf, new_buf, exist_buf, newm, existm);
741 ret = 0;
5e242b0d 742 }
5e242b0d 743
d62a17ae 744 /* 9. Same IGP metric. Compare the cluster list length as
745 representative of IGP hops metric. Rewrite the metric value
746 pair (newm, existm) with the cluster list length. Prefer the
747 path with smaller cluster list length. */
748 if (newm == existm) {
749 if (peer_sort(new->peer) == BGP_PEER_IBGP
750 && peer_sort(exist->peer) == BGP_PEER_IBGP
751 && (mpath_cfg == NULL
752 || CHECK_FLAG(
753 mpath_cfg->ibgp_flags,
754 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
755 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
756 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
757
758 if (newm < existm) {
759 if (debug)
760 zlog_debug(
761 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
762 pfx_buf, new_buf, exist_buf,
763 newm, existm);
764 ret = 1;
765 }
766
767 if (newm > existm) {
768 if (debug)
769 zlog_debug(
770 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
771 pfx_buf, new_buf, exist_buf,
772 newm, existm);
773 ret = 0;
774 }
775 }
776 }
31a4638f 777
d62a17ae 778 /* 10. confed-external vs. confed-internal */
779 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
780 if (new_sort == BGP_PEER_CONFED
781 && exist_sort == BGP_PEER_IBGP) {
782 if (debug)
783 zlog_debug(
784 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
785 pfx_buf, new_buf, exist_buf);
786 return 1;
787 }
718e3744 788
d62a17ae 789 if (exist_sort == BGP_PEER_CONFED
790 && new_sort == BGP_PEER_IBGP) {
791 if (debug)
792 zlog_debug(
793 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
794 pfx_buf, new_buf, exist_buf);
795 return 0;
796 }
797 }
718e3744 798
d62a17ae 799 /* 11. Maximum path check. */
800 if (newm == existm) {
801 /* If one path has a label but the other does not, do not treat
802 * them as equals for multipath
803 */
a4d82a8a 804 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 805 != (exist->extra
b57ba6d2 806 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 807 if (debug)
808 zlog_debug(
809 "%s: %s and %s cannot be multipath, one has a label while the other does not",
810 pfx_buf, new_buf, exist_buf);
811 } else if (bgp_flag_check(bgp,
812 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
813
814 /*
815 * For the two paths, all comparison steps till IGP
816 * metric
817 * have succeeded - including AS_PATH hop count. Since
818 * 'bgp
819 * bestpath as-path multipath-relax' knob is on, we
820 * don't need
821 * an exact match of AS_PATH. Thus, mark the paths are
822 * equal.
823 * That will trigger both these paths to get into the
824 * multipath
825 * array.
826 */
827 *paths_eq = 1;
828
829 if (debug)
830 zlog_debug(
831 "%s: %s and %s are equal via multipath-relax",
832 pfx_buf, new_buf, exist_buf);
833 } else if (new->peer->sort == BGP_PEER_IBGP) {
834 if (aspath_cmp(new->attr->aspath,
835 exist->attr->aspath)) {
836 *paths_eq = 1;
837
838 if (debug)
839 zlog_debug(
840 "%s: %s and %s are equal via matching aspaths",
841 pfx_buf, new_buf, exist_buf);
842 }
843 } else if (new->peer->as == exist->peer->as) {
844 *paths_eq = 1;
845
846 if (debug)
847 zlog_debug(
848 "%s: %s and %s are equal via same remote-as",
849 pfx_buf, new_buf, exist_buf);
850 }
851 } else {
852 /*
853 * TODO: If unequal cost ibgp multipath is enabled we can
854 * mark the paths as equal here instead of returning
855 */
856 if (debug) {
857 if (ret == 1)
858 zlog_debug(
859 "%s: %s wins over %s after IGP metric comparison",
860 pfx_buf, new_buf, exist_buf);
861 else
862 zlog_debug(
863 "%s: %s loses to %s after IGP metric comparison",
864 pfx_buf, new_buf, exist_buf);
865 }
866 return ret;
867 }
718e3744 868
d62a17ae 869 /* 12. If both paths are external, prefer the path that was received
870 first (the oldest one). This step minimizes route-flap, since a
871 newer path won't displace an older one, even if it was the
872 preferred route based on the additional decision criteria below. */
873 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
874 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
875 if (CHECK_FLAG(new->flags, BGP_INFO_SELECTED)) {
876 if (debug)
877 zlog_debug(
878 "%s: %s wins over %s due to oldest external",
879 pfx_buf, new_buf, exist_buf);
880 return 1;
881 }
9fbdd100 882
d62a17ae 883 if (CHECK_FLAG(exist->flags, BGP_INFO_SELECTED)) {
884 if (debug)
885 zlog_debug(
886 "%s: %s loses to %s due to oldest external",
887 pfx_buf, new_buf, exist_buf);
888 return 0;
889 }
890 }
718e3744 891
d62a17ae 892 /* 13. Router-ID comparision. */
893 /* If one of the paths is "stale", the corresponding peer router-id will
894 * be 0 and would always win over the other path. If originator id is
895 * used for the comparision, it will decide which path is better.
896 */
897 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
898 new_id.s_addr = newattr->originator_id.s_addr;
899 else
900 new_id.s_addr = new->peer->remote_id.s_addr;
901 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
902 exist_id.s_addr = existattr->originator_id.s_addr;
903 else
904 exist_id.s_addr = exist->peer->remote_id.s_addr;
905
906 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
907 if (debug)
908 zlog_debug(
909 "%s: %s wins over %s due to Router-ID comparison",
910 pfx_buf, new_buf, exist_buf);
911 return 1;
912 }
718e3744 913
d62a17ae 914 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
915 if (debug)
916 zlog_debug(
917 "%s: %s loses to %s due to Router-ID comparison",
918 pfx_buf, new_buf, exist_buf);
919 return 0;
920 }
9fbdd100 921
d62a17ae 922 /* 14. Cluster length comparision. */
923 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
924 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
925
926 if (new_cluster < exist_cluster) {
927 if (debug)
928 zlog_debug(
929 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
930 pfx_buf, new_buf, exist_buf, new_cluster,
931 exist_cluster);
932 return 1;
933 }
718e3744 934
d62a17ae 935 if (new_cluster > exist_cluster) {
936 if (debug)
937 zlog_debug(
938 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
939 pfx_buf, new_buf, exist_buf, new_cluster,
940 exist_cluster);
941 return 0;
942 }
9fbdd100 943
d62a17ae 944 /* 15. Neighbor address comparision. */
945 /* Do this only if neither path is "stale" as stale paths do not have
946 * valid peer information (as the connection may or may not be up).
947 */
948 if (CHECK_FLAG(exist->flags, BGP_INFO_STALE)) {
949 if (debug)
950 zlog_debug(
951 "%s: %s wins over %s due to latter path being STALE",
952 pfx_buf, new_buf, exist_buf);
953 return 1;
954 }
0de5153c 955
d62a17ae 956 if (CHECK_FLAG(new->flags, BGP_INFO_STALE)) {
957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to former path being STALE",
960 pfx_buf, new_buf, exist_buf);
961 return 0;
962 }
718e3744 963
d62a17ae 964 /* locally configured routes to advertise do not have su_remote */
965 if (new->peer->su_remote == NULL)
966 return 0;
967 if (exist->peer->su_remote == NULL)
968 return 1;
9fbdd100 969
d62a17ae 970 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
971
972 if (ret == 1) {
973 if (debug)
974 zlog_debug(
975 "%s: %s loses to %s due to Neighor IP comparison",
976 pfx_buf, new_buf, exist_buf);
977 return 0;
978 }
979
980 if (ret == -1) {
981 if (debug)
982 zlog_debug(
983 "%s: %s wins over %s due to Neighor IP comparison",
984 pfx_buf, new_buf, exist_buf);
985 return 1;
986 }
9fbdd100 987
d62a17ae 988 if (debug)
989 zlog_debug("%s: %s wins over %s due to nothing left to compare",
990 pfx_buf, new_buf, exist_buf);
718e3744 991
d62a17ae 992 return 1;
718e3744 993}
994
65efcfce
LB
995/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
996 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 997 * multipath is enabled
65efcfce 998 * This version is compatible with */
d62a17ae 999int bgp_info_cmp_compatible(struct bgp *bgp, struct bgp_info *new,
1000 struct bgp_info *exist, char *pfx_buf, afi_t afi,
1001 safi_t safi)
1002{
1003 int paths_eq;
1004 int ret;
1005 ret = bgp_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf, afi,
1006 safi);
1007
1008 if (paths_eq)
1009 ret = 0;
1010 else {
1011 if (ret == 1)
1012 ret = -1;
1013 else
1014 ret = 1;
1015 }
1016 return ret;
65efcfce
LB
1017}
1018
d62a17ae 1019static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1020 struct attr *attr, afi_t afi,
1021 safi_t safi)
718e3744 1022{
d62a17ae 1023 struct bgp_filter *filter;
718e3744 1024
d62a17ae 1025 filter = &peer->filter[afi][safi];
718e3744 1026
d62a17ae 1027#define FILTER_EXIST_WARN(F, f, filter) \
1028 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1029 zlog_warn("%s: Could not find configured input %s-list %s!", \
1030 peer->host, #f, F##_IN_NAME(filter));
1031
1032 if (DISTRIBUTE_IN_NAME(filter)) {
1033 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1034
1035 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1036 return FILTER_DENY;
1037 }
1038
1039 if (PREFIX_LIST_IN_NAME(filter)) {
1040 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1041
1042 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1043 return FILTER_DENY;
1044 }
1045
1046 if (FILTER_LIST_IN_NAME(filter)) {
1047 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1048
1049 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1050 == AS_FILTER_DENY)
1051 return FILTER_DENY;
1052 }
1053
1054 return FILTER_PERMIT;
650f76c2 1055#undef FILTER_EXIST_WARN
718e3744 1056}
1057
d62a17ae 1058static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1059 struct attr *attr, afi_t afi,
1060 safi_t safi)
718e3744 1061{
d62a17ae 1062 struct bgp_filter *filter;
1063
1064 filter = &peer->filter[afi][safi];
1065
1066#define FILTER_EXIST_WARN(F, f, filter) \
1067 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1068 zlog_warn("%s: Could not find configured output %s-list %s!", \
1069 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1070
d62a17ae 1071 if (DISTRIBUTE_OUT_NAME(filter)) {
1072 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1073
d62a17ae 1074 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1075 return FILTER_DENY;
1076 }
1077
1078 if (PREFIX_LIST_OUT_NAME(filter)) {
1079 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1080
d62a17ae 1081 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1082 == PREFIX_DENY)
1083 return FILTER_DENY;
1084 }
718e3744 1085
d62a17ae 1086 if (FILTER_LIST_OUT_NAME(filter)) {
1087 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1088
d62a17ae 1089 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1090 == AS_FILTER_DENY)
1091 return FILTER_DENY;
1092 }
718e3744 1093
d62a17ae 1094 return FILTER_PERMIT;
650f76c2 1095#undef FILTER_EXIST_WARN
718e3744 1096}
1097
1098/* If community attribute includes no_export then return 1. */
d62a17ae 1099static int bgp_community_filter(struct peer *peer, struct attr *attr)
1100{
1101 if (attr->community) {
1102 /* NO_ADVERTISE check. */
1103 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1104 return 1;
1105
1106 /* NO_EXPORT check. */
1107 if (peer->sort == BGP_PEER_EBGP
1108 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1109 return 1;
1110
1111 /* NO_EXPORT_SUBCONFED check. */
1112 if (peer->sort == BGP_PEER_EBGP
1113 || peer->sort == BGP_PEER_CONFED)
1114 if (community_include(attr->community,
1115 COMMUNITY_NO_EXPORT_SUBCONFED))
1116 return 1;
1117 }
1118 return 0;
718e3744 1119}
1120
1121/* Route reflection loop check. */
d62a17ae 1122static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1123{
d62a17ae 1124 struct in_addr cluster_id;
718e3744 1125
d62a17ae 1126 if (attr->cluster) {
1127 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1128 cluster_id = peer->bgp->cluster_id;
1129 else
1130 cluster_id = peer->bgp->router_id;
1131
1132 if (cluster_loop_check(attr->cluster, cluster_id))
1133 return 1;
1134 }
1135 return 0;
718e3744 1136}
6b0655a2 1137
d62a17ae 1138static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1139 struct attr *attr, afi_t afi, safi_t safi,
1140 const char *rmap_name)
718e3744 1141{
d62a17ae 1142 struct bgp_filter *filter;
1143 struct bgp_info info;
1144 route_map_result_t ret;
1145 struct route_map *rmap = NULL;
718e3744 1146
d62a17ae 1147 filter = &peer->filter[afi][safi];
718e3744 1148
d62a17ae 1149 /* Apply default weight value. */
1150 if (peer->weight[afi][safi])
1151 attr->weight = peer->weight[afi][safi];
718e3744 1152
d62a17ae 1153 if (rmap_name) {
1154 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1155
d62a17ae 1156 if (rmap == NULL)
1157 return RMAP_DENY;
1158 } else {
1159 if (ROUTE_MAP_IN_NAME(filter)) {
1160 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1161
d62a17ae 1162 if (rmap == NULL)
1163 return RMAP_DENY;
1164 }
1165 }
0b16f239 1166
d62a17ae 1167 /* Route map apply. */
1168 if (rmap) {
1169 /* Duplicate current value to new strucutre for modification. */
1170 info.peer = peer;
1171 info.attr = attr;
718e3744 1172
d62a17ae 1173 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1174
d62a17ae 1175 /* Apply BGP route map to the attribute. */
1176 ret = route_map_apply(rmap, p, RMAP_BGP, &info);
0b16f239 1177
d62a17ae 1178 peer->rmap_type = 0;
0b16f239 1179
d62a17ae 1180 if (ret == RMAP_DENYMATCH) {
1181 /* Free newly generated AS path and community by
1182 * route-map. */
1183 bgp_attr_flush(attr);
1184 return RMAP_DENY;
1185 }
0b16f239 1186 }
d62a17ae 1187 return RMAP_PERMIT;
0b16f239
DS
1188}
1189
d62a17ae 1190static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1191 struct attr *attr, afi_t afi, safi_t safi,
1192 const char *rmap_name)
0b16f239 1193{
d62a17ae 1194 struct bgp_info info;
1195 route_map_result_t ret;
1196 struct route_map *rmap = NULL;
d7c0a89a 1197 uint8_t rmap_type;
0b16f239 1198
b787157a
DS
1199 /*
1200 * So if we get to this point and have no rmap_name
1201 * we want to just show the output as it currently
1202 * exists.
1203 */
1204 if (!rmap_name)
1205 return RMAP_PERMIT;
0b16f239 1206
d62a17ae 1207 /* Apply default weight value. */
1208 if (peer->weight[afi][safi])
1209 attr->weight = peer->weight[afi][safi];
0b16f239 1210
b787157a 1211 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1212
b787157a
DS
1213 /*
1214 * If we have a route map name and we do not find
1215 * the routemap that means we have an implicit
1216 * deny.
1217 */
1218 if (rmap == NULL)
1219 return RMAP_DENY;
0b16f239 1220
d62a17ae 1221 /* Route map apply. */
b787157a
DS
1222 /* Duplicate current value to new strucutre for modification. */
1223 info.peer = peer;
1224 info.attr = attr;
0b16f239 1225
0f672529 1226 rmap_type = peer->rmap_type;
b787157a 1227 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1228
b787157a
DS
1229 /* Apply BGP route map to the attribute. */
1230 ret = route_map_apply(rmap, p, RMAP_BGP, &info);
ac41b2a2 1231
0f672529 1232 peer->rmap_type = rmap_type;
b787157a
DS
1233
1234 if (ret == RMAP_DENYMATCH)
1235 /*
1236 * caller has multiple error paths with bgp_attr_flush()
1237 */
1238 return RMAP_DENY;
ac41b2a2 1239
d62a17ae 1240 return RMAP_PERMIT;
718e3744 1241}
6b0655a2 1242
5000f21c 1243/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1244static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1245 struct peer *peer, struct attr *attr)
1246{
1247 if (peer->sort == BGP_PEER_EBGP
1248 && (peer_af_flag_check(peer, afi, safi,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1250 || peer_af_flag_check(peer, afi, safi,
1251 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1252 || peer_af_flag_check(peer, afi, safi,
1253 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1254 || peer_af_flag_check(peer, afi, safi,
1255 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1256 // Take action on the entire aspath
1257 if (peer_af_flag_check(peer, afi, safi,
1258 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1259 || peer_af_flag_check(peer, afi, safi,
1260 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1261 if (peer_af_flag_check(
1262 peer, afi, safi,
1263 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1264 attr->aspath = aspath_replace_private_asns(
1265 attr->aspath, bgp->as);
1266
1267 // The entire aspath consists of private ASNs so create
1268 // an empty aspath
1269 else if (aspath_private_as_check(attr->aspath))
1270 attr->aspath = aspath_empty_get();
1271
1272 // There are some public and some private ASNs, remove
1273 // the private ASNs
1274 else
1275 attr->aspath = aspath_remove_private_asns(
1276 attr->aspath);
1277 }
1278
1279 // 'all' was not specified so the entire aspath must be private
1280 // ASNs
1281 // for us to do anything
1282 else if (aspath_private_as_check(attr->aspath)) {
1283 if (peer_af_flag_check(
1284 peer, afi, safi,
1285 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1286 attr->aspath = aspath_replace_private_asns(
1287 attr->aspath, bgp->as);
1288 else
1289 attr->aspath = aspath_empty_get();
1290 }
1291 }
5000f21c
DS
1292}
1293
c7122e14 1294/* If this is an EBGP peer with as-override */
d62a17ae 1295static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1296 struct peer *peer, struct attr *attr)
1297{
1298 if (peer->sort == BGP_PEER_EBGP
1299 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1300 if (aspath_single_asn_check(attr->aspath, peer->as))
1301 attr->aspath = aspath_replace_specific_asn(
1302 attr->aspath, peer->as, bgp->as);
1303 }
1304}
1305
7f323236
DW
1306void bgp_attr_add_gshut_community(struct attr *attr)
1307{
1308 struct community *old;
1309 struct community *new;
1310 struct community *merge;
1311 struct community *gshut;
1312
1313 old = attr->community;
1314 gshut = community_str2com("graceful-shutdown");
1315
1316 if (old) {
1317 merge = community_merge(community_dup(old), gshut);
1318
a4d82a8a 1319 if (old->refcnt == 0)
7f323236
DW
1320 community_free(old);
1321
1322 new = community_uniq_sort(merge);
1323 community_free(merge);
1324 } else {
1325 new = community_dup(gshut);
1326 }
1327
1328 community_free(gshut);
1329 attr->community = new;
1330 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1331
1332 /* When we add the graceful-shutdown community we must also
1333 * lower the local-preference */
1334 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1335 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1336}
1337
1338
d7c0a89a 1339static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1340{
960035b2 1341 if (family == AF_INET) {
d62a17ae 1342 attr->nexthop.s_addr = 0;
960035b2
PZ
1343 attr->mp_nexthop_global_in.s_addr = 0;
1344 }
d62a17ae 1345 if (family == AF_INET6)
1346 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1347 if (family == AF_EVPN)
1348 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1349}
1350
d62a17ae 1351int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
1352 struct update_subgroup *subgrp, struct prefix *p,
1353 struct attr *attr)
1354{
1355 struct bgp_filter *filter;
1356 struct peer *from;
1357 struct peer *peer;
1358 struct peer *onlypeer;
1359 struct bgp *bgp;
1360 struct attr *riattr;
d62a17ae 1361 char buf[PREFIX_STRLEN];
1362 int ret;
1363 int transparent;
1364 int reflect;
1365 afi_t afi;
1366 safi_t safi;
1367 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1368
1369 if (DISABLE_BGP_ANNOUNCE)
1370 return 0;
1371
1372 afi = SUBGRP_AFI(subgrp);
1373 safi = SUBGRP_SAFI(subgrp);
1374 peer = SUBGRP_PEER(subgrp);
1375 onlypeer = NULL;
1376 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1377 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1378
1379 from = ri->peer;
1380 filter = &peer->filter[afi][safi];
1381 bgp = SUBGRP_INST(subgrp);
1382 riattr = bgp_info_mpath_count(ri) ? bgp_info_mpath_attr(ri) : ri->attr;
3f9c7369 1383
65efcfce 1384#if ENABLE_BGP_VNC
d62a17ae 1385 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1386 && ((ri->type == ZEBRA_ROUTE_BGP_DIRECT)
1387 || (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1388
1389 /*
1390 * direct and direct_ext type routes originate internally even
1391 * though they can have peer pointers that reference other
1392 * systems
1393 */
1394 prefix2str(p, buf, PREFIX_STRLEN);
1395 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1396 __func__, buf);
1397 samepeer_safe = 1;
1398 }
65efcfce
LB
1399#endif
1400
ddb5b488
PZ
1401 if (((afi == AFI_IP) || (afi == AFI_IP6))
1402 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
1403 && (ri->type == ZEBRA_ROUTE_BGP)
1404 && (ri->sub_type == BGP_ROUTE_IMPORTED)) {
1405
1406 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1407
1408 samepeer_safe = 1;
1409 }
1410
d62a17ae 1411 /* With addpath we may be asked to TX all kinds of paths so make sure
1412 * ri is valid */
1413 if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID)
1414 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)
1415 || CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
1416 return 0;
1417 }
adbac85e 1418
d62a17ae 1419 /* If this is not the bestpath then check to see if there is an enabled
1420 * addpath
1421 * feature that requires us to advertise it */
1422 if (!CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
1423 if (!bgp_addpath_tx_path(peer, afi, safi, ri)) {
1424 return 0;
1425 }
1426 }
06370dac 1427
d62a17ae 1428 /* Aggregate-address suppress check. */
1429 if (ri->extra && ri->extra->suppress)
1430 if (!UNSUPPRESS_MAP_NAME(filter)) {
1431 return 0;
1432 }
3f9c7369 1433
13b7e7f0
DS
1434 /*
1435 * If we are doing VRF 2 VRF leaking via the import
1436 * statement, we want to prevent the route going
1437 * off box as that the RT and RD created are localy
1438 * significant and globaly useless.
1439 */
1440 if (safi == SAFI_MPLS_VPN && ri->extra && ri->extra->num_labels
1441 && ri->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
1442 return 0;
1443
d62a17ae 1444 /* If it's labeled safi, make sure the route has a valid label. */
1445 if (safi == SAFI_LABELED_UNICAST) {
1446 mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi);
1447 if (!bgp_is_valid_label(&label)) {
1448 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1449 zlog_debug("u%" PRIu64 ":s%" PRIu64
1450 " %s/%d is filtered - no label (%p)",
1451 subgrp->update_group->id, subgrp->id,
1452 inet_ntop(p->family, &p->u.prefix,
1453 buf, SU_ADDRSTRLEN),
1454 p->prefixlen, &label);
1455 return 0;
1456 }
1457 }
cd1964ff 1458
d62a17ae 1459 /* Do not send back route to sender. */
1460 if (onlypeer && from == onlypeer) {
1461 return 0;
1462 }
3f9c7369 1463
d62a17ae 1464 /* Do not send the default route in the BGP table if the neighbor is
1465 * configured for default-originate */
1466 if (CHECK_FLAG(peer->af_flags[afi][safi],
1467 PEER_FLAG_DEFAULT_ORIGINATE)) {
1468 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1469 return 0;
1470 else if (p->family == AF_INET6 && p->prefixlen == 0)
1471 return 0;
1472 }
4125bb67 1473
d62a17ae 1474 /* Transparency check. */
1475 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1476 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1477 transparent = 1;
1478 else
1479 transparent = 0;
1480
1481 /* If community is not disabled check the no-export and local. */
1482 if (!transparent && bgp_community_filter(peer, riattr)) {
1483 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1484 zlog_debug(
1485 "subgrpannouncecheck: community filter check fail");
1486 return 0;
1487 }
3f9c7369 1488
d62a17ae 1489 /* If the attribute has originator-id and it is same as remote
1490 peer's id. */
1491 if (onlypeer && riattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1492 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &riattr->originator_id))) {
1493 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1494 zlog_debug(
1495 "%s [Update:SEND] %s originator-id is same as "
1496 "remote router-id",
1497 onlypeer->host,
1498 prefix2str(p, buf, sizeof(buf)));
1499 return 0;
1500 }
3f9c7369 1501
d62a17ae 1502 /* ORF prefix-list filter check */
1503 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1504 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1505 || CHECK_FLAG(peer->af_cap[afi][safi],
1506 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1507 if (peer->orf_plist[afi][safi]) {
1508 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1509 == PREFIX_DENY) {
1510 if (bgp_debug_update(NULL, p,
1511 subgrp->update_group, 0))
1512 zlog_debug(
1513 "%s [Update:SEND] %s is filtered via ORF",
1514 peer->host,
1515 prefix2str(p, buf,
1516 sizeof(buf)));
1517 return 0;
1518 }
1519 }
1520
1521 /* Output filter check. */
1522 if (bgp_output_filter(peer, p, riattr, afi, safi) == FILTER_DENY) {
1523 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1524 zlog_debug("%s [Update:SEND] %s is filtered",
1525 peer->host, prefix2str(p, buf, sizeof(buf)));
1526 return 0;
1527 }
3f9c7369
DS
1528
1529#ifdef BGP_SEND_ASPATH_CHECK
d62a17ae 1530 /* AS path loop check. */
1531 if (onlypeer && aspath_loop_check(riattr->aspath, onlypeer->as)) {
1532 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1533 zlog_debug(
1534 "%s [Update:SEND] suppress announcement to peer AS %u "
1535 "that is part of AS path.",
1536 onlypeer->host, onlypeer->as);
1537 return 0;
1538 }
3f9c7369
DS
1539#endif /* BGP_SEND_ASPATH_CHECK */
1540
d62a17ae 1541 /* If we're a CONFED we need to loop check the CONFED ID too */
1542 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1543 if (aspath_loop_check(riattr->aspath, bgp->confed_id)) {
1544 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1545 zlog_debug(
1546 "%s [Update:SEND] suppress announcement to peer AS %u"
1547 " is AS path.",
1548 peer->host, bgp->confed_id);
1549 return 0;
1550 }
3f9c7369 1551 }
3f9c7369 1552
d62a17ae 1553 /* Route-Reflect check. */
1554 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1555 reflect = 1;
1556 else
1557 reflect = 0;
1558
1559 /* IBGP reflection check. */
1560 if (reflect && !samepeer_safe) {
1561 /* A route from a Client peer. */
1562 if (CHECK_FLAG(from->af_flags[afi][safi],
1563 PEER_FLAG_REFLECTOR_CLIENT)) {
1564 /* Reflect to all the Non-Client peers and also to the
1565 Client peers other than the originator. Originator
1566 check
1567 is already done. So there is noting to do. */
1568 /* no bgp client-to-client reflection check. */
1569 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1570 if (CHECK_FLAG(peer->af_flags[afi][safi],
1571 PEER_FLAG_REFLECTOR_CLIENT))
1572 return 0;
1573 } else {
1574 /* A route from a Non-client peer. Reflect to all other
1575 clients. */
1576 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1577 PEER_FLAG_REFLECTOR_CLIENT))
1578 return 0;
1579 }
1580 }
3f9c7369 1581
d62a17ae 1582 /* For modify attribute, copy it to temporary structure. */
1583 bgp_attr_dup(attr, riattr);
1584
1585 /* If local-preference is not set. */
1586 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1587 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1588 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1589 attr->local_pref = bgp->default_local_pref;
3f9c7369 1590 }
3f9c7369 1591
d62a17ae 1592 /* If originator-id is not set and the route is to be reflected,
1593 set the originator id */
1594 if (reflect
1595 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1596 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1597 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1598 }
3f9c7369 1599
d62a17ae 1600 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1601 */
1602 if (peer->sort == BGP_PEER_EBGP
1603 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1604 if (from != bgp->peer_self && !transparent
1605 && !CHECK_FLAG(peer->af_flags[afi][safi],
1606 PEER_FLAG_MED_UNCHANGED))
1607 attr->flag &=
1608 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1609 }
3f9c7369 1610
d62a17ae 1611 /* Since the nexthop attribute can vary per peer, it is not explicitly
1612 * set
1613 * in announce check, only certain flags and length (or number of
1614 * nexthops
1615 * -- for IPv6/MP_REACH) are set here in order to guide the update
1616 * formation
1617 * code in setting the nexthop(s) on a per peer basis in
1618 * reformat_peer().
1619 * Typically, the source nexthop in the attribute is preserved but in
1620 * the
1621 * scenarios where we know it will always be overwritten, we reset the
1622 * nexthop to "0" in an attempt to achieve better Update packing. An
1623 * example of this is when a prefix from each of 2 IBGP peers needs to
1624 * be
1625 * announced to an EBGP peer (and they have the same attributes barring
1626 * their nexthop).
1627 */
1628 if (reflect)
1629 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1630
1631#define NEXTHOP_IS_V6 \
1632 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1633 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1634 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1635 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1636
1637 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1638 * if
1639 * the peer (group) is configured to receive link-local nexthop
1640 * unchanged
1641 * and it is available in the prefix OR we're not reflecting the route
1642 * and
1643 * the peer (group) to whom we're going to announce is on a shared
1644 * network
1645 * and this is either a self-originated route or the peer is EBGP.
1646 */
1647 if (NEXTHOP_IS_V6) {
1648 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1649 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1650 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1651 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
1652 || (!reflect && peer->shared_network
1653 && (from == bgp->peer_self
1654 || peer->sort == BGP_PEER_EBGP))) {
1655 attr->mp_nexthop_len =
1656 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1657 }
3f9c7369 1658
d62a17ae 1659 /* Clear off link-local nexthop in source, whenever it is not
1660 * needed to
1661 * ensure more prefixes share the same attribute for
1662 * announcement.
1663 */
1664 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1665 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1666 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1667 }
3f9c7369 1668
d62a17ae 1669 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1670 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1671
1672 /* Route map & unsuppress-map apply. */
1673 if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) {
1674 struct bgp_info info;
16f7ce2b 1675 struct bgp_info_extra dummy_info_extra;
d62a17ae 1676 struct attr dummy_attr;
1677
1678 info.peer = peer;
1679 info.attr = attr;
d37ba549 1680
16f7ce2b
MK
1681 if (ri->extra) {
1682 memcpy(&dummy_info_extra, ri->extra,
1683 sizeof(struct bgp_info_extra));
1684 info.extra = &dummy_info_extra;
1685 }
1686
d62a17ae 1687 /* don't confuse inbound and outbound setting */
1688 RESET_FLAG(attr->rmap_change_flags);
1689
1690 /*
1691 * The route reflector is not allowed to modify the attributes
1692 * of the reflected IBGP routes unless explicitly allowed.
1693 */
1694 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1695 && !bgp_flag_check(bgp,
1696 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1697 bgp_attr_dup(&dummy_attr, attr);
1698 info.attr = &dummy_attr;
1699 }
3f9c7369 1700
d62a17ae 1701 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1702
d62a17ae 1703 if (ri->extra && ri->extra->suppress)
1704 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1705 RMAP_BGP, &info);
1706 else
1707 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1708 RMAP_BGP, &info);
1709
1710 peer->rmap_type = 0;
1711
1712 if (ret == RMAP_DENYMATCH) {
1713 bgp_attr_flush(attr);
1714 return 0;
1715 }
3f9c7369 1716 }
3f9c7369 1717
7f323236 1718 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1719 if (peer->sort == BGP_PEER_IBGP
1720 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1721 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1722 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1723 } else {
1724 bgp_attr_add_gshut_community(attr);
1725 }
1726 }
1727
d62a17ae 1728 /* After route-map has been applied, we check to see if the nexthop to
1729 * be carried in the attribute (that is used for the announcement) can
1730 * be cleared off or not. We do this in all cases where we would be
1731 * setting the nexthop to "ourselves". For IPv6, we only need to
1732 * consider
1733 * the global nexthop here; the link-local nexthop would have been
1734 * cleared
1735 * already, and if not, it is required by the update formation code.
1736 * Also see earlier comments in this function.
1737 */
1738 /*
1739 * If route-map has performed some operation on the nexthop or the peer
1740 * configuration says to pass it unchanged, we cannot reset the nexthop
1741 * here, so only attempt to do it if these aren't true. Note that the
1742 * route-map handler itself might have cleared the nexthop, if for
1743 * example,
1744 * it is configured as 'peer-address'.
1745 */
1746 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
1747 riattr->rmap_change_flags)
1748 && !transparent
1749 && !CHECK_FLAG(peer->af_flags[afi][safi],
1750 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1751 /* We can reset the nexthop, if setting (or forcing) it to
1752 * 'self' */
1753 if (CHECK_FLAG(peer->af_flags[afi][safi],
1754 PEER_FLAG_NEXTHOP_SELF)
1755 || CHECK_FLAG(peer->af_flags[afi][safi],
1756 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1757 if (!reflect
1758 || CHECK_FLAG(peer->af_flags[afi][safi],
1759 PEER_FLAG_FORCE_NEXTHOP_SELF))
1760 subgroup_announce_reset_nhop(
1761 (peer_cap_enhe(peer, afi, safi)
1762 ? AF_INET6
1763 : p->family),
1764 attr);
1765 } else if (peer->sort == BGP_PEER_EBGP) {
1766 /* Can also reset the nexthop if announcing to EBGP, but
1767 * only if
1768 * no peer in the subgroup is on a shared subnet.
1769 * Note: 3rd party nexthop currently implemented for
1770 * IPv4 only.
1771 */
65d4e0c6
DS
1772 if (!bgp_subgrp_multiaccess_check_v4(riattr->nexthop,
1773 subgrp))
d62a17ae 1774 subgroup_announce_reset_nhop(
1775 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
1776 ? AF_INET6
1777 : p->family),
d62a17ae 1778 attr);
960035b2
PZ
1779 } else if (CHECK_FLAG(ri->flags, BGP_INFO_ANNC_NH_SELF)) {
1780 /*
1781 * This flag is used for leaked vpn-vrf routes
1782 */
1783 int family = p->family;
1784
1785 if (peer_cap_enhe(peer, afi, safi))
1786 family = AF_INET6;
1787
1788 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1789 zlog_debug(
1790 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1791 __func__, family2str(family));
1792 subgroup_announce_reset_nhop(family, attr);
d62a17ae 1793 }
960035b2 1794
d62a17ae 1795 /* If IPv6/MP and nexthop does not have any override and happens
1796 * to
1797 * be a link-local address, reset it so that we don't pass along
1798 * the
1799 * source's link-local IPv6 address to recipients who may not be
1800 * on
1801 * the same interface.
1802 */
1803 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1804 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1805 subgroup_announce_reset_nhop(AF_INET6, attr);
1806 }
1807 }
3f9c7369 1808
d62a17ae 1809 return 1;
3f9c7369
DS
1810}
1811
d62a17ae 1812void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1813 struct bgp_maxpaths_cfg *mpath_cfg,
1814 struct bgp_info_pair *result, afi_t afi, safi_t safi)
1815{
1816 struct bgp_info *new_select;
1817 struct bgp_info *old_select;
1818 struct bgp_info *ri;
1819 struct bgp_info *ri1;
1820 struct bgp_info *ri2;
1821 struct bgp_info *nextri = NULL;
1822 int paths_eq, do_mpath, debug;
1823 struct list mp_list;
1824 char pfx_buf[PREFIX2STR_BUFFER];
1825 char path_buf[PATH_ADDPATH_STR_BUFFER];
1826
1827 bgp_mp_list_init(&mp_list);
1828 do_mpath =
1829 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1830
1831 debug = bgp_debug_bestpath(&rn->p);
1832
1833 if (debug)
1834 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1835
1836 /* bgp deterministic-med */
1837 new_select = NULL;
1838 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1839
1840 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1841 for (ri1 = rn->info; ri1; ri1 = ri1->next)
1842 bgp_info_unset_flag(rn, ri1, BGP_INFO_DMED_SELECTED);
1843
1844 for (ri1 = rn->info; ri1; ri1 = ri1->next) {
1845 if (CHECK_FLAG(ri1->flags, BGP_INFO_DMED_CHECK))
1846 continue;
1847 if (BGP_INFO_HOLDDOWN(ri1))
1848 continue;
1849 if (ri1->peer && ri1->peer != bgp->peer_self)
1850 if (ri1->peer->status != Established)
1851 continue;
1852
1853 new_select = ri1;
1854 if (ri1->next) {
1855 for (ri2 = ri1->next; ri2; ri2 = ri2->next) {
1856 if (CHECK_FLAG(ri2->flags,
1857 BGP_INFO_DMED_CHECK))
1858 continue;
1859 if (BGP_INFO_HOLDDOWN(ri2))
1860 continue;
1861 if (ri2->peer
1862 && ri2->peer != bgp->peer_self
1863 && !CHECK_FLAG(
1864 ri2->peer->sflags,
1865 PEER_STATUS_NSF_WAIT))
1866 if (ri2->peer->status
1867 != Established)
1868 continue;
1869
1870 if (aspath_cmp_left(ri1->attr->aspath,
1871 ri2->attr->aspath)
1872 || aspath_cmp_left_confed(
1873 ri1->attr->aspath,
1874 ri2->attr->aspath)) {
1875 if (bgp_info_cmp(bgp, ri2,
1876 new_select,
1877 &paths_eq,
1878 mpath_cfg,
1879 debug, pfx_buf,
1880 afi, safi)) {
1881 bgp_info_unset_flag(
1882 rn, new_select,
1883 BGP_INFO_DMED_SELECTED);
1884 new_select = ri2;
1885 }
1886
1887 bgp_info_set_flag(
1888 rn, ri2,
1889 BGP_INFO_DMED_CHECK);
1890 }
1891 }
1892 }
1893 bgp_info_set_flag(rn, new_select, BGP_INFO_DMED_CHECK);
1894 bgp_info_set_flag(rn, new_select,
1895 BGP_INFO_DMED_SELECTED);
1896
1897 if (debug) {
1898 bgp_info_path_with_addpath_rx_str(new_select,
1899 path_buf);
c66faab1 1900 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 1901 pfx_buf, path_buf,
1902 aspath_get_first_as(
1903 new_select->attr->aspath));
1904 }
1905 }
1906 }
96450faf 1907
d62a17ae 1908 /* Check old selected route and new selected route. */
1909 old_select = NULL;
1910 new_select = NULL;
1911 for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1);
1912 ri = nextri) {
1913 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED))
1914 old_select = ri;
1915
1916 if (BGP_INFO_HOLDDOWN(ri)) {
1917 /* reap REMOVED routes, if needs be
1918 * selected route must stay for a while longer though
1919 */
1920 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
1921 && (ri != old_select))
1922 bgp_info_reap(rn, ri);
1923
ddb5b488
PZ
1924 if (debug)
1925 zlog_debug("%s: ri %p in holddown", __func__,
1926 ri);
1927
d62a17ae 1928 continue;
1929 }
96450faf 1930
d62a17ae 1931 if (ri->peer && ri->peer != bgp->peer_self
1932 && !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT))
ddb5b488
PZ
1933 if (ri->peer->status != Established) {
1934
1935 if (debug)
1936 zlog_debug(
1937 "%s: ri %p non self peer %s not estab state",
1938 __func__, ri, ri->peer->host);
1939
d62a17ae 1940 continue;
ddb5b488 1941 }
9fbdd100 1942
d62a17ae 1943 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
1944 && (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) {
1945 bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
ddb5b488
PZ
1946 if (debug)
1947 zlog_debug("%s: ri %p dmed", __func__, ri);
d62a17ae 1948 continue;
1949 }
9fbdd100 1950
d62a17ae 1951 bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
06370dac 1952
d62a17ae 1953 if (bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg,
1954 debug, pfx_buf, afi, safi)) {
1955 new_select = ri;
1956 }
1957 }
718e3744 1958
d62a17ae 1959 /* Now that we know which path is the bestpath see if any of the other
1960 * paths
1961 * qualify as multipaths
1962 */
1963 if (debug) {
1964 if (new_select)
1965 bgp_info_path_with_addpath_rx_str(new_select, path_buf);
1966 else
1967 sprintf(path_buf, "NONE");
1968 zlog_debug(
1969 "%s: After path selection, newbest is %s oldbest was %s",
1970 pfx_buf, path_buf,
1971 old_select ? old_select->peer->host : "NONE");
96450faf 1972 }
9fbdd100 1973
d62a17ae 1974 if (do_mpath && new_select) {
1975 for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1);
1976 ri = nextri) {
1977
1978 if (debug)
1979 bgp_info_path_with_addpath_rx_str(ri, path_buf);
1980
1981 if (ri == new_select) {
1982 if (debug)
1983 zlog_debug(
1984 "%s: %s is the bestpath, add to the multipath list",
1985 pfx_buf, path_buf);
1986 bgp_mp_list_add(&mp_list, ri);
1987 continue;
1988 }
1989
1990 if (BGP_INFO_HOLDDOWN(ri))
1991 continue;
1992
1993 if (ri->peer && ri->peer != bgp->peer_self
1994 && !CHECK_FLAG(ri->peer->sflags,
1995 PEER_STATUS_NSF_WAIT))
1996 if (ri->peer->status != Established)
1997 continue;
1998
1999 if (!bgp_info_nexthop_cmp(ri, new_select)) {
2000 if (debug)
2001 zlog_debug(
2002 "%s: %s has the same nexthop as the bestpath, skip it",
2003 pfx_buf, path_buf);
2004 continue;
2005 }
2006
2007 bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg,
2008 debug, pfx_buf, afi, safi);
2009
2010 if (paths_eq) {
2011 if (debug)
2012 zlog_debug(
2013 "%s: %s is equivalent to the bestpath, add to the multipath list",
2014 pfx_buf, path_buf);
2015 bgp_mp_list_add(&mp_list, ri);
2016 }
2017 }
2018 }
fee0f4c6 2019
d62a17ae 2020 bgp_info_mpath_update(rn, new_select, old_select, &mp_list, mpath_cfg);
2021 bgp_info_mpath_aggregate_update(new_select, old_select);
2022 bgp_mp_list_clear(&mp_list);
96450faf 2023
d62a17ae 2024 result->old = old_select;
2025 result->new = new_select;
96450faf 2026
d62a17ae 2027 return;
fee0f4c6 2028}
2029
3f9c7369
DS
2030/*
2031 * A new route/change in bestpath of an existing route. Evaluate the path
2032 * for advertisement to the subgroup.
2033 */
d62a17ae 2034int subgroup_process_announce_selected(struct update_subgroup *subgrp,
2035 struct bgp_info *selected,
2036 struct bgp_node *rn,
d7c0a89a 2037 uint32_t addpath_tx_id)
d62a17ae 2038{
2039 struct prefix *p;
2040 struct peer *onlypeer;
2041 struct attr attr;
2042 afi_t afi;
2043 safi_t safi;
adbac85e 2044
d62a17ae 2045 p = &rn->p;
2046 afi = SUBGRP_AFI(subgrp);
2047 safi = SUBGRP_SAFI(subgrp);
2048 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2049 : NULL);
2050
e0207895
PZ
2051 if (BGP_DEBUG(update, UPDATE_OUT)) {
2052 char buf_prefix[PREFIX_STRLEN];
2053 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2054 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2055 selected);
e0207895
PZ
2056 }
2057
d62a17ae 2058 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2059 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2060 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2061 return 0;
2062
2063 memset(&attr, 0, sizeof(struct attr));
2064 /* It's initialized in bgp_announce_check() */
2065
2066 /* Announcement to the subgroup. If the route is filtered withdraw it.
2067 */
2068 if (selected) {
2069 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2070 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2071 else
2072 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
2073 selected->addpath_tx_id);
2074 }
2075
2076 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2077 else {
2078 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2079 }
558d1fec 2080
d62a17ae 2081 return 0;
200df115 2082}
fee0f4c6 2083
3064bf43 2084/*
e1072051 2085 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2086 * This is called at the end of route processing.
3064bf43 2087 */
d62a17ae 2088void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2089{
d62a17ae 2090 struct bgp_info *ri;
3064bf43 2091
d62a17ae 2092 for (ri = rn->info; ri; ri = ri->next) {
2093 if (BGP_INFO_HOLDDOWN(ri))
2094 continue;
2095 UNSET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
2096 UNSET_FLAG(ri->flags, BGP_INFO_ATTR_CHANGED);
2097 }
3064bf43 2098}
2099
2100/*
2101 * Has the route changed from the RIB's perspective? This is invoked only
2102 * if the route selection returns the same best route as earlier - to
2103 * determine if we need to update zebra or not.
2104 */
d62a17ae 2105int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected)
2106{
2107 struct bgp_info *mpinfo;
2108
2bb9eff4
DS
2109 /* If this is multipath, check all selected paths for any nexthop
2110 * change or attribute change. Some attribute changes (e.g., community)
2111 * aren't of relevance to the RIB, but we'll update zebra to ensure
2112 * we handle the case of BGP nexthop change. This is the behavior
2113 * when the best path has an attribute change anyway.
d62a17ae 2114 */
2115 if (CHECK_FLAG(selected->flags, BGP_INFO_IGP_CHANGED)
2116 || CHECK_FLAG(selected->flags, BGP_INFO_MULTIPATH_CHG))
2117 return 1;
2118
2bb9eff4
DS
2119 /*
2120 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2121 */
2122 for (mpinfo = bgp_info_mpath_first(selected); mpinfo;
2123 mpinfo = bgp_info_mpath_next(mpinfo)) {
2124 if (CHECK_FLAG(mpinfo->flags, BGP_INFO_IGP_CHANGED)
2125 || CHECK_FLAG(mpinfo->flags, BGP_INFO_ATTR_CHANGED))
2126 return 1;
2127 }
3064bf43 2128
d62a17ae 2129 /* Nothing has changed from the RIB's perspective. */
2130 return 0;
3064bf43 2131}
2132
d62a17ae 2133struct bgp_process_queue {
2134 struct bgp *bgp;
a4d82a8a 2135 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2136#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2137 unsigned int flags;
2138 unsigned int queued;
200df115 2139};
2140
3103e8d2
DS
2141/*
2142 * old_select = The old best path
2143 * new_select = the new best path
2144 *
2145 * if (!old_select && new_select)
2146 * We are sending new information on.
2147 *
2148 * if (old_select && new_select) {
2149 * if (new_select != old_select)
2150 * We have a new best path send a change
2151 * else
2152 * We've received a update with new attributes that needs
2153 * to be passed on.
2154 * }
2155 *
2156 * if (old_select && !new_select)
2157 * We have no eligible route that we can announce or the rn
2158 * is being removed.
2159 */
aac24838
JB
2160static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2161 afi_t afi, safi_t safi)
d62a17ae 2162{
d62a17ae 2163 struct prefix *p = &rn->p;
2164 struct bgp_info *new_select;
2165 struct bgp_info *old_select;
2166 struct bgp_info_pair old_and_new;
ddb5b488
PZ
2167 char pfx_buf[PREFIX2STR_BUFFER];
2168 int debug = 0;
d62a17ae 2169
2170 /* Is it end of initial update? (after startup) */
2171 if (!rn) {
2172 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2173 sizeof(bgp->update_delay_zebra_resume_time));
2174
2175 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2176 FOREACH_AFI_SAFI (afi, safi) {
2177 if (bgp_fibupd_safi(safi))
2178 bgp_zebra_announce_table(bgp, afi, safi);
2179 }
d62a17ae 2180 bgp->main_peers_update_hold = 0;
2181
2182 bgp_start_routeadv(bgp);
aac24838 2183 return;
d62a17ae 2184 }
cb1faec9 2185
ddb5b488
PZ
2186 debug = bgp_debug_bestpath(&rn->p);
2187 if (debug) {
2188 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2189 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2190 afi2str(afi), safi2str(safi));
2191 }
2192
d62a17ae 2193 /* Best path selection. */
2194 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2195 afi, safi);
2196 old_select = old_and_new.old;
2197 new_select = old_and_new.new;
2198
2199 /* Do we need to allocate or free labels?
2200 * Right now, since we only deal with per-prefix labels, it is not
cb499ebb 2201 * necessary to do this upon changes to best path except if the label
09fdc88c 2202 * index changes
d62a17ae 2203 */
318cac96 2204 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2205 if (new_select) {
2206 if (!old_select
2207 || bgp_label_index_differs(new_select, old_select)
2208 || new_select->sub_type != old_select->sub_type) {
2209 if (new_select->sub_type == BGP_ROUTE_STATIC
2210 && new_select->attr->flag
2211 & ATTR_FLAG_BIT(
2212 BGP_ATTR_PREFIX_SID)
2213 && new_select->attr->label_index
2214 != BGP_INVALID_LABEL_INDEX) {
2215 if (CHECK_FLAG(
2216 rn->flags,
2217 BGP_NODE_REGISTERED_FOR_LABEL))
2218 bgp_unregister_for_label(rn);
70e98a7f 2219 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2220 &rn->local_label);
2221 bgp_set_valid_label(&rn->local_label);
2222 } else
2223 bgp_register_for_label(rn, new_select);
2224 }
a4d82a8a
PZ
2225 } else if (CHECK_FLAG(rn->flags,
2226 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2227 bgp_unregister_for_label(rn);
318cac96
DW
2228 }
2229 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2230 bgp_unregister_for_label(rn);
d62a17ae 2231 }
cd1964ff 2232
ddb5b488
PZ
2233 if (debug) {
2234 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2235 zlog_debug(
2236 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2237 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2238 old_select, new_select);
2239 }
2240
d62a17ae 2241 /* If best route remains the same and this is not due to user-initiated
2242 * clear, see exactly what needs to be done.
2243 */
d62a17ae 2244 if (old_select && old_select == new_select
2245 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
2246 && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
2247 && !bgp->addpath_tx_used[afi][safi]) {
2248 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2249#if ENABLE_BGP_VNC
d62a17ae 2250 vnc_import_bgp_add_route(bgp, p, old_select);
2251 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2252#endif
bb744275 2253 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2254 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2255
2256 if (new_select->type == ZEBRA_ROUTE_BGP
2257 && (new_select->sub_type == BGP_ROUTE_NORMAL
2258 || new_select->sub_type
2259 == BGP_ROUTE_IMPORTED))
2260
2261 bgp_zebra_announce(rn, p, old_select,
2262 bgp, afi, safi);
2263 }
d62a17ae 2264 }
2265 UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
2266 bgp_zebra_clear_route_change_flags(rn);
2267
2268 /* If there is a change of interest to peers, reannounce the
2269 * route. */
2270 if (CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
2271 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2272 group_announce_route(bgp, afi, safi, rn, new_select);
2273
2274 /* unicast routes must also be annouced to
2275 * labeled-unicast update-groups */
2276 if (safi == SAFI_UNICAST)
2277 group_announce_route(bgp, afi,
2278 SAFI_LABELED_UNICAST, rn,
2279 new_select);
2280
2281 UNSET_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED);
2282 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2283 }
fee0f4c6 2284
d62a17ae 2285 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2286 return;
d62a17ae 2287 }
8ad7271d 2288
d62a17ae 2289 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2290 */
2291 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2292
2293 /* bestpath has changed; bump version */
2294 if (old_select || new_select) {
2295 bgp_bump_version(rn);
2296
2297 if (!bgp->t_rmap_def_originate_eval) {
2298 bgp_lock(bgp);
2299 thread_add_timer(
2300 bm->master,
2301 update_group_refresh_default_originate_route_map,
2302 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2303 &bgp->t_rmap_def_originate_eval);
2304 }
2305 }
3f9c7369 2306
d62a17ae 2307 if (old_select)
2308 bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
2309 if (new_select) {
ddb5b488
PZ
2310 if (debug)
2311 zlog_debug("%s: setting SELECTED flag", __func__);
d62a17ae 2312 bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
2313 bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
2314 UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
2315 }
338b3424 2316
65efcfce 2317#if ENABLE_BGP_VNC
d62a17ae 2318 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2319 if (old_select != new_select) {
2320 if (old_select) {
2321 vnc_import_bgp_exterior_del_route(bgp, p,
2322 old_select);
2323 vnc_import_bgp_del_route(bgp, p, old_select);
2324 }
2325 if (new_select) {
2326 vnc_import_bgp_exterior_add_route(bgp, p,
2327 new_select);
2328 vnc_import_bgp_add_route(bgp, p, new_select);
2329 }
2330 }
2331 }
65efcfce
LB
2332#endif
2333
d62a17ae 2334 group_announce_route(bgp, afi, safi, rn, new_select);
2335
2336 /* unicast routes must also be annouced to labeled-unicast update-groups
2337 */
2338 if (safi == SAFI_UNICAST)
2339 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2340 new_select);
2341
2342 /* FIB update. */
2343 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2344 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2345 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2346 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2347 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2348 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2349
2350 /* if this is an evpn imported type-5 prefix,
2351 * we need to withdraw the route first to clear
2352 * the nh neigh and the RMAC entry.
2353 */
2354 if (old_select &&
2355 is_route_parent_evpn(old_select))
2356 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2357
d62a17ae 2358 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2359 } else {
d62a17ae 2360 /* Withdraw the route from the kernel. */
2361 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2362 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2363 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2364 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2365
568e10ca 2366 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2367 }
718e3744 2368 }
3064bf43 2369
5424b7ba
MK
2370 /* advertise/withdraw type-5 routes */
2371 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
7b1bf203 2372 if (advertise_type5_routes(bgp, afi) && new_select &&
7e4ed18e
MK
2373 (!new_select->extra || !new_select->extra->parent)) {
2374
2375 /* apply the route-map */
2376 if (bgp->adv_cmd_rmap[afi][safi].map) {
2377 int ret = 0;
2378
3518f352
DS
2379 ret = route_map_apply(
2380 bgp->adv_cmd_rmap[afi][safi].map,
2381 &rn->p, RMAP_BGP, new_select);
7e4ed18e 2382 if (ret == RMAP_MATCH)
3518f352
DS
2383 bgp_evpn_advertise_type5_route(
2384 bgp, &rn->p, new_select->attr,
2385 afi, safi);
7e4ed18e
MK
2386 } else {
2387 bgp_evpn_advertise_type5_route(bgp,
2388 &rn->p,
2389 new_select->attr,
2390 afi, safi);
2391
2392 }
2393 } else if (advertise_type5_routes(bgp, afi) && old_select &&
2394 (!old_select->extra || !old_select->extra->parent))
31310b25 2395 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2396 }
2397
d62a17ae 2398 /* Clear any route change flags. */
2399 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2400
d62a17ae 2401 /* Reap old select bgp_info, if it has been removed */
2402 if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED))
2403 bgp_info_reap(rn, old_select);
2404
2405 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2406 return;
718e3744 2407}
2408
aac24838 2409static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2410{
aac24838
JB
2411 struct bgp_process_queue *pqnode = data;
2412 struct bgp *bgp = pqnode->bgp;
d62a17ae 2413 struct bgp_table *table;
ac021f40 2414 struct bgp_node *rn;
aac24838
JB
2415
2416 /* eoiu marker */
2417 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2418 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2419 /* should always have dedicated wq call */
2420 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2421 return WQ_SUCCESS;
2422 }
2423
ac021f40
LB
2424 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2425 rn = STAILQ_FIRST(&pqnode->pqueue);
2426 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2427 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2428 table = bgp_node_table(rn);
ac021f40 2429 /* note, new RNs may be added as part of processing */
aac24838 2430 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2431
aac24838 2432 bgp_unlock_node(rn);
d62a17ae 2433 bgp_table_unlock(table);
2434 }
aac24838
JB
2435
2436 return WQ_SUCCESS;
2437}
2438
2439static void bgp_processq_del(struct work_queue *wq, void *data)
2440{
2441 struct bgp_process_queue *pqnode = data;
2442
2443 bgp_unlock(pqnode->bgp);
2444
2445 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2446}
2447
d62a17ae 2448void bgp_process_queue_init(void)
200df115 2449{
d62a17ae 2450 if (!bm->process_main_queue) {
2451 bm->process_main_queue =
2452 work_queue_new(bm->master, "process_main_queue");
2453
2454 if (!bm->process_main_queue) {
2455 zlog_err("%s: Failed to allocate work queue", __func__);
2456 exit(1);
2457 }
2458 }
2459
aac24838 2460 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2461 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2462 bm->process_main_queue->spec.max_retries = 0;
2463 bm->process_main_queue->spec.hold = 50;
2464 /* Use a higher yield value of 50ms for main queue processing */
2465 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2466}
2467
cfe8d15a 2468static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2469{
2470 struct bgp_process_queue *pqnode;
2471
a4d82a8a
PZ
2472 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2473 sizeof(struct bgp_process_queue));
aac24838
JB
2474
2475 /* unlocked in bgp_processq_del */
2476 pqnode->bgp = bgp_lock(bgp);
2477 STAILQ_INIT(&pqnode->pqueue);
2478
aac24838
JB
2479 return pqnode;
2480}
2481
d62a17ae 2482void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2483{
aac24838
JB
2484#define ARBITRARY_PROCESS_QLEN 10000
2485 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2486 struct bgp_process_queue *pqnode;
cfe8d15a 2487 int pqnode_reuse = 0;
495f0b13 2488
d62a17ae 2489 /* already scheduled for processing? */
2490 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2491 return;
2e02b9b2 2492
aac24838 2493 if (wq == NULL)
d62a17ae 2494 return;
2495
aac24838 2496 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2497 limit only if is from the same BGP view and it's not an EOIU marker
2498 */
aac24838
JB
2499 if (work_queue_item_count(wq)) {
2500 struct work_queue_item *item = work_queue_last_item(wq);
2501 pqnode = item->data;
228da428 2502
a4d82a8a
PZ
2503 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2504 || pqnode->bgp != bgp
2505 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2506 pqnode = bgp_processq_alloc(bgp);
2507 else
2508 pqnode_reuse = 1;
aac24838 2509 } else
cfe8d15a 2510 pqnode = bgp_processq_alloc(bgp);
aac24838 2511 /* all unlocked in bgp_process_wq */
d62a17ae 2512 bgp_table_lock(bgp_node_table(rn));
aac24838 2513
d62a17ae 2514 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2515 bgp_lock_node(rn);
2516
60466a63
QY
2517 /* can't be enqueued twice */
2518 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2519 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2520 pqnode->queued++;
2521
cfe8d15a
LB
2522 if (!pqnode_reuse)
2523 work_queue_add(wq, pqnode);
2524
d62a17ae 2525 return;
fee0f4c6 2526}
0a486e5f 2527
d62a17ae 2528void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2529{
d62a17ae 2530 struct bgp_process_queue *pqnode;
cb1faec9 2531
d62a17ae 2532 if (bm->process_main_queue == NULL)
2533 return;
2e02b9b2 2534
cfe8d15a 2535 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2536
aac24838 2537 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2538 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2539}
2540
d62a17ae 2541static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2542{
d62a17ae 2543 struct peer *peer;
0a486e5f 2544
d62a17ae 2545 peer = THREAD_ARG(thread);
2546 peer->t_pmax_restart = NULL;
0a486e5f 2547
d62a17ae 2548 if (bgp_debug_neighbor_events(peer))
2549 zlog_debug(
2550 "%s Maximum-prefix restart timer expired, restore peering",
2551 peer->host);
0a486e5f 2552
a9bafa95
DS
2553 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2554 zlog_debug("%s: %s peer_clear failed",
2555 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2556
d62a17ae 2557 return 0;
0a486e5f 2558}
2559
d62a17ae 2560int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2561 int always)
718e3744 2562{
d62a17ae 2563 iana_afi_t pkt_afi;
5c525538 2564 iana_safi_t pkt_safi;
9cabb64b 2565
d62a17ae 2566 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2567 return 0;
e0701b79 2568
d62a17ae 2569 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2570 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2571 PEER_STATUS_PREFIX_LIMIT)
2572 && !always)
2573 return 0;
e0701b79 2574
d62a17ae 2575 zlog_info(
2576 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2577 "limit %ld",
2578 afi_safi_print(afi, safi), peer->host,
2579 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2580 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2581
2582 if (CHECK_FLAG(peer->af_flags[afi][safi],
2583 PEER_FLAG_MAX_PREFIX_WARNING))
2584 return 0;
2585
2586 /* Convert AFI, SAFI to values for packet. */
2587 pkt_afi = afi_int2iana(afi);
2588 pkt_safi = safi_int2iana(safi);
2589 {
d7c0a89a 2590 uint8_t ndata[7];
d62a17ae 2591
2592 ndata[0] = (pkt_afi >> 8);
2593 ndata[1] = pkt_afi;
2594 ndata[2] = pkt_safi;
2595 ndata[3] = (peer->pmax[afi][safi] >> 24);
2596 ndata[4] = (peer->pmax[afi][safi] >> 16);
2597 ndata[5] = (peer->pmax[afi][safi] >> 8);
2598 ndata[6] = (peer->pmax[afi][safi]);
2599
2600 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2601 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2602 BGP_NOTIFY_CEASE_MAX_PREFIX,
2603 ndata, 7);
2604 }
2605
2606 /* Dynamic peers will just close their connection. */
2607 if (peer_dynamic_neighbor(peer))
2608 return 1;
2609
2610 /* restart timer start */
2611 if (peer->pmax_restart[afi][safi]) {
2612 peer->v_pmax_restart =
2613 peer->pmax_restart[afi][safi] * 60;
2614
2615 if (bgp_debug_neighbor_events(peer))
2616 zlog_debug(
2617 "%s Maximum-prefix restart timer started for %d secs",
2618 peer->host, peer->v_pmax_restart);
2619
2620 BGP_TIMER_ON(peer->t_pmax_restart,
2621 bgp_maximum_prefix_restart_timer,
2622 peer->v_pmax_restart);
2623 }
2624
2625 return 1;
2626 } else
2627 UNSET_FLAG(peer->af_sflags[afi][safi],
2628 PEER_STATUS_PREFIX_LIMIT);
2629
2630 if (peer->pcount[afi][safi]
2631 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2632 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2633 PEER_STATUS_PREFIX_THRESHOLD)
2634 && !always)
2635 return 0;
2636
2637 zlog_info(
2638 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2639 afi_safi_print(afi, safi), peer->host,
2640 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2641 SET_FLAG(peer->af_sflags[afi][safi],
2642 PEER_STATUS_PREFIX_THRESHOLD);
2643 } else
2644 UNSET_FLAG(peer->af_sflags[afi][safi],
2645 PEER_STATUS_PREFIX_THRESHOLD);
2646 return 0;
718e3744 2647}
2648
b40d939b 2649/* Unconditionally remove the route from the RIB, without taking
2650 * damping into consideration (eg, because the session went down)
2651 */
60466a63
QY
2652void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
2653 afi_t afi, safi_t safi)
718e3744 2654{
d62a17ae 2655 bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
2656
2657 if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
2658 bgp_info_delete(rn, ri); /* keep historical info */
2659
2660 bgp_process(peer->bgp, rn, afi, safi);
2661}
2662
2663static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri,
2664 struct peer *peer, afi_t afi, safi_t safi,
2665 struct prefix_rd *prd)
2666{
2667 int status = BGP_DAMP_NONE;
2668
2669 /* apply dampening, if result is suppressed, we'll be retaining
2670 * the bgp_info in the RIB for historical reference.
2671 */
2672 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2673 && peer->sort == BGP_PEER_EBGP)
2674 if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0))
2675 == BGP_DAMP_SUPPRESSED) {
2676 bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi,
2677 safi);
2678 return;
2679 }
2680
65efcfce 2681#if ENABLE_BGP_VNC
d62a17ae 2682 if (safi == SAFI_MPLS_VPN) {
2683 struct bgp_node *prn = NULL;
2684 struct bgp_table *table = NULL;
2685
2686 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2687 (struct prefix *)prd);
2688 if (prn->info) {
2689 table = (struct bgp_table *)(prn->info);
2690
2691 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2692 peer->bgp, prd, table, &rn->p, ri);
2693 }
2694 bgp_unlock_node(prn);
2695 }
2696 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2697 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
65efcfce 2698
d62a17ae 2699 vnc_import_bgp_del_route(peer->bgp, &rn->p, ri);
2700 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
2701 ri);
2702 }
65efcfce 2703 }
d62a17ae 2704#endif
128ea8ab 2705
d62a17ae 2706 /* If this is an EVPN route, process for un-import. */
2707 if (safi == SAFI_EVPN)
2708 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, ri);
128ea8ab 2709
d62a17ae 2710 bgp_rib_remove(rn, ri, peer, afi, safi);
718e3744 2711}
2712
d7c0a89a 2713struct bgp_info *info_make(int type, int sub_type, unsigned short instance,
d62a17ae 2714 struct peer *peer, struct attr *attr,
2715 struct bgp_node *rn)
fb018d25 2716{
d62a17ae 2717 struct bgp_info *new;
fb018d25 2718
d62a17ae 2719 /* Make new BGP info. */
2720 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info));
2721 new->type = type;
2722 new->instance = instance;
2723 new->sub_type = sub_type;
2724 new->peer = peer;
2725 new->attr = attr;
2726 new->uptime = bgp_clock();
2727 new->net = rn;
2728 new->addpath_tx_id = ++peer->bgp->addpath_tx_id;
2729 return new;
fb018d25
DS
2730}
2731
d62a17ae 2732static void overlay_index_update(struct attr *attr,
2733 struct eth_segment_id *eth_s_id,
2734 union gw_addr *gw_ip)
684a7227 2735{
d62a17ae 2736 if (!attr)
2737 return;
684a7227 2738
d62a17ae 2739 if (eth_s_id == NULL) {
2740 memset(&(attr->evpn_overlay.eth_s_id), 0,
2741 sizeof(struct eth_segment_id));
2742 } else {
2743 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2744 sizeof(struct eth_segment_id));
2745 }
2746 if (gw_ip == NULL) {
2747 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2748 } else {
2749 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2750 sizeof(union gw_addr));
2751 }
684a7227
PG
2752}
2753
d62a17ae 2754static bool overlay_index_equal(afi_t afi, struct bgp_info *info,
2755 struct eth_segment_id *eth_s_id,
2756 union gw_addr *gw_ip)
2757{
2758 struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote;
2759 union gw_addr *info_gw_ip, *info_gw_ip_remote;
2760 char temp[16];
2761
2762 if (afi != AFI_L2VPN)
2763 return true;
2764 if (!info->attr) {
2765 memset(&temp, 0, 16);
2766 info_eth_s_id = (struct eth_segment_id *)&temp;
2767 info_gw_ip = (union gw_addr *)&temp;
2768 if (eth_s_id == NULL && gw_ip == NULL)
2769 return true;
2770 } else {
2771 info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id);
2772 info_gw_ip = &(info->attr->evpn_overlay.gw_ip);
2773 }
2774 if (gw_ip == NULL)
2775 info_gw_ip_remote = (union gw_addr *)&temp;
2776 else
2777 info_gw_ip_remote = gw_ip;
2778 if (eth_s_id == NULL)
2779 info_eth_s_id_remote = (struct eth_segment_id *)&temp;
2780 else
2781 info_eth_s_id_remote = eth_s_id;
2782 if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr)))
2783 return false;
2784 return !memcmp(info_eth_s_id, info_eth_s_id_remote,
2785 sizeof(struct eth_segment_id));
684a7227
PG
2786}
2787
c265ee22 2788/* Check if received nexthop is valid or not. */
d62a17ae 2789static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2790 struct attr *attr)
2791{
2792 int ret = 0;
2793
2794 /* Only validated for unicast and multicast currently. */
2795 /* Also valid for EVPN where the nexthop is an IP address. */
2796 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2797 return 0;
2798
2799 /* If NEXT_HOP is present, validate it. */
2800 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2801 if (attr->nexthop.s_addr == 0
2802 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2803 || bgp_nexthop_self(bgp, attr->nexthop))
2804 return 1;
2805 }
c265ee22 2806
d62a17ae 2807 /* If MP_NEXTHOP is present, validate it. */
2808 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2809 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2810 * it is not an IPv6 link-local address.
2811 */
2812 if (attr->mp_nexthop_len) {
2813 switch (attr->mp_nexthop_len) {
2814 case BGP_ATTR_NHLEN_IPV4:
2815 case BGP_ATTR_NHLEN_VPNV4:
2816 ret = (attr->mp_nexthop_global_in.s_addr == 0
2817 || IPV4_CLASS_DE(ntohl(
2818 attr->mp_nexthop_global_in.s_addr))
2819 || bgp_nexthop_self(bgp,
2820 attr->mp_nexthop_global_in));
2821 break;
2822
2823 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2824 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2825 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2826 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
2827 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
2828 || IN6_IS_ADDR_MULTICAST(
2829 &attr->mp_nexthop_global));
2830 break;
2831
2832 default:
2833 ret = 1;
2834 break;
2835 }
2836 }
c265ee22 2837
d62a17ae 2838 return ret;
2839}
2840
d7c0a89a 2841int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 2842 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 2843 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 2844 uint32_t num_labels, int soft_reconfig,
a4d82a8a 2845 struct bgp_route_evpn *evpn)
d62a17ae 2846{
2847 int ret;
2848 int aspath_loop_count = 0;
2849 struct bgp_node *rn;
2850 struct bgp *bgp;
2851 struct attr new_attr;
2852 struct attr *attr_new;
2853 struct bgp_info *ri;
2854 struct bgp_info *new;
b57ba6d2 2855 struct bgp_info_extra *extra;
d62a17ae 2856 const char *reason;
2857 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 2858 int connected = 0;
2859 int do_loop_check = 1;
2860 int has_valid_label = 0;
65efcfce 2861#if ENABLE_BGP_VNC
d62a17ae 2862 int vnc_implicit_withdraw = 0;
65efcfce 2863#endif
d62a17ae 2864 int same_attr = 0;
718e3744 2865
d62a17ae 2866 memset(&new_attr, 0, sizeof(struct attr));
2867 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
2868 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 2869
d62a17ae 2870 bgp = peer->bgp;
2871 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
2872 /* TODO: Check to see if we can get rid of "is_valid_label" */
2873 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
2874 has_valid_label = (num_labels > 0) ? 1 : 0;
2875 else
2876 has_valid_label = bgp_is_valid_label(label);
718e3744 2877
d62a17ae 2878 /* When peer's soft reconfiguration enabled. Record input packet in
2879 Adj-RIBs-In. */
2880 if (!soft_reconfig
2881 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
2882 && peer != bgp->peer_self)
2883 bgp_adj_in_set(rn, peer, attr, addpath_id);
2884
2885 /* Check previously received route. */
2886 for (ri = rn->info; ri; ri = ri->next)
2887 if (ri->peer == peer && ri->type == type
2888 && ri->sub_type == sub_type
2889 && ri->addpath_rx_id == addpath_id)
2890 break;
2891
2892 /* AS path local-as loop check. */
2893 if (peer->change_local_as) {
c4368918
DW
2894 if (peer->allowas_in[afi][safi])
2895 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
2896 else if (!CHECK_FLAG(peer->flags,
2897 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 2898 aspath_loop_count = 1;
2899
2900 if (aspath_loop_check(attr->aspath, peer->change_local_as)
2901 > aspath_loop_count) {
2902 reason = "as-path contains our own AS;";
2903 goto filtered;
2904 }
718e3744 2905 }
718e3744 2906
d62a17ae 2907 /* If the peer is configured for "allowas-in origin" and the last ASN in
2908 * the
2909 * as-path is our ASN then we do not need to call aspath_loop_check
2910 */
2911 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
2912 if (aspath_get_last_as(attr->aspath) == bgp->as)
2913 do_loop_check = 0;
2914
2915 /* AS path loop check. */
2916 if (do_loop_check) {
2917 if (aspath_loop_check(attr->aspath, bgp->as)
2918 > peer->allowas_in[afi][safi]
2919 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
2920 && aspath_loop_check(attr->aspath, bgp->confed_id)
2921 > peer->allowas_in[afi][safi])) {
2922 reason = "as-path contains our own AS;";
2923 goto filtered;
2924 }
2925 }
aac9ef6c 2926
d62a17ae 2927 /* Route reflector originator ID check. */
2928 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2929 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
2930 reason = "originator is us;";
2931 goto filtered;
2932 }
718e3744 2933
d62a17ae 2934 /* Route reflector cluster ID check. */
2935 if (bgp_cluster_filter(peer, attr)) {
2936 reason = "reflected from the same cluster;";
2937 goto filtered;
2938 }
718e3744 2939
d62a17ae 2940 /* Apply incoming filter. */
2941 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
2942 reason = "filter;";
2943 goto filtered;
2944 }
718e3744 2945
d62a17ae 2946 bgp_attr_dup(&new_attr, attr);
2947
2948 /* Apply incoming route-map.
2949 * NB: new_attr may now contain newly allocated values from route-map
2950 * "set"
2951 * commands, so we need bgp_attr_flush in the error paths, until we
2952 * intern
2953 * the attr (which takes over the memory references) */
2954 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
2955 == RMAP_DENY) {
2956 reason = "route-map;";
2957 bgp_attr_flush(&new_attr);
2958 goto filtered;
2959 }
718e3744 2960
7f323236
DW
2961 if (peer->sort == BGP_PEER_EBGP) {
2962
a4d82a8a
PZ
2963 /* If we receive the graceful-shutdown community from an eBGP
2964 * peer we must lower local-preference */
2965 if (new_attr.community
2966 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
2967 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2968 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
2969
a4d82a8a
PZ
2970 /* If graceful-shutdown is configured then add the GSHUT
2971 * community to all paths received from eBGP peers */
2972 } else if (bgp_flag_check(peer->bgp,
2973 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
2974 bgp_attr_add_gshut_community(&new_attr);
2975 }
2976 }
2977
d62a17ae 2978 /* next hop check. */
a4d82a8a
PZ
2979 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
2980 && bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
d62a17ae 2981 reason = "martian or self next-hop;";
2982 bgp_attr_flush(&new_attr);
2983 goto filtered;
2984 }
718e3744 2985
d62a17ae 2986 attr_new = bgp_attr_intern(&new_attr);
2987
2988 /* If the update is implicit withdraw. */
2989 if (ri) {
2990 ri->uptime = bgp_clock();
2991 same_attr = attrhash_cmp(ri->attr, attr_new);
2992
2993 /* Same attribute comes in. */
2994 if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
2995 && attrhash_cmp(ri->attr, attr_new)
2996 && (!has_valid_label
2997 || memcmp(&(bgp_info_extra_get(ri))->label, label,
b57ba6d2 2998 num_labels * sizeof(mpls_label_t))
d62a17ae 2999 == 0)
3000 && (overlay_index_equal(
3001 afi, ri, evpn == NULL ? NULL : &evpn->eth_s_id,
3002 evpn == NULL ? NULL : &evpn->gw_ip))) {
3003 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3004 BGP_CONFIG_DAMPENING)
3005 && peer->sort == BGP_PEER_EBGP
3006 && CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) {
3007 if (bgp_debug_update(peer, p, NULL, 1)) {
3008 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3009 afi, safi, prd, p, label,
3010 num_labels, addpath_id ? 1 : 0,
3011 addpath_id, pfx_buf,
3012 sizeof(pfx_buf));
d62a17ae 3013 zlog_debug("%s rcvd %s", peer->host,
3014 pfx_buf);
3015 }
3016
3017 if (bgp_damp_update(ri, rn, afi, safi)
3018 != BGP_DAMP_SUPPRESSED) {
3019 bgp_aggregate_increment(bgp, p, ri, afi,
3020 safi);
3021 bgp_process(bgp, rn, afi, safi);
3022 }
3023 } else /* Duplicate - odd */
3024 {
3025 if (bgp_debug_update(peer, p, NULL, 1)) {
3026 if (!peer->rcvd_attr_printed) {
3027 zlog_debug(
3028 "%s rcvd UPDATE w/ attr: %s",
3029 peer->host,
3030 peer->rcvd_attr_str);
3031 peer->rcvd_attr_printed = 1;
3032 }
3033
3034 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3035 afi, safi, prd, p, label,
3036 num_labels, addpath_id ? 1 : 0,
3037 addpath_id, pfx_buf,
3038 sizeof(pfx_buf));
d62a17ae 3039 zlog_debug(
3040 "%s rcvd %s...duplicate ignored",
3041 peer->host, pfx_buf);
3042 }
3043
3044 /* graceful restart STALE flag unset. */
3045 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) {
3046 bgp_info_unset_flag(rn, ri,
3047 BGP_INFO_STALE);
3048 bgp_process(bgp, rn, afi, safi);
3049 }
3050 }
3051
3052 bgp_unlock_node(rn);
3053 bgp_attr_unintern(&attr_new);
3054
3055 return 0;
3056 }
718e3744 3057
d62a17ae 3058 /* Withdraw/Announce before we fully processed the withdraw */
3059 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
3060 if (bgp_debug_update(peer, p, NULL, 1)) {
3061 bgp_debug_rdpfxpath2str(
a4d82a8a 3062 afi, safi, prd, p, label, num_labels,
d62a17ae 3063 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3064 sizeof(pfx_buf));
3065 zlog_debug(
3066 "%s rcvd %s, flapped quicker than processing",
3067 peer->host, pfx_buf);
3068 }
3069
3070 bgp_info_restore(rn, ri);
3071 }
718e3744 3072
d62a17ae 3073 /* Received Logging. */
3074 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3075 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3076 num_labels, addpath_id ? 1 : 0,
3077 addpath_id, pfx_buf,
3078 sizeof(pfx_buf));
d62a17ae 3079 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3080 }
718e3744 3081
d62a17ae 3082 /* graceful restart STALE flag unset. */
3083 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
3084 bgp_info_unset_flag(rn, ri, BGP_INFO_STALE);
3085
3086 /* The attribute is changed. */
3087 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
3088
3089 /* implicit withdraw, decrement aggregate and pcount here.
3090 * only if update is accepted, they'll increment below.
3091 */
3092 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
3093
3094 /* Update bgp route dampening information. */
3095 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3096 && peer->sort == BGP_PEER_EBGP) {
3097 /* This is implicit withdraw so we should update
3098 dampening
3099 information. */
3100 if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
3101 bgp_damp_withdraw(ri, rn, afi, safi, 1);
3102 }
65efcfce 3103#if ENABLE_BGP_VNC
d62a17ae 3104 if (safi == SAFI_MPLS_VPN) {
3105 struct bgp_node *prn = NULL;
3106 struct bgp_table *table = NULL;
3107
3108 prn = bgp_node_get(bgp->rib[afi][safi],
3109 (struct prefix *)prd);
3110 if (prn->info) {
3111 table = (struct bgp_table *)(prn->info);
3112
3113 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3114 bgp, prd, table, p, ri);
3115 }
3116 bgp_unlock_node(prn);
3117 }
3118 if ((afi == AFI_IP || afi == AFI_IP6)
3119 && (safi == SAFI_UNICAST)) {
3120 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
3121 /*
3122 * Implicit withdraw case.
3123 */
3124 ++vnc_implicit_withdraw;
3125 vnc_import_bgp_del_route(bgp, p, ri);
3126 vnc_import_bgp_exterior_del_route(bgp, p, ri);
3127 }
3128 }
65efcfce 3129#endif
128ea8ab 3130
d62a17ae 3131 /* Special handling for EVPN update of an existing route. If the
3132 * extended community attribute has changed, we need to
3133 * un-import
3134 * the route using its existing extended community. It will be
3135 * subsequently processed for import with the new extended
3136 * community.
3137 */
3138 if (safi == SAFI_EVPN && !same_attr) {
3139 if ((ri->attr->flag
3140 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3141 && (attr_new->flag
3142 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3143 int cmp;
3144
3145 cmp = ecommunity_cmp(ri->attr->ecommunity,
3146 attr_new->ecommunity);
3147 if (!cmp) {
3148 if (bgp_debug_update(peer, p, NULL, 1))
3149 zlog_debug(
3150 "Change in EXT-COMM, existing %s new %s",
3151 ecommunity_str(
3152 ri->attr->ecommunity),
3153 ecommunity_str(
3154 attr_new->ecommunity));
3155 bgp_evpn_unimport_route(bgp, afi, safi,
3156 p, ri);
3157 }
3158 }
3159 }
718e3744 3160
d62a17ae 3161 /* Update to new attribute. */
3162 bgp_attr_unintern(&ri->attr);
3163 ri->attr = attr_new;
3164
3165 /* Update MPLS label */
3166 if (has_valid_label) {
b57ba6d2
MK
3167 extra = bgp_info_extra_get(ri);
3168 memcpy(&extra->label, label,
3169 num_labels * sizeof(mpls_label_t));
3170 extra->num_labels = num_labels;
3171 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3172 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3173 }
718e3744 3174
65efcfce 3175#if ENABLE_BGP_VNC
d62a17ae 3176 if ((afi == AFI_IP || afi == AFI_IP6)
3177 && (safi == SAFI_UNICAST)) {
3178 if (vnc_implicit_withdraw) {
3179 /*
3180 * Add back the route with its new attributes
3181 * (e.g., nexthop).
3182 * The route is still selected, until the route
3183 * selection
3184 * queued by bgp_process actually runs. We have
3185 * to make this
3186 * update to the VNC side immediately to avoid
3187 * racing against
3188 * configuration changes (e.g., route-map
3189 * changes) which
3190 * trigger re-importation of the entire RIB.
3191 */
3192 vnc_import_bgp_add_route(bgp, p, ri);
3193 vnc_import_bgp_exterior_add_route(bgp, p, ri);
3194 }
3195 }
65efcfce 3196#endif
d62a17ae 3197 /* Update Overlay Index */
3198 if (afi == AFI_L2VPN) {
3199 overlay_index_update(
3200 ri->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
3201 evpn == NULL ? NULL : &evpn->gw_ip);
3202 }
65efcfce 3203
d62a17ae 3204 /* Update bgp route dampening information. */
3205 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3206 && peer->sort == BGP_PEER_EBGP) {
3207 /* Now we do normal update dampening. */
3208 ret = bgp_damp_update(ri, rn, afi, safi);
3209 if (ret == BGP_DAMP_SUPPRESSED) {
3210 bgp_unlock_node(rn);
3211 return 0;
3212 }
3213 }
128ea8ab 3214
d62a17ae 3215 /* Nexthop reachability check - for unicast and
3216 * labeled-unicast.. */
3217 if ((afi == AFI_IP || afi == AFI_IP6)
3218 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3219 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3220 && !CHECK_FLAG(peer->flags,
3221 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3222 && !bgp_flag_check(
3223 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3224 connected = 1;
3225 else
3226 connected = 0;
3227
960035b2
PZ
3228 struct bgp *bgp_nexthop = bgp;
3229
3230 if (ri->extra && ri->extra->bgp_orig)
3231 bgp_nexthop = ri->extra->bgp_orig;
3232
3233 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi,
3234 ri, NULL, connected)
a4d82a8a 3235 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
d62a17ae 3236 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
3237 else {
3238 if (BGP_DEBUG(nht, NHT)) {
3239 char buf1[INET6_ADDRSTRLEN];
3240 inet_ntop(AF_INET,
3241 (const void *)&attr_new
3242 ->nexthop,
3243 buf1, INET6_ADDRSTRLEN);
3244 zlog_debug("%s(%s): NH unresolved",
3245 __FUNCTION__, buf1);
3246 }
3247 bgp_info_unset_flag(rn, ri, BGP_INFO_VALID);
3248 }
3249 } else
3250 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
3251
3252#if ENABLE_BGP_VNC
3253 if (safi == SAFI_MPLS_VPN) {
3254 struct bgp_node *prn = NULL;
3255 struct bgp_table *table = NULL;
3256
3257 prn = bgp_node_get(bgp->rib[afi][safi],
3258 (struct prefix *)prd);
3259 if (prn->info) {
3260 table = (struct bgp_table *)(prn->info);
3261
3262 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3263 bgp, prd, table, p, ri);
3264 }
3265 bgp_unlock_node(prn);
3266 }
3267#endif
718e3744 3268
d62a17ae 3269 /* If this is an EVPN route and some attribute has changed,
3270 * process
3271 * route for import. If the extended community has changed, we
3272 * would
3273 * have done the un-import earlier and the import would result
3274 * in the
3275 * route getting injected into appropriate L2 VNIs. If it is
3276 * just
3277 * some other attribute change, the import will result in
3278 * updating
3279 * the attributes for the route in the VNI(s).
3280 */
3281 if (safi == SAFI_EVPN && !same_attr)
3282 bgp_evpn_import_route(bgp, afi, safi, p, ri);
3283
3284 /* Process change. */
3285 bgp_aggregate_increment(bgp, p, ri, afi, safi);
3286
3287 bgp_process(bgp, rn, afi, safi);
3288 bgp_unlock_node(rn);
558d1fec 3289
ddb5b488
PZ
3290 if (SAFI_UNICAST == safi
3291 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3292 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3293
3294 vpn_leak_from_vrf_update(bgp_get_default(), bgp, ri);
3295 }
3296 if ((SAFI_MPLS_VPN == safi)
3297 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3298
3299 vpn_leak_to_vrf_update(bgp, ri);
3300 }
3301
28070ee3 3302#if ENABLE_BGP_VNC
d62a17ae 3303 if (SAFI_MPLS_VPN == safi) {
3304 mpls_label_t label_decoded = decode_label(label);
28070ee3 3305
d62a17ae 3306 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3307 type, sub_type, &label_decoded);
3308 }
3309 if (SAFI_ENCAP == safi) {
3310 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3311 type, sub_type, NULL);
3312 }
28070ee3
PZ
3313#endif
3314
d62a17ae 3315 return 0;
3316 } // End of implicit withdraw
718e3744 3317
d62a17ae 3318 /* Received Logging. */
3319 if (bgp_debug_update(peer, p, NULL, 1)) {
3320 if (!peer->rcvd_attr_printed) {
3321 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3322 peer->rcvd_attr_str);
3323 peer->rcvd_attr_printed = 1;
3324 }
718e3744 3325
a4d82a8a 3326 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3327 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3328 sizeof(pfx_buf));
3329 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3330 }
718e3744 3331
d62a17ae 3332 /* Make new BGP info. */
3333 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3334
d62a17ae 3335 /* Update MPLS label */
3336 if (has_valid_label) {
b57ba6d2 3337 extra = bgp_info_extra_get(new);
a4d82a8a 3338 memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t));
b57ba6d2
MK
3339 extra->num_labels = num_labels;
3340 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3341 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3342 }
718e3744 3343
d62a17ae 3344 /* Update Overlay Index */
3345 if (afi == AFI_L2VPN) {
3346 overlay_index_update(new->attr,
3347 evpn == NULL ? NULL : &evpn->eth_s_id,
3348 evpn == NULL ? NULL : &evpn->gw_ip);
3349 }
3350 /* Nexthop reachability check. */
3351 if ((afi == AFI_IP || afi == AFI_IP6)
3352 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3353 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3354 && !CHECK_FLAG(peer->flags,
3355 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3356 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3357 connected = 1;
3358 else
3359 connected = 0;
3360
960035b2 3361 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected)
a4d82a8a 3362 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
d62a17ae 3363 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
3364 else {
3365 if (BGP_DEBUG(nht, NHT)) {
3366 char buf1[INET6_ADDRSTRLEN];
3367 inet_ntop(AF_INET,
3368 (const void *)&attr_new->nexthop,
3369 buf1, INET6_ADDRSTRLEN);
3370 zlog_debug("%s(%s): NH unresolved",
3371 __FUNCTION__, buf1);
3372 }
3373 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
3374 }
3375 } else
3376 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
a82478b9 3377
d62a17ae 3378 /* Addpath ID */
3379 new->addpath_rx_id = addpath_id;
3380
3381 /* Increment prefix */
3382 bgp_aggregate_increment(bgp, p, new, afi, safi);
3383
3384 /* Register new BGP information. */
3385 bgp_info_add(rn, new);
3386
3387 /* route_node_get lock */
3388 bgp_unlock_node(rn);
558d1fec 3389
65efcfce 3390#if ENABLE_BGP_VNC
d62a17ae 3391 if (safi == SAFI_MPLS_VPN) {
3392 struct bgp_node *prn = NULL;
3393 struct bgp_table *table = NULL;
3394
3395 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
3396 if (prn->info) {
3397 table = (struct bgp_table *)(prn->info);
3398
3399 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3400 bgp, prd, table, p, new);
3401 }
3402 bgp_unlock_node(prn);
3403 }
65efcfce
LB
3404#endif
3405
d62a17ae 3406 /* If maximum prefix count is configured and current prefix
3407 count exeed it. */
3408 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3409 return -1;
718e3744 3410
d62a17ae 3411 /* If this is an EVPN route, process for import. */
3412 if (safi == SAFI_EVPN)
3413 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3414
d62a17ae 3415 /* Process change. */
3416 bgp_process(bgp, rn, afi, safi);
718e3744 3417
ddb5b488
PZ
3418 if (SAFI_UNICAST == safi
3419 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3420 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3421 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3422 }
3423 if ((SAFI_MPLS_VPN == safi)
3424 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3425
3426 vpn_leak_to_vrf_update(bgp, new);
3427 }
28070ee3 3428#if ENABLE_BGP_VNC
d62a17ae 3429 if (SAFI_MPLS_VPN == safi) {
3430 mpls_label_t label_decoded = decode_label(label);
28070ee3 3431
d62a17ae 3432 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3433 sub_type, &label_decoded);
3434 }
3435 if (SAFI_ENCAP == safi) {
3436 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3437 sub_type, NULL);
3438 }
28070ee3
PZ
3439#endif
3440
d62a17ae 3441 return 0;
718e3744 3442
d62a17ae 3443/* This BGP update is filtered. Log the reason then update BGP
3444 entry. */
3445filtered:
3446 if (bgp_debug_update(peer, p, NULL, 1)) {
3447 if (!peer->rcvd_attr_printed) {
3448 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3449 peer->rcvd_attr_str);
3450 peer->rcvd_attr_printed = 1;
3451 }
718e3744 3452
a4d82a8a 3453 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3454 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3455 sizeof(pfx_buf));
3456 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3457 peer->host, pfx_buf, reason);
3458 }
128ea8ab 3459
d62a17ae 3460 if (ri) {
3461 /* If this is an EVPN route, un-import it as it is now filtered.
3462 */
3463 if (safi == SAFI_EVPN)
3464 bgp_evpn_unimport_route(bgp, afi, safi, p, ri);
718e3744 3465
ddb5b488
PZ
3466 if (SAFI_UNICAST == safi
3467 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3468 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3469
3470 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
3471 }
3472 if ((SAFI_MPLS_VPN == safi)
3473 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3474
3475 vpn_leak_to_vrf_withdraw(bgp, ri);
3476 }
3477
d62a17ae 3478 bgp_rib_remove(rn, ri, peer, afi, safi);
3479 }
3480
3481 bgp_unlock_node(rn);
558d1fec 3482
97736e32 3483#if ENABLE_BGP_VNC
d62a17ae 3484 /*
3485 * Filtered update is treated as an implicit withdrawal (see
3486 * bgp_rib_remove()
3487 * a few lines above)
3488 */
3489 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3490 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3491 0);
3492 }
97736e32
PZ
3493#endif
3494
d62a17ae 3495 return 0;
718e3744 3496}
3497
d7c0a89a 3498int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3499 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3500 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3501 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 3502{
d62a17ae 3503 struct bgp *bgp;
3504 char pfx_buf[BGP_PRD_PATH_STRLEN];
3505 struct bgp_node *rn;
3506 struct bgp_info *ri;
718e3744 3507
28070ee3 3508#if ENABLE_BGP_VNC
d62a17ae 3509 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3510 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3511 0);
3512 }
28070ee3
PZ
3513#endif
3514
d62a17ae 3515 bgp = peer->bgp;
3516
3517 /* Lookup node. */
3518 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3519
3520 /* If peer is soft reconfiguration enabled. Record input packet for
3521 * further calculation.
3522 *
3523 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3524 * routes that are filtered. This tanks out Quagga RS pretty badly due
3525 * to
3526 * the iteration over all RS clients.
3527 * Since we need to remove the entry from adj_in anyway, do that first
3528 * and
3529 * if there was no entry, we don't need to do anything more.
3530 */
3531 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3532 && peer != bgp->peer_self)
3533 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
3534 if (bgp_debug_update(peer, p, NULL, 1)) {
3535 bgp_debug_rdpfxpath2str(
a4d82a8a 3536 afi, safi, prd, p, label, num_labels,
d62a17ae 3537 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3538 sizeof(pfx_buf));
3539 zlog_debug(
3540 "%s withdrawing route %s not in adj-in",
3541 peer->host, pfx_buf);
3542 }
3543 bgp_unlock_node(rn);
3544 return 0;
3545 }
cd808e74 3546
d62a17ae 3547 /* Lookup withdrawn route. */
3548 for (ri = rn->info; ri; ri = ri->next)
3549 if (ri->peer == peer && ri->type == type
3550 && ri->sub_type == sub_type
3551 && ri->addpath_rx_id == addpath_id)
3552 break;
3553
3554 /* Logging. */
3555 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3556 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3557 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3558 sizeof(pfx_buf));
3559 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3560 pfx_buf);
3561 }
718e3744 3562
d62a17ae 3563 /* Withdraw specified route from routing table. */
ddb5b488 3564 if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) {
d62a17ae 3565 bgp_rib_withdraw(rn, ri, peer, afi, safi, prd);
ddb5b488
PZ
3566 if (SAFI_UNICAST == safi
3567 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3568 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3569 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
3570 }
3571 if ((SAFI_MPLS_VPN == safi)
3572 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3573
3574 vpn_leak_to_vrf_withdraw(bgp, ri);
3575 }
3576 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 3577 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3578 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3579 sizeof(pfx_buf));
3580 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3581 }
718e3744 3582
d62a17ae 3583 /* Unlock bgp_node_get() lock. */
3584 bgp_unlock_node(rn);
3585
3586 return 0;
718e3744 3587}
6b0655a2 3588
d62a17ae 3589void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3590 int withdraw)
718e3744 3591{
d62a17ae 3592 struct update_subgroup *subgrp;
3593 subgrp = peer_subgroup(peer, afi, safi);
3594 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3595}
6182d65b 3596
718e3744 3597
3f9c7369
DS
3598/*
3599 * bgp_stop_announce_route_timer
3600 */
d62a17ae 3601void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3602{
d62a17ae 3603 if (!paf->t_announce_route)
3604 return;
3605
3606 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3607}
6b0655a2 3608
3f9c7369
DS
3609/*
3610 * bgp_announce_route_timer_expired
3611 *
3612 * Callback that is invoked when the route announcement timer for a
3613 * peer_af expires.
3614 */
d62a17ae 3615static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3616{
d62a17ae 3617 struct peer_af *paf;
3618 struct peer *peer;
558d1fec 3619
d62a17ae 3620 paf = THREAD_ARG(t);
3621 peer = paf->peer;
718e3744 3622
d62a17ae 3623 if (peer->status != Established)
3624 return 0;
3f9c7369 3625
d62a17ae 3626 if (!peer->afc_nego[paf->afi][paf->safi])
3627 return 0;
3f9c7369 3628
d62a17ae 3629 peer_af_announce_route(paf, 1);
3630 return 0;
718e3744 3631}
3632
3f9c7369
DS
3633/*
3634 * bgp_announce_route
3635 *
3636 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3637 */
d62a17ae 3638void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3639{
3640 struct peer_af *paf;
3641 struct update_subgroup *subgrp;
3642
3643 paf = peer_af_find(peer, afi, safi);
3644 if (!paf)
3645 return;
3646 subgrp = PAF_SUBGRP(paf);
3647
3648 /*
3649 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3650 * or a refresh has already been triggered.
3651 */
3652 if (!subgrp || paf->t_announce_route)
3653 return;
3654
3655 /*
3656 * Start a timer to stagger/delay the announce. This serves
3657 * two purposes - announcement can potentially be combined for
3658 * multiple peers and the announcement doesn't happen in the
3659 * vty context.
3660 */
3661 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3662 (subgrp->peer_count == 1)
3663 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3664 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3665 &paf->t_announce_route);
3f9c7369
DS
3666}
3667
3668/*
3669 * Announce routes from all AF tables to a peer.
3670 *
3671 * This should ONLY be called when there is a need to refresh the
3672 * routes to the peer based on a policy change for this peer alone
3673 * or a route refresh request received from the peer.
3674 * The operation will result in splitting the peer from its existing
3675 * subgroups and putting it in new subgroups.
3676 */
d62a17ae 3677void bgp_announce_route_all(struct peer *peer)
718e3744 3678{
d62a17ae 3679 afi_t afi;
3680 safi_t safi;
3681
05c7a1cc
QY
3682 FOREACH_AFI_SAFI (afi, safi)
3683 bgp_announce_route(peer, afi, safi);
718e3744 3684}
6b0655a2 3685
d62a17ae 3686static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3687 struct bgp_table *table,
3688 struct prefix_rd *prd)
718e3744 3689{
d62a17ae 3690 int ret;
3691 struct bgp_node *rn;
3692 struct bgp_adj_in *ain;
718e3744 3693
d62a17ae 3694 if (!table)
3695 table = peer->bgp->rib[afi][safi];
718e3744 3696
d62a17ae 3697 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3698 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3699 if (ain->peer != peer)
3700 continue;
8692c506 3701
ea47320b 3702 struct bgp_info *ri = rn->info;
d7c0a89a 3703 uint32_t num_labels = 0;
b57ba6d2
MK
3704 mpls_label_t *label_pnt = NULL;
3705
3706 if (ri && ri->extra)
3707 num_labels = ri->extra->num_labels;
3708 if (num_labels)
3709 label_pnt = &ri->extra->label[0];
8692c506 3710
ea47320b
DL
3711 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3712 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
3713 BGP_ROUTE_NORMAL, prd, label_pnt,
3714 num_labels, 1, NULL);
ea47320b
DL
3715
3716 if (ret < 0) {
3717 bgp_unlock_node(rn);
3718 return;
d62a17ae 3719 }
3720 }
718e3744 3721}
3722
d62a17ae 3723void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3724{
d62a17ae 3725 struct bgp_node *rn;
3726 struct bgp_table *table;
718e3744 3727
d62a17ae 3728 if (peer->status != Established)
3729 return;
718e3744 3730
d62a17ae 3731 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3732 && (safi != SAFI_EVPN))
3733 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3734 else
3735 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3736 rn = bgp_route_next(rn))
3737 if ((table = rn->info) != NULL) {
3738 struct prefix_rd prd;
3739 prd.family = AF_UNSPEC;
3740 prd.prefixlen = 64;
3741 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3742
d62a17ae 3743 bgp_soft_reconfig_table(peer, afi, safi, table,
3744 &prd);
3745 }
718e3744 3746}
6b0655a2 3747
228da428 3748
d62a17ae 3749struct bgp_clear_node_queue {
3750 struct bgp_node *rn;
228da428
CC
3751};
3752
d62a17ae 3753static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3754{
d62a17ae 3755 struct bgp_clear_node_queue *cnq = data;
3756 struct bgp_node *rn = cnq->rn;
3757 struct peer *peer = wq->spec.data;
3758 struct bgp_info *ri;
3103e8d2 3759 struct bgp *bgp;
d62a17ae 3760 afi_t afi = bgp_node_table(rn)->afi;
3761 safi_t safi = bgp_node_table(rn)->safi;
3762
3763 assert(rn && peer);
3103e8d2 3764 bgp = peer->bgp;
d62a17ae 3765
3766 /* It is possible that we have multiple paths for a prefix from a peer
3767 * if that peer is using AddPath.
3768 */
ea47320b
DL
3769 for (ri = rn->info; ri; ri = ri->next) {
3770 if (ri->peer != peer)
3771 continue;
3772
3773 /* graceful restart STALE flag set. */
3774 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
3775 && peer->nsf[afi][safi]
3776 && !CHECK_FLAG(ri->flags, BGP_INFO_STALE)
3777 && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
3778 bgp_info_set_flag(rn, ri, BGP_INFO_STALE);
3779 else {
3780 /* If this is an EVPN route, process for
3781 * un-import. */
3782 if (safi == SAFI_EVPN)
3103e8d2 3783 bgp_evpn_unimport_route(bgp, afi, safi,
ea47320b 3784 &rn->p, ri);
3103e8d2
DS
3785 /* Handle withdraw for VRF route-leaking and L3VPN */
3786 if (SAFI_UNICAST == safi
3787 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 3788 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2
DS
3789 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3790 bgp, ri);
960035b2 3791 }
3103e8d2 3792 if (SAFI_MPLS_VPN == safi &&
960035b2 3793 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
3103e8d2 3794 vpn_leak_to_vrf_withdraw(bgp, ri);
960035b2 3795 }
3103e8d2 3796
ea47320b 3797 bgp_rib_remove(rn, ri, peer, afi, safi);
d62a17ae 3798 }
ea47320b 3799 }
d62a17ae 3800 return WQ_SUCCESS;
200df115 3801}
3802
d62a17ae 3803static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 3804{
d62a17ae 3805 struct bgp_clear_node_queue *cnq = data;
3806 struct bgp_node *rn = cnq->rn;
3807 struct bgp_table *table = bgp_node_table(rn);
228da428 3808
d62a17ae 3809 bgp_unlock_node(rn);
3810 bgp_table_unlock(table);
3811 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 3812}
3813
d62a17ae 3814static void bgp_clear_node_complete(struct work_queue *wq)
200df115 3815{
d62a17ae 3816 struct peer *peer = wq->spec.data;
64e580a7 3817
d62a17ae 3818 /* Tickle FSM to start moving again */
3819 BGP_EVENT_ADD(peer, Clearing_Completed);
3820
3821 peer_unlock(peer); /* bgp_clear_route */
200df115 3822}
718e3744 3823
d62a17ae 3824static void bgp_clear_node_queue_init(struct peer *peer)
200df115 3825{
d62a17ae 3826 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3827
3828 snprintf(wname, sizeof(wname), "clear %s", peer->host);
3829#undef CLEAR_QUEUE_NAME_LEN
3830
3831 if ((peer->clear_node_queue = work_queue_new(bm->master, wname))
3832 == NULL) {
3833 zlog_err("%s: Failed to allocate work queue", __func__);
3834 exit(1);
0c6262ed 3835 }
d62a17ae 3836 peer->clear_node_queue->spec.hold = 10;
3837 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
3838 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
3839 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
3840 peer->clear_node_queue->spec.max_retries = 0;
3841
3842 /* we only 'lock' this peer reference when the queue is actually active
3843 */
3844 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
3845}
3846
d62a17ae 3847static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
3848 struct bgp_table *table)
65ca75e0 3849{
d62a17ae 3850 struct bgp_node *rn;
3851 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 3852
d62a17ae 3853 if (!table)
3854 table = peer->bgp->rib[afi][safi];
dc83d712 3855
d62a17ae 3856 /* If still no table => afi/safi isn't configured at all or smth. */
3857 if (!table)
3858 return;
dc83d712 3859
d62a17ae 3860 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
3861 struct bgp_info *ri, *next;
3862 struct bgp_adj_in *ain;
3863 struct bgp_adj_in *ain_next;
3864
3865 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3866 * queued for every clearing peer, regardless of whether it is
3867 * relevant to the peer at hand.
3868 *
3869 * Overview: There are 3 different indices which need to be
3870 * scrubbed, potentially, when a peer is removed:
3871 *
3872 * 1 peer's routes visible via the RIB (ie accepted routes)
3873 * 2 peer's routes visible by the (optional) peer's adj-in index
3874 * 3 other routes visible by the peer's adj-out index
3875 *
3876 * 3 there is no hurry in scrubbing, once the struct peer is
3877 * removed from bgp->peer, we could just GC such deleted peer's
3878 * adj-outs at our leisure.
3879 *
3880 * 1 and 2 must be 'scrubbed' in some way, at least made
3881 * invisible via RIB index before peer session is allowed to be
3882 * brought back up. So one needs to know when such a 'search' is
3883 * complete.
3884 *
3885 * Ideally:
3886 *
3887 * - there'd be a single global queue or a single RIB walker
3888 * - rather than tracking which route_nodes still need to be
3889 * examined on a peer basis, we'd track which peers still
3890 * aren't cleared
3891 *
3892 * Given that our per-peer prefix-counts now should be reliable,
3893 * this may actually be achievable. It doesn't seem to be a huge
3894 * problem at this time,
3895 *
3896 * It is possible that we have multiple paths for a prefix from
3897 * a peer
3898 * if that peer is using AddPath.
3899 */
3900 ain = rn->adj_in;
3901 while (ain) {
3902 ain_next = ain->next;
3903
3904 if (ain->peer == peer) {
3905 bgp_adj_in_remove(rn, ain);
3906 bgp_unlock_node(rn);
3907 }
3908
3909 ain = ain_next;
3910 }
3911
3912 for (ri = rn->info; ri; ri = next) {
3913 next = ri->next;
3914 if (ri->peer != peer)
3915 continue;
3916
3917 if (force)
3918 bgp_info_reap(rn, ri);
3919 else {
3920 struct bgp_clear_node_queue *cnq;
3921
3922 /* both unlocked in bgp_clear_node_queue_del */
3923 bgp_table_lock(bgp_node_table(rn));
3924 bgp_lock_node(rn);
3925 cnq = XCALLOC(
3926 MTYPE_BGP_CLEAR_NODE_QUEUE,
3927 sizeof(struct bgp_clear_node_queue));
3928 cnq->rn = rn;
3929 work_queue_add(peer->clear_node_queue, cnq);
3930 break;
3931 }
3932 }
3933 }
3934 return;
3935}
3936
3937void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
3938{
3939 struct bgp_node *rn;
3940 struct bgp_table *table;
3941
3942 if (peer->clear_node_queue == NULL)
3943 bgp_clear_node_queue_init(peer);
3944
3945 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3946 * Idle until it receives a Clearing_Completed event. This protects
3947 * against peers which flap faster than we can we clear, which could
3948 * lead to:
3949 *
3950 * a) race with routes from the new session being installed before
3951 * clear_route_node visits the node (to delete the route of that
3952 * peer)
3953 * b) resource exhaustion, clear_route_node likely leads to an entry
3954 * on the process_main queue. Fast-flapping could cause that queue
3955 * to grow and grow.
3956 */
3957
3958 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3959 * the unlock will happen upon work-queue completion; other wise, the
3960 * unlock happens at the end of this function.
3961 */
3962 if (!peer->clear_node_queue->thread)
3963 peer_lock(peer);
3964
3965 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
3966 bgp_clear_route_table(peer, afi, safi, NULL);
3967 else
3968 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3969 rn = bgp_route_next(rn))
3970 if ((table = rn->info) != NULL)
3971 bgp_clear_route_table(peer, afi, safi, table);
3972
3973 /* unlock if no nodes got added to the clear-node-queue. */
3974 if (!peer->clear_node_queue->thread)
3975 peer_unlock(peer);
718e3744 3976}
d62a17ae 3977
3978void bgp_clear_route_all(struct peer *peer)
718e3744 3979{
d62a17ae 3980 afi_t afi;
3981 safi_t safi;
718e3744 3982
05c7a1cc
QY
3983 FOREACH_AFI_SAFI (afi, safi)
3984 bgp_clear_route(peer, afi, safi);
65efcfce
LB
3985
3986#if ENABLE_BGP_VNC
d62a17ae 3987 rfapiProcessPeerDown(peer);
65efcfce 3988#endif
718e3744 3989}
3990
d62a17ae 3991void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3992{
d62a17ae 3993 struct bgp_table *table;
3994 struct bgp_node *rn;
3995 struct bgp_adj_in *ain;
3996 struct bgp_adj_in *ain_next;
718e3744 3997
d62a17ae 3998 table = peer->bgp->rib[afi][safi];
718e3744 3999
d62a17ae 4000 /* It is possible that we have multiple paths for a prefix from a peer
4001 * if that peer is using AddPath.
4002 */
4003 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4004 ain = rn->adj_in;
43143c8f 4005
d62a17ae 4006 while (ain) {
4007 ain_next = ain->next;
43143c8f 4008
d62a17ae 4009 if (ain->peer == peer) {
4010 bgp_adj_in_remove(rn, ain);
4011 bgp_unlock_node(rn);
4012 }
43143c8f 4013
d62a17ae 4014 ain = ain_next;
4015 }
4016 }
718e3744 4017}
93406d87 4018
d62a17ae 4019void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4020{
4021 struct bgp_node *rn;
4022 struct bgp_info *ri;
4023 struct bgp_table *table;
4024
4025 if (safi == SAFI_MPLS_VPN) {
4026 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4027 rn = bgp_route_next(rn)) {
4028 struct bgp_node *rm;
4029 struct bgp_info *ri;
4030
4031 /* look for neighbor in tables */
ea47320b
DL
4032 if ((table = rn->info) == NULL)
4033 continue;
4034
4035 for (rm = bgp_table_top(table); rm;
4036 rm = bgp_route_next(rm))
4037 for (ri = rm->info; ri; ri = ri->next) {
4038 if (ri->peer != peer)
4039 continue;
4040 if (!CHECK_FLAG(ri->flags,
4041 BGP_INFO_STALE))
4042 break;
4043
4044 bgp_rib_remove(rm, ri, peer, afi, safi);
4045 break;
4046 }
d62a17ae 4047 }
4048 } else {
4049 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4050 rn = bgp_route_next(rn))
ea47320b
DL
4051 for (ri = rn->info; ri; ri = ri->next) {
4052 if (ri->peer != peer)
4053 continue;
4054 if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE))
d62a17ae 4055 break;
ea47320b
DL
4056 bgp_rib_remove(rn, ri, peer, afi, safi);
4057 break;
4058 }
d62a17ae 4059 }
93406d87 4060}
6b0655a2 4061
568e10ca 4062static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4063 safi_t safi)
bb86c601 4064{
d62a17ae 4065 struct bgp_node *rn;
4066 struct bgp_info *ri;
4067 struct bgp_info *next;
bb86c601 4068
d62a17ae 4069 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4070 for (ri = rn->info; ri; ri = next) {
4071 next = ri->next;
4072 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
4073 && ri->type == ZEBRA_ROUTE_BGP
4074 && (ri->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
4075 || ri->sub_type == BGP_ROUTE_AGGREGATE
4076 || ri->sub_type == BGP_ROUTE_IMPORTED)) {
4077
d62a17ae 4078 if (bgp_fibupd_safi(safi))
568e10ca 4079 bgp_zebra_withdraw(&rn->p, ri,
4080 bgp, safi);
d62a17ae 4081 bgp_info_reap(rn, ri);
4082 }
4083 }
bb86c601
LB
4084}
4085
718e3744 4086/* Delete all kernel routes. */
d62a17ae 4087void bgp_cleanup_routes(struct bgp *bgp)
4088{
4089 afi_t afi;
4090 struct bgp_node *rn;
4091
4092 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4093 if (afi == AFI_L2VPN)
4094 continue;
568e10ca 4095 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4096 SAFI_UNICAST);
d62a17ae 4097 /*
4098 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4099 */
4100 if (afi != AFI_L2VPN) {
4101 safi_t safi;
4102 safi = SAFI_MPLS_VPN;
4103 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4104 rn = bgp_route_next(rn)) {
4105 if (rn->info) {
568e10ca 4106 bgp_cleanup_table(bgp,
d62a17ae 4107 (struct bgp_table *)(rn->info),
4108 safi);
4109 bgp_table_finish((struct bgp_table **)&(
4110 rn->info));
4111 rn->info = NULL;
4112 bgp_unlock_node(rn);
4113 }
4114 }
4115 safi = SAFI_ENCAP;
4116 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4117 rn = bgp_route_next(rn)) {
4118 if (rn->info) {
568e10ca 4119 bgp_cleanup_table(bgp,
d62a17ae 4120 (struct bgp_table *)(rn->info),
4121 safi);
4122 bgp_table_finish((struct bgp_table **)&(
4123 rn->info));
4124 rn->info = NULL;
4125 bgp_unlock_node(rn);
4126 }
4127 }
4128 }
4129 }
4130 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4131 rn = bgp_route_next(rn)) {
4132 if (rn->info) {
568e10ca 4133 bgp_cleanup_table(bgp,
4134 (struct bgp_table *)(rn->info),
d62a17ae 4135 SAFI_EVPN);
4136 bgp_table_finish((struct bgp_table **)&(rn->info));
4137 rn->info = NULL;
4138 bgp_unlock_node(rn);
4139 }
bb86c601 4140 }
718e3744 4141}
4142
d62a17ae 4143void bgp_reset(void)
718e3744 4144{
d62a17ae 4145 vty_reset();
4146 bgp_zclient_reset();
4147 access_list_reset();
4148 prefix_list_reset();
718e3744 4149}
6b0655a2 4150
d62a17ae 4151static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4152{
d62a17ae 4153 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4154 && CHECK_FLAG(peer->af_cap[afi][safi],
4155 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4156}
4157
718e3744 4158/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4159 value. */
d62a17ae 4160int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4161 struct bgp_nlri *packet)
4162{
d7c0a89a
QY
4163 uint8_t *pnt;
4164 uint8_t *lim;
d62a17ae 4165 struct prefix p;
4166 int psize;
4167 int ret;
4168 afi_t afi;
4169 safi_t safi;
4170 int addpath_encoded;
d7c0a89a 4171 uint32_t addpath_id;
d62a17ae 4172
d62a17ae 4173 pnt = packet->nlri;
4174 lim = pnt + packet->length;
4175 afi = packet->afi;
4176 safi = packet->safi;
4177 addpath_id = 0;
4178 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4179
4180 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4181 syntactic validity. If the field is syntactically incorrect,
4182 then the Error Subcode is set to Invalid Network Field. */
4183 for (; pnt < lim; pnt += psize) {
4184 /* Clear prefix structure. */
4185 memset(&p, 0, sizeof(struct prefix));
4186
4187 if (addpath_encoded) {
4188
4189 /* When packet overflow occurs return immediately. */
4190 if (pnt + BGP_ADDPATH_ID_LEN > lim)
4191 return -1;
4192
4193 addpath_id = ntohl(*((uint32_t *)pnt));
4194 pnt += BGP_ADDPATH_ID_LEN;
4195 }
718e3744 4196
d62a17ae 4197 /* Fetch prefix length. */
4198 p.prefixlen = *pnt++;
4199 /* afi/safi validity already verified by caller,
4200 * bgp_update_receive */
4201 p.family = afi2family(afi);
4202
4203 /* Prefix length check. */
4204 if (p.prefixlen > prefix_blen(&p) * 8) {
4205 zlog_err(
4206 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4207 peer->host, p.prefixlen, packet->afi);
4208 return -1;
4209 }
6b0655a2 4210
d62a17ae 4211 /* Packet size overflow check. */
4212 psize = PSIZE(p.prefixlen);
4213
4214 /* When packet overflow occur return immediately. */
4215 if (pnt + psize > lim) {
4216 zlog_err(
4217 "%s [Error] Update packet error (prefix length %d overflows packet)",
4218 peer->host, p.prefixlen);
4219 return -1;
4220 }
4221
4222 /* Defensive coding, double-check the psize fits in a struct
4223 * prefix */
4224 if (psize > (ssize_t)sizeof(p.u)) {
4225 zlog_err(
4226 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4227 peer->host, p.prefixlen, sizeof(p.u));
4228 return -1;
4229 }
4230
4231 /* Fetch prefix from NLRI packet. */
4232 memcpy(&p.u.prefix, pnt, psize);
4233
4234 /* Check address. */
4235 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4236 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4237 /* From RFC4271 Section 6.3:
4238 *
4239 * If a prefix in the NLRI field is semantically
4240 * incorrect
4241 * (e.g., an unexpected multicast IP address),
4242 * an error SHOULD
4243 * be logged locally, and the prefix SHOULD be
4244 * ignored.
a4d82a8a 4245 */
d62a17ae 4246 zlog_err(
4247 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4248 peer->host, inet_ntoa(p.u.prefix4));
4249 continue;
4250 }
4251 }
4252
4253 /* Check address. */
4254 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4255 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4256 char buf[BUFSIZ];
4257
4258 zlog_err(
4259 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4260 peer->host,
4261 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4262 BUFSIZ));
4263
4264 continue;
4265 }
4266 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4267 char buf[BUFSIZ];
4268
4269 zlog_err(
4270 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4271 peer->host,
4272 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4273 BUFSIZ));
4274
4275 continue;
4276 }
4277 }
4278
4279 /* Normal process. */
4280 if (attr)
4281 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4282 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4283 NULL, NULL, 0, 0, NULL);
d62a17ae 4284 else
4285 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4286 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4287 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4288 NULL);
d62a17ae 4289
4290 /* Address family configuration mismatch or maximum-prefix count
4291 overflow. */
4292 if (ret < 0)
4293 return -1;
4294 }
4295
4296 /* Packet length consistency check. */
4297 if (pnt != lim) {
4298 zlog_err(
4299 "%s [Error] Update packet error (prefix length mismatch with total length)",
4300 peer->host);
4301 return -1;
4302 }
6b0655a2 4303
d62a17ae 4304 return 0;
718e3744 4305}
4306
d62a17ae 4307static struct bgp_static *bgp_static_new(void)
718e3744 4308{
d62a17ae 4309 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4310}
4311
d62a17ae 4312static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4313{
d62a17ae 4314 if (bgp_static->rmap.name)
4315 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4316 if (bgp_static->eth_s_id)
4317 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
4318 XFREE(MTYPE_BGP_STATIC, bgp_static);
4319}
4320
4321void bgp_static_update(struct bgp *bgp, struct prefix *p,
4322 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4323{
4324 struct bgp_node *rn;
4325 struct bgp_info *ri;
4326 struct bgp_info *new;
4327 struct bgp_info info;
4328 struct attr attr;
4329 struct attr *attr_new;
4330 int ret;
65efcfce 4331#if ENABLE_BGP_VNC
d62a17ae 4332 int vnc_implicit_withdraw = 0;
65efcfce 4333#endif
fee0f4c6 4334
d62a17ae 4335 assert(bgp_static);
4336 if (!bgp_static)
4337 return;
dd8103a9 4338
d62a17ae 4339 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4340
d62a17ae 4341 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4342
d62a17ae 4343 attr.nexthop = bgp_static->igpnexthop;
4344 attr.med = bgp_static->igpmetric;
4345 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4346
d62a17ae 4347 if (bgp_static->atomic)
4348 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4349
d62a17ae 4350 /* Store label index, if required. */
4351 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4352 attr.label_index = bgp_static->label_index;
4353 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4354 }
718e3744 4355
d62a17ae 4356 /* Apply route-map. */
4357 if (bgp_static->rmap.name) {
4358 struct attr attr_tmp = attr;
4359 info.peer = bgp->peer_self;
4360 info.attr = &attr_tmp;
fee0f4c6 4361
d62a17ae 4362 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4363
d62a17ae 4364 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
fee0f4c6 4365
d62a17ae 4366 bgp->peer_self->rmap_type = 0;
718e3744 4367
d62a17ae 4368 if (ret == RMAP_DENYMATCH) {
4369 /* Free uninterned attribute. */
4370 bgp_attr_flush(&attr_tmp);
718e3744 4371
d62a17ae 4372 /* Unintern original. */
4373 aspath_unintern(&attr.aspath);
4374 bgp_static_withdraw(bgp, p, afi, safi);
4375 return;
4376 }
7f323236
DW
4377
4378 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4379 bgp_attr_add_gshut_community(&attr_tmp);
4380
d62a17ae 4381 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4382 } else {
4383
4384 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4385 bgp_attr_add_gshut_community(&attr);
4386
d62a17ae 4387 attr_new = bgp_attr_intern(&attr);
7f323236 4388 }
718e3744 4389
d62a17ae 4390 for (ri = rn->info; ri; ri = ri->next)
4391 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4392 && ri->sub_type == BGP_ROUTE_STATIC)
4393 break;
4394
4395 if (ri) {
4396 if (attrhash_cmp(ri->attr, attr_new)
4397 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
4398 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4399 bgp_unlock_node(rn);
4400 bgp_attr_unintern(&attr_new);
4401 aspath_unintern(&attr.aspath);
4402 return;
4403 } else {
4404 /* The attribute is changed. */
4405 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4406
4407 /* Rewrite BGP route information. */
4408 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4409 bgp_info_restore(rn, ri);
4410 else
4411 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
65efcfce 4412#if ENABLE_BGP_VNC
d62a17ae 4413 if ((afi == AFI_IP || afi == AFI_IP6)
4414 && (safi == SAFI_UNICAST)) {
4415 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
4416 /*
4417 * Implicit withdraw case.
4418 * We have to do this before ri is
4419 * changed
4420 */
4421 ++vnc_implicit_withdraw;
4422 vnc_import_bgp_del_route(bgp, p, ri);
4423 vnc_import_bgp_exterior_del_route(
4424 bgp, p, ri);
4425 }
4426 }
65efcfce 4427#endif
d62a17ae 4428 bgp_attr_unintern(&ri->attr);
4429 ri->attr = attr_new;
4430 ri->uptime = bgp_clock();
65efcfce 4431#if ENABLE_BGP_VNC
d62a17ae 4432 if ((afi == AFI_IP || afi == AFI_IP6)
4433 && (safi == SAFI_UNICAST)) {
4434 if (vnc_implicit_withdraw) {
4435 vnc_import_bgp_add_route(bgp, p, ri);
4436 vnc_import_bgp_exterior_add_route(
4437 bgp, p, ri);
4438 }
4439 }
65efcfce 4440#endif
718e3744 4441
d62a17ae 4442 /* Nexthop reachability check. */
4443 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4444 && (safi == SAFI_UNICAST
4445 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4446
4447 struct bgp *bgp_nexthop = bgp;
4448
4449 if (ri->extra && ri->extra->bgp_orig)
4450 bgp_nexthop = ri->extra->bgp_orig;
4451
4452 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4453 afi, ri, NULL, 0))
d62a17ae 4454 bgp_info_set_flag(rn, ri,
4455 BGP_INFO_VALID);
4456 else {
4457 if (BGP_DEBUG(nht, NHT)) {
4458 char buf1[INET6_ADDRSTRLEN];
4459 inet_ntop(p->family,
4460 &p->u.prefix, buf1,
4461 INET6_ADDRSTRLEN);
4462 zlog_debug(
4463 "%s(%s): Route not in table, not advertising",
4464 __FUNCTION__, buf1);
4465 }
4466 bgp_info_unset_flag(rn, ri,
4467 BGP_INFO_VALID);
4468 }
4469 } else {
4470 /* Delete the NHT structure if any, if we're
4471 * toggling between
4472 * enabling/disabling import check. We
4473 * deregister the route
4474 * from NHT to avoid overloading NHT and the
4475 * process interaction
4476 */
4477 bgp_unlink_nexthop(ri);
4478 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
4479 }
4480 /* Process change. */
4481 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4482 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4483
4484 if (SAFI_UNICAST == safi
4485 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4486 || bgp->inst_type
4487 == BGP_INSTANCE_TYPE_DEFAULT)) {
4488 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
4489 ri);
4490 }
4491
d62a17ae 4492 bgp_unlock_node(rn);
4493 aspath_unintern(&attr.aspath);
4494 return;
4495 }
718e3744 4496 }
718e3744 4497
d62a17ae 4498 /* Make new BGP info. */
4499 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4500 attr_new, rn);
4501 /* Nexthop reachability check. */
4502 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4503 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4504 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
d62a17ae 4505 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
4506 else {
4507 if (BGP_DEBUG(nht, NHT)) {
4508 char buf1[INET6_ADDRSTRLEN];
4509 inet_ntop(p->family, &p->u.prefix, buf1,
4510 INET6_ADDRSTRLEN);
4511 zlog_debug(
4512 "%s(%s): Route not in table, not advertising",
4513 __FUNCTION__, buf1);
4514 }
4515 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
4516 }
4517 } else {
4518 /* Delete the NHT structure if any, if we're toggling between
4519 * enabling/disabling import check. We deregister the route
4520 * from NHT to avoid overloading NHT and the process interaction
4521 */
4522 bgp_unlink_nexthop(new);
4523
4524 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
fc9a856f 4525 }
078430f6 4526
d62a17ae 4527 /* Aggregate address increment. */
4528 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4529
d62a17ae 4530 /* Register new BGP information. */
4531 bgp_info_add(rn, new);
718e3744 4532
d62a17ae 4533 /* route_node_get lock */
4534 bgp_unlock_node(rn);
4535
4536 /* Process change. */
4537 bgp_process(bgp, rn, afi, safi);
4538
ddb5b488
PZ
4539 if (SAFI_UNICAST == safi
4540 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4541 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4542 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4543 }
4544
d62a17ae 4545 /* Unintern original. */
4546 aspath_unintern(&attr.aspath);
718e3744 4547}
4548
d62a17ae 4549void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4550 safi_t safi)
718e3744 4551{
d62a17ae 4552 struct bgp_node *rn;
4553 struct bgp_info *ri;
718e3744 4554
d62a17ae 4555 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4556
d62a17ae 4557 /* Check selected route and self inserted route. */
4558 for (ri = rn->info; ri; ri = ri->next)
4559 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4560 && ri->sub_type == BGP_ROUTE_STATIC)
4561 break;
4562
4563 /* Withdraw static BGP route from routing table. */
4564 if (ri) {
ddb5b488
PZ
4565 if (SAFI_UNICAST == safi
4566 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4567 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4568 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
4569 }
d62a17ae 4570 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4571 bgp_unlink_nexthop(ri);
4572 bgp_info_delete(rn, ri);
4573 bgp_process(bgp, rn, afi, safi);
4574 }
718e3744 4575
d62a17ae 4576 /* Unlock bgp_node_lookup. */
4577 bgp_unlock_node(rn);
718e3744 4578}
4579
137446f9
LB
4580/*
4581 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4582 */
d62a17ae 4583static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4584 afi_t afi, safi_t safi,
4585 struct prefix_rd *prd)
718e3744 4586{
d62a17ae 4587 struct bgp_node *rn;
4588 struct bgp_info *ri;
718e3744 4589
d62a17ae 4590 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4591
d62a17ae 4592 /* Check selected route and self inserted route. */
4593 for (ri = rn->info; ri; ri = ri->next)
4594 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4595 && ri->sub_type == BGP_ROUTE_STATIC)
4596 break;
718e3744 4597
d62a17ae 4598 /* Withdraw static BGP route from routing table. */
4599 if (ri) {
65efcfce 4600#if ENABLE_BGP_VNC
d62a17ae 4601 rfapiProcessWithdraw(
4602 ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type,
4603 1); /* Kill, since it is an administrative change */
65efcfce 4604#endif
ddb5b488
PZ
4605 if (SAFI_MPLS_VPN == safi
4606 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4607 vpn_leak_to_vrf_withdraw(bgp, ri);
4608 }
d62a17ae 4609 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4610 bgp_info_delete(rn, ri);
4611 bgp_process(bgp, rn, afi, safi);
4612 }
718e3744 4613
d62a17ae 4614 /* Unlock bgp_node_lookup. */
4615 bgp_unlock_node(rn);
718e3744 4616}
4617
d62a17ae 4618static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4619 struct bgp_static *bgp_static, afi_t afi,
4620 safi_t safi)
137446f9 4621{
d62a17ae 4622 struct bgp_node *rn;
4623 struct bgp_info *new;
4624 struct attr *attr_new;
4625 struct attr attr = {0};
4626 struct bgp_info *ri;
65efcfce 4627#if ENABLE_BGP_VNC
d62a17ae 4628 mpls_label_t label = 0;
65efcfce 4629#endif
d7c0a89a 4630 uint32_t num_labels = 0;
d62a17ae 4631 union gw_addr add;
137446f9 4632
d62a17ae 4633 assert(bgp_static);
137446f9 4634
b57ba6d2
MK
4635 if (bgp_static->label != MPLS_INVALID_LABEL)
4636 num_labels = 1;
d62a17ae 4637 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4638 &bgp_static->prd);
137446f9 4639
d62a17ae 4640 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4641
d62a17ae 4642 attr.nexthop = bgp_static->igpnexthop;
4643 attr.med = bgp_static->igpmetric;
4644 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4645
d62a17ae 4646 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4647 || (safi == SAFI_ENCAP)) {
4648 if (afi == AFI_IP) {
4649 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4650 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4651 }
4652 }
4653 if (afi == AFI_L2VPN) {
4654 if (bgp_static->gatewayIp.family == AF_INET)
4655 add.ipv4.s_addr =
4656 bgp_static->gatewayIp.u.prefix4.s_addr;
4657 else if (bgp_static->gatewayIp.family == AF_INET6)
4658 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4659 sizeof(struct in6_addr));
4660 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4661 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4662 struct bgp_encap_type_vxlan bet;
4663 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4664 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4665 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4666 }
4667 if (bgp_static->router_mac) {
4668 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4669 }
4670 }
4671 /* Apply route-map. */
4672 if (bgp_static->rmap.name) {
4673 struct attr attr_tmp = attr;
4674 struct bgp_info info;
4675 int ret;
137446f9 4676
d62a17ae 4677 info.peer = bgp->peer_self;
4678 info.attr = &attr_tmp;
137446f9 4679
d62a17ae 4680 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4681
d62a17ae 4682 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
137446f9 4683
d62a17ae 4684 bgp->peer_self->rmap_type = 0;
137446f9 4685
d62a17ae 4686 if (ret == RMAP_DENYMATCH) {
4687 /* Free uninterned attribute. */
4688 bgp_attr_flush(&attr_tmp);
137446f9 4689
d62a17ae 4690 /* Unintern original. */
4691 aspath_unintern(&attr.aspath);
4692 bgp_static_withdraw_safi(bgp, p, afi, safi,
4693 &bgp_static->prd);
4694 return;
4695 }
137446f9 4696
d62a17ae 4697 attr_new = bgp_attr_intern(&attr_tmp);
4698 } else {
4699 attr_new = bgp_attr_intern(&attr);
4700 }
137446f9 4701
d62a17ae 4702 for (ri = rn->info; ri; ri = ri->next)
4703 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4704 && ri->sub_type == BGP_ROUTE_STATIC)
4705 break;
4706
4707 if (ri) {
4708 union gw_addr add;
4709 memset(&add, 0, sizeof(union gw_addr));
4710 if (attrhash_cmp(ri->attr, attr_new)
4711 && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add)
4712 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
4713 bgp_unlock_node(rn);
4714 bgp_attr_unintern(&attr_new);
4715 aspath_unintern(&attr.aspath);
4716 return;
4717 } else {
4718 /* The attribute is changed. */
4719 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4720
4721 /* Rewrite BGP route information. */
4722 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4723 bgp_info_restore(rn, ri);
4724 else
4725 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4726 bgp_attr_unintern(&ri->attr);
4727 ri->attr = attr_new;
4728 ri->uptime = bgp_clock();
65efcfce 4729#if ENABLE_BGP_VNC
d62a17ae 4730 if (ri->extra)
317f1fe0 4731 label = decode_label(&ri->extra->label[0]);
65efcfce 4732#endif
137446f9 4733
d62a17ae 4734 /* Process change. */
4735 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4736 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4737
4738 if (SAFI_MPLS_VPN == safi
4739 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4740 vpn_leak_to_vrf_update(bgp, ri);
4741 }
65efcfce 4742#if ENABLE_BGP_VNC
d62a17ae 4743 rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
4744 ri->attr, afi, safi, ri->type,
4745 ri->sub_type, &label);
65efcfce 4746#endif
d62a17ae 4747 bgp_unlock_node(rn);
4748 aspath_unintern(&attr.aspath);
4749 return;
4750 }
4751 }
137446f9
LB
4752
4753
d62a17ae 4754 /* Make new BGP info. */
4755 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4756 attr_new, rn);
4757 SET_FLAG(new->flags, BGP_INFO_VALID);
4758 new->extra = bgp_info_extra_new();
b57ba6d2
MK
4759 if (num_labels) {
4760 new->extra->label[0] = bgp_static->label;
4761 new->extra->num_labels = num_labels;
4762 }
65efcfce 4763#if ENABLE_BGP_VNC
d62a17ae 4764 label = decode_label(&bgp_static->label);
65efcfce 4765#endif
137446f9 4766
d62a17ae 4767 /* Aggregate address increment. */
4768 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 4769
d62a17ae 4770 /* Register new BGP information. */
4771 bgp_info_add(rn, new);
4772 /* route_node_get lock */
4773 bgp_unlock_node(rn);
137446f9 4774
d62a17ae 4775 /* Process change. */
4776 bgp_process(bgp, rn, afi, safi);
137446f9 4777
ddb5b488
PZ
4778 if (SAFI_MPLS_VPN == safi
4779 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4780 vpn_leak_to_vrf_update(bgp, new);
4781 }
65efcfce 4782#if ENABLE_BGP_VNC
d62a17ae 4783 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
4784 safi, new->type, new->sub_type, &label);
65efcfce
LB
4785#endif
4786
d62a17ae 4787 /* Unintern original. */
4788 aspath_unintern(&attr.aspath);
137446f9
LB
4789}
4790
718e3744 4791/* Configure static BGP network. When user don't run zebra, static
4792 route should be installed as valid. */
e2a86ad9
DS
4793static int bgp_static_set(struct vty *vty, const char *negate,
4794 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 4795 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 4796{
4797 VTY_DECLVAR_CONTEXT(bgp, bgp);
4798 int ret;
4799 struct prefix p;
4800 struct bgp_static *bgp_static;
4801 struct bgp_node *rn;
d7c0a89a 4802 uint8_t need_update = 0;
d62a17ae 4803
4804 /* Convert IP prefix string to struct prefix. */
4805 ret = str2prefix(ip_str, &p);
4806 if (!ret) {
4807 vty_out(vty, "%% Malformed prefix\n");
4808 return CMD_WARNING_CONFIG_FAILED;
4809 }
4810 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4811 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4812 return CMD_WARNING_CONFIG_FAILED;
4813 }
718e3744 4814
d62a17ae 4815 apply_mask(&p);
718e3744 4816
e2a86ad9 4817 if (negate) {
718e3744 4818
e2a86ad9
DS
4819 /* Set BGP static route configuration. */
4820 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 4821
e2a86ad9 4822 if (!rn) {
a4d82a8a 4823 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 4824 return CMD_WARNING_CONFIG_FAILED;
4825 }
4826
e2a86ad9 4827 bgp_static = rn->info;
d62a17ae 4828
e2a86ad9
DS
4829 if ((label_index != BGP_INVALID_LABEL_INDEX)
4830 && (label_index != bgp_static->label_index)) {
4831 vty_out(vty,
4832 "%% label-index doesn't match static route\n");
4833 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4834 }
d62a17ae 4835
e2a86ad9
DS
4836 if ((rmap && bgp_static->rmap.name)
4837 && strcmp(rmap, bgp_static->rmap.name)) {
4838 vty_out(vty,
4839 "%% route-map name doesn't match static route\n");
4840 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4841 }
718e3744 4842
e2a86ad9
DS
4843 /* Update BGP RIB. */
4844 if (!bgp_static->backdoor)
4845 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 4846
e2a86ad9
DS
4847 /* Clear configuration. */
4848 bgp_static_free(bgp_static);
4849 rn->info = NULL;
4850 bgp_unlock_node(rn);
4851 bgp_unlock_node(rn);
4852 } else {
718e3744 4853
e2a86ad9
DS
4854 /* Set BGP static route configuration. */
4855 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 4856
e2a86ad9
DS
4857 if (rn->info) {
4858 /* Configuration change. */
4859 bgp_static = rn->info;
718e3744 4860
e2a86ad9
DS
4861 /* Label index cannot be changed. */
4862 if (bgp_static->label_index != label_index) {
4863 vty_out(vty, "%% cannot change label-index\n");
4864 return CMD_WARNING_CONFIG_FAILED;
4865 }
d62a17ae 4866
e2a86ad9 4867 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
4868 if (bgp_static->valid
4869 && bgp_static->backdoor != backdoor)
e2a86ad9 4870 need_update = 1;
718e3744 4871
e2a86ad9 4872 bgp_static->backdoor = backdoor;
718e3744 4873
e2a86ad9
DS
4874 if (rmap) {
4875 if (bgp_static->rmap.name)
4876 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4877 bgp_static->rmap.name);
e2a86ad9
DS
4878 bgp_static->rmap.name =
4879 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4880 bgp_static->rmap.map =
4881 route_map_lookup_by_name(rmap);
4882 } else {
4883 if (bgp_static->rmap.name)
4884 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4885 bgp_static->rmap.name);
e2a86ad9
DS
4886 bgp_static->rmap.name = NULL;
4887 bgp_static->rmap.map = NULL;
4888 bgp_static->valid = 0;
4889 }
4890 bgp_unlock_node(rn);
4891 } else {
4892 /* New configuration. */
4893 bgp_static = bgp_static_new();
4894 bgp_static->backdoor = backdoor;
4895 bgp_static->valid = 0;
4896 bgp_static->igpmetric = 0;
4897 bgp_static->igpnexthop.s_addr = 0;
4898 bgp_static->label_index = label_index;
718e3744 4899
e2a86ad9
DS
4900 if (rmap) {
4901 if (bgp_static->rmap.name)
4902 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4903 bgp_static->rmap.name);
e2a86ad9
DS
4904 bgp_static->rmap.name =
4905 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4906 bgp_static->rmap.map =
4907 route_map_lookup_by_name(rmap);
4908 }
4909 rn->info = bgp_static;
4910 }
d62a17ae 4911
e2a86ad9
DS
4912 bgp_static->valid = 1;
4913 if (need_update)
4914 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 4915
e2a86ad9
DS
4916 if (!bgp_static->backdoor)
4917 bgp_static_update(bgp, &p, bgp_static, afi, safi);
4918 }
d62a17ae 4919
4920 return CMD_SUCCESS;
4921}
4922
4923void bgp_static_add(struct bgp *bgp)
4924{
4925 afi_t afi;
4926 safi_t safi;
4927 struct bgp_node *rn;
4928 struct bgp_node *rm;
4929 struct bgp_table *table;
4930 struct bgp_static *bgp_static;
4931
05c7a1cc
QY
4932 FOREACH_AFI_SAFI (afi, safi)
4933 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4934 rn = bgp_route_next(rn)) {
4935 if (rn->info == NULL)
4936 continue;
ea47320b 4937
05c7a1cc
QY
4938 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4939 || (safi == SAFI_EVPN)) {
4940 table = rn->info;
4941
4942 for (rm = bgp_table_top(table); rm;
4943 rm = bgp_route_next(rm)) {
4944 bgp_static = rm->info;
4945 bgp_static_update_safi(bgp, &rm->p,
4946 bgp_static, afi,
4947 safi);
d62a17ae 4948 }
05c7a1cc
QY
4949 } else {
4950 bgp_static_update(bgp, &rn->p, rn->info, afi,
4951 safi);
ea47320b 4952 }
05c7a1cc 4953 }
6aeb9e78
DS
4954}
4955
718e3744 4956/* Called from bgp_delete(). Delete all static routes from the BGP
4957 instance. */
d62a17ae 4958void bgp_static_delete(struct bgp *bgp)
4959{
4960 afi_t afi;
4961 safi_t safi;
4962 struct bgp_node *rn;
4963 struct bgp_node *rm;
4964 struct bgp_table *table;
4965 struct bgp_static *bgp_static;
4966
05c7a1cc
QY
4967 FOREACH_AFI_SAFI (afi, safi)
4968 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4969 rn = bgp_route_next(rn)) {
4970 if (rn->info == NULL)
4971 continue;
ea47320b 4972
05c7a1cc
QY
4973 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4974 || (safi == SAFI_EVPN)) {
4975 table = rn->info;
4976
4977 for (rm = bgp_table_top(table); rm;
4978 rm = bgp_route_next(rm)) {
4979 bgp_static = rm->info;
4980 bgp_static_withdraw_safi(
4981 bgp, &rm->p, AFI_IP, safi,
4982 (struct prefix_rd *)&rn->p);
ea47320b
DL
4983 bgp_static_free(bgp_static);
4984 rn->info = NULL;
4985 bgp_unlock_node(rn);
d62a17ae 4986 }
05c7a1cc
QY
4987 } else {
4988 bgp_static = rn->info;
4989 bgp_static_withdraw(bgp, &rn->p, afi, safi);
4990 bgp_static_free(bgp_static);
4991 rn->info = NULL;
4992 bgp_unlock_node(rn);
ea47320b 4993 }
05c7a1cc 4994 }
d62a17ae 4995}
4996
4997void bgp_static_redo_import_check(struct bgp *bgp)
4998{
4999 afi_t afi;
5000 safi_t safi;
5001 struct bgp_node *rn;
5002 struct bgp_node *rm;
5003 struct bgp_table *table;
5004 struct bgp_static *bgp_static;
5005
5006 /* Use this flag to force reprocessing of the route */
5007 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5008 FOREACH_AFI_SAFI (afi, safi) {
5009 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5010 rn = bgp_route_next(rn)) {
5011 if (rn->info == NULL)
5012 continue;
ea47320b 5013
05c7a1cc
QY
5014 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5015 || (safi == SAFI_EVPN)) {
5016 table = rn->info;
5017
5018 for (rm = bgp_table_top(table); rm;
5019 rm = bgp_route_next(rm)) {
5020 bgp_static = rm->info;
5021 bgp_static_update_safi(bgp, &rm->p,
5022 bgp_static, afi,
5023 safi);
d62a17ae 5024 }
05c7a1cc
QY
5025 } else {
5026 bgp_static = rn->info;
5027 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5028 safi);
ea47320b 5029 }
05c7a1cc
QY
5030 }
5031 }
d62a17ae 5032 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5033}
5034
5035static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5036 safi_t safi)
5037{
5038 struct bgp_table *table;
5039 struct bgp_node *rn;
5040 struct bgp_info *ri;
5041
5042 table = bgp->rib[afi][safi];
5043 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5044 for (ri = rn->info; ri; ri = ri->next) {
5045 if (ri->peer == bgp->peer_self
5046 && ((ri->type == ZEBRA_ROUTE_BGP
5047 && ri->sub_type == BGP_ROUTE_STATIC)
5048 || (ri->type != ZEBRA_ROUTE_BGP
5049 && ri->sub_type
5050 == BGP_ROUTE_REDISTRIBUTE))) {
5051 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
5052 safi);
5053 bgp_unlink_nexthop(ri);
5054 bgp_info_delete(rn, ri);
5055 bgp_process(bgp, rn, afi, safi);
5056 }
5057 }
5058 }
ad4cbda1 5059}
5060
5061/*
5062 * Purge all networks and redistributed routes from routing table.
5063 * Invoked upon the instance going down.
5064 */
d62a17ae 5065void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5066{
d62a17ae 5067 afi_t afi;
5068 safi_t safi;
ad4cbda1 5069
05c7a1cc
QY
5070 FOREACH_AFI_SAFI (afi, safi)
5071 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5072}
5073
137446f9
LB
5074/*
5075 * gpz 110624
5076 * Currently this is used to set static routes for VPN and ENCAP.
5077 * I think it can probably be factored with bgp_static_set.
5078 */
d62a17ae 5079int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5080 const char *ip_str, const char *rd_str,
5081 const char *label_str, const char *rmap_str,
5082 int evpn_type, const char *esi, const char *gwip,
5083 const char *ethtag, const char *routermac)
5084{
5085 VTY_DECLVAR_CONTEXT(bgp, bgp);
5086 int ret;
5087 struct prefix p;
5088 struct prefix_rd prd;
5089 struct bgp_node *prn;
5090 struct bgp_node *rn;
5091 struct bgp_table *table;
5092 struct bgp_static *bgp_static;
5093 mpls_label_t label = MPLS_INVALID_LABEL;
5094 struct prefix gw_ip;
5095
5096 /* validate ip prefix */
5097 ret = str2prefix(ip_str, &p);
5098 if (!ret) {
5099 vty_out(vty, "%% Malformed prefix\n");
5100 return CMD_WARNING_CONFIG_FAILED;
5101 }
5102 apply_mask(&p);
5103 if ((afi == AFI_L2VPN)
5104 && (bgp_build_evpn_prefix(evpn_type,
5105 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5106 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5107 return CMD_WARNING_CONFIG_FAILED;
5108 }
718e3744 5109
d62a17ae 5110 ret = str2prefix_rd(rd_str, &prd);
5111 if (!ret) {
5112 vty_out(vty, "%% Malformed rd\n");
5113 return CMD_WARNING_CONFIG_FAILED;
5114 }
718e3744 5115
d62a17ae 5116 if (label_str) {
5117 unsigned long label_val;
5118 label_val = strtoul(label_str, NULL, 10);
5119 encode_label(label_val, &label);
5120 }
9bedbb1e 5121
d62a17ae 5122 if (safi == SAFI_EVPN) {
5123 if (esi && str2esi(esi, NULL) == 0) {
5124 vty_out(vty, "%% Malformed ESI\n");
5125 return CMD_WARNING_CONFIG_FAILED;
5126 }
5127 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5128 vty_out(vty, "%% Malformed Router MAC\n");
5129 return CMD_WARNING_CONFIG_FAILED;
5130 }
5131 if (gwip) {
5132 memset(&gw_ip, 0, sizeof(struct prefix));
5133 ret = str2prefix(gwip, &gw_ip);
5134 if (!ret) {
5135 vty_out(vty, "%% Malformed GatewayIp\n");
5136 return CMD_WARNING_CONFIG_FAILED;
5137 }
5138 if ((gw_ip.family == AF_INET
3714a385 5139 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5140 (struct prefix_evpn *)&p))
5141 || (gw_ip.family == AF_INET6
3714a385 5142 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5143 (struct prefix_evpn *)&p))) {
5144 vty_out(vty,
5145 "%% GatewayIp family differs with IP prefix\n");
5146 return CMD_WARNING_CONFIG_FAILED;
5147 }
5148 }
5149 }
5150 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5151 if (prn->info == NULL)
960035b2 5152 prn->info = bgp_table_init(bgp, afi, safi);
d62a17ae 5153 else
5154 bgp_unlock_node(prn);
5155 table = prn->info;
5156
5157 rn = bgp_node_get(table, &p);
5158
5159 if (rn->info) {
5160 vty_out(vty, "%% Same network configuration exists\n");
5161 bgp_unlock_node(rn);
5162 } else {
5163 /* New configuration. */
5164 bgp_static = bgp_static_new();
5165 bgp_static->backdoor = 0;
5166 bgp_static->valid = 0;
5167 bgp_static->igpmetric = 0;
5168 bgp_static->igpnexthop.s_addr = 0;
5169 bgp_static->label = label;
5170 bgp_static->prd = prd;
5171
5172 if (rmap_str) {
5173 if (bgp_static->rmap.name)
5174 XFREE(MTYPE_ROUTE_MAP_NAME,
5175 bgp_static->rmap.name);
5176 bgp_static->rmap.name =
5177 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5178 bgp_static->rmap.map =
5179 route_map_lookup_by_name(rmap_str);
5180 }
718e3744 5181
d62a17ae 5182 if (safi == SAFI_EVPN) {
5183 if (esi) {
5184 bgp_static->eth_s_id =
5185 XCALLOC(MTYPE_ATTR,
5186 sizeof(struct eth_segment_id));
5187 str2esi(esi, bgp_static->eth_s_id);
5188 }
5189 if (routermac) {
5190 bgp_static->router_mac =
28328ea9 5191 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
d62a17ae 5192 prefix_str2mac(routermac,
5193 bgp_static->router_mac);
5194 }
5195 if (gwip)
5196 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5197 }
5198 rn->info = bgp_static;
718e3744 5199
d62a17ae 5200 bgp_static->valid = 1;
5201 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5202 }
718e3744 5203
d62a17ae 5204 return CMD_SUCCESS;
718e3744 5205}
5206
5207/* Configure static BGP network. */
d62a17ae 5208int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5209 const char *ip_str, const char *rd_str,
5210 const char *label_str, int evpn_type, const char *esi,
5211 const char *gwip, const char *ethtag)
5212{
5213 VTY_DECLVAR_CONTEXT(bgp, bgp);
5214 int ret;
5215 struct prefix p;
5216 struct prefix_rd prd;
5217 struct bgp_node *prn;
5218 struct bgp_node *rn;
5219 struct bgp_table *table;
5220 struct bgp_static *bgp_static;
5221 mpls_label_t label = MPLS_INVALID_LABEL;
5222
5223 /* Convert IP prefix string to struct prefix. */
5224 ret = str2prefix(ip_str, &p);
5225 if (!ret) {
5226 vty_out(vty, "%% Malformed prefix\n");
5227 return CMD_WARNING_CONFIG_FAILED;
5228 }
5229 apply_mask(&p);
5230 if ((afi == AFI_L2VPN)
5231 && (bgp_build_evpn_prefix(evpn_type,
5232 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5233 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5234 return CMD_WARNING_CONFIG_FAILED;
5235 }
5236 ret = str2prefix_rd(rd_str, &prd);
5237 if (!ret) {
5238 vty_out(vty, "%% Malformed rd\n");
5239 return CMD_WARNING_CONFIG_FAILED;
5240 }
718e3744 5241
d62a17ae 5242 if (label_str) {
5243 unsigned long label_val;
5244 label_val = strtoul(label_str, NULL, 10);
5245 encode_label(label_val, &label);
5246 }
718e3744 5247
d62a17ae 5248 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5249 if (prn->info == NULL)
960035b2 5250 prn->info = bgp_table_init(bgp, afi, safi);
d62a17ae 5251 else
5252 bgp_unlock_node(prn);
5253 table = prn->info;
718e3744 5254
d62a17ae 5255 rn = bgp_node_lookup(table, &p);
6b0655a2 5256
d62a17ae 5257 if (rn) {
5258 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5259
d62a17ae 5260 bgp_static = rn->info;
5261 bgp_static_free(bgp_static);
5262 rn->info = NULL;
5263 bgp_unlock_node(rn);
5264 bgp_unlock_node(rn);
5265 } else
5266 vty_out(vty, "%% Can't find the route\n");
5267
5268 return CMD_SUCCESS;
5269}
5270
5271static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5272 const char *rmap_name)
5273{
5274 VTY_DECLVAR_CONTEXT(bgp, bgp);
5275 struct bgp_rmap *rmap;
5276
5277 rmap = &bgp->table_map[afi][safi];
5278 if (rmap_name) {
5279 if (rmap->name)
5280 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5281 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5282 rmap->map = route_map_lookup_by_name(rmap_name);
5283 } else {
5284 if (rmap->name)
5285 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5286 rmap->name = NULL;
5287 rmap->map = NULL;
5288 }
73ac8160 5289
d62a17ae 5290 if (bgp_fibupd_safi(safi))
5291 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5292
d62a17ae 5293 return CMD_SUCCESS;
73ac8160
DS
5294}
5295
d62a17ae 5296static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5297 const char *rmap_name)
73ac8160 5298{
d62a17ae 5299 VTY_DECLVAR_CONTEXT(bgp, bgp);
5300 struct bgp_rmap *rmap;
73ac8160 5301
d62a17ae 5302 rmap = &bgp->table_map[afi][safi];
5303 if (rmap->name)
5304 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5305 rmap->name = NULL;
5306 rmap->map = NULL;
73ac8160 5307
d62a17ae 5308 if (bgp_fibupd_safi(safi))
5309 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5310
d62a17ae 5311 return CMD_SUCCESS;
73ac8160
DS
5312}
5313
2b791107 5314void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5315 safi_t safi)
73ac8160 5316{
d62a17ae 5317 if (bgp->table_map[afi][safi].name) {
d62a17ae 5318 vty_out(vty, " table-map %s\n",
5319 bgp->table_map[afi][safi].name);
5320 }
73ac8160
DS
5321}
5322
73ac8160
DS
5323DEFUN (bgp_table_map,
5324 bgp_table_map_cmd,
5325 "table-map WORD",
5326 "BGP table to RIB route download filter\n"
5327 "Name of the route map\n")
5328{
d62a17ae 5329 int idx_word = 1;
5330 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5331 argv[idx_word]->arg);
73ac8160
DS
5332}
5333DEFUN (no_bgp_table_map,
5334 no_bgp_table_map_cmd,
5335 "no table-map WORD",
3a2d747c 5336 NO_STR
73ac8160
DS
5337 "BGP table to RIB route download filter\n"
5338 "Name of the route map\n")
5339{
d62a17ae 5340 int idx_word = 2;
5341 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5342 argv[idx_word]->arg);
73ac8160
DS
5343}
5344
e2a86ad9
DS
5345DEFPY(bgp_network,
5346 bgp_network_cmd,
5347 "[no] network \
5348 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5349 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5350 backdoor$backdoor}]",
5351 NO_STR
5352 "Specify a network to announce via BGP\n"
5353 "IPv4 prefix\n"
5354 "Network number\n"
5355 "Network mask\n"
5356 "Network mask\n"
5357 "Route-map to modify the attributes\n"
5358 "Name of the route map\n"
5359 "Label index to associate with the prefix\n"
5360 "Label index value\n"
5361 "Specify a BGP backdoor route\n")
5362{
5363 char addr_prefix_str[BUFSIZ];
5364
5365 if (address_str) {
5366 int ret;
718e3744 5367
e2a86ad9
DS
5368 ret = netmask_str2prefix_str(address_str, netmask_str,
5369 addr_prefix_str);
5370 if (!ret) {
5371 vty_out(vty, "%% Inconsistent address and mask\n");
5372 return CMD_WARNING_CONFIG_FAILED;
5373 }
d62a17ae 5374 }
718e3744 5375
a4d82a8a
PZ
5376 return bgp_static_set(
5377 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5378 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5379 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5380}
5381
e2a86ad9
DS
5382DEFPY(ipv6_bgp_network,
5383 ipv6_bgp_network_cmd,
5384 "[no] network X:X::X:X/M$prefix \
5385 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5386 NO_STR
5387 "Specify a network to announce via BGP\n"
5388 "IPv6 prefix\n"
5389 "Route-map to modify the attributes\n"
5390 "Name of the route map\n"
5391 "Label index to associate with the prefix\n"
5392 "Label index value\n")
718e3744 5393{
a4d82a8a
PZ
5394 return bgp_static_set(
5395 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5396 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5397}
5398
718e3744 5399/* Aggreagete address:
5400
5401 advertise-map Set condition to advertise attribute
5402 as-set Generate AS set path information
5403 attribute-map Set attributes of aggregate
5404 route-map Set parameters of aggregate
5405 summary-only Filter more specific routes from updates
5406 suppress-map Conditionally filter more specific routes from updates
5407 <cr>
5408 */
d62a17ae 5409struct bgp_aggregate {
5410 /* Summary-only flag. */
d7c0a89a 5411 uint8_t summary_only;
718e3744 5412
d62a17ae 5413 /* AS set generation. */
d7c0a89a 5414 uint8_t as_set;
718e3744 5415
d62a17ae 5416 /* Route-map for aggregated route. */
5417 struct route_map *map;
718e3744 5418
d62a17ae 5419 /* Suppress-count. */
5420 unsigned long count;
718e3744 5421
d62a17ae 5422 /* SAFI configuration. */
5423 safi_t safi;
718e3744 5424};
5425
d62a17ae 5426static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5427{
d62a17ae 5428 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5429}
5430
d62a17ae 5431static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5432{
d62a17ae 5433 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5434}
718e3744 5435
b5d58c32 5436/* Update an aggregate as routes are added/removed from the BGP table */
d62a17ae 5437static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
5438 struct bgp_info *rinew, afi_t afi, safi_t safi,
5439 struct bgp_info *del,
5440 struct bgp_aggregate *aggregate)
5441{
5442 struct bgp_table *table;
5443 struct bgp_node *top;
5444 struct bgp_node *rn;
d7c0a89a 5445 uint8_t origin;
d62a17ae 5446 struct aspath *aspath = NULL;
5447 struct aspath *asmerge = NULL;
5448 struct community *community = NULL;
5449 struct community *commerge = NULL;
d62a17ae 5450 struct bgp_info *ri;
5451 struct bgp_info *new;
d62a17ae 5452 unsigned long match = 0;
d7c0a89a 5453 uint8_t atomic_aggregate = 0;
d62a17ae 5454
d62a17ae 5455 /* ORIGIN attribute: If at least one route among routes that are
5456 aggregated has ORIGIN with the value INCOMPLETE, then the
5457 aggregated route must have the ORIGIN attribute with the value
5458 INCOMPLETE. Otherwise, if at least one route among routes that
5459 are aggregated has ORIGIN with the value EGP, then the aggregated
5460 route must have the origin attribute with the value EGP. In all
5461 other case the value of the ORIGIN attribute of the aggregated
5462 route is INTERNAL. */
5463 origin = BGP_ORIGIN_IGP;
718e3744 5464
d62a17ae 5465 table = bgp->rib[afi][safi];
718e3744 5466
d62a17ae 5467 top = bgp_node_get(table, p);
5468 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5469 rn = bgp_route_next_until(rn, top)) {
5470 if (rn->p.prefixlen <= p->prefixlen)
5471 continue;
d62a17ae 5472
c2ff8b3e 5473 match = 0;
d62a17ae 5474
c2ff8b3e
DS
5475 for (ri = rn->info; ri; ri = ri->next) {
5476 if (BGP_INFO_HOLDDOWN(ri))
5477 continue;
d62a17ae 5478
c2ff8b3e
DS
5479 if (del && ri == del)
5480 continue;
718e3744 5481
c2ff8b3e
DS
5482 if (ri->attr->flag
5483 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5484 atomic_aggregate = 1;
d62a17ae 5485
c2ff8b3e
DS
5486 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5487 continue;
5488
5489 if (aggregate->summary_only) {
5490 (bgp_info_extra_get(ri))->suppress++;
5491 bgp_info_set_flag(rn, ri,
5492 BGP_INFO_ATTR_CHANGED);
5493 match++;
d62a17ae 5494 }
c2ff8b3e
DS
5495
5496 aggregate->count++;
5497
5498 if (origin < ri->attr->origin)
5499 origin = ri->attr->origin;
5500
5501 if (!aggregate->as_set)
5502 continue;
5503
5504 if (aspath) {
5505 asmerge = aspath_aggregate(aspath,
5506 ri->attr->aspath);
5507 aspath_free(aspath);
5508 aspath = asmerge;
5509 } else
5510 aspath = aspath_dup(ri->attr->aspath);
5511
5512 if (!ri->attr->community)
5513 continue;
5514
5515 if (community) {
5516 commerge = community_merge(community,
5517 ri->attr->community);
5518 community = community_uniq_sort(commerge);
5519 community_free(commerge);
5520 } else
5521 community = community_dup(ri->attr->community);
d62a17ae 5522 }
c2ff8b3e
DS
5523 if (match)
5524 bgp_process(bgp, rn, afi, safi);
5525 }
d62a17ae 5526 bgp_unlock_node(top);
718e3744 5527
d62a17ae 5528 if (rinew) {
718e3744 5529 aggregate->count++;
5530
d62a17ae 5531 if (aggregate->summary_only)
5532 (bgp_info_extra_get(rinew))->suppress++;
5533
5534 if (origin < rinew->attr->origin)
5535 origin = rinew->attr->origin;
5536
5537 if (aggregate->as_set) {
5538 if (aspath) {
5539 asmerge = aspath_aggregate(aspath,
5540 rinew->attr->aspath);
5541 aspath_free(aspath);
5542 aspath = asmerge;
5543 } else
5544 aspath = aspath_dup(rinew->attr->aspath);
5545
5546 if (rinew->attr->community) {
5547 if (community) {
5548 commerge = community_merge(
5549 community,
5550 rinew->attr->community);
5551 community =
5552 community_uniq_sort(commerge);
5553 community_free(commerge);
5554 } else
5555 community = community_dup(
5556 rinew->attr->community);
5557 }
718e3744 5558 }
718e3744 5559 }
718e3744 5560
d62a17ae 5561 if (aggregate->count > 0) {
5562 rn = bgp_node_get(table, p);
5563 new = info_make(
5564 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5565 bgp_attr_aggregate_intern(bgp, origin, aspath,
5566 community, aggregate->as_set,
5567 atomic_aggregate),
5568 rn);
5569 SET_FLAG(new->flags, BGP_INFO_VALID);
5570
5571 bgp_info_add(rn, new);
5572 bgp_unlock_node(rn);
5573 bgp_process(bgp, rn, afi, safi);
5574 } else {
5575 if (aspath)
5576 aspath_free(aspath);
5577 if (community)
5578 community_free(community);
5579 }
718e3744 5580}
5581
d62a17ae 5582void bgp_aggregate_delete(struct bgp *, struct prefix *, afi_t, safi_t,
5583 struct bgp_aggregate *);
718e3744 5584
d62a17ae 5585void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
5586 struct bgp_info *ri, afi_t afi, safi_t safi)
718e3744 5587{
d62a17ae 5588 struct bgp_node *child;
5589 struct bgp_node *rn;
5590 struct bgp_aggregate *aggregate;
5591 struct bgp_table *table;
718e3744 5592
d62a17ae 5593 table = bgp->aggregate[afi][safi];
f018db83 5594
d62a17ae 5595 /* No aggregates configured. */
5596 if (bgp_table_top_nolock(table) == NULL)
5597 return;
f018db83 5598
d62a17ae 5599 if (p->prefixlen == 0)
5600 return;
718e3744 5601
d62a17ae 5602 if (BGP_INFO_HOLDDOWN(ri))
5603 return;
718e3744 5604
d62a17ae 5605 child = bgp_node_get(table, p);
718e3744 5606
d62a17ae 5607 /* Aggregate address configuration check. */
5608 for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
5609 if ((aggregate = rn->info) != NULL
5610 && rn->p.prefixlen < p->prefixlen) {
5611 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5612 bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL,
5613 aggregate);
5614 }
5615 bgp_unlock_node(child);
718e3744 5616}
5617
d62a17ae 5618void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
5619 struct bgp_info *del, afi_t afi, safi_t safi)
718e3744 5620{
d62a17ae 5621 struct bgp_node *child;
5622 struct bgp_node *rn;
5623 struct bgp_aggregate *aggregate;
5624 struct bgp_table *table;
718e3744 5625
d62a17ae 5626 table = bgp->aggregate[afi][safi];
718e3744 5627
d62a17ae 5628 /* No aggregates configured. */
5629 if (bgp_table_top_nolock(table) == NULL)
5630 return;
718e3744 5631
d62a17ae 5632 if (p->prefixlen == 0)
5633 return;
718e3744 5634
d62a17ae 5635 child = bgp_node_get(table, p);
718e3744 5636
d62a17ae 5637 /* Aggregate address configuration check. */
5638 for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
5639 if ((aggregate = rn->info) != NULL
5640 && rn->p.prefixlen < p->prefixlen) {
5641 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5642 bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
5643 aggregate);
5644 }
5645 bgp_unlock_node(child);
5646}
718e3744 5647
d62a17ae 5648/* Called via bgp_aggregate_set when the user configures aggregate-address */
5649static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
5650 safi_t safi, struct bgp_aggregate *aggregate)
5651{
5652 struct bgp_table *table;
5653 struct bgp_node *top;
5654 struct bgp_node *rn;
5655 struct bgp_info *new;
5656 struct bgp_info *ri;
5657 unsigned long match;
d7c0a89a 5658 uint8_t origin = BGP_ORIGIN_IGP;
d62a17ae 5659 struct aspath *aspath = NULL;
5660 struct aspath *asmerge = NULL;
5661 struct community *community = NULL;
5662 struct community *commerge = NULL;
d7c0a89a 5663 uint8_t atomic_aggregate = 0;
d62a17ae 5664
5665 table = bgp->rib[afi][safi];
5666
5667 /* Sanity check. */
5668 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5669 return;
5670 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5671 return;
42f7e184 5672
d62a17ae 5673 /* If routes exists below this node, generate aggregate routes. */
5674 top = bgp_node_get(table, p);
5675 for (rn = bgp_node_get(table, p); rn;
ea47320b
DL
5676 rn = bgp_route_next_until(rn, top)) {
5677 if (rn->p.prefixlen <= p->prefixlen)
5678 continue;
d62a17ae 5679
ea47320b 5680 match = 0;
d62a17ae 5681
ea47320b
DL
5682 for (ri = rn->info; ri; ri = ri->next) {
5683 if (BGP_INFO_HOLDDOWN(ri))
5684 continue;
d62a17ae 5685
ea47320b
DL
5686 if (ri->attr->flag
5687 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5688 atomic_aggregate = 1;
d62a17ae 5689
ea47320b
DL
5690 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5691 continue;
d62a17ae 5692
ea47320b
DL
5693 /* summary-only aggregate route suppress
5694 * aggregated route announcement. */
5695 if (aggregate->summary_only) {
5696 (bgp_info_extra_get(ri))->suppress++;
5697 bgp_info_set_flag(rn, ri,
5698 BGP_INFO_ATTR_CHANGED);
5699 match++;
5700 }
d62a17ae 5701
ea47320b
DL
5702 /* If at least one route among routes that are
5703 * aggregated has ORIGIN with the value INCOMPLETE,
5704 * then the aggregated route MUST have the ORIGIN
5705 * attribute with the value INCOMPLETE. Otherwise, if
5706 * at least one route among routes that are aggregated
5707 * has ORIGIN with the value EGP, then the aggregated
5708 * route MUST have the ORIGIN attribute with the value
5709 * EGP.
5710 */
5711 if (origin < ri->attr->origin)
5712 origin = ri->attr->origin;
5713
5714 /* as-set aggregate route generate origin, as path,
5715 * community aggregation. */
5716 if (aggregate->as_set) {
5717 if (aspath) {
60466a63
QY
5718 asmerge = aspath_aggregate(
5719 aspath, ri->attr->aspath);
ea47320b
DL
5720 aspath_free(aspath);
5721 aspath = asmerge;
5722 } else
5723 aspath = aspath_dup(ri->attr->aspath);
5724
5725 if (ri->attr->community) {
5726 if (community) {
5727 commerge = community_merge(
5728 community,
5729 ri->attr->community);
5730 community = community_uniq_sort(
5731 commerge);
60466a63 5732 community_free(commerge);
ea47320b
DL
5733 } else
5734 community = community_dup(
5735 ri->attr->community);
d62a17ae 5736 }
5737 }
ea47320b 5738 aggregate->count++;
d62a17ae 5739 }
ea47320b
DL
5740
5741 /* If this node is suppressed, process the change. */
5742 if (match)
5743 bgp_process(bgp, rn, afi, safi);
5744 }
d62a17ae 5745 bgp_unlock_node(top);
5746
5747 /* Add aggregate route to BGP table. */
5748 if (aggregate->count) {
5749 rn = bgp_node_get(table, p);
5750 new = info_make(
5751 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5752 bgp_attr_aggregate_intern(bgp, origin, aspath,
5753 community, aggregate->as_set,
5754 atomic_aggregate),
5755 rn);
5756 SET_FLAG(new->flags, BGP_INFO_VALID);
5757
5758 bgp_info_add(rn, new);
5759 bgp_unlock_node(rn);
5760
5761 /* Process change. */
5762 bgp_process(bgp, rn, afi, safi);
5763 } else {
5764 if (aspath)
5765 aspath_free(aspath);
5766 if (community)
5767 community_free(community);
5768 }
718e3744 5769}
5770
d62a17ae 5771void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5772 safi_t safi, struct bgp_aggregate *aggregate)
718e3744 5773{
d62a17ae 5774 struct bgp_table *table;
5775 struct bgp_node *top;
5776 struct bgp_node *rn;
5777 struct bgp_info *ri;
5778 unsigned long match;
718e3744 5779
d62a17ae 5780 table = bgp->rib[afi][safi];
718e3744 5781
d62a17ae 5782 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5783 return;
5784 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5785 return;
5786
5787 /* If routes exists below this node, generate aggregate routes. */
5788 top = bgp_node_get(table, p);
5789 for (rn = bgp_node_get(table, p); rn;
ea47320b
DL
5790 rn = bgp_route_next_until(rn, top)) {
5791 if (rn->p.prefixlen <= p->prefixlen)
5792 continue;
5793 match = 0;
d62a17ae 5794
ea47320b
DL
5795 for (ri = rn->info; ri; ri = ri->next) {
5796 if (BGP_INFO_HOLDDOWN(ri))
5797 continue;
d62a17ae 5798
ea47320b
DL
5799 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5800 continue;
5801
5802 if (aggregate->summary_only && ri->extra) {
5803 ri->extra->suppress--;
5804
5805 if (ri->extra->suppress == 0) {
60466a63
QY
5806 bgp_info_set_flag(
5807 rn, ri, BGP_INFO_ATTR_CHANGED);
ea47320b 5808 match++;
d62a17ae 5809 }
5810 }
ea47320b 5811 aggregate->count--;
d62a17ae 5812 }
ea47320b
DL
5813
5814 /* If this node was suppressed, process the change. */
5815 if (match)
5816 bgp_process(bgp, rn, afi, safi);
5817 }
d62a17ae 5818 bgp_unlock_node(top);
718e3744 5819
d62a17ae 5820 /* Delete aggregate route from BGP table. */
5821 rn = bgp_node_get(table, p);
718e3744 5822
5823 for (ri = rn->info; ri; ri = ri->next)
d62a17ae 5824 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
5825 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5826 break;
5827
5828 /* Withdraw static BGP route from routing table. */
5829 if (ri) {
5830 bgp_info_delete(rn, ri);
5831 bgp_process(bgp, rn, afi, safi);
5832 }
718e3744 5833
d62a17ae 5834 /* Unlock bgp_node_lookup. */
5835 bgp_unlock_node(rn);
718e3744 5836}
5837
5838/* Aggregate route attribute. */
5839#define AGGREGATE_SUMMARY_ONLY 1
5840#define AGGREGATE_AS_SET 1
5841
d62a17ae 5842static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5843 afi_t afi, safi_t safi)
718e3744 5844{
d62a17ae 5845 VTY_DECLVAR_CONTEXT(bgp, bgp);
5846 int ret;
5847 struct prefix p;
5848 struct bgp_node *rn;
5849 struct bgp_aggregate *aggregate;
718e3744 5850
d62a17ae 5851 /* Convert string to prefix structure. */
5852 ret = str2prefix(prefix_str, &p);
5853 if (!ret) {
5854 vty_out(vty, "Malformed prefix\n");
5855 return CMD_WARNING_CONFIG_FAILED;
5856 }
5857 apply_mask(&p);
5858
5859 /* Old configuration check. */
5860 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5861 if (!rn) {
5862 vty_out(vty,
5863 "%% There is no aggregate-address configuration.\n");
5864 return CMD_WARNING_CONFIG_FAILED;
5865 }
f6269b4f 5866
d62a17ae 5867 aggregate = rn->info;
09990cdd 5868 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
d62a17ae 5869
5870 /* Unlock aggregate address configuration. */
5871 rn->info = NULL;
5872 bgp_aggregate_free(aggregate);
5873 bgp_unlock_node(rn);
5874 bgp_unlock_node(rn);
5875
5876 return CMD_SUCCESS;
5877}
5878
5879static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
d7c0a89a 5880 safi_t safi, uint8_t summary_only, uint8_t as_set)
d62a17ae 5881{
5882 VTY_DECLVAR_CONTEXT(bgp, bgp);
5883 int ret;
5884 struct prefix p;
5885 struct bgp_node *rn;
5886 struct bgp_aggregate *aggregate;
5887
5888 /* Convert string to prefix structure. */
5889 ret = str2prefix(prefix_str, &p);
5890 if (!ret) {
5891 vty_out(vty, "Malformed prefix\n");
5892 return CMD_WARNING_CONFIG_FAILED;
5893 }
5894 apply_mask(&p);
5895
5896 /* Old configuration check. */
5897 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
5898
5899 if (rn->info) {
5900 vty_out(vty, "There is already same aggregate network.\n");
5901 /* try to remove the old entry */
5902 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
5903 if (ret) {
5904 vty_out(vty, "Error deleting aggregate.\n");
5905 bgp_unlock_node(rn);
5906 return CMD_WARNING_CONFIG_FAILED;
5907 }
5908 }
718e3744 5909
d62a17ae 5910 /* Make aggregate address structure. */
5911 aggregate = bgp_aggregate_new();
5912 aggregate->summary_only = summary_only;
5913 aggregate->as_set = as_set;
5914 aggregate->safi = safi;
5915 rn->info = aggregate;
718e3744 5916
d62a17ae 5917 /* Aggregate address insert into BGP routing table. */
09990cdd 5918 bgp_aggregate_add(bgp, &p, afi, safi, aggregate);
718e3744 5919
d62a17ae 5920 return CMD_SUCCESS;
718e3744 5921}
5922
5923DEFUN (aggregate_address,
5924 aggregate_address_cmd,
e3e6107d 5925 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5926 "Configure BGP aggregate entries\n"
5927 "Aggregate prefix\n"
5928 "Generate AS set path information\n"
a636c635
DW
5929 "Filter more specific routes from updates\n"
5930 "Filter more specific routes from updates\n"
5931 "Generate AS set path information\n")
718e3744 5932{
d62a17ae 5933 int idx = 0;
5934 argv_find(argv, argc, "A.B.C.D/M", &idx);
5935 char *prefix = argv[idx]->arg;
5936 int as_set =
5937 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5938 idx = 0;
5939 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5940 ? AGGREGATE_SUMMARY_ONLY
5941 : 0;
e3e6107d 5942
d62a17ae 5943 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
5944 summary_only, as_set);
718e3744 5945}
5946
e3e6107d
QY
5947DEFUN (aggregate_address_mask,
5948 aggregate_address_mask_cmd,
5949 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5950 "Configure BGP aggregate entries\n"
5951 "Aggregate address\n"
5952 "Aggregate mask\n"
5953 "Generate AS set path information\n"
a636c635
DW
5954 "Filter more specific routes from updates\n"
5955 "Filter more specific routes from updates\n"
5956 "Generate AS set path information\n")
718e3744 5957{
d62a17ae 5958 int idx = 0;
5959 argv_find(argv, argc, "A.B.C.D", &idx);
5960 char *prefix = argv[idx]->arg;
5961 char *mask = argv[idx + 1]->arg;
5962 int as_set =
5963 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5964 idx = 0;
5965 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5966 ? AGGREGATE_SUMMARY_ONLY
5967 : 0;
5968
5969 char prefix_str[BUFSIZ];
5970 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
5971
5972 if (!ret) {
5973 vty_out(vty, "%% Inconsistent address and mask\n");
5974 return CMD_WARNING_CONFIG_FAILED;
5975 }
718e3744 5976
d62a17ae 5977 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5978 summary_only, as_set);
718e3744 5979}
5980
718e3744 5981DEFUN (no_aggregate_address,
5982 no_aggregate_address_cmd,
e3e6107d 5983 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5984 NO_STR
5985 "Configure BGP aggregate entries\n"
a636c635
DW
5986 "Aggregate prefix\n"
5987 "Generate AS set path information\n"
e3e6107d
QY
5988 "Filter more specific routes from updates\n"
5989 "Filter more specific routes from updates\n"
5990 "Generate AS set path information\n")
718e3744 5991{
d62a17ae 5992 int idx = 0;
5993 argv_find(argv, argc, "A.B.C.D/M", &idx);
5994 char *prefix = argv[idx]->arg;
5995 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 5996}
5997
718e3744 5998DEFUN (no_aggregate_address_mask,
5999 no_aggregate_address_mask_cmd,
e3e6107d 6000 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6001 NO_STR
6002 "Configure BGP aggregate entries\n"
6003 "Aggregate address\n"
a636c635
DW
6004 "Aggregate mask\n"
6005 "Generate AS set path information\n"
e3e6107d
QY
6006 "Filter more specific routes from updates\n"
6007 "Filter more specific routes from updates\n"
6008 "Generate AS set path information\n")
718e3744 6009{
d62a17ae 6010 int idx = 0;
6011 argv_find(argv, argc, "A.B.C.D", &idx);
6012 char *prefix = argv[idx]->arg;
6013 char *mask = argv[idx + 1]->arg;
718e3744 6014
d62a17ae 6015 char prefix_str[BUFSIZ];
6016 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6017
d62a17ae 6018 if (!ret) {
6019 vty_out(vty, "%% Inconsistent address and mask\n");
6020 return CMD_WARNING_CONFIG_FAILED;
6021 }
718e3744 6022
d62a17ae 6023 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6024}
6025
718e3744 6026DEFUN (ipv6_aggregate_address,
6027 ipv6_aggregate_address_cmd,
e3e6107d 6028 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6029 "Configure BGP aggregate entries\n"
6030 "Aggregate prefix\n"
6031 "Filter more specific routes from updates\n")
6032{
d62a17ae 6033 int idx = 0;
6034 argv_find(argv, argc, "X:X::X:X/M", &idx);
6035 char *prefix = argv[idx]->arg;
6036 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6037 ? AGGREGATE_SUMMARY_ONLY
6038 : 0;
6039 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6040 0);
718e3744 6041}
6042
6043DEFUN (no_ipv6_aggregate_address,
6044 no_ipv6_aggregate_address_cmd,
e3e6107d 6045 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6046 NO_STR
6047 "Configure BGP aggregate entries\n"
16cedbb0
QY
6048 "Aggregate prefix\n"
6049 "Filter more specific routes from updates\n")
718e3744 6050{
d62a17ae 6051 int idx = 0;
6052 argv_find(argv, argc, "X:X::X:X/M", &idx);
6053 char *prefix = argv[idx]->arg;
6054 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6055}
6056
718e3744 6057/* Redistribute route treatment. */
d62a17ae 6058void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6059 const union g_addr *nexthop, ifindex_t ifindex,
6060 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6061 uint8_t type, unsigned short instance,
6062 route_tag_t tag)
d62a17ae 6063{
6064 struct bgp_info *new;
6065 struct bgp_info *bi;
6066 struct bgp_info info;
6067 struct bgp_node *bn;
6068 struct attr attr;
6069 struct attr *new_attr;
6070 afi_t afi;
6071 int ret;
6072 struct bgp_redist *red;
6073
6074 /* Make default attribute. */
6075 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff 6076
a4d82a8a 6077 switch (nhtype) {
9de1f7ff
DS
6078 case NEXTHOP_TYPE_IFINDEX:
6079 break;
6080 case NEXTHOP_TYPE_IPV4:
6081 case NEXTHOP_TYPE_IPV4_IFINDEX:
6082 attr.nexthop = nexthop->ipv4;
6083 break;
6084 case NEXTHOP_TYPE_IPV6:
6085 case NEXTHOP_TYPE_IPV6_IFINDEX:
6086 attr.mp_nexthop_global = nexthop->ipv6;
6087 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6088 break;
6089 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6090 switch (p->family) {
6091 case AF_INET:
9de1f7ff 6092 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6093 break;
6094 case AF_INET6:
9de1f7ff
DS
6095 memset(&attr.mp_nexthop_global, 0,
6096 sizeof(attr.mp_nexthop_global));
74489921 6097 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6098 break;
74489921 6099 }
9de1f7ff 6100 break;
d62a17ae 6101 }
74489921 6102 attr.nh_ifindex = ifindex;
f04a80a5 6103
d62a17ae 6104 attr.med = metric;
6105 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6106 attr.tag = tag;
718e3744 6107
d62a17ae 6108 afi = family2afi(p->family);
6aeb9e78 6109
d62a17ae 6110 red = bgp_redist_lookup(bgp, afi, type, instance);
6111 if (red) {
6112 struct attr attr_new;
718e3744 6113
d62a17ae 6114 /* Copy attribute for modification. */
6115 bgp_attr_dup(&attr_new, &attr);
718e3744 6116
d62a17ae 6117 if (red->redist_metric_flag)
6118 attr_new.med = red->redist_metric;
718e3744 6119
d62a17ae 6120 /* Apply route-map. */
6121 if (red->rmap.name) {
6122 info.peer = bgp->peer_self;
6123 info.attr = &attr_new;
718e3744 6124
d62a17ae 6125 SET_FLAG(bgp->peer_self->rmap_type,
6126 PEER_RMAP_TYPE_REDISTRIBUTE);
6127
6128 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
6129 &info);
6130
6131 bgp->peer_self->rmap_type = 0;
6132
6133 if (ret == RMAP_DENYMATCH) {
6134 /* Free uninterned attribute. */
6135 bgp_attr_flush(&attr_new);
6136
6137 /* Unintern original. */
6138 aspath_unintern(&attr.aspath);
6139 bgp_redistribute_delete(bgp, p, type, instance);
6140 return;
6141 }
6142 }
6143
7f323236
DW
6144 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6145 bgp_attr_add_gshut_community(&attr_new);
6146
d62a17ae 6147 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6148 SAFI_UNICAST, p, NULL);
6149
6150 new_attr = bgp_attr_intern(&attr_new);
6151
6152 for (bi = bn->info; bi; bi = bi->next)
6153 if (bi->peer == bgp->peer_self
6154 && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
6155 break;
6156
6157 if (bi) {
6158 /* Ensure the (source route) type is updated. */
6159 bi->type = type;
6160 if (attrhash_cmp(bi->attr, new_attr)
6161 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
6162 bgp_attr_unintern(&new_attr);
6163 aspath_unintern(&attr.aspath);
6164 bgp_unlock_node(bn);
6165 return;
6166 } else {
6167 /* The attribute is changed. */
6168 bgp_info_set_flag(bn, bi,
6169 BGP_INFO_ATTR_CHANGED);
6170
6171 /* Rewrite BGP route information. */
6172 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
6173 bgp_info_restore(bn, bi);
6174 else
6175 bgp_aggregate_decrement(bgp, p, bi, afi,
6176 SAFI_UNICAST);
6177 bgp_attr_unintern(&bi->attr);
6178 bi->attr = new_attr;
6179 bi->uptime = bgp_clock();
6180
6181 /* Process change. */
6182 bgp_aggregate_increment(bgp, p, bi, afi,
6183 SAFI_UNICAST);
6184 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6185 bgp_unlock_node(bn);
6186 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6187
6188 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6189 || (bgp->inst_type
6190 == BGP_INSTANCE_TYPE_DEFAULT)) {
6191
6192 vpn_leak_from_vrf_update(
6193 bgp_get_default(), bgp, bi);
6194 }
d62a17ae 6195 return;
6196 }
6197 }
6198
6199 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6200 bgp->peer_self, new_attr, bn);
6201 SET_FLAG(new->flags, BGP_INFO_VALID);
6202
6203 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
6204 bgp_info_add(bn, new);
6205 bgp_unlock_node(bn);
6206 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6207
6208 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6209 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6210
6211 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6212 }
d62a17ae 6213 }
6214
6215 /* Unintern original. */
6216 aspath_unintern(&attr.aspath);
718e3744 6217}
6218
d7c0a89a
QY
6219void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6220 unsigned short instance)
718e3744 6221{
d62a17ae 6222 afi_t afi;
6223 struct bgp_node *rn;
6224 struct bgp_info *ri;
6225 struct bgp_redist *red;
718e3744 6226
d62a17ae 6227 afi = family2afi(p->family);
718e3744 6228
d62a17ae 6229 red = bgp_redist_lookup(bgp, afi, type, instance);
6230 if (red) {
6231 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6232 SAFI_UNICAST, p, NULL);
6233
6234 for (ri = rn->info; ri; ri = ri->next)
6235 if (ri->peer == bgp->peer_self && ri->type == type)
6236 break;
6237
6238 if (ri) {
ddb5b488
PZ
6239 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6240 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6241
6242 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6243 bgp, ri);
6244 }
d62a17ae 6245 bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
6246 bgp_info_delete(rn, ri);
6247 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6248 }
6249 bgp_unlock_node(rn);
6250 }
6251}
6252
6253/* Withdraw specified route type's route. */
6254void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6255 unsigned short instance)
d62a17ae 6256{
6257 struct bgp_node *rn;
6258 struct bgp_info *ri;
6259 struct bgp_table *table;
6260
6261 table = bgp->rib[afi][SAFI_UNICAST];
6262
6263 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6264 for (ri = rn->info; ri; ri = ri->next)
6265 if (ri->peer == bgp->peer_self && ri->type == type
6266 && ri->instance == instance)
6267 break;
6268
6269 if (ri) {
ddb5b488
PZ
6270 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6271 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6272
6273 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6274 bgp, ri);
6275 }
d62a17ae 6276 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
6277 SAFI_UNICAST);
6278 bgp_info_delete(rn, ri);
6279 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6280 }
718e3744 6281 }
718e3744 6282}
6b0655a2 6283
718e3744 6284/* Static function to display route. */
9c92b5f7
MK
6285static void route_vty_out_route(struct prefix *p, struct vty *vty,
6286 json_object *json)
718e3744 6287{
be054588 6288 int len = 0;
d7c0a89a 6289 uint32_t destination;
d62a17ae 6290 char buf[BUFSIZ];
718e3744 6291
d62a17ae 6292 if (p->family == AF_INET) {
c6462ff4
MK
6293 if (!json) {
6294 len = vty_out(vty, "%s",
6295 inet_ntop(p->family, &p->u.prefix, buf,
6296 BUFSIZ));
6297 destination = ntohl(p->u.prefix4.s_addr);
6298
6299 if ((IN_CLASSC(destination) && p->prefixlen == 24)
6300 || (IN_CLASSB(destination) && p->prefixlen == 16)
6301 || (IN_CLASSA(destination) && p->prefixlen == 8)
6302 || p->u.prefix4.s_addr == 0) {
b682f6de 6303 /* When mask is natural,
6304 mask is not displayed. */
c6462ff4
MK
6305 } else
6306 len += vty_out(vty, "/%d", p->prefixlen);
6307 } else {
6308 json_object_string_add(json, "prefix",
6309 inet_ntop(p->family,
6310 &p->u.prefix, buf,
6311 BUFSIZ));
6312 json_object_int_add(json, "prefixLen", p->prefixlen);
6313 }
d62a17ae 6314 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6315 prefix2str(p, buf, PREFIX_STRLEN);
6316 len = vty_out(vty, "%s", buf);
6317 } else if (p->family == AF_EVPN) {
d62a17ae 6318#if defined(HAVE_CUMULUS)
57f7feb6 6319 if (!json)
60466a63
QY
6320 len = vty_out(
6321 vty, "%s",
6322 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6323 BUFSIZ));
57f7feb6 6324 else
60466a63 6325 bgp_evpn_route2json((struct prefix_evpn *)p, json);
520d5d76 6326#else
d62a17ae 6327 prefix2str(p, buf, PREFIX_STRLEN);
6328 len = vty_out(vty, "%s", buf);
520d5d76 6329#endif
dba3c1d3
PG
6330 } else if (p->family == AF_FLOWSPEC) {
6331 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6332 json ?
6333 NLRI_STRING_FORMAT_JSON_SIMPLE :
6334 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6335 } else {
c6462ff4 6336 if (!json)
60466a63
QY
6337 len = vty_out(
6338 vty, "%s/%d",
6339 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6340 p->prefixlen);
9c92b5f7 6341 }
d62a17ae 6342
9c92b5f7
MK
6343 if (!json) {
6344 len = 17 - len;
6345 if (len < 1)
6346 vty_out(vty, "\n%*s", 20, " ");
6347 else
6348 vty_out(vty, "%*s", len, " ");
6349 }
718e3744 6350}
6351
d62a17ae 6352enum bgp_display_type {
6353 normal_list,
718e3744 6354};
6355
b40d939b 6356/* Print the short form route status for a bgp_info */
d62a17ae 6357static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo,
6358 json_object *json_path)
718e3744 6359{
d62a17ae 6360 if (json_path) {
b05a1c8b 6361
d62a17ae 6362 /* Route status display. */
6363 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6364 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6365
d62a17ae 6366 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6367 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6368
d62a17ae 6369 if (binfo->extra && binfo->extra->suppress)
6370 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6371
d62a17ae 6372 if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6373 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6374 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6375
d62a17ae 6376 /* Selected */
6377 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6378 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6379
d62a17ae 6380 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6381 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6382
d62a17ae 6383 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6384 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6385
d62a17ae 6386 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6387 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6388
d62a17ae 6389 /* Internal route. */
6390 if ((binfo->peer->as)
6391 && (binfo->peer->as == binfo->peer->local_as))
6392 json_object_string_add(json_path, "pathFrom",
6393 "internal");
6394 else
6395 json_object_string_add(json_path, "pathFrom",
6396 "external");
b05a1c8b 6397
d62a17ae 6398 return;
6399 }
b05a1c8b 6400
d62a17ae 6401 /* Route status display. */
6402 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6403 vty_out(vty, "R");
6404 else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6405 vty_out(vty, "S");
6406 else if (binfo->extra && binfo->extra->suppress)
6407 vty_out(vty, "s");
6408 else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6409 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6410 vty_out(vty, "*");
6411 else
6412 vty_out(vty, " ");
6413
6414 /* Selected */
6415 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6416 vty_out(vty, "h");
6417 else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6418 vty_out(vty, "d");
6419 else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6420 vty_out(vty, ">");
6421 else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6422 vty_out(vty, "=");
6423 else
6424 vty_out(vty, " ");
718e3744 6425
d62a17ae 6426 /* Internal route. */
6427 if (binfo->peer && (binfo->peer->as)
6428 && (binfo->peer->as == binfo->peer->local_as))
6429 vty_out(vty, "i");
6430 else
6431 vty_out(vty, " ");
b40d939b 6432}
6433
6434/* called from terminal list command */
d62a17ae 6435void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6436 int display, safi_t safi, json_object *json_paths)
6437{
6438 struct attr *attr;
6439 json_object *json_path = NULL;
6440 json_object *json_nexthops = NULL;
6441 json_object *json_nexthop_global = NULL;
6442 json_object *json_nexthop_ll = NULL;
9df8b37c
PZ
6443 char vrf_id_str[VRF_NAMSIZ] = {0};
6444 bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
6445 ? true
6446 : false;
6447 bool nexthop_othervrf = false;
43089216 6448 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
9df8b37c 6449 const char *nexthop_vrfname = "Default";
d62a17ae 6450
6451 if (json_paths)
6452 json_path = json_object_new_object();
6453
6454 /* short status lead text */
6455 route_vty_short_status_out(vty, binfo, json_path);
6456
6457 if (!json_paths) {
6458 /* print prefix and mask */
6459 if (!display)
9c92b5f7 6460 route_vty_out_route(p, vty, json_path);
d62a17ae 6461 else
6462 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6463 } else {
b682f6de 6464 route_vty_out_route(p, vty, json_path);
d62a17ae 6465 }
47fc97cc 6466
d62a17ae 6467 /* Print attribute */
6468 attr = binfo->attr;
445c2480
DS
6469 if (!attr) {
6470 if (json_paths)
6471 json_object_array_add(json_paths, json_path);
6472 else
6473 vty_out(vty, "\n");
d62a17ae 6474
445c2480
DS
6475 return;
6476 }
6477
9df8b37c
PZ
6478 /*
6479 * If vrf id of nexthop is different from that of prefix,
6480 * set up printable string to append
6481 */
6482 if (binfo->extra && binfo->extra->bgp_orig) {
6483 const char *self = "";
6484
6485 if (nexthop_self)
6486 self = "<";
6487
6488 nexthop_othervrf = true;
6489 nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
6490
6491 if (binfo->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
6492 snprintf(vrf_id_str, sizeof(vrf_id_str),
6493 "@%s%s", VRFID_NONE_STR, self);
6494 else
6495 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
6496 binfo->extra->bgp_orig->vrf_id, self);
6497
6498 if (binfo->extra->bgp_orig->inst_type !=
6499 BGP_INSTANCE_TYPE_DEFAULT)
6500
6501 nexthop_vrfname = binfo->extra->bgp_orig->name;
6502 } else {
6503 const char *self = "";
6504
6505 if (nexthop_self)
6506 self = "<";
6507
6508 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
6509 }
6510
445c2480
DS
6511 /*
6512 * For ENCAP and EVPN routes, nexthop address family is not
6513 * neccessarily the same as the prefix address family.
6514 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6515 * EVPN routes are also exchanged with a MP nexthop. Currently,
6516 * this
6517 * is only IPv4, the value will be present in either
6518 * attr->nexthop or
6519 * attr->mp_nexthop_global_in
6520 */
6521 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6522 char buf[BUFSIZ];
6523 char nexthop[128];
6524 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6525
6526 switch (af) {
6527 case AF_INET:
6528 sprintf(nexthop, "%s",
a4d82a8a
PZ
6529 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
6530 BUFSIZ));
445c2480
DS
6531 break;
6532 case AF_INET6:
6533 sprintf(nexthop, "%s",
a4d82a8a
PZ
6534 inet_ntop(af, &attr->mp_nexthop_global, buf,
6535 BUFSIZ));
445c2480
DS
6536 break;
6537 default:
6538 sprintf(nexthop, "?");
6539 break;
d62a17ae 6540 }
d62a17ae 6541
445c2480
DS
6542 if (json_paths) {
6543 json_nexthop_global = json_object_new_object();
6544
a4d82a8a
PZ
6545 json_object_string_add(json_nexthop_global, "afi",
6546 (af == AF_INET) ? "ip" : "ipv6");
445c2480 6547 json_object_string_add(json_nexthop_global,
a4d82a8a 6548 (af == AF_INET) ? "ip" : "ipv6",
445c2480
DS
6549 nexthop);
6550 json_object_boolean_true_add(json_nexthop_global,
6551 "used");
6552 } else
9df8b37c 6553 vty_out(vty, "%s%s", nexthop, vrf_id_str);
445c2480
DS
6554 } else if (safi == SAFI_EVPN) {
6555 if (json_paths) {
6556 json_nexthop_global = json_object_new_object();
6557
6558 json_object_string_add(json_nexthop_global, "ip",
6559 inet_ntoa(attr->nexthop));
a4d82a8a
PZ
6560 json_object_string_add(json_nexthop_global, "afi",
6561 "ipv4");
445c2480
DS
6562 json_object_boolean_true_add(json_nexthop_global,
6563 "used");
6564 } else
9df8b37c
PZ
6565 vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
6566 vrf_id_str);
d33fc23b 6567 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
6568 if (attr->nexthop.s_addr != 0) {
6569 if (json_paths) {
6570 json_nexthop_global = json_object_new_object();
6571 json_object_string_add(
6572 json_nexthop_global, "ip",
6573 inet_ntoa(attr->nexthop));
6574 json_object_string_add(json_nexthop_global,
6575 "afi", "ipv4");
6576 json_object_boolean_true_add(json_nexthop_global,
6577 "used");
6578 } else {
6579 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6580 }
6581 }
d33fc23b 6582 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6583 if (json_paths) {
6584 json_nexthop_global = json_object_new_object();
d62a17ae 6585
a4d82a8a
PZ
6586 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
6587 json_object_string_add(
6588 json_nexthop_global, "ip",
6589 inet_ntoa(attr->mp_nexthop_global_in));
445c2480 6590 else
a4d82a8a
PZ
6591 json_object_string_add(
6592 json_nexthop_global, "ip",
6593 inet_ntoa(attr->nexthop));
445c2480 6594
a4d82a8a
PZ
6595 json_object_string_add(json_nexthop_global, "afi",
6596 "ipv4");
445c2480
DS
6597 json_object_boolean_true_add(json_nexthop_global,
6598 "used");
6599 } else {
9df8b37c
PZ
6600 char buf[BUFSIZ];
6601
a4d82a8a 6602 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
9df8b37c
PZ
6603 snprintf(buf, sizeof(buf), "%s%s",
6604 inet_ntoa(attr->mp_nexthop_global_in),
6605 vrf_id_str);
445c2480 6606 else
9df8b37c
PZ
6607 snprintf(buf, sizeof(buf), "%s%s",
6608 inet_ntoa(attr->nexthop),
6609 vrf_id_str);
6610 vty_out(vty, "%-16s", buf);
d62a17ae 6611 }
445c2480 6612 }
b05a1c8b 6613
445c2480 6614 /* IPv6 Next Hop */
a4d82a8a 6615 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6616 int len;
6617 char buf[BUFSIZ];
d62a17ae 6618
445c2480
DS
6619 if (json_paths) {
6620 json_nexthop_global = json_object_new_object();
a4d82a8a
PZ
6621 json_object_string_add(
6622 json_nexthop_global, "ip",
6623 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
6624 buf, BUFSIZ));
6625 json_object_string_add(json_nexthop_global, "afi",
6626 "ipv6");
6627 json_object_string_add(json_nexthop_global, "scope",
6628 "global");
445c2480
DS
6629
6630 /* We display both LL & GL if both have been
6631 * received */
6632 if ((attr->mp_nexthop_len == 32)
6633 || (binfo->peer->conf_if)) {
a4d82a8a 6634 json_nexthop_ll = json_object_new_object();
d62a17ae 6635 json_object_string_add(
445c2480 6636 json_nexthop_ll, "ip",
a4d82a8a
PZ
6637 inet_ntop(AF_INET6,
6638 &attr->mp_nexthop_local, buf,
6639 BUFSIZ));
6640 json_object_string_add(json_nexthop_ll, "afi",
6641 "ipv6");
6642 json_object_string_add(json_nexthop_ll, "scope",
445c2480 6643 "link-local");
d62a17ae 6644
a4d82a8a
PZ
6645 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
6646 &attr->mp_nexthop_local)
445c2480
DS
6647 != 0)
6648 && !attr->mp_nexthop_prefer_global)
d62a17ae 6649 json_object_boolean_true_add(
a4d82a8a 6650 json_nexthop_ll, "used");
445c2480
DS
6651 else
6652 json_object_boolean_true_add(
a4d82a8a 6653 json_nexthop_global, "used");
445c2480
DS
6654 } else
6655 json_object_boolean_true_add(
6656 json_nexthop_global, "used");
6657 } else {
6658 /* Display LL if LL/Global both in table unless
6659 * prefer-global is set */
6660 if (((attr->mp_nexthop_len == 32)
6661 && !attr->mp_nexthop_prefer_global)
6662 || (binfo->peer->conf_if)) {
6663 if (binfo->peer->conf_if) {
a4d82a8a
PZ
6664 len = vty_out(vty, "%s",
6665 binfo->peer->conf_if);
445c2480
DS
6666 len = 16 - len; /* len of IPv6
6667 addr + max
6668 len of def
6669 ifname */
6670
6671 if (len < 1)
a4d82a8a 6672 vty_out(vty, "\n%*s", 36, " ");
445c2480 6673 else
a4d82a8a 6674 vty_out(vty, "%*s", len, " ");
d62a17ae 6675 } else {
6676 len = vty_out(
9df8b37c 6677 vty, "%s%s",
d62a17ae 6678 inet_ntop(
6679 AF_INET6,
445c2480 6680 &attr->mp_nexthop_local,
9df8b37c
PZ
6681 buf, BUFSIZ),
6682 vrf_id_str);
d62a17ae 6683 len = 16 - len;
6684
6685 if (len < 1)
a4d82a8a 6686 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 6687 else
a4d82a8a 6688 vty_out(vty, "%*s", len, " ");
d62a17ae 6689 }
445c2480 6690 } else {
a4d82a8a 6691 len = vty_out(
9df8b37c 6692 vty, "%s%s",
a4d82a8a
PZ
6693 inet_ntop(AF_INET6,
6694 &attr->mp_nexthop_global, buf,
9df8b37c
PZ
6695 BUFSIZ),
6696 vrf_id_str);
445c2480
DS
6697 len = 16 - len;
6698
6699 if (len < 1)
6700 vty_out(vty, "\n%*s", 36, " ");
6701 else
6702 vty_out(vty, "%*s", len, " ");
d62a17ae 6703 }
6704 }
445c2480 6705 }
718e3744 6706
445c2480
DS
6707 /* MED/Metric */
6708 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6709 if (json_paths)
a4d82a8a 6710 json_object_int_add(json_path, "med", attr->med);
445c2480
DS
6711 else
6712 vty_out(vty, "%10u", attr->med);
6713 else if (!json_paths)
6714 vty_out(vty, " ");
d62a17ae 6715
445c2480
DS
6716 /* Local Pref */
6717 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
d62a17ae 6718 if (json_paths)
445c2480
DS
6719 json_object_int_add(json_path, "localpref",
6720 attr->local_pref);
d62a17ae 6721 else
445c2480
DS
6722 vty_out(vty, "%7u", attr->local_pref);
6723 else if (!json_paths)
6724 vty_out(vty, " ");
d62a17ae 6725
445c2480
DS
6726 if (json_paths)
6727 json_object_int_add(json_path, "weight", attr->weight);
6728 else
6729 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6730
445c2480
DS
6731 if (json_paths) {
6732 char buf[BUFSIZ];
a4d82a8a
PZ
6733 json_object_string_add(
6734 json_path, "peerId",
6735 sockunion2str(&binfo->peer->su, buf, SU_ADDRSTRLEN));
445c2480 6736 }
b05a1c8b 6737
445c2480
DS
6738 /* Print aspath */
6739 if (attr->aspath) {
d62a17ae 6740 if (json_paths)
445c2480
DS
6741 json_object_string_add(json_path, "aspath",
6742 attr->aspath->str);
d62a17ae 6743 else
445c2480 6744 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6745 }
f1aa5d8a 6746
445c2480
DS
6747 /* Print origin */
6748 if (json_paths)
a4d82a8a
PZ
6749 json_object_string_add(json_path, "origin",
6750 bgp_origin_long_str[attr->origin]);
445c2480
DS
6751 else
6752 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6753
9df8b37c
PZ
6754 if (json_paths) {
6755 if (nexthop_self)
6756 json_object_boolean_true_add(json_path,
6757 "announceNexthopSelf");
6758 if (nexthop_othervrf) {
6759 json_object_string_add(json_path, "nhVrfName",
6760 nexthop_vrfname);
6761
6762 json_object_int_add(json_path, "nhVrfId",
6763 ((nexthop_vrfid == VRF_UNKNOWN)
6764 ? -1
6765 : (int)nexthop_vrfid));
6766 }
6767 }
6768
d62a17ae 6769 if (json_paths) {
6770 if (json_nexthop_global || json_nexthop_ll) {
6771 json_nexthops = json_object_new_array();
f1aa5d8a 6772
d62a17ae 6773 if (json_nexthop_global)
6774 json_object_array_add(json_nexthops,
6775 json_nexthop_global);
f1aa5d8a 6776
d62a17ae 6777 if (json_nexthop_ll)
6778 json_object_array_add(json_nexthops,
6779 json_nexthop_ll);
f1aa5d8a 6780
d62a17ae 6781 json_object_object_add(json_path, "nexthops",
6782 json_nexthops);
6783 }
6784
6785 json_object_array_add(json_paths, json_path);
6786 } else {
6787 vty_out(vty, "\n");
65efcfce 6788#if ENABLE_BGP_VNC
d62a17ae 6789 /* prints an additional line, indented, with VNC info, if
6790 * present */
6791 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
6792 rfapi_vty_out_vncinfo(vty, p, binfo, safi);
65efcfce 6793#endif
d62a17ae 6794 }
6795}
718e3744 6796
6797/* called from terminal list command */
d62a17ae 6798void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
d7c0a89a 6799 safi_t safi, uint8_t use_json, json_object *json_ar)
d62a17ae 6800{
6801 json_object *json_status = NULL;
6802 json_object *json_net = NULL;
6803 char buff[BUFSIZ];
6804 /* Route status display. */
6805 if (use_json) {
6806 json_status = json_object_new_object();
6807 json_net = json_object_new_object();
6808 } else {
6809 vty_out(vty, "*");
6810 vty_out(vty, ">");
6811 vty_out(vty, " ");
6812 }
718e3744 6813
d62a17ae 6814 /* print prefix and mask */
6815 if (use_json)
6816 json_object_string_add(
6817 json_net, "addrPrefix",
6818 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
6819 else
9c92b5f7 6820 route_vty_out_route(p, vty, NULL);
d62a17ae 6821
6822 /* Print attribute */
6823 if (attr) {
6824 if (use_json) {
6825 if (p->family == AF_INET
6826 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6827 || safi == SAFI_EVPN
6828 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6829 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6830 || safi == SAFI_EVPN)
6831 json_object_string_add(
6832 json_net, "nextHop",
6833 inet_ntoa(
6834 attr->mp_nexthop_global_in));
6835 else
6836 json_object_string_add(
6837 json_net, "nextHop",
6838 inet_ntoa(attr->nexthop));
6839 } else if (p->family == AF_INET6
6840 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6841 char buf[BUFSIZ];
6842
6843 json_object_string_add(
6844 json_net, "netHopGloabal",
6845 inet_ntop(AF_INET6,
6846 &attr->mp_nexthop_global, buf,
6847 BUFSIZ));
6848 }
6849
6850 if (attr->flag
6851 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6852 json_object_int_add(json_net, "metric",
6853 attr->med);
6854
6855 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6856 json_object_int_add(json_net, "localPref",
6857 attr->local_pref);
6858
6859 json_object_int_add(json_net, "weight", attr->weight);
6860
6861 /* Print aspath */
6862 if (attr->aspath)
6863 json_object_string_add(json_net, "asPath",
6864 attr->aspath->str);
6865
6866 /* Print origin */
6867 json_object_string_add(json_net, "bgpOriginCode",
6868 bgp_origin_str[attr->origin]);
6869 } else {
6870 if (p->family == AF_INET
6871 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6872 || safi == SAFI_EVPN
6873 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6874 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6875 || safi == SAFI_EVPN)
6876 vty_out(vty, "%-16s",
6877 inet_ntoa(
6878 attr->mp_nexthop_global_in));
6879 else
6880 vty_out(vty, "%-16s",
6881 inet_ntoa(attr->nexthop));
6882 } else if (p->family == AF_INET6
6883 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6884 int len;
6885 char buf[BUFSIZ];
6886
6887 len = vty_out(
6888 vty, "%s",
6889 inet_ntop(AF_INET6,
6890 &attr->mp_nexthop_global, buf,
6891 BUFSIZ));
6892 len = 16 - len;
6893 if (len < 1)
6894 vty_out(vty, "\n%*s", 36, " ");
6895 else
6896 vty_out(vty, "%*s", len, " ");
6897 }
6898 if (attr->flag
6899 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6900 vty_out(vty, "%10u", attr->med);
6901 else
6902 vty_out(vty, " ");
718e3744 6903
d62a17ae 6904 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6905 vty_out(vty, "%7u", attr->local_pref);
6906 else
6907 vty_out(vty, " ");
6908
6909 vty_out(vty, "%7u ", attr->weight);
6910
6911 /* Print aspath */
6912 if (attr->aspath)
6913 aspath_print_vty(vty, "%s", attr->aspath, " ");
6914
6915 /* Print origin */
6916 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6917 }
6918 }
6919 if (use_json) {
6920 json_object_boolean_true_add(json_status, "*");
6921 json_object_boolean_true_add(json_status, ">");
6922 json_object_object_add(json_net, "appliedStatusSymbols",
6923 json_status);
6924 char buf_cut[BUFSIZ];
6925 json_object_object_add(
6926 json_ar,
6927 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
6928 json_net);
6929 } else
6930 vty_out(vty, "\n");
6931}
6932
6933void route_vty_out_tag(struct vty *vty, struct prefix *p,
6934 struct bgp_info *binfo, int display, safi_t safi,
6935 json_object *json)
6936{
6937 json_object *json_out = NULL;
6938 struct attr *attr;
6939 mpls_label_t label = MPLS_INVALID_LABEL;
6940
6941 if (!binfo->extra)
6942 return;
6943
6944 if (json)
6945 json_out = json_object_new_object();
6946
6947 /* short status lead text */
6948 route_vty_short_status_out(vty, binfo, json_out);
6949
6950 /* print prefix and mask */
6951 if (json == NULL) {
6952 if (!display)
9c92b5f7 6953 route_vty_out_route(p, vty, NULL);
d62a17ae 6954 else
6955 vty_out(vty, "%*s", 17, " ");
6956 }
6957
6958 /* Print attribute */
6959 attr = binfo->attr;
6960 if (attr) {
6961 if (((p->family == AF_INET)
6962 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 6963 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 6964 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6965 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6966 || safi == SAFI_EVPN) {
6967 if (json)
6968 json_object_string_add(
6969 json_out, "mpNexthopGlobalIn",
6970 inet_ntoa(
6971 attr->mp_nexthop_global_in));
6972 else
6973 vty_out(vty, "%-16s",
6974 inet_ntoa(
6975 attr->mp_nexthop_global_in));
6976 } else {
6977 if (json)
6978 json_object_string_add(
6979 json_out, "nexthop",
6980 inet_ntoa(attr->nexthop));
6981 else
6982 vty_out(vty, "%-16s",
6983 inet_ntoa(attr->nexthop));
6984 }
6985 } else if (((p->family == AF_INET6)
6986 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6987 || (safi == SAFI_EVPN
d62a17ae 6988 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6989 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6990 char buf_a[BUFSIZ];
6991 char buf_b[BUFSIZ];
6992 char buf_c[BUFSIZ];
6993 if (attr->mp_nexthop_len
6994 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
6995 if (json)
6996 json_object_string_add(
6997 json_out, "mpNexthopGlobalIn",
6998 inet_ntop(
6999 AF_INET6,
7000 &attr->mp_nexthop_global,
7001 buf_a, BUFSIZ));
7002 else
7003 vty_out(vty, "%s",
7004 inet_ntop(
7005 AF_INET6,
7006 &attr->mp_nexthop_global,
7007 buf_a, BUFSIZ));
7008 } else if (attr->mp_nexthop_len
7009 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7010 if (json) {
7011 inet_ntop(AF_INET6,
7012 &attr->mp_nexthop_global,
7013 buf_a, BUFSIZ);
7014 inet_ntop(AF_INET6,
7015 &attr->mp_nexthop_local,
7016 buf_b, BUFSIZ);
7017 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
7018 json_object_string_add(
7019 json_out,
7020 "mpNexthopGlobalLocal", buf_c);
7021 } else
7022 vty_out(vty, "%s(%s)",
7023 inet_ntop(
7024 AF_INET6,
7025 &attr->mp_nexthop_global,
7026 buf_a, BUFSIZ),
7027 inet_ntop(
7028 AF_INET6,
7029 &attr->mp_nexthop_local,
7030 buf_b, BUFSIZ));
7031 }
7032 }
7033 }
7034
b57ba6d2 7035 label = decode_label(&binfo->extra->label[0]);
d62a17ae 7036
7037 if (bgp_is_valid_label(&label)) {
7038 if (json) {
7039 json_object_int_add(json_out, "notag", label);
7040 json_object_array_add(json, json_out);
7041 } else {
7042 vty_out(vty, "notag/%d", label);
7043 vty_out(vty, "\n");
7044 }
7045 }
7046}
718e3744 7047
d62a17ae 7048void route_vty_out_overlay(struct vty *vty, struct prefix *p,
7049 struct bgp_info *binfo, int display,
7050 json_object *json_paths)
718e3744 7051{
d62a17ae 7052 struct attr *attr;
7053 char buf[BUFSIZ];
7054 json_object *json_path = NULL;
784d3a42 7055
d62a17ae 7056 if (json_paths)
7057 json_path = json_object_new_object();
856ca177 7058
d62a17ae 7059 if (!binfo->extra)
7060 return;
718e3744 7061
d62a17ae 7062 /* short status lead text */
7063 route_vty_short_status_out(vty, binfo, json_path);
856ca177 7064
d62a17ae 7065 /* print prefix and mask */
7066 if (!display)
9c92b5f7 7067 route_vty_out_route(p, vty, NULL);
d62a17ae 7068 else
7069 vty_out(vty, "%*s", 17, " ");
7070
7071 /* Print attribute */
7072 attr = binfo->attr;
7073 if (attr) {
7074 char buf1[BUFSIZ];
7075 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7076
7077 switch (af) {
7078 case AF_INET:
7079 vty_out(vty, "%-16s",
7080 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7081 BUFSIZ));
7082 break;
7083 case AF_INET6:
7084 vty_out(vty, "%s(%s)",
7085 inet_ntop(af, &attr->mp_nexthop_global, buf,
7086 BUFSIZ),
7087 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7088 BUFSIZ));
7089 break;
7090 default:
7091 vty_out(vty, "?");
7092 }
988258b4
QY
7093
7094 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7095
7096 vty_out(vty, "%s", str);
7097 XFREE(MTYPE_TMP, str);
7098
3714a385 7099 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
988258b4
QY
7100 vty_out(vty, "/%s",
7101 inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
3714a385 7102 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
988258b4
QY
7103 vty_out(vty, "/%s",
7104 inet_ntop(AF_INET6,
7105 &(attr->evpn_overlay.gw_ip.ipv6), buf,
7106 BUFSIZ));
7107 }
7108 if (attr->ecommunity) {
7109 char *mac = NULL;
7110 struct ecommunity_val *routermac = ecommunity_lookup(
7111 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7112 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7113 if (routermac)
7114 mac = ecom_mac2str((char *)routermac->val);
7115 if (mac) {
7116 vty_out(vty, "/%s", (char *)mac);
7117 XFREE(MTYPE_TMP, mac);
7118 }
7119 }
7120 vty_out(vty, "\n");
718e3744 7121 }
718e3744 7122
d62a17ae 7123}
718e3744 7124
d62a17ae 7125/* dampening route */
7126static void damp_route_vty_out(struct vty *vty, struct prefix *p,
7127 struct bgp_info *binfo, int display, safi_t safi,
d7c0a89a 7128 uint8_t use_json, json_object *json)
d62a17ae 7129{
7130 struct attr *attr;
7131 int len;
7132 char timebuf[BGP_UPTIME_LEN];
7133
7134 /* short status lead text */
7135 route_vty_short_status_out(vty, binfo, json);
7136
7137 /* print prefix and mask */
7138 if (!use_json) {
7139 if (!display)
9c92b5f7 7140 route_vty_out_route(p, vty, NULL);
d62a17ae 7141 else
7142 vty_out(vty, "%*s", 17, " ");
7143 }
7144
7145 len = vty_out(vty, "%s", binfo->peer->host);
7146 len = 17 - len;
7147 if (len < 1) {
7148 if (!use_json)
7149 vty_out(vty, "\n%*s", 34, " ");
7150 } else {
7151 if (use_json)
7152 json_object_int_add(json, "peerHost", len);
7153 else
7154 vty_out(vty, "%*s", len, " ");
7155 }
7156
7157 if (use_json)
7158 bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN,
7159 use_json, json);
7160 else
996c9314
LB
7161 vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7162 BGP_UPTIME_LEN,
7163 use_json, json));
d62a17ae 7164
7165 /* Print attribute */
7166 attr = binfo->attr;
7167 if (attr) {
7168 /* Print aspath */
7169 if (attr->aspath) {
7170 if (use_json)
7171 json_object_string_add(json, "asPath",
7172 attr->aspath->str);
7173 else
7174 aspath_print_vty(vty, "%s", attr->aspath, " ");
7175 }
7176
7177 /* Print origin */
7178 if (use_json)
7179 json_object_string_add(json, "origin",
7180 bgp_origin_str[attr->origin]);
7181 else
7182 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7183 }
7184 if (!use_json)
7185 vty_out(vty, "\n");
7186}
718e3744 7187
d62a17ae 7188/* flap route */
7189static void flap_route_vty_out(struct vty *vty, struct prefix *p,
7190 struct bgp_info *binfo, int display, safi_t safi,
d7c0a89a 7191 uint8_t use_json, json_object *json)
784d3a42 7192{
d62a17ae 7193 struct attr *attr;
7194 struct bgp_damp_info *bdi;
7195 char timebuf[BGP_UPTIME_LEN];
7196 int len;
784d3a42 7197
d62a17ae 7198 if (!binfo->extra)
7199 return;
784d3a42 7200
d62a17ae 7201 bdi = binfo->extra->damp_info;
784d3a42 7202
d62a17ae 7203 /* short status lead text */
7204 route_vty_short_status_out(vty, binfo, json);
784d3a42 7205
d62a17ae 7206 /* print prefix and mask */
7207 if (!use_json) {
7208 if (!display)
9c92b5f7 7209 route_vty_out_route(p, vty, NULL);
d62a17ae 7210 else
7211 vty_out(vty, "%*s", 17, " ");
7212 }
784d3a42 7213
d62a17ae 7214 len = vty_out(vty, "%s", binfo->peer->host);
7215 len = 16 - len;
7216 if (len < 1) {
7217 if (!use_json)
7218 vty_out(vty, "\n%*s", 33, " ");
7219 } else {
7220 if (use_json)
7221 json_object_int_add(json, "peerHost", len);
7222 else
7223 vty_out(vty, "%*s", len, " ");
7224 }
784d3a42 7225
d62a17ae 7226 len = vty_out(vty, "%d", bdi->flap);
7227 len = 5 - len;
7228 if (len < 1) {
7229 if (!use_json)
7230 vty_out(vty, " ");
7231 } else {
7232 if (use_json)
7233 json_object_int_add(json, "bdiFlap", len);
7234 else
7235 vty_out(vty, "%*s", len, " ");
7236 }
7237
7238 if (use_json)
7239 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7240 json);
7241 else
996c9314
LB
7242 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7243 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7244
7245 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
7246 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7247 if (use_json)
7248 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7249 BGP_UPTIME_LEN, use_json, json);
7250 else
7251 vty_out(vty, "%s ",
7252 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7253 BGP_UPTIME_LEN,
7254 use_json, json));
7255 } else {
7256 if (!use_json)
7257 vty_out(vty, "%*s ", 8, " ");
7258 }
7259
7260 /* Print attribute */
7261 attr = binfo->attr;
7262 if (attr) {
7263 /* Print aspath */
7264 if (attr->aspath) {
7265 if (use_json)
7266 json_object_string_add(json, "asPath",
7267 attr->aspath->str);
7268 else
7269 aspath_print_vty(vty, "%s", attr->aspath, " ");
7270 }
7271
7272 /* Print origin */
7273 if (use_json)
7274 json_object_string_add(json, "origin",
7275 bgp_origin_str[attr->origin]);
7276 else
7277 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7278 }
7279 if (!use_json)
7280 vty_out(vty, "\n");
7281}
7282
7283static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7284 int *first, const char *header,
7285 json_object *json_adv_to)
7286{
7287 char buf1[INET6_ADDRSTRLEN];
7288 json_object *json_peer = NULL;
7289
7290 if (json_adv_to) {
7291 /* 'advertised-to' is a dictionary of peers we have advertised
7292 * this
7293 * prefix too. The key is the peer's IP or swpX, the value is
7294 * the
7295 * hostname if we know it and "" if not.
7296 */
7297 json_peer = json_object_new_object();
7298
7299 if (peer->hostname)
7300 json_object_string_add(json_peer, "hostname",
7301 peer->hostname);
7302
7303 if (peer->conf_if)
7304 json_object_object_add(json_adv_to, peer->conf_if,
7305 json_peer);
7306 else
7307 json_object_object_add(
7308 json_adv_to,
7309 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7310 json_peer);
7311 } else {
7312 if (*first) {
7313 vty_out(vty, "%s", header);
7314 *first = 0;
7315 }
7316
7317 if (peer->hostname
7318 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7319 if (peer->conf_if)
7320 vty_out(vty, " %s(%s)", peer->hostname,
7321 peer->conf_if);
7322 else
7323 vty_out(vty, " %s(%s)", peer->hostname,
7324 sockunion2str(&peer->su, buf1,
7325 SU_ADDRSTRLEN));
7326 } else {
7327 if (peer->conf_if)
7328 vty_out(vty, " %s", peer->conf_if);
7329 else
7330 vty_out(vty, " %s",
7331 sockunion2str(&peer->su, buf1,
7332 SU_ADDRSTRLEN));
7333 }
7334 }
784d3a42
PG
7335}
7336
d62a17ae 7337void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
7338 struct bgp_info *binfo, afi_t afi, safi_t safi,
7339 json_object *json_paths)
7340{
7341 char buf[INET6_ADDRSTRLEN];
7342 char buf1[BUFSIZ];
7343#if defined(HAVE_CUMULUS)
7344 char buf2[EVPN_ROUTE_STRLEN];
7345#endif
7346 struct attr *attr;
7347 int sockunion_vty_out(struct vty *, union sockunion *);
7348 time_t tbuf;
7349 json_object *json_bestpath = NULL;
7350 json_object *json_cluster_list = NULL;
7351 json_object *json_cluster_list_list = NULL;
7352 json_object *json_ext_community = NULL;
7353 json_object *json_last_update = NULL;
7fd077aa 7354 json_object *json_pmsi = NULL;
d62a17ae 7355 json_object *json_nexthop_global = NULL;
7356 json_object *json_nexthop_ll = NULL;
7357 json_object *json_nexthops = NULL;
7358 json_object *json_path = NULL;
7359 json_object *json_peer = NULL;
7360 json_object *json_string = NULL;
7361 json_object *json_adv_to = NULL;
7362 int first = 0;
7363 struct listnode *node, *nnode;
7364 struct peer *peer;
7365 int addpath_capable;
7366 int has_adj;
7367 unsigned int first_as;
9df8b37c
PZ
7368 bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
7369 ? true
7370 : false;
d62a17ae 7371
7372 if (json_paths) {
7373 json_path = json_object_new_object();
7374 json_peer = json_object_new_object();
7375 json_nexthop_global = json_object_new_object();
7376 }
7377
7378#if defined(HAVE_CUMULUS)
7379 if (!json_paths && safi == SAFI_EVPN) {
b57ba6d2 7380 char tag_buf[30];
d62a17ae 7381
7382 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7383 vty_out(vty, " Route %s", buf2);
7384 tag_buf[0] = '\0';
b57ba6d2
MK
7385 if (binfo->extra && binfo->extra->num_labels) {
7386 bgp_evpn_label2str(binfo->extra->label,
a4d82a8a
PZ
7387 binfo->extra->num_labels, tag_buf,
7388 sizeof(tag_buf));
d62a17ae 7389 vty_out(vty, " VNI %s", tag_buf);
7390 }
7391 vty_out(vty, "\n");
7392 if (binfo->extra && binfo->extra->parent) {
7393 struct bgp_info *parent_ri;
7394 struct bgp_node *rn, *prn;
7395
7396 parent_ri = (struct bgp_info *)binfo->extra->parent;
7397 rn = parent_ri->net;
7398 if (rn && rn->prn) {
7399 prn = rn->prn;
7400 vty_out(vty, " Imported from %s:%s\n",
7401 prefix_rd2str(
7402 (struct prefix_rd *)&prn->p,
06b9f471 7403 buf1, sizeof(buf1)),
d62a17ae 7404 buf2);
7405 }
7406 }
7407 }
7408#endif
7409
7410 attr = binfo->attr;
7411
7412 if (attr) {
7413 /* Line1 display AS-path, Aggregator */
7414 if (attr->aspath) {
7415 if (json_paths) {
68e1a55b
DS
7416 if (!attr->aspath->json)
7417 aspath_str_update(attr->aspath, true);
d62a17ae 7418 json_object_lock(attr->aspath->json);
7419 json_object_object_add(json_path, "aspath",
7420 attr->aspath->json);
7421 } else {
7422 if (attr->aspath->segments)
7423 aspath_print_vty(vty, " %s",
7424 attr->aspath, "");
7425 else
7426 vty_out(vty, " Local");
7427 }
7428 }
7429
7430 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) {
7431 if (json_paths)
7432 json_object_boolean_true_add(json_path,
7433 "removed");
7434 else
7435 vty_out(vty, ", (removed)");
7436 }
7437
7438 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) {
7439 if (json_paths)
7440 json_object_boolean_true_add(json_path,
7441 "stale");
7442 else
7443 vty_out(vty, ", (stale)");
7444 }
7445
7446 if (CHECK_FLAG(attr->flag,
7447 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7448 if (json_paths) {
7449 json_object_int_add(json_path, "aggregatorAs",
7450 attr->aggregator_as);
7451 json_object_string_add(
7452 json_path, "aggregatorId",
7453 inet_ntoa(attr->aggregator_addr));
7454 } else {
7455 vty_out(vty, ", (aggregated by %u %s)",
7456 attr->aggregator_as,
7457 inet_ntoa(attr->aggregator_addr));
7458 }
7459 }
7460
7461 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7462 PEER_FLAG_REFLECTOR_CLIENT)) {
7463 if (json_paths)
7464 json_object_boolean_true_add(
7465 json_path, "rxedFromRrClient");
7466 else
7467 vty_out(vty, ", (Received from a RR-client)");
7468 }
7469
7470 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7471 PEER_FLAG_RSERVER_CLIENT)) {
7472 if (json_paths)
7473 json_object_boolean_true_add(
7474 json_path, "rxedFromRsClient");
7475 else
7476 vty_out(vty, ", (Received from a RS-client)");
7477 }
7478
7479 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7480 if (json_paths)
7481 json_object_boolean_true_add(
7482 json_path, "dampeningHistoryEntry");
7483 else
7484 vty_out(vty, ", (history entry)");
7485 } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
7486 if (json_paths)
7487 json_object_boolean_true_add(
7488 json_path, "dampeningSuppressed");
7489 else
7490 vty_out(vty, ", (suppressed due to dampening)");
7491 }
7492
7493 if (!json_paths)
7494 vty_out(vty, "\n");
7495
7496 /* Line2 display Next-hop, Neighbor, Router-id */
7497 /* Display the nexthop */
a4d82a8a
PZ
7498 if ((p->family == AF_INET || p->family == AF_ETHERNET
7499 || p->family == AF_EVPN)
d62a17ae 7500 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7501 || safi == SAFI_EVPN
7502 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7503 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7504 || safi == SAFI_EVPN) {
7505 if (json_paths)
7506 json_object_string_add(
7507 json_nexthop_global, "ip",
7508 inet_ntoa(
7509 attr->mp_nexthop_global_in));
7510 else
7511 vty_out(vty, " %s",
7512 inet_ntoa(
7513 attr->mp_nexthop_global_in));
7514 } else {
7515 if (json_paths)
7516 json_object_string_add(
7517 json_nexthop_global, "ip",
7518 inet_ntoa(attr->nexthop));
7519 else
7520 vty_out(vty, " %s",
7521 inet_ntoa(attr->nexthop));
7522 }
7523
7524 if (json_paths)
7525 json_object_string_add(json_nexthop_global,
7526 "afi", "ipv4");
7527 } else {
7528 if (json_paths) {
7529 json_object_string_add(
7530 json_nexthop_global, "ip",
7531 inet_ntop(AF_INET6,
7532 &attr->mp_nexthop_global, buf,
7533 INET6_ADDRSTRLEN));
7534 json_object_string_add(json_nexthop_global,
7535 "afi", "ipv6");
7536 json_object_string_add(json_nexthop_global,
7537 "scope", "global");
7538 } else {
7539 vty_out(vty, " %s",
7540 inet_ntop(AF_INET6,
7541 &attr->mp_nexthop_global, buf,
7542 INET6_ADDRSTRLEN));
7543 }
7544 }
7545
7546 /* Display the IGP cost or 'inaccessible' */
7547 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7548 if (json_paths)
7549 json_object_boolean_false_add(
7550 json_nexthop_global, "accessible");
7551 else
7552 vty_out(vty, " (inaccessible)");
7553 } else {
7554 if (binfo->extra && binfo->extra->igpmetric) {
7555 if (json_paths)
7556 json_object_int_add(
7557 json_nexthop_global, "metric",
7558 binfo->extra->igpmetric);
7559 else
7560 vty_out(vty, " (metric %u)",
7561 binfo->extra->igpmetric);
7562 }
7563
7564 /* IGP cost is 0, display this only for json */
7565 else {
7566 if (json_paths)
7567 json_object_int_add(json_nexthop_global,
7568 "metric", 0);
7569 }
7570
7571 if (json_paths)
7572 json_object_boolean_true_add(
7573 json_nexthop_global, "accessible");
7574 }
7575
7576 /* Display peer "from" output */
7577 /* This path was originated locally */
7578 if (binfo->peer == bgp->peer_self) {
7579
7580 if (safi == SAFI_EVPN
7581 || (p->family == AF_INET
7582 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7583 if (json_paths)
7584 json_object_string_add(
7585 json_peer, "peerId", "0.0.0.0");
7586 else
7587 vty_out(vty, " from 0.0.0.0 ");
7588 } else {
7589 if (json_paths)
7590 json_object_string_add(json_peer,
7591 "peerId", "::");
7592 else
7593 vty_out(vty, " from :: ");
7594 }
7595
7596 if (json_paths)
7597 json_object_string_add(
7598 json_peer, "routerId",
7599 inet_ntoa(bgp->router_id));
7600 else
7601 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7602 }
7603
7604 /* We RXed this path from one of our peers */
7605 else {
7606
7607 if (json_paths) {
7608 json_object_string_add(
7609 json_peer, "peerId",
7610 sockunion2str(&binfo->peer->su, buf,
7611 SU_ADDRSTRLEN));
7612 json_object_string_add(
7613 json_peer, "routerId",
7614 inet_ntop(AF_INET,
7615 &binfo->peer->remote_id, buf1,
06b9f471 7616 sizeof(buf1)));
d62a17ae 7617
7618 if (binfo->peer->hostname)
7619 json_object_string_add(
7620 json_peer, "hostname",
7621 binfo->peer->hostname);
7622
7623 if (binfo->peer->domainname)
7624 json_object_string_add(
7625 json_peer, "domainname",
7626 binfo->peer->domainname);
7627
7628 if (binfo->peer->conf_if)
7629 json_object_string_add(
7630 json_peer, "interface",
7631 binfo->peer->conf_if);
7632 } else {
7633 if (binfo->peer->conf_if) {
7634 if (binfo->peer->hostname
7635 && bgp_flag_check(
7636 binfo->peer->bgp,
7637 BGP_FLAG_SHOW_HOSTNAME))
7638 vty_out(vty, " from %s(%s)",
7639 binfo->peer->hostname,
7640 binfo->peer->conf_if);
7641 else
7642 vty_out(vty, " from %s",
7643 binfo->peer->conf_if);
7644 } else {
7645 if (binfo->peer->hostname
7646 && bgp_flag_check(
7647 binfo->peer->bgp,
7648 BGP_FLAG_SHOW_HOSTNAME))
7649 vty_out(vty, " from %s(%s)",
7650 binfo->peer->hostname,
7651 binfo->peer->host);
7652 else
7653 vty_out(vty, " from %s",
7654 sockunion2str(
7655 &binfo->peer
7656 ->su,
7657 buf,
7658 SU_ADDRSTRLEN));
7659 }
7660
7661 if (attr->flag
7662 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7663 vty_out(vty, " (%s)",
7664 inet_ntoa(attr->originator_id));
7665 else
7666 vty_out(vty, " (%s)",
7667 inet_ntop(
7668 AF_INET,
7669 &binfo->peer->remote_id,
06b9f471 7670 buf1, sizeof(buf1)));
d62a17ae 7671 }
7672 }
7673
9df8b37c
PZ
7674 /*
7675 * Note when vrfid of nexthop is different from that of prefix
7676 */
7677 if (binfo->extra && binfo->extra->bgp_orig) {
7678 vrf_id_t nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
7679
7680 if (json_paths) {
7681 const char *vn;
7682
7683 if (binfo->extra->bgp_orig->inst_type ==
7684 BGP_INSTANCE_TYPE_DEFAULT)
7685
7686 vn = "Default";
7687 else
7688 vn = binfo->extra->bgp_orig->name;
7689
7690 json_object_string_add(json_path, "nhVrfName",
7691 vn);
7692
7693 if (nexthop_vrfid == VRF_UNKNOWN) {
7694 json_object_int_add(json_path,
7695 "nhVrfId", -1);
7696 } else {
7697 json_object_int_add(json_path,
7698 "nhVrfId", (int)nexthop_vrfid);
7699 }
7700 } else {
7701 if (nexthop_vrfid == VRF_UNKNOWN)
7702 vty_out(vty, " vrf ?");
7703 else
7704 vty_out(vty, " vrf %u", nexthop_vrfid);
7705 }
7706 }
7707
7708 if (nexthop_self) {
7709 if (json_paths) {
7710 json_object_boolean_true_add(json_path,
7711 "announceNexthopSelf");
7712 } else {
7713 vty_out(vty, " announce-nh-self");
7714 }
7715 }
7716
d62a17ae 7717 if (!json_paths)
7718 vty_out(vty, "\n");
7719
7720 /* display the link-local nexthop */
7721 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7722 if (json_paths) {
7723 json_nexthop_ll = json_object_new_object();
7724 json_object_string_add(
7725 json_nexthop_ll, "ip",
7726 inet_ntop(AF_INET6,
7727 &attr->mp_nexthop_local, buf,
7728 INET6_ADDRSTRLEN));
7729 json_object_string_add(json_nexthop_ll, "afi",
7730 "ipv6");
7731 json_object_string_add(json_nexthop_ll, "scope",
7732 "link-local");
7733
7734 json_object_boolean_true_add(json_nexthop_ll,
7735 "accessible");
7736
7737 if (!attr->mp_nexthop_prefer_global)
7738 json_object_boolean_true_add(
7739 json_nexthop_ll, "used");
7740 else
7741 json_object_boolean_true_add(
7742 json_nexthop_global, "used");
7743 } else {
7744 vty_out(vty, " (%s) %s\n",
7745 inet_ntop(AF_INET6,
7746 &attr->mp_nexthop_local, buf,
7747 INET6_ADDRSTRLEN),
7748 attr->mp_nexthop_prefer_global
7749 ? "(prefer-global)"
7750 : "(used)");
7751 }
7752 }
7753 /* If we do not have a link-local nexthop then we must flag the
7754 global as "used" */
7755 else {
7756 if (json_paths)
7757 json_object_boolean_true_add(
7758 json_nexthop_global, "used");
7759 }
718e3744 7760
d62a17ae 7761 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7762 * Int/Ext/Local, Atomic, best */
7763 if (json_paths)
7764 json_object_string_add(
7765 json_path, "origin",
7766 bgp_origin_long_str[attr->origin]);
7767 else
7768 vty_out(vty, " Origin %s",
7769 bgp_origin_long_str[attr->origin]);
7770
7771 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
7772 if (json_paths)
7773 json_object_int_add(json_path, "med",
7774 attr->med);
7775 else
7776 vty_out(vty, ", metric %u", attr->med);
7777 }
718e3744 7778
d62a17ae 7779 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7780 if (json_paths)
7781 json_object_int_add(json_path, "localpref",
7782 attr->local_pref);
7783 else
7784 vty_out(vty, ", localpref %u",
7785 attr->local_pref);
7786 } else {
7787 if (json_paths)
7788 json_object_int_add(json_path, "localpref",
7789 bgp->default_local_pref);
7790 else
7791 vty_out(vty, ", localpref %u",
7792 bgp->default_local_pref);
7793 }
718e3744 7794
d62a17ae 7795 if (attr->weight != 0) {
7796 if (json_paths)
7797 json_object_int_add(json_path, "weight",
7798 attr->weight);
7799 else
7800 vty_out(vty, ", weight %u", attr->weight);
7801 }
718e3744 7802
d62a17ae 7803 if (attr->tag != 0) {
7804 if (json_paths)
7805 json_object_int_add(json_path, "tag",
7806 attr->tag);
7807 else
7808 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7809 attr->tag);
7810 }
718e3744 7811
d62a17ae 7812 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7813 if (json_paths)
7814 json_object_boolean_false_add(json_path,
7815 "valid");
7816 else
7817 vty_out(vty, ", invalid");
7818 } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7819 if (json_paths)
7820 json_object_boolean_true_add(json_path,
7821 "valid");
7822 else
7823 vty_out(vty, ", valid");
7824 }
718e3744 7825
d62a17ae 7826 if (binfo->peer != bgp->peer_self) {
7827 if (binfo->peer->as == binfo->peer->local_as) {
7828 if (CHECK_FLAG(bgp->config,
7829 BGP_CONFIG_CONFEDERATION)) {
7830 if (json_paths)
7831 json_object_string_add(
7832 json_peer, "type",
7833 "confed-internal");
7834 else
7835 vty_out(vty,
7836 ", confed-internal");
7837 } else {
7838 if (json_paths)
7839 json_object_string_add(
7840 json_peer, "type",
7841 "internal");
7842 else
7843 vty_out(vty, ", internal");
7844 }
7845 } else {
7846 if (bgp_confederation_peers_check(
7847 bgp, binfo->peer->as)) {
7848 if (json_paths)
7849 json_object_string_add(
7850 json_peer, "type",
7851 "confed-external");
7852 else
7853 vty_out(vty,
7854 ", confed-external");
7855 } else {
7856 if (json_paths)
7857 json_object_string_add(
7858 json_peer, "type",
7859 "external");
7860 else
7861 vty_out(vty, ", external");
7862 }
7863 }
7864 } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) {
7865 if (json_paths) {
7866 json_object_boolean_true_add(json_path,
7867 "aggregated");
7868 json_object_boolean_true_add(json_path,
7869 "local");
7870 } else {
7871 vty_out(vty, ", aggregated, local");
7872 }
7873 } else if (binfo->type != ZEBRA_ROUTE_BGP) {
7874 if (json_paths)
7875 json_object_boolean_true_add(json_path,
7876 "sourced");
7877 else
7878 vty_out(vty, ", sourced");
7879 } else {
7880 if (json_paths) {
7881 json_object_boolean_true_add(json_path,
7882 "sourced");
7883 json_object_boolean_true_add(json_path,
7884 "local");
7885 } else {
7886 vty_out(vty, ", sourced, local");
7887 }
7888 }
718e3744 7889
d62a17ae 7890 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
7891 if (json_paths)
7892 json_object_boolean_true_add(json_path,
7893 "atomicAggregate");
7894 else
7895 vty_out(vty, ", atomic-aggregate");
7896 }
718e3744 7897
d62a17ae 7898 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)
7899 || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)
7900 && bgp_info_mpath_count(binfo))) {
7901 if (json_paths)
7902 json_object_boolean_true_add(json_path,
7903 "multipath");
7904 else
7905 vty_out(vty, ", multipath");
7906 }
856ca177 7907
d62a17ae 7908 // Mark the bestpath(s)
7909 if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) {
7910 first_as = aspath_get_first_as(attr->aspath);
7911
7912 if (json_paths) {
7913 if (!json_bestpath)
7914 json_bestpath =
7915 json_object_new_object();
7916 json_object_int_add(json_bestpath,
7917 "bestpathFromAs", first_as);
7918 } else {
7919 if (first_as)
fb2b0934 7920 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 7921 first_as);
7922 else
7923 vty_out(vty,
7924 ", bestpath-from-AS Local");
7925 }
7926 }
718e3744 7927
d62a17ae 7928 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) {
7929 if (json_paths) {
7930 if (!json_bestpath)
7931 json_bestpath =
7932 json_object_new_object();
7933 json_object_boolean_true_add(json_bestpath,
7934 "overall");
7935 } else
7936 vty_out(vty, ", best");
7937 }
718e3744 7938
d62a17ae 7939 if (json_bestpath)
7940 json_object_object_add(json_path, "bestpath",
7941 json_bestpath);
7942
7943 if (!json_paths)
7944 vty_out(vty, "\n");
7945
7946 /* Line 4 display Community */
7947 if (attr->community) {
7948 if (json_paths) {
a69ea8ae 7949 if (!attr->community->json)
a4d82a8a 7950 community_str(attr->community, true);
d62a17ae 7951 json_object_lock(attr->community->json);
7952 json_object_object_add(json_path, "community",
7953 attr->community->json);
7954 } else {
7955 vty_out(vty, " Community: %s\n",
7956 attr->community->str);
7957 }
7958 }
718e3744 7959
d62a17ae 7960 /* Line 5 display Extended-community */
7961 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7962 if (json_paths) {
7963 json_ext_community = json_object_new_object();
7964 json_object_string_add(json_ext_community,
7965 "string",
7966 attr->ecommunity->str);
7967 json_object_object_add(json_path,
7968 "extendedCommunity",
7969 json_ext_community);
7970 } else {
7971 vty_out(vty, " Extended Community: %s\n",
7972 attr->ecommunity->str);
7973 }
7974 }
adbac85e 7975
d62a17ae 7976 /* Line 6 display Large community */
b96879c0
DS
7977 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
7978 if (json_paths) {
8d9b8ed9
PM
7979 if (!attr->lcommunity->json)
7980 lcommunity_str(attr->lcommunity, true);
7981 json_object_lock(attr->lcommunity->json);
b96879c0
DS
7982 json_object_object_add(json_path,
7983 "largeCommunity",
8d9b8ed9 7984 attr->lcommunity->json);
b96879c0
DS
7985 } else {
7986 vty_out(vty, " Large Community: %s\n",
7987 attr->lcommunity->str);
7988 }
7989 }
d62a17ae 7990
7991 /* Line 7 display Originator, Cluster-id */
7992 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7993 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
7994 if (attr->flag
7995 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
7996 if (json_paths)
7997 json_object_string_add(
7998 json_path, "originatorId",
7999 inet_ntoa(attr->originator_id));
8000 else
8001 vty_out(vty, " Originator: %s",
8002 inet_ntoa(attr->originator_id));
8003 }
8004
8005 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8006 int i;
8007
8008 if (json_paths) {
8009 json_cluster_list =
8010 json_object_new_object();
8011 json_cluster_list_list =
8012 json_object_new_array();
8013
8014 for (i = 0;
8015 i < attr->cluster->length / 4;
8016 i++) {
8017 json_string = json_object_new_string(
8018 inet_ntoa(
8019 attr->cluster->list
8020 [i]));
8021 json_object_array_add(
8022 json_cluster_list_list,
8023 json_string);
8024 }
8025
8026 /* struct cluster_list does not have
8027 "str" variable like
8028 * aspath and community do. Add this
8029 someday if someone
8030 * asks for it.
8031 json_object_string_add(json_cluster_list,
8032 "string", attr->cluster->str);
8033 */
8034 json_object_object_add(
8035 json_cluster_list, "list",
8036 json_cluster_list_list);
8037 json_object_object_add(
8038 json_path, "clusterList",
8039 json_cluster_list);
8040 } else {
8041 vty_out(vty, ", Cluster list: ");
8042
8043 for (i = 0;
8044 i < attr->cluster->length / 4;
8045 i++) {
8046 vty_out(vty, "%s ",
8047 inet_ntoa(
8048 attr->cluster->list
8049 [i]));
8050 }
8051 }
8052 }
8053
8054 if (!json_paths)
8055 vty_out(vty, "\n");
8056 }
adbac85e 8057
d62a17ae 8058 if (binfo->extra && binfo->extra->damp_info)
8059 bgp_damp_info_vty(vty, binfo, json_path);
8060
8061/* Remote Label */
8c197128 8062#if defined(HAVE_CUMULUS)
b57ba6d2 8063 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0])
d62a17ae 8064 && safi != SAFI_EVPN)
8065#else
b57ba6d2 8066 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0]))
8c197128 8067#endif
d62a17ae 8068 {
a4d82a8a
PZ
8069 mpls_label_t label =
8070 label_pton(&binfo->extra->label[0]);
d62a17ae 8071 if (json_paths)
8072 json_object_int_add(json_path, "remoteLabel",
8073 label);
8074 else
8075 vty_out(vty, " Remote label: %d\n", label);
8076 }
b05a1c8b 8077
d62a17ae 8078 /* Label Index */
8079 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8080 if (json_paths)
8081 json_object_int_add(json_path, "labelIndex",
8082 attr->label_index);
8083 else
8084 vty_out(vty, " Label Index: %d\n",
8085 attr->label_index);
8086 }
520d5d76 8087
d62a17ae 8088 /* Line 8 display Addpath IDs */
8089 if (binfo->addpath_rx_id || binfo->addpath_tx_id) {
8090 if (json_paths) {
8091 json_object_int_add(json_path, "addpathRxId",
8092 binfo->addpath_rx_id);
8093 json_object_int_add(json_path, "addpathTxId",
8094 binfo->addpath_tx_id);
8095 } else {
8096 vty_out(vty, " AddPath ID: RX %u, TX %u\n",
8097 binfo->addpath_rx_id,
8098 binfo->addpath_tx_id);
8099 }
8100 }
718e3744 8101
d62a17ae 8102 /* If we used addpath to TX a non-bestpath we need to display
8103 * "Advertised to" on a path-by-path basis */
8104 if (bgp->addpath_tx_used[afi][safi]) {
8105 first = 1;
8106
8107 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8108 addpath_capable =
8109 bgp_addpath_encode_tx(peer, afi, safi);
8110 has_adj = bgp_adj_out_lookup(
8111 peer, binfo->net, binfo->addpath_tx_id);
8112
8113 if ((addpath_capable && has_adj)
8114 || (!addpath_capable && has_adj
8115 && CHECK_FLAG(binfo->flags,
8116 BGP_INFO_SELECTED))) {
8117 if (json_path && !json_adv_to)
8118 json_adv_to =
8119 json_object_new_object();
8120
8121 route_vty_out_advertised_to(
8122 vty, peer, &first,
8123 " Advertised to:",
8124 json_adv_to);
8125 }
8126 }
8127
8128 if (json_path) {
8129 if (json_adv_to) {
8130 json_object_object_add(json_path,
8131 "advertisedTo",
8132 json_adv_to);
8133 }
8134 } else {
8135 if (!first) {
8136 vty_out(vty, "\n");
8137 }
8138 }
8139 }
b05a1c8b 8140
d62a17ae 8141 /* Line 9 display Uptime */
8142 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
8143 if (json_paths) {
8144 json_last_update = json_object_new_object();
8145 json_object_int_add(json_last_update, "epoch", tbuf);
8146 json_object_string_add(json_last_update, "string",
8147 ctime(&tbuf));
8148 json_object_object_add(json_path, "lastUpdate",
8149 json_last_update);
8150 } else
8151 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 8152
8153 /* Line 10 display PMSI tunnel attribute, if present */
8154 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 8155 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
8156 attr->pmsi_tnl_type,
8157 PMSI_TNLTYPE_STR_DEFAULT);
8158
7fd077aa 8159 if (json_paths) {
8160 json_pmsi = json_object_new_object();
b7d08f5a 8161 json_object_string_add(json_pmsi,
8162 "tunnelType", str);
7fd077aa 8163 json_object_object_add(json_path, "pmsi",
8164 json_pmsi);
8165 } else
8166 vty_out(vty, " PMSI Tunnel Type: %s\n",
b7d08f5a 8167 str);
7fd077aa 8168 }
8169
d62a17ae 8170 }
f1aa5d8a 8171
d62a17ae 8172 /* We've constructed the json object for this path, add it to the json
8173 * array of paths
8174 */
8175 if (json_paths) {
8176 if (json_nexthop_global || json_nexthop_ll) {
8177 json_nexthops = json_object_new_array();
f1aa5d8a 8178
d62a17ae 8179 if (json_nexthop_global)
8180 json_object_array_add(json_nexthops,
8181 json_nexthop_global);
f1aa5d8a 8182
d62a17ae 8183 if (json_nexthop_ll)
8184 json_object_array_add(json_nexthops,
8185 json_nexthop_ll);
f1aa5d8a 8186
d62a17ae 8187 json_object_object_add(json_path, "nexthops",
8188 json_nexthops);
8189 }
8190
8191 json_object_object_add(json_path, "peer", json_peer);
8192 json_object_array_add(json_paths, json_path);
8193 } else
8194 vty_out(vty, "\n");
b366b518
BB
8195}
8196
96ade3ed 8197#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8198#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8199#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8200
d62a17ae 8201static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8202 const char *prefix_list_str, afi_t afi,
8203 safi_t safi, enum bgp_show_type type);
8204static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8205 const char *filter, afi_t afi, safi_t safi,
8206 enum bgp_show_type type);
8207static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8208 const char *rmap_str, afi_t afi, safi_t safi,
8209 enum bgp_show_type type);
8210static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8211 const char *com, int exact, afi_t afi,
8212 safi_t safi);
8213static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8214 const char *prefix, afi_t afi, safi_t safi,
8215 enum bgp_show_type type);
a4d82a8a
PZ
8216static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
8217 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
8218static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8219 const char *comstr, int exact, afi_t afi,
d62a17ae 8220 safi_t safi);
8221
1ae44dfc
LB
8222
8223static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8224 struct bgp_table *table, enum bgp_show_type type,
d7c0a89a 8225 void *output_arg, uint8_t use_json, char *rd,
a4d82a8a
PZ
8226 int is_last, unsigned long *output_cum,
8227 unsigned long *total_cum,
9386b588 8228 unsigned long *json_header_depth)
d62a17ae 8229{
8230 struct bgp_info *ri;
8231 struct bgp_node *rn;
8232 int header = 1;
8233 int display;
1ae44dfc
LB
8234 unsigned long output_count = 0;
8235 unsigned long total_count = 0;
d62a17ae 8236 struct prefix *p;
8237 char buf[BUFSIZ];
8238 char buf2[BUFSIZ];
8239 json_object *json_paths = NULL;
8240 int first = 1;
8241
1ae44dfc
LB
8242 if (output_cum && *output_cum != 0)
8243 header = 0;
8244
9386b588 8245 if (use_json && !*json_header_depth) {
d62a17ae 8246 vty_out(vty,
66f80d74
DS
8247 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8248 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
a8bf7d9c 8249 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
d62a17ae 8250 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
8251 : bgp->name,
8252 table->version, inet_ntoa(bgp->router_id));
9386b588
PZ
8253 *json_header_depth = 2;
8254 if (rd) {
445c2480 8255 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
8256 ++*json_header_depth;
8257 }
d62a17ae 8258 json_paths = json_object_new_object();
8259 }
718e3744 8260
445c2480
DS
8261 if (use_json && rd) {
8262 vty_out(vty, " \"%s\" : { ", rd);
8263 }
8264
d62a17ae 8265 /* Start processing of routes. */
98ce9a06
DS
8266 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
8267 if (rn->info == NULL)
8268 continue;
d62a17ae 8269
98ce9a06 8270 display = 0;
98ce9a06
DS
8271 if (use_json)
8272 json_paths = json_object_new_array();
8273 else
8274 json_paths = NULL;
d62a17ae 8275
98ce9a06
DS
8276 for (ri = rn->info; ri; ri = ri->next) {
8277 total_count++;
8278 if (type == bgp_show_type_flap_statistics
8279 || type == bgp_show_type_flap_neighbor
8280 || type == bgp_show_type_dampend_paths
8281 || type == bgp_show_type_damp_neighbor) {
a4d82a8a 8282 if (!(ri->extra && ri->extra->damp_info))
98ce9a06
DS
8283 continue;
8284 }
8285 if (type == bgp_show_type_regexp) {
8286 regex_t *regex = output_arg;
d62a17ae 8287
98ce9a06
DS
8288 if (bgp_regexec(regex, ri->attr->aspath)
8289 == REG_NOMATCH)
8290 continue;
8291 }
8292 if (type == bgp_show_type_prefix_list) {
8293 struct prefix_list *plist = output_arg;
d62a17ae 8294
98ce9a06
DS
8295 if (prefix_list_apply(plist, &rn->p)
8296 != PREFIX_PERMIT)
8297 continue;
8298 }
8299 if (type == bgp_show_type_filter_list) {
8300 struct as_list *as_list = output_arg;
d62a17ae 8301
98ce9a06
DS
8302 if (as_list_apply(as_list, ri->attr->aspath)
8303 != AS_FILTER_PERMIT)
8304 continue;
8305 }
8306 if (type == bgp_show_type_route_map) {
8307 struct route_map *rmap = output_arg;
8308 struct bgp_info binfo;
8309 struct attr dummy_attr;
8310 int ret;
d62a17ae 8311
98ce9a06 8312 bgp_attr_dup(&dummy_attr, ri->attr);
d62a17ae 8313
98ce9a06
DS
8314 binfo.peer = ri->peer;
8315 binfo.attr = &dummy_attr;
d62a17ae 8316
a4d82a8a
PZ
8317 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
8318 &binfo);
98ce9a06
DS
8319 if (ret == RMAP_DENYMATCH)
8320 continue;
8321 }
8322 if (type == bgp_show_type_neighbor
8323 || type == bgp_show_type_flap_neighbor
8324 || type == bgp_show_type_damp_neighbor) {
8325 union sockunion *su = output_arg;
8326
8327 if (ri->peer == NULL
8328 || ri->peer->su_remote == NULL
a4d82a8a 8329 || !sockunion_same(ri->peer->su_remote, su))
98ce9a06
DS
8330 continue;
8331 }
8332 if (type == bgp_show_type_cidr_only) {
d7c0a89a 8333 uint32_t destination;
d62a17ae 8334
98ce9a06
DS
8335 destination = ntohl(rn->p.u.prefix4.s_addr);
8336 if (IN_CLASSC(destination)
8337 && rn->p.prefixlen == 24)
8338 continue;
8339 if (IN_CLASSB(destination)
8340 && rn->p.prefixlen == 16)
8341 continue;
8342 if (IN_CLASSA(destination)
8343 && rn->p.prefixlen == 8)
8344 continue;
8345 }
8346 if (type == bgp_show_type_prefix_longer) {
8347 struct prefix *p = output_arg;
d62a17ae 8348
98ce9a06
DS
8349 if (!prefix_match(p, &rn->p))
8350 continue;
8351 }
8352 if (type == bgp_show_type_community_all) {
8353 if (!ri->attr->community)
8354 continue;
8355 }
8356 if (type == bgp_show_type_community) {
8357 struct community *com = output_arg;
d62a17ae 8358
98ce9a06
DS
8359 if (!ri->attr->community
8360 || !community_match(ri->attr->community,
8361 com))
8362 continue;
8363 }
8364 if (type == bgp_show_type_community_exact) {
8365 struct community *com = output_arg;
d62a17ae 8366
98ce9a06 8367 if (!ri->attr->community
a4d82a8a 8368 || !community_cmp(ri->attr->community, com))
98ce9a06
DS
8369 continue;
8370 }
8371 if (type == bgp_show_type_community_list) {
8372 struct community_list *list = output_arg;
d62a17ae 8373
a4d82a8a
PZ
8374 if (!community_list_match(ri->attr->community,
8375 list))
98ce9a06
DS
8376 continue;
8377 }
a4d82a8a 8378 if (type == bgp_show_type_community_list_exact) {
98ce9a06 8379 struct community_list *list = output_arg;
d62a17ae 8380
98ce9a06
DS
8381 if (!community_list_exact_match(
8382 ri->attr->community, list))
8383 continue;
8384 }
8385 if (type == bgp_show_type_lcommunity) {
8386 struct lcommunity *lcom = output_arg;
d62a17ae 8387
98ce9a06
DS
8388 if (!ri->attr->lcommunity
8389 || !lcommunity_match(ri->attr->lcommunity,
8390 lcom))
8391 continue;
8392 }
8393 if (type == bgp_show_type_lcommunity_list) {
8394 struct community_list *list = output_arg;
d62a17ae 8395
a4d82a8a
PZ
8396 if (!lcommunity_list_match(ri->attr->lcommunity,
8397 list))
98ce9a06
DS
8398 continue;
8399 }
8400 if (type == bgp_show_type_lcommunity_all) {
8401 if (!ri->attr->lcommunity)
8402 continue;
8403 }
8404 if (type == bgp_show_type_dampend_paths
8405 || type == bgp_show_type_damp_neighbor) {
8406 if (!CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)
8407 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
8408 continue;
8409 }
8410
8411 if (!use_json && header) {
996c9314 8412 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 8413 ", local router ID is %s, vrf id ",
98ce9a06
DS
8414 table->version,
8415 inet_ntoa(bgp->router_id));
9df8b37c
PZ
8416 if (bgp->vrf_id == VRF_UNKNOWN)
8417 vty_out(vty, "%s", VRFID_NONE_STR);
8418 else
8419 vty_out(vty, "%u", bgp->vrf_id);
8420 vty_out(vty, "\n");
98ce9a06 8421 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 8422 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 8423 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8424 if (type == bgp_show_type_dampend_paths
8425 || type == bgp_show_type_damp_neighbor)
98ce9a06 8426 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
8427 else if (type == bgp_show_type_flap_statistics
8428 || type == bgp_show_type_flap_neighbor)
98ce9a06 8429 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8430 else
98ce9a06
DS
8431 vty_out(vty, BGP_SHOW_HEADER);
8432 header = 0;
d62a17ae 8433 }
98ce9a06
DS
8434 if (rd != NULL && !display && !output_count) {
8435 if (!use_json)
8436 vty_out(vty,
8437 "Route Distinguisher: %s\n",
8438 rd);
d62a17ae 8439 }
98ce9a06
DS
8440 if (type == bgp_show_type_dampend_paths
8441 || type == bgp_show_type_damp_neighbor)
8442 damp_route_vty_out(vty, &rn->p, ri, display,
a4d82a8a 8443 safi, use_json, json_paths);
98ce9a06
DS
8444 else if (type == bgp_show_type_flap_statistics
8445 || type == bgp_show_type_flap_neighbor)
8446 flap_route_vty_out(vty, &rn->p, ri, display,
a4d82a8a 8447 safi, use_json, json_paths);
98ce9a06 8448 else
a4d82a8a
PZ
8449 route_vty_out(vty, &rn->p, ri, display, safi,
8450 json_paths);
98ce9a06 8451 display++;
d62a17ae 8452 }
8453
98ce9a06
DS
8454 if (display) {
8455 output_count++;
8456 if (!use_json)
8457 continue;
8458
8459 p = &rn->p;
8460 sprintf(buf2, "%s/%d",
a4d82a8a 8461 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
98ce9a06 8462 p->prefixlen);
8cc84563
DS
8463 if (first)
8464 vty_out(vty, "\"%s\": ", buf2);
8465 else
8466 vty_out(vty, ",\"%s\": ", buf2);
8467
98ce9a06 8468 vty_out(vty, "%s",
23b2a7ef 8469 json_object_to_json_string(json_paths));
98ce9a06 8470 json_object_free(json_paths);
449feb8e 8471 json_paths = NULL;
98ce9a06
DS
8472 first = 0;
8473 }
8474 }
8475
1ae44dfc
LB
8476 if (output_cum) {
8477 output_count += *output_cum;
8478 *output_cum = output_count;
8479 }
8480 if (total_cum) {
8481 total_count += *total_cum;
8482 *total_cum = total_count;
8483 }
d62a17ae 8484 if (use_json) {
449feb8e
DS
8485 if (json_paths)
8486 json_object_free(json_paths);
9386b588 8487 if (rd) {
a4d82a8a 8488 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
8489 }
8490 if (is_last) {
a4d82a8a
PZ
8491 unsigned long i;
8492 for (i = 0; i < *json_header_depth; ++i)
8493 vty_out(vty, " } ");
9386b588 8494 }
d62a17ae 8495 } else {
1ae44dfc
LB
8496 if (is_last) {
8497 /* No route is displayed */
8498 if (output_count == 0) {
8499 if (type == bgp_show_type_normal)
8500 vty_out(vty,
8501 "No BGP prefixes displayed, %ld exist\n",
8502 total_count);
8503 } else
d62a17ae 8504 vty_out(vty,
1ae44dfc
LB
8505 "\nDisplayed %ld routes and %ld total paths\n",
8506 output_count, total_count);
8507 }
d62a17ae 8508 }
718e3744 8509
d62a17ae 8510 return CMD_SUCCESS;
718e3744 8511}
8512
1ae44dfc
LB
8513int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8514 struct bgp_table *table, struct prefix_rd *prd_match,
8515 enum bgp_show_type type, void *output_arg,
d7c0a89a 8516 uint8_t use_json)
1ae44dfc
LB
8517{
8518 struct bgp_node *rn, *next;
8519 unsigned long output_cum = 0;
8520 unsigned long total_cum = 0;
9386b588 8521 unsigned long json_header_depth = 0;
0136788c
LB
8522 bool show_msg;
8523
8524 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
8525
8526 for (rn = bgp_table_top(table); rn; rn = next) {
8527 next = bgp_route_next(rn);
8528 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8529 continue;
8530 if (rn->info != NULL) {
8531 struct prefix_rd prd;
06b9f471 8532 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8533
8534 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8535 prefix_rd2str(&prd, rd, sizeof(rd));
1ae44dfc 8536 bgp_show_table(vty, bgp, safi, rn->info, type,
a4d82a8a 8537 output_arg, use_json, rd, next == NULL,
9386b588
PZ
8538 &output_cum, &total_cum,
8539 &json_header_depth);
0136788c
LB
8540 if (next == NULL)
8541 show_msg = false;
1ae44dfc
LB
8542 }
8543 }
0136788c
LB
8544 if (show_msg) {
8545 if (output_cum == 0)
8546 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
8547 total_cum);
8548 else
8549 vty_out(vty,
8550 "\nDisplayed %ld routes and %ld total paths\n",
8551 output_cum, total_cum);
8552 }
1ae44dfc
LB
8553 return CMD_SUCCESS;
8554}
d62a17ae 8555static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
d7c0a89a 8556 enum bgp_show_type type, void *output_arg, uint8_t use_json)
fee0f4c6 8557{
d62a17ae 8558 struct bgp_table *table;
9386b588 8559 unsigned long json_header_depth = 0;
fee0f4c6 8560
d62a17ae 8561 if (bgp == NULL) {
8562 bgp = bgp_get_default();
8563 }
fee0f4c6 8564
d62a17ae 8565 if (bgp == NULL) {
8566 if (!use_json)
8567 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8568 else
8569 vty_out(vty, "{}\n");
d62a17ae 8570 return CMD_WARNING;
8571 }
4dd6177e 8572
1ae44dfc 8573 table = bgp->rib[afi][safi];
d62a17ae 8574 /* use MPLS and ENCAP specific shows until they are merged */
8575 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
8576 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
8577 output_arg, use_json);
d62a17ae 8578 }
dba3c1d3
PG
8579
8580 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
8581 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
8582 output_arg, use_json,
8583 1, NULL, NULL);
8584 }
d62a17ae 8585 /* labeled-unicast routes live in the unicast table */
8586 else if (safi == SAFI_LABELED_UNICAST)
8587 safi = SAFI_UNICAST;
fee0f4c6 8588
1ae44dfc 8589 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 8590 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 8591}
8592
d62a17ae 8593static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
d7c0a89a 8594 safi_t safi, uint8_t use_json)
f186de26 8595{
d62a17ae 8596 struct listnode *node, *nnode;
8597 struct bgp *bgp;
8598 int is_first = 1;
f186de26 8599
d62a17ae 8600 if (use_json)
8601 vty_out(vty, "{\n");
9f689658 8602
d62a17ae 8603 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
8604 if (use_json) {
8605 if (!is_first)
8606 vty_out(vty, ",\n");
8607 else
8608 is_first = 0;
8609
8610 vty_out(vty, "\"%s\":",
8611 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8612 ? "Default"
8613 : bgp->name);
8614 } else {
8615 vty_out(vty, "\nInstance %s:\n",
8616 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8617 ? "Default"
8618 : bgp->name);
8619 }
8620 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8621 use_json);
8622 }
9f689658 8623
d62a17ae 8624 if (use_json)
8625 vty_out(vty, "}\n");
f186de26 8626}
8627
718e3744 8628/* Header of detailed BGP route information */
d62a17ae 8629void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8630 struct bgp_node *rn, struct prefix_rd *prd,
8631 afi_t afi, safi_t safi, json_object *json)
8632{
8633 struct bgp_info *ri;
8634 struct prefix *p;
8635 struct peer *peer;
8636 struct listnode *node, *nnode;
06b9f471 8637 char buf1[RD_ADDRSTRLEN];
d62a17ae 8638 char buf2[INET6_ADDRSTRLEN];
8c197128 8639#if defined(HAVE_CUMULUS)
d62a17ae 8640 char buf3[EVPN_ROUTE_STRLEN];
8c197128 8641#endif
0291c246 8642 char prefix_str[BUFSIZ];
d62a17ae 8643 int count = 0;
8644 int best = 0;
8645 int suppress = 0;
8646 int no_export = 0;
8647 int no_advertise = 0;
8648 int local_as = 0;
8649 int first = 1;
8650 int has_valid_label = 0;
8651 mpls_label_t label = 0;
8652 json_object *json_adv_to = NULL;
9bedbb1e 8653
d62a17ae 8654 p = &rn->p;
8655 has_valid_label = bgp_is_valid_label(&rn->local_label);
8656
8657 if (has_valid_label)
8658 label = label_pton(&rn->local_label);
8659
8660 if (json) {
8661 if (has_valid_label)
8662 json_object_int_add(json, "localLabel", label);
8663
60466a63
QY
8664 json_object_string_add(
8665 json, "prefix",
8666 prefix2str(p, prefix_str, sizeof(prefix_str)));
d62a17ae 8667 } else {
8668#if defined(HAVE_CUMULUS)
8669 if (safi == SAFI_EVPN)
8670 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 8671 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 8672 : "",
8673 prd ? ":" : "",
8674 bgp_evpn_route2str((struct prefix_evpn *)p,
8675 buf3, sizeof(buf3)));
8676 else
8677 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8678 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8679 ? prefix_rd2str(prd, buf1,
06b9f471 8680 sizeof(buf1))
d62a17ae 8681 : ""),
8682 safi == SAFI_MPLS_VPN ? ":" : "",
8683 inet_ntop(p->family, &p->u.prefix, buf2,
8684 INET6_ADDRSTRLEN),
8685 p->prefixlen);
520d5d76 8686#else
d62a17ae 8687 if (p->family == AF_ETHERNET)
8688 prefix2str(p, buf2, INET6_ADDRSTRLEN);
8689 else
8690 inet_ntop(p->family, &p->u.prefix, buf2,
8691 INET6_ADDRSTRLEN);
8692 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8693 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8694 || safi == SAFI_EVPN)
a4d82a8a
PZ
8695 ? prefix_rd2str(prd, buf1, sizeof(buf1))
8696 : ""),
d62a17ae 8697 ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":"
8698 : "",
8699 buf2, p->prefixlen);
520d5d76 8700#endif
cd1964ff 8701
d62a17ae 8702 if (has_valid_label)
8703 vty_out(vty, "Local label: %d\n", label);
8704#if defined(HAVE_CUMULUS)
8705 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
520d5d76 8706#else
d62a17ae 8707 if (bgp_labeled_safi(safi))
520d5d76 8708#endif
d62a17ae 8709 vty_out(vty, "not allocated\n");
8710 }
718e3744 8711
d62a17ae 8712 for (ri = rn->info; ri; ri = ri->next) {
8713 count++;
8714 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
8715 best = count;
8716 if (ri->extra && ri->extra->suppress)
8717 suppress = 1;
8718 if (ri->attr->community != NULL) {
8719 if (community_include(ri->attr->community,
8720 COMMUNITY_NO_ADVERTISE))
8721 no_advertise = 1;
8722 if (community_include(ri->attr->community,
8723 COMMUNITY_NO_EXPORT))
8724 no_export = 1;
8725 if (community_include(ri->attr->community,
8726 COMMUNITY_LOCAL_AS))
8727 local_as = 1;
8728 }
8729 }
718e3744 8730 }
718e3744 8731
d62a17ae 8732 if (!json) {
8733 vty_out(vty, "Paths: (%d available", count);
8734 if (best) {
8735 vty_out(vty, ", best #%d", best);
8736 if (safi == SAFI_UNICAST)
8737 vty_out(vty, ", table %s",
8738 (bgp->inst_type
8739 == BGP_INSTANCE_TYPE_DEFAULT)
8740 ? "Default-IP-Routing-Table"
8741 : bgp->name);
8742 } else
8743 vty_out(vty, ", no best path");
8744
8745 if (no_advertise)
8746 vty_out(vty, ", not advertised to any peer");
8747 else if (no_export)
8748 vty_out(vty, ", not advertised to EBGP peer");
8749 else if (local_as)
8750 vty_out(vty, ", not advertised outside local AS");
8751
8752 if (suppress)
8753 vty_out(vty,
8754 ", Advertisements suppressed by an aggregate.");
8755 vty_out(vty, ")\n");
8756 }
718e3744 8757
d62a17ae 8758 /* If we are not using addpath then we can display Advertised to and
8759 * that will
8760 * show what peers we advertised the bestpath to. If we are using
8761 * addpath
8762 * though then we must display Advertised to on a path-by-path basis. */
8763 if (!bgp->addpath_tx_used[afi][safi]) {
8764 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8765 if (bgp_adj_out_lookup(peer, rn, 0)) {
8766 if (json && !json_adv_to)
8767 json_adv_to = json_object_new_object();
8768
8769 route_vty_out_advertised_to(
8770 vty, peer, &first,
8771 " Advertised to non peer-group peers:\n ",
8772 json_adv_to);
8773 }
8774 }
8775
8776 if (json) {
8777 if (json_adv_to) {
8778 json_object_object_add(json, "advertisedTo",
8779 json_adv_to);
8780 }
8781 } else {
8782 if (first)
8783 vty_out(vty, " Not advertised to any peer");
8784 vty_out(vty, "\n");
8785 }
8786 }
718e3744 8787}
8788
8789/* Display specified route of BGP table. */
d62a17ae 8790static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
8791 struct bgp_table *rib, const char *ip_str,
8792 afi_t afi, safi_t safi,
8793 struct prefix_rd *prd, int prefix_check,
d7c0a89a
QY
8794 enum bgp_path_type pathtype,
8795 uint8_t use_json)
d62a17ae 8796{
8797 int ret;
8798 int header;
8799 int display = 0;
8800 struct prefix match;
8801 struct bgp_node *rn;
8802 struct bgp_node *rm;
8803 struct bgp_info *ri;
8804 struct bgp_table *table;
8805 json_object *json = NULL;
8806 json_object *json_paths = NULL;
8807
8808 /* Check IP address argument. */
8809 ret = str2prefix(ip_str, &match);
8810 if (!ret) {
8811 vty_out(vty, "address is malformed\n");
8812 return CMD_WARNING;
8813 }
718e3744 8814
d62a17ae 8815 match.family = afi2family(afi);
b05a1c8b 8816
d62a17ae 8817 if (use_json) {
8818 json = json_object_new_object();
8819 json_paths = json_object_new_array();
8820 }
718e3744 8821
d62a17ae 8822 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
8823 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
8824 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
8825 continue;
8826
ea47320b
DL
8827 if ((table = rn->info) == NULL)
8828 continue;
d62a17ae 8829
ea47320b
DL
8830 header = 1;
8831
8832 if ((rm = bgp_node_match(table, &match)) == NULL)
8833 continue;
d62a17ae 8834
ea47320b
DL
8835 if (prefix_check
8836 && rm->p.prefixlen != match.prefixlen) {
8837 bgp_unlock_node(rm);
8838 continue;
8839 }
d62a17ae 8840
ea47320b
DL
8841 for (ri = rm->info; ri; ri = ri->next) {
8842 if (header) {
60466a63
QY
8843 route_vty_out_detail_header(
8844 vty, bgp, rm,
8845 (struct prefix_rd *)&rn->p,
ea47320b
DL
8846 AFI_IP, safi, json);
8847 header = 0;
d62a17ae 8848 }
ea47320b
DL
8849 display++;
8850
8851 if (pathtype == BGP_PATH_ALL
8852 || (pathtype == BGP_PATH_BESTPATH
8853 && CHECK_FLAG(ri->flags,
8854 BGP_INFO_SELECTED))
8855 || (pathtype == BGP_PATH_MULTIPATH
8856 && (CHECK_FLAG(ri->flags,
8857 BGP_INFO_MULTIPATH)
8858 || CHECK_FLAG(ri->flags,
60466a63 8859 BGP_INFO_SELECTED))))
ea47320b
DL
8860 route_vty_out_detail(vty, bgp, &rm->p,
8861 ri, AFI_IP, safi,
8862 json_paths);
d62a17ae 8863 }
ea47320b
DL
8864
8865 bgp_unlock_node(rm);
d62a17ae 8866 }
98a9dbc7
PG
8867 } else if (safi == SAFI_FLOWSPEC) {
8868 rn = bgp_flowspec_get_match_per_ip(afi, rib,
8869 &match, prefix_check);
8870 if (rn != NULL) {
8871 route_vty_out_flowspec(vty, &rn->p,
8872 rn->info, use_json ?
8873 NLRI_STRING_FORMAT_JSON :
8874 NLRI_STRING_FORMAT_LARGE,
8875 json_paths);
8876 display++;
8877 bgp_unlock_node(rn);
8878 }
d62a17ae 8879 } else {
8880 header = 1;
8881
8882 if ((rn = bgp_node_match(rib, &match)) != NULL) {
8883 if (!prefix_check
8884 || rn->p.prefixlen == match.prefixlen) {
8885 for (ri = rn->info; ri; ri = ri->next) {
8886 if (header) {
8887 route_vty_out_detail_header(
8888 vty, bgp, rn, NULL, afi,
8889 safi, json);
8890 header = 0;
8891 }
8892 display++;
8893
8894 if (pathtype == BGP_PATH_ALL
8895 || (pathtype == BGP_PATH_BESTPATH
8896 && CHECK_FLAG(
8897 ri->flags,
8898 BGP_INFO_SELECTED))
8899 || (pathtype == BGP_PATH_MULTIPATH
8900 && (CHECK_FLAG(
8901 ri->flags,
8902 BGP_INFO_MULTIPATH)
8903 || CHECK_FLAG(
8904 ri->flags,
8905 BGP_INFO_SELECTED))))
8906 route_vty_out_detail(
8907 vty, bgp, &rn->p, ri,
8908 afi, safi, json_paths);
8909 }
8910 }
8911
8912 bgp_unlock_node(rn);
8913 }
8914 }
e5eee9af 8915
d62a17ae 8916 if (use_json) {
8917 if (display)
8918 json_object_object_add(json, "paths", json_paths);
8919
996c9314
LB
8920 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8921 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 8922 json_object_free(json);
8923 } else {
8924 if (!display) {
8925 vty_out(vty, "%% Network not in table\n");
8926 return CMD_WARNING;
8927 }
8928 }
b05a1c8b 8929
d62a17ae 8930 return CMD_SUCCESS;
718e3744 8931}
8932
fee0f4c6 8933/* Display specified route of Main RIB */
d62a17ae 8934static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
8935 afi_t afi, safi_t safi, struct prefix_rd *prd,
8936 int prefix_check, enum bgp_path_type pathtype,
d7c0a89a 8937 uint8_t use_json)
d62a17ae 8938{
9b86009a 8939 if (!bgp) {
d62a17ae 8940 bgp = bgp_get_default();
9b86009a
RW
8941 if (!bgp) {
8942 if (!use_json)
8943 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8944 else
8945 vty_out(vty, "{}\n");
9b86009a
RW
8946 return CMD_WARNING;
8947 }
8948 }
d62a17ae 8949
8950 /* labeled-unicast routes live in the unicast table */
8951 if (safi == SAFI_LABELED_UNICAST)
8952 safi = SAFI_UNICAST;
8953
8954 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
8955 afi, safi, prd, prefix_check, pathtype,
8956 use_json);
8957}
8958
8959static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
8960 struct cmd_token **argv, afi_t afi, safi_t safi,
d7c0a89a 8961 uint8_t uj)
d62a17ae 8962{
8963 struct lcommunity *lcom;
8964 struct buffer *b;
8965 int i;
8966 char *str;
8967 int first = 0;
8968
8969 b = buffer_new(1024);
8970 for (i = 0; i < argc; i++) {
8971 if (first)
8972 buffer_putc(b, ' ');
8973 else {
8974 if (strmatch(argv[i]->text, "AA:BB:CC")) {
8975 first = 1;
8976 buffer_putstr(b, argv[i]->arg);
8977 }
8978 }
8979 }
8980 buffer_putc(b, '\0');
57d187bc 8981
d62a17ae 8982 str = buffer_getstr(b);
8983 buffer_free(b);
57d187bc 8984
d62a17ae 8985 lcom = lcommunity_str2com(str);
8986 XFREE(MTYPE_TMP, str);
8987 if (!lcom) {
8988 vty_out(vty, "%% Large-community malformed\n");
8989 return CMD_WARNING;
8990 }
57d187bc 8991
d62a17ae 8992 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
8993 uj);
57d187bc
JS
8994}
8995
d62a17ae 8996static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
8997 const char *lcom, afi_t afi, safi_t safi,
d7c0a89a 8998 uint8_t uj)
57d187bc 8999{
d62a17ae 9000 struct community_list *list;
57d187bc 9001
d62a17ae 9002 list = community_list_lookup(bgp_clist, lcom,
9003 LARGE_COMMUNITY_LIST_MASTER);
9004 if (list == NULL) {
9005 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9006 lcom);
9007 return CMD_WARNING;
9008 }
57d187bc 9009
d62a17ae 9010 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
9011 list, uj);
fee0f4c6 9012}
9013
52951b63
DS
9014DEFUN (show_ip_bgp_large_community_list,
9015 show_ip_bgp_large_community_list_cmd,
4dd6177e 9016 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
52951b63
DS
9017 SHOW_STR
9018 IP_STR
9019 BGP_STR
9020 BGP_INSTANCE_HELP_STR
9bedbb1e 9021 BGP_AFI_HELP_STR
4dd6177e 9022 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9023 "Display routes matching the large-community-list\n"
9024 "large-community-list number\n"
9025 "large-community-list name\n"
9026 JSON_STR)
9027{
d62a17ae 9028 char *vrf = NULL;
9029 afi_t afi = AFI_IP6;
9030 safi_t safi = SAFI_UNICAST;
9031 int idx = 0;
9032
9033 if (argv_find(argv, argc, "ip", &idx))
9034 afi = AFI_IP;
9035 if (argv_find(argv, argc, "view", &idx)
9036 || argv_find(argv, argc, "vrf", &idx))
9037 vrf = argv[++idx]->arg;
9038 if (argv_find(argv, argc, "ipv4", &idx)
9039 || argv_find(argv, argc, "ipv6", &idx)) {
9040 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9041 if (argv_find(argv, argc, "unicast", &idx)
9042 || argv_find(argv, argc, "multicast", &idx))
9043 safi = bgp_vty_safi_from_str(argv[idx]->text);
9044 }
9045
9046 int uj = use_json(argc, argv);
9047
9048 struct bgp *bgp = bgp_lookup_by_name(vrf);
9049 if (bgp == NULL) {
9050 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9051 return CMD_WARNING;
9052 }
9053
9054 argv_find(argv, argc, "large-community-list", &idx);
9055 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
9056 uj);
52951b63
DS
9057}
9058DEFUN (show_ip_bgp_large_community,
9059 show_ip_bgp_large_community_cmd,
4dd6177e 9060 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
9061 SHOW_STR
9062 IP_STR
9063 BGP_STR
9064 BGP_INSTANCE_HELP_STR
9bedbb1e 9065 BGP_AFI_HELP_STR
4dd6177e 9066 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9067 "Display routes matching the large-communities\n"
9068 "List of large-community numbers\n"
9069 JSON_STR)
9070{
d62a17ae 9071 char *vrf = NULL;
9072 afi_t afi = AFI_IP6;
9073 safi_t safi = SAFI_UNICAST;
9074 int idx = 0;
9075
9076 if (argv_find(argv, argc, "ip", &idx))
9077 afi = AFI_IP;
9078 if (argv_find(argv, argc, "view", &idx)
9079 || argv_find(argv, argc, "vrf", &idx))
9080 vrf = argv[++idx]->arg;
9081 if (argv_find(argv, argc, "ipv4", &idx)
9082 || argv_find(argv, argc, "ipv6", &idx)) {
9083 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9084 if (argv_find(argv, argc, "unicast", &idx)
9085 || argv_find(argv, argc, "multicast", &idx))
9086 safi = bgp_vty_safi_from_str(argv[idx]->text);
9087 }
9088
9089 int uj = use_json(argc, argv);
9090
9091 struct bgp *bgp = bgp_lookup_by_name(vrf);
9092 if (bgp == NULL) {
9093 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9094 return CMD_WARNING;
9095 }
9096
9097 if (argv_find(argv, argc, "AA:BB:CC", &idx))
9098 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
9099 else
9100 return bgp_show(vty, bgp, afi, safi,
9101 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
9102}
9103
d62a17ae 9104static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9105 safi_t safi);
e01ca200 9106
7b2ff250
DW
9107
9108/* BGP route print out function without JSON */
af462945
DS
9109DEFUN (show_ip_bgp,
9110 show_ip_bgp_cmd,
4dd6177e 9111 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
9112 <dampening <parameters>\
9113 |route-map WORD\
9114 |prefix-list WORD\
9115 |filter-list WORD\
9116 |statistics\
31d5efe2 9117 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
7b2ff250
DW
9118 |community-list <(1-500)|WORD> [exact-match]\
9119 |A.B.C.D/M longer-prefixes\
9120 |X:X::X:X/M longer-prefixes\
9121 >",
718e3744 9122 SHOW_STR
9123 IP_STR
9124 BGP_STR
a636c635 9125 BGP_INSTANCE_HELP_STR
4f280b15 9126 BGP_AFI_HELP_STR
4dd6177e 9127 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 9128 "Display detailed information about dampening\n"
af462945 9129 "Display detail of configured dampening parameters\n"
a636c635
DW
9130 "Display routes matching the route-map\n"
9131 "A route-map to match on\n"
9132 "Display routes conforming to the prefix-list\n"
8c3deaae 9133 "Prefix-list name\n"
a636c635
DW
9134 "Display routes conforming to the filter-list\n"
9135 "Regular expression access list name\n"
e01ca200 9136 "BGP RIB advertisement statistics\n"
a636c635
DW
9137 "Display routes matching the communities\n"
9138 COMMUNITY_AANN_STR
9139 "Do not send outside local AS (well-known community)\n"
9140 "Do not advertise to any peer (well-known community)\n"
9141 "Do not export to next AS (well-known community)\n"
7f323236 9142 "Graceful shutdown (well-known community)\n"
a636c635
DW
9143 "Exact match of the communities\n"
9144 "Display routes matching the community-list\n"
9145 "community-list number\n"
9146 "community-list name\n"
9147 "Exact match of the communities\n"
0c7b1b01 9148 "IPv4 prefix\n"
8c3deaae 9149 "Display route and more specific routes\n"
0c7b1b01 9150 "IPv6 prefix\n"
7b2ff250 9151 "Display route and more specific routes\n")
718e3744 9152{
d62a17ae 9153 afi_t afi = AFI_IP6;
9154 safi_t safi = SAFI_UNICAST;
9155 int exact_match = 0;
d62a17ae 9156 struct bgp *bgp = NULL;
9157 int idx = 0;
7f323236 9158 int idx_community_type = 0;
d62a17ae 9159
9160 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9161 &bgp);
9162 if (!idx)
9163 return CMD_WARNING;
9164
d62a17ae 9165 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 9166 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 9167 return bgp_show_dampening_parameters(vty, afi, safi);
9168 }
c016b6c7 9169
d62a17ae 9170 if (argv_find(argv, argc, "prefix-list", &idx))
9171 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
9172 safi, bgp_show_type_prefix_list);
9173
9174 if (argv_find(argv, argc, "filter-list", &idx))
9175 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
9176 safi, bgp_show_type_filter_list);
9177
9178 if (argv_find(argv, argc, "statistics", &idx))
9179 return bgp_table_stats(vty, bgp, afi, safi);
9180
9181 if (argv_find(argv, argc, "route-map", &idx))
9182 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
9183 safi, bgp_show_type_route_map);
9184
9185 if (argv_find(argv, argc, "community", &idx)) {
9186 /* show a specific community */
7f323236 9187 if (argv_find(argv, argc, "local-AS", &idx_community_type)
a4d82a8a
PZ
9188 || argv_find(argv, argc, "no-advertise",
9189 &idx_community_type)
7f323236 9190 || argv_find(argv, argc, "no-export", &idx_community_type)
a4d82a8a
PZ
9191 || argv_find(argv, argc, "graceful-shutdown",
9192 &idx_community_type)
7f323236
DW
9193 || argv_find(argv, argc, "AA:NN", &idx_community_type)) {
9194
9195 if (argv_find(argv, argc, "exact-match", &idx))
d62a17ae 9196 exact_match = 1;
a4d82a8a
PZ
9197 return bgp_show_community(vty, bgp,
9198 argv[idx_community_type]->arg,
d62a17ae 9199 exact_match, afi, safi);
9200 }
d62a17ae 9201 }
a636c635 9202
d62a17ae 9203 if (argv_find(argv, argc, "community-list", &idx)) {
9204 const char *clist_number_or_name = argv[++idx]->arg;
9205 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
9206 exact_match = 1;
9207 return bgp_show_community_list(vty, bgp, clist_number_or_name,
9208 exact_match, afi, safi);
9209 }
9210 /* prefix-longer */
9211 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9212 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9213 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
9214 safi,
9215 bgp_show_type_prefix_longer);
9216
7b2ff250
DW
9217 return CMD_WARNING;
9218}
9219
9220/* BGP route print out function with JSON */
9221DEFUN (show_ip_bgp_json,
9222 show_ip_bgp_json_cmd,
9223 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
9224 [<\
9225 cidr-only\
9226 |dampening <flap-statistics|dampened-paths>\
9227 |community \
9228 >] [json]",
9229 SHOW_STR
9230 IP_STR
9231 BGP_STR
9232 BGP_INSTANCE_HELP_STR
9233 BGP_AFI_HELP_STR
9234 BGP_SAFI_WITH_LABEL_HELP_STR
9235 "Display only routes with non-natural netmasks\n"
9236 "Display detailed information about dampening\n"
9237 "Display flap statistics of routes\n"
9238 "Display paths suppressed due to dampening\n"
9239 "Display routes matching the communities\n"
9240 JSON_STR)
9241{
9242 afi_t afi = AFI_IP6;
9243 safi_t safi = SAFI_UNICAST;
9244 enum bgp_show_type sh_type = bgp_show_type_normal;
9245 struct bgp *bgp = NULL;
9246 int idx = 0;
9247
9248 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9249 &bgp);
9250 if (!idx)
9251 return CMD_WARNING;
9252
9253 int uj = use_json(argc, argv);
9254 if (uj)
9255 argc--;
9256
9257 if (argv_find(argv, argc, "cidr-only", &idx))
9258 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
9259 NULL, uj);
9260
9261 if (argv_find(argv, argc, "dampening", &idx)) {
9262 if (argv_find(argv, argc, "dampened-paths", &idx))
9263 return bgp_show(vty, bgp, afi, safi,
9264 bgp_show_type_dampend_paths, NULL, uj);
9265 else if (argv_find(argv, argc, "flap-statistics", &idx))
9266 return bgp_show(vty, bgp, afi, safi,
9267 bgp_show_type_flap_statistics, NULL,
9268 uj);
9269 }
9270
9271 if (argv_find(argv, argc, "community", &idx)) {
9272 /* show all communities */
9273 return bgp_show(vty, bgp, afi, safi,
9274 bgp_show_type_community_all, NULL, uj);
9275 }
1ae44dfc 9276 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 9277}
47fc97cc 9278
718e3744 9279DEFUN (show_ip_bgp_route,
9280 show_ip_bgp_route_cmd,
4dd6177e 9281 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 9282 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 9283 SHOW_STR
9284 IP_STR
9285 BGP_STR
a636c635 9286 BGP_INSTANCE_HELP_STR
4f280b15 9287 BGP_AFI_HELP_STR
4dd6177e 9288 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 9289 "Network in the BGP routing table to display\n"
0c7b1b01 9290 "IPv4 prefix\n"
8c3deaae 9291 "Network in the BGP routing table to display\n"
0c7b1b01 9292 "IPv6 prefix\n"
4092b06c 9293 "Display only the bestpath\n"
b05a1c8b 9294 "Display only multipaths\n"
9973d184 9295 JSON_STR)
4092b06c 9296{
d62a17ae 9297 int prefix_check = 0;
ae19d7dd 9298
d62a17ae 9299 afi_t afi = AFI_IP6;
9300 safi_t safi = SAFI_UNICAST;
9301 char *prefix = NULL;
9302 struct bgp *bgp = NULL;
9303 enum bgp_path_type path_type;
d7c0a89a 9304 uint8_t uj = use_json(argc, argv);
b05a1c8b 9305
d62a17ae 9306 int idx = 0;
ae19d7dd 9307
d62a17ae 9308 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9309 &bgp);
9310 if (!idx)
9311 return CMD_WARNING;
c41247f5 9312
d62a17ae 9313 if (!bgp) {
9314 vty_out(vty,
9315 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9316 return CMD_WARNING;
9317 }
a636c635 9318
d62a17ae 9319 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9320 if (argv_find(argv, argc, "A.B.C.D", &idx)
9321 || argv_find(argv, argc, "X:X::X:X", &idx))
9322 prefix_check = 0;
9323 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9324 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9325 prefix_check = 1;
9326
9327 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9328 && afi != AFI_IP6) {
9329 vty_out(vty,
9330 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9331 return CMD_WARNING;
9332 }
9333 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9334 && afi != AFI_IP) {
9335 vty_out(vty,
9336 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9337 return CMD_WARNING;
9338 }
9339
9340 prefix = argv[idx]->arg;
9341
9342 /* [<bestpath|multipath>] */
9343 if (argv_find(argv, argc, "bestpath", &idx))
9344 path_type = BGP_PATH_BESTPATH;
9345 else if (argv_find(argv, argc, "multipath", &idx))
9346 path_type = BGP_PATH_MULTIPATH;
9347 else
9348 path_type = BGP_PATH_ALL;
a636c635 9349
d62a17ae 9350 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9351 path_type, uj);
4092b06c
DS
9352}
9353
8c3deaae
QY
9354DEFUN (show_ip_bgp_regexp,
9355 show_ip_bgp_regexp_cmd,
4dd6177e 9356 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9357 SHOW_STR
9358 IP_STR
9359 BGP_STR
b00b230a 9360 BGP_INSTANCE_HELP_STR
4f280b15 9361 BGP_AFI_HELP_STR
4dd6177e 9362 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9363 "Display routes matching the AS path regular expression\n"
9364 "A regular-expression to match the BGP AS paths\n")
9365{
d62a17ae 9366 afi_t afi = AFI_IP6;
9367 safi_t safi = SAFI_UNICAST;
9368 struct bgp *bgp = NULL;
8c3deaae 9369
d62a17ae 9370 int idx = 0;
9371 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9372 &bgp);
9373 if (!idx)
9374 return CMD_WARNING;
8c3deaae 9375
d62a17ae 9376 // get index of regex
9377 argv_find(argv, argc, "regexp", &idx);
9378 idx++;
8c3deaae 9379
d62a17ae 9380 char *regstr = argv_concat(argv, argc, idx);
e889891d 9381 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 9382 bgp_show_type_regexp);
9383 XFREE(MTYPE_TMP, regstr);
9384 return rc;
8c3deaae
QY
9385}
9386
a636c635
DW
9387DEFUN (show_ip_bgp_instance_all,
9388 show_ip_bgp_instance_all_cmd,
4dd6177e 9389 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9390 SHOW_STR
a636c635 9391 IP_STR
4092b06c 9392 BGP_STR
a636c635 9393 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9394 BGP_AFI_HELP_STR
4dd6177e 9395 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9396 JSON_STR)
4092b06c 9397{
d62a17ae 9398 afi_t afi = AFI_IP;
9399 safi_t safi = SAFI_UNICAST;
9400 struct bgp *bgp = NULL;
ae19d7dd 9401
d62a17ae 9402 int idx = 0;
9403 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9404 &bgp);
9405 if (!idx)
9406 return CMD_WARNING;
ae19d7dd 9407
d62a17ae 9408 int uj = use_json(argc, argv);
9409 if (uj)
9410 argc--;
e3e29b32 9411
d62a17ae 9412 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9413 return CMD_SUCCESS;
e3e29b32
LB
9414}
9415
a4d82a8a
PZ
9416static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9417 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 9418{
d62a17ae 9419 regex_t *regex;
9420 int rc;
e3e29b32 9421
d62a17ae 9422 regex = bgp_regcomp(regstr);
9423 if (!regex) {
9424 vty_out(vty, "Can't compile regexp %s\n", regstr);
9425 return CMD_WARNING;
9426 }
a636c635 9427
e889891d 9428 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 9429 bgp_regex_free(regex);
9430 return rc;
e3e29b32
LB
9431}
9432
d62a17ae 9433static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9434 const char *prefix_list_str, afi_t afi,
9435 safi_t safi, enum bgp_show_type type)
e3e29b32 9436{
d62a17ae 9437 struct prefix_list *plist;
718e3744 9438
d62a17ae 9439 plist = prefix_list_lookup(afi, prefix_list_str);
9440 if (plist == NULL) {
9441 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9442 prefix_list_str);
9443 return CMD_WARNING;
9444 }
718e3744 9445
d62a17ae 9446 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9447}
9448
d62a17ae 9449static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9450 const char *filter, afi_t afi, safi_t safi,
9451 enum bgp_show_type type)
4092b06c 9452{
d62a17ae 9453 struct as_list *as_list;
718e3744 9454
d62a17ae 9455 as_list = as_list_lookup(filter);
9456 if (as_list == NULL) {
9457 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9458 filter);
9459 return CMD_WARNING;
9460 }
a636c635 9461
d62a17ae 9462 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9463}
9464
d62a17ae 9465static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9466 const char *rmap_str, afi_t afi, safi_t safi,
9467 enum bgp_show_type type)
718e3744 9468{
d62a17ae 9469 struct route_map *rmap;
bb46e94f 9470
d62a17ae 9471 rmap = route_map_lookup_by_name(rmap_str);
9472 if (!rmap) {
9473 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9474 return CMD_WARNING;
9475 }
9476
9477 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9478}
9479
7f323236
DW
9480static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9481 const char *comstr, int exact, afi_t afi,
d62a17ae 9482 safi_t safi)
9483{
9484 struct community *com;
d62a17ae 9485 int ret = 0;
9486
7f323236 9487 com = community_str2com(comstr);
d62a17ae 9488 if (!com) {
7f323236 9489 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 9490 return CMD_WARNING;
9491 }
9492
9493 ret = bgp_show(vty, bgp, afi, safi,
9494 (exact ? bgp_show_type_community_exact
9495 : bgp_show_type_community),
9496 com, 0);
9497 community_free(com);
46c3ce83 9498
d62a17ae 9499 return ret;
718e3744 9500}
9501
d62a17ae 9502static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9503 const char *com, int exact, afi_t afi,
9504 safi_t safi)
50ef26d4 9505{
d62a17ae 9506 struct community_list *list;
50ef26d4 9507
d62a17ae 9508 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9509 if (list == NULL) {
9510 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9511 return CMD_WARNING;
9512 }
718e3744 9513
d62a17ae 9514 return bgp_show(vty, bgp, afi, safi,
9515 (exact ? bgp_show_type_community_list_exact
9516 : bgp_show_type_community_list),
9517 list, 0);
50ef26d4 9518}
9519
d62a17ae 9520static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9521 const char *prefix, afi_t afi, safi_t safi,
9522 enum bgp_show_type type)
718e3744 9523{
d62a17ae 9524 int ret;
9525 struct prefix *p;
47fc97cc 9526
d62a17ae 9527 p = prefix_new();
95cbbd2a 9528
d62a17ae 9529 ret = str2prefix(prefix, p);
9530 if (!ret) {
9531 vty_out(vty, "%% Malformed Prefix\n");
9532 return CMD_WARNING;
9533 }
47e9b292 9534
d62a17ae 9535 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9536 prefix_free(p);
9537 return ret;
9538}
9539
9540static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
d7c0a89a 9541 const char *ip_str, uint8_t use_json)
d62a17ae 9542{
9543 int ret;
9544 struct peer *peer;
9545 union sockunion su;
9546
9547 /* Get peer sockunion. */
9548 ret = str2sockunion(ip_str, &su);
9549 if (ret < 0) {
9550 peer = peer_lookup_by_conf_if(bgp, ip_str);
9551 if (!peer) {
9552 peer = peer_lookup_by_hostname(bgp, ip_str);
9553
9554 if (!peer) {
9555 if (use_json) {
9556 json_object *json_no = NULL;
9557 json_no = json_object_new_object();
9558 json_object_string_add(
9559 json_no,
9560 "malformedAddressOrName",
9561 ip_str);
9562 vty_out(vty, "%s\n",
66f80d74 9563 json_object_to_json_string_ext(
a4d82a8a
PZ
9564 json_no,
9565 JSON_C_TO_STRING_PRETTY));
d62a17ae 9566 json_object_free(json_no);
9567 } else
9568 vty_out(vty,
9569 "%% Malformed address or name: %s\n",
9570 ip_str);
9571 return NULL;
9572 }
9573 }
9574 return peer;
9575 }
718e3744 9576
d62a17ae 9577 /* Peer structure lookup. */
9578 peer = peer_lookup(bgp, &su);
9579 if (!peer) {
9580 if (use_json) {
9581 json_object *json_no = NULL;
9582 json_no = json_object_new_object();
9583 json_object_string_add(json_no, "warning",
9e6e6f46 9584 "No such neighbor in this view/vrf");
d62a17ae 9585 vty_out(vty, "%s\n",
a4d82a8a
PZ
9586 json_object_to_json_string_ext(
9587 json_no, JSON_C_TO_STRING_PRETTY));
d62a17ae 9588 json_object_free(json_no);
9589 } else
9e6e6f46 9590 vty_out(vty, "No such neighbor in this view/vrf\n");
d62a17ae 9591 return NULL;
9592 }
2815e61f 9593
d62a17ae 9594 return peer;
9595}
9596
9597enum bgp_stats {
9598 BGP_STATS_MAXBITLEN = 0,
9599 BGP_STATS_RIB,
9600 BGP_STATS_PREFIXES,
9601 BGP_STATS_TOTPLEN,
9602 BGP_STATS_UNAGGREGATEABLE,
9603 BGP_STATS_MAX_AGGREGATEABLE,
9604 BGP_STATS_AGGREGATES,
9605 BGP_STATS_SPACE,
9606 BGP_STATS_ASPATH_COUNT,
9607 BGP_STATS_ASPATH_MAXHOPS,
9608 BGP_STATS_ASPATH_TOTHOPS,
9609 BGP_STATS_ASPATH_MAXSIZE,
9610 BGP_STATS_ASPATH_TOTSIZE,
9611 BGP_STATS_ASN_HIGHEST,
9612 BGP_STATS_MAX,
a636c635 9613};
2815e61f 9614
d62a17ae 9615static const char *table_stats_strs[] = {
9d303b37
DL
9616 [BGP_STATS_PREFIXES] = "Total Prefixes",
9617 [BGP_STATS_TOTPLEN] = "Average prefix length",
9618 [BGP_STATS_RIB] = "Total Advertisements",
9619 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9620 [BGP_STATS_MAX_AGGREGATEABLE] =
9621 "Maximum aggregateable prefixes",
9622 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9623 [BGP_STATS_SPACE] = "Address space advertised",
9624 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9625 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9626 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9627 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9628 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9629 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9630 [BGP_STATS_MAX] = NULL,
a636c635 9631};
2815e61f 9632
d62a17ae 9633struct bgp_table_stats {
9634 struct bgp_table *table;
9635 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 9636 double total_space;
ff7924f6
PJ
9637};
9638
a636c635
DW
9639#if 0
9640#define TALLY_SIGFIG 100000
9641static unsigned long
9642ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9643{
a636c635
DW
9644 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9645 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9646 unsigned long ret = newtot / count;
9647
9648 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9649 return ret + 1;
9650 else
9651 return ret;
9652}
9653#endif
ff7924f6 9654
d62a17ae 9655static int bgp_table_stats_walker(struct thread *t)
2815e61f 9656{
d62a17ae 9657 struct bgp_node *rn;
9658 struct bgp_node *top;
9659 struct bgp_table_stats *ts = THREAD_ARG(t);
9660 unsigned int space = 0;
a636c635 9661
d62a17ae 9662 if (!(top = bgp_table_top(ts->table)))
9663 return 0;
2815e61f 9664
d62a17ae 9665 switch (top->p.family) {
9666 case AF_INET:
9667 space = IPV4_MAX_BITLEN;
9668 break;
9669 case AF_INET6:
9670 space = IPV6_MAX_BITLEN;
9671 break;
9672 }
9673
9674 ts->counts[BGP_STATS_MAXBITLEN] = space;
9675
9676 for (rn = top; rn; rn = bgp_route_next(rn)) {
9677 struct bgp_info *ri;
9678 struct bgp_node *prn = bgp_node_parent_nolock(rn);
9679 unsigned int rinum = 0;
9680
9681 if (rn == top)
9682 continue;
9683
9684 if (!rn->info)
9685 continue;
9686
9687 ts->counts[BGP_STATS_PREFIXES]++;
9688 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9689
a636c635
DW
9690#if 0
9691 ts->counts[BGP_STATS_AVGPLEN]
9692 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9693 ts->counts[BGP_STATS_AVGPLEN],
9694 rn->p.prefixlen);
9695#endif
d62a17ae 9696
9697 /* check if the prefix is included by any other announcements */
9698 while (prn && !prn->info)
9699 prn = bgp_node_parent_nolock(prn);
9700
9701 if (prn == NULL || prn == top) {
9702 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9703 /* announced address space */
9704 if (space)
a4d82a8a
PZ
9705 ts->total_space +=
9706 pow(2.0, space - rn->p.prefixlen);
d62a17ae 9707 } else if (prn->info)
9708 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9709
9710 for (ri = rn->info; ri; ri = ri->next) {
9711 rinum++;
9712 ts->counts[BGP_STATS_RIB]++;
9713
9714 if (ri->attr
9715 && (CHECK_FLAG(ri->attr->flag,
9716 ATTR_FLAG_BIT(
9717 BGP_ATTR_ATOMIC_AGGREGATE))))
9718 ts->counts[BGP_STATS_AGGREGATES]++;
9719
9720 /* as-path stats */
9721 if (ri->attr && ri->attr->aspath) {
9722 unsigned int hops =
9723 aspath_count_hops(ri->attr->aspath);
9724 unsigned int size =
9725 aspath_size(ri->attr->aspath);
9726 as_t highest = aspath_highest(ri->attr->aspath);
9727
9728 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9729
9730 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
9731 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
9732 hops;
9733
9734 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
9735 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
9736 size;
9737
9738 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
9739 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635
DW
9740#if 0
9741 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
9742 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9743 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
9744 hops);
9745 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
9746 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9747 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
9748 size);
9749#endif
d62a17ae 9750 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
9751 ts->counts[BGP_STATS_ASN_HIGHEST] =
9752 highest;
9753 }
9754 }
9755 }
9756 return 0;
2815e61f 9757}
ff7924f6 9758
d62a17ae 9759static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9760 safi_t safi)
2815e61f 9761{
d62a17ae 9762 struct bgp_table_stats ts;
9763 unsigned int i;
019386c2 9764
d62a17ae 9765 if (!bgp->rib[afi][safi]) {
9766 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9767 afi, safi);
9768 return CMD_WARNING;
9769 }
019386c2 9770
d62a17ae 9771 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 9772
d62a17ae 9773 /* labeled-unicast routes live in the unicast table */
9774 if (safi == SAFI_LABELED_UNICAST)
9775 safi = SAFI_UNICAST;
019386c2 9776
d62a17ae 9777 memset(&ts, 0, sizeof(ts));
9778 ts.table = bgp->rib[afi][safi];
9779 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 9780
d62a17ae 9781 for (i = 0; i < BGP_STATS_MAX; i++) {
9782 if (!table_stats_strs[i])
9783 continue;
9784
9785 switch (i) {
a636c635
DW
9786#if 0
9787 case BGP_STATS_ASPATH_AVGHOPS:
9788 case BGP_STATS_ASPATH_AVGSIZE:
9789 case BGP_STATS_AVGPLEN:
9790 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9791 vty_out (vty, "%12.2f",
9792 (float)ts.counts[i] / (float)TALLY_SIGFIG);
9793 break;
9794#endif
d62a17ae 9795 case BGP_STATS_ASPATH_TOTHOPS:
9796 case BGP_STATS_ASPATH_TOTSIZE:
9797 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9798 vty_out(vty, "%12.2f",
9799 ts.counts[i]
9800 ? (float)ts.counts[i]
9801 / (float)ts.counts
9802 [BGP_STATS_ASPATH_COUNT]
9803 : 0);
9804 break;
9805 case BGP_STATS_TOTPLEN:
9806 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9807 vty_out(vty, "%12.2f",
9808 ts.counts[i]
9809 ? (float)ts.counts[i]
9810 / (float)ts.counts
9811 [BGP_STATS_PREFIXES]
9812 : 0);
9813 break;
9814 case BGP_STATS_SPACE:
9815 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
9816 vty_out(vty, "%12g\n", ts.total_space);
9817
9818 if (afi == AFI_IP6) {
9819 vty_out(vty, "%30s: ", "/32 equivalent ");
9820 vty_out(vty, "%12g\n",
a4d82a8a 9821 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
9822 vty_out(vty, "%30s: ", "/48 equivalent ");
9823 vty_out(vty, "%12g\n",
a4d82a8a 9824 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
9825 } else {
9826 vty_out(vty, "%30s: ", "% announced ");
9827 vty_out(vty, "%12.2f\n",
9828 ts.total_space * 100. * pow(2.0, -32));
9829 vty_out(vty, "%30s: ", "/8 equivalent ");
9830 vty_out(vty, "%12.2f\n",
a4d82a8a 9831 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
9832 vty_out(vty, "%30s: ", "/24 equivalent ");
9833 vty_out(vty, "%12.2f\n",
a4d82a8a 9834 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 9835 }
d62a17ae 9836 break;
9837 default:
9838 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9839 vty_out(vty, "%12llu", ts.counts[i]);
9840 }
ff7924f6 9841
d62a17ae 9842 vty_out(vty, "\n");
9843 }
9844 return CMD_SUCCESS;
9845}
9846
9847enum bgp_pcounts {
9848 PCOUNT_ADJ_IN = 0,
9849 PCOUNT_DAMPED,
9850 PCOUNT_REMOVED,
9851 PCOUNT_HISTORY,
9852 PCOUNT_STALE,
9853 PCOUNT_VALID,
9854 PCOUNT_ALL,
9855 PCOUNT_COUNTED,
9856 PCOUNT_PFCNT, /* the figure we display to users */
9857 PCOUNT_MAX,
a636c635 9858};
718e3744 9859
d62a17ae 9860static const char *pcount_strs[] = {
9d303b37
DL
9861 [PCOUNT_ADJ_IN] = "Adj-in",
9862 [PCOUNT_DAMPED] = "Damped",
9863 [PCOUNT_REMOVED] = "Removed",
9864 [PCOUNT_HISTORY] = "History",
9865 [PCOUNT_STALE] = "Stale",
9866 [PCOUNT_VALID] = "Valid",
9867 [PCOUNT_ALL] = "All RIB",
9868 [PCOUNT_COUNTED] = "PfxCt counted",
9869 [PCOUNT_PFCNT] = "Useable",
9870 [PCOUNT_MAX] = NULL,
a636c635 9871};
718e3744 9872
d62a17ae 9873struct peer_pcounts {
9874 unsigned int count[PCOUNT_MAX];
9875 const struct peer *peer;
9876 const struct bgp_table *table;
a636c635 9877};
47fc97cc 9878
d62a17ae 9879static int bgp_peer_count_walker(struct thread *t)
9880{
9881 struct bgp_node *rn;
9882 struct peer_pcounts *pc = THREAD_ARG(t);
9883 const struct peer *peer = pc->peer;
9884
9885 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
9886 struct bgp_adj_in *ain;
9887 struct bgp_info *ri;
9888
9889 for (ain = rn->adj_in; ain; ain = ain->next)
9890 if (ain->peer == peer)
9891 pc->count[PCOUNT_ADJ_IN]++;
9892
9893 for (ri = rn->info; ri; ri = ri->next) {
9894 char buf[SU_ADDRSTRLEN];
9895
9896 if (ri->peer != peer)
9897 continue;
9898
9899 pc->count[PCOUNT_ALL]++;
9900
9901 if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED))
9902 pc->count[PCOUNT_DAMPED]++;
9903 if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
9904 pc->count[PCOUNT_HISTORY]++;
9905 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
9906 pc->count[PCOUNT_REMOVED]++;
9907 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
9908 pc->count[PCOUNT_STALE]++;
9909 if (CHECK_FLAG(ri->flags, BGP_INFO_VALID))
9910 pc->count[PCOUNT_VALID]++;
9911 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9912 pc->count[PCOUNT_PFCNT]++;
9913
9914 if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
9915 pc->count[PCOUNT_COUNTED]++;
9916 if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9917 zlog_warn(
9918 "%s [pcount] %s/%d is counted but flags 0x%x",
9919 peer->host,
9920 inet_ntop(rn->p.family,
9921 &rn->p.u.prefix, buf,
9922 SU_ADDRSTRLEN),
9923 rn->p.prefixlen, ri->flags);
9924 } else {
9925 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9926 zlog_warn(
9927 "%s [pcount] %s/%d not counted but flags 0x%x",
9928 peer->host,
9929 inet_ntop(rn->p.family,
9930 &rn->p.u.prefix, buf,
9931 SU_ADDRSTRLEN),
9932 rn->p.prefixlen, ri->flags);
9933 }
9934 }
9935 }
9936 return 0;
718e3744 9937}
9938
d62a17ae 9939static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
d7c0a89a 9940 safi_t safi, uint8_t use_json)
856ca177 9941{
d62a17ae 9942 struct peer_pcounts pcounts = {.peer = peer};
9943 unsigned int i;
9944 json_object *json = NULL;
9945 json_object *json_loop = NULL;
856ca177 9946
d62a17ae 9947 if (use_json) {
9948 json = json_object_new_object();
9949 json_loop = json_object_new_object();
9950 }
718e3744 9951
d62a17ae 9952 if (!peer || !peer->bgp || !peer->afc[afi][safi]
9953 || !peer->bgp->rib[afi][safi]) {
9954 if (use_json) {
9955 json_object_string_add(
9956 json, "warning",
9957 "No such neighbor or address family");
9958 vty_out(vty, "%s\n", json_object_to_json_string(json));
9959 json_object_free(json);
9960 } else
9961 vty_out(vty, "%% No such neighbor or address family\n");
9962
9963 return CMD_WARNING;
9964 }
2a71e9ce 9965
d62a17ae 9966 memset(&pcounts, 0, sizeof(pcounts));
9967 pcounts.peer = peer;
9968 pcounts.table = peer->bgp->rib[afi][safi];
9969
9970 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
9971 * stats for the thread-walk (i.e. ensure this can't be blamed on
9972 * on just vty_read()).
9973 */
d62a17ae 9974 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
9975
9976 if (use_json) {
9977 json_object_string_add(json, "prefixCountsFor", peer->host);
9978 json_object_string_add(json, "multiProtocol",
9979 afi_safi_print(afi, safi));
9980 json_object_int_add(json, "pfxCounter",
9981 peer->pcount[afi][safi]);
9982
9983 for (i = 0; i < PCOUNT_MAX; i++)
9984 json_object_int_add(json_loop, pcount_strs[i],
9985 pcounts.count[i]);
9986
9987 json_object_object_add(json, "ribTableWalkCounters", json_loop);
9988
9989 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
9990 json_object_string_add(json, "pfxctDriftFor",
9991 peer->host);
9992 json_object_string_add(
9993 json, "recommended",
9994 "Please report this bug, with the above command output");
9995 }
996c9314
LB
9996 vty_out(vty, "%s\n", json_object_to_json_string_ext(
9997 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 9998 json_object_free(json);
9999 } else {
10000
10001 if (peer->hostname
10002 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
10003 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10004 peer->hostname, peer->host,
10005 afi_safi_print(afi, safi));
10006 } else {
10007 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
10008 afi_safi_print(afi, safi));
10009 }
10010
10011 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
10012 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10013
10014 for (i = 0; i < PCOUNT_MAX; i++)
10015 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10016 pcounts.count[i]);
10017
10018 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10019 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10020 vty_out(vty,
10021 "Please report this bug, with the above command output\n");
10022 }
10023 }
10024
10025 return CMD_SUCCESS;
718e3744 10026}
10027
a636c635
DW
10028DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10029 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10030 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10031 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10032 SHOW_STR
10033 IP_STR
10034 BGP_STR
8386ac43 10035 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10036 BGP_AFI_HELP_STR
10037 BGP_SAFI_HELP_STR
0b16f239
DS
10038 "Detailed information on TCP and BGP neighbor connections\n"
10039 "Neighbor to display information about\n"
10040 "Neighbor to display information about\n"
91d37724 10041 "Neighbor on BGP configured interface\n"
a636c635 10042 "Display detailed prefix count information\n"
9973d184 10043 JSON_STR)
0b16f239 10044{
d62a17ae 10045 afi_t afi = AFI_IP6;
10046 safi_t safi = SAFI_UNICAST;
10047 struct peer *peer;
10048 int idx = 0;
10049 struct bgp *bgp = NULL;
856ca177 10050
d62a17ae 10051 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10052 &bgp);
10053 if (!idx)
10054 return CMD_WARNING;
0b16f239 10055
d62a17ae 10056 int uj = use_json(argc, argv);
10057 if (uj)
10058 argc--;
0b16f239 10059
d62a17ae 10060 argv_find(argv, argc, "neighbors", &idx);
10061 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
10062 if (!peer)
10063 return CMD_WARNING;
bb46e94f 10064
d62a17ae 10065 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 10066}
0b16f239 10067
d6902373
PG
10068#ifdef KEEP_OLD_VPN_COMMANDS
10069DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
10070 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
10071 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
10072 SHOW_STR
10073 IP_STR
10074 BGP_STR
d6902373 10075 BGP_VPNVX_HELP_STR
91d37724 10076 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
10077 "Detailed information on TCP and BGP neighbor connections\n"
10078 "Neighbor to display information about\n"
10079 "Neighbor to display information about\n"
91d37724 10080 "Neighbor on BGP configured interface\n"
a636c635 10081 "Display detailed prefix count information\n"
9973d184 10082 JSON_STR)
a636c635 10083{
d62a17ae 10084 int idx_peer = 6;
10085 struct peer *peer;
d7c0a89a 10086 uint8_t uj = use_json(argc, argv);
a636c635 10087
d62a17ae 10088 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
10089 if (!peer)
10090 return CMD_WARNING;
10091
10092 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
10093}
10094
d6902373
PG
10095DEFUN (show_ip_bgp_vpn_all_route_prefix,
10096 show_ip_bgp_vpn_all_route_prefix_cmd,
10097 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
10098 SHOW_STR
10099 IP_STR
10100 BGP_STR
d6902373 10101 BGP_VPNVX_HELP_STR
91d37724
QY
10102 "Display information about all VPNv4 NLRIs\n"
10103 "Network in the BGP routing table to display\n"
3a2d747c 10104 "Network in the BGP routing table to display\n"
9973d184 10105 JSON_STR)
91d37724 10106{
d62a17ae 10107 int idx = 0;
10108 char *network = NULL;
10109 struct bgp *bgp = bgp_get_default();
10110 if (!bgp) {
10111 vty_out(vty, "Can't find default instance\n");
10112 return CMD_WARNING;
10113 }
87e34b58 10114
d62a17ae 10115 if (argv_find(argv, argc, "A.B.C.D", &idx))
10116 network = argv[idx]->arg;
10117 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10118 network = argv[idx]->arg;
10119 else {
10120 vty_out(vty, "Unable to figure out Network\n");
10121 return CMD_WARNING;
10122 }
87e34b58 10123
d62a17ae 10124 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
10125 BGP_PATH_ALL, use_json(argc, argv));
91d37724 10126}
d6902373 10127#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 10128
4c63a661
PG
10129DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
10130 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
10131 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10132 SHOW_STR
10133 IP_STR
10134 BGP_STR
10135 L2VPN_HELP_STR
10136 EVPN_HELP_STR
10137 "Display information about all EVPN NLRIs\n"
10138 "Network in the BGP routing table to display\n"
10139 "Network in the BGP routing table to display\n"
10140 JSON_STR)
10141{
d62a17ae 10142 int idx = 0;
10143 char *network = NULL;
a636c635 10144
d62a17ae 10145 if (argv_find(argv, argc, "A.B.C.D", &idx))
10146 network = argv[idx]->arg;
10147 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10148 network = argv[idx]->arg;
10149 else {
10150 vty_out(vty, "Unable to figure out Network\n");
10151 return CMD_WARNING;
10152 }
10153 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
10154 BGP_PATH_ALL, use_json(argc, argv));
10155}
10156
10157static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6
PM
10158 safi_t safi, enum bgp_show_adj_route_type type,
10159 const char *rmap_name, uint8_t use_json,
10160 json_object *json)
d62a17ae 10161{
10162 struct bgp_table *table;
10163 struct bgp_adj_in *ain;
10164 struct bgp_adj_out *adj;
10165 unsigned long output_count;
10166 unsigned long filtered_count;
10167 struct bgp_node *rn;
10168 int header1 = 1;
10169 struct bgp *bgp;
10170 int header2 = 1;
10171 struct attr attr;
10172 int ret;
10173 struct update_subgroup *subgrp;
10174 json_object *json_scode = NULL;
10175 json_object *json_ocode = NULL;
10176 json_object *json_ar = NULL;
10177 struct peer_af *paf;
10178
10179 if (use_json) {
10180 json_scode = json_object_new_object();
10181 json_ocode = json_object_new_object();
10182 json_ar = json_object_new_object();
10183
10184 json_object_string_add(json_scode, "suppressed", "s");
10185 json_object_string_add(json_scode, "damped", "d");
10186 json_object_string_add(json_scode, "history", "h");
10187 json_object_string_add(json_scode, "valid", "*");
10188 json_object_string_add(json_scode, "best", ">");
10189 json_object_string_add(json_scode, "multipath", "=");
10190 json_object_string_add(json_scode, "internal", "i");
10191 json_object_string_add(json_scode, "ribFailure", "r");
10192 json_object_string_add(json_scode, "stale", "S");
10193 json_object_string_add(json_scode, "removed", "R");
10194
10195 json_object_string_add(json_ocode, "igp", "i");
10196 json_object_string_add(json_ocode, "egp", "e");
10197 json_object_string_add(json_ocode, "incomplete", "?");
10198 }
a636c635 10199
d62a17ae 10200 bgp = peer->bgp;
a636c635 10201
d62a17ae 10202 if (!bgp) {
10203 if (use_json) {
10204 json_object_string_add(json, "alert", "no BGP");
10205 vty_out(vty, "%s\n", json_object_to_json_string(json));
10206 json_object_free(json);
10207 } else
10208 vty_out(vty, "%% No bgp\n");
10209 return;
10210 }
a636c635 10211
d62a17ae 10212 table = bgp->rib[afi][safi];
10213
10214 output_count = filtered_count = 0;
10215 subgrp = peer_subgroup(peer, afi, safi);
10216
6392aaa6 10217 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 10218 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
10219 if (use_json) {
10220 json_object_int_add(json, "bgpTableVersion",
10221 table->version);
10222 json_object_string_add(json, "bgpLocalRouterId",
10223 inet_ntoa(bgp->router_id));
10224 json_object_object_add(json, "bgpStatusCodes",
10225 json_scode);
10226 json_object_object_add(json, "bgpOriginCodes",
10227 json_ocode);
10228 json_object_string_add(json,
10229 "bgpOriginatingDefaultNetwork",
10230 "0.0.0.0");
10231 } else {
996c9314 10232 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 10233 ", local router ID is %s, vrf id ",
d62a17ae 10234 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
10235 if (bgp->vrf_id == VRF_UNKNOWN)
10236 vty_out(vty, "%s", VRFID_NONE_STR);
10237 else
10238 vty_out(vty, "%u", bgp->vrf_id);
10239 vty_out(vty, "\n");
d62a17ae 10240 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10241 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 10242 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10243
10244 vty_out(vty, "Originating default network 0.0.0.0\n\n");
10245 }
10246 header1 = 0;
10247 }
a636c635 10248
d62a17ae 10249 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
10250 if (type == bgp_show_adj_route_received
10251 || type == bgp_show_adj_route_filtered) {
d62a17ae 10252 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 10253 if (ain->peer != peer || !ain->attr)
ea47320b 10254 continue;
6392aaa6 10255
ea47320b
DL
10256 if (header1) {
10257 if (use_json) {
10258 json_object_int_add(
60466a63 10259 json, "bgpTableVersion",
ea47320b
DL
10260 0);
10261 json_object_string_add(
10262 json,
10263 "bgpLocalRouterId",
10264 inet_ntoa(
10265 bgp->router_id));
10266 json_object_object_add(
60466a63 10267 json, "bgpStatusCodes",
ea47320b
DL
10268 json_scode);
10269 json_object_object_add(
60466a63 10270 json, "bgpOriginCodes",
ea47320b
DL
10271 json_ocode);
10272 } else {
10273 vty_out(vty,
9df8b37c 10274 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 10275 inet_ntoa(
9df8b37c
PZ
10276 bgp->router_id));
10277 if (bgp->vrf_id == VRF_UNKNOWN)
10278 vty_out(vty, "%s",
10279 VRFID_NONE_STR);
10280 else
10281 vty_out(vty, "%u",
10282 bgp->vrf_id);
10283 vty_out(vty, "\n");
ea47320b
DL
10284 vty_out(vty,
10285 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10286 vty_out(vty,
10287 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
10288 vty_out(vty,
10289 BGP_SHOW_OCODE_HEADER);
d62a17ae 10290 }
ea47320b
DL
10291 header1 = 0;
10292 }
10293 if (header2) {
10294 if (!use_json)
10295 vty_out(vty, BGP_SHOW_HEADER);
10296 header2 = 0;
10297 }
6392aaa6
PM
10298
10299 bgp_attr_dup(&attr, ain->attr);
10300 ret = bgp_input_modifier(peer, &rn->p, &attr,
10301 afi, safi, rmap_name);
10302
10303 if (type == bgp_show_adj_route_filtered
b755861b
PM
10304 && ret != RMAP_DENY) {
10305 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10306 continue;
d62a17ae 10307 }
6392aaa6
PM
10308
10309 if (type == bgp_show_adj_route_received
10310 && ret == RMAP_DENY)
10311 filtered_count++;
10312
10313 route_vty_out_tmp(vty, &rn->p, &attr, safi,
10314 use_json, json_ar);
b755861b 10315 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10316 output_count++;
d62a17ae 10317 }
6392aaa6 10318 } else if (type == bgp_show_adj_route_advertised) {
d62a17ae 10319 for (adj = rn->adj_out; adj; adj = adj->next)
924c3f6a 10320 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 10321 if (paf->peer != peer || !adj->attr)
924c3f6a 10322 continue;
d62a17ae 10323
924c3f6a
DS
10324 if (header1) {
10325 if (use_json) {
10326 json_object_int_add(
10327 json,
10328 "bgpTableVersion",
10329 table->version);
10330 json_object_string_add(
10331 json,
10332 "bgpLocalRouterId",
10333 inet_ntoa(
10334 bgp->router_id));
10335 json_object_object_add(
10336 json,
10337 "bgpStatusCodes",
10338 json_scode);
10339 json_object_object_add(
10340 json,
10341 "bgpOriginCodes",
10342 json_ocode);
10343 } else {
10344 vty_out(vty,
10345 "BGP table version is %" PRIu64
9df8b37c 10346 ", local router ID is %s, vrf id ",
924c3f6a
DS
10347 table->version,
10348 inet_ntoa(
10349 bgp->router_id));
9df8b37c
PZ
10350 if (bgp->vrf_id ==
10351 VRF_UNKNOWN)
10352 vty_out(vty,
10353 "%s",
10354 VRFID_NONE_STR);
10355 else
10356 vty_out(vty,
10357 "%u",
10358 bgp->vrf_id);
10359 vty_out(vty, "\n");
924c3f6a
DS
10360 vty_out(vty,
10361 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10362 vty_out(vty,
10363 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
10364 vty_out(vty,
10365 BGP_SHOW_OCODE_HEADER);
a2addae8 10366 }
924c3f6a
DS
10367 header1 = 0;
10368 }
924c3f6a
DS
10369 if (header2) {
10370 if (!use_json)
10371 vty_out(vty,
10372 BGP_SHOW_HEADER);
10373 header2 = 0;
10374 }
d62a17ae 10375
b755861b
PM
10376 bgp_attr_dup(&attr, adj->attr);
10377 ret = bgp_output_modifier(
10378 peer, &rn->p, &attr, afi, safi,
10379 rmap_name);
f46d8e1e 10380
b755861b
PM
10381 if (ret != RMAP_DENY) {
10382 route_vty_out_tmp(vty, &rn->p,
10383 &attr, safi,
10384 use_json,
10385 json_ar);
10386 output_count++;
10387 } else {
10388 filtered_count++;
a2addae8 10389 }
b755861b
PM
10390
10391 bgp_attr_undup(&attr, adj->attr);
924c3f6a 10392 }
d62a17ae 10393 }
10394 }
d62a17ae 10395
d62a17ae 10396 if (use_json) {
6392aaa6
PM
10397 json_object_object_add(json, "advertisedRoutes", json_ar);
10398 json_object_int_add(json, "totalPrefixCounter", output_count);
10399 json_object_int_add(json, "filteredPrefixCounter",
10400 filtered_count);
10401
996c9314
LB
10402 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10403 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10404 json_object_free(json);
6392aaa6
PM
10405 } else if (output_count > 0) {
10406 if (filtered_count > 0)
10407 vty_out(vty,
10408 "\nTotal number of prefixes %ld (%ld filtered)\n",
10409 output_count, filtered_count);
10410 else
10411 vty_out(vty, "\nTotal number of prefixes %ld\n",
10412 output_count);
d62a17ae 10413 }
a636c635 10414}
2a71e9ce 10415
d62a17ae 10416static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6
PM
10417 safi_t safi, enum bgp_show_adj_route_type type,
10418 const char *rmap_name, uint8_t use_json)
0b16f239 10419{
d62a17ae 10420 json_object *json = NULL;
0b16f239 10421
d62a17ae 10422 if (use_json)
10423 json = json_object_new_object();
0b16f239 10424
d62a17ae 10425 /* labeled-unicast routes live in the unicast table */
10426 if (safi == SAFI_LABELED_UNICAST)
10427 safi = SAFI_UNICAST;
4dd6177e 10428
d62a17ae 10429 if (!peer || !peer->afc[afi][safi]) {
10430 if (use_json) {
10431 json_object_string_add(
10432 json, "warning",
10433 "No such neighbor or address family");
10434 vty_out(vty, "%s\n", json_object_to_json_string(json));
10435 json_object_free(json);
10436 } else
10437 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10438
d62a17ae 10439 return CMD_WARNING;
10440 }
10441
6392aaa6
PM
10442 if ((type == bgp_show_adj_route_received
10443 || type == bgp_show_adj_route_filtered)
d62a17ae 10444 && !CHECK_FLAG(peer->af_flags[afi][safi],
10445 PEER_FLAG_SOFT_RECONFIG)) {
10446 if (use_json) {
10447 json_object_string_add(
10448 json, "warning",
10449 "Inbound soft reconfiguration not enabled");
10450 vty_out(vty, "%s\n", json_object_to_json_string(json));
10451 json_object_free(json);
10452 } else
10453 vty_out(vty,
10454 "%% Inbound soft reconfiguration not enabled\n");
10455
10456 return CMD_WARNING;
10457 }
0b16f239 10458
6392aaa6 10459 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 10460
d62a17ae 10461 return CMD_SUCCESS;
a636c635 10462}
50ef26d4 10463
a636c635
DW
10464DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10465 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10466 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 10467 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 10468 SHOW_STR
10469 IP_STR
10470 BGP_STR
a636c635 10471 BGP_INSTANCE_HELP_STR
7395a2c9 10472 BGP_AFI_HELP_STR
4dd6177e 10473 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10474 "Detailed information on TCP and BGP neighbor connections\n"
10475 "Neighbor to display information about\n"
10476 "Neighbor to display information about\n"
91d37724 10477 "Neighbor on BGP configured interface\n"
a636c635 10478 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
10479 "Display the received routes from neighbor\n"
10480 "Display the filtered routes received from neighbor\n"
a636c635
DW
10481 "Route-map to modify the attributes\n"
10482 "Name of the route map\n"
9973d184 10483 JSON_STR)
718e3744 10484{
d62a17ae 10485 afi_t afi = AFI_IP6;
10486 safi_t safi = SAFI_UNICAST;
10487 char *rmap_name = NULL;
10488 char *peerstr = NULL;
d62a17ae 10489 struct bgp *bgp = NULL;
10490 struct peer *peer;
6392aaa6 10491 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
bb46e94f 10492
d62a17ae 10493 int idx = 0;
d62a17ae 10494 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10495 &bgp);
10496 if (!idx)
10497 return CMD_WARNING;
c493f2d8 10498
d62a17ae 10499 int uj = use_json(argc, argv);
6392aaa6 10500
d62a17ae 10501 if (uj)
10502 argc--;
30a6a167 10503
d62a17ae 10504 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10505 argv_find(argv, argc, "neighbors", &idx);
10506 peerstr = argv[++idx]->arg;
8c3deaae 10507
d62a17ae 10508 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10509 if (!peer)
10510 return CMD_WARNING;
856ca177 10511
d62a17ae 10512 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
10513 type = bgp_show_adj_route_advertised;
10514 else if (argv_find(argv, argc, "received-routes", &idx))
10515 type = bgp_show_adj_route_received;
10516 else if (argv_find(argv, argc, "filtered-routes", &idx))
10517 type = bgp_show_adj_route_filtered;
10518
d62a17ae 10519 if (argv_find(argv, argc, "route-map", &idx))
10520 rmap_name = argv[++idx]->arg;
95cbbd2a 10521
6392aaa6 10522 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
10523}
10524
718e3744 10525DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10526 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10527 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10528 SHOW_STR
10529 IP_STR
10530 BGP_STR
8c3deaae
QY
10531 "Address Family\n"
10532 "Address Family\n"
718e3744 10533 "Address Family modifier\n"
10534 "Detailed information on TCP and BGP neighbor connections\n"
10535 "Neighbor to display information about\n"
10536 "Neighbor to display information about\n"
91d37724 10537 "Neighbor on BGP configured interface\n"
718e3744 10538 "Display information received from a BGP neighbor\n"
856ca177 10539 "Display the prefixlist filter\n"
9973d184 10540 JSON_STR)
718e3744 10541{
d62a17ae 10542 afi_t afi = AFI_IP6;
10543 safi_t safi = SAFI_UNICAST;
10544 char *peerstr = NULL;
10545
10546 char name[BUFSIZ];
10547 union sockunion su;
10548 struct peer *peer;
10549 int count, ret;
10550
10551 int idx = 0;
10552
10553 /* show [ip] bgp */
10554 if (argv_find(argv, argc, "ip", &idx))
10555 afi = AFI_IP;
10556 /* [<ipv4|ipv6> [unicast]] */
10557 if (argv_find(argv, argc, "ipv4", &idx))
10558 afi = AFI_IP;
10559 if (argv_find(argv, argc, "ipv6", &idx))
10560 afi = AFI_IP6;
10561 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10562 argv_find(argv, argc, "neighbors", &idx);
10563 peerstr = argv[++idx]->arg;
10564
d7c0a89a 10565 uint8_t uj = use_json(argc, argv);
d62a17ae 10566
10567 ret = str2sockunion(peerstr, &su);
10568 if (ret < 0) {
10569 peer = peer_lookup_by_conf_if(NULL, peerstr);
10570 if (!peer) {
10571 if (uj)
10572 vty_out(vty, "{}\n");
10573 else
10574 vty_out(vty,
10575 "%% Malformed address or name: %s\n",
10576 peerstr);
10577 return CMD_WARNING;
10578 }
10579 } else {
10580 peer = peer_lookup(NULL, &su);
10581 if (!peer) {
10582 if (uj)
10583 vty_out(vty, "{}\n");
10584 else
10585 vty_out(vty, "No peer\n");
10586 return CMD_WARNING;
10587 }
10588 }
718e3744 10589
d62a17ae 10590 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10591 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10592 if (count) {
10593 if (!uj)
10594 vty_out(vty, "Address Family: %s\n",
10595 afi_safi_print(afi, safi));
10596 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10597 } else {
10598 if (uj)
10599 vty_out(vty, "{}\n");
10600 else
10601 vty_out(vty, "No functional output\n");
10602 }
718e3744 10603
d62a17ae 10604 return CMD_SUCCESS;
10605}
10606
10607static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10608 afi_t afi, safi_t safi,
d7c0a89a 10609 enum bgp_show_type type, uint8_t use_json)
d62a17ae 10610{
8a893163
DW
10611 /* labeled-unicast routes live in the unicast table */
10612 if (safi == SAFI_LABELED_UNICAST)
10613 safi = SAFI_UNICAST;
10614
d62a17ae 10615 if (!peer || !peer->afc[afi][safi]) {
10616 if (use_json) {
10617 json_object *json_no = NULL;
10618 json_no = json_object_new_object();
10619 json_object_string_add(
10620 json_no, "warning",
10621 "No such neighbor or address family");
10622 vty_out(vty, "%s\n",
10623 json_object_to_json_string(json_no));
10624 json_object_free(json_no);
10625 } else
10626 vty_out(vty, "%% No such neighbor or address family\n");
10627 return CMD_WARNING;
10628 }
47fc97cc 10629
d62a17ae 10630 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10631}
10632
dba3c1d3
PG
10633DEFUN (show_ip_bgp_flowspec_routes_detailed,
10634 show_ip_bgp_flowspec_routes_detailed_cmd,
10635 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
10636 SHOW_STR
10637 IP_STR
10638 BGP_STR
10639 BGP_INSTANCE_HELP_STR
10640 BGP_AFI_HELP_STR
10641 "SAFI Flowspec\n"
10642 "Detailed information on flowspec entries\n"
10643 JSON_STR)
10644{
10645 afi_t afi = AFI_IP;
10646 safi_t safi = SAFI_UNICAST;
10647 struct bgp *bgp = NULL;
10648 int idx = 0;
10649
10650 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10651 &bgp);
10652 if (!idx)
10653 return CMD_WARNING;
10654
10655 return bgp_show(vty, bgp, afi, safi,
10656 bgp_show_type_detail, NULL, use_json(argc, argv));
10657}
10658
718e3744 10659DEFUN (show_ip_bgp_neighbor_routes,
10660 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10661 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10662 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10663 SHOW_STR
10664 IP_STR
10665 BGP_STR
8386ac43 10666 BGP_INSTANCE_HELP_STR
4f280b15 10667 BGP_AFI_HELP_STR
4dd6177e 10668 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10669 "Detailed information on TCP and BGP neighbor connections\n"
10670 "Neighbor to display information about\n"
10671 "Neighbor to display information about\n"
91d37724 10672 "Neighbor on BGP configured interface\n"
2525cf39 10673 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10674 "Display the dampened routes received from neighbor\n"
10675 "Display routes learned from neighbor\n"
9973d184 10676 JSON_STR)
718e3744 10677{
d62a17ae 10678 char *peerstr = NULL;
10679 struct bgp *bgp = NULL;
10680 afi_t afi = AFI_IP6;
10681 safi_t safi = SAFI_UNICAST;
10682 struct peer *peer;
10683 enum bgp_show_type sh_type = bgp_show_type_neighbor;
856ca177 10684
d62a17ae 10685 int idx = 0;
bb46e94f 10686
d62a17ae 10687 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10688 &bgp);
10689 if (!idx)
10690 return CMD_WARNING;
c493f2d8 10691
d62a17ae 10692 int uj = use_json(argc, argv);
10693 if (uj)
10694 argc--;
30a6a167 10695
d62a17ae 10696 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10697 argv_find(argv, argc, "neighbors", &idx);
10698 peerstr = argv[++idx]->arg;
8c3deaae 10699
d62a17ae 10700 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 10701 if (!peer)
d62a17ae 10702 return CMD_WARNING;
bb46e94f 10703
d62a17ae 10704 if (argv_find(argv, argc, "flap-statistics", &idx))
10705 sh_type = bgp_show_type_flap_neighbor;
10706 else if (argv_find(argv, argc, "dampened-routes", &idx))
10707 sh_type = bgp_show_type_damp_neighbor;
10708 else if (argv_find(argv, argc, "routes", &idx))
10709 sh_type = bgp_show_type_neighbor;
2525cf39 10710
d62a17ae 10711 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 10712}
6b0655a2 10713
734b349e 10714struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10715
d62a17ae 10716struct bgp_distance {
10717 /* Distance value for the IP source prefix. */
d7c0a89a 10718 uint8_t distance;
718e3744 10719
d62a17ae 10720 /* Name of the access-list to be matched. */
10721 char *access_list;
718e3744 10722};
10723
4f280b15
LB
10724DEFUN (show_bgp_afi_vpn_rd_route,
10725 show_bgp_afi_vpn_rd_route_cmd,
d114b977 10726 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
10727 SHOW_STR
10728 BGP_STR
10729 BGP_AFI_HELP_STR
10730 "Address Family modifier\n"
10731 "Display information for a route distinguisher\n"
10732 "Route Distinguisher\n"
7395a2c9
DS
10733 "Network in the BGP routing table to display\n"
10734 "Network in the BGP routing table to display\n"
10735 JSON_STR)
4f280b15 10736{
d62a17ae 10737 int ret;
10738 struct prefix_rd prd;
10739 afi_t afi = AFI_MAX;
10740 int idx = 0;
4f280b15 10741
ff6566f3
DS
10742 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
10743 vty_out(vty, "%% Malformed Address Family\n");
10744 return CMD_WARNING;
10745 }
10746
d62a17ae 10747 ret = str2prefix_rd(argv[5]->arg, &prd);
10748 if (!ret) {
10749 vty_out(vty, "%% Malformed Route Distinguisher\n");
10750 return CMD_WARNING;
10751 }
ff6566f3 10752
d62a17ae 10753 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
10754 0, BGP_PATH_ALL, use_json(argc, argv));
4f280b15
LB
10755}
10756
d62a17ae 10757static struct bgp_distance *bgp_distance_new(void)
718e3744 10758{
d62a17ae 10759 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 10760}
10761
d62a17ae 10762static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 10763{
d62a17ae 10764 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 10765}
10766
d62a17ae 10767static int bgp_distance_set(struct vty *vty, const char *distance_str,
10768 const char *ip_str, const char *access_list_str)
718e3744 10769{
d62a17ae 10770 int ret;
10771 afi_t afi;
10772 safi_t safi;
10773 struct prefix p;
d7c0a89a 10774 uint8_t distance;
d62a17ae 10775 struct bgp_node *rn;
10776 struct bgp_distance *bdistance;
718e3744 10777
d62a17ae 10778 afi = bgp_node_afi(vty);
10779 safi = bgp_node_safi(vty);
734b349e 10780
d62a17ae 10781 ret = str2prefix(ip_str, &p);
10782 if (ret == 0) {
10783 vty_out(vty, "Malformed prefix\n");
10784 return CMD_WARNING_CONFIG_FAILED;
10785 }
718e3744 10786
d62a17ae 10787 distance = atoi(distance_str);
718e3744 10788
d62a17ae 10789 /* Get BGP distance node. */
10790 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
10791 if (rn->info) {
10792 bdistance = rn->info;
10793 bgp_unlock_node(rn);
10794 } else {
10795 bdistance = bgp_distance_new();
10796 rn->info = bdistance;
10797 }
718e3744 10798
d62a17ae 10799 /* Set distance value. */
10800 bdistance->distance = distance;
718e3744 10801
d62a17ae 10802 /* Reset access-list configuration. */
10803 if (bdistance->access_list) {
10804 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10805 bdistance->access_list = NULL;
10806 }
10807 if (access_list_str)
10808 bdistance->access_list =
10809 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 10810
d62a17ae 10811 return CMD_SUCCESS;
718e3744 10812}
10813
d62a17ae 10814static int bgp_distance_unset(struct vty *vty, const char *distance_str,
10815 const char *ip_str, const char *access_list_str)
718e3744 10816{
d62a17ae 10817 int ret;
10818 afi_t afi;
10819 safi_t safi;
10820 struct prefix p;
10821 int distance;
10822 struct bgp_node *rn;
10823 struct bgp_distance *bdistance;
718e3744 10824
d62a17ae 10825 afi = bgp_node_afi(vty);
10826 safi = bgp_node_safi(vty);
734b349e 10827
d62a17ae 10828 ret = str2prefix(ip_str, &p);
10829 if (ret == 0) {
10830 vty_out(vty, "Malformed prefix\n");
10831 return CMD_WARNING_CONFIG_FAILED;
10832 }
718e3744 10833
d62a17ae 10834 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
10835 (struct prefix *)&p);
10836 if (!rn) {
10837 vty_out(vty, "Can't find specified prefix\n");
10838 return CMD_WARNING_CONFIG_FAILED;
10839 }
718e3744 10840
d62a17ae 10841 bdistance = rn->info;
10842 distance = atoi(distance_str);
1f9a9fff 10843
d62a17ae 10844 if (bdistance->distance != distance) {
10845 vty_out(vty, "Distance does not match configured\n");
10846 return CMD_WARNING_CONFIG_FAILED;
10847 }
718e3744 10848
d62a17ae 10849 if (bdistance->access_list)
10850 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10851 bgp_distance_free(bdistance);
718e3744 10852
d62a17ae 10853 rn->info = NULL;
10854 bgp_unlock_node(rn);
10855 bgp_unlock_node(rn);
718e3744 10856
d62a17ae 10857 return CMD_SUCCESS;
718e3744 10858}
10859
718e3744 10860/* Apply BGP information to distance method. */
d7c0a89a
QY
10861uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
10862 safi_t safi, struct bgp *bgp)
d62a17ae 10863{
10864 struct bgp_node *rn;
10865 struct prefix q;
10866 struct peer *peer;
10867 struct bgp_distance *bdistance;
10868 struct access_list *alist;
10869 struct bgp_static *bgp_static;
10870
10871 if (!bgp)
10872 return 0;
10873
10874 peer = rinfo->peer;
10875
10876 /* Check source address. */
10877 sockunion2hostprefix(&peer->su, &q);
10878 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
10879 if (rn) {
10880 bdistance = rn->info;
10881 bgp_unlock_node(rn);
10882
10883 if (bdistance->access_list) {
10884 alist = access_list_lookup(afi, bdistance->access_list);
10885 if (alist
10886 && access_list_apply(alist, p) == FILTER_PERMIT)
10887 return bdistance->distance;
10888 } else
10889 return bdistance->distance;
718e3744 10890 }
718e3744 10891
d62a17ae 10892 /* Backdoor check. */
10893 rn = bgp_node_lookup(bgp->route[afi][safi], p);
10894 if (rn) {
10895 bgp_static = rn->info;
10896 bgp_unlock_node(rn);
718e3744 10897
d62a17ae 10898 if (bgp_static->backdoor) {
10899 if (bgp->distance_local[afi][safi])
10900 return bgp->distance_local[afi][safi];
10901 else
10902 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10903 }
718e3744 10904 }
718e3744 10905
d62a17ae 10906 if (peer->sort == BGP_PEER_EBGP) {
10907 if (bgp->distance_ebgp[afi][safi])
10908 return bgp->distance_ebgp[afi][safi];
10909 return ZEBRA_EBGP_DISTANCE_DEFAULT;
10910 } else {
10911 if (bgp->distance_ibgp[afi][safi])
10912 return bgp->distance_ibgp[afi][safi];
10913 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10914 }
718e3744 10915}
10916
10917DEFUN (bgp_distance,
10918 bgp_distance_cmd,
6147e2c6 10919 "distance bgp (1-255) (1-255) (1-255)",
718e3744 10920 "Define an administrative distance\n"
10921 "BGP distance\n"
10922 "Distance for routes external to the AS\n"
10923 "Distance for routes internal to the AS\n"
10924 "Distance for local routes\n")
10925{
d62a17ae 10926 VTY_DECLVAR_CONTEXT(bgp, bgp);
10927 int idx_number = 2;
10928 int idx_number_2 = 3;
10929 int idx_number_3 = 4;
10930 afi_t afi;
10931 safi_t safi;
718e3744 10932
d62a17ae 10933 afi = bgp_node_afi(vty);
10934 safi = bgp_node_safi(vty);
718e3744 10935
d62a17ae 10936 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
10937 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
10938 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
10939 return CMD_SUCCESS;
718e3744 10940}
10941
10942DEFUN (no_bgp_distance,
10943 no_bgp_distance_cmd,
a636c635 10944 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 10945 NO_STR
10946 "Define an administrative distance\n"
10947 "BGP distance\n"
10948 "Distance for routes external to the AS\n"
10949 "Distance for routes internal to the AS\n"
10950 "Distance for local routes\n")
10951{
d62a17ae 10952 VTY_DECLVAR_CONTEXT(bgp, bgp);
10953 afi_t afi;
10954 safi_t safi;
718e3744 10955
d62a17ae 10956 afi = bgp_node_afi(vty);
10957 safi = bgp_node_safi(vty);
718e3744 10958
d62a17ae 10959 bgp->distance_ebgp[afi][safi] = 0;
10960 bgp->distance_ibgp[afi][safi] = 0;
10961 bgp->distance_local[afi][safi] = 0;
10962 return CMD_SUCCESS;
718e3744 10963}
10964
718e3744 10965
10966DEFUN (bgp_distance_source,
10967 bgp_distance_source_cmd,
6147e2c6 10968 "distance (1-255) A.B.C.D/M",
718e3744 10969 "Define an administrative distance\n"
10970 "Administrative distance\n"
10971 "IP source prefix\n")
10972{
d62a17ae 10973 int idx_number = 1;
10974 int idx_ipv4_prefixlen = 2;
10975 bgp_distance_set(vty, argv[idx_number]->arg,
10976 argv[idx_ipv4_prefixlen]->arg, NULL);
10977 return CMD_SUCCESS;
718e3744 10978}
10979
10980DEFUN (no_bgp_distance_source,
10981 no_bgp_distance_source_cmd,
6147e2c6 10982 "no distance (1-255) A.B.C.D/M",
718e3744 10983 NO_STR
10984 "Define an administrative distance\n"
10985 "Administrative distance\n"
10986 "IP source prefix\n")
10987{
d62a17ae 10988 int idx_number = 2;
10989 int idx_ipv4_prefixlen = 3;
10990 bgp_distance_unset(vty, argv[idx_number]->arg,
10991 argv[idx_ipv4_prefixlen]->arg, NULL);
10992 return CMD_SUCCESS;
718e3744 10993}
10994
10995DEFUN (bgp_distance_source_access_list,
10996 bgp_distance_source_access_list_cmd,
6147e2c6 10997 "distance (1-255) A.B.C.D/M WORD",
718e3744 10998 "Define an administrative distance\n"
10999 "Administrative distance\n"
11000 "IP source prefix\n"
11001 "Access list name\n")
11002{
d62a17ae 11003 int idx_number = 1;
11004 int idx_ipv4_prefixlen = 2;
11005 int idx_word = 3;
11006 bgp_distance_set(vty, argv[idx_number]->arg,
11007 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11008 return CMD_SUCCESS;
718e3744 11009}
11010
11011DEFUN (no_bgp_distance_source_access_list,
11012 no_bgp_distance_source_access_list_cmd,
6147e2c6 11013 "no distance (1-255) A.B.C.D/M WORD",
718e3744 11014 NO_STR
11015 "Define an administrative distance\n"
11016 "Administrative distance\n"
11017 "IP source prefix\n"
11018 "Access list name\n")
11019{
d62a17ae 11020 int idx_number = 2;
11021 int idx_ipv4_prefixlen = 3;
11022 int idx_word = 4;
11023 bgp_distance_unset(vty, argv[idx_number]->arg,
11024 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11025 return CMD_SUCCESS;
718e3744 11026}
6b0655a2 11027
734b349e
MZ
11028DEFUN (ipv6_bgp_distance_source,
11029 ipv6_bgp_distance_source_cmd,
39e92c06 11030 "distance (1-255) X:X::X:X/M",
734b349e
MZ
11031 "Define an administrative distance\n"
11032 "Administrative distance\n"
11033 "IP source prefix\n")
11034{
d62a17ae 11035 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
11036 return CMD_SUCCESS;
734b349e
MZ
11037}
11038
11039DEFUN (no_ipv6_bgp_distance_source,
11040 no_ipv6_bgp_distance_source_cmd,
39e92c06 11041 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
11042 NO_STR
11043 "Define an administrative distance\n"
11044 "Administrative distance\n"
11045 "IP source prefix\n")
11046{
d62a17ae 11047 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
11048 return CMD_SUCCESS;
734b349e
MZ
11049}
11050
11051DEFUN (ipv6_bgp_distance_source_access_list,
11052 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11053 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11054 "Define an administrative distance\n"
11055 "Administrative distance\n"
11056 "IP source prefix\n"
11057 "Access list name\n")
11058{
d62a17ae 11059 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
11060 return CMD_SUCCESS;
734b349e
MZ
11061}
11062
11063DEFUN (no_ipv6_bgp_distance_source_access_list,
11064 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11065 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11066 NO_STR
11067 "Define an administrative distance\n"
11068 "Administrative distance\n"
11069 "IP source prefix\n"
11070 "Access list name\n")
11071{
d62a17ae 11072 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
11073 return CMD_SUCCESS;
734b349e
MZ
11074}
11075
718e3744 11076DEFUN (bgp_damp_set,
11077 bgp_damp_set_cmd,
31500417 11078 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11079 "BGP Specific commands\n"
11080 "Enable route-flap dampening\n"
11081 "Half-life time for the penalty\n"
11082 "Value to start reusing a route\n"
11083 "Value to start suppressing a route\n"
11084 "Maximum duration to suppress a stable route\n")
11085{
d62a17ae 11086 VTY_DECLVAR_CONTEXT(bgp, bgp);
11087 int idx_half_life = 2;
11088 int idx_reuse = 3;
11089 int idx_suppress = 4;
11090 int idx_max_suppress = 5;
11091 int half = DEFAULT_HALF_LIFE * 60;
11092 int reuse = DEFAULT_REUSE;
11093 int suppress = DEFAULT_SUPPRESS;
11094 int max = 4 * half;
11095
11096 if (argc == 6) {
11097 half = atoi(argv[idx_half_life]->arg) * 60;
11098 reuse = atoi(argv[idx_reuse]->arg);
11099 suppress = atoi(argv[idx_suppress]->arg);
11100 max = atoi(argv[idx_max_suppress]->arg) * 60;
11101 } else if (argc == 3) {
11102 half = atoi(argv[idx_half_life]->arg) * 60;
11103 max = 4 * half;
11104 }
718e3744 11105
d62a17ae 11106 if (suppress < reuse) {
11107 vty_out(vty,
11108 "Suppress value cannot be less than reuse value \n");
11109 return 0;
11110 }
7ebe9748 11111
d62a17ae 11112 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
11113 reuse, suppress, max);
718e3744 11114}
11115
718e3744 11116DEFUN (bgp_damp_unset,
11117 bgp_damp_unset_cmd,
d04c479d 11118 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11119 NO_STR
11120 "BGP Specific commands\n"
16cedbb0
QY
11121 "Enable route-flap dampening\n"
11122 "Half-life time for the penalty\n"
11123 "Value to start reusing a route\n"
11124 "Value to start suppressing a route\n"
11125 "Maximum duration to suppress a stable route\n")
718e3744 11126{
d62a17ae 11127 VTY_DECLVAR_CONTEXT(bgp, bgp);
11128 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 11129}
11130
718e3744 11131/* Display specified route of BGP table. */
d62a17ae 11132static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
11133 const char *ip_str, afi_t afi, safi_t safi,
11134 struct prefix_rd *prd, int prefix_check)
11135{
11136 int ret;
11137 struct prefix match;
11138 struct bgp_node *rn;
11139 struct bgp_node *rm;
11140 struct bgp_info *ri;
11141 struct bgp_info *ri_temp;
11142 struct bgp *bgp;
11143 struct bgp_table *table;
11144
11145 /* BGP structure lookup. */
11146 if (view_name) {
11147 bgp = bgp_lookup_by_name(view_name);
11148 if (bgp == NULL) {
11149 vty_out(vty, "%% Can't find BGP instance %s\n",
11150 view_name);
11151 return CMD_WARNING;
11152 }
11153 } else {
11154 bgp = bgp_get_default();
11155 if (bgp == NULL) {
11156 vty_out(vty, "%% No BGP process is configured\n");
11157 return CMD_WARNING;
11158 }
718e3744 11159 }
718e3744 11160
d62a17ae 11161 /* Check IP address argument. */
11162 ret = str2prefix(ip_str, &match);
11163 if (!ret) {
11164 vty_out(vty, "%% address is malformed\n");
11165 return CMD_WARNING;
11166 }
718e3744 11167
d62a17ae 11168 match.family = afi2family(afi);
11169
11170 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
11171 || (safi == SAFI_EVPN)) {
11172 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11173 rn = bgp_route_next(rn)) {
11174 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11175 continue;
ea47320b
DL
11176 if ((table = rn->info) == NULL)
11177 continue;
11178 if ((rm = bgp_node_match(table, &match)) == NULL)
11179 continue;
d62a17ae 11180
ea47320b
DL
11181 if (!prefix_check
11182 || rm->p.prefixlen == match.prefixlen) {
11183 ri = rm->info;
11184 while (ri) {
60466a63 11185 if (ri->extra && ri->extra->damp_info) {
ea47320b
DL
11186 ri_temp = ri->next;
11187 bgp_damp_info_free(
60466a63
QY
11188 ri->extra->damp_info,
11189 1);
ea47320b
DL
11190 ri = ri_temp;
11191 } else
11192 ri = ri->next;
d62a17ae 11193 }
ea47320b
DL
11194 }
11195
11196 bgp_unlock_node(rm);
d62a17ae 11197 }
11198 } else {
11199 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11200 != NULL) {
11201 if (!prefix_check
11202 || rn->p.prefixlen == match.prefixlen) {
11203 ri = rn->info;
11204 while (ri) {
11205 if (ri->extra && ri->extra->damp_info) {
11206 ri_temp = ri->next;
11207 bgp_damp_info_free(
11208 ri->extra->damp_info,
11209 1);
11210 ri = ri_temp;
11211 } else
11212 ri = ri->next;
11213 }
11214 }
11215
11216 bgp_unlock_node(rn);
11217 }
11218 }
718e3744 11219
d62a17ae 11220 return CMD_SUCCESS;
718e3744 11221}
11222
11223DEFUN (clear_ip_bgp_dampening,
11224 clear_ip_bgp_dampening_cmd,
11225 "clear ip bgp dampening",
11226 CLEAR_STR
11227 IP_STR
11228 BGP_STR
11229 "Clear route flap dampening information\n")
11230{
d62a17ae 11231 bgp_damp_info_clean();
11232 return CMD_SUCCESS;
718e3744 11233}
11234
11235DEFUN (clear_ip_bgp_dampening_prefix,
11236 clear_ip_bgp_dampening_prefix_cmd,
11237 "clear ip bgp dampening A.B.C.D/M",
11238 CLEAR_STR
11239 IP_STR
11240 BGP_STR
11241 "Clear route flap dampening information\n"
0c7b1b01 11242 "IPv4 prefix\n")
718e3744 11243{
d62a17ae 11244 int idx_ipv4_prefixlen = 4;
11245 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11246 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11247}
11248
11249DEFUN (clear_ip_bgp_dampening_address,
11250 clear_ip_bgp_dampening_address_cmd,
11251 "clear ip bgp dampening A.B.C.D",
11252 CLEAR_STR
11253 IP_STR
11254 BGP_STR
11255 "Clear route flap dampening information\n"
11256 "Network to clear damping information\n")
11257{
d62a17ae 11258 int idx_ipv4 = 4;
11259 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11260 SAFI_UNICAST, NULL, 0);
718e3744 11261}
11262
11263DEFUN (clear_ip_bgp_dampening_address_mask,
11264 clear_ip_bgp_dampening_address_mask_cmd,
11265 "clear ip bgp dampening A.B.C.D A.B.C.D",
11266 CLEAR_STR
11267 IP_STR
11268 BGP_STR
11269 "Clear route flap dampening information\n"
11270 "Network to clear damping information\n"
11271 "Network mask\n")
11272{
d62a17ae 11273 int idx_ipv4 = 4;
11274 int idx_ipv4_2 = 5;
11275 int ret;
11276 char prefix_str[BUFSIZ];
718e3744 11277
d62a17ae 11278 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11279 prefix_str);
11280 if (!ret) {
11281 vty_out(vty, "%% Inconsistent address and mask\n");
11282 return CMD_WARNING;
11283 }
718e3744 11284
d62a17ae 11285 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11286 NULL, 0);
718e3744 11287}
6b0655a2 11288
587ff0fd 11289/* also used for encap safi */
2b791107
DL
11290static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11291 afi_t afi, safi_t safi)
d62a17ae 11292{
11293 struct bgp_node *prn;
11294 struct bgp_node *rn;
11295 struct bgp_table *table;
11296 struct prefix *p;
11297 struct prefix_rd *prd;
11298 struct bgp_static *bgp_static;
11299 mpls_label_t label;
11300 char buf[SU_ADDRSTRLEN];
11301 char rdbuf[RD_ADDRSTRLEN];
11302
11303 /* Network configuration. */
11304 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11305 prn = bgp_route_next(prn)) {
11306 if ((table = prn->info) == NULL)
11307 continue;
d62a17ae 11308
60466a63 11309 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
ea47320b
DL
11310 if ((bgp_static = rn->info) == NULL)
11311 continue;
d62a17ae 11312
ea47320b
DL
11313 p = &rn->p;
11314 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11315
ea47320b 11316 /* "network" configuration display. */
06b9f471 11317 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11318 label = decode_label(&bgp_static->label);
11319
11320 vty_out(vty, " network %s/%d rd %s",
11321 inet_ntop(p->family, &p->u.prefix, buf,
11322 SU_ADDRSTRLEN),
11323 p->prefixlen, rdbuf);
11324 if (safi == SAFI_MPLS_VPN)
11325 vty_out(vty, " label %u", label);
11326
11327 if (bgp_static->rmap.name)
11328 vty_out(vty, " route-map %s",
11329 bgp_static->rmap.name);
e2a86ad9
DS
11330
11331 if (bgp_static->backdoor)
11332 vty_out(vty, " backdoor");
11333
ea47320b
DL
11334 vty_out(vty, "\n");
11335 }
11336 }
d62a17ae 11337}
11338
2b791107
DL
11339static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11340 afi_t afi, safi_t safi)
d62a17ae 11341{
11342 struct bgp_node *prn;
11343 struct bgp_node *rn;
11344 struct bgp_table *table;
11345 struct prefix *p;
11346 struct prefix_rd *prd;
11347 struct bgp_static *bgp_static;
11348 char buf[PREFIX_STRLEN];
11349 char buf2[SU_ADDRSTRLEN];
11350 char rdbuf[RD_ADDRSTRLEN];
11351
11352 /* Network configuration. */
11353 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11354 prn = bgp_route_next(prn)) {
11355 if ((table = prn->info) == NULL)
11356 continue;
d62a17ae 11357
60466a63 11358 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
ea47320b
DL
11359 if ((bgp_static = rn->info) == NULL)
11360 continue;
d62a17ae 11361
ea47320b
DL
11362 char *macrouter = NULL;
11363 char *esi = NULL;
d62a17ae 11364
ea47320b
DL
11365 if (bgp_static->router_mac)
11366 macrouter = prefix_mac2str(
11367 bgp_static->router_mac, NULL, 0);
11368 if (bgp_static->eth_s_id)
11369 esi = esi2str(bgp_static->eth_s_id);
11370 p = &rn->p;
11371 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11372
ea47320b 11373 /* "network" configuration display. */
06b9f471 11374 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11375 if (p->u.prefix_evpn.route_type == 5) {
11376 char local_buf[PREFIX_STRLEN];
3714a385 11377 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
11378 struct prefix_evpn *)p)
11379 ? AF_INET
11380 : AF_INET6;
3714a385 11381 inet_ntop(family,
11382 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
11383 local_buf, PREFIX_STRLEN);
11384 sprintf(buf, "%s/%u", local_buf,
3714a385 11385 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
11386 } else {
11387 prefix2str(p, buf, sizeof(buf));
11388 }
ea47320b 11389
a4d82a8a
PZ
11390 if (bgp_static->gatewayIp.family == AF_INET
11391 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
11392 inet_ntop(bgp_static->gatewayIp.family,
11393 &bgp_static->gatewayIp.u.prefix, buf2,
11394 sizeof(buf2));
ea47320b 11395 vty_out(vty,
7bcc8dac 11396 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 11397 buf, rdbuf,
11398 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 11399 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11400 macrouter);
11401
11402 if (macrouter)
11403 XFREE(MTYPE_TMP, macrouter);
11404 if (esi)
11405 XFREE(MTYPE_TMP, esi);
11406 }
11407 }
3da6fcd5
PG
11408}
11409
718e3744 11410/* Configuration of static route announcement and aggregate
11411 information. */
2b791107
DL
11412void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11413 safi_t safi)
d62a17ae 11414{
11415 struct bgp_node *rn;
11416 struct prefix *p;
11417 struct bgp_static *bgp_static;
11418 struct bgp_aggregate *bgp_aggregate;
11419 char buf[SU_ADDRSTRLEN];
11420
2b791107
DL
11421 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11422 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11423 return;
11424 }
d62a17ae 11425
2b791107
DL
11426 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11427 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11428 return;
11429 }
d62a17ae 11430
11431 /* Network configuration. */
11432 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b
DL
11433 rn = bgp_route_next(rn)) {
11434 if ((bgp_static = rn->info) == NULL)
11435 continue;
d62a17ae 11436
ea47320b 11437 p = &rn->p;
d62a17ae 11438
ea47320b 11439 /* "network" configuration display. */
60466a63 11440 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
d7c0a89a 11441 uint32_t destination;
ea47320b 11442 struct in_addr netmask;
d62a17ae 11443
ea47320b
DL
11444 destination = ntohl(p->u.prefix4.s_addr);
11445 masklen2ip(p->prefixlen, &netmask);
11446 vty_out(vty, " network %s",
11447 inet_ntop(p->family, &p->u.prefix, buf,
11448 SU_ADDRSTRLEN));
d62a17ae 11449
ea47320b
DL
11450 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11451 || (IN_CLASSB(destination) && p->prefixlen == 16)
11452 || (IN_CLASSA(destination) && p->prefixlen == 8)
11453 || p->u.prefix4.s_addr == 0) {
11454 /* Natural mask is not display. */
11455 } else
11456 vty_out(vty, " mask %s", inet_ntoa(netmask));
11457 } else {
11458 vty_out(vty, " network %s/%d",
11459 inet_ntop(p->family, &p->u.prefix, buf,
11460 SU_ADDRSTRLEN),
11461 p->prefixlen);
11462 }
d62a17ae 11463
ea47320b
DL
11464 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11465 vty_out(vty, " label-index %u",
11466 bgp_static->label_index);
d62a17ae 11467
ea47320b
DL
11468 if (bgp_static->rmap.name)
11469 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
11470
11471 if (bgp_static->backdoor)
11472 vty_out(vty, " backdoor");
718e3744 11473
ea47320b
DL
11474 vty_out(vty, "\n");
11475 }
11476
d62a17ae 11477 /* Aggregate-address configuration. */
11478 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b
DL
11479 rn = bgp_route_next(rn)) {
11480 if ((bgp_aggregate = rn->info) == NULL)
11481 continue;
d62a17ae 11482
ea47320b 11483 p = &rn->p;
d62a17ae 11484
ea47320b
DL
11485 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11486 struct in_addr netmask;
d62a17ae 11487
ea47320b
DL
11488 masklen2ip(p->prefixlen, &netmask);
11489 vty_out(vty, " aggregate-address %s %s",
11490 inet_ntop(p->family, &p->u.prefix, buf,
11491 SU_ADDRSTRLEN),
11492 inet_ntoa(netmask));
11493 } else {
11494 vty_out(vty, " aggregate-address %s/%d",
11495 inet_ntop(p->family, &p->u.prefix, buf,
11496 SU_ADDRSTRLEN),
11497 p->prefixlen);
11498 }
d62a17ae 11499
ea47320b
DL
11500 if (bgp_aggregate->as_set)
11501 vty_out(vty, " as-set");
d62a17ae 11502
ea47320b
DL
11503 if (bgp_aggregate->summary_only)
11504 vty_out(vty, " summary-only");
718e3744 11505
ea47320b
DL
11506 vty_out(vty, "\n");
11507 }
d62a17ae 11508}
734b349e 11509
2b791107 11510void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11511 safi_t safi)
d62a17ae 11512{
11513 struct bgp_node *rn;
11514 struct bgp_distance *bdistance;
11515
11516 /* Distance configuration. */
11517 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11518 && bgp->distance_local[afi][safi]
11519 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11520 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11521 || bgp->distance_local[afi][safi]
11522 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11523 vty_out(vty, " distance bgp %d %d %d\n",
11524 bgp->distance_ebgp[afi][safi],
11525 bgp->distance_ibgp[afi][safi],
11526 bgp->distance_local[afi][safi]);
11527 }
734b349e 11528
d62a17ae 11529 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
11530 rn = bgp_route_next(rn))
11531 if ((bdistance = rn->info) != NULL) {
11532 char buf[PREFIX_STRLEN];
11533
d62a17ae 11534 vty_out(vty, " distance %d %s %s\n",
11535 bdistance->distance,
11536 prefix2str(&rn->p, buf, sizeof(buf)),
11537 bdistance->access_list ? bdistance->access_list
11538 : "");
11539 }
718e3744 11540}
11541
11542/* Allocate routing table structure and install commands. */
d62a17ae 11543void bgp_route_init(void)
11544{
11545 afi_t afi;
11546 safi_t safi;
11547
11548 /* Init BGP distance table. */
05c7a1cc 11549 FOREACH_AFI_SAFI (afi, safi)
960035b2 11550 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 11551
11552 /* IPv4 BGP commands. */
11553 install_element(BGP_NODE, &bgp_table_map_cmd);
11554 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 11555 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 11556
11557 install_element(BGP_NODE, &aggregate_address_cmd);
11558 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11559 install_element(BGP_NODE, &no_aggregate_address_cmd);
11560 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11561
11562 /* IPv4 unicast configuration. */
11563 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11564 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 11565 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 11566
11567 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11568 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11569 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11570 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11571
11572 /* IPv4 multicast configuration. */
11573 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11574 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 11575 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 11576 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11577 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11578 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11579 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11580
11581 /* IPv4 labeled-unicast configuration. */
11582 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11583 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11584 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11585 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11586 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11587
11588 install_element(VIEW_NODE,
11589 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11590 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11591 install_element(VIEW_NODE,
11592 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11593#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11594 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11595#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11596 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11597 install_element(VIEW_NODE,
11598 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11599
d62a17ae 11600 /* BGP dampening clear commands */
11601 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11602 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11603
d62a17ae 11604 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11605 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11606
11607 /* prefix count */
11608 install_element(ENABLE_NODE,
11609 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11610#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11611 install_element(ENABLE_NODE,
11612 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11613#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11614
d62a17ae 11615 /* New config IPv6 BGP commands. */
11616 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11617 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11618 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 11619
11620 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11621 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11622
11623 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11624
d62a17ae 11625 install_element(BGP_NODE, &bgp_distance_cmd);
11626 install_element(BGP_NODE, &no_bgp_distance_cmd);
11627 install_element(BGP_NODE, &bgp_distance_source_cmd);
11628 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11629 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11630 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11631 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11632 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11633 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11634 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11635 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11636 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11637 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11638 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11639 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11640 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11641 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11642 install_element(BGP_IPV4M_NODE,
11643 &no_bgp_distance_source_access_list_cmd);
11644 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11645 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11646 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11647 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11648 install_element(BGP_IPV6_NODE,
11649 &ipv6_bgp_distance_source_access_list_cmd);
11650 install_element(BGP_IPV6_NODE,
11651 &no_ipv6_bgp_distance_source_access_list_cmd);
11652 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11653 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11654 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11655 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11656 install_element(BGP_IPV6M_NODE,
11657 &ipv6_bgp_distance_source_access_list_cmd);
11658 install_element(BGP_IPV6M_NODE,
11659 &no_ipv6_bgp_distance_source_access_list_cmd);
11660
11661 install_element(BGP_NODE, &bgp_damp_set_cmd);
11662 install_element(BGP_NODE, &bgp_damp_unset_cmd);
11663 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
11664 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
11665
11666 /* IPv4 Multicast Mode */
11667 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
11668 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
11669
11670 /* Large Communities */
11671 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11672 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
11673
11674 /* show bgp ipv4 flowspec detailed */
11675 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
11676
d62a17ae 11677}
11678
11679void bgp_route_finish(void)
11680{
11681 afi_t afi;
11682 safi_t safi;
11683
05c7a1cc
QY
11684 FOREACH_AFI_SAFI (afi, safi) {
11685 bgp_table_unlock(bgp_distance_table[afi][safi]);
11686 bgp_distance_table[afi][safi] = NULL;
11687 }
228da428 11688}