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