]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Dissallow useless aggregation commands from the cli
[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
d62a17ae 5667 /* If routes exists below this node, generate aggregate routes. */
5668 top = bgp_node_get(table, p);
5669 for (rn = bgp_node_get(table, p); rn;
ea47320b
DL
5670 rn = bgp_route_next_until(rn, top)) {
5671 if (rn->p.prefixlen <= p->prefixlen)
5672 continue;
d62a17ae 5673
ea47320b 5674 match = 0;
d62a17ae 5675
ea47320b
DL
5676 for (ri = rn->info; ri; ri = ri->next) {
5677 if (BGP_INFO_HOLDDOWN(ri))
5678 continue;
d62a17ae 5679
ea47320b
DL
5680 if (ri->attr->flag
5681 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5682 atomic_aggregate = 1;
d62a17ae 5683
ea47320b
DL
5684 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5685 continue;
d62a17ae 5686
ea47320b
DL
5687 /* summary-only aggregate route suppress
5688 * aggregated route announcement. */
5689 if (aggregate->summary_only) {
5690 (bgp_info_extra_get(ri))->suppress++;
5691 bgp_info_set_flag(rn, ri,
5692 BGP_INFO_ATTR_CHANGED);
5693 match++;
5694 }
d62a17ae 5695
ea47320b
DL
5696 /* If at least one route among routes that are
5697 * aggregated has ORIGIN with the value INCOMPLETE,
5698 * then the aggregated route MUST have the ORIGIN
5699 * attribute with the value INCOMPLETE. Otherwise, if
5700 * at least one route among routes that are aggregated
5701 * has ORIGIN with the value EGP, then the aggregated
5702 * route MUST have the ORIGIN attribute with the value
5703 * EGP.
5704 */
5705 if (origin < ri->attr->origin)
5706 origin = ri->attr->origin;
5707
5708 /* as-set aggregate route generate origin, as path,
5709 * community aggregation. */
5710 if (aggregate->as_set) {
5711 if (aspath) {
60466a63
QY
5712 asmerge = aspath_aggregate(
5713 aspath, ri->attr->aspath);
ea47320b
DL
5714 aspath_free(aspath);
5715 aspath = asmerge;
5716 } else
5717 aspath = aspath_dup(ri->attr->aspath);
5718
5719 if (ri->attr->community) {
5720 if (community) {
5721 commerge = community_merge(
5722 community,
5723 ri->attr->community);
5724 community = community_uniq_sort(
5725 commerge);
60466a63 5726 community_free(commerge);
ea47320b
DL
5727 } else
5728 community = community_dup(
5729 ri->attr->community);
d62a17ae 5730 }
5731 }
ea47320b 5732 aggregate->count++;
d62a17ae 5733 }
ea47320b
DL
5734
5735 /* If this node is suppressed, process the change. */
5736 if (match)
5737 bgp_process(bgp, rn, afi, safi);
5738 }
d62a17ae 5739 bgp_unlock_node(top);
5740
5741 /* Add aggregate route to BGP table. */
5742 if (aggregate->count) {
5743 rn = bgp_node_get(table, p);
5744 new = info_make(
5745 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5746 bgp_attr_aggregate_intern(bgp, origin, aspath,
5747 community, aggregate->as_set,
5748 atomic_aggregate),
5749 rn);
5750 SET_FLAG(new->flags, BGP_INFO_VALID);
5751
5752 bgp_info_add(rn, new);
5753 bgp_unlock_node(rn);
5754
5755 /* Process change. */
5756 bgp_process(bgp, rn, afi, safi);
5757 } else {
5758 if (aspath)
5759 aspath_free(aspath);
5760 if (community)
5761 community_free(community);
5762 }
718e3744 5763}
5764
d62a17ae 5765void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5766 safi_t safi, struct bgp_aggregate *aggregate)
718e3744 5767{
d62a17ae 5768 struct bgp_table *table;
5769 struct bgp_node *top;
5770 struct bgp_node *rn;
5771 struct bgp_info *ri;
5772 unsigned long match;
718e3744 5773
d62a17ae 5774 table = bgp->rib[afi][safi];
718e3744 5775
d62a17ae 5776 /* If routes exists below this node, generate aggregate routes. */
5777 top = bgp_node_get(table, p);
5778 for (rn = bgp_node_get(table, p); rn;
ea47320b
DL
5779 rn = bgp_route_next_until(rn, top)) {
5780 if (rn->p.prefixlen <= p->prefixlen)
5781 continue;
5782 match = 0;
d62a17ae 5783
ea47320b
DL
5784 for (ri = rn->info; ri; ri = ri->next) {
5785 if (BGP_INFO_HOLDDOWN(ri))
5786 continue;
d62a17ae 5787
ea47320b
DL
5788 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5789 continue;
5790
5791 if (aggregate->summary_only && ri->extra) {
5792 ri->extra->suppress--;
5793
5794 if (ri->extra->suppress == 0) {
60466a63
QY
5795 bgp_info_set_flag(
5796 rn, ri, BGP_INFO_ATTR_CHANGED);
ea47320b 5797 match++;
d62a17ae 5798 }
5799 }
ea47320b 5800 aggregate->count--;
d62a17ae 5801 }
ea47320b
DL
5802
5803 /* If this node was suppressed, process the change. */
5804 if (match)
5805 bgp_process(bgp, rn, afi, safi);
5806 }
d62a17ae 5807 bgp_unlock_node(top);
718e3744 5808
d62a17ae 5809 /* Delete aggregate route from BGP table. */
5810 rn = bgp_node_get(table, p);
718e3744 5811
5812 for (ri = rn->info; ri; ri = ri->next)
d62a17ae 5813 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
5814 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5815 break;
5816
5817 /* Withdraw static BGP route from routing table. */
5818 if (ri) {
5819 bgp_info_delete(rn, ri);
5820 bgp_process(bgp, rn, afi, safi);
5821 }
718e3744 5822
d62a17ae 5823 /* Unlock bgp_node_lookup. */
5824 bgp_unlock_node(rn);
718e3744 5825}
5826
5827/* Aggregate route attribute. */
5828#define AGGREGATE_SUMMARY_ONLY 1
5829#define AGGREGATE_AS_SET 1
5830
d62a17ae 5831static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5832 afi_t afi, safi_t safi)
718e3744 5833{
d62a17ae 5834 VTY_DECLVAR_CONTEXT(bgp, bgp);
5835 int ret;
5836 struct prefix p;
5837 struct bgp_node *rn;
5838 struct bgp_aggregate *aggregate;
718e3744 5839
d62a17ae 5840 /* Convert string to prefix structure. */
5841 ret = str2prefix(prefix_str, &p);
5842 if (!ret) {
5843 vty_out(vty, "Malformed prefix\n");
5844 return CMD_WARNING_CONFIG_FAILED;
5845 }
5846 apply_mask(&p);
5847
5848 /* Old configuration check. */
5849 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5850 if (!rn) {
5851 vty_out(vty,
5852 "%% There is no aggregate-address configuration.\n");
5853 return CMD_WARNING_CONFIG_FAILED;
5854 }
f6269b4f 5855
d62a17ae 5856 aggregate = rn->info;
09990cdd 5857 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
d62a17ae 5858
5859 /* Unlock aggregate address configuration. */
5860 rn->info = NULL;
5861 bgp_aggregate_free(aggregate);
5862 bgp_unlock_node(rn);
5863 bgp_unlock_node(rn);
5864
5865 return CMD_SUCCESS;
5866}
5867
5868static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
d7c0a89a 5869 safi_t safi, uint8_t summary_only, uint8_t as_set)
d62a17ae 5870{
5871 VTY_DECLVAR_CONTEXT(bgp, bgp);
5872 int ret;
5873 struct prefix p;
5874 struct bgp_node *rn;
5875 struct bgp_aggregate *aggregate;
5876
5877 /* Convert string to prefix structure. */
5878 ret = str2prefix(prefix_str, &p);
5879 if (!ret) {
5880 vty_out(vty, "Malformed prefix\n");
5881 return CMD_WARNING_CONFIG_FAILED;
5882 }
5883 apply_mask(&p);
5884
3624ac81
DS
5885 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
5886 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
5887 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5888 prefix_str);
5889 return CMD_WARNING_CONFIG_FAILED;
5890 }
5891
d62a17ae 5892 /* Old configuration check. */
5893 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
5894
5895 if (rn->info) {
5896 vty_out(vty, "There is already same aggregate network.\n");
5897 /* try to remove the old entry */
5898 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
5899 if (ret) {
5900 vty_out(vty, "Error deleting aggregate.\n");
5901 bgp_unlock_node(rn);
5902 return CMD_WARNING_CONFIG_FAILED;
5903 }
5904 }
718e3744 5905
d62a17ae 5906 /* Make aggregate address structure. */
5907 aggregate = bgp_aggregate_new();
5908 aggregate->summary_only = summary_only;
5909 aggregate->as_set = as_set;
5910 aggregate->safi = safi;
5911 rn->info = aggregate;
718e3744 5912
d62a17ae 5913 /* Aggregate address insert into BGP routing table. */
09990cdd 5914 bgp_aggregate_add(bgp, &p, afi, safi, aggregate);
718e3744 5915
d62a17ae 5916 return CMD_SUCCESS;
718e3744 5917}
5918
5919DEFUN (aggregate_address,
5920 aggregate_address_cmd,
e3e6107d 5921 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5922 "Configure BGP aggregate entries\n"
5923 "Aggregate prefix\n"
5924 "Generate AS set path information\n"
a636c635
DW
5925 "Filter more specific routes from updates\n"
5926 "Filter more specific routes from updates\n"
5927 "Generate AS set path information\n")
718e3744 5928{
d62a17ae 5929 int idx = 0;
5930 argv_find(argv, argc, "A.B.C.D/M", &idx);
5931 char *prefix = argv[idx]->arg;
5932 int as_set =
5933 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5934 idx = 0;
5935 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5936 ? AGGREGATE_SUMMARY_ONLY
5937 : 0;
e3e6107d 5938
d62a17ae 5939 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
5940 summary_only, as_set);
718e3744 5941}
5942
e3e6107d
QY
5943DEFUN (aggregate_address_mask,
5944 aggregate_address_mask_cmd,
5945 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5946 "Configure BGP aggregate entries\n"
5947 "Aggregate address\n"
5948 "Aggregate mask\n"
5949 "Generate AS set path information\n"
a636c635
DW
5950 "Filter more specific routes from updates\n"
5951 "Filter more specific routes from updates\n"
5952 "Generate AS set path information\n")
718e3744 5953{
d62a17ae 5954 int idx = 0;
5955 argv_find(argv, argc, "A.B.C.D", &idx);
5956 char *prefix = argv[idx]->arg;
5957 char *mask = argv[idx + 1]->arg;
5958 int as_set =
5959 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5960 idx = 0;
5961 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5962 ? AGGREGATE_SUMMARY_ONLY
5963 : 0;
5964
5965 char prefix_str[BUFSIZ];
5966 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
5967
5968 if (!ret) {
5969 vty_out(vty, "%% Inconsistent address and mask\n");
5970 return CMD_WARNING_CONFIG_FAILED;
5971 }
718e3744 5972
d62a17ae 5973 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5974 summary_only, as_set);
718e3744 5975}
5976
718e3744 5977DEFUN (no_aggregate_address,
5978 no_aggregate_address_cmd,
e3e6107d 5979 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5980 NO_STR
5981 "Configure BGP aggregate entries\n"
a636c635
DW
5982 "Aggregate prefix\n"
5983 "Generate AS set path information\n"
e3e6107d
QY
5984 "Filter more specific routes from updates\n"
5985 "Filter more specific routes from updates\n"
5986 "Generate AS set path information\n")
718e3744 5987{
d62a17ae 5988 int idx = 0;
5989 argv_find(argv, argc, "A.B.C.D/M", &idx);
5990 char *prefix = argv[idx]->arg;
5991 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 5992}
5993
718e3744 5994DEFUN (no_aggregate_address_mask,
5995 no_aggregate_address_mask_cmd,
e3e6107d 5996 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5997 NO_STR
5998 "Configure BGP aggregate entries\n"
5999 "Aggregate address\n"
a636c635
DW
6000 "Aggregate mask\n"
6001 "Generate AS set path information\n"
e3e6107d
QY
6002 "Filter more specific routes from updates\n"
6003 "Filter more specific routes from updates\n"
6004 "Generate AS set path information\n")
718e3744 6005{
d62a17ae 6006 int idx = 0;
6007 argv_find(argv, argc, "A.B.C.D", &idx);
6008 char *prefix = argv[idx]->arg;
6009 char *mask = argv[idx + 1]->arg;
718e3744 6010
d62a17ae 6011 char prefix_str[BUFSIZ];
6012 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6013
d62a17ae 6014 if (!ret) {
6015 vty_out(vty, "%% Inconsistent address and mask\n");
6016 return CMD_WARNING_CONFIG_FAILED;
6017 }
718e3744 6018
d62a17ae 6019 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6020}
6021
718e3744 6022DEFUN (ipv6_aggregate_address,
6023 ipv6_aggregate_address_cmd,
e3e6107d 6024 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6025 "Configure BGP aggregate entries\n"
6026 "Aggregate prefix\n"
6027 "Filter more specific routes from updates\n")
6028{
d62a17ae 6029 int idx = 0;
6030 argv_find(argv, argc, "X:X::X:X/M", &idx);
6031 char *prefix = argv[idx]->arg;
6032 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6033 ? AGGREGATE_SUMMARY_ONLY
6034 : 0;
6035 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6036 0);
718e3744 6037}
6038
6039DEFUN (no_ipv6_aggregate_address,
6040 no_ipv6_aggregate_address_cmd,
e3e6107d 6041 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6042 NO_STR
6043 "Configure BGP aggregate entries\n"
16cedbb0
QY
6044 "Aggregate prefix\n"
6045 "Filter more specific routes from updates\n")
718e3744 6046{
d62a17ae 6047 int idx = 0;
6048 argv_find(argv, argc, "X:X::X:X/M", &idx);
6049 char *prefix = argv[idx]->arg;
6050 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6051}
6052
718e3744 6053/* Redistribute route treatment. */
d62a17ae 6054void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6055 const union g_addr *nexthop, ifindex_t ifindex,
6056 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6057 uint8_t type, unsigned short instance,
6058 route_tag_t tag)
d62a17ae 6059{
6060 struct bgp_info *new;
6061 struct bgp_info *bi;
6062 struct bgp_info info;
6063 struct bgp_node *bn;
6064 struct attr attr;
6065 struct attr *new_attr;
6066 afi_t afi;
6067 int ret;
6068 struct bgp_redist *red;
6069
6070 /* Make default attribute. */
6071 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff 6072
a4d82a8a 6073 switch (nhtype) {
9de1f7ff
DS
6074 case NEXTHOP_TYPE_IFINDEX:
6075 break;
6076 case NEXTHOP_TYPE_IPV4:
6077 case NEXTHOP_TYPE_IPV4_IFINDEX:
6078 attr.nexthop = nexthop->ipv4;
6079 break;
6080 case NEXTHOP_TYPE_IPV6:
6081 case NEXTHOP_TYPE_IPV6_IFINDEX:
6082 attr.mp_nexthop_global = nexthop->ipv6;
6083 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6084 break;
6085 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6086 switch (p->family) {
6087 case AF_INET:
9de1f7ff 6088 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6089 break;
6090 case AF_INET6:
9de1f7ff
DS
6091 memset(&attr.mp_nexthop_global, 0,
6092 sizeof(attr.mp_nexthop_global));
74489921 6093 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6094 break;
74489921 6095 }
9de1f7ff 6096 break;
d62a17ae 6097 }
74489921 6098 attr.nh_ifindex = ifindex;
f04a80a5 6099
d62a17ae 6100 attr.med = metric;
6101 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6102 attr.tag = tag;
718e3744 6103
d62a17ae 6104 afi = family2afi(p->family);
6aeb9e78 6105
d62a17ae 6106 red = bgp_redist_lookup(bgp, afi, type, instance);
6107 if (red) {
6108 struct attr attr_new;
718e3744 6109
d62a17ae 6110 /* Copy attribute for modification. */
6111 bgp_attr_dup(&attr_new, &attr);
718e3744 6112
d62a17ae 6113 if (red->redist_metric_flag)
6114 attr_new.med = red->redist_metric;
718e3744 6115
d62a17ae 6116 /* Apply route-map. */
6117 if (red->rmap.name) {
6118 info.peer = bgp->peer_self;
6119 info.attr = &attr_new;
718e3744 6120
d62a17ae 6121 SET_FLAG(bgp->peer_self->rmap_type,
6122 PEER_RMAP_TYPE_REDISTRIBUTE);
6123
6124 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
6125 &info);
6126
6127 bgp->peer_self->rmap_type = 0;
6128
6129 if (ret == RMAP_DENYMATCH) {
6130 /* Free uninterned attribute. */
6131 bgp_attr_flush(&attr_new);
6132
6133 /* Unintern original. */
6134 aspath_unintern(&attr.aspath);
6135 bgp_redistribute_delete(bgp, p, type, instance);
6136 return;
6137 }
6138 }
6139
7f323236
DW
6140 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6141 bgp_attr_add_gshut_community(&attr_new);
6142
d62a17ae 6143 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6144 SAFI_UNICAST, p, NULL);
6145
6146 new_attr = bgp_attr_intern(&attr_new);
6147
6148 for (bi = bn->info; bi; bi = bi->next)
6149 if (bi->peer == bgp->peer_self
6150 && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
6151 break;
6152
6153 if (bi) {
6154 /* Ensure the (source route) type is updated. */
6155 bi->type = type;
6156 if (attrhash_cmp(bi->attr, new_attr)
6157 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
6158 bgp_attr_unintern(&new_attr);
6159 aspath_unintern(&attr.aspath);
6160 bgp_unlock_node(bn);
6161 return;
6162 } else {
6163 /* The attribute is changed. */
6164 bgp_info_set_flag(bn, bi,
6165 BGP_INFO_ATTR_CHANGED);
6166
6167 /* Rewrite BGP route information. */
6168 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
6169 bgp_info_restore(bn, bi);
6170 else
6171 bgp_aggregate_decrement(bgp, p, bi, afi,
6172 SAFI_UNICAST);
6173 bgp_attr_unintern(&bi->attr);
6174 bi->attr = new_attr;
6175 bi->uptime = bgp_clock();
6176
6177 /* Process change. */
6178 bgp_aggregate_increment(bgp, p, bi, afi,
6179 SAFI_UNICAST);
6180 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6181 bgp_unlock_node(bn);
6182 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6183
6184 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6185 || (bgp->inst_type
6186 == BGP_INSTANCE_TYPE_DEFAULT)) {
6187
6188 vpn_leak_from_vrf_update(
6189 bgp_get_default(), bgp, bi);
6190 }
d62a17ae 6191 return;
6192 }
6193 }
6194
6195 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6196 bgp->peer_self, new_attr, bn);
6197 SET_FLAG(new->flags, BGP_INFO_VALID);
6198
6199 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
6200 bgp_info_add(bn, new);
6201 bgp_unlock_node(bn);
6202 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6203
6204 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6205 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6206
6207 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6208 }
d62a17ae 6209 }
6210
6211 /* Unintern original. */
6212 aspath_unintern(&attr.aspath);
718e3744 6213}
6214
d7c0a89a
QY
6215void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6216 unsigned short instance)
718e3744 6217{
d62a17ae 6218 afi_t afi;
6219 struct bgp_node *rn;
6220 struct bgp_info *ri;
6221 struct bgp_redist *red;
718e3744 6222
d62a17ae 6223 afi = family2afi(p->family);
718e3744 6224
d62a17ae 6225 red = bgp_redist_lookup(bgp, afi, type, instance);
6226 if (red) {
6227 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6228 SAFI_UNICAST, p, NULL);
6229
6230 for (ri = rn->info; ri; ri = ri->next)
6231 if (ri->peer == bgp->peer_self && ri->type == type)
6232 break;
6233
6234 if (ri) {
ddb5b488
PZ
6235 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6236 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6237
6238 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6239 bgp, ri);
6240 }
d62a17ae 6241 bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
6242 bgp_info_delete(rn, ri);
6243 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6244 }
6245 bgp_unlock_node(rn);
6246 }
6247}
6248
6249/* Withdraw specified route type's route. */
6250void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6251 unsigned short instance)
d62a17ae 6252{
6253 struct bgp_node *rn;
6254 struct bgp_info *ri;
6255 struct bgp_table *table;
6256
6257 table = bgp->rib[afi][SAFI_UNICAST];
6258
6259 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6260 for (ri = rn->info; ri; ri = ri->next)
6261 if (ri->peer == bgp->peer_self && ri->type == type
6262 && ri->instance == instance)
6263 break;
6264
6265 if (ri) {
ddb5b488
PZ
6266 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6267 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6268
6269 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6270 bgp, ri);
6271 }
d62a17ae 6272 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
6273 SAFI_UNICAST);
6274 bgp_info_delete(rn, ri);
6275 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6276 }
718e3744 6277 }
718e3744 6278}
6b0655a2 6279
718e3744 6280/* Static function to display route. */
9c92b5f7
MK
6281static void route_vty_out_route(struct prefix *p, struct vty *vty,
6282 json_object *json)
718e3744 6283{
be054588 6284 int len = 0;
d7c0a89a 6285 uint32_t destination;
d62a17ae 6286 char buf[BUFSIZ];
718e3744 6287
d62a17ae 6288 if (p->family == AF_INET) {
c6462ff4
MK
6289 if (!json) {
6290 len = vty_out(vty, "%s",
6291 inet_ntop(p->family, &p->u.prefix, buf,
6292 BUFSIZ));
6293 destination = ntohl(p->u.prefix4.s_addr);
6294
6295 if ((IN_CLASSC(destination) && p->prefixlen == 24)
6296 || (IN_CLASSB(destination) && p->prefixlen == 16)
6297 || (IN_CLASSA(destination) && p->prefixlen == 8)
6298 || p->u.prefix4.s_addr == 0) {
b682f6de 6299 /* When mask is natural,
6300 mask is not displayed. */
c6462ff4
MK
6301 } else
6302 len += vty_out(vty, "/%d", p->prefixlen);
6303 } else {
6304 json_object_string_add(json, "prefix",
6305 inet_ntop(p->family,
6306 &p->u.prefix, buf,
6307 BUFSIZ));
6308 json_object_int_add(json, "prefixLen", p->prefixlen);
6309 }
d62a17ae 6310 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6311 prefix2str(p, buf, PREFIX_STRLEN);
6312 len = vty_out(vty, "%s", buf);
6313 } else if (p->family == AF_EVPN) {
d62a17ae 6314#if defined(HAVE_CUMULUS)
57f7feb6 6315 if (!json)
60466a63
QY
6316 len = vty_out(
6317 vty, "%s",
6318 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6319 BUFSIZ));
57f7feb6 6320 else
60466a63 6321 bgp_evpn_route2json((struct prefix_evpn *)p, json);
520d5d76 6322#else
d62a17ae 6323 prefix2str(p, buf, PREFIX_STRLEN);
6324 len = vty_out(vty, "%s", buf);
520d5d76 6325#endif
dba3c1d3
PG
6326 } else if (p->family == AF_FLOWSPEC) {
6327 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6328 json ?
6329 NLRI_STRING_FORMAT_JSON_SIMPLE :
6330 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6331 } else {
c6462ff4 6332 if (!json)
60466a63
QY
6333 len = vty_out(
6334 vty, "%s/%d",
6335 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6336 p->prefixlen);
9c92b5f7 6337 }
d62a17ae 6338
9c92b5f7
MK
6339 if (!json) {
6340 len = 17 - len;
6341 if (len < 1)
6342 vty_out(vty, "\n%*s", 20, " ");
6343 else
6344 vty_out(vty, "%*s", len, " ");
6345 }
718e3744 6346}
6347
d62a17ae 6348enum bgp_display_type {
6349 normal_list,
718e3744 6350};
6351
b40d939b 6352/* Print the short form route status for a bgp_info */
d62a17ae 6353static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo,
6354 json_object *json_path)
718e3744 6355{
d62a17ae 6356 if (json_path) {
b05a1c8b 6357
d62a17ae 6358 /* Route status display. */
6359 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6360 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6361
d62a17ae 6362 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6363 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6364
d62a17ae 6365 if (binfo->extra && binfo->extra->suppress)
6366 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6367
d62a17ae 6368 if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6369 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6370 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6371
d62a17ae 6372 /* Selected */
6373 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6374 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6375
d62a17ae 6376 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6377 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6378
d62a17ae 6379 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6380 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6381
d62a17ae 6382 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6383 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6384
d62a17ae 6385 /* Internal route. */
6386 if ((binfo->peer->as)
6387 && (binfo->peer->as == binfo->peer->local_as))
6388 json_object_string_add(json_path, "pathFrom",
6389 "internal");
6390 else
6391 json_object_string_add(json_path, "pathFrom",
6392 "external");
b05a1c8b 6393
d62a17ae 6394 return;
6395 }
b05a1c8b 6396
d62a17ae 6397 /* Route status display. */
6398 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6399 vty_out(vty, "R");
6400 else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6401 vty_out(vty, "S");
6402 else if (binfo->extra && binfo->extra->suppress)
6403 vty_out(vty, "s");
6404 else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6405 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6406 vty_out(vty, "*");
6407 else
6408 vty_out(vty, " ");
6409
6410 /* Selected */
6411 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6412 vty_out(vty, "h");
6413 else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6414 vty_out(vty, "d");
6415 else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6416 vty_out(vty, ">");
6417 else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6418 vty_out(vty, "=");
6419 else
6420 vty_out(vty, " ");
718e3744 6421
d62a17ae 6422 /* Internal route. */
6423 if (binfo->peer && (binfo->peer->as)
6424 && (binfo->peer->as == binfo->peer->local_as))
6425 vty_out(vty, "i");
6426 else
6427 vty_out(vty, " ");
b40d939b 6428}
6429
6430/* called from terminal list command */
d62a17ae 6431void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6432 int display, safi_t safi, json_object *json_paths)
6433{
6434 struct attr *attr;
6435 json_object *json_path = NULL;
6436 json_object *json_nexthops = NULL;
6437 json_object *json_nexthop_global = NULL;
6438 json_object *json_nexthop_ll = NULL;
9df8b37c
PZ
6439 char vrf_id_str[VRF_NAMSIZ] = {0};
6440 bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
6441 ? true
6442 : false;
6443 bool nexthop_othervrf = false;
43089216 6444 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
9df8b37c 6445 const char *nexthop_vrfname = "Default";
d62a17ae 6446
6447 if (json_paths)
6448 json_path = json_object_new_object();
6449
6450 /* short status lead text */
6451 route_vty_short_status_out(vty, binfo, json_path);
6452
6453 if (!json_paths) {
6454 /* print prefix and mask */
6455 if (!display)
9c92b5f7 6456 route_vty_out_route(p, vty, json_path);
d62a17ae 6457 else
6458 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6459 } else {
b682f6de 6460 route_vty_out_route(p, vty, json_path);
d62a17ae 6461 }
47fc97cc 6462
d62a17ae 6463 /* Print attribute */
6464 attr = binfo->attr;
445c2480
DS
6465 if (!attr) {
6466 if (json_paths)
6467 json_object_array_add(json_paths, json_path);
6468 else
6469 vty_out(vty, "\n");
d62a17ae 6470
445c2480
DS
6471 return;
6472 }
6473
9df8b37c
PZ
6474 /*
6475 * If vrf id of nexthop is different from that of prefix,
6476 * set up printable string to append
6477 */
6478 if (binfo->extra && binfo->extra->bgp_orig) {
6479 const char *self = "";
6480
6481 if (nexthop_self)
6482 self = "<";
6483
6484 nexthop_othervrf = true;
6485 nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
6486
6487 if (binfo->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
6488 snprintf(vrf_id_str, sizeof(vrf_id_str),
6489 "@%s%s", VRFID_NONE_STR, self);
6490 else
6491 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
6492 binfo->extra->bgp_orig->vrf_id, self);
6493
6494 if (binfo->extra->bgp_orig->inst_type !=
6495 BGP_INSTANCE_TYPE_DEFAULT)
6496
6497 nexthop_vrfname = binfo->extra->bgp_orig->name;
6498 } else {
6499 const char *self = "";
6500
6501 if (nexthop_self)
6502 self = "<";
6503
6504 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
6505 }
6506
445c2480
DS
6507 /*
6508 * For ENCAP and EVPN routes, nexthop address family is not
6509 * neccessarily the same as the prefix address family.
6510 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6511 * EVPN routes are also exchanged with a MP nexthop. Currently,
6512 * this
6513 * is only IPv4, the value will be present in either
6514 * attr->nexthop or
6515 * attr->mp_nexthop_global_in
6516 */
6517 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6518 char buf[BUFSIZ];
6519 char nexthop[128];
6520 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6521
6522 switch (af) {
6523 case AF_INET:
6524 sprintf(nexthop, "%s",
a4d82a8a
PZ
6525 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
6526 BUFSIZ));
445c2480
DS
6527 break;
6528 case AF_INET6:
6529 sprintf(nexthop, "%s",
a4d82a8a
PZ
6530 inet_ntop(af, &attr->mp_nexthop_global, buf,
6531 BUFSIZ));
445c2480
DS
6532 break;
6533 default:
6534 sprintf(nexthop, "?");
6535 break;
d62a17ae 6536 }
d62a17ae 6537
445c2480
DS
6538 if (json_paths) {
6539 json_nexthop_global = json_object_new_object();
6540
a4d82a8a
PZ
6541 json_object_string_add(json_nexthop_global, "afi",
6542 (af == AF_INET) ? "ip" : "ipv6");
445c2480 6543 json_object_string_add(json_nexthop_global,
a4d82a8a 6544 (af == AF_INET) ? "ip" : "ipv6",
445c2480
DS
6545 nexthop);
6546 json_object_boolean_true_add(json_nexthop_global,
6547 "used");
6548 } else
9df8b37c 6549 vty_out(vty, "%s%s", nexthop, vrf_id_str);
445c2480
DS
6550 } else if (safi == SAFI_EVPN) {
6551 if (json_paths) {
6552 json_nexthop_global = json_object_new_object();
6553
6554 json_object_string_add(json_nexthop_global, "ip",
6555 inet_ntoa(attr->nexthop));
a4d82a8a
PZ
6556 json_object_string_add(json_nexthop_global, "afi",
6557 "ipv4");
445c2480
DS
6558 json_object_boolean_true_add(json_nexthop_global,
6559 "used");
6560 } else
9df8b37c
PZ
6561 vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
6562 vrf_id_str);
d33fc23b 6563 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
6564 if (attr->nexthop.s_addr != 0) {
6565 if (json_paths) {
6566 json_nexthop_global = json_object_new_object();
6567 json_object_string_add(
6568 json_nexthop_global, "ip",
6569 inet_ntoa(attr->nexthop));
6570 json_object_string_add(json_nexthop_global,
6571 "afi", "ipv4");
6572 json_object_boolean_true_add(json_nexthop_global,
6573 "used");
6574 } else {
6575 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6576 }
6577 }
d33fc23b 6578 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6579 if (json_paths) {
6580 json_nexthop_global = json_object_new_object();
d62a17ae 6581
a4d82a8a
PZ
6582 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
6583 json_object_string_add(
6584 json_nexthop_global, "ip",
6585 inet_ntoa(attr->mp_nexthop_global_in));
445c2480 6586 else
a4d82a8a
PZ
6587 json_object_string_add(
6588 json_nexthop_global, "ip",
6589 inet_ntoa(attr->nexthop));
445c2480 6590
a4d82a8a
PZ
6591 json_object_string_add(json_nexthop_global, "afi",
6592 "ipv4");
445c2480
DS
6593 json_object_boolean_true_add(json_nexthop_global,
6594 "used");
6595 } else {
9df8b37c
PZ
6596 char buf[BUFSIZ];
6597
a4d82a8a 6598 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
9df8b37c
PZ
6599 snprintf(buf, sizeof(buf), "%s%s",
6600 inet_ntoa(attr->mp_nexthop_global_in),
6601 vrf_id_str);
445c2480 6602 else
9df8b37c
PZ
6603 snprintf(buf, sizeof(buf), "%s%s",
6604 inet_ntoa(attr->nexthop),
6605 vrf_id_str);
6606 vty_out(vty, "%-16s", buf);
d62a17ae 6607 }
445c2480 6608 }
b05a1c8b 6609
445c2480 6610 /* IPv6 Next Hop */
a4d82a8a 6611 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6612 int len;
6613 char buf[BUFSIZ];
d62a17ae 6614
445c2480
DS
6615 if (json_paths) {
6616 json_nexthop_global = json_object_new_object();
a4d82a8a
PZ
6617 json_object_string_add(
6618 json_nexthop_global, "ip",
6619 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
6620 buf, BUFSIZ));
6621 json_object_string_add(json_nexthop_global, "afi",
6622 "ipv6");
6623 json_object_string_add(json_nexthop_global, "scope",
6624 "global");
445c2480
DS
6625
6626 /* We display both LL & GL if both have been
6627 * received */
6628 if ((attr->mp_nexthop_len == 32)
6629 || (binfo->peer->conf_if)) {
a4d82a8a 6630 json_nexthop_ll = json_object_new_object();
d62a17ae 6631 json_object_string_add(
445c2480 6632 json_nexthop_ll, "ip",
a4d82a8a
PZ
6633 inet_ntop(AF_INET6,
6634 &attr->mp_nexthop_local, buf,
6635 BUFSIZ));
6636 json_object_string_add(json_nexthop_ll, "afi",
6637 "ipv6");
6638 json_object_string_add(json_nexthop_ll, "scope",
445c2480 6639 "link-local");
d62a17ae 6640
a4d82a8a
PZ
6641 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
6642 &attr->mp_nexthop_local)
445c2480
DS
6643 != 0)
6644 && !attr->mp_nexthop_prefer_global)
d62a17ae 6645 json_object_boolean_true_add(
a4d82a8a 6646 json_nexthop_ll, "used");
445c2480
DS
6647 else
6648 json_object_boolean_true_add(
a4d82a8a 6649 json_nexthop_global, "used");
445c2480
DS
6650 } else
6651 json_object_boolean_true_add(
6652 json_nexthop_global, "used");
6653 } else {
6654 /* Display LL if LL/Global both in table unless
6655 * prefer-global is set */
6656 if (((attr->mp_nexthop_len == 32)
6657 && !attr->mp_nexthop_prefer_global)
6658 || (binfo->peer->conf_if)) {
6659 if (binfo->peer->conf_if) {
a4d82a8a
PZ
6660 len = vty_out(vty, "%s",
6661 binfo->peer->conf_if);
445c2480
DS
6662 len = 16 - len; /* len of IPv6
6663 addr + max
6664 len of def
6665 ifname */
6666
6667 if (len < 1)
a4d82a8a 6668 vty_out(vty, "\n%*s", 36, " ");
445c2480 6669 else
a4d82a8a 6670 vty_out(vty, "%*s", len, " ");
d62a17ae 6671 } else {
6672 len = vty_out(
9df8b37c 6673 vty, "%s%s",
d62a17ae 6674 inet_ntop(
6675 AF_INET6,
445c2480 6676 &attr->mp_nexthop_local,
9df8b37c
PZ
6677 buf, BUFSIZ),
6678 vrf_id_str);
d62a17ae 6679 len = 16 - len;
6680
6681 if (len < 1)
a4d82a8a 6682 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 6683 else
a4d82a8a 6684 vty_out(vty, "%*s", len, " ");
d62a17ae 6685 }
445c2480 6686 } else {
a4d82a8a 6687 len = vty_out(
9df8b37c 6688 vty, "%s%s",
a4d82a8a
PZ
6689 inet_ntop(AF_INET6,
6690 &attr->mp_nexthop_global, buf,
9df8b37c
PZ
6691 BUFSIZ),
6692 vrf_id_str);
445c2480
DS
6693 len = 16 - len;
6694
6695 if (len < 1)
6696 vty_out(vty, "\n%*s", 36, " ");
6697 else
6698 vty_out(vty, "%*s", len, " ");
d62a17ae 6699 }
6700 }
445c2480 6701 }
718e3744 6702
445c2480
DS
6703 /* MED/Metric */
6704 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6705 if (json_paths)
a4d82a8a 6706 json_object_int_add(json_path, "med", attr->med);
445c2480
DS
6707 else
6708 vty_out(vty, "%10u", attr->med);
6709 else if (!json_paths)
6710 vty_out(vty, " ");
d62a17ae 6711
445c2480
DS
6712 /* Local Pref */
6713 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
d62a17ae 6714 if (json_paths)
445c2480
DS
6715 json_object_int_add(json_path, "localpref",
6716 attr->local_pref);
d62a17ae 6717 else
445c2480
DS
6718 vty_out(vty, "%7u", attr->local_pref);
6719 else if (!json_paths)
6720 vty_out(vty, " ");
d62a17ae 6721
445c2480
DS
6722 if (json_paths)
6723 json_object_int_add(json_path, "weight", attr->weight);
6724 else
6725 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6726
445c2480
DS
6727 if (json_paths) {
6728 char buf[BUFSIZ];
a4d82a8a
PZ
6729 json_object_string_add(
6730 json_path, "peerId",
6731 sockunion2str(&binfo->peer->su, buf, SU_ADDRSTRLEN));
445c2480 6732 }
b05a1c8b 6733
445c2480
DS
6734 /* Print aspath */
6735 if (attr->aspath) {
d62a17ae 6736 if (json_paths)
445c2480
DS
6737 json_object_string_add(json_path, "aspath",
6738 attr->aspath->str);
d62a17ae 6739 else
445c2480 6740 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6741 }
f1aa5d8a 6742
445c2480
DS
6743 /* Print origin */
6744 if (json_paths)
a4d82a8a
PZ
6745 json_object_string_add(json_path, "origin",
6746 bgp_origin_long_str[attr->origin]);
445c2480
DS
6747 else
6748 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6749
9df8b37c
PZ
6750 if (json_paths) {
6751 if (nexthop_self)
6752 json_object_boolean_true_add(json_path,
6753 "announceNexthopSelf");
6754 if (nexthop_othervrf) {
6755 json_object_string_add(json_path, "nhVrfName",
6756 nexthop_vrfname);
6757
6758 json_object_int_add(json_path, "nhVrfId",
6759 ((nexthop_vrfid == VRF_UNKNOWN)
6760 ? -1
6761 : (int)nexthop_vrfid));
6762 }
6763 }
6764
d62a17ae 6765 if (json_paths) {
6766 if (json_nexthop_global || json_nexthop_ll) {
6767 json_nexthops = json_object_new_array();
f1aa5d8a 6768
d62a17ae 6769 if (json_nexthop_global)
6770 json_object_array_add(json_nexthops,
6771 json_nexthop_global);
f1aa5d8a 6772
d62a17ae 6773 if (json_nexthop_ll)
6774 json_object_array_add(json_nexthops,
6775 json_nexthop_ll);
f1aa5d8a 6776
d62a17ae 6777 json_object_object_add(json_path, "nexthops",
6778 json_nexthops);
6779 }
6780
6781 json_object_array_add(json_paths, json_path);
6782 } else {
6783 vty_out(vty, "\n");
65efcfce 6784#if ENABLE_BGP_VNC
d62a17ae 6785 /* prints an additional line, indented, with VNC info, if
6786 * present */
6787 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
6788 rfapi_vty_out_vncinfo(vty, p, binfo, safi);
65efcfce 6789#endif
d62a17ae 6790 }
6791}
718e3744 6792
6793/* called from terminal list command */
d62a17ae 6794void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
d7c0a89a 6795 safi_t safi, uint8_t use_json, json_object *json_ar)
d62a17ae 6796{
6797 json_object *json_status = NULL;
6798 json_object *json_net = NULL;
6799 char buff[BUFSIZ];
6800 /* Route status display. */
6801 if (use_json) {
6802 json_status = json_object_new_object();
6803 json_net = json_object_new_object();
6804 } else {
6805 vty_out(vty, "*");
6806 vty_out(vty, ">");
6807 vty_out(vty, " ");
6808 }
718e3744 6809
d62a17ae 6810 /* print prefix and mask */
6811 if (use_json)
6812 json_object_string_add(
6813 json_net, "addrPrefix",
6814 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
6815 else
9c92b5f7 6816 route_vty_out_route(p, vty, NULL);
d62a17ae 6817
6818 /* Print attribute */
6819 if (attr) {
6820 if (use_json) {
6821 if (p->family == AF_INET
6822 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6823 || safi == SAFI_EVPN
6824 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6825 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6826 || safi == SAFI_EVPN)
6827 json_object_string_add(
6828 json_net, "nextHop",
6829 inet_ntoa(
6830 attr->mp_nexthop_global_in));
6831 else
6832 json_object_string_add(
6833 json_net, "nextHop",
6834 inet_ntoa(attr->nexthop));
6835 } else if (p->family == AF_INET6
6836 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6837 char buf[BUFSIZ];
6838
6839 json_object_string_add(
6840 json_net, "netHopGloabal",
6841 inet_ntop(AF_INET6,
6842 &attr->mp_nexthop_global, buf,
6843 BUFSIZ));
6844 }
6845
6846 if (attr->flag
6847 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6848 json_object_int_add(json_net, "metric",
6849 attr->med);
6850
6851 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6852 json_object_int_add(json_net, "localPref",
6853 attr->local_pref);
6854
6855 json_object_int_add(json_net, "weight", attr->weight);
6856
6857 /* Print aspath */
6858 if (attr->aspath)
6859 json_object_string_add(json_net, "asPath",
6860 attr->aspath->str);
6861
6862 /* Print origin */
6863 json_object_string_add(json_net, "bgpOriginCode",
6864 bgp_origin_str[attr->origin]);
6865 } else {
6866 if (p->family == AF_INET
6867 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6868 || safi == SAFI_EVPN
6869 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6870 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6871 || safi == SAFI_EVPN)
6872 vty_out(vty, "%-16s",
6873 inet_ntoa(
6874 attr->mp_nexthop_global_in));
6875 else
6876 vty_out(vty, "%-16s",
6877 inet_ntoa(attr->nexthop));
6878 } else if (p->family == AF_INET6
6879 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6880 int len;
6881 char buf[BUFSIZ];
6882
6883 len = vty_out(
6884 vty, "%s",
6885 inet_ntop(AF_INET6,
6886 &attr->mp_nexthop_global, buf,
6887 BUFSIZ));
6888 len = 16 - len;
6889 if (len < 1)
6890 vty_out(vty, "\n%*s", 36, " ");
6891 else
6892 vty_out(vty, "%*s", len, " ");
6893 }
6894 if (attr->flag
6895 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6896 vty_out(vty, "%10u", attr->med);
6897 else
6898 vty_out(vty, " ");
718e3744 6899
d62a17ae 6900 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6901 vty_out(vty, "%7u", attr->local_pref);
6902 else
6903 vty_out(vty, " ");
6904
6905 vty_out(vty, "%7u ", attr->weight);
6906
6907 /* Print aspath */
6908 if (attr->aspath)
6909 aspath_print_vty(vty, "%s", attr->aspath, " ");
6910
6911 /* Print origin */
6912 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6913 }
6914 }
6915 if (use_json) {
6916 json_object_boolean_true_add(json_status, "*");
6917 json_object_boolean_true_add(json_status, ">");
6918 json_object_object_add(json_net, "appliedStatusSymbols",
6919 json_status);
6920 char buf_cut[BUFSIZ];
6921 json_object_object_add(
6922 json_ar,
6923 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
6924 json_net);
6925 } else
6926 vty_out(vty, "\n");
6927}
6928
6929void route_vty_out_tag(struct vty *vty, struct prefix *p,
6930 struct bgp_info *binfo, int display, safi_t safi,
6931 json_object *json)
6932{
6933 json_object *json_out = NULL;
6934 struct attr *attr;
6935 mpls_label_t label = MPLS_INVALID_LABEL;
6936
6937 if (!binfo->extra)
6938 return;
6939
6940 if (json)
6941 json_out = json_object_new_object();
6942
6943 /* short status lead text */
6944 route_vty_short_status_out(vty, binfo, json_out);
6945
6946 /* print prefix and mask */
6947 if (json == NULL) {
6948 if (!display)
9c92b5f7 6949 route_vty_out_route(p, vty, NULL);
d62a17ae 6950 else
6951 vty_out(vty, "%*s", 17, " ");
6952 }
6953
6954 /* Print attribute */
6955 attr = binfo->attr;
6956 if (attr) {
6957 if (((p->family == AF_INET)
6958 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 6959 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 6960 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6961 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6962 || safi == SAFI_EVPN) {
6963 if (json)
6964 json_object_string_add(
6965 json_out, "mpNexthopGlobalIn",
6966 inet_ntoa(
6967 attr->mp_nexthop_global_in));
6968 else
6969 vty_out(vty, "%-16s",
6970 inet_ntoa(
6971 attr->mp_nexthop_global_in));
6972 } else {
6973 if (json)
6974 json_object_string_add(
6975 json_out, "nexthop",
6976 inet_ntoa(attr->nexthop));
6977 else
6978 vty_out(vty, "%-16s",
6979 inet_ntoa(attr->nexthop));
6980 }
6981 } else if (((p->family == AF_INET6)
6982 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6983 || (safi == SAFI_EVPN
d62a17ae 6984 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6985 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6986 char buf_a[BUFSIZ];
6987 char buf_b[BUFSIZ];
6988 char buf_c[BUFSIZ];
6989 if (attr->mp_nexthop_len
6990 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
6991 if (json)
6992 json_object_string_add(
6993 json_out, "mpNexthopGlobalIn",
6994 inet_ntop(
6995 AF_INET6,
6996 &attr->mp_nexthop_global,
6997 buf_a, BUFSIZ));
6998 else
6999 vty_out(vty, "%s",
7000 inet_ntop(
7001 AF_INET6,
7002 &attr->mp_nexthop_global,
7003 buf_a, BUFSIZ));
7004 } else if (attr->mp_nexthop_len
7005 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7006 if (json) {
7007 inet_ntop(AF_INET6,
7008 &attr->mp_nexthop_global,
7009 buf_a, BUFSIZ);
7010 inet_ntop(AF_INET6,
7011 &attr->mp_nexthop_local,
7012 buf_b, BUFSIZ);
7013 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
7014 json_object_string_add(
7015 json_out,
7016 "mpNexthopGlobalLocal", buf_c);
7017 } else
7018 vty_out(vty, "%s(%s)",
7019 inet_ntop(
7020 AF_INET6,
7021 &attr->mp_nexthop_global,
7022 buf_a, BUFSIZ),
7023 inet_ntop(
7024 AF_INET6,
7025 &attr->mp_nexthop_local,
7026 buf_b, BUFSIZ));
7027 }
7028 }
7029 }
7030
b57ba6d2 7031 label = decode_label(&binfo->extra->label[0]);
d62a17ae 7032
7033 if (bgp_is_valid_label(&label)) {
7034 if (json) {
7035 json_object_int_add(json_out, "notag", label);
7036 json_object_array_add(json, json_out);
7037 } else {
7038 vty_out(vty, "notag/%d", label);
7039 vty_out(vty, "\n");
7040 }
7041 }
7042}
718e3744 7043
d62a17ae 7044void route_vty_out_overlay(struct vty *vty, struct prefix *p,
7045 struct bgp_info *binfo, int display,
7046 json_object *json_paths)
718e3744 7047{
d62a17ae 7048 struct attr *attr;
7049 char buf[BUFSIZ];
7050 json_object *json_path = NULL;
784d3a42 7051
d62a17ae 7052 if (json_paths)
7053 json_path = json_object_new_object();
856ca177 7054
d62a17ae 7055 if (!binfo->extra)
7056 return;
718e3744 7057
d62a17ae 7058 /* short status lead text */
7059 route_vty_short_status_out(vty, binfo, json_path);
856ca177 7060
d62a17ae 7061 /* print prefix and mask */
7062 if (!display)
9c92b5f7 7063 route_vty_out_route(p, vty, NULL);
d62a17ae 7064 else
7065 vty_out(vty, "%*s", 17, " ");
7066
7067 /* Print attribute */
7068 attr = binfo->attr;
7069 if (attr) {
7070 char buf1[BUFSIZ];
7071 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7072
7073 switch (af) {
7074 case AF_INET:
7075 vty_out(vty, "%-16s",
7076 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7077 BUFSIZ));
7078 break;
7079 case AF_INET6:
7080 vty_out(vty, "%s(%s)",
7081 inet_ntop(af, &attr->mp_nexthop_global, buf,
7082 BUFSIZ),
7083 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7084 BUFSIZ));
7085 break;
7086 default:
7087 vty_out(vty, "?");
7088 }
988258b4
QY
7089
7090 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7091
7092 vty_out(vty, "%s", str);
7093 XFREE(MTYPE_TMP, str);
7094
3714a385 7095 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
988258b4
QY
7096 vty_out(vty, "/%s",
7097 inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
3714a385 7098 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
988258b4
QY
7099 vty_out(vty, "/%s",
7100 inet_ntop(AF_INET6,
7101 &(attr->evpn_overlay.gw_ip.ipv6), buf,
7102 BUFSIZ));
7103 }
7104 if (attr->ecommunity) {
7105 char *mac = NULL;
7106 struct ecommunity_val *routermac = ecommunity_lookup(
7107 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7108 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7109 if (routermac)
7110 mac = ecom_mac2str((char *)routermac->val);
7111 if (mac) {
7112 vty_out(vty, "/%s", (char *)mac);
7113 XFREE(MTYPE_TMP, mac);
7114 }
7115 }
7116 vty_out(vty, "\n");
718e3744 7117 }
718e3744 7118
d62a17ae 7119}
718e3744 7120
d62a17ae 7121/* dampening route */
7122static void damp_route_vty_out(struct vty *vty, struct prefix *p,
7123 struct bgp_info *binfo, int display, safi_t safi,
d7c0a89a 7124 uint8_t use_json, json_object *json)
d62a17ae 7125{
7126 struct attr *attr;
7127 int len;
7128 char timebuf[BGP_UPTIME_LEN];
7129
7130 /* short status lead text */
7131 route_vty_short_status_out(vty, binfo, json);
7132
7133 /* print prefix and mask */
7134 if (!use_json) {
7135 if (!display)
9c92b5f7 7136 route_vty_out_route(p, vty, NULL);
d62a17ae 7137 else
7138 vty_out(vty, "%*s", 17, " ");
7139 }
7140
7141 len = vty_out(vty, "%s", binfo->peer->host);
7142 len = 17 - len;
7143 if (len < 1) {
7144 if (!use_json)
7145 vty_out(vty, "\n%*s", 34, " ");
7146 } else {
7147 if (use_json)
7148 json_object_int_add(json, "peerHost", len);
7149 else
7150 vty_out(vty, "%*s", len, " ");
7151 }
7152
7153 if (use_json)
7154 bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN,
7155 use_json, json);
7156 else
996c9314
LB
7157 vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7158 BGP_UPTIME_LEN,
7159 use_json, json));
d62a17ae 7160
7161 /* Print attribute */
7162 attr = binfo->attr;
7163 if (attr) {
7164 /* Print aspath */
7165 if (attr->aspath) {
7166 if (use_json)
7167 json_object_string_add(json, "asPath",
7168 attr->aspath->str);
7169 else
7170 aspath_print_vty(vty, "%s", attr->aspath, " ");
7171 }
7172
7173 /* Print origin */
7174 if (use_json)
7175 json_object_string_add(json, "origin",
7176 bgp_origin_str[attr->origin]);
7177 else
7178 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7179 }
7180 if (!use_json)
7181 vty_out(vty, "\n");
7182}
718e3744 7183
d62a17ae 7184/* flap route */
7185static void flap_route_vty_out(struct vty *vty, struct prefix *p,
7186 struct bgp_info *binfo, int display, safi_t safi,
d7c0a89a 7187 uint8_t use_json, json_object *json)
784d3a42 7188{
d62a17ae 7189 struct attr *attr;
7190 struct bgp_damp_info *bdi;
7191 char timebuf[BGP_UPTIME_LEN];
7192 int len;
784d3a42 7193
d62a17ae 7194 if (!binfo->extra)
7195 return;
784d3a42 7196
d62a17ae 7197 bdi = binfo->extra->damp_info;
784d3a42 7198
d62a17ae 7199 /* short status lead text */
7200 route_vty_short_status_out(vty, binfo, json);
784d3a42 7201
d62a17ae 7202 /* print prefix and mask */
7203 if (!use_json) {
7204 if (!display)
9c92b5f7 7205 route_vty_out_route(p, vty, NULL);
d62a17ae 7206 else
7207 vty_out(vty, "%*s", 17, " ");
7208 }
784d3a42 7209
d62a17ae 7210 len = vty_out(vty, "%s", binfo->peer->host);
7211 len = 16 - len;
7212 if (len < 1) {
7213 if (!use_json)
7214 vty_out(vty, "\n%*s", 33, " ");
7215 } else {
7216 if (use_json)
7217 json_object_int_add(json, "peerHost", len);
7218 else
7219 vty_out(vty, "%*s", len, " ");
7220 }
784d3a42 7221
d62a17ae 7222 len = vty_out(vty, "%d", bdi->flap);
7223 len = 5 - len;
7224 if (len < 1) {
7225 if (!use_json)
7226 vty_out(vty, " ");
7227 } else {
7228 if (use_json)
7229 json_object_int_add(json, "bdiFlap", len);
7230 else
7231 vty_out(vty, "%*s", len, " ");
7232 }
7233
7234 if (use_json)
7235 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7236 json);
7237 else
996c9314
LB
7238 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7239 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7240
7241 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
7242 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7243 if (use_json)
7244 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7245 BGP_UPTIME_LEN, use_json, json);
7246 else
7247 vty_out(vty, "%s ",
7248 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7249 BGP_UPTIME_LEN,
7250 use_json, json));
7251 } else {
7252 if (!use_json)
7253 vty_out(vty, "%*s ", 8, " ");
7254 }
7255
7256 /* Print attribute */
7257 attr = binfo->attr;
7258 if (attr) {
7259 /* Print aspath */
7260 if (attr->aspath) {
7261 if (use_json)
7262 json_object_string_add(json, "asPath",
7263 attr->aspath->str);
7264 else
7265 aspath_print_vty(vty, "%s", attr->aspath, " ");
7266 }
7267
7268 /* Print origin */
7269 if (use_json)
7270 json_object_string_add(json, "origin",
7271 bgp_origin_str[attr->origin]);
7272 else
7273 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7274 }
7275 if (!use_json)
7276 vty_out(vty, "\n");
7277}
7278
7279static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7280 int *first, const char *header,
7281 json_object *json_adv_to)
7282{
7283 char buf1[INET6_ADDRSTRLEN];
7284 json_object *json_peer = NULL;
7285
7286 if (json_adv_to) {
7287 /* 'advertised-to' is a dictionary of peers we have advertised
7288 * this
7289 * prefix too. The key is the peer's IP or swpX, the value is
7290 * the
7291 * hostname if we know it and "" if not.
7292 */
7293 json_peer = json_object_new_object();
7294
7295 if (peer->hostname)
7296 json_object_string_add(json_peer, "hostname",
7297 peer->hostname);
7298
7299 if (peer->conf_if)
7300 json_object_object_add(json_adv_to, peer->conf_if,
7301 json_peer);
7302 else
7303 json_object_object_add(
7304 json_adv_to,
7305 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7306 json_peer);
7307 } else {
7308 if (*first) {
7309 vty_out(vty, "%s", header);
7310 *first = 0;
7311 }
7312
7313 if (peer->hostname
7314 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7315 if (peer->conf_if)
7316 vty_out(vty, " %s(%s)", peer->hostname,
7317 peer->conf_if);
7318 else
7319 vty_out(vty, " %s(%s)", peer->hostname,
7320 sockunion2str(&peer->su, buf1,
7321 SU_ADDRSTRLEN));
7322 } else {
7323 if (peer->conf_if)
7324 vty_out(vty, " %s", peer->conf_if);
7325 else
7326 vty_out(vty, " %s",
7327 sockunion2str(&peer->su, buf1,
7328 SU_ADDRSTRLEN));
7329 }
7330 }
784d3a42
PG
7331}
7332
d62a17ae 7333void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
7334 struct bgp_info *binfo, afi_t afi, safi_t safi,
7335 json_object *json_paths)
7336{
7337 char buf[INET6_ADDRSTRLEN];
7338 char buf1[BUFSIZ];
7339#if defined(HAVE_CUMULUS)
7340 char buf2[EVPN_ROUTE_STRLEN];
7341#endif
7342 struct attr *attr;
7343 int sockunion_vty_out(struct vty *, union sockunion *);
7344 time_t tbuf;
7345 json_object *json_bestpath = NULL;
7346 json_object *json_cluster_list = NULL;
7347 json_object *json_cluster_list_list = NULL;
7348 json_object *json_ext_community = NULL;
7349 json_object *json_last_update = NULL;
7fd077aa 7350 json_object *json_pmsi = NULL;
d62a17ae 7351 json_object *json_nexthop_global = NULL;
7352 json_object *json_nexthop_ll = NULL;
7353 json_object *json_nexthops = NULL;
7354 json_object *json_path = NULL;
7355 json_object *json_peer = NULL;
7356 json_object *json_string = NULL;
7357 json_object *json_adv_to = NULL;
7358 int first = 0;
7359 struct listnode *node, *nnode;
7360 struct peer *peer;
7361 int addpath_capable;
7362 int has_adj;
7363 unsigned int first_as;
9df8b37c
PZ
7364 bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
7365 ? true
7366 : false;
d62a17ae 7367
7368 if (json_paths) {
7369 json_path = json_object_new_object();
7370 json_peer = json_object_new_object();
7371 json_nexthop_global = json_object_new_object();
7372 }
7373
7374#if defined(HAVE_CUMULUS)
7375 if (!json_paths && safi == SAFI_EVPN) {
b57ba6d2 7376 char tag_buf[30];
d62a17ae 7377
7378 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7379 vty_out(vty, " Route %s", buf2);
7380 tag_buf[0] = '\0';
b57ba6d2
MK
7381 if (binfo->extra && binfo->extra->num_labels) {
7382 bgp_evpn_label2str(binfo->extra->label,
a4d82a8a
PZ
7383 binfo->extra->num_labels, tag_buf,
7384 sizeof(tag_buf));
d62a17ae 7385 vty_out(vty, " VNI %s", tag_buf);
7386 }
7387 vty_out(vty, "\n");
7388 if (binfo->extra && binfo->extra->parent) {
7389 struct bgp_info *parent_ri;
7390 struct bgp_node *rn, *prn;
7391
7392 parent_ri = (struct bgp_info *)binfo->extra->parent;
7393 rn = parent_ri->net;
7394 if (rn && rn->prn) {
7395 prn = rn->prn;
7396 vty_out(vty, " Imported from %s:%s\n",
7397 prefix_rd2str(
7398 (struct prefix_rd *)&prn->p,
06b9f471 7399 buf1, sizeof(buf1)),
d62a17ae 7400 buf2);
7401 }
7402 }
7403 }
7404#endif
7405
7406 attr = binfo->attr;
7407
7408 if (attr) {
7409 /* Line1 display AS-path, Aggregator */
7410 if (attr->aspath) {
7411 if (json_paths) {
68e1a55b
DS
7412 if (!attr->aspath->json)
7413 aspath_str_update(attr->aspath, true);
d62a17ae 7414 json_object_lock(attr->aspath->json);
7415 json_object_object_add(json_path, "aspath",
7416 attr->aspath->json);
7417 } else {
7418 if (attr->aspath->segments)
7419 aspath_print_vty(vty, " %s",
7420 attr->aspath, "");
7421 else
7422 vty_out(vty, " Local");
7423 }
7424 }
7425
7426 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) {
7427 if (json_paths)
7428 json_object_boolean_true_add(json_path,
7429 "removed");
7430 else
7431 vty_out(vty, ", (removed)");
7432 }
7433
7434 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) {
7435 if (json_paths)
7436 json_object_boolean_true_add(json_path,
7437 "stale");
7438 else
7439 vty_out(vty, ", (stale)");
7440 }
7441
7442 if (CHECK_FLAG(attr->flag,
7443 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7444 if (json_paths) {
7445 json_object_int_add(json_path, "aggregatorAs",
7446 attr->aggregator_as);
7447 json_object_string_add(
7448 json_path, "aggregatorId",
7449 inet_ntoa(attr->aggregator_addr));
7450 } else {
7451 vty_out(vty, ", (aggregated by %u %s)",
7452 attr->aggregator_as,
7453 inet_ntoa(attr->aggregator_addr));
7454 }
7455 }
7456
7457 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7458 PEER_FLAG_REFLECTOR_CLIENT)) {
7459 if (json_paths)
7460 json_object_boolean_true_add(
7461 json_path, "rxedFromRrClient");
7462 else
7463 vty_out(vty, ", (Received from a RR-client)");
7464 }
7465
7466 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7467 PEER_FLAG_RSERVER_CLIENT)) {
7468 if (json_paths)
7469 json_object_boolean_true_add(
7470 json_path, "rxedFromRsClient");
7471 else
7472 vty_out(vty, ", (Received from a RS-client)");
7473 }
7474
7475 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7476 if (json_paths)
7477 json_object_boolean_true_add(
7478 json_path, "dampeningHistoryEntry");
7479 else
7480 vty_out(vty, ", (history entry)");
7481 } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
7482 if (json_paths)
7483 json_object_boolean_true_add(
7484 json_path, "dampeningSuppressed");
7485 else
7486 vty_out(vty, ", (suppressed due to dampening)");
7487 }
7488
7489 if (!json_paths)
7490 vty_out(vty, "\n");
7491
7492 /* Line2 display Next-hop, Neighbor, Router-id */
7493 /* Display the nexthop */
a4d82a8a
PZ
7494 if ((p->family == AF_INET || p->family == AF_ETHERNET
7495 || p->family == AF_EVPN)
d62a17ae 7496 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7497 || safi == SAFI_EVPN
7498 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7499 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7500 || safi == SAFI_EVPN) {
7501 if (json_paths)
7502 json_object_string_add(
7503 json_nexthop_global, "ip",
7504 inet_ntoa(
7505 attr->mp_nexthop_global_in));
7506 else
7507 vty_out(vty, " %s",
7508 inet_ntoa(
7509 attr->mp_nexthop_global_in));
7510 } else {
7511 if (json_paths)
7512 json_object_string_add(
7513 json_nexthop_global, "ip",
7514 inet_ntoa(attr->nexthop));
7515 else
7516 vty_out(vty, " %s",
7517 inet_ntoa(attr->nexthop));
7518 }
7519
7520 if (json_paths)
7521 json_object_string_add(json_nexthop_global,
7522 "afi", "ipv4");
7523 } else {
7524 if (json_paths) {
7525 json_object_string_add(
7526 json_nexthop_global, "ip",
7527 inet_ntop(AF_INET6,
7528 &attr->mp_nexthop_global, buf,
7529 INET6_ADDRSTRLEN));
7530 json_object_string_add(json_nexthop_global,
7531 "afi", "ipv6");
7532 json_object_string_add(json_nexthop_global,
7533 "scope", "global");
7534 } else {
7535 vty_out(vty, " %s",
7536 inet_ntop(AF_INET6,
7537 &attr->mp_nexthop_global, buf,
7538 INET6_ADDRSTRLEN));
7539 }
7540 }
7541
7542 /* Display the IGP cost or 'inaccessible' */
7543 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7544 if (json_paths)
7545 json_object_boolean_false_add(
7546 json_nexthop_global, "accessible");
7547 else
7548 vty_out(vty, " (inaccessible)");
7549 } else {
7550 if (binfo->extra && binfo->extra->igpmetric) {
7551 if (json_paths)
7552 json_object_int_add(
7553 json_nexthop_global, "metric",
7554 binfo->extra->igpmetric);
7555 else
7556 vty_out(vty, " (metric %u)",
7557 binfo->extra->igpmetric);
7558 }
7559
7560 /* IGP cost is 0, display this only for json */
7561 else {
7562 if (json_paths)
7563 json_object_int_add(json_nexthop_global,
7564 "metric", 0);
7565 }
7566
7567 if (json_paths)
7568 json_object_boolean_true_add(
7569 json_nexthop_global, "accessible");
7570 }
7571
7572 /* Display peer "from" output */
7573 /* This path was originated locally */
7574 if (binfo->peer == bgp->peer_self) {
7575
7576 if (safi == SAFI_EVPN
7577 || (p->family == AF_INET
7578 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7579 if (json_paths)
7580 json_object_string_add(
7581 json_peer, "peerId", "0.0.0.0");
7582 else
7583 vty_out(vty, " from 0.0.0.0 ");
7584 } else {
7585 if (json_paths)
7586 json_object_string_add(json_peer,
7587 "peerId", "::");
7588 else
7589 vty_out(vty, " from :: ");
7590 }
7591
7592 if (json_paths)
7593 json_object_string_add(
7594 json_peer, "routerId",
7595 inet_ntoa(bgp->router_id));
7596 else
7597 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7598 }
7599
7600 /* We RXed this path from one of our peers */
7601 else {
7602
7603 if (json_paths) {
7604 json_object_string_add(
7605 json_peer, "peerId",
7606 sockunion2str(&binfo->peer->su, buf,
7607 SU_ADDRSTRLEN));
7608 json_object_string_add(
7609 json_peer, "routerId",
7610 inet_ntop(AF_INET,
7611 &binfo->peer->remote_id, buf1,
06b9f471 7612 sizeof(buf1)));
d62a17ae 7613
7614 if (binfo->peer->hostname)
7615 json_object_string_add(
7616 json_peer, "hostname",
7617 binfo->peer->hostname);
7618
7619 if (binfo->peer->domainname)
7620 json_object_string_add(
7621 json_peer, "domainname",
7622 binfo->peer->domainname);
7623
7624 if (binfo->peer->conf_if)
7625 json_object_string_add(
7626 json_peer, "interface",
7627 binfo->peer->conf_if);
7628 } else {
7629 if (binfo->peer->conf_if) {
7630 if (binfo->peer->hostname
7631 && bgp_flag_check(
7632 binfo->peer->bgp,
7633 BGP_FLAG_SHOW_HOSTNAME))
7634 vty_out(vty, " from %s(%s)",
7635 binfo->peer->hostname,
7636 binfo->peer->conf_if);
7637 else
7638 vty_out(vty, " from %s",
7639 binfo->peer->conf_if);
7640 } else {
7641 if (binfo->peer->hostname
7642 && bgp_flag_check(
7643 binfo->peer->bgp,
7644 BGP_FLAG_SHOW_HOSTNAME))
7645 vty_out(vty, " from %s(%s)",
7646 binfo->peer->hostname,
7647 binfo->peer->host);
7648 else
7649 vty_out(vty, " from %s",
7650 sockunion2str(
7651 &binfo->peer
7652 ->su,
7653 buf,
7654 SU_ADDRSTRLEN));
7655 }
7656
7657 if (attr->flag
7658 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7659 vty_out(vty, " (%s)",
7660 inet_ntoa(attr->originator_id));
7661 else
7662 vty_out(vty, " (%s)",
7663 inet_ntop(
7664 AF_INET,
7665 &binfo->peer->remote_id,
06b9f471 7666 buf1, sizeof(buf1)));
d62a17ae 7667 }
7668 }
7669
9df8b37c
PZ
7670 /*
7671 * Note when vrfid of nexthop is different from that of prefix
7672 */
7673 if (binfo->extra && binfo->extra->bgp_orig) {
7674 vrf_id_t nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
7675
7676 if (json_paths) {
7677 const char *vn;
7678
7679 if (binfo->extra->bgp_orig->inst_type ==
7680 BGP_INSTANCE_TYPE_DEFAULT)
7681
7682 vn = "Default";
7683 else
7684 vn = binfo->extra->bgp_orig->name;
7685
7686 json_object_string_add(json_path, "nhVrfName",
7687 vn);
7688
7689 if (nexthop_vrfid == VRF_UNKNOWN) {
7690 json_object_int_add(json_path,
7691 "nhVrfId", -1);
7692 } else {
7693 json_object_int_add(json_path,
7694 "nhVrfId", (int)nexthop_vrfid);
7695 }
7696 } else {
7697 if (nexthop_vrfid == VRF_UNKNOWN)
7698 vty_out(vty, " vrf ?");
7699 else
7700 vty_out(vty, " vrf %u", nexthop_vrfid);
7701 }
7702 }
7703
7704 if (nexthop_self) {
7705 if (json_paths) {
7706 json_object_boolean_true_add(json_path,
7707 "announceNexthopSelf");
7708 } else {
7709 vty_out(vty, " announce-nh-self");
7710 }
7711 }
7712
d62a17ae 7713 if (!json_paths)
7714 vty_out(vty, "\n");
7715
7716 /* display the link-local nexthop */
7717 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7718 if (json_paths) {
7719 json_nexthop_ll = json_object_new_object();
7720 json_object_string_add(
7721 json_nexthop_ll, "ip",
7722 inet_ntop(AF_INET6,
7723 &attr->mp_nexthop_local, buf,
7724 INET6_ADDRSTRLEN));
7725 json_object_string_add(json_nexthop_ll, "afi",
7726 "ipv6");
7727 json_object_string_add(json_nexthop_ll, "scope",
7728 "link-local");
7729
7730 json_object_boolean_true_add(json_nexthop_ll,
7731 "accessible");
7732
7733 if (!attr->mp_nexthop_prefer_global)
7734 json_object_boolean_true_add(
7735 json_nexthop_ll, "used");
7736 else
7737 json_object_boolean_true_add(
7738 json_nexthop_global, "used");
7739 } else {
7740 vty_out(vty, " (%s) %s\n",
7741 inet_ntop(AF_INET6,
7742 &attr->mp_nexthop_local, buf,
7743 INET6_ADDRSTRLEN),
7744 attr->mp_nexthop_prefer_global
7745 ? "(prefer-global)"
7746 : "(used)");
7747 }
7748 }
7749 /* If we do not have a link-local nexthop then we must flag the
7750 global as "used" */
7751 else {
7752 if (json_paths)
7753 json_object_boolean_true_add(
7754 json_nexthop_global, "used");
7755 }
718e3744 7756
d62a17ae 7757 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7758 * Int/Ext/Local, Atomic, best */
7759 if (json_paths)
7760 json_object_string_add(
7761 json_path, "origin",
7762 bgp_origin_long_str[attr->origin]);
7763 else
7764 vty_out(vty, " Origin %s",
7765 bgp_origin_long_str[attr->origin]);
7766
7767 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
7768 if (json_paths)
7769 json_object_int_add(json_path, "med",
7770 attr->med);
7771 else
7772 vty_out(vty, ", metric %u", attr->med);
7773 }
718e3744 7774
d62a17ae 7775 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7776 if (json_paths)
7777 json_object_int_add(json_path, "localpref",
7778 attr->local_pref);
7779 else
7780 vty_out(vty, ", localpref %u",
7781 attr->local_pref);
7782 } else {
7783 if (json_paths)
7784 json_object_int_add(json_path, "localpref",
7785 bgp->default_local_pref);
7786 else
7787 vty_out(vty, ", localpref %u",
7788 bgp->default_local_pref);
7789 }
718e3744 7790
d62a17ae 7791 if (attr->weight != 0) {
7792 if (json_paths)
7793 json_object_int_add(json_path, "weight",
7794 attr->weight);
7795 else
7796 vty_out(vty, ", weight %u", attr->weight);
7797 }
718e3744 7798
d62a17ae 7799 if (attr->tag != 0) {
7800 if (json_paths)
7801 json_object_int_add(json_path, "tag",
7802 attr->tag);
7803 else
7804 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7805 attr->tag);
7806 }
718e3744 7807
d62a17ae 7808 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7809 if (json_paths)
7810 json_object_boolean_false_add(json_path,
7811 "valid");
7812 else
7813 vty_out(vty, ", invalid");
7814 } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7815 if (json_paths)
7816 json_object_boolean_true_add(json_path,
7817 "valid");
7818 else
7819 vty_out(vty, ", valid");
7820 }
718e3744 7821
d62a17ae 7822 if (binfo->peer != bgp->peer_self) {
7823 if (binfo->peer->as == binfo->peer->local_as) {
7824 if (CHECK_FLAG(bgp->config,
7825 BGP_CONFIG_CONFEDERATION)) {
7826 if (json_paths)
7827 json_object_string_add(
7828 json_peer, "type",
7829 "confed-internal");
7830 else
7831 vty_out(vty,
7832 ", confed-internal");
7833 } else {
7834 if (json_paths)
7835 json_object_string_add(
7836 json_peer, "type",
7837 "internal");
7838 else
7839 vty_out(vty, ", internal");
7840 }
7841 } else {
7842 if (bgp_confederation_peers_check(
7843 bgp, binfo->peer->as)) {
7844 if (json_paths)
7845 json_object_string_add(
7846 json_peer, "type",
7847 "confed-external");
7848 else
7849 vty_out(vty,
7850 ", confed-external");
7851 } else {
7852 if (json_paths)
7853 json_object_string_add(
7854 json_peer, "type",
7855 "external");
7856 else
7857 vty_out(vty, ", external");
7858 }
7859 }
7860 } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) {
7861 if (json_paths) {
7862 json_object_boolean_true_add(json_path,
7863 "aggregated");
7864 json_object_boolean_true_add(json_path,
7865 "local");
7866 } else {
7867 vty_out(vty, ", aggregated, local");
7868 }
7869 } else if (binfo->type != ZEBRA_ROUTE_BGP) {
7870 if (json_paths)
7871 json_object_boolean_true_add(json_path,
7872 "sourced");
7873 else
7874 vty_out(vty, ", sourced");
7875 } else {
7876 if (json_paths) {
7877 json_object_boolean_true_add(json_path,
7878 "sourced");
7879 json_object_boolean_true_add(json_path,
7880 "local");
7881 } else {
7882 vty_out(vty, ", sourced, local");
7883 }
7884 }
718e3744 7885
d62a17ae 7886 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
7887 if (json_paths)
7888 json_object_boolean_true_add(json_path,
7889 "atomicAggregate");
7890 else
7891 vty_out(vty, ", atomic-aggregate");
7892 }
718e3744 7893
d62a17ae 7894 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)
7895 || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)
7896 && bgp_info_mpath_count(binfo))) {
7897 if (json_paths)
7898 json_object_boolean_true_add(json_path,
7899 "multipath");
7900 else
7901 vty_out(vty, ", multipath");
7902 }
856ca177 7903
d62a17ae 7904 // Mark the bestpath(s)
7905 if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) {
7906 first_as = aspath_get_first_as(attr->aspath);
7907
7908 if (json_paths) {
7909 if (!json_bestpath)
7910 json_bestpath =
7911 json_object_new_object();
7912 json_object_int_add(json_bestpath,
7913 "bestpathFromAs", first_as);
7914 } else {
7915 if (first_as)
fb2b0934 7916 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 7917 first_as);
7918 else
7919 vty_out(vty,
7920 ", bestpath-from-AS Local");
7921 }
7922 }
718e3744 7923
d62a17ae 7924 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) {
7925 if (json_paths) {
7926 if (!json_bestpath)
7927 json_bestpath =
7928 json_object_new_object();
7929 json_object_boolean_true_add(json_bestpath,
7930 "overall");
7931 } else
7932 vty_out(vty, ", best");
7933 }
718e3744 7934
d62a17ae 7935 if (json_bestpath)
7936 json_object_object_add(json_path, "bestpath",
7937 json_bestpath);
7938
7939 if (!json_paths)
7940 vty_out(vty, "\n");
7941
7942 /* Line 4 display Community */
7943 if (attr->community) {
7944 if (json_paths) {
a69ea8ae 7945 if (!attr->community->json)
a4d82a8a 7946 community_str(attr->community, true);
d62a17ae 7947 json_object_lock(attr->community->json);
7948 json_object_object_add(json_path, "community",
7949 attr->community->json);
7950 } else {
7951 vty_out(vty, " Community: %s\n",
7952 attr->community->str);
7953 }
7954 }
718e3744 7955
d62a17ae 7956 /* Line 5 display Extended-community */
7957 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7958 if (json_paths) {
7959 json_ext_community = json_object_new_object();
7960 json_object_string_add(json_ext_community,
7961 "string",
7962 attr->ecommunity->str);
7963 json_object_object_add(json_path,
7964 "extendedCommunity",
7965 json_ext_community);
7966 } else {
7967 vty_out(vty, " Extended Community: %s\n",
7968 attr->ecommunity->str);
7969 }
7970 }
adbac85e 7971
d62a17ae 7972 /* Line 6 display Large community */
b96879c0
DS
7973 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
7974 if (json_paths) {
8d9b8ed9
PM
7975 if (!attr->lcommunity->json)
7976 lcommunity_str(attr->lcommunity, true);
7977 json_object_lock(attr->lcommunity->json);
b96879c0
DS
7978 json_object_object_add(json_path,
7979 "largeCommunity",
8d9b8ed9 7980 attr->lcommunity->json);
b96879c0
DS
7981 } else {
7982 vty_out(vty, " Large Community: %s\n",
7983 attr->lcommunity->str);
7984 }
7985 }
d62a17ae 7986
7987 /* Line 7 display Originator, Cluster-id */
7988 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7989 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
7990 if (attr->flag
7991 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
7992 if (json_paths)
7993 json_object_string_add(
7994 json_path, "originatorId",
7995 inet_ntoa(attr->originator_id));
7996 else
7997 vty_out(vty, " Originator: %s",
7998 inet_ntoa(attr->originator_id));
7999 }
8000
8001 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
8002 int i;
8003
8004 if (json_paths) {
8005 json_cluster_list =
8006 json_object_new_object();
8007 json_cluster_list_list =
8008 json_object_new_array();
8009
8010 for (i = 0;
8011 i < attr->cluster->length / 4;
8012 i++) {
8013 json_string = json_object_new_string(
8014 inet_ntoa(
8015 attr->cluster->list
8016 [i]));
8017 json_object_array_add(
8018 json_cluster_list_list,
8019 json_string);
8020 }
8021
8022 /* struct cluster_list does not have
8023 "str" variable like
8024 * aspath and community do. Add this
8025 someday if someone
8026 * asks for it.
8027 json_object_string_add(json_cluster_list,
8028 "string", attr->cluster->str);
8029 */
8030 json_object_object_add(
8031 json_cluster_list, "list",
8032 json_cluster_list_list);
8033 json_object_object_add(
8034 json_path, "clusterList",
8035 json_cluster_list);
8036 } else {
8037 vty_out(vty, ", Cluster list: ");
8038
8039 for (i = 0;
8040 i < attr->cluster->length / 4;
8041 i++) {
8042 vty_out(vty, "%s ",
8043 inet_ntoa(
8044 attr->cluster->list
8045 [i]));
8046 }
8047 }
8048 }
8049
8050 if (!json_paths)
8051 vty_out(vty, "\n");
8052 }
adbac85e 8053
d62a17ae 8054 if (binfo->extra && binfo->extra->damp_info)
8055 bgp_damp_info_vty(vty, binfo, json_path);
8056
8057/* Remote Label */
8c197128 8058#if defined(HAVE_CUMULUS)
b57ba6d2 8059 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0])
d62a17ae 8060 && safi != SAFI_EVPN)
8061#else
b57ba6d2 8062 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0]))
8c197128 8063#endif
d62a17ae 8064 {
a4d82a8a
PZ
8065 mpls_label_t label =
8066 label_pton(&binfo->extra->label[0]);
d62a17ae 8067 if (json_paths)
8068 json_object_int_add(json_path, "remoteLabel",
8069 label);
8070 else
8071 vty_out(vty, " Remote label: %d\n", label);
8072 }
b05a1c8b 8073
d62a17ae 8074 /* Label Index */
8075 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8076 if (json_paths)
8077 json_object_int_add(json_path, "labelIndex",
8078 attr->label_index);
8079 else
8080 vty_out(vty, " Label Index: %d\n",
8081 attr->label_index);
8082 }
520d5d76 8083
d62a17ae 8084 /* Line 8 display Addpath IDs */
8085 if (binfo->addpath_rx_id || binfo->addpath_tx_id) {
8086 if (json_paths) {
8087 json_object_int_add(json_path, "addpathRxId",
8088 binfo->addpath_rx_id);
8089 json_object_int_add(json_path, "addpathTxId",
8090 binfo->addpath_tx_id);
8091 } else {
8092 vty_out(vty, " AddPath ID: RX %u, TX %u\n",
8093 binfo->addpath_rx_id,
8094 binfo->addpath_tx_id);
8095 }
8096 }
718e3744 8097
d62a17ae 8098 /* If we used addpath to TX a non-bestpath we need to display
8099 * "Advertised to" on a path-by-path basis */
8100 if (bgp->addpath_tx_used[afi][safi]) {
8101 first = 1;
8102
8103 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8104 addpath_capable =
8105 bgp_addpath_encode_tx(peer, afi, safi);
8106 has_adj = bgp_adj_out_lookup(
8107 peer, binfo->net, binfo->addpath_tx_id);
8108
8109 if ((addpath_capable && has_adj)
8110 || (!addpath_capable && has_adj
8111 && CHECK_FLAG(binfo->flags,
8112 BGP_INFO_SELECTED))) {
8113 if (json_path && !json_adv_to)
8114 json_adv_to =
8115 json_object_new_object();
8116
8117 route_vty_out_advertised_to(
8118 vty, peer, &first,
8119 " Advertised to:",
8120 json_adv_to);
8121 }
8122 }
8123
8124 if (json_path) {
8125 if (json_adv_to) {
8126 json_object_object_add(json_path,
8127 "advertisedTo",
8128 json_adv_to);
8129 }
8130 } else {
8131 if (!first) {
8132 vty_out(vty, "\n");
8133 }
8134 }
8135 }
b05a1c8b 8136
d62a17ae 8137 /* Line 9 display Uptime */
8138 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
8139 if (json_paths) {
8140 json_last_update = json_object_new_object();
8141 json_object_int_add(json_last_update, "epoch", tbuf);
8142 json_object_string_add(json_last_update, "string",
8143 ctime(&tbuf));
8144 json_object_object_add(json_path, "lastUpdate",
8145 json_last_update);
8146 } else
8147 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 8148
8149 /* Line 10 display PMSI tunnel attribute, if present */
8150 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 8151 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
8152 attr->pmsi_tnl_type,
8153 PMSI_TNLTYPE_STR_DEFAULT);
8154
7fd077aa 8155 if (json_paths) {
8156 json_pmsi = json_object_new_object();
b7d08f5a 8157 json_object_string_add(json_pmsi,
8158 "tunnelType", str);
7fd077aa 8159 json_object_object_add(json_path, "pmsi",
8160 json_pmsi);
8161 } else
8162 vty_out(vty, " PMSI Tunnel Type: %s\n",
b7d08f5a 8163 str);
7fd077aa 8164 }
8165
d62a17ae 8166 }
f1aa5d8a 8167
d62a17ae 8168 /* We've constructed the json object for this path, add it to the json
8169 * array of paths
8170 */
8171 if (json_paths) {
8172 if (json_nexthop_global || json_nexthop_ll) {
8173 json_nexthops = json_object_new_array();
f1aa5d8a 8174
d62a17ae 8175 if (json_nexthop_global)
8176 json_object_array_add(json_nexthops,
8177 json_nexthop_global);
f1aa5d8a 8178
d62a17ae 8179 if (json_nexthop_ll)
8180 json_object_array_add(json_nexthops,
8181 json_nexthop_ll);
f1aa5d8a 8182
d62a17ae 8183 json_object_object_add(json_path, "nexthops",
8184 json_nexthops);
8185 }
8186
8187 json_object_object_add(json_path, "peer", json_peer);
8188 json_object_array_add(json_paths, json_path);
8189 } else
8190 vty_out(vty, "\n");
b366b518
BB
8191}
8192
96ade3ed 8193#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8194#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8195#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8196
d62a17ae 8197static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8198 const char *prefix_list_str, afi_t afi,
8199 safi_t safi, enum bgp_show_type type);
8200static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8201 const char *filter, afi_t afi, safi_t safi,
8202 enum bgp_show_type type);
8203static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8204 const char *rmap_str, afi_t afi, safi_t safi,
8205 enum bgp_show_type type);
8206static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8207 const char *com, int exact, afi_t afi,
8208 safi_t safi);
8209static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8210 const char *prefix, afi_t afi, safi_t safi,
8211 enum bgp_show_type type);
a4d82a8a
PZ
8212static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
8213 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
8214static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8215 const char *comstr, int exact, afi_t afi,
d62a17ae 8216 safi_t safi);
8217
1ae44dfc
LB
8218
8219static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8220 struct bgp_table *table, enum bgp_show_type type,
d7c0a89a 8221 void *output_arg, uint8_t use_json, char *rd,
a4d82a8a
PZ
8222 int is_last, unsigned long *output_cum,
8223 unsigned long *total_cum,
9386b588 8224 unsigned long *json_header_depth)
d62a17ae 8225{
8226 struct bgp_info *ri;
8227 struct bgp_node *rn;
8228 int header = 1;
8229 int display;
1ae44dfc
LB
8230 unsigned long output_count = 0;
8231 unsigned long total_count = 0;
d62a17ae 8232 struct prefix *p;
8233 char buf[BUFSIZ];
8234 char buf2[BUFSIZ];
8235 json_object *json_paths = NULL;
8236 int first = 1;
8237
1ae44dfc
LB
8238 if (output_cum && *output_cum != 0)
8239 header = 0;
8240
9386b588 8241 if (use_json && !*json_header_depth) {
d62a17ae 8242 vty_out(vty,
66f80d74
DS
8243 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8244 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
a8bf7d9c 8245 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
d62a17ae 8246 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
8247 : bgp->name,
8248 table->version, inet_ntoa(bgp->router_id));
9386b588
PZ
8249 *json_header_depth = 2;
8250 if (rd) {
445c2480 8251 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
8252 ++*json_header_depth;
8253 }
d62a17ae 8254 json_paths = json_object_new_object();
8255 }
718e3744 8256
445c2480
DS
8257 if (use_json && rd) {
8258 vty_out(vty, " \"%s\" : { ", rd);
8259 }
8260
d62a17ae 8261 /* Start processing of routes. */
98ce9a06
DS
8262 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
8263 if (rn->info == NULL)
8264 continue;
d62a17ae 8265
98ce9a06 8266 display = 0;
98ce9a06
DS
8267 if (use_json)
8268 json_paths = json_object_new_array();
8269 else
8270 json_paths = NULL;
d62a17ae 8271
98ce9a06
DS
8272 for (ri = rn->info; ri; ri = ri->next) {
8273 total_count++;
8274 if (type == bgp_show_type_flap_statistics
8275 || type == bgp_show_type_flap_neighbor
8276 || type == bgp_show_type_dampend_paths
8277 || type == bgp_show_type_damp_neighbor) {
a4d82a8a 8278 if (!(ri->extra && ri->extra->damp_info))
98ce9a06
DS
8279 continue;
8280 }
8281 if (type == bgp_show_type_regexp) {
8282 regex_t *regex = output_arg;
d62a17ae 8283
98ce9a06
DS
8284 if (bgp_regexec(regex, ri->attr->aspath)
8285 == REG_NOMATCH)
8286 continue;
8287 }
8288 if (type == bgp_show_type_prefix_list) {
8289 struct prefix_list *plist = output_arg;
d62a17ae 8290
98ce9a06
DS
8291 if (prefix_list_apply(plist, &rn->p)
8292 != PREFIX_PERMIT)
8293 continue;
8294 }
8295 if (type == bgp_show_type_filter_list) {
8296 struct as_list *as_list = output_arg;
d62a17ae 8297
98ce9a06
DS
8298 if (as_list_apply(as_list, ri->attr->aspath)
8299 != AS_FILTER_PERMIT)
8300 continue;
8301 }
8302 if (type == bgp_show_type_route_map) {
8303 struct route_map *rmap = output_arg;
8304 struct bgp_info binfo;
8305 struct attr dummy_attr;
8306 int ret;
d62a17ae 8307
98ce9a06 8308 bgp_attr_dup(&dummy_attr, ri->attr);
d62a17ae 8309
98ce9a06
DS
8310 binfo.peer = ri->peer;
8311 binfo.attr = &dummy_attr;
d62a17ae 8312
a4d82a8a
PZ
8313 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
8314 &binfo);
98ce9a06
DS
8315 if (ret == RMAP_DENYMATCH)
8316 continue;
8317 }
8318 if (type == bgp_show_type_neighbor
8319 || type == bgp_show_type_flap_neighbor
8320 || type == bgp_show_type_damp_neighbor) {
8321 union sockunion *su = output_arg;
8322
8323 if (ri->peer == NULL
8324 || ri->peer->su_remote == NULL
a4d82a8a 8325 || !sockunion_same(ri->peer->su_remote, su))
98ce9a06
DS
8326 continue;
8327 }
8328 if (type == bgp_show_type_cidr_only) {
d7c0a89a 8329 uint32_t destination;
d62a17ae 8330
98ce9a06
DS
8331 destination = ntohl(rn->p.u.prefix4.s_addr);
8332 if (IN_CLASSC(destination)
8333 && rn->p.prefixlen == 24)
8334 continue;
8335 if (IN_CLASSB(destination)
8336 && rn->p.prefixlen == 16)
8337 continue;
8338 if (IN_CLASSA(destination)
8339 && rn->p.prefixlen == 8)
8340 continue;
8341 }
8342 if (type == bgp_show_type_prefix_longer) {
8343 struct prefix *p = output_arg;
d62a17ae 8344
98ce9a06
DS
8345 if (!prefix_match(p, &rn->p))
8346 continue;
8347 }
8348 if (type == bgp_show_type_community_all) {
8349 if (!ri->attr->community)
8350 continue;
8351 }
8352 if (type == bgp_show_type_community) {
8353 struct community *com = output_arg;
d62a17ae 8354
98ce9a06
DS
8355 if (!ri->attr->community
8356 || !community_match(ri->attr->community,
8357 com))
8358 continue;
8359 }
8360 if (type == bgp_show_type_community_exact) {
8361 struct community *com = output_arg;
d62a17ae 8362
98ce9a06 8363 if (!ri->attr->community
a4d82a8a 8364 || !community_cmp(ri->attr->community, com))
98ce9a06
DS
8365 continue;
8366 }
8367 if (type == bgp_show_type_community_list) {
8368 struct community_list *list = output_arg;
d62a17ae 8369
a4d82a8a
PZ
8370 if (!community_list_match(ri->attr->community,
8371 list))
98ce9a06
DS
8372 continue;
8373 }
a4d82a8a 8374 if (type == bgp_show_type_community_list_exact) {
98ce9a06 8375 struct community_list *list = output_arg;
d62a17ae 8376
98ce9a06
DS
8377 if (!community_list_exact_match(
8378 ri->attr->community, list))
8379 continue;
8380 }
8381 if (type == bgp_show_type_lcommunity) {
8382 struct lcommunity *lcom = output_arg;
d62a17ae 8383
98ce9a06
DS
8384 if (!ri->attr->lcommunity
8385 || !lcommunity_match(ri->attr->lcommunity,
8386 lcom))
8387 continue;
8388 }
8389 if (type == bgp_show_type_lcommunity_list) {
8390 struct community_list *list = output_arg;
d62a17ae 8391
a4d82a8a
PZ
8392 if (!lcommunity_list_match(ri->attr->lcommunity,
8393 list))
98ce9a06
DS
8394 continue;
8395 }
8396 if (type == bgp_show_type_lcommunity_all) {
8397 if (!ri->attr->lcommunity)
8398 continue;
8399 }
8400 if (type == bgp_show_type_dampend_paths
8401 || type == bgp_show_type_damp_neighbor) {
8402 if (!CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)
8403 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
8404 continue;
8405 }
8406
8407 if (!use_json && header) {
996c9314 8408 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 8409 ", local router ID is %s, vrf id ",
98ce9a06
DS
8410 table->version,
8411 inet_ntoa(bgp->router_id));
9df8b37c
PZ
8412 if (bgp->vrf_id == VRF_UNKNOWN)
8413 vty_out(vty, "%s", VRFID_NONE_STR);
8414 else
8415 vty_out(vty, "%u", bgp->vrf_id);
8416 vty_out(vty, "\n");
98ce9a06 8417 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 8418 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 8419 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8420 if (type == bgp_show_type_dampend_paths
8421 || type == bgp_show_type_damp_neighbor)
98ce9a06 8422 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
8423 else if (type == bgp_show_type_flap_statistics
8424 || type == bgp_show_type_flap_neighbor)
98ce9a06 8425 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8426 else
98ce9a06
DS
8427 vty_out(vty, BGP_SHOW_HEADER);
8428 header = 0;
d62a17ae 8429 }
98ce9a06
DS
8430 if (rd != NULL && !display && !output_count) {
8431 if (!use_json)
8432 vty_out(vty,
8433 "Route Distinguisher: %s\n",
8434 rd);
d62a17ae 8435 }
98ce9a06
DS
8436 if (type == bgp_show_type_dampend_paths
8437 || type == bgp_show_type_damp_neighbor)
8438 damp_route_vty_out(vty, &rn->p, ri, display,
a4d82a8a 8439 safi, use_json, json_paths);
98ce9a06
DS
8440 else if (type == bgp_show_type_flap_statistics
8441 || type == bgp_show_type_flap_neighbor)
8442 flap_route_vty_out(vty, &rn->p, ri, display,
a4d82a8a 8443 safi, use_json, json_paths);
98ce9a06 8444 else
a4d82a8a
PZ
8445 route_vty_out(vty, &rn->p, ri, display, safi,
8446 json_paths);
98ce9a06 8447 display++;
d62a17ae 8448 }
8449
98ce9a06
DS
8450 if (display) {
8451 output_count++;
8452 if (!use_json)
8453 continue;
8454
8455 p = &rn->p;
8456 sprintf(buf2, "%s/%d",
a4d82a8a 8457 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
98ce9a06 8458 p->prefixlen);
8cc84563
DS
8459 if (first)
8460 vty_out(vty, "\"%s\": ", buf2);
8461 else
8462 vty_out(vty, ",\"%s\": ", buf2);
8463
98ce9a06 8464 vty_out(vty, "%s",
23b2a7ef 8465 json_object_to_json_string(json_paths));
98ce9a06 8466 json_object_free(json_paths);
449feb8e 8467 json_paths = NULL;
98ce9a06
DS
8468 first = 0;
8469 }
8470 }
8471
1ae44dfc
LB
8472 if (output_cum) {
8473 output_count += *output_cum;
8474 *output_cum = output_count;
8475 }
8476 if (total_cum) {
8477 total_count += *total_cum;
8478 *total_cum = total_count;
8479 }
d62a17ae 8480 if (use_json) {
449feb8e
DS
8481 if (json_paths)
8482 json_object_free(json_paths);
9386b588 8483 if (rd) {
a4d82a8a 8484 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
8485 }
8486 if (is_last) {
a4d82a8a
PZ
8487 unsigned long i;
8488 for (i = 0; i < *json_header_depth; ++i)
8489 vty_out(vty, " } ");
9386b588 8490 }
d62a17ae 8491 } else {
1ae44dfc
LB
8492 if (is_last) {
8493 /* No route is displayed */
8494 if (output_count == 0) {
8495 if (type == bgp_show_type_normal)
8496 vty_out(vty,
8497 "No BGP prefixes displayed, %ld exist\n",
8498 total_count);
8499 } else
d62a17ae 8500 vty_out(vty,
1ae44dfc
LB
8501 "\nDisplayed %ld routes and %ld total paths\n",
8502 output_count, total_count);
8503 }
d62a17ae 8504 }
718e3744 8505
d62a17ae 8506 return CMD_SUCCESS;
718e3744 8507}
8508
1ae44dfc
LB
8509int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8510 struct bgp_table *table, struct prefix_rd *prd_match,
8511 enum bgp_show_type type, void *output_arg,
d7c0a89a 8512 uint8_t use_json)
1ae44dfc
LB
8513{
8514 struct bgp_node *rn, *next;
8515 unsigned long output_cum = 0;
8516 unsigned long total_cum = 0;
9386b588 8517 unsigned long json_header_depth = 0;
0136788c
LB
8518 bool show_msg;
8519
8520 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
8521
8522 for (rn = bgp_table_top(table); rn; rn = next) {
8523 next = bgp_route_next(rn);
8524 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8525 continue;
8526 if (rn->info != NULL) {
8527 struct prefix_rd prd;
06b9f471 8528 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8529
8530 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8531 prefix_rd2str(&prd, rd, sizeof(rd));
1ae44dfc 8532 bgp_show_table(vty, bgp, safi, rn->info, type,
a4d82a8a 8533 output_arg, use_json, rd, next == NULL,
9386b588
PZ
8534 &output_cum, &total_cum,
8535 &json_header_depth);
0136788c
LB
8536 if (next == NULL)
8537 show_msg = false;
1ae44dfc
LB
8538 }
8539 }
0136788c
LB
8540 if (show_msg) {
8541 if (output_cum == 0)
8542 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
8543 total_cum);
8544 else
8545 vty_out(vty,
8546 "\nDisplayed %ld routes and %ld total paths\n",
8547 output_cum, total_cum);
8548 }
1ae44dfc
LB
8549 return CMD_SUCCESS;
8550}
d62a17ae 8551static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
d7c0a89a 8552 enum bgp_show_type type, void *output_arg, uint8_t use_json)
fee0f4c6 8553{
d62a17ae 8554 struct bgp_table *table;
9386b588 8555 unsigned long json_header_depth = 0;
fee0f4c6 8556
d62a17ae 8557 if (bgp == NULL) {
8558 bgp = bgp_get_default();
8559 }
fee0f4c6 8560
d62a17ae 8561 if (bgp == NULL) {
8562 if (!use_json)
8563 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8564 else
8565 vty_out(vty, "{}\n");
d62a17ae 8566 return CMD_WARNING;
8567 }
4dd6177e 8568
1ae44dfc 8569 table = bgp->rib[afi][safi];
d62a17ae 8570 /* use MPLS and ENCAP specific shows until they are merged */
8571 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
8572 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
8573 output_arg, use_json);
d62a17ae 8574 }
dba3c1d3
PG
8575
8576 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
8577 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
8578 output_arg, use_json,
8579 1, NULL, NULL);
8580 }
d62a17ae 8581 /* labeled-unicast routes live in the unicast table */
8582 else if (safi == SAFI_LABELED_UNICAST)
8583 safi = SAFI_UNICAST;
fee0f4c6 8584
1ae44dfc 8585 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 8586 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 8587}
8588
d62a17ae 8589static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
d7c0a89a 8590 safi_t safi, uint8_t use_json)
f186de26 8591{
d62a17ae 8592 struct listnode *node, *nnode;
8593 struct bgp *bgp;
8594 int is_first = 1;
f186de26 8595
d62a17ae 8596 if (use_json)
8597 vty_out(vty, "{\n");
9f689658 8598
d62a17ae 8599 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
8600 if (use_json) {
8601 if (!is_first)
8602 vty_out(vty, ",\n");
8603 else
8604 is_first = 0;
8605
8606 vty_out(vty, "\"%s\":",
8607 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8608 ? "Default"
8609 : bgp->name);
8610 } else {
8611 vty_out(vty, "\nInstance %s:\n",
8612 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8613 ? "Default"
8614 : bgp->name);
8615 }
8616 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8617 use_json);
8618 }
9f689658 8619
d62a17ae 8620 if (use_json)
8621 vty_out(vty, "}\n");
f186de26 8622}
8623
718e3744 8624/* Header of detailed BGP route information */
d62a17ae 8625void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8626 struct bgp_node *rn, struct prefix_rd *prd,
8627 afi_t afi, safi_t safi, json_object *json)
8628{
8629 struct bgp_info *ri;
8630 struct prefix *p;
8631 struct peer *peer;
8632 struct listnode *node, *nnode;
06b9f471 8633 char buf1[RD_ADDRSTRLEN];
d62a17ae 8634 char buf2[INET6_ADDRSTRLEN];
8c197128 8635#if defined(HAVE_CUMULUS)
d62a17ae 8636 char buf3[EVPN_ROUTE_STRLEN];
8c197128 8637#endif
0291c246 8638 char prefix_str[BUFSIZ];
d62a17ae 8639 int count = 0;
8640 int best = 0;
8641 int suppress = 0;
8642 int no_export = 0;
8643 int no_advertise = 0;
8644 int local_as = 0;
8645 int first = 1;
8646 int has_valid_label = 0;
8647 mpls_label_t label = 0;
8648 json_object *json_adv_to = NULL;
9bedbb1e 8649
d62a17ae 8650 p = &rn->p;
8651 has_valid_label = bgp_is_valid_label(&rn->local_label);
8652
8653 if (has_valid_label)
8654 label = label_pton(&rn->local_label);
8655
8656 if (json) {
8657 if (has_valid_label)
8658 json_object_int_add(json, "localLabel", label);
8659
60466a63
QY
8660 json_object_string_add(
8661 json, "prefix",
8662 prefix2str(p, prefix_str, sizeof(prefix_str)));
d62a17ae 8663 } else {
8664#if defined(HAVE_CUMULUS)
8665 if (safi == SAFI_EVPN)
8666 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 8667 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 8668 : "",
8669 prd ? ":" : "",
8670 bgp_evpn_route2str((struct prefix_evpn *)p,
8671 buf3, sizeof(buf3)));
8672 else
8673 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8674 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8675 ? prefix_rd2str(prd, buf1,
06b9f471 8676 sizeof(buf1))
d62a17ae 8677 : ""),
8678 safi == SAFI_MPLS_VPN ? ":" : "",
8679 inet_ntop(p->family, &p->u.prefix, buf2,
8680 INET6_ADDRSTRLEN),
8681 p->prefixlen);
520d5d76 8682#else
d62a17ae 8683 if (p->family == AF_ETHERNET)
8684 prefix2str(p, buf2, INET6_ADDRSTRLEN);
8685 else
8686 inet_ntop(p->family, &p->u.prefix, buf2,
8687 INET6_ADDRSTRLEN);
8688 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8689 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8690 || safi == SAFI_EVPN)
a4d82a8a
PZ
8691 ? prefix_rd2str(prd, buf1, sizeof(buf1))
8692 : ""),
d62a17ae 8693 ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":"
8694 : "",
8695 buf2, p->prefixlen);
520d5d76 8696#endif
cd1964ff 8697
d62a17ae 8698 if (has_valid_label)
8699 vty_out(vty, "Local label: %d\n", label);
8700#if defined(HAVE_CUMULUS)
8701 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
520d5d76 8702#else
d62a17ae 8703 if (bgp_labeled_safi(safi))
520d5d76 8704#endif
d62a17ae 8705 vty_out(vty, "not allocated\n");
8706 }
718e3744 8707
d62a17ae 8708 for (ri = rn->info; ri; ri = ri->next) {
8709 count++;
8710 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
8711 best = count;
8712 if (ri->extra && ri->extra->suppress)
8713 suppress = 1;
8714 if (ri->attr->community != NULL) {
8715 if (community_include(ri->attr->community,
8716 COMMUNITY_NO_ADVERTISE))
8717 no_advertise = 1;
8718 if (community_include(ri->attr->community,
8719 COMMUNITY_NO_EXPORT))
8720 no_export = 1;
8721 if (community_include(ri->attr->community,
8722 COMMUNITY_LOCAL_AS))
8723 local_as = 1;
8724 }
8725 }
718e3744 8726 }
718e3744 8727
d62a17ae 8728 if (!json) {
8729 vty_out(vty, "Paths: (%d available", count);
8730 if (best) {
8731 vty_out(vty, ", best #%d", best);
8732 if (safi == SAFI_UNICAST)
8733 vty_out(vty, ", table %s",
8734 (bgp->inst_type
8735 == BGP_INSTANCE_TYPE_DEFAULT)
8736 ? "Default-IP-Routing-Table"
8737 : bgp->name);
8738 } else
8739 vty_out(vty, ", no best path");
8740
8741 if (no_advertise)
8742 vty_out(vty, ", not advertised to any peer");
8743 else if (no_export)
8744 vty_out(vty, ", not advertised to EBGP peer");
8745 else if (local_as)
8746 vty_out(vty, ", not advertised outside local AS");
8747
8748 if (suppress)
8749 vty_out(vty,
8750 ", Advertisements suppressed by an aggregate.");
8751 vty_out(vty, ")\n");
8752 }
718e3744 8753
d62a17ae 8754 /* If we are not using addpath then we can display Advertised to and
8755 * that will
8756 * show what peers we advertised the bestpath to. If we are using
8757 * addpath
8758 * though then we must display Advertised to on a path-by-path basis. */
8759 if (!bgp->addpath_tx_used[afi][safi]) {
8760 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8761 if (bgp_adj_out_lookup(peer, rn, 0)) {
8762 if (json && !json_adv_to)
8763 json_adv_to = json_object_new_object();
8764
8765 route_vty_out_advertised_to(
8766 vty, peer, &first,
8767 " Advertised to non peer-group peers:\n ",
8768 json_adv_to);
8769 }
8770 }
8771
8772 if (json) {
8773 if (json_adv_to) {
8774 json_object_object_add(json, "advertisedTo",
8775 json_adv_to);
8776 }
8777 } else {
8778 if (first)
8779 vty_out(vty, " Not advertised to any peer");
8780 vty_out(vty, "\n");
8781 }
8782 }
718e3744 8783}
8784
8785/* Display specified route of BGP table. */
d62a17ae 8786static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
8787 struct bgp_table *rib, const char *ip_str,
8788 afi_t afi, safi_t safi,
8789 struct prefix_rd *prd, int prefix_check,
d7c0a89a
QY
8790 enum bgp_path_type pathtype,
8791 uint8_t use_json)
d62a17ae 8792{
8793 int ret;
8794 int header;
8795 int display = 0;
8796 struct prefix match;
8797 struct bgp_node *rn;
8798 struct bgp_node *rm;
8799 struct bgp_info *ri;
8800 struct bgp_table *table;
8801 json_object *json = NULL;
8802 json_object *json_paths = NULL;
8803
8804 /* Check IP address argument. */
8805 ret = str2prefix(ip_str, &match);
8806 if (!ret) {
8807 vty_out(vty, "address is malformed\n");
8808 return CMD_WARNING;
8809 }
718e3744 8810
d62a17ae 8811 match.family = afi2family(afi);
b05a1c8b 8812
d62a17ae 8813 if (use_json) {
8814 json = json_object_new_object();
8815 json_paths = json_object_new_array();
8816 }
718e3744 8817
d62a17ae 8818 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
8819 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
8820 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
8821 continue;
8822
ea47320b
DL
8823 if ((table = rn->info) == NULL)
8824 continue;
d62a17ae 8825
ea47320b
DL
8826 header = 1;
8827
8828 if ((rm = bgp_node_match(table, &match)) == NULL)
8829 continue;
d62a17ae 8830
ea47320b
DL
8831 if (prefix_check
8832 && rm->p.prefixlen != match.prefixlen) {
8833 bgp_unlock_node(rm);
8834 continue;
8835 }
d62a17ae 8836
ea47320b
DL
8837 for (ri = rm->info; ri; ri = ri->next) {
8838 if (header) {
60466a63
QY
8839 route_vty_out_detail_header(
8840 vty, bgp, rm,
8841 (struct prefix_rd *)&rn->p,
ea47320b
DL
8842 AFI_IP, safi, json);
8843 header = 0;
d62a17ae 8844 }
ea47320b
DL
8845 display++;
8846
8847 if (pathtype == BGP_PATH_ALL
8848 || (pathtype == BGP_PATH_BESTPATH
8849 && CHECK_FLAG(ri->flags,
8850 BGP_INFO_SELECTED))
8851 || (pathtype == BGP_PATH_MULTIPATH
8852 && (CHECK_FLAG(ri->flags,
8853 BGP_INFO_MULTIPATH)
8854 || CHECK_FLAG(ri->flags,
60466a63 8855 BGP_INFO_SELECTED))))
ea47320b
DL
8856 route_vty_out_detail(vty, bgp, &rm->p,
8857 ri, AFI_IP, safi,
8858 json_paths);
d62a17ae 8859 }
ea47320b
DL
8860
8861 bgp_unlock_node(rm);
d62a17ae 8862 }
98a9dbc7
PG
8863 } else if (safi == SAFI_FLOWSPEC) {
8864 rn = bgp_flowspec_get_match_per_ip(afi, rib,
8865 &match, prefix_check);
8866 if (rn != NULL) {
8867 route_vty_out_flowspec(vty, &rn->p,
8868 rn->info, use_json ?
8869 NLRI_STRING_FORMAT_JSON :
8870 NLRI_STRING_FORMAT_LARGE,
8871 json_paths);
8872 display++;
8873 bgp_unlock_node(rn);
8874 }
d62a17ae 8875 } else {
8876 header = 1;
8877
8878 if ((rn = bgp_node_match(rib, &match)) != NULL) {
8879 if (!prefix_check
8880 || rn->p.prefixlen == match.prefixlen) {
8881 for (ri = rn->info; ri; ri = ri->next) {
8882 if (header) {
8883 route_vty_out_detail_header(
8884 vty, bgp, rn, NULL, afi,
8885 safi, json);
8886 header = 0;
8887 }
8888 display++;
8889
8890 if (pathtype == BGP_PATH_ALL
8891 || (pathtype == BGP_PATH_BESTPATH
8892 && CHECK_FLAG(
8893 ri->flags,
8894 BGP_INFO_SELECTED))
8895 || (pathtype == BGP_PATH_MULTIPATH
8896 && (CHECK_FLAG(
8897 ri->flags,
8898 BGP_INFO_MULTIPATH)
8899 || CHECK_FLAG(
8900 ri->flags,
8901 BGP_INFO_SELECTED))))
8902 route_vty_out_detail(
8903 vty, bgp, &rn->p, ri,
8904 afi, safi, json_paths);
8905 }
8906 }
8907
8908 bgp_unlock_node(rn);
8909 }
8910 }
e5eee9af 8911
d62a17ae 8912 if (use_json) {
8913 if (display)
8914 json_object_object_add(json, "paths", json_paths);
8915
996c9314
LB
8916 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8917 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 8918 json_object_free(json);
8919 } else {
8920 if (!display) {
8921 vty_out(vty, "%% Network not in table\n");
8922 return CMD_WARNING;
8923 }
8924 }
b05a1c8b 8925
d62a17ae 8926 return CMD_SUCCESS;
718e3744 8927}
8928
fee0f4c6 8929/* Display specified route of Main RIB */
d62a17ae 8930static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
8931 afi_t afi, safi_t safi, struct prefix_rd *prd,
8932 int prefix_check, enum bgp_path_type pathtype,
d7c0a89a 8933 uint8_t use_json)
d62a17ae 8934{
9b86009a 8935 if (!bgp) {
d62a17ae 8936 bgp = bgp_get_default();
9b86009a
RW
8937 if (!bgp) {
8938 if (!use_json)
8939 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8940 else
8941 vty_out(vty, "{}\n");
9b86009a
RW
8942 return CMD_WARNING;
8943 }
8944 }
d62a17ae 8945
8946 /* labeled-unicast routes live in the unicast table */
8947 if (safi == SAFI_LABELED_UNICAST)
8948 safi = SAFI_UNICAST;
8949
8950 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
8951 afi, safi, prd, prefix_check, pathtype,
8952 use_json);
8953}
8954
8955static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
8956 struct cmd_token **argv, afi_t afi, safi_t safi,
d7c0a89a 8957 uint8_t uj)
d62a17ae 8958{
8959 struct lcommunity *lcom;
8960 struct buffer *b;
8961 int i;
8962 char *str;
8963 int first = 0;
8964
8965 b = buffer_new(1024);
8966 for (i = 0; i < argc; i++) {
8967 if (first)
8968 buffer_putc(b, ' ');
8969 else {
8970 if (strmatch(argv[i]->text, "AA:BB:CC")) {
8971 first = 1;
8972 buffer_putstr(b, argv[i]->arg);
8973 }
8974 }
8975 }
8976 buffer_putc(b, '\0');
57d187bc 8977
d62a17ae 8978 str = buffer_getstr(b);
8979 buffer_free(b);
57d187bc 8980
d62a17ae 8981 lcom = lcommunity_str2com(str);
8982 XFREE(MTYPE_TMP, str);
8983 if (!lcom) {
8984 vty_out(vty, "%% Large-community malformed\n");
8985 return CMD_WARNING;
8986 }
57d187bc 8987
d62a17ae 8988 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
8989 uj);
57d187bc
JS
8990}
8991
d62a17ae 8992static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
8993 const char *lcom, afi_t afi, safi_t safi,
d7c0a89a 8994 uint8_t uj)
57d187bc 8995{
d62a17ae 8996 struct community_list *list;
57d187bc 8997
d62a17ae 8998 list = community_list_lookup(bgp_clist, lcom,
8999 LARGE_COMMUNITY_LIST_MASTER);
9000 if (list == NULL) {
9001 vty_out(vty, "%% %s is not a valid large-community-list name\n",
9002 lcom);
9003 return CMD_WARNING;
9004 }
57d187bc 9005
d62a17ae 9006 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
9007 list, uj);
fee0f4c6 9008}
9009
52951b63
DS
9010DEFUN (show_ip_bgp_large_community_list,
9011 show_ip_bgp_large_community_list_cmd,
4dd6177e 9012 "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
9013 SHOW_STR
9014 IP_STR
9015 BGP_STR
9016 BGP_INSTANCE_HELP_STR
9bedbb1e 9017 BGP_AFI_HELP_STR
4dd6177e 9018 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9019 "Display routes matching the large-community-list\n"
9020 "large-community-list number\n"
9021 "large-community-list name\n"
9022 JSON_STR)
9023{
d62a17ae 9024 char *vrf = NULL;
9025 afi_t afi = AFI_IP6;
9026 safi_t safi = SAFI_UNICAST;
9027 int idx = 0;
9028
9029 if (argv_find(argv, argc, "ip", &idx))
9030 afi = AFI_IP;
9031 if (argv_find(argv, argc, "view", &idx)
9032 || argv_find(argv, argc, "vrf", &idx))
9033 vrf = argv[++idx]->arg;
9034 if (argv_find(argv, argc, "ipv4", &idx)
9035 || argv_find(argv, argc, "ipv6", &idx)) {
9036 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9037 if (argv_find(argv, argc, "unicast", &idx)
9038 || argv_find(argv, argc, "multicast", &idx))
9039 safi = bgp_vty_safi_from_str(argv[idx]->text);
9040 }
9041
9042 int uj = use_json(argc, argv);
9043
9044 struct bgp *bgp = bgp_lookup_by_name(vrf);
9045 if (bgp == NULL) {
9046 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9047 return CMD_WARNING;
9048 }
9049
9050 argv_find(argv, argc, "large-community-list", &idx);
9051 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
9052 uj);
52951b63
DS
9053}
9054DEFUN (show_ip_bgp_large_community,
9055 show_ip_bgp_large_community_cmd,
4dd6177e 9056 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
9057 SHOW_STR
9058 IP_STR
9059 BGP_STR
9060 BGP_INSTANCE_HELP_STR
9bedbb1e 9061 BGP_AFI_HELP_STR
4dd6177e 9062 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9063 "Display routes matching the large-communities\n"
9064 "List of large-community numbers\n"
9065 JSON_STR)
9066{
d62a17ae 9067 char *vrf = NULL;
9068 afi_t afi = AFI_IP6;
9069 safi_t safi = SAFI_UNICAST;
9070 int idx = 0;
9071
9072 if (argv_find(argv, argc, "ip", &idx))
9073 afi = AFI_IP;
9074 if (argv_find(argv, argc, "view", &idx)
9075 || argv_find(argv, argc, "vrf", &idx))
9076 vrf = argv[++idx]->arg;
9077 if (argv_find(argv, argc, "ipv4", &idx)
9078 || argv_find(argv, argc, "ipv6", &idx)) {
9079 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9080 if (argv_find(argv, argc, "unicast", &idx)
9081 || argv_find(argv, argc, "multicast", &idx))
9082 safi = bgp_vty_safi_from_str(argv[idx]->text);
9083 }
9084
9085 int uj = use_json(argc, argv);
9086
9087 struct bgp *bgp = bgp_lookup_by_name(vrf);
9088 if (bgp == NULL) {
9089 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9090 return CMD_WARNING;
9091 }
9092
9093 if (argv_find(argv, argc, "AA:BB:CC", &idx))
9094 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
9095 else
9096 return bgp_show(vty, bgp, afi, safi,
9097 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
9098}
9099
d62a17ae 9100static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9101 safi_t safi);
e01ca200 9102
7b2ff250
DW
9103
9104/* BGP route print out function without JSON */
af462945
DS
9105DEFUN (show_ip_bgp,
9106 show_ip_bgp_cmd,
4dd6177e 9107 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
9108 <dampening <parameters>\
9109 |route-map WORD\
9110 |prefix-list WORD\
9111 |filter-list WORD\
9112 |statistics\
31d5efe2 9113 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
7b2ff250
DW
9114 |community-list <(1-500)|WORD> [exact-match]\
9115 |A.B.C.D/M longer-prefixes\
9116 |X:X::X:X/M longer-prefixes\
9117 >",
718e3744 9118 SHOW_STR
9119 IP_STR
9120 BGP_STR
a636c635 9121 BGP_INSTANCE_HELP_STR
4f280b15 9122 BGP_AFI_HELP_STR
4dd6177e 9123 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 9124 "Display detailed information about dampening\n"
af462945 9125 "Display detail of configured dampening parameters\n"
a636c635
DW
9126 "Display routes matching the route-map\n"
9127 "A route-map to match on\n"
9128 "Display routes conforming to the prefix-list\n"
8c3deaae 9129 "Prefix-list name\n"
a636c635
DW
9130 "Display routes conforming to the filter-list\n"
9131 "Regular expression access list name\n"
e01ca200 9132 "BGP RIB advertisement statistics\n"
a636c635
DW
9133 "Display routes matching the communities\n"
9134 COMMUNITY_AANN_STR
9135 "Do not send outside local AS (well-known community)\n"
9136 "Do not advertise to any peer (well-known community)\n"
9137 "Do not export to next AS (well-known community)\n"
7f323236 9138 "Graceful shutdown (well-known community)\n"
a636c635
DW
9139 "Exact match of the communities\n"
9140 "Display routes matching the community-list\n"
9141 "community-list number\n"
9142 "community-list name\n"
9143 "Exact match of the communities\n"
0c7b1b01 9144 "IPv4 prefix\n"
8c3deaae 9145 "Display route and more specific routes\n"
0c7b1b01 9146 "IPv6 prefix\n"
7b2ff250 9147 "Display route and more specific routes\n")
718e3744 9148{
d62a17ae 9149 afi_t afi = AFI_IP6;
9150 safi_t safi = SAFI_UNICAST;
9151 int exact_match = 0;
d62a17ae 9152 struct bgp *bgp = NULL;
9153 int idx = 0;
7f323236 9154 int idx_community_type = 0;
d62a17ae 9155
9156 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9157 &bgp);
9158 if (!idx)
9159 return CMD_WARNING;
9160
d62a17ae 9161 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 9162 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 9163 return bgp_show_dampening_parameters(vty, afi, safi);
9164 }
c016b6c7 9165
d62a17ae 9166 if (argv_find(argv, argc, "prefix-list", &idx))
9167 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
9168 safi, bgp_show_type_prefix_list);
9169
9170 if (argv_find(argv, argc, "filter-list", &idx))
9171 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
9172 safi, bgp_show_type_filter_list);
9173
9174 if (argv_find(argv, argc, "statistics", &idx))
9175 return bgp_table_stats(vty, bgp, afi, safi);
9176
9177 if (argv_find(argv, argc, "route-map", &idx))
9178 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
9179 safi, bgp_show_type_route_map);
9180
9181 if (argv_find(argv, argc, "community", &idx)) {
9182 /* show a specific community */
7f323236 9183 if (argv_find(argv, argc, "local-AS", &idx_community_type)
a4d82a8a
PZ
9184 || argv_find(argv, argc, "no-advertise",
9185 &idx_community_type)
7f323236 9186 || argv_find(argv, argc, "no-export", &idx_community_type)
a4d82a8a
PZ
9187 || argv_find(argv, argc, "graceful-shutdown",
9188 &idx_community_type)
7f323236
DW
9189 || argv_find(argv, argc, "AA:NN", &idx_community_type)) {
9190
9191 if (argv_find(argv, argc, "exact-match", &idx))
d62a17ae 9192 exact_match = 1;
a4d82a8a
PZ
9193 return bgp_show_community(vty, bgp,
9194 argv[idx_community_type]->arg,
d62a17ae 9195 exact_match, afi, safi);
9196 }
d62a17ae 9197 }
a636c635 9198
d62a17ae 9199 if (argv_find(argv, argc, "community-list", &idx)) {
9200 const char *clist_number_or_name = argv[++idx]->arg;
9201 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
9202 exact_match = 1;
9203 return bgp_show_community_list(vty, bgp, clist_number_or_name,
9204 exact_match, afi, safi);
9205 }
9206 /* prefix-longer */
9207 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9208 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9209 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
9210 safi,
9211 bgp_show_type_prefix_longer);
9212
7b2ff250
DW
9213 return CMD_WARNING;
9214}
9215
9216/* BGP route print out function with JSON */
9217DEFUN (show_ip_bgp_json,
9218 show_ip_bgp_json_cmd,
9219 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
9220 [<\
9221 cidr-only\
9222 |dampening <flap-statistics|dampened-paths>\
9223 |community \
9224 >] [json]",
9225 SHOW_STR
9226 IP_STR
9227 BGP_STR
9228 BGP_INSTANCE_HELP_STR
9229 BGP_AFI_HELP_STR
9230 BGP_SAFI_WITH_LABEL_HELP_STR
9231 "Display only routes with non-natural netmasks\n"
9232 "Display detailed information about dampening\n"
9233 "Display flap statistics of routes\n"
9234 "Display paths suppressed due to dampening\n"
9235 "Display routes matching the communities\n"
9236 JSON_STR)
9237{
9238 afi_t afi = AFI_IP6;
9239 safi_t safi = SAFI_UNICAST;
9240 enum bgp_show_type sh_type = bgp_show_type_normal;
9241 struct bgp *bgp = NULL;
9242 int idx = 0;
9243
9244 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9245 &bgp);
9246 if (!idx)
9247 return CMD_WARNING;
9248
9249 int uj = use_json(argc, argv);
9250 if (uj)
9251 argc--;
9252
9253 if (argv_find(argv, argc, "cidr-only", &idx))
9254 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
9255 NULL, uj);
9256
9257 if (argv_find(argv, argc, "dampening", &idx)) {
9258 if (argv_find(argv, argc, "dampened-paths", &idx))
9259 return bgp_show(vty, bgp, afi, safi,
9260 bgp_show_type_dampend_paths, NULL, uj);
9261 else if (argv_find(argv, argc, "flap-statistics", &idx))
9262 return bgp_show(vty, bgp, afi, safi,
9263 bgp_show_type_flap_statistics, NULL,
9264 uj);
9265 }
9266
9267 if (argv_find(argv, argc, "community", &idx)) {
9268 /* show all communities */
9269 return bgp_show(vty, bgp, afi, safi,
9270 bgp_show_type_community_all, NULL, uj);
9271 }
1ae44dfc 9272 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 9273}
47fc97cc 9274
718e3744 9275DEFUN (show_ip_bgp_route,
9276 show_ip_bgp_route_cmd,
4dd6177e 9277 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 9278 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 9279 SHOW_STR
9280 IP_STR
9281 BGP_STR
a636c635 9282 BGP_INSTANCE_HELP_STR
4f280b15 9283 BGP_AFI_HELP_STR
4dd6177e 9284 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 9285 "Network in the BGP routing table to display\n"
0c7b1b01 9286 "IPv4 prefix\n"
8c3deaae 9287 "Network in the BGP routing table to display\n"
0c7b1b01 9288 "IPv6 prefix\n"
4092b06c 9289 "Display only the bestpath\n"
b05a1c8b 9290 "Display only multipaths\n"
9973d184 9291 JSON_STR)
4092b06c 9292{
d62a17ae 9293 int prefix_check = 0;
ae19d7dd 9294
d62a17ae 9295 afi_t afi = AFI_IP6;
9296 safi_t safi = SAFI_UNICAST;
9297 char *prefix = NULL;
9298 struct bgp *bgp = NULL;
9299 enum bgp_path_type path_type;
d7c0a89a 9300 uint8_t uj = use_json(argc, argv);
b05a1c8b 9301
d62a17ae 9302 int idx = 0;
ae19d7dd 9303
d62a17ae 9304 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9305 &bgp);
9306 if (!idx)
9307 return CMD_WARNING;
c41247f5 9308
d62a17ae 9309 if (!bgp) {
9310 vty_out(vty,
9311 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9312 return CMD_WARNING;
9313 }
a636c635 9314
d62a17ae 9315 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9316 if (argv_find(argv, argc, "A.B.C.D", &idx)
9317 || argv_find(argv, argc, "X:X::X:X", &idx))
9318 prefix_check = 0;
9319 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9320 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9321 prefix_check = 1;
9322
9323 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9324 && afi != AFI_IP6) {
9325 vty_out(vty,
9326 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9327 return CMD_WARNING;
9328 }
9329 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9330 && afi != AFI_IP) {
9331 vty_out(vty,
9332 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9333 return CMD_WARNING;
9334 }
9335
9336 prefix = argv[idx]->arg;
9337
9338 /* [<bestpath|multipath>] */
9339 if (argv_find(argv, argc, "bestpath", &idx))
9340 path_type = BGP_PATH_BESTPATH;
9341 else if (argv_find(argv, argc, "multipath", &idx))
9342 path_type = BGP_PATH_MULTIPATH;
9343 else
9344 path_type = BGP_PATH_ALL;
a636c635 9345
d62a17ae 9346 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9347 path_type, uj);
4092b06c
DS
9348}
9349
8c3deaae
QY
9350DEFUN (show_ip_bgp_regexp,
9351 show_ip_bgp_regexp_cmd,
4dd6177e 9352 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9353 SHOW_STR
9354 IP_STR
9355 BGP_STR
b00b230a 9356 BGP_INSTANCE_HELP_STR
4f280b15 9357 BGP_AFI_HELP_STR
4dd6177e 9358 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9359 "Display routes matching the AS path regular expression\n"
9360 "A regular-expression to match the BGP AS paths\n")
9361{
d62a17ae 9362 afi_t afi = AFI_IP6;
9363 safi_t safi = SAFI_UNICAST;
9364 struct bgp *bgp = NULL;
8c3deaae 9365
d62a17ae 9366 int idx = 0;
9367 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9368 &bgp);
9369 if (!idx)
9370 return CMD_WARNING;
8c3deaae 9371
d62a17ae 9372 // get index of regex
9373 argv_find(argv, argc, "regexp", &idx);
9374 idx++;
8c3deaae 9375
d62a17ae 9376 char *regstr = argv_concat(argv, argc, idx);
e889891d 9377 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 9378 bgp_show_type_regexp);
9379 XFREE(MTYPE_TMP, regstr);
9380 return rc;
8c3deaae
QY
9381}
9382
a636c635
DW
9383DEFUN (show_ip_bgp_instance_all,
9384 show_ip_bgp_instance_all_cmd,
4dd6177e 9385 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9386 SHOW_STR
a636c635 9387 IP_STR
4092b06c 9388 BGP_STR
a636c635 9389 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9390 BGP_AFI_HELP_STR
4dd6177e 9391 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9392 JSON_STR)
4092b06c 9393{
d62a17ae 9394 afi_t afi = AFI_IP;
9395 safi_t safi = SAFI_UNICAST;
9396 struct bgp *bgp = NULL;
ae19d7dd 9397
d62a17ae 9398 int idx = 0;
9399 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9400 &bgp);
9401 if (!idx)
9402 return CMD_WARNING;
ae19d7dd 9403
d62a17ae 9404 int uj = use_json(argc, argv);
9405 if (uj)
9406 argc--;
e3e29b32 9407
d62a17ae 9408 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9409 return CMD_SUCCESS;
e3e29b32
LB
9410}
9411
a4d82a8a
PZ
9412static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9413 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 9414{
d62a17ae 9415 regex_t *regex;
9416 int rc;
e3e29b32 9417
d62a17ae 9418 regex = bgp_regcomp(regstr);
9419 if (!regex) {
9420 vty_out(vty, "Can't compile regexp %s\n", regstr);
9421 return CMD_WARNING;
9422 }
a636c635 9423
e889891d 9424 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 9425 bgp_regex_free(regex);
9426 return rc;
e3e29b32
LB
9427}
9428
d62a17ae 9429static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9430 const char *prefix_list_str, afi_t afi,
9431 safi_t safi, enum bgp_show_type type)
e3e29b32 9432{
d62a17ae 9433 struct prefix_list *plist;
718e3744 9434
d62a17ae 9435 plist = prefix_list_lookup(afi, prefix_list_str);
9436 if (plist == NULL) {
9437 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9438 prefix_list_str);
9439 return CMD_WARNING;
9440 }
718e3744 9441
d62a17ae 9442 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9443}
9444
d62a17ae 9445static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9446 const char *filter, afi_t afi, safi_t safi,
9447 enum bgp_show_type type)
4092b06c 9448{
d62a17ae 9449 struct as_list *as_list;
718e3744 9450
d62a17ae 9451 as_list = as_list_lookup(filter);
9452 if (as_list == NULL) {
9453 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9454 filter);
9455 return CMD_WARNING;
9456 }
a636c635 9457
d62a17ae 9458 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9459}
9460
d62a17ae 9461static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9462 const char *rmap_str, afi_t afi, safi_t safi,
9463 enum bgp_show_type type)
718e3744 9464{
d62a17ae 9465 struct route_map *rmap;
bb46e94f 9466
d62a17ae 9467 rmap = route_map_lookup_by_name(rmap_str);
9468 if (!rmap) {
9469 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9470 return CMD_WARNING;
9471 }
9472
9473 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9474}
9475
7f323236
DW
9476static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9477 const char *comstr, int exact, afi_t afi,
d62a17ae 9478 safi_t safi)
9479{
9480 struct community *com;
d62a17ae 9481 int ret = 0;
9482
7f323236 9483 com = community_str2com(comstr);
d62a17ae 9484 if (!com) {
7f323236 9485 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 9486 return CMD_WARNING;
9487 }
9488
9489 ret = bgp_show(vty, bgp, afi, safi,
9490 (exact ? bgp_show_type_community_exact
9491 : bgp_show_type_community),
9492 com, 0);
9493 community_free(com);
46c3ce83 9494
d62a17ae 9495 return ret;
718e3744 9496}
9497
d62a17ae 9498static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9499 const char *com, int exact, afi_t afi,
9500 safi_t safi)
50ef26d4 9501{
d62a17ae 9502 struct community_list *list;
50ef26d4 9503
d62a17ae 9504 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9505 if (list == NULL) {
9506 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9507 return CMD_WARNING;
9508 }
718e3744 9509
d62a17ae 9510 return bgp_show(vty, bgp, afi, safi,
9511 (exact ? bgp_show_type_community_list_exact
9512 : bgp_show_type_community_list),
9513 list, 0);
50ef26d4 9514}
9515
d62a17ae 9516static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9517 const char *prefix, afi_t afi, safi_t safi,
9518 enum bgp_show_type type)
718e3744 9519{
d62a17ae 9520 int ret;
9521 struct prefix *p;
47fc97cc 9522
d62a17ae 9523 p = prefix_new();
95cbbd2a 9524
d62a17ae 9525 ret = str2prefix(prefix, p);
9526 if (!ret) {
9527 vty_out(vty, "%% Malformed Prefix\n");
9528 return CMD_WARNING;
9529 }
47e9b292 9530
d62a17ae 9531 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9532 prefix_free(p);
9533 return ret;
9534}
9535
9536static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
d7c0a89a 9537 const char *ip_str, uint8_t use_json)
d62a17ae 9538{
9539 int ret;
9540 struct peer *peer;
9541 union sockunion su;
9542
9543 /* Get peer sockunion. */
9544 ret = str2sockunion(ip_str, &su);
9545 if (ret < 0) {
9546 peer = peer_lookup_by_conf_if(bgp, ip_str);
9547 if (!peer) {
9548 peer = peer_lookup_by_hostname(bgp, ip_str);
9549
9550 if (!peer) {
9551 if (use_json) {
9552 json_object *json_no = NULL;
9553 json_no = json_object_new_object();
9554 json_object_string_add(
9555 json_no,
9556 "malformedAddressOrName",
9557 ip_str);
9558 vty_out(vty, "%s\n",
66f80d74 9559 json_object_to_json_string_ext(
a4d82a8a
PZ
9560 json_no,
9561 JSON_C_TO_STRING_PRETTY));
d62a17ae 9562 json_object_free(json_no);
9563 } else
9564 vty_out(vty,
9565 "%% Malformed address or name: %s\n",
9566 ip_str);
9567 return NULL;
9568 }
9569 }
9570 return peer;
9571 }
718e3744 9572
d62a17ae 9573 /* Peer structure lookup. */
9574 peer = peer_lookup(bgp, &su);
9575 if (!peer) {
9576 if (use_json) {
9577 json_object *json_no = NULL;
9578 json_no = json_object_new_object();
9579 json_object_string_add(json_no, "warning",
9e6e6f46 9580 "No such neighbor in this view/vrf");
d62a17ae 9581 vty_out(vty, "%s\n",
a4d82a8a
PZ
9582 json_object_to_json_string_ext(
9583 json_no, JSON_C_TO_STRING_PRETTY));
d62a17ae 9584 json_object_free(json_no);
9585 } else
9e6e6f46 9586 vty_out(vty, "No such neighbor in this view/vrf\n");
d62a17ae 9587 return NULL;
9588 }
2815e61f 9589
d62a17ae 9590 return peer;
9591}
9592
9593enum bgp_stats {
9594 BGP_STATS_MAXBITLEN = 0,
9595 BGP_STATS_RIB,
9596 BGP_STATS_PREFIXES,
9597 BGP_STATS_TOTPLEN,
9598 BGP_STATS_UNAGGREGATEABLE,
9599 BGP_STATS_MAX_AGGREGATEABLE,
9600 BGP_STATS_AGGREGATES,
9601 BGP_STATS_SPACE,
9602 BGP_STATS_ASPATH_COUNT,
9603 BGP_STATS_ASPATH_MAXHOPS,
9604 BGP_STATS_ASPATH_TOTHOPS,
9605 BGP_STATS_ASPATH_MAXSIZE,
9606 BGP_STATS_ASPATH_TOTSIZE,
9607 BGP_STATS_ASN_HIGHEST,
9608 BGP_STATS_MAX,
a636c635 9609};
2815e61f 9610
d62a17ae 9611static const char *table_stats_strs[] = {
9d303b37
DL
9612 [BGP_STATS_PREFIXES] = "Total Prefixes",
9613 [BGP_STATS_TOTPLEN] = "Average prefix length",
9614 [BGP_STATS_RIB] = "Total Advertisements",
9615 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9616 [BGP_STATS_MAX_AGGREGATEABLE] =
9617 "Maximum aggregateable prefixes",
9618 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9619 [BGP_STATS_SPACE] = "Address space advertised",
9620 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9621 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9622 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9623 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9624 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9625 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9626 [BGP_STATS_MAX] = NULL,
a636c635 9627};
2815e61f 9628
d62a17ae 9629struct bgp_table_stats {
9630 struct bgp_table *table;
9631 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 9632 double total_space;
ff7924f6
PJ
9633};
9634
a636c635
DW
9635#if 0
9636#define TALLY_SIGFIG 100000
9637static unsigned long
9638ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9639{
a636c635
DW
9640 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9641 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9642 unsigned long ret = newtot / count;
9643
9644 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9645 return ret + 1;
9646 else
9647 return ret;
9648}
9649#endif
ff7924f6 9650
d62a17ae 9651static int bgp_table_stats_walker(struct thread *t)
2815e61f 9652{
d62a17ae 9653 struct bgp_node *rn;
9654 struct bgp_node *top;
9655 struct bgp_table_stats *ts = THREAD_ARG(t);
9656 unsigned int space = 0;
a636c635 9657
d62a17ae 9658 if (!(top = bgp_table_top(ts->table)))
9659 return 0;
2815e61f 9660
d62a17ae 9661 switch (top->p.family) {
9662 case AF_INET:
9663 space = IPV4_MAX_BITLEN;
9664 break;
9665 case AF_INET6:
9666 space = IPV6_MAX_BITLEN;
9667 break;
9668 }
9669
9670 ts->counts[BGP_STATS_MAXBITLEN] = space;
9671
9672 for (rn = top; rn; rn = bgp_route_next(rn)) {
9673 struct bgp_info *ri;
9674 struct bgp_node *prn = bgp_node_parent_nolock(rn);
9675 unsigned int rinum = 0;
9676
9677 if (rn == top)
9678 continue;
9679
9680 if (!rn->info)
9681 continue;
9682
9683 ts->counts[BGP_STATS_PREFIXES]++;
9684 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9685
a636c635
DW
9686#if 0
9687 ts->counts[BGP_STATS_AVGPLEN]
9688 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9689 ts->counts[BGP_STATS_AVGPLEN],
9690 rn->p.prefixlen);
9691#endif
d62a17ae 9692
9693 /* check if the prefix is included by any other announcements */
9694 while (prn && !prn->info)
9695 prn = bgp_node_parent_nolock(prn);
9696
9697 if (prn == NULL || prn == top) {
9698 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9699 /* announced address space */
9700 if (space)
a4d82a8a
PZ
9701 ts->total_space +=
9702 pow(2.0, space - rn->p.prefixlen);
d62a17ae 9703 } else if (prn->info)
9704 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9705
9706 for (ri = rn->info; ri; ri = ri->next) {
9707 rinum++;
9708 ts->counts[BGP_STATS_RIB]++;
9709
9710 if (ri->attr
9711 && (CHECK_FLAG(ri->attr->flag,
9712 ATTR_FLAG_BIT(
9713 BGP_ATTR_ATOMIC_AGGREGATE))))
9714 ts->counts[BGP_STATS_AGGREGATES]++;
9715
9716 /* as-path stats */
9717 if (ri->attr && ri->attr->aspath) {
9718 unsigned int hops =
9719 aspath_count_hops(ri->attr->aspath);
9720 unsigned int size =
9721 aspath_size(ri->attr->aspath);
9722 as_t highest = aspath_highest(ri->attr->aspath);
9723
9724 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9725
9726 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
9727 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
9728 hops;
9729
9730 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
9731 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
9732 size;
9733
9734 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
9735 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635
DW
9736#if 0
9737 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
9738 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9739 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
9740 hops);
9741 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
9742 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9743 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
9744 size);
9745#endif
d62a17ae 9746 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
9747 ts->counts[BGP_STATS_ASN_HIGHEST] =
9748 highest;
9749 }
9750 }
9751 }
9752 return 0;
2815e61f 9753}
ff7924f6 9754
d62a17ae 9755static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9756 safi_t safi)
2815e61f 9757{
d62a17ae 9758 struct bgp_table_stats ts;
9759 unsigned int i;
019386c2 9760
d62a17ae 9761 if (!bgp->rib[afi][safi]) {
9762 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9763 afi, safi);
9764 return CMD_WARNING;
9765 }
019386c2 9766
d62a17ae 9767 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 9768
d62a17ae 9769 /* labeled-unicast routes live in the unicast table */
9770 if (safi == SAFI_LABELED_UNICAST)
9771 safi = SAFI_UNICAST;
019386c2 9772
d62a17ae 9773 memset(&ts, 0, sizeof(ts));
9774 ts.table = bgp->rib[afi][safi];
9775 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 9776
d62a17ae 9777 for (i = 0; i < BGP_STATS_MAX; i++) {
9778 if (!table_stats_strs[i])
9779 continue;
9780
9781 switch (i) {
a636c635
DW
9782#if 0
9783 case BGP_STATS_ASPATH_AVGHOPS:
9784 case BGP_STATS_ASPATH_AVGSIZE:
9785 case BGP_STATS_AVGPLEN:
9786 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9787 vty_out (vty, "%12.2f",
9788 (float)ts.counts[i] / (float)TALLY_SIGFIG);
9789 break;
9790#endif
d62a17ae 9791 case BGP_STATS_ASPATH_TOTHOPS:
9792 case BGP_STATS_ASPATH_TOTSIZE:
9793 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9794 vty_out(vty, "%12.2f",
9795 ts.counts[i]
9796 ? (float)ts.counts[i]
9797 / (float)ts.counts
9798 [BGP_STATS_ASPATH_COUNT]
9799 : 0);
9800 break;
9801 case BGP_STATS_TOTPLEN:
9802 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9803 vty_out(vty, "%12.2f",
9804 ts.counts[i]
9805 ? (float)ts.counts[i]
9806 / (float)ts.counts
9807 [BGP_STATS_PREFIXES]
9808 : 0);
9809 break;
9810 case BGP_STATS_SPACE:
9811 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
9812 vty_out(vty, "%12g\n", ts.total_space);
9813
9814 if (afi == AFI_IP6) {
9815 vty_out(vty, "%30s: ", "/32 equivalent ");
9816 vty_out(vty, "%12g\n",
a4d82a8a 9817 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
9818 vty_out(vty, "%30s: ", "/48 equivalent ");
9819 vty_out(vty, "%12g\n",
a4d82a8a 9820 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
9821 } else {
9822 vty_out(vty, "%30s: ", "% announced ");
9823 vty_out(vty, "%12.2f\n",
9824 ts.total_space * 100. * pow(2.0, -32));
9825 vty_out(vty, "%30s: ", "/8 equivalent ");
9826 vty_out(vty, "%12.2f\n",
a4d82a8a 9827 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
9828 vty_out(vty, "%30s: ", "/24 equivalent ");
9829 vty_out(vty, "%12.2f\n",
a4d82a8a 9830 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 9831 }
d62a17ae 9832 break;
9833 default:
9834 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9835 vty_out(vty, "%12llu", ts.counts[i]);
9836 }
ff7924f6 9837
d62a17ae 9838 vty_out(vty, "\n");
9839 }
9840 return CMD_SUCCESS;
9841}
9842
9843enum bgp_pcounts {
9844 PCOUNT_ADJ_IN = 0,
9845 PCOUNT_DAMPED,
9846 PCOUNT_REMOVED,
9847 PCOUNT_HISTORY,
9848 PCOUNT_STALE,
9849 PCOUNT_VALID,
9850 PCOUNT_ALL,
9851 PCOUNT_COUNTED,
9852 PCOUNT_PFCNT, /* the figure we display to users */
9853 PCOUNT_MAX,
a636c635 9854};
718e3744 9855
d62a17ae 9856static const char *pcount_strs[] = {
9d303b37
DL
9857 [PCOUNT_ADJ_IN] = "Adj-in",
9858 [PCOUNT_DAMPED] = "Damped",
9859 [PCOUNT_REMOVED] = "Removed",
9860 [PCOUNT_HISTORY] = "History",
9861 [PCOUNT_STALE] = "Stale",
9862 [PCOUNT_VALID] = "Valid",
9863 [PCOUNT_ALL] = "All RIB",
9864 [PCOUNT_COUNTED] = "PfxCt counted",
9865 [PCOUNT_PFCNT] = "Useable",
9866 [PCOUNT_MAX] = NULL,
a636c635 9867};
718e3744 9868
d62a17ae 9869struct peer_pcounts {
9870 unsigned int count[PCOUNT_MAX];
9871 const struct peer *peer;
9872 const struct bgp_table *table;
a636c635 9873};
47fc97cc 9874
d62a17ae 9875static int bgp_peer_count_walker(struct thread *t)
9876{
9877 struct bgp_node *rn;
9878 struct peer_pcounts *pc = THREAD_ARG(t);
9879 const struct peer *peer = pc->peer;
9880
9881 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
9882 struct bgp_adj_in *ain;
9883 struct bgp_info *ri;
9884
9885 for (ain = rn->adj_in; ain; ain = ain->next)
9886 if (ain->peer == peer)
9887 pc->count[PCOUNT_ADJ_IN]++;
9888
9889 for (ri = rn->info; ri; ri = ri->next) {
9890 char buf[SU_ADDRSTRLEN];
9891
9892 if (ri->peer != peer)
9893 continue;
9894
9895 pc->count[PCOUNT_ALL]++;
9896
9897 if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED))
9898 pc->count[PCOUNT_DAMPED]++;
9899 if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
9900 pc->count[PCOUNT_HISTORY]++;
9901 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
9902 pc->count[PCOUNT_REMOVED]++;
9903 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
9904 pc->count[PCOUNT_STALE]++;
9905 if (CHECK_FLAG(ri->flags, BGP_INFO_VALID))
9906 pc->count[PCOUNT_VALID]++;
9907 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9908 pc->count[PCOUNT_PFCNT]++;
9909
9910 if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
9911 pc->count[PCOUNT_COUNTED]++;
9912 if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9913 zlog_warn(
9914 "%s [pcount] %s/%d is counted but flags 0x%x",
9915 peer->host,
9916 inet_ntop(rn->p.family,
9917 &rn->p.u.prefix, buf,
9918 SU_ADDRSTRLEN),
9919 rn->p.prefixlen, ri->flags);
9920 } else {
9921 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9922 zlog_warn(
9923 "%s [pcount] %s/%d not counted but flags 0x%x",
9924 peer->host,
9925 inet_ntop(rn->p.family,
9926 &rn->p.u.prefix, buf,
9927 SU_ADDRSTRLEN),
9928 rn->p.prefixlen, ri->flags);
9929 }
9930 }
9931 }
9932 return 0;
718e3744 9933}
9934
d62a17ae 9935static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
d7c0a89a 9936 safi_t safi, uint8_t use_json)
856ca177 9937{
d62a17ae 9938 struct peer_pcounts pcounts = {.peer = peer};
9939 unsigned int i;
9940 json_object *json = NULL;
9941 json_object *json_loop = NULL;
856ca177 9942
d62a17ae 9943 if (use_json) {
9944 json = json_object_new_object();
9945 json_loop = json_object_new_object();
9946 }
718e3744 9947
d62a17ae 9948 if (!peer || !peer->bgp || !peer->afc[afi][safi]
9949 || !peer->bgp->rib[afi][safi]) {
9950 if (use_json) {
9951 json_object_string_add(
9952 json, "warning",
9953 "No such neighbor or address family");
9954 vty_out(vty, "%s\n", json_object_to_json_string(json));
9955 json_object_free(json);
9956 } else
9957 vty_out(vty, "%% No such neighbor or address family\n");
9958
9959 return CMD_WARNING;
9960 }
2a71e9ce 9961
d62a17ae 9962 memset(&pcounts, 0, sizeof(pcounts));
9963 pcounts.peer = peer;
9964 pcounts.table = peer->bgp->rib[afi][safi];
9965
9966 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
9967 * stats for the thread-walk (i.e. ensure this can't be blamed on
9968 * on just vty_read()).
9969 */
d62a17ae 9970 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
9971
9972 if (use_json) {
9973 json_object_string_add(json, "prefixCountsFor", peer->host);
9974 json_object_string_add(json, "multiProtocol",
9975 afi_safi_print(afi, safi));
9976 json_object_int_add(json, "pfxCounter",
9977 peer->pcount[afi][safi]);
9978
9979 for (i = 0; i < PCOUNT_MAX; i++)
9980 json_object_int_add(json_loop, pcount_strs[i],
9981 pcounts.count[i]);
9982
9983 json_object_object_add(json, "ribTableWalkCounters", json_loop);
9984
9985 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
9986 json_object_string_add(json, "pfxctDriftFor",
9987 peer->host);
9988 json_object_string_add(
9989 json, "recommended",
9990 "Please report this bug, with the above command output");
9991 }
996c9314
LB
9992 vty_out(vty, "%s\n", json_object_to_json_string_ext(
9993 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 9994 json_object_free(json);
9995 } else {
9996
9997 if (peer->hostname
9998 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
9999 vty_out(vty, "Prefix counts for %s/%s, %s\n",
10000 peer->hostname, peer->host,
10001 afi_safi_print(afi, safi));
10002 } else {
10003 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
10004 afi_safi_print(afi, safi));
10005 }
10006
10007 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
10008 vty_out(vty, "\nCounts from RIB table walk:\n\n");
10009
10010 for (i = 0; i < PCOUNT_MAX; i++)
10011 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
10012 pcounts.count[i]);
10013
10014 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
10015 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
10016 vty_out(vty,
10017 "Please report this bug, with the above command output\n");
10018 }
10019 }
10020
10021 return CMD_SUCCESS;
718e3744 10022}
10023
a636c635
DW
10024DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10025 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10026 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10027 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10028 SHOW_STR
10029 IP_STR
10030 BGP_STR
8386ac43 10031 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10032 BGP_AFI_HELP_STR
10033 BGP_SAFI_HELP_STR
0b16f239
DS
10034 "Detailed information on TCP and BGP neighbor connections\n"
10035 "Neighbor to display information about\n"
10036 "Neighbor to display information about\n"
91d37724 10037 "Neighbor on BGP configured interface\n"
a636c635 10038 "Display detailed prefix count information\n"
9973d184 10039 JSON_STR)
0b16f239 10040{
d62a17ae 10041 afi_t afi = AFI_IP6;
10042 safi_t safi = SAFI_UNICAST;
10043 struct peer *peer;
10044 int idx = 0;
10045 struct bgp *bgp = NULL;
856ca177 10046
d62a17ae 10047 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10048 &bgp);
10049 if (!idx)
10050 return CMD_WARNING;
0b16f239 10051
d62a17ae 10052 int uj = use_json(argc, argv);
10053 if (uj)
10054 argc--;
0b16f239 10055
d62a17ae 10056 argv_find(argv, argc, "neighbors", &idx);
10057 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
10058 if (!peer)
10059 return CMD_WARNING;
bb46e94f 10060
d62a17ae 10061 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 10062}
0b16f239 10063
d6902373
PG
10064#ifdef KEEP_OLD_VPN_COMMANDS
10065DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
10066 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
10067 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
10068 SHOW_STR
10069 IP_STR
10070 BGP_STR
d6902373 10071 BGP_VPNVX_HELP_STR
91d37724 10072 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
10073 "Detailed information on TCP and BGP neighbor connections\n"
10074 "Neighbor to display information about\n"
10075 "Neighbor to display information about\n"
91d37724 10076 "Neighbor on BGP configured interface\n"
a636c635 10077 "Display detailed prefix count information\n"
9973d184 10078 JSON_STR)
a636c635 10079{
d62a17ae 10080 int idx_peer = 6;
10081 struct peer *peer;
d7c0a89a 10082 uint8_t uj = use_json(argc, argv);
a636c635 10083
d62a17ae 10084 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
10085 if (!peer)
10086 return CMD_WARNING;
10087
10088 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
10089}
10090
d6902373
PG
10091DEFUN (show_ip_bgp_vpn_all_route_prefix,
10092 show_ip_bgp_vpn_all_route_prefix_cmd,
10093 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
10094 SHOW_STR
10095 IP_STR
10096 BGP_STR
d6902373 10097 BGP_VPNVX_HELP_STR
91d37724
QY
10098 "Display information about all VPNv4 NLRIs\n"
10099 "Network in the BGP routing table to display\n"
3a2d747c 10100 "Network in the BGP routing table to display\n"
9973d184 10101 JSON_STR)
91d37724 10102{
d62a17ae 10103 int idx = 0;
10104 char *network = NULL;
10105 struct bgp *bgp = bgp_get_default();
10106 if (!bgp) {
10107 vty_out(vty, "Can't find default instance\n");
10108 return CMD_WARNING;
10109 }
87e34b58 10110
d62a17ae 10111 if (argv_find(argv, argc, "A.B.C.D", &idx))
10112 network = argv[idx]->arg;
10113 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10114 network = argv[idx]->arg;
10115 else {
10116 vty_out(vty, "Unable to figure out Network\n");
10117 return CMD_WARNING;
10118 }
87e34b58 10119
d62a17ae 10120 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
10121 BGP_PATH_ALL, use_json(argc, argv));
91d37724 10122}
d6902373 10123#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 10124
4c63a661
PG
10125DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
10126 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
10127 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10128 SHOW_STR
10129 IP_STR
10130 BGP_STR
10131 L2VPN_HELP_STR
10132 EVPN_HELP_STR
10133 "Display information about all EVPN NLRIs\n"
10134 "Network in the BGP routing table to display\n"
10135 "Network in the BGP routing table to display\n"
10136 JSON_STR)
10137{
d62a17ae 10138 int idx = 0;
10139 char *network = NULL;
a636c635 10140
d62a17ae 10141 if (argv_find(argv, argc, "A.B.C.D", &idx))
10142 network = argv[idx]->arg;
10143 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10144 network = argv[idx]->arg;
10145 else {
10146 vty_out(vty, "Unable to figure out Network\n");
10147 return CMD_WARNING;
10148 }
10149 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
10150 BGP_PATH_ALL, use_json(argc, argv));
10151}
10152
10153static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6
PM
10154 safi_t safi, enum bgp_show_adj_route_type type,
10155 const char *rmap_name, uint8_t use_json,
10156 json_object *json)
d62a17ae 10157{
10158 struct bgp_table *table;
10159 struct bgp_adj_in *ain;
10160 struct bgp_adj_out *adj;
10161 unsigned long output_count;
10162 unsigned long filtered_count;
10163 struct bgp_node *rn;
10164 int header1 = 1;
10165 struct bgp *bgp;
10166 int header2 = 1;
10167 struct attr attr;
10168 int ret;
10169 struct update_subgroup *subgrp;
10170 json_object *json_scode = NULL;
10171 json_object *json_ocode = NULL;
10172 json_object *json_ar = NULL;
10173 struct peer_af *paf;
10174
10175 if (use_json) {
10176 json_scode = json_object_new_object();
10177 json_ocode = json_object_new_object();
10178 json_ar = json_object_new_object();
10179
10180 json_object_string_add(json_scode, "suppressed", "s");
10181 json_object_string_add(json_scode, "damped", "d");
10182 json_object_string_add(json_scode, "history", "h");
10183 json_object_string_add(json_scode, "valid", "*");
10184 json_object_string_add(json_scode, "best", ">");
10185 json_object_string_add(json_scode, "multipath", "=");
10186 json_object_string_add(json_scode, "internal", "i");
10187 json_object_string_add(json_scode, "ribFailure", "r");
10188 json_object_string_add(json_scode, "stale", "S");
10189 json_object_string_add(json_scode, "removed", "R");
10190
10191 json_object_string_add(json_ocode, "igp", "i");
10192 json_object_string_add(json_ocode, "egp", "e");
10193 json_object_string_add(json_ocode, "incomplete", "?");
10194 }
a636c635 10195
d62a17ae 10196 bgp = peer->bgp;
a636c635 10197
d62a17ae 10198 if (!bgp) {
10199 if (use_json) {
10200 json_object_string_add(json, "alert", "no BGP");
10201 vty_out(vty, "%s\n", json_object_to_json_string(json));
10202 json_object_free(json);
10203 } else
10204 vty_out(vty, "%% No bgp\n");
10205 return;
10206 }
a636c635 10207
d62a17ae 10208 table = bgp->rib[afi][safi];
10209
10210 output_count = filtered_count = 0;
10211 subgrp = peer_subgroup(peer, afi, safi);
10212
6392aaa6 10213 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 10214 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
10215 if (use_json) {
10216 json_object_int_add(json, "bgpTableVersion",
10217 table->version);
10218 json_object_string_add(json, "bgpLocalRouterId",
10219 inet_ntoa(bgp->router_id));
10220 json_object_object_add(json, "bgpStatusCodes",
10221 json_scode);
10222 json_object_object_add(json, "bgpOriginCodes",
10223 json_ocode);
10224 json_object_string_add(json,
10225 "bgpOriginatingDefaultNetwork",
10226 "0.0.0.0");
10227 } else {
996c9314 10228 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 10229 ", local router ID is %s, vrf id ",
d62a17ae 10230 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
10231 if (bgp->vrf_id == VRF_UNKNOWN)
10232 vty_out(vty, "%s", VRFID_NONE_STR);
10233 else
10234 vty_out(vty, "%u", bgp->vrf_id);
10235 vty_out(vty, "\n");
d62a17ae 10236 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10237 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 10238 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10239
10240 vty_out(vty, "Originating default network 0.0.0.0\n\n");
10241 }
10242 header1 = 0;
10243 }
a636c635 10244
d62a17ae 10245 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
10246 if (type == bgp_show_adj_route_received
10247 || type == bgp_show_adj_route_filtered) {
d62a17ae 10248 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 10249 if (ain->peer != peer || !ain->attr)
ea47320b 10250 continue;
6392aaa6 10251
ea47320b
DL
10252 if (header1) {
10253 if (use_json) {
10254 json_object_int_add(
60466a63 10255 json, "bgpTableVersion",
ea47320b
DL
10256 0);
10257 json_object_string_add(
10258 json,
10259 "bgpLocalRouterId",
10260 inet_ntoa(
10261 bgp->router_id));
10262 json_object_object_add(
60466a63 10263 json, "bgpStatusCodes",
ea47320b
DL
10264 json_scode);
10265 json_object_object_add(
60466a63 10266 json, "bgpOriginCodes",
ea47320b
DL
10267 json_ocode);
10268 } else {
10269 vty_out(vty,
9df8b37c 10270 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 10271 inet_ntoa(
9df8b37c
PZ
10272 bgp->router_id));
10273 if (bgp->vrf_id == VRF_UNKNOWN)
10274 vty_out(vty, "%s",
10275 VRFID_NONE_STR);
10276 else
10277 vty_out(vty, "%u",
10278 bgp->vrf_id);
10279 vty_out(vty, "\n");
ea47320b
DL
10280 vty_out(vty,
10281 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10282 vty_out(vty,
10283 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
10284 vty_out(vty,
10285 BGP_SHOW_OCODE_HEADER);
d62a17ae 10286 }
ea47320b
DL
10287 header1 = 0;
10288 }
10289 if (header2) {
10290 if (!use_json)
10291 vty_out(vty, BGP_SHOW_HEADER);
10292 header2 = 0;
10293 }
6392aaa6
PM
10294
10295 bgp_attr_dup(&attr, ain->attr);
10296 ret = bgp_input_modifier(peer, &rn->p, &attr,
10297 afi, safi, rmap_name);
10298
10299 if (type == bgp_show_adj_route_filtered
b755861b
PM
10300 && ret != RMAP_DENY) {
10301 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10302 continue;
d62a17ae 10303 }
6392aaa6
PM
10304
10305 if (type == bgp_show_adj_route_received
10306 && ret == RMAP_DENY)
10307 filtered_count++;
10308
10309 route_vty_out_tmp(vty, &rn->p, &attr, safi,
10310 use_json, json_ar);
b755861b 10311 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10312 output_count++;
d62a17ae 10313 }
6392aaa6 10314 } else if (type == bgp_show_adj_route_advertised) {
d62a17ae 10315 for (adj = rn->adj_out; adj; adj = adj->next)
924c3f6a 10316 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 10317 if (paf->peer != peer || !adj->attr)
924c3f6a 10318 continue;
d62a17ae 10319
924c3f6a
DS
10320 if (header1) {
10321 if (use_json) {
10322 json_object_int_add(
10323 json,
10324 "bgpTableVersion",
10325 table->version);
10326 json_object_string_add(
10327 json,
10328 "bgpLocalRouterId",
10329 inet_ntoa(
10330 bgp->router_id));
10331 json_object_object_add(
10332 json,
10333 "bgpStatusCodes",
10334 json_scode);
10335 json_object_object_add(
10336 json,
10337 "bgpOriginCodes",
10338 json_ocode);
10339 } else {
10340 vty_out(vty,
10341 "BGP table version is %" PRIu64
9df8b37c 10342 ", local router ID is %s, vrf id ",
924c3f6a
DS
10343 table->version,
10344 inet_ntoa(
10345 bgp->router_id));
9df8b37c
PZ
10346 if (bgp->vrf_id ==
10347 VRF_UNKNOWN)
10348 vty_out(vty,
10349 "%s",
10350 VRFID_NONE_STR);
10351 else
10352 vty_out(vty,
10353 "%u",
10354 bgp->vrf_id);
10355 vty_out(vty, "\n");
924c3f6a
DS
10356 vty_out(vty,
10357 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10358 vty_out(vty,
10359 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
10360 vty_out(vty,
10361 BGP_SHOW_OCODE_HEADER);
a2addae8 10362 }
924c3f6a
DS
10363 header1 = 0;
10364 }
924c3f6a
DS
10365 if (header2) {
10366 if (!use_json)
10367 vty_out(vty,
10368 BGP_SHOW_HEADER);
10369 header2 = 0;
10370 }
d62a17ae 10371
b755861b
PM
10372 bgp_attr_dup(&attr, adj->attr);
10373 ret = bgp_output_modifier(
10374 peer, &rn->p, &attr, afi, safi,
10375 rmap_name);
f46d8e1e 10376
b755861b
PM
10377 if (ret != RMAP_DENY) {
10378 route_vty_out_tmp(vty, &rn->p,
10379 &attr, safi,
10380 use_json,
10381 json_ar);
10382 output_count++;
10383 } else {
10384 filtered_count++;
a2addae8 10385 }
b755861b
PM
10386
10387 bgp_attr_undup(&attr, adj->attr);
924c3f6a 10388 }
d62a17ae 10389 }
10390 }
d62a17ae 10391
d62a17ae 10392 if (use_json) {
6392aaa6
PM
10393 json_object_object_add(json, "advertisedRoutes", json_ar);
10394 json_object_int_add(json, "totalPrefixCounter", output_count);
10395 json_object_int_add(json, "filteredPrefixCounter",
10396 filtered_count);
10397
996c9314
LB
10398 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10399 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10400 json_object_free(json);
6392aaa6
PM
10401 } else if (output_count > 0) {
10402 if (filtered_count > 0)
10403 vty_out(vty,
10404 "\nTotal number of prefixes %ld (%ld filtered)\n",
10405 output_count, filtered_count);
10406 else
10407 vty_out(vty, "\nTotal number of prefixes %ld\n",
10408 output_count);
d62a17ae 10409 }
a636c635 10410}
2a71e9ce 10411
d62a17ae 10412static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6
PM
10413 safi_t safi, enum bgp_show_adj_route_type type,
10414 const char *rmap_name, uint8_t use_json)
0b16f239 10415{
d62a17ae 10416 json_object *json = NULL;
0b16f239 10417
d62a17ae 10418 if (use_json)
10419 json = json_object_new_object();
0b16f239 10420
d62a17ae 10421 /* labeled-unicast routes live in the unicast table */
10422 if (safi == SAFI_LABELED_UNICAST)
10423 safi = SAFI_UNICAST;
4dd6177e 10424
d62a17ae 10425 if (!peer || !peer->afc[afi][safi]) {
10426 if (use_json) {
10427 json_object_string_add(
10428 json, "warning",
10429 "No such neighbor or address family");
10430 vty_out(vty, "%s\n", json_object_to_json_string(json));
10431 json_object_free(json);
10432 } else
10433 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10434
d62a17ae 10435 return CMD_WARNING;
10436 }
10437
6392aaa6
PM
10438 if ((type == bgp_show_adj_route_received
10439 || type == bgp_show_adj_route_filtered)
d62a17ae 10440 && !CHECK_FLAG(peer->af_flags[afi][safi],
10441 PEER_FLAG_SOFT_RECONFIG)) {
10442 if (use_json) {
10443 json_object_string_add(
10444 json, "warning",
10445 "Inbound soft reconfiguration not enabled");
10446 vty_out(vty, "%s\n", json_object_to_json_string(json));
10447 json_object_free(json);
10448 } else
10449 vty_out(vty,
10450 "%% Inbound soft reconfiguration not enabled\n");
10451
10452 return CMD_WARNING;
10453 }
0b16f239 10454
6392aaa6 10455 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 10456
d62a17ae 10457 return CMD_SUCCESS;
a636c635 10458}
50ef26d4 10459
a636c635
DW
10460DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10461 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10462 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 10463 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 10464 SHOW_STR
10465 IP_STR
10466 BGP_STR
a636c635 10467 BGP_INSTANCE_HELP_STR
7395a2c9 10468 BGP_AFI_HELP_STR
4dd6177e 10469 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10470 "Detailed information on TCP and BGP neighbor connections\n"
10471 "Neighbor to display information about\n"
10472 "Neighbor to display information about\n"
91d37724 10473 "Neighbor on BGP configured interface\n"
a636c635 10474 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
10475 "Display the received routes from neighbor\n"
10476 "Display the filtered routes received from neighbor\n"
a636c635
DW
10477 "Route-map to modify the attributes\n"
10478 "Name of the route map\n"
9973d184 10479 JSON_STR)
718e3744 10480{
d62a17ae 10481 afi_t afi = AFI_IP6;
10482 safi_t safi = SAFI_UNICAST;
10483 char *rmap_name = NULL;
10484 char *peerstr = NULL;
d62a17ae 10485 struct bgp *bgp = NULL;
10486 struct peer *peer;
6392aaa6 10487 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
bb46e94f 10488
d62a17ae 10489 int idx = 0;
d62a17ae 10490 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10491 &bgp);
10492 if (!idx)
10493 return CMD_WARNING;
c493f2d8 10494
d62a17ae 10495 int uj = use_json(argc, argv);
6392aaa6 10496
d62a17ae 10497 if (uj)
10498 argc--;
30a6a167 10499
d62a17ae 10500 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10501 argv_find(argv, argc, "neighbors", &idx);
10502 peerstr = argv[++idx]->arg;
8c3deaae 10503
d62a17ae 10504 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10505 if (!peer)
10506 return CMD_WARNING;
856ca177 10507
d62a17ae 10508 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
10509 type = bgp_show_adj_route_advertised;
10510 else if (argv_find(argv, argc, "received-routes", &idx))
10511 type = bgp_show_adj_route_received;
10512 else if (argv_find(argv, argc, "filtered-routes", &idx))
10513 type = bgp_show_adj_route_filtered;
10514
d62a17ae 10515 if (argv_find(argv, argc, "route-map", &idx))
10516 rmap_name = argv[++idx]->arg;
95cbbd2a 10517
6392aaa6 10518 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
10519}
10520
718e3744 10521DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10522 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10523 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10524 SHOW_STR
10525 IP_STR
10526 BGP_STR
8c3deaae
QY
10527 "Address Family\n"
10528 "Address Family\n"
718e3744 10529 "Address Family modifier\n"
10530 "Detailed information on TCP and BGP neighbor connections\n"
10531 "Neighbor to display information about\n"
10532 "Neighbor to display information about\n"
91d37724 10533 "Neighbor on BGP configured interface\n"
718e3744 10534 "Display information received from a BGP neighbor\n"
856ca177 10535 "Display the prefixlist filter\n"
9973d184 10536 JSON_STR)
718e3744 10537{
d62a17ae 10538 afi_t afi = AFI_IP6;
10539 safi_t safi = SAFI_UNICAST;
10540 char *peerstr = NULL;
10541
10542 char name[BUFSIZ];
10543 union sockunion su;
10544 struct peer *peer;
10545 int count, ret;
10546
10547 int idx = 0;
10548
10549 /* show [ip] bgp */
10550 if (argv_find(argv, argc, "ip", &idx))
10551 afi = AFI_IP;
10552 /* [<ipv4|ipv6> [unicast]] */
10553 if (argv_find(argv, argc, "ipv4", &idx))
10554 afi = AFI_IP;
10555 if (argv_find(argv, argc, "ipv6", &idx))
10556 afi = AFI_IP6;
10557 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10558 argv_find(argv, argc, "neighbors", &idx);
10559 peerstr = argv[++idx]->arg;
10560
d7c0a89a 10561 uint8_t uj = use_json(argc, argv);
d62a17ae 10562
10563 ret = str2sockunion(peerstr, &su);
10564 if (ret < 0) {
10565 peer = peer_lookup_by_conf_if(NULL, peerstr);
10566 if (!peer) {
10567 if (uj)
10568 vty_out(vty, "{}\n");
10569 else
10570 vty_out(vty,
10571 "%% Malformed address or name: %s\n",
10572 peerstr);
10573 return CMD_WARNING;
10574 }
10575 } else {
10576 peer = peer_lookup(NULL, &su);
10577 if (!peer) {
10578 if (uj)
10579 vty_out(vty, "{}\n");
10580 else
10581 vty_out(vty, "No peer\n");
10582 return CMD_WARNING;
10583 }
10584 }
718e3744 10585
d62a17ae 10586 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10587 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10588 if (count) {
10589 if (!uj)
10590 vty_out(vty, "Address Family: %s\n",
10591 afi_safi_print(afi, safi));
10592 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10593 } else {
10594 if (uj)
10595 vty_out(vty, "{}\n");
10596 else
10597 vty_out(vty, "No functional output\n");
10598 }
718e3744 10599
d62a17ae 10600 return CMD_SUCCESS;
10601}
10602
10603static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10604 afi_t afi, safi_t safi,
d7c0a89a 10605 enum bgp_show_type type, uint8_t use_json)
d62a17ae 10606{
8a893163
DW
10607 /* labeled-unicast routes live in the unicast table */
10608 if (safi == SAFI_LABELED_UNICAST)
10609 safi = SAFI_UNICAST;
10610
d62a17ae 10611 if (!peer || !peer->afc[afi][safi]) {
10612 if (use_json) {
10613 json_object *json_no = NULL;
10614 json_no = json_object_new_object();
10615 json_object_string_add(
10616 json_no, "warning",
10617 "No such neighbor or address family");
10618 vty_out(vty, "%s\n",
10619 json_object_to_json_string(json_no));
10620 json_object_free(json_no);
10621 } else
10622 vty_out(vty, "%% No such neighbor or address family\n");
10623 return CMD_WARNING;
10624 }
47fc97cc 10625
d62a17ae 10626 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10627}
10628
dba3c1d3
PG
10629DEFUN (show_ip_bgp_flowspec_routes_detailed,
10630 show_ip_bgp_flowspec_routes_detailed_cmd,
10631 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
10632 SHOW_STR
10633 IP_STR
10634 BGP_STR
10635 BGP_INSTANCE_HELP_STR
10636 BGP_AFI_HELP_STR
10637 "SAFI Flowspec\n"
10638 "Detailed information on flowspec entries\n"
10639 JSON_STR)
10640{
10641 afi_t afi = AFI_IP;
10642 safi_t safi = SAFI_UNICAST;
10643 struct bgp *bgp = NULL;
10644 int idx = 0;
10645
10646 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10647 &bgp);
10648 if (!idx)
10649 return CMD_WARNING;
10650
10651 return bgp_show(vty, bgp, afi, safi,
10652 bgp_show_type_detail, NULL, use_json(argc, argv));
10653}
10654
718e3744 10655DEFUN (show_ip_bgp_neighbor_routes,
10656 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10657 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10658 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10659 SHOW_STR
10660 IP_STR
10661 BGP_STR
8386ac43 10662 BGP_INSTANCE_HELP_STR
4f280b15 10663 BGP_AFI_HELP_STR
4dd6177e 10664 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10665 "Detailed information on TCP and BGP neighbor connections\n"
10666 "Neighbor to display information about\n"
10667 "Neighbor to display information about\n"
91d37724 10668 "Neighbor on BGP configured interface\n"
2525cf39 10669 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10670 "Display the dampened routes received from neighbor\n"
10671 "Display routes learned from neighbor\n"
9973d184 10672 JSON_STR)
718e3744 10673{
d62a17ae 10674 char *peerstr = NULL;
10675 struct bgp *bgp = NULL;
10676 afi_t afi = AFI_IP6;
10677 safi_t safi = SAFI_UNICAST;
10678 struct peer *peer;
10679 enum bgp_show_type sh_type = bgp_show_type_neighbor;
856ca177 10680
d62a17ae 10681 int idx = 0;
bb46e94f 10682
d62a17ae 10683 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10684 &bgp);
10685 if (!idx)
10686 return CMD_WARNING;
c493f2d8 10687
d62a17ae 10688 int uj = use_json(argc, argv);
10689 if (uj)
10690 argc--;
30a6a167 10691
d62a17ae 10692 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10693 argv_find(argv, argc, "neighbors", &idx);
10694 peerstr = argv[++idx]->arg;
8c3deaae 10695
d62a17ae 10696 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 10697 if (!peer)
d62a17ae 10698 return CMD_WARNING;
bb46e94f 10699
d62a17ae 10700 if (argv_find(argv, argc, "flap-statistics", &idx))
10701 sh_type = bgp_show_type_flap_neighbor;
10702 else if (argv_find(argv, argc, "dampened-routes", &idx))
10703 sh_type = bgp_show_type_damp_neighbor;
10704 else if (argv_find(argv, argc, "routes", &idx))
10705 sh_type = bgp_show_type_neighbor;
2525cf39 10706
d62a17ae 10707 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 10708}
6b0655a2 10709
734b349e 10710struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10711
d62a17ae 10712struct bgp_distance {
10713 /* Distance value for the IP source prefix. */
d7c0a89a 10714 uint8_t distance;
718e3744 10715
d62a17ae 10716 /* Name of the access-list to be matched. */
10717 char *access_list;
718e3744 10718};
10719
4f280b15
LB
10720DEFUN (show_bgp_afi_vpn_rd_route,
10721 show_bgp_afi_vpn_rd_route_cmd,
d114b977 10722 "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
10723 SHOW_STR
10724 BGP_STR
10725 BGP_AFI_HELP_STR
10726 "Address Family modifier\n"
10727 "Display information for a route distinguisher\n"
10728 "Route Distinguisher\n"
7395a2c9
DS
10729 "Network in the BGP routing table to display\n"
10730 "Network in the BGP routing table to display\n"
10731 JSON_STR)
4f280b15 10732{
d62a17ae 10733 int ret;
10734 struct prefix_rd prd;
10735 afi_t afi = AFI_MAX;
10736 int idx = 0;
4f280b15 10737
ff6566f3
DS
10738 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
10739 vty_out(vty, "%% Malformed Address Family\n");
10740 return CMD_WARNING;
10741 }
10742
d62a17ae 10743 ret = str2prefix_rd(argv[5]->arg, &prd);
10744 if (!ret) {
10745 vty_out(vty, "%% Malformed Route Distinguisher\n");
10746 return CMD_WARNING;
10747 }
ff6566f3 10748
d62a17ae 10749 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
10750 0, BGP_PATH_ALL, use_json(argc, argv));
4f280b15
LB
10751}
10752
d62a17ae 10753static struct bgp_distance *bgp_distance_new(void)
718e3744 10754{
d62a17ae 10755 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 10756}
10757
d62a17ae 10758static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 10759{
d62a17ae 10760 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 10761}
10762
d62a17ae 10763static int bgp_distance_set(struct vty *vty, const char *distance_str,
10764 const char *ip_str, const char *access_list_str)
718e3744 10765{
d62a17ae 10766 int ret;
10767 afi_t afi;
10768 safi_t safi;
10769 struct prefix p;
d7c0a89a 10770 uint8_t distance;
d62a17ae 10771 struct bgp_node *rn;
10772 struct bgp_distance *bdistance;
718e3744 10773
d62a17ae 10774 afi = bgp_node_afi(vty);
10775 safi = bgp_node_safi(vty);
734b349e 10776
d62a17ae 10777 ret = str2prefix(ip_str, &p);
10778 if (ret == 0) {
10779 vty_out(vty, "Malformed prefix\n");
10780 return CMD_WARNING_CONFIG_FAILED;
10781 }
718e3744 10782
d62a17ae 10783 distance = atoi(distance_str);
718e3744 10784
d62a17ae 10785 /* Get BGP distance node. */
10786 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
10787 if (rn->info) {
10788 bdistance = rn->info;
10789 bgp_unlock_node(rn);
10790 } else {
10791 bdistance = bgp_distance_new();
10792 rn->info = bdistance;
10793 }
718e3744 10794
d62a17ae 10795 /* Set distance value. */
10796 bdistance->distance = distance;
718e3744 10797
d62a17ae 10798 /* Reset access-list configuration. */
10799 if (bdistance->access_list) {
10800 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10801 bdistance->access_list = NULL;
10802 }
10803 if (access_list_str)
10804 bdistance->access_list =
10805 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 10806
d62a17ae 10807 return CMD_SUCCESS;
718e3744 10808}
10809
d62a17ae 10810static int bgp_distance_unset(struct vty *vty, const char *distance_str,
10811 const char *ip_str, const char *access_list_str)
718e3744 10812{
d62a17ae 10813 int ret;
10814 afi_t afi;
10815 safi_t safi;
10816 struct prefix p;
10817 int distance;
10818 struct bgp_node *rn;
10819 struct bgp_distance *bdistance;
718e3744 10820
d62a17ae 10821 afi = bgp_node_afi(vty);
10822 safi = bgp_node_safi(vty);
734b349e 10823
d62a17ae 10824 ret = str2prefix(ip_str, &p);
10825 if (ret == 0) {
10826 vty_out(vty, "Malformed prefix\n");
10827 return CMD_WARNING_CONFIG_FAILED;
10828 }
718e3744 10829
d62a17ae 10830 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
10831 (struct prefix *)&p);
10832 if (!rn) {
10833 vty_out(vty, "Can't find specified prefix\n");
10834 return CMD_WARNING_CONFIG_FAILED;
10835 }
718e3744 10836
d62a17ae 10837 bdistance = rn->info;
10838 distance = atoi(distance_str);
1f9a9fff 10839
d62a17ae 10840 if (bdistance->distance != distance) {
10841 vty_out(vty, "Distance does not match configured\n");
10842 return CMD_WARNING_CONFIG_FAILED;
10843 }
718e3744 10844
d62a17ae 10845 if (bdistance->access_list)
10846 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10847 bgp_distance_free(bdistance);
718e3744 10848
d62a17ae 10849 rn->info = NULL;
10850 bgp_unlock_node(rn);
10851 bgp_unlock_node(rn);
718e3744 10852
d62a17ae 10853 return CMD_SUCCESS;
718e3744 10854}
10855
718e3744 10856/* Apply BGP information to distance method. */
d7c0a89a
QY
10857uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
10858 safi_t safi, struct bgp *bgp)
d62a17ae 10859{
10860 struct bgp_node *rn;
10861 struct prefix q;
10862 struct peer *peer;
10863 struct bgp_distance *bdistance;
10864 struct access_list *alist;
10865 struct bgp_static *bgp_static;
10866
10867 if (!bgp)
10868 return 0;
10869
10870 peer = rinfo->peer;
10871
10872 /* Check source address. */
10873 sockunion2hostprefix(&peer->su, &q);
10874 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
10875 if (rn) {
10876 bdistance = rn->info;
10877 bgp_unlock_node(rn);
10878
10879 if (bdistance->access_list) {
10880 alist = access_list_lookup(afi, bdistance->access_list);
10881 if (alist
10882 && access_list_apply(alist, p) == FILTER_PERMIT)
10883 return bdistance->distance;
10884 } else
10885 return bdistance->distance;
718e3744 10886 }
718e3744 10887
d62a17ae 10888 /* Backdoor check. */
10889 rn = bgp_node_lookup(bgp->route[afi][safi], p);
10890 if (rn) {
10891 bgp_static = rn->info;
10892 bgp_unlock_node(rn);
718e3744 10893
d62a17ae 10894 if (bgp_static->backdoor) {
10895 if (bgp->distance_local[afi][safi])
10896 return bgp->distance_local[afi][safi];
10897 else
10898 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10899 }
718e3744 10900 }
718e3744 10901
d62a17ae 10902 if (peer->sort == BGP_PEER_EBGP) {
10903 if (bgp->distance_ebgp[afi][safi])
10904 return bgp->distance_ebgp[afi][safi];
10905 return ZEBRA_EBGP_DISTANCE_DEFAULT;
10906 } else {
10907 if (bgp->distance_ibgp[afi][safi])
10908 return bgp->distance_ibgp[afi][safi];
10909 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10910 }
718e3744 10911}
10912
10913DEFUN (bgp_distance,
10914 bgp_distance_cmd,
6147e2c6 10915 "distance bgp (1-255) (1-255) (1-255)",
718e3744 10916 "Define an administrative distance\n"
10917 "BGP distance\n"
10918 "Distance for routes external to the AS\n"
10919 "Distance for routes internal to the AS\n"
10920 "Distance for local routes\n")
10921{
d62a17ae 10922 VTY_DECLVAR_CONTEXT(bgp, bgp);
10923 int idx_number = 2;
10924 int idx_number_2 = 3;
10925 int idx_number_3 = 4;
10926 afi_t afi;
10927 safi_t safi;
718e3744 10928
d62a17ae 10929 afi = bgp_node_afi(vty);
10930 safi = bgp_node_safi(vty);
718e3744 10931
d62a17ae 10932 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
10933 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
10934 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
10935 return CMD_SUCCESS;
718e3744 10936}
10937
10938DEFUN (no_bgp_distance,
10939 no_bgp_distance_cmd,
a636c635 10940 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 10941 NO_STR
10942 "Define an administrative distance\n"
10943 "BGP distance\n"
10944 "Distance for routes external to the AS\n"
10945 "Distance for routes internal to the AS\n"
10946 "Distance for local routes\n")
10947{
d62a17ae 10948 VTY_DECLVAR_CONTEXT(bgp, bgp);
10949 afi_t afi;
10950 safi_t safi;
718e3744 10951
d62a17ae 10952 afi = bgp_node_afi(vty);
10953 safi = bgp_node_safi(vty);
718e3744 10954
d62a17ae 10955 bgp->distance_ebgp[afi][safi] = 0;
10956 bgp->distance_ibgp[afi][safi] = 0;
10957 bgp->distance_local[afi][safi] = 0;
10958 return CMD_SUCCESS;
718e3744 10959}
10960
718e3744 10961
10962DEFUN (bgp_distance_source,
10963 bgp_distance_source_cmd,
6147e2c6 10964 "distance (1-255) A.B.C.D/M",
718e3744 10965 "Define an administrative distance\n"
10966 "Administrative distance\n"
10967 "IP source prefix\n")
10968{
d62a17ae 10969 int idx_number = 1;
10970 int idx_ipv4_prefixlen = 2;
10971 bgp_distance_set(vty, argv[idx_number]->arg,
10972 argv[idx_ipv4_prefixlen]->arg, NULL);
10973 return CMD_SUCCESS;
718e3744 10974}
10975
10976DEFUN (no_bgp_distance_source,
10977 no_bgp_distance_source_cmd,
6147e2c6 10978 "no distance (1-255) A.B.C.D/M",
718e3744 10979 NO_STR
10980 "Define an administrative distance\n"
10981 "Administrative distance\n"
10982 "IP source prefix\n")
10983{
d62a17ae 10984 int idx_number = 2;
10985 int idx_ipv4_prefixlen = 3;
10986 bgp_distance_unset(vty, argv[idx_number]->arg,
10987 argv[idx_ipv4_prefixlen]->arg, NULL);
10988 return CMD_SUCCESS;
718e3744 10989}
10990
10991DEFUN (bgp_distance_source_access_list,
10992 bgp_distance_source_access_list_cmd,
6147e2c6 10993 "distance (1-255) A.B.C.D/M WORD",
718e3744 10994 "Define an administrative distance\n"
10995 "Administrative distance\n"
10996 "IP source prefix\n"
10997 "Access list name\n")
10998{
d62a17ae 10999 int idx_number = 1;
11000 int idx_ipv4_prefixlen = 2;
11001 int idx_word = 3;
11002 bgp_distance_set(vty, argv[idx_number]->arg,
11003 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11004 return CMD_SUCCESS;
718e3744 11005}
11006
11007DEFUN (no_bgp_distance_source_access_list,
11008 no_bgp_distance_source_access_list_cmd,
6147e2c6 11009 "no distance (1-255) A.B.C.D/M WORD",
718e3744 11010 NO_STR
11011 "Define an administrative distance\n"
11012 "Administrative distance\n"
11013 "IP source prefix\n"
11014 "Access list name\n")
11015{
d62a17ae 11016 int idx_number = 2;
11017 int idx_ipv4_prefixlen = 3;
11018 int idx_word = 4;
11019 bgp_distance_unset(vty, argv[idx_number]->arg,
11020 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11021 return CMD_SUCCESS;
718e3744 11022}
6b0655a2 11023
734b349e
MZ
11024DEFUN (ipv6_bgp_distance_source,
11025 ipv6_bgp_distance_source_cmd,
39e92c06 11026 "distance (1-255) X:X::X:X/M",
734b349e
MZ
11027 "Define an administrative distance\n"
11028 "Administrative distance\n"
11029 "IP source prefix\n")
11030{
d62a17ae 11031 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
11032 return CMD_SUCCESS;
734b349e
MZ
11033}
11034
11035DEFUN (no_ipv6_bgp_distance_source,
11036 no_ipv6_bgp_distance_source_cmd,
39e92c06 11037 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
11038 NO_STR
11039 "Define an administrative distance\n"
11040 "Administrative distance\n"
11041 "IP source prefix\n")
11042{
d62a17ae 11043 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
11044 return CMD_SUCCESS;
734b349e
MZ
11045}
11046
11047DEFUN (ipv6_bgp_distance_source_access_list,
11048 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11049 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11050 "Define an administrative distance\n"
11051 "Administrative distance\n"
11052 "IP source prefix\n"
11053 "Access list name\n")
11054{
d62a17ae 11055 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
11056 return CMD_SUCCESS;
734b349e
MZ
11057}
11058
11059DEFUN (no_ipv6_bgp_distance_source_access_list,
11060 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11061 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11062 NO_STR
11063 "Define an administrative distance\n"
11064 "Administrative distance\n"
11065 "IP source prefix\n"
11066 "Access list name\n")
11067{
d62a17ae 11068 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
11069 return CMD_SUCCESS;
734b349e
MZ
11070}
11071
718e3744 11072DEFUN (bgp_damp_set,
11073 bgp_damp_set_cmd,
31500417 11074 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11075 "BGP Specific commands\n"
11076 "Enable route-flap dampening\n"
11077 "Half-life time for the penalty\n"
11078 "Value to start reusing a route\n"
11079 "Value to start suppressing a route\n"
11080 "Maximum duration to suppress a stable route\n")
11081{
d62a17ae 11082 VTY_DECLVAR_CONTEXT(bgp, bgp);
11083 int idx_half_life = 2;
11084 int idx_reuse = 3;
11085 int idx_suppress = 4;
11086 int idx_max_suppress = 5;
11087 int half = DEFAULT_HALF_LIFE * 60;
11088 int reuse = DEFAULT_REUSE;
11089 int suppress = DEFAULT_SUPPRESS;
11090 int max = 4 * half;
11091
11092 if (argc == 6) {
11093 half = atoi(argv[idx_half_life]->arg) * 60;
11094 reuse = atoi(argv[idx_reuse]->arg);
11095 suppress = atoi(argv[idx_suppress]->arg);
11096 max = atoi(argv[idx_max_suppress]->arg) * 60;
11097 } else if (argc == 3) {
11098 half = atoi(argv[idx_half_life]->arg) * 60;
11099 max = 4 * half;
11100 }
718e3744 11101
d62a17ae 11102 if (suppress < reuse) {
11103 vty_out(vty,
11104 "Suppress value cannot be less than reuse value \n");
11105 return 0;
11106 }
7ebe9748 11107
d62a17ae 11108 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
11109 reuse, suppress, max);
718e3744 11110}
11111
718e3744 11112DEFUN (bgp_damp_unset,
11113 bgp_damp_unset_cmd,
d04c479d 11114 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11115 NO_STR
11116 "BGP Specific commands\n"
16cedbb0
QY
11117 "Enable route-flap dampening\n"
11118 "Half-life time for the penalty\n"
11119 "Value to start reusing a route\n"
11120 "Value to start suppressing a route\n"
11121 "Maximum duration to suppress a stable route\n")
718e3744 11122{
d62a17ae 11123 VTY_DECLVAR_CONTEXT(bgp, bgp);
11124 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 11125}
11126
718e3744 11127/* Display specified route of BGP table. */
d62a17ae 11128static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
11129 const char *ip_str, afi_t afi, safi_t safi,
11130 struct prefix_rd *prd, int prefix_check)
11131{
11132 int ret;
11133 struct prefix match;
11134 struct bgp_node *rn;
11135 struct bgp_node *rm;
11136 struct bgp_info *ri;
11137 struct bgp_info *ri_temp;
11138 struct bgp *bgp;
11139 struct bgp_table *table;
11140
11141 /* BGP structure lookup. */
11142 if (view_name) {
11143 bgp = bgp_lookup_by_name(view_name);
11144 if (bgp == NULL) {
11145 vty_out(vty, "%% Can't find BGP instance %s\n",
11146 view_name);
11147 return CMD_WARNING;
11148 }
11149 } else {
11150 bgp = bgp_get_default();
11151 if (bgp == NULL) {
11152 vty_out(vty, "%% No BGP process is configured\n");
11153 return CMD_WARNING;
11154 }
718e3744 11155 }
718e3744 11156
d62a17ae 11157 /* Check IP address argument. */
11158 ret = str2prefix(ip_str, &match);
11159 if (!ret) {
11160 vty_out(vty, "%% address is malformed\n");
11161 return CMD_WARNING;
11162 }
718e3744 11163
d62a17ae 11164 match.family = afi2family(afi);
11165
11166 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
11167 || (safi == SAFI_EVPN)) {
11168 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11169 rn = bgp_route_next(rn)) {
11170 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11171 continue;
ea47320b
DL
11172 if ((table = rn->info) == NULL)
11173 continue;
11174 if ((rm = bgp_node_match(table, &match)) == NULL)
11175 continue;
d62a17ae 11176
ea47320b
DL
11177 if (!prefix_check
11178 || rm->p.prefixlen == match.prefixlen) {
11179 ri = rm->info;
11180 while (ri) {
60466a63 11181 if (ri->extra && ri->extra->damp_info) {
ea47320b
DL
11182 ri_temp = ri->next;
11183 bgp_damp_info_free(
60466a63
QY
11184 ri->extra->damp_info,
11185 1);
ea47320b
DL
11186 ri = ri_temp;
11187 } else
11188 ri = ri->next;
d62a17ae 11189 }
ea47320b
DL
11190 }
11191
11192 bgp_unlock_node(rm);
d62a17ae 11193 }
11194 } else {
11195 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11196 != NULL) {
11197 if (!prefix_check
11198 || rn->p.prefixlen == match.prefixlen) {
11199 ri = rn->info;
11200 while (ri) {
11201 if (ri->extra && ri->extra->damp_info) {
11202 ri_temp = ri->next;
11203 bgp_damp_info_free(
11204 ri->extra->damp_info,
11205 1);
11206 ri = ri_temp;
11207 } else
11208 ri = ri->next;
11209 }
11210 }
11211
11212 bgp_unlock_node(rn);
11213 }
11214 }
718e3744 11215
d62a17ae 11216 return CMD_SUCCESS;
718e3744 11217}
11218
11219DEFUN (clear_ip_bgp_dampening,
11220 clear_ip_bgp_dampening_cmd,
11221 "clear ip bgp dampening",
11222 CLEAR_STR
11223 IP_STR
11224 BGP_STR
11225 "Clear route flap dampening information\n")
11226{
d62a17ae 11227 bgp_damp_info_clean();
11228 return CMD_SUCCESS;
718e3744 11229}
11230
11231DEFUN (clear_ip_bgp_dampening_prefix,
11232 clear_ip_bgp_dampening_prefix_cmd,
11233 "clear ip bgp dampening A.B.C.D/M",
11234 CLEAR_STR
11235 IP_STR
11236 BGP_STR
11237 "Clear route flap dampening information\n"
0c7b1b01 11238 "IPv4 prefix\n")
718e3744 11239{
d62a17ae 11240 int idx_ipv4_prefixlen = 4;
11241 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11242 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11243}
11244
11245DEFUN (clear_ip_bgp_dampening_address,
11246 clear_ip_bgp_dampening_address_cmd,
11247 "clear ip bgp dampening A.B.C.D",
11248 CLEAR_STR
11249 IP_STR
11250 BGP_STR
11251 "Clear route flap dampening information\n"
11252 "Network to clear damping information\n")
11253{
d62a17ae 11254 int idx_ipv4 = 4;
11255 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11256 SAFI_UNICAST, NULL, 0);
718e3744 11257}
11258
11259DEFUN (clear_ip_bgp_dampening_address_mask,
11260 clear_ip_bgp_dampening_address_mask_cmd,
11261 "clear ip bgp dampening A.B.C.D A.B.C.D",
11262 CLEAR_STR
11263 IP_STR
11264 BGP_STR
11265 "Clear route flap dampening information\n"
11266 "Network to clear damping information\n"
11267 "Network mask\n")
11268{
d62a17ae 11269 int idx_ipv4 = 4;
11270 int idx_ipv4_2 = 5;
11271 int ret;
11272 char prefix_str[BUFSIZ];
718e3744 11273
d62a17ae 11274 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11275 prefix_str);
11276 if (!ret) {
11277 vty_out(vty, "%% Inconsistent address and mask\n");
11278 return CMD_WARNING;
11279 }
718e3744 11280
d62a17ae 11281 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11282 NULL, 0);
718e3744 11283}
6b0655a2 11284
587ff0fd 11285/* also used for encap safi */
2b791107
DL
11286static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11287 afi_t afi, safi_t safi)
d62a17ae 11288{
11289 struct bgp_node *prn;
11290 struct bgp_node *rn;
11291 struct bgp_table *table;
11292 struct prefix *p;
11293 struct prefix_rd *prd;
11294 struct bgp_static *bgp_static;
11295 mpls_label_t label;
11296 char buf[SU_ADDRSTRLEN];
11297 char rdbuf[RD_ADDRSTRLEN];
11298
11299 /* Network configuration. */
11300 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11301 prn = bgp_route_next(prn)) {
11302 if ((table = prn->info) == NULL)
11303 continue;
d62a17ae 11304
60466a63 11305 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
ea47320b
DL
11306 if ((bgp_static = rn->info) == NULL)
11307 continue;
d62a17ae 11308
ea47320b
DL
11309 p = &rn->p;
11310 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11311
ea47320b 11312 /* "network" configuration display. */
06b9f471 11313 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11314 label = decode_label(&bgp_static->label);
11315
11316 vty_out(vty, " network %s/%d rd %s",
11317 inet_ntop(p->family, &p->u.prefix, buf,
11318 SU_ADDRSTRLEN),
11319 p->prefixlen, rdbuf);
11320 if (safi == SAFI_MPLS_VPN)
11321 vty_out(vty, " label %u", label);
11322
11323 if (bgp_static->rmap.name)
11324 vty_out(vty, " route-map %s",
11325 bgp_static->rmap.name);
e2a86ad9
DS
11326
11327 if (bgp_static->backdoor)
11328 vty_out(vty, " backdoor");
11329
ea47320b
DL
11330 vty_out(vty, "\n");
11331 }
11332 }
d62a17ae 11333}
11334
2b791107
DL
11335static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11336 afi_t afi, safi_t safi)
d62a17ae 11337{
11338 struct bgp_node *prn;
11339 struct bgp_node *rn;
11340 struct bgp_table *table;
11341 struct prefix *p;
11342 struct prefix_rd *prd;
11343 struct bgp_static *bgp_static;
11344 char buf[PREFIX_STRLEN];
11345 char buf2[SU_ADDRSTRLEN];
11346 char rdbuf[RD_ADDRSTRLEN];
11347
11348 /* Network configuration. */
11349 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11350 prn = bgp_route_next(prn)) {
11351 if ((table = prn->info) == NULL)
11352 continue;
d62a17ae 11353
60466a63 11354 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
ea47320b
DL
11355 if ((bgp_static = rn->info) == NULL)
11356 continue;
d62a17ae 11357
ea47320b
DL
11358 char *macrouter = NULL;
11359 char *esi = NULL;
d62a17ae 11360
ea47320b
DL
11361 if (bgp_static->router_mac)
11362 macrouter = prefix_mac2str(
11363 bgp_static->router_mac, NULL, 0);
11364 if (bgp_static->eth_s_id)
11365 esi = esi2str(bgp_static->eth_s_id);
11366 p = &rn->p;
11367 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11368
ea47320b 11369 /* "network" configuration display. */
06b9f471 11370 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11371 if (p->u.prefix_evpn.route_type == 5) {
11372 char local_buf[PREFIX_STRLEN];
3714a385 11373 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
11374 struct prefix_evpn *)p)
11375 ? AF_INET
11376 : AF_INET6;
3714a385 11377 inet_ntop(family,
11378 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
11379 local_buf, PREFIX_STRLEN);
11380 sprintf(buf, "%s/%u", local_buf,
3714a385 11381 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
11382 } else {
11383 prefix2str(p, buf, sizeof(buf));
11384 }
ea47320b 11385
a4d82a8a
PZ
11386 if (bgp_static->gatewayIp.family == AF_INET
11387 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
11388 inet_ntop(bgp_static->gatewayIp.family,
11389 &bgp_static->gatewayIp.u.prefix, buf2,
11390 sizeof(buf2));
ea47320b 11391 vty_out(vty,
7bcc8dac 11392 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 11393 buf, rdbuf,
11394 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 11395 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11396 macrouter);
11397
11398 if (macrouter)
11399 XFREE(MTYPE_TMP, macrouter);
11400 if (esi)
11401 XFREE(MTYPE_TMP, esi);
11402 }
11403 }
3da6fcd5
PG
11404}
11405
718e3744 11406/* Configuration of static route announcement and aggregate
11407 information. */
2b791107
DL
11408void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11409 safi_t safi)
d62a17ae 11410{
11411 struct bgp_node *rn;
11412 struct prefix *p;
11413 struct bgp_static *bgp_static;
11414 struct bgp_aggregate *bgp_aggregate;
11415 char buf[SU_ADDRSTRLEN];
11416
2b791107
DL
11417 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11418 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11419 return;
11420 }
d62a17ae 11421
2b791107
DL
11422 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11423 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11424 return;
11425 }
d62a17ae 11426
11427 /* Network configuration. */
11428 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b
DL
11429 rn = bgp_route_next(rn)) {
11430 if ((bgp_static = rn->info) == NULL)
11431 continue;
d62a17ae 11432
ea47320b 11433 p = &rn->p;
d62a17ae 11434
ea47320b 11435 /* "network" configuration display. */
60466a63 11436 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
d7c0a89a 11437 uint32_t destination;
ea47320b 11438 struct in_addr netmask;
d62a17ae 11439
ea47320b
DL
11440 destination = ntohl(p->u.prefix4.s_addr);
11441 masklen2ip(p->prefixlen, &netmask);
11442 vty_out(vty, " network %s",
11443 inet_ntop(p->family, &p->u.prefix, buf,
11444 SU_ADDRSTRLEN));
d62a17ae 11445
ea47320b
DL
11446 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11447 || (IN_CLASSB(destination) && p->prefixlen == 16)
11448 || (IN_CLASSA(destination) && p->prefixlen == 8)
11449 || p->u.prefix4.s_addr == 0) {
11450 /* Natural mask is not display. */
11451 } else
11452 vty_out(vty, " mask %s", inet_ntoa(netmask));
11453 } else {
11454 vty_out(vty, " network %s/%d",
11455 inet_ntop(p->family, &p->u.prefix, buf,
11456 SU_ADDRSTRLEN),
11457 p->prefixlen);
11458 }
d62a17ae 11459
ea47320b
DL
11460 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11461 vty_out(vty, " label-index %u",
11462 bgp_static->label_index);
d62a17ae 11463
ea47320b
DL
11464 if (bgp_static->rmap.name)
11465 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
11466
11467 if (bgp_static->backdoor)
11468 vty_out(vty, " backdoor");
718e3744 11469
ea47320b
DL
11470 vty_out(vty, "\n");
11471 }
11472
d62a17ae 11473 /* Aggregate-address configuration. */
11474 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b
DL
11475 rn = bgp_route_next(rn)) {
11476 if ((bgp_aggregate = rn->info) == NULL)
11477 continue;
d62a17ae 11478
ea47320b 11479 p = &rn->p;
d62a17ae 11480
ea47320b
DL
11481 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11482 struct in_addr netmask;
d62a17ae 11483
ea47320b
DL
11484 masklen2ip(p->prefixlen, &netmask);
11485 vty_out(vty, " aggregate-address %s %s",
11486 inet_ntop(p->family, &p->u.prefix, buf,
11487 SU_ADDRSTRLEN),
11488 inet_ntoa(netmask));
11489 } else {
11490 vty_out(vty, " aggregate-address %s/%d",
11491 inet_ntop(p->family, &p->u.prefix, buf,
11492 SU_ADDRSTRLEN),
11493 p->prefixlen);
11494 }
d62a17ae 11495
ea47320b
DL
11496 if (bgp_aggregate->as_set)
11497 vty_out(vty, " as-set");
d62a17ae 11498
ea47320b
DL
11499 if (bgp_aggregate->summary_only)
11500 vty_out(vty, " summary-only");
718e3744 11501
ea47320b
DL
11502 vty_out(vty, "\n");
11503 }
d62a17ae 11504}
734b349e 11505
2b791107 11506void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11507 safi_t safi)
d62a17ae 11508{
11509 struct bgp_node *rn;
11510 struct bgp_distance *bdistance;
11511
11512 /* Distance configuration. */
11513 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11514 && bgp->distance_local[afi][safi]
11515 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11516 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11517 || bgp->distance_local[afi][safi]
11518 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11519 vty_out(vty, " distance bgp %d %d %d\n",
11520 bgp->distance_ebgp[afi][safi],
11521 bgp->distance_ibgp[afi][safi],
11522 bgp->distance_local[afi][safi]);
11523 }
734b349e 11524
d62a17ae 11525 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
11526 rn = bgp_route_next(rn))
11527 if ((bdistance = rn->info) != NULL) {
11528 char buf[PREFIX_STRLEN];
11529
d62a17ae 11530 vty_out(vty, " distance %d %s %s\n",
11531 bdistance->distance,
11532 prefix2str(&rn->p, buf, sizeof(buf)),
11533 bdistance->access_list ? bdistance->access_list
11534 : "");
11535 }
718e3744 11536}
11537
11538/* Allocate routing table structure and install commands. */
d62a17ae 11539void bgp_route_init(void)
11540{
11541 afi_t afi;
11542 safi_t safi;
11543
11544 /* Init BGP distance table. */
05c7a1cc 11545 FOREACH_AFI_SAFI (afi, safi)
960035b2 11546 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 11547
11548 /* IPv4 BGP commands. */
11549 install_element(BGP_NODE, &bgp_table_map_cmd);
11550 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 11551 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 11552
11553 install_element(BGP_NODE, &aggregate_address_cmd);
11554 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11555 install_element(BGP_NODE, &no_aggregate_address_cmd);
11556 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11557
11558 /* IPv4 unicast configuration. */
11559 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11560 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 11561 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 11562
11563 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11564 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11565 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11566 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11567
11568 /* IPv4 multicast configuration. */
11569 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11570 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 11571 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 11572 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11573 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11574 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11575 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11576
11577 /* IPv4 labeled-unicast configuration. */
11578 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11579 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11580 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11581 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11582 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11583
11584 install_element(VIEW_NODE,
11585 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11586 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11587 install_element(VIEW_NODE,
11588 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11589#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11590 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11591#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11592 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11593 install_element(VIEW_NODE,
11594 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11595
d62a17ae 11596 /* BGP dampening clear commands */
11597 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11598 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11599
d62a17ae 11600 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11601 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11602
11603 /* prefix count */
11604 install_element(ENABLE_NODE,
11605 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11606#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11607 install_element(ENABLE_NODE,
11608 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11609#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11610
d62a17ae 11611 /* New config IPv6 BGP commands. */
11612 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11613 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11614 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 11615
11616 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11617 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11618
11619 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11620
d62a17ae 11621 install_element(BGP_NODE, &bgp_distance_cmd);
11622 install_element(BGP_NODE, &no_bgp_distance_cmd);
11623 install_element(BGP_NODE, &bgp_distance_source_cmd);
11624 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11625 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11626 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11627 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11628 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11629 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11630 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11631 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11632 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11633 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11634 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11635 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11636 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11637 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11638 install_element(BGP_IPV4M_NODE,
11639 &no_bgp_distance_source_access_list_cmd);
11640 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11641 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11642 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11643 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11644 install_element(BGP_IPV6_NODE,
11645 &ipv6_bgp_distance_source_access_list_cmd);
11646 install_element(BGP_IPV6_NODE,
11647 &no_ipv6_bgp_distance_source_access_list_cmd);
11648 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11649 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11650 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11651 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11652 install_element(BGP_IPV6M_NODE,
11653 &ipv6_bgp_distance_source_access_list_cmd);
11654 install_element(BGP_IPV6M_NODE,
11655 &no_ipv6_bgp_distance_source_access_list_cmd);
11656
11657 install_element(BGP_NODE, &bgp_damp_set_cmd);
11658 install_element(BGP_NODE, &bgp_damp_unset_cmd);
11659 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
11660 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
11661
11662 /* IPv4 Multicast Mode */
11663 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
11664 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
11665
11666 /* Large Communities */
11667 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11668 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
11669
11670 /* show bgp ipv4 flowspec detailed */
11671 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
11672
d62a17ae 11673}
11674
11675void bgp_route_finish(void)
11676{
11677 afi_t afi;
11678 safi_t safi;
11679
05c7a1cc
QY
11680 FOREACH_AFI_SAFI (afi, safi) {
11681 bgp_table_unlock(bgp_distance_table[afi][safi]);
11682 bgp_distance_table[afi][safi] = NULL;
11683 }
228da428 11684}