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