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