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