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