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