]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #3091 from donaldsharp/routemap_countemup
[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 357 else
450971aa 358 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 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;
d62a17ae 4043
4044 /* look for neighbor in tables */
ea47320b
DL
4045 if ((table = rn->info) == NULL)
4046 continue;
4047
4048 for (rm = bgp_table_top(table); rm;
4049 rm = bgp_route_next(rm))
4050 for (ri = rm->info; ri; ri = ri->next) {
4051 if (ri->peer != peer)
4052 continue;
4053 if (!CHECK_FLAG(ri->flags,
4054 BGP_INFO_STALE))
4055 break;
4056
4057 bgp_rib_remove(rm, ri, peer, afi, safi);
4058 break;
4059 }
d62a17ae 4060 }
4061 } else {
4062 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4063 rn = bgp_route_next(rn))
ea47320b
DL
4064 for (ri = rn->info; ri; ri = ri->next) {
4065 if (ri->peer != peer)
4066 continue;
4067 if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE))
d62a17ae 4068 break;
ea47320b
DL
4069 bgp_rib_remove(rn, ri, peer, afi, safi);
4070 break;
4071 }
d62a17ae 4072 }
93406d87 4073}
6b0655a2 4074
568e10ca 4075static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4076 safi_t safi)
bb86c601 4077{
d62a17ae 4078 struct bgp_node *rn;
4079 struct bgp_info *ri;
4080 struct bgp_info *next;
bb86c601 4081
d62a17ae 4082 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4083 for (ri = rn->info; ri; ri = next) {
4084 next = ri->next;
4085 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
4086 && ri->type == ZEBRA_ROUTE_BGP
4087 && (ri->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
4088 || ri->sub_type == BGP_ROUTE_AGGREGATE
4089 || ri->sub_type == BGP_ROUTE_IMPORTED)) {
4090
d62a17ae 4091 if (bgp_fibupd_safi(safi))
568e10ca 4092 bgp_zebra_withdraw(&rn->p, ri,
4093 bgp, safi);
d62a17ae 4094 bgp_info_reap(rn, ri);
4095 }
4096 }
bb86c601
LB
4097}
4098
718e3744 4099/* Delete all kernel routes. */
d62a17ae 4100void bgp_cleanup_routes(struct bgp *bgp)
4101{
4102 afi_t afi;
4103 struct bgp_node *rn;
4104
4105 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4106 if (afi == AFI_L2VPN)
4107 continue;
568e10ca 4108 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4109 SAFI_UNICAST);
d62a17ae 4110 /*
4111 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4112 */
4113 if (afi != AFI_L2VPN) {
4114 safi_t safi;
4115 safi = SAFI_MPLS_VPN;
4116 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4117 rn = bgp_route_next(rn)) {
4118 if (rn->info) {
568e10ca 4119 bgp_cleanup_table(bgp,
d62a17ae 4120 (struct bgp_table *)(rn->info),
4121 safi);
4122 bgp_table_finish((struct bgp_table **)&(
4123 rn->info));
4124 rn->info = NULL;
4125 bgp_unlock_node(rn);
4126 }
4127 }
4128 safi = SAFI_ENCAP;
4129 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4130 rn = bgp_route_next(rn)) {
4131 if (rn->info) {
568e10ca 4132 bgp_cleanup_table(bgp,
d62a17ae 4133 (struct bgp_table *)(rn->info),
4134 safi);
4135 bgp_table_finish((struct bgp_table **)&(
4136 rn->info));
4137 rn->info = NULL;
4138 bgp_unlock_node(rn);
4139 }
4140 }
4141 }
4142 }
4143 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4144 rn = bgp_route_next(rn)) {
4145 if (rn->info) {
568e10ca 4146 bgp_cleanup_table(bgp,
4147 (struct bgp_table *)(rn->info),
d62a17ae 4148 SAFI_EVPN);
4149 bgp_table_finish((struct bgp_table **)&(rn->info));
4150 rn->info = NULL;
4151 bgp_unlock_node(rn);
4152 }
bb86c601 4153 }
718e3744 4154}
4155
d62a17ae 4156void bgp_reset(void)
718e3744 4157{
d62a17ae 4158 vty_reset();
4159 bgp_zclient_reset();
4160 access_list_reset();
4161 prefix_list_reset();
718e3744 4162}
6b0655a2 4163
d62a17ae 4164static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4165{
d62a17ae 4166 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4167 && CHECK_FLAG(peer->af_cap[afi][safi],
4168 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4169}
4170
718e3744 4171/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4172 value. */
d62a17ae 4173int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4174 struct bgp_nlri *packet)
4175{
d7c0a89a
QY
4176 uint8_t *pnt;
4177 uint8_t *lim;
d62a17ae 4178 struct prefix p;
4179 int psize;
4180 int ret;
4181 afi_t afi;
4182 safi_t safi;
4183 int addpath_encoded;
d7c0a89a 4184 uint32_t addpath_id;
d62a17ae 4185
d62a17ae 4186 pnt = packet->nlri;
4187 lim = pnt + packet->length;
4188 afi = packet->afi;
4189 safi = packet->safi;
4190 addpath_id = 0;
4191 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4192
4193 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4194 syntactic validity. If the field is syntactically incorrect,
4195 then the Error Subcode is set to Invalid Network Field. */
4196 for (; pnt < lim; pnt += psize) {
4197 /* Clear prefix structure. */
4198 memset(&p, 0, sizeof(struct prefix));
4199
4200 if (addpath_encoded) {
4201
4202 /* When packet overflow occurs return immediately. */
4203 if (pnt + BGP_ADDPATH_ID_LEN > lim)
4204 return -1;
4205
4206 addpath_id = ntohl(*((uint32_t *)pnt));
4207 pnt += BGP_ADDPATH_ID_LEN;
4208 }
718e3744 4209
d62a17ae 4210 /* Fetch prefix length. */
4211 p.prefixlen = *pnt++;
4212 /* afi/safi validity already verified by caller,
4213 * bgp_update_receive */
4214 p.family = afi2family(afi);
4215
4216 /* Prefix length check. */
4217 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4218 flog_err(
e50f7cfd 4219 EC_BGP_UPDATE_RCV,
14454c9f 4220 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4221 peer->host, p.prefixlen, packet->afi);
4222 return -1;
4223 }
6b0655a2 4224
d62a17ae 4225 /* Packet size overflow check. */
4226 psize = PSIZE(p.prefixlen);
4227
4228 /* When packet overflow occur return immediately. */
4229 if (pnt + psize > lim) {
af4c2728 4230 flog_err(
e50f7cfd 4231 EC_BGP_UPDATE_RCV,
d62a17ae 4232 "%s [Error] Update packet error (prefix length %d overflows packet)",
4233 peer->host, p.prefixlen);
4234 return -1;
4235 }
4236
4237 /* Defensive coding, double-check the psize fits in a struct
4238 * prefix */
4239 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4240 flog_err(
e50f7cfd 4241 EC_BGP_UPDATE_RCV,
d62a17ae 4242 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4243 peer->host, p.prefixlen, sizeof(p.u));
4244 return -1;
4245 }
4246
4247 /* Fetch prefix from NLRI packet. */
a85297a7 4248 memcpy(p.u.val, pnt, psize);
d62a17ae 4249
4250 /* Check address. */
4251 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4252 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4253 /* From RFC4271 Section 6.3:
4254 *
4255 * If a prefix in the NLRI field is semantically
4256 * incorrect
4257 * (e.g., an unexpected multicast IP address),
4258 * an error SHOULD
4259 * be logged locally, and the prefix SHOULD be
4260 * ignored.
a4d82a8a 4261 */
af4c2728 4262 flog_err(
e50f7cfd 4263 EC_BGP_UPDATE_RCV,
d62a17ae 4264 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4265 peer->host, inet_ntoa(p.u.prefix4));
4266 continue;
4267 }
4268 }
4269
4270 /* Check address. */
4271 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4272 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4273 char buf[BUFSIZ];
4274
af4c2728 4275 flog_err(
e50f7cfd 4276 EC_BGP_UPDATE_RCV,
d62a17ae 4277 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4278 peer->host,
4279 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4280 BUFSIZ));
4281
4282 continue;
4283 }
4284 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4285 char buf[BUFSIZ];
4286
af4c2728 4287 flog_err(
e50f7cfd 4288 EC_BGP_UPDATE_RCV,
d62a17ae 4289 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4290 peer->host,
4291 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4292 BUFSIZ));
4293
4294 continue;
4295 }
4296 }
4297
4298 /* Normal process. */
4299 if (attr)
4300 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4301 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4302 NULL, NULL, 0, 0, NULL);
d62a17ae 4303 else
4304 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4305 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4306 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4307 NULL);
d62a17ae 4308
4309 /* Address family configuration mismatch or maximum-prefix count
4310 overflow. */
4311 if (ret < 0)
4312 return -1;
4313 }
4314
4315 /* Packet length consistency check. */
4316 if (pnt != lim) {
af4c2728 4317 flog_err(
e50f7cfd 4318 EC_BGP_UPDATE_RCV,
d62a17ae 4319 "%s [Error] Update packet error (prefix length mismatch with total length)",
4320 peer->host);
4321 return -1;
4322 }
6b0655a2 4323
d62a17ae 4324 return 0;
718e3744 4325}
4326
d62a17ae 4327static struct bgp_static *bgp_static_new(void)
718e3744 4328{
d62a17ae 4329 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4330}
4331
d62a17ae 4332static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4333{
d62a17ae 4334 if (bgp_static->rmap.name)
4335 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4336 if (bgp_static->eth_s_id)
4337 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
4338 XFREE(MTYPE_BGP_STATIC, bgp_static);
4339}
4340
4341void bgp_static_update(struct bgp *bgp, struct prefix *p,
4342 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4343{
4344 struct bgp_node *rn;
4345 struct bgp_info *ri;
4346 struct bgp_info *new;
4347 struct bgp_info info;
4348 struct attr attr;
4349 struct attr *attr_new;
4350 int ret;
65efcfce 4351#if ENABLE_BGP_VNC
d62a17ae 4352 int vnc_implicit_withdraw = 0;
65efcfce 4353#endif
fee0f4c6 4354
d62a17ae 4355 assert(bgp_static);
4356 if (!bgp_static)
4357 return;
dd8103a9 4358
d62a17ae 4359 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4360
d62a17ae 4361 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4362
d62a17ae 4363 attr.nexthop = bgp_static->igpnexthop;
4364 attr.med = bgp_static->igpmetric;
4365 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4366
d62a17ae 4367 if (bgp_static->atomic)
4368 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4369
d62a17ae 4370 /* Store label index, if required. */
4371 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4372 attr.label_index = bgp_static->label_index;
4373 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4374 }
718e3744 4375
d62a17ae 4376 /* Apply route-map. */
4377 if (bgp_static->rmap.name) {
4378 struct attr attr_tmp = attr;
80ced710
CS
4379
4380 memset(&info, 0, sizeof(struct bgp_info));
d62a17ae 4381 info.peer = bgp->peer_self;
4382 info.attr = &attr_tmp;
fee0f4c6 4383
d62a17ae 4384 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4385
d62a17ae 4386 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
fee0f4c6 4387
d62a17ae 4388 bgp->peer_self->rmap_type = 0;
718e3744 4389
d62a17ae 4390 if (ret == RMAP_DENYMATCH) {
4391 /* Free uninterned attribute. */
4392 bgp_attr_flush(&attr_tmp);
718e3744 4393
d62a17ae 4394 /* Unintern original. */
4395 aspath_unintern(&attr.aspath);
4396 bgp_static_withdraw(bgp, p, afi, safi);
4397 return;
4398 }
7f323236
DW
4399
4400 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4401 bgp_attr_add_gshut_community(&attr_tmp);
4402
d62a17ae 4403 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4404 } else {
4405
4406 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4407 bgp_attr_add_gshut_community(&attr);
4408
d62a17ae 4409 attr_new = bgp_attr_intern(&attr);
7f323236 4410 }
718e3744 4411
d62a17ae 4412 for (ri = rn->info; ri; ri = ri->next)
4413 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4414 && ri->sub_type == BGP_ROUTE_STATIC)
4415 break;
4416
4417 if (ri) {
4418 if (attrhash_cmp(ri->attr, attr_new)
4419 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
4420 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4421 bgp_unlock_node(rn);
4422 bgp_attr_unintern(&attr_new);
4423 aspath_unintern(&attr.aspath);
4424 return;
4425 } else {
4426 /* The attribute is changed. */
4427 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4428
4429 /* Rewrite BGP route information. */
4430 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4431 bgp_info_restore(rn, ri);
4432 else
4433 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
65efcfce 4434#if ENABLE_BGP_VNC
d62a17ae 4435 if ((afi == AFI_IP || afi == AFI_IP6)
4436 && (safi == SAFI_UNICAST)) {
4437 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
4438 /*
4439 * Implicit withdraw case.
4440 * We have to do this before ri is
4441 * changed
4442 */
4443 ++vnc_implicit_withdraw;
4444 vnc_import_bgp_del_route(bgp, p, ri);
4445 vnc_import_bgp_exterior_del_route(
4446 bgp, p, ri);
4447 }
4448 }
65efcfce 4449#endif
d62a17ae 4450 bgp_attr_unintern(&ri->attr);
4451 ri->attr = attr_new;
4452 ri->uptime = bgp_clock();
65efcfce 4453#if ENABLE_BGP_VNC
d62a17ae 4454 if ((afi == AFI_IP || afi == AFI_IP6)
4455 && (safi == SAFI_UNICAST)) {
4456 if (vnc_implicit_withdraw) {
4457 vnc_import_bgp_add_route(bgp, p, ri);
4458 vnc_import_bgp_exterior_add_route(
4459 bgp, p, ri);
4460 }
4461 }
65efcfce 4462#endif
718e3744 4463
d62a17ae 4464 /* Nexthop reachability check. */
4465 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4466 && (safi == SAFI_UNICAST
4467 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
4468
4469 struct bgp *bgp_nexthop = bgp;
4470
4471 if (ri->extra && ri->extra->bgp_orig)
4472 bgp_nexthop = ri->extra->bgp_orig;
4473
4474 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4475 afi, ri, NULL, 0))
d62a17ae 4476 bgp_info_set_flag(rn, ri,
4477 BGP_INFO_VALID);
4478 else {
4479 if (BGP_DEBUG(nht, NHT)) {
4480 char buf1[INET6_ADDRSTRLEN];
4481 inet_ntop(p->family,
4482 &p->u.prefix, buf1,
4483 INET6_ADDRSTRLEN);
4484 zlog_debug(
4485 "%s(%s): Route not in table, not advertising",
4486 __FUNCTION__, buf1);
4487 }
4488 bgp_info_unset_flag(rn, ri,
4489 BGP_INFO_VALID);
4490 }
4491 } else {
4492 /* Delete the NHT structure if any, if we're
4493 * toggling between
4494 * enabling/disabling import check. We
4495 * deregister the route
4496 * from NHT to avoid overloading NHT and the
4497 * process interaction
4498 */
4499 bgp_unlink_nexthop(ri);
4500 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
4501 }
4502 /* Process change. */
4503 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4504 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4505
4506 if (SAFI_UNICAST == safi
4507 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4508 || bgp->inst_type
4509 == BGP_INSTANCE_TYPE_DEFAULT)) {
4510 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
4511 ri);
4512 }
4513
d62a17ae 4514 bgp_unlock_node(rn);
4515 aspath_unintern(&attr.aspath);
4516 return;
4517 }
718e3744 4518 }
718e3744 4519
d62a17ae 4520 /* Make new BGP info. */
4521 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4522 attr_new, rn);
4523 /* Nexthop reachability check. */
4524 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4525 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 4526 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
d62a17ae 4527 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
4528 else {
4529 if (BGP_DEBUG(nht, NHT)) {
4530 char buf1[INET6_ADDRSTRLEN];
4531 inet_ntop(p->family, &p->u.prefix, buf1,
4532 INET6_ADDRSTRLEN);
4533 zlog_debug(
4534 "%s(%s): Route not in table, not advertising",
4535 __FUNCTION__, buf1);
4536 }
4537 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
4538 }
4539 } else {
4540 /* Delete the NHT structure if any, if we're toggling between
4541 * enabling/disabling import check. We deregister the route
4542 * from NHT to avoid overloading NHT and the process interaction
4543 */
4544 bgp_unlink_nexthop(new);
4545
4546 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
fc9a856f 4547 }
078430f6 4548
d62a17ae 4549 /* Aggregate address increment. */
4550 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4551
d62a17ae 4552 /* Register new BGP information. */
4553 bgp_info_add(rn, new);
718e3744 4554
d62a17ae 4555 /* route_node_get lock */
4556 bgp_unlock_node(rn);
4557
4558 /* Process change. */
4559 bgp_process(bgp, rn, afi, safi);
4560
ddb5b488
PZ
4561 if (SAFI_UNICAST == safi
4562 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4563 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4564 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4565 }
4566
d62a17ae 4567 /* Unintern original. */
4568 aspath_unintern(&attr.aspath);
718e3744 4569}
4570
d62a17ae 4571void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4572 safi_t safi)
718e3744 4573{
d62a17ae 4574 struct bgp_node *rn;
4575 struct bgp_info *ri;
718e3744 4576
d62a17ae 4577 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4578
d62a17ae 4579 /* Check selected route and self inserted route. */
4580 for (ri = rn->info; ri; ri = ri->next)
4581 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4582 && ri->sub_type == BGP_ROUTE_STATIC)
4583 break;
4584
4585 /* Withdraw static BGP route from routing table. */
4586 if (ri) {
ddb5b488
PZ
4587 if (SAFI_UNICAST == safi
4588 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4589 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4590 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
4591 }
d62a17ae 4592 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4593 bgp_unlink_nexthop(ri);
4594 bgp_info_delete(rn, ri);
4595 bgp_process(bgp, rn, afi, safi);
4596 }
718e3744 4597
d62a17ae 4598 /* Unlock bgp_node_lookup. */
4599 bgp_unlock_node(rn);
718e3744 4600}
4601
137446f9
LB
4602/*
4603 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4604 */
d62a17ae 4605static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4606 afi_t afi, safi_t safi,
4607 struct prefix_rd *prd)
718e3744 4608{
d62a17ae 4609 struct bgp_node *rn;
4610 struct bgp_info *ri;
718e3744 4611
d62a17ae 4612 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4613
d62a17ae 4614 /* Check selected route and self inserted route. */
4615 for (ri = rn->info; ri; ri = ri->next)
4616 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4617 && ri->sub_type == BGP_ROUTE_STATIC)
4618 break;
718e3744 4619
d62a17ae 4620 /* Withdraw static BGP route from routing table. */
4621 if (ri) {
65efcfce 4622#if ENABLE_BGP_VNC
d62a17ae 4623 rfapiProcessWithdraw(
4624 ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type,
4625 1); /* Kill, since it is an administrative change */
65efcfce 4626#endif
ddb5b488
PZ
4627 if (SAFI_MPLS_VPN == safi
4628 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4629 vpn_leak_to_vrf_withdraw(bgp, ri);
4630 }
d62a17ae 4631 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4632 bgp_info_delete(rn, ri);
4633 bgp_process(bgp, rn, afi, safi);
4634 }
718e3744 4635
d62a17ae 4636 /* Unlock bgp_node_lookup. */
4637 bgp_unlock_node(rn);
718e3744 4638}
4639
d62a17ae 4640static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4641 struct bgp_static *bgp_static, afi_t afi,
4642 safi_t safi)
137446f9 4643{
d62a17ae 4644 struct bgp_node *rn;
4645 struct bgp_info *new;
4646 struct attr *attr_new;
4647 struct attr attr = {0};
4648 struct bgp_info *ri;
65efcfce 4649#if ENABLE_BGP_VNC
d62a17ae 4650 mpls_label_t label = 0;
65efcfce 4651#endif
d7c0a89a 4652 uint32_t num_labels = 0;
d62a17ae 4653 union gw_addr add;
137446f9 4654
d62a17ae 4655 assert(bgp_static);
137446f9 4656
b57ba6d2
MK
4657 if (bgp_static->label != MPLS_INVALID_LABEL)
4658 num_labels = 1;
d62a17ae 4659 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4660 &bgp_static->prd);
137446f9 4661
d62a17ae 4662 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4663
d62a17ae 4664 attr.nexthop = bgp_static->igpnexthop;
4665 attr.med = bgp_static->igpmetric;
4666 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4667
d62a17ae 4668 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4669 || (safi == SAFI_ENCAP)) {
4670 if (afi == AFI_IP) {
4671 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4672 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4673 }
4674 }
4675 if (afi == AFI_L2VPN) {
4676 if (bgp_static->gatewayIp.family == AF_INET)
4677 add.ipv4.s_addr =
4678 bgp_static->gatewayIp.u.prefix4.s_addr;
4679 else if (bgp_static->gatewayIp.family == AF_INET6)
4680 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4681 sizeof(struct in6_addr));
4682 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4683 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4684 struct bgp_encap_type_vxlan bet;
4685 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 4686 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 4687 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4688 }
4689 if (bgp_static->router_mac) {
4690 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4691 }
4692 }
4693 /* Apply route-map. */
4694 if (bgp_static->rmap.name) {
4695 struct attr attr_tmp = attr;
4696 struct bgp_info info;
4697 int ret;
137446f9 4698
d62a17ae 4699 info.peer = bgp->peer_self;
4700 info.attr = &attr_tmp;
137446f9 4701
d62a17ae 4702 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4703
d62a17ae 4704 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
137446f9 4705
d62a17ae 4706 bgp->peer_self->rmap_type = 0;
137446f9 4707
d62a17ae 4708 if (ret == RMAP_DENYMATCH) {
4709 /* Free uninterned attribute. */
4710 bgp_attr_flush(&attr_tmp);
137446f9 4711
d62a17ae 4712 /* Unintern original. */
4713 aspath_unintern(&attr.aspath);
4714 bgp_static_withdraw_safi(bgp, p, afi, safi,
4715 &bgp_static->prd);
4716 return;
4717 }
137446f9 4718
d62a17ae 4719 attr_new = bgp_attr_intern(&attr_tmp);
4720 } else {
4721 attr_new = bgp_attr_intern(&attr);
4722 }
137446f9 4723
d62a17ae 4724 for (ri = rn->info; ri; ri = ri->next)
4725 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4726 && ri->sub_type == BGP_ROUTE_STATIC)
4727 break;
4728
4729 if (ri) {
d62a17ae 4730 memset(&add, 0, sizeof(union gw_addr));
4731 if (attrhash_cmp(ri->attr, attr_new)
4732 && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add)
4733 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
4734 bgp_unlock_node(rn);
4735 bgp_attr_unintern(&attr_new);
4736 aspath_unintern(&attr.aspath);
4737 return;
4738 } else {
4739 /* The attribute is changed. */
4740 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4741
4742 /* Rewrite BGP route information. */
4743 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4744 bgp_info_restore(rn, ri);
4745 else
4746 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4747 bgp_attr_unintern(&ri->attr);
4748 ri->attr = attr_new;
4749 ri->uptime = bgp_clock();
65efcfce 4750#if ENABLE_BGP_VNC
d62a17ae 4751 if (ri->extra)
317f1fe0 4752 label = decode_label(&ri->extra->label[0]);
65efcfce 4753#endif
137446f9 4754
d62a17ae 4755 /* Process change. */
4756 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4757 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
4758
4759 if (SAFI_MPLS_VPN == safi
4760 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4761 vpn_leak_to_vrf_update(bgp, ri);
4762 }
65efcfce 4763#if ENABLE_BGP_VNC
d62a17ae 4764 rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
4765 ri->attr, afi, safi, ri->type,
4766 ri->sub_type, &label);
65efcfce 4767#endif
d62a17ae 4768 bgp_unlock_node(rn);
4769 aspath_unintern(&attr.aspath);
4770 return;
4771 }
4772 }
137446f9
LB
4773
4774
d62a17ae 4775 /* Make new BGP info. */
4776 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4777 attr_new, rn);
4778 SET_FLAG(new->flags, BGP_INFO_VALID);
4779 new->extra = bgp_info_extra_new();
b57ba6d2
MK
4780 if (num_labels) {
4781 new->extra->label[0] = bgp_static->label;
4782 new->extra->num_labels = num_labels;
4783 }
65efcfce 4784#if ENABLE_BGP_VNC
d62a17ae 4785 label = decode_label(&bgp_static->label);
65efcfce 4786#endif
137446f9 4787
d62a17ae 4788 /* Aggregate address increment. */
4789 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 4790
d62a17ae 4791 /* Register new BGP information. */
4792 bgp_info_add(rn, new);
4793 /* route_node_get lock */
4794 bgp_unlock_node(rn);
137446f9 4795
d62a17ae 4796 /* Process change. */
4797 bgp_process(bgp, rn, afi, safi);
137446f9 4798
ddb5b488
PZ
4799 if (SAFI_MPLS_VPN == safi
4800 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
4801 vpn_leak_to_vrf_update(bgp, new);
4802 }
65efcfce 4803#if ENABLE_BGP_VNC
d62a17ae 4804 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
4805 safi, new->type, new->sub_type, &label);
65efcfce
LB
4806#endif
4807
d62a17ae 4808 /* Unintern original. */
4809 aspath_unintern(&attr.aspath);
137446f9
LB
4810}
4811
718e3744 4812/* Configure static BGP network. When user don't run zebra, static
4813 route should be installed as valid. */
e2a86ad9
DS
4814static int bgp_static_set(struct vty *vty, const char *negate,
4815 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 4816 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 4817{
4818 VTY_DECLVAR_CONTEXT(bgp, bgp);
4819 int ret;
4820 struct prefix p;
4821 struct bgp_static *bgp_static;
4822 struct bgp_node *rn;
d7c0a89a 4823 uint8_t need_update = 0;
d62a17ae 4824
4825 /* Convert IP prefix string to struct prefix. */
4826 ret = str2prefix(ip_str, &p);
4827 if (!ret) {
4828 vty_out(vty, "%% Malformed prefix\n");
4829 return CMD_WARNING_CONFIG_FAILED;
4830 }
4831 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4832 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4833 return CMD_WARNING_CONFIG_FAILED;
4834 }
718e3744 4835
d62a17ae 4836 apply_mask(&p);
718e3744 4837
e2a86ad9 4838 if (negate) {
718e3744 4839
e2a86ad9
DS
4840 /* Set BGP static route configuration. */
4841 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 4842
e2a86ad9 4843 if (!rn) {
a4d82a8a 4844 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 4845 return CMD_WARNING_CONFIG_FAILED;
4846 }
4847
a78beeb5 4848 bgp_static = bgp_static_get_node_info(rn);
d62a17ae 4849
e2a86ad9
DS
4850 if ((label_index != BGP_INVALID_LABEL_INDEX)
4851 && (label_index != bgp_static->label_index)) {
4852 vty_out(vty,
4853 "%% label-index doesn't match static route\n");
4854 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4855 }
d62a17ae 4856
e2a86ad9
DS
4857 if ((rmap && bgp_static->rmap.name)
4858 && strcmp(rmap, bgp_static->rmap.name)) {
4859 vty_out(vty,
4860 "%% route-map name doesn't match static route\n");
4861 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 4862 }
718e3744 4863
e2a86ad9
DS
4864 /* Update BGP RIB. */
4865 if (!bgp_static->backdoor)
4866 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 4867
e2a86ad9
DS
4868 /* Clear configuration. */
4869 bgp_static_free(bgp_static);
a78beeb5 4870 bgp_static_set_node_info(rn, NULL);
e2a86ad9
DS
4871 bgp_unlock_node(rn);
4872 bgp_unlock_node(rn);
4873 } else {
718e3744 4874
e2a86ad9
DS
4875 /* Set BGP static route configuration. */
4876 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 4877
a78beeb5
DS
4878 bgp_static = bgp_static_get_node_info(rn);
4879 if (bgp_static) {
e2a86ad9 4880 /* Configuration change. */
e2a86ad9
DS
4881 /* Label index cannot be changed. */
4882 if (bgp_static->label_index != label_index) {
4883 vty_out(vty, "%% cannot change label-index\n");
4884 return CMD_WARNING_CONFIG_FAILED;
4885 }
d62a17ae 4886
e2a86ad9 4887 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
4888 if (bgp_static->valid
4889 && bgp_static->backdoor != backdoor)
e2a86ad9 4890 need_update = 1;
718e3744 4891
e2a86ad9 4892 bgp_static->backdoor = backdoor;
718e3744 4893
e2a86ad9
DS
4894 if (rmap) {
4895 if (bgp_static->rmap.name)
4896 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4897 bgp_static->rmap.name);
e2a86ad9
DS
4898 bgp_static->rmap.name =
4899 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4900 bgp_static->rmap.map =
4901 route_map_lookup_by_name(rmap);
4902 } else {
4903 if (bgp_static->rmap.name)
4904 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4905 bgp_static->rmap.name);
e2a86ad9
DS
4906 bgp_static->rmap.name = NULL;
4907 bgp_static->rmap.map = NULL;
4908 bgp_static->valid = 0;
4909 }
4910 bgp_unlock_node(rn);
4911 } else {
4912 /* New configuration. */
4913 bgp_static = bgp_static_new();
4914 bgp_static->backdoor = backdoor;
4915 bgp_static->valid = 0;
4916 bgp_static->igpmetric = 0;
4917 bgp_static->igpnexthop.s_addr = 0;
4918 bgp_static->label_index = label_index;
718e3744 4919
e2a86ad9
DS
4920 if (rmap) {
4921 if (bgp_static->rmap.name)
4922 XFREE(MTYPE_ROUTE_MAP_NAME,
a4d82a8a 4923 bgp_static->rmap.name);
e2a86ad9
DS
4924 bgp_static->rmap.name =
4925 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4926 bgp_static->rmap.map =
4927 route_map_lookup_by_name(rmap);
4928 }
a78beeb5 4929 bgp_static_set_node_info(rn, bgp_static);
e2a86ad9 4930 }
d62a17ae 4931
e2a86ad9
DS
4932 bgp_static->valid = 1;
4933 if (need_update)
4934 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 4935
e2a86ad9
DS
4936 if (!bgp_static->backdoor)
4937 bgp_static_update(bgp, &p, bgp_static, afi, safi);
4938 }
d62a17ae 4939
4940 return CMD_SUCCESS;
4941}
4942
4943void bgp_static_add(struct bgp *bgp)
4944{
4945 afi_t afi;
4946 safi_t safi;
4947 struct bgp_node *rn;
4948 struct bgp_node *rm;
4949 struct bgp_table *table;
4950 struct bgp_static *bgp_static;
4951
05c7a1cc
QY
4952 FOREACH_AFI_SAFI (afi, safi)
4953 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4954 rn = bgp_route_next(rn)) {
4955 if (rn->info == NULL)
4956 continue;
ea47320b 4957
05c7a1cc
QY
4958 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4959 || (safi == SAFI_EVPN)) {
4960 table = rn->info;
4961
4962 for (rm = bgp_table_top(table); rm;
4963 rm = bgp_route_next(rm)) {
a78beeb5
DS
4964 bgp_static =
4965 bgp_static_get_node_info(rm);
05c7a1cc
QY
4966 bgp_static_update_safi(bgp, &rm->p,
4967 bgp_static, afi,
4968 safi);
d62a17ae 4969 }
05c7a1cc 4970 } else {
a78beeb5
DS
4971 bgp_static_update(bgp, &rn->p,
4972 bgp_static_get_node_info(rn),
4973 afi, safi);
ea47320b 4974 }
05c7a1cc 4975 }
6aeb9e78
DS
4976}
4977
718e3744 4978/* Called from bgp_delete(). Delete all static routes from the BGP
4979 instance. */
d62a17ae 4980void bgp_static_delete(struct bgp *bgp)
4981{
4982 afi_t afi;
4983 safi_t safi;
4984 struct bgp_node *rn;
4985 struct bgp_node *rm;
4986 struct bgp_table *table;
4987 struct bgp_static *bgp_static;
4988
05c7a1cc
QY
4989 FOREACH_AFI_SAFI (afi, safi)
4990 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4991 rn = bgp_route_next(rn)) {
4992 if (rn->info == NULL)
4993 continue;
ea47320b 4994
05c7a1cc
QY
4995 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4996 || (safi == SAFI_EVPN)) {
4997 table = rn->info;
4998
4999 for (rm = bgp_table_top(table); rm;
5000 rm = bgp_route_next(rm)) {
a78beeb5
DS
5001 bgp_static =
5002 bgp_static_get_node_info(rm);
05c7a1cc
QY
5003 bgp_static_withdraw_safi(
5004 bgp, &rm->p, AFI_IP, safi,
5005 (struct prefix_rd *)&rn->p);
ea47320b 5006 bgp_static_free(bgp_static);
a78beeb5 5007 bgp_static_set_node_info(rn, NULL);
ea47320b 5008 bgp_unlock_node(rn);
d62a17ae 5009 }
05c7a1cc 5010 } else {
a78beeb5 5011 bgp_static = bgp_static_get_node_info(rn);
05c7a1cc
QY
5012 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5013 bgp_static_free(bgp_static);
a78beeb5 5014 bgp_static_set_node_info(rn, NULL);
05c7a1cc 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)) {
a78beeb5
DS
5043 bgp_static =
5044 bgp_static_get_node_info(rm);
05c7a1cc
QY
5045 bgp_static_update_safi(bgp, &rm->p,
5046 bgp_static, afi,
5047 safi);
d62a17ae 5048 }
05c7a1cc 5049 } else {
a78beeb5 5050 bgp_static = bgp_static_get_node_info(rn);
05c7a1cc
QY
5051 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5052 safi);
ea47320b 5053 }
05c7a1cc
QY
5054 }
5055 }
d62a17ae 5056 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5057}
5058
5059static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5060 safi_t safi)
5061{
5062 struct bgp_table *table;
5063 struct bgp_node *rn;
5064 struct bgp_info *ri;
5065
5066 table = bgp->rib[afi][safi];
5067 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5068 for (ri = rn->info; ri; ri = ri->next) {
5069 if (ri->peer == bgp->peer_self
5070 && ((ri->type == ZEBRA_ROUTE_BGP
5071 && ri->sub_type == BGP_ROUTE_STATIC)
5072 || (ri->type != ZEBRA_ROUTE_BGP
5073 && ri->sub_type
5074 == BGP_ROUTE_REDISTRIBUTE))) {
5075 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
5076 safi);
5077 bgp_unlink_nexthop(ri);
5078 bgp_info_delete(rn, ri);
5079 bgp_process(bgp, rn, afi, safi);
5080 }
5081 }
5082 }
ad4cbda1 5083}
5084
5085/*
5086 * Purge all networks and redistributed routes from routing table.
5087 * Invoked upon the instance going down.
5088 */
d62a17ae 5089void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5090{
d62a17ae 5091 afi_t afi;
5092 safi_t safi;
ad4cbda1 5093
05c7a1cc
QY
5094 FOREACH_AFI_SAFI (afi, safi)
5095 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5096}
5097
137446f9
LB
5098/*
5099 * gpz 110624
5100 * Currently this is used to set static routes for VPN and ENCAP.
5101 * I think it can probably be factored with bgp_static_set.
5102 */
d62a17ae 5103int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5104 const char *ip_str, const char *rd_str,
5105 const char *label_str, const char *rmap_str,
5106 int evpn_type, const char *esi, const char *gwip,
5107 const char *ethtag, const char *routermac)
5108{
5109 VTY_DECLVAR_CONTEXT(bgp, bgp);
5110 int ret;
5111 struct prefix p;
5112 struct prefix_rd prd;
5113 struct bgp_node *prn;
5114 struct bgp_node *rn;
5115 struct bgp_table *table;
5116 struct bgp_static *bgp_static;
5117 mpls_label_t label = MPLS_INVALID_LABEL;
5118 struct prefix gw_ip;
5119
5120 /* validate ip prefix */
5121 ret = str2prefix(ip_str, &p);
5122 if (!ret) {
5123 vty_out(vty, "%% Malformed prefix\n");
5124 return CMD_WARNING_CONFIG_FAILED;
5125 }
5126 apply_mask(&p);
5127 if ((afi == AFI_L2VPN)
5128 && (bgp_build_evpn_prefix(evpn_type,
5129 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5130 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5131 return CMD_WARNING_CONFIG_FAILED;
5132 }
718e3744 5133
d62a17ae 5134 ret = str2prefix_rd(rd_str, &prd);
5135 if (!ret) {
5136 vty_out(vty, "%% Malformed rd\n");
5137 return CMD_WARNING_CONFIG_FAILED;
5138 }
718e3744 5139
d62a17ae 5140 if (label_str) {
5141 unsigned long label_val;
5142 label_val = strtoul(label_str, NULL, 10);
5143 encode_label(label_val, &label);
5144 }
9bedbb1e 5145
d62a17ae 5146 if (safi == SAFI_EVPN) {
5147 if (esi && str2esi(esi, NULL) == 0) {
5148 vty_out(vty, "%% Malformed ESI\n");
5149 return CMD_WARNING_CONFIG_FAILED;
5150 }
5151 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5152 vty_out(vty, "%% Malformed Router MAC\n");
5153 return CMD_WARNING_CONFIG_FAILED;
5154 }
5155 if (gwip) {
5156 memset(&gw_ip, 0, sizeof(struct prefix));
5157 ret = str2prefix(gwip, &gw_ip);
5158 if (!ret) {
5159 vty_out(vty, "%% Malformed GatewayIp\n");
5160 return CMD_WARNING_CONFIG_FAILED;
5161 }
5162 if ((gw_ip.family == AF_INET
3714a385 5163 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5164 (struct prefix_evpn *)&p))
5165 || (gw_ip.family == AF_INET6
3714a385 5166 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5167 (struct prefix_evpn *)&p))) {
5168 vty_out(vty,
5169 "%% GatewayIp family differs with IP prefix\n");
5170 return CMD_WARNING_CONFIG_FAILED;
5171 }
5172 }
5173 }
5174 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5175 if (prn->info == NULL)
960035b2 5176 prn->info = bgp_table_init(bgp, afi, safi);
d62a17ae 5177 else
5178 bgp_unlock_node(prn);
5179 table = prn->info;
5180
5181 rn = bgp_node_get(table, &p);
5182
5183 if (rn->info) {
5184 vty_out(vty, "%% Same network configuration exists\n");
5185 bgp_unlock_node(rn);
5186 } else {
5187 /* New configuration. */
5188 bgp_static = bgp_static_new();
5189 bgp_static->backdoor = 0;
5190 bgp_static->valid = 0;
5191 bgp_static->igpmetric = 0;
5192 bgp_static->igpnexthop.s_addr = 0;
5193 bgp_static->label = label;
5194 bgp_static->prd = prd;
5195
5196 if (rmap_str) {
5197 if (bgp_static->rmap.name)
5198 XFREE(MTYPE_ROUTE_MAP_NAME,
5199 bgp_static->rmap.name);
5200 bgp_static->rmap.name =
5201 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5202 bgp_static->rmap.map =
5203 route_map_lookup_by_name(rmap_str);
5204 }
718e3744 5205
d62a17ae 5206 if (safi == SAFI_EVPN) {
5207 if (esi) {
5208 bgp_static->eth_s_id =
5209 XCALLOC(MTYPE_ATTR,
5210 sizeof(struct eth_segment_id));
5211 str2esi(esi, bgp_static->eth_s_id);
5212 }
5213 if (routermac) {
5214 bgp_static->router_mac =
28328ea9 5215 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5216 (void)prefix_str2mac(routermac,
5217 bgp_static->router_mac);
d62a17ae 5218 }
5219 if (gwip)
5220 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5221 }
a78beeb5 5222 bgp_static_set_node_info(rn, bgp_static);
718e3744 5223
d62a17ae 5224 bgp_static->valid = 1;
5225 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5226 }
718e3744 5227
d62a17ae 5228 return CMD_SUCCESS;
718e3744 5229}
5230
5231/* Configure static BGP network. */
d62a17ae 5232int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5233 const char *ip_str, const char *rd_str,
5234 const char *label_str, int evpn_type, const char *esi,
5235 const char *gwip, const char *ethtag)
5236{
5237 VTY_DECLVAR_CONTEXT(bgp, bgp);
5238 int ret;
5239 struct prefix p;
5240 struct prefix_rd prd;
5241 struct bgp_node *prn;
5242 struct bgp_node *rn;
5243 struct bgp_table *table;
5244 struct bgp_static *bgp_static;
5245 mpls_label_t label = MPLS_INVALID_LABEL;
5246
5247 /* Convert IP prefix string to struct prefix. */
5248 ret = str2prefix(ip_str, &p);
5249 if (!ret) {
5250 vty_out(vty, "%% Malformed prefix\n");
5251 return CMD_WARNING_CONFIG_FAILED;
5252 }
5253 apply_mask(&p);
5254 if ((afi == AFI_L2VPN)
5255 && (bgp_build_evpn_prefix(evpn_type,
5256 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5257 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5258 return CMD_WARNING_CONFIG_FAILED;
5259 }
5260 ret = str2prefix_rd(rd_str, &prd);
5261 if (!ret) {
5262 vty_out(vty, "%% Malformed rd\n");
5263 return CMD_WARNING_CONFIG_FAILED;
5264 }
718e3744 5265
d62a17ae 5266 if (label_str) {
5267 unsigned long label_val;
5268 label_val = strtoul(label_str, NULL, 10);
5269 encode_label(label_val, &label);
5270 }
718e3744 5271
d62a17ae 5272 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5273 if (prn->info == NULL)
960035b2 5274 prn->info = bgp_table_init(bgp, afi, safi);
d62a17ae 5275 else
5276 bgp_unlock_node(prn);
5277 table = prn->info;
718e3744 5278
d62a17ae 5279 rn = bgp_node_lookup(table, &p);
6b0655a2 5280
d62a17ae 5281 if (rn) {
5282 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5283
a78beeb5 5284 bgp_static = bgp_static_get_node_info(rn);
d62a17ae 5285 bgp_static_free(bgp_static);
a78beeb5 5286 bgp_static_set_node_info(rn, NULL);
d62a17ae 5287 bgp_unlock_node(rn);
5288 bgp_unlock_node(rn);
5289 } else
5290 vty_out(vty, "%% Can't find the route\n");
5291
5292 return CMD_SUCCESS;
5293}
5294
5295static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5296 const char *rmap_name)
5297{
5298 VTY_DECLVAR_CONTEXT(bgp, bgp);
5299 struct bgp_rmap *rmap;
5300
5301 rmap = &bgp->table_map[afi][safi];
5302 if (rmap_name) {
5303 if (rmap->name)
5304 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5305 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5306 rmap->map = route_map_lookup_by_name(rmap_name);
5307 } else {
5308 if (rmap->name)
5309 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5310 rmap->name = NULL;
5311 rmap->map = NULL;
5312 }
73ac8160 5313
d62a17ae 5314 if (bgp_fibupd_safi(safi))
5315 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5316
d62a17ae 5317 return CMD_SUCCESS;
73ac8160
DS
5318}
5319
d62a17ae 5320static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5321 const char *rmap_name)
73ac8160 5322{
d62a17ae 5323 VTY_DECLVAR_CONTEXT(bgp, bgp);
5324 struct bgp_rmap *rmap;
73ac8160 5325
d62a17ae 5326 rmap = &bgp->table_map[afi][safi];
5327 if (rmap->name)
5328 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
5329 rmap->name = NULL;
5330 rmap->map = NULL;
73ac8160 5331
d62a17ae 5332 if (bgp_fibupd_safi(safi))
5333 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5334
d62a17ae 5335 return CMD_SUCCESS;
73ac8160
DS
5336}
5337
2b791107 5338void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5339 safi_t safi)
73ac8160 5340{
d62a17ae 5341 if (bgp->table_map[afi][safi].name) {
d62a17ae 5342 vty_out(vty, " table-map %s\n",
5343 bgp->table_map[afi][safi].name);
5344 }
73ac8160
DS
5345}
5346
73ac8160
DS
5347DEFUN (bgp_table_map,
5348 bgp_table_map_cmd,
5349 "table-map WORD",
5350 "BGP table to RIB route download filter\n"
5351 "Name of the route map\n")
5352{
d62a17ae 5353 int idx_word = 1;
5354 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5355 argv[idx_word]->arg);
73ac8160
DS
5356}
5357DEFUN (no_bgp_table_map,
5358 no_bgp_table_map_cmd,
5359 "no table-map WORD",
3a2d747c 5360 NO_STR
73ac8160
DS
5361 "BGP table to RIB route download filter\n"
5362 "Name of the route map\n")
5363{
d62a17ae 5364 int idx_word = 2;
5365 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5366 argv[idx_word]->arg);
73ac8160
DS
5367}
5368
e2a86ad9
DS
5369DEFPY(bgp_network,
5370 bgp_network_cmd,
5371 "[no] network \
5372 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5373 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5374 backdoor$backdoor}]",
5375 NO_STR
5376 "Specify a network to announce via BGP\n"
5377 "IPv4 prefix\n"
5378 "Network number\n"
5379 "Network mask\n"
5380 "Network mask\n"
5381 "Route-map to modify the attributes\n"
5382 "Name of the route map\n"
5383 "Label index to associate with the prefix\n"
5384 "Label index value\n"
5385 "Specify a BGP backdoor route\n")
5386{
5387 char addr_prefix_str[BUFSIZ];
5388
5389 if (address_str) {
5390 int ret;
718e3744 5391
e2a86ad9
DS
5392 ret = netmask_str2prefix_str(address_str, netmask_str,
5393 addr_prefix_str);
5394 if (!ret) {
5395 vty_out(vty, "%% Inconsistent address and mask\n");
5396 return CMD_WARNING_CONFIG_FAILED;
5397 }
d62a17ae 5398 }
718e3744 5399
a4d82a8a
PZ
5400 return bgp_static_set(
5401 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5402 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5403 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5404}
5405
e2a86ad9
DS
5406DEFPY(ipv6_bgp_network,
5407 ipv6_bgp_network_cmd,
5408 "[no] network X:X::X:X/M$prefix \
5409 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5410 NO_STR
5411 "Specify a network to announce via BGP\n"
5412 "IPv6 prefix\n"
5413 "Route-map to modify the attributes\n"
5414 "Name of the route map\n"
5415 "Label index to associate with the prefix\n"
5416 "Label index value\n")
718e3744 5417{
a4d82a8a
PZ
5418 return bgp_static_set(
5419 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5420 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5421}
5422
718e3744 5423/* Aggreagete address:
5424
5425 advertise-map Set condition to advertise attribute
5426 as-set Generate AS set path information
5427 attribute-map Set attributes of aggregate
5428 route-map Set parameters of aggregate
5429 summary-only Filter more specific routes from updates
5430 suppress-map Conditionally filter more specific routes from updates
5431 <cr>
5432 */
d62a17ae 5433struct bgp_aggregate {
5434 /* Summary-only flag. */
d7c0a89a 5435 uint8_t summary_only;
718e3744 5436
d62a17ae 5437 /* AS set generation. */
d7c0a89a 5438 uint8_t as_set;
718e3744 5439
d62a17ae 5440 /* Route-map for aggregated route. */
5441 struct route_map *map;
718e3744 5442
d62a17ae 5443 /* Suppress-count. */
5444 unsigned long count;
718e3744 5445
d62a17ae 5446 /* SAFI configuration. */
5447 safi_t safi;
718e3744 5448};
5449
d62a17ae 5450static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5451{
d62a17ae 5452 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5453}
5454
d62a17ae 5455static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5456{
d62a17ae 5457 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5458}
718e3744 5459
29f7d023
DS
5460static int bgp_aggregate_info_same(struct bgp_info *ri, uint8_t origin,
5461 struct aspath *aspath,
eaaf8adb
DS
5462 struct community *comm)
5463{
5464 static struct aspath *ae = NULL;
5465
5466 if (!ae)
5467 ae = aspath_empty();
5468
5469 if (!ri)
5470 return 0;
5471
29f7d023
DS
5472 if (origin != ri->attr->origin)
5473 return 0;
5474
eaaf8adb
DS
5475 if (!aspath_cmp(ri->attr->aspath, (aspath) ? aspath : ae))
5476 return 0;
5477
5478 if (!community_cmp(ri->attr->community, comm))
5479 return 0;
5480
5481 return 1;
5482}
5483
c701010e
DS
5484static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
5485 struct prefix *p, uint8_t origin,
5486 struct aspath *aspath,
5487 struct community *community,
5488 uint8_t atomic_aggregate,
5489 struct bgp_aggregate *aggregate)
5490{
5491 struct bgp_node *rn;
5492 struct bgp_table *table;
5493 struct bgp_info *ri, *new;
5494
5495 table = bgp->rib[afi][safi];
5496
5497 rn = bgp_node_get(table, p);
eaaf8adb
DS
5498
5499 for (ri = rn->info; ri; ri = ri->next)
5500 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
5501 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5502 break;
5503
c701010e 5504 if (aggregate->count > 0) {
eaaf8adb
DS
5505 /*
5506 * If the aggregate information has not changed
5507 * no need to re-install it again.
5508 */
29f7d023
DS
5509 if (bgp_aggregate_info_same(rn->info, origin, aspath,
5510 community)) {
eaaf8adb
DS
5511 bgp_unlock_node(rn);
5512
5513 if (aspath)
5514 aspath_free(aspath);
5515 if (community)
5516 community_free(community);
5517
5518 return;
5519 }
5520
5521 /*
5522 * Mark the old as unusable
5523 */
5524 if (ri)
5525 bgp_info_delete(rn, ri);
5526
c701010e
DS
5527 new = info_make(
5528 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5529 bgp_attr_aggregate_intern(bgp, origin, aspath,
5530 community, aggregate->as_set,
5531 atomic_aggregate),
5532 rn);
5533 SET_FLAG(new->flags, BGP_INFO_VALID);
5534
5535 bgp_info_add(rn, new);
5536 bgp_process(bgp, rn, afi, safi);
5537 } else {
5538 for (ri = rn->info; ri; ri = ri->next)
5539 if (ri->peer == bgp->peer_self
5540 && ri->type == ZEBRA_ROUTE_BGP
5541 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5542 break;
5543
5544 /* Withdraw static BGP route from routing table. */
5545 if (ri) {
5546 bgp_info_delete(rn, ri);
5547 bgp_process(bgp, rn, afi, safi);
5548 }
5549 }
5550
5551 bgp_unlock_node(rn);
5552}
5553
b5d58c32 5554/* Update an aggregate as routes are added/removed from the BGP table */
d62a17ae 5555static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
5556 struct bgp_info *rinew, afi_t afi, safi_t safi,
5557 struct bgp_info *del,
5558 struct bgp_aggregate *aggregate)
5559{
5560 struct bgp_table *table;
5561 struct bgp_node *top;
5562 struct bgp_node *rn;
d7c0a89a 5563 uint8_t origin;
d62a17ae 5564 struct aspath *aspath = NULL;
5565 struct aspath *asmerge = NULL;
5566 struct community *community = NULL;
5567 struct community *commerge = NULL;
d62a17ae 5568 struct bgp_info *ri;
d62a17ae 5569 unsigned long match = 0;
d7c0a89a 5570 uint8_t atomic_aggregate = 0;
d62a17ae 5571
d62a17ae 5572 /* ORIGIN attribute: If at least one route among routes that are
5573 aggregated has ORIGIN with the value INCOMPLETE, then the
5574 aggregated route must have the ORIGIN attribute with the value
5575 INCOMPLETE. Otherwise, if at least one route among routes that
5576 are aggregated has ORIGIN with the value EGP, then the aggregated
5577 route must have the origin attribute with the value EGP. In all
5578 other case the value of the ORIGIN attribute of the aggregated
5579 route is INTERNAL. */
5580 origin = BGP_ORIGIN_IGP;
718e3744 5581
d62a17ae 5582 table = bgp->rib[afi][safi];
718e3744 5583
d62a17ae 5584 top = bgp_node_get(table, p);
5585 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
5586 rn = bgp_route_next_until(rn, top)) {
5587 if (rn->p.prefixlen <= p->prefixlen)
5588 continue;
d62a17ae 5589
c2ff8b3e 5590 match = 0;
d62a17ae 5591
c2ff8b3e
DS
5592 for (ri = rn->info; ri; ri = ri->next) {
5593 if (BGP_INFO_HOLDDOWN(ri))
5594 continue;
718e3744 5595
c2ff8b3e
DS
5596 if (del && ri == del)
5597 continue;
718e3744 5598
c2ff8b3e
DS
5599 if (ri->attr->flag
5600 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5601 atomic_aggregate = 1;
d62a17ae 5602
c2ff8b3e
DS
5603 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5604 continue;
d62a17ae 5605
f273fef1
DS
5606 /*
5607 * summary-only aggregate route suppress
5608 * aggregated route announcements.
5609 */
c2ff8b3e
DS
5610 if (aggregate->summary_only) {
5611 (bgp_info_extra_get(ri))->suppress++;
5612 bgp_info_set_flag(rn, ri,
5613 BGP_INFO_ATTR_CHANGED);
5614 match++;
d62a17ae 5615 }
c2ff8b3e
DS
5616
5617 aggregate->count++;
5618
f273fef1
DS
5619 /*
5620 * If at least one route among routes that are
5621 * aggregated has ORIGIN with the value INCOMPLETE,
5622 * then the aggregated route MUST have the ORIGIN
5623 * attribute with the value INCOMPLETE. Otherwise, if
5624 * at least one route among routes that are aggregated
5625 * has ORIGIN with the value EGP, then the aggregated
5626 * route MUST have the ORIGIN attribute with the value
5627 * EGP.
5628 */
c2ff8b3e
DS
5629 if (origin < ri->attr->origin)
5630 origin = ri->attr->origin;
5631
5632 if (!aggregate->as_set)
5633 continue;
5634
f273fef1
DS
5635 /*
5636 * as-set aggregate route generate origin, as path,
5637 * and community aggregation.
5638 */
c2ff8b3e
DS
5639 if (aspath) {
5640 asmerge = aspath_aggregate(aspath,
5641 ri->attr->aspath);
5642 aspath_free(aspath);
5643 aspath = asmerge;
5644 } else
5645 aspath = aspath_dup(ri->attr->aspath);
5646
5647 if (!ri->attr->community)
5648 continue;
5649
5650 if (community) {
5651 commerge = community_merge(community,
5652 ri->attr->community);
5653 community = community_uniq_sort(commerge);
5654 community_free(commerge);
5655 } else
5656 community = community_dup(ri->attr->community);
d62a17ae 5657 }
c2ff8b3e
DS
5658 if (match)
5659 bgp_process(bgp, rn, afi, safi);
5660 }
d62a17ae 5661 bgp_unlock_node(top);
718e3744 5662
d62a17ae 5663 if (rinew) {
718e3744 5664 aggregate->count++;
5665
d62a17ae 5666 if (aggregate->summary_only)
5667 (bgp_info_extra_get(rinew))->suppress++;
5668
5669 if (origin < rinew->attr->origin)
5670 origin = rinew->attr->origin;
5671
5672 if (aggregate->as_set) {
5673 if (aspath) {
5674 asmerge = aspath_aggregate(aspath,
5675 rinew->attr->aspath);
5676 aspath_free(aspath);
5677 aspath = asmerge;
5678 } else
5679 aspath = aspath_dup(rinew->attr->aspath);
5680
5681 if (rinew->attr->community) {
5682 if (community) {
5683 commerge = community_merge(
5684 community,
5685 rinew->attr->community);
5686 community =
5687 community_uniq_sort(commerge);
5688 community_free(commerge);
5689 } else
5690 community = community_dup(
5691 rinew->attr->community);
5692 }
718e3744 5693 }
718e3744 5694 }
718e3744 5695
c701010e
DS
5696 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
5697 atomic_aggregate, aggregate);
d62a17ae 5698
c701010e 5699 if (aggregate->count == 0) {
d62a17ae 5700 if (aspath)
5701 aspath_free(aspath);
5702 if (community)
5703 community_free(community);
5704 }
718e3744 5705}
5706
3b7db173
DS
5707static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5708 safi_t safi, struct bgp_aggregate *aggregate)
5709{
5710 struct bgp_table *table;
5711 struct bgp_node *top;
5712 struct bgp_node *rn;
5713 struct bgp_info *ri;
5714 unsigned long match;
5715
5716 table = bgp->rib[afi][safi];
5717
5718 /* If routes exists below this node, generate aggregate routes. */
5719 top = bgp_node_get(table, p);
5720 for (rn = bgp_node_get(table, p); rn;
5721 rn = bgp_route_next_until(rn, top)) {
5722 if (rn->p.prefixlen <= p->prefixlen)
5723 continue;
5724 match = 0;
5725
5726 for (ri = rn->info; ri; ri = ri->next) {
5727 if (BGP_INFO_HOLDDOWN(ri))
5728 continue;
5729
5730 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5731 continue;
5732
5733 if (aggregate->summary_only && ri->extra) {
5734 ri->extra->suppress--;
5735
5736 if (ri->extra->suppress == 0) {
5737 bgp_info_set_flag(
5738 rn, ri, BGP_INFO_ATTR_CHANGED);
5739 match++;
5740 }
5741 }
5742 aggregate->count--;
5743 }
5744
5745 /* If this node was suppressed, process the change. */
5746 if (match)
5747 bgp_process(bgp, rn, afi, safi);
5748 }
5749 bgp_unlock_node(top);
5750}
718e3744 5751
d62a17ae 5752void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
5753 struct bgp_info *ri, afi_t afi, safi_t safi)
718e3744 5754{
d62a17ae 5755 struct bgp_node *child;
5756 struct bgp_node *rn;
5757 struct bgp_aggregate *aggregate;
5758 struct bgp_table *table;
718e3744 5759
d62a17ae 5760 table = bgp->aggregate[afi][safi];
f018db83 5761
d62a17ae 5762 /* No aggregates configured. */
5763 if (bgp_table_top_nolock(table) == NULL)
5764 return;
f018db83 5765
d62a17ae 5766 if (p->prefixlen == 0)
5767 return;
718e3744 5768
d62a17ae 5769 if (BGP_INFO_HOLDDOWN(ri))
5770 return;
718e3744 5771
d62a17ae 5772 child = bgp_node_get(table, p);
718e3744 5773
d62a17ae 5774 /* Aggregate address configuration check. */
b1e62edd
DS
5775 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
5776 aggregate = bgp_aggregate_get_node_info(rn);
5777 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
d62a17ae 5778 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5779 bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL,
5780 aggregate);
5781 }
b1e62edd 5782 }
d62a17ae 5783 bgp_unlock_node(child);
718e3744 5784}
5785
d62a17ae 5786void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
5787 struct bgp_info *del, afi_t afi, safi_t safi)
718e3744 5788{
d62a17ae 5789 struct bgp_node *child;
5790 struct bgp_node *rn;
5791 struct bgp_aggregate *aggregate;
5792 struct bgp_table *table;
718e3744 5793
d62a17ae 5794 table = bgp->aggregate[afi][safi];
718e3744 5795
d62a17ae 5796 /* No aggregates configured. */
5797 if (bgp_table_top_nolock(table) == NULL)
5798 return;
718e3744 5799
d62a17ae 5800 if (p->prefixlen == 0)
5801 return;
718e3744 5802
d62a17ae 5803 child = bgp_node_get(table, p);
718e3744 5804
d62a17ae 5805 /* Aggregate address configuration check. */
b1e62edd
DS
5806 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
5807 aggregate = bgp_aggregate_get_node_info(rn);
5808 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
d62a17ae 5809 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5810 bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
5811 aggregate);
5812 }
b1e62edd 5813 }
d62a17ae 5814 bgp_unlock_node(child);
5815}
718e3744 5816
718e3744 5817/* Aggregate route attribute. */
5818#define AGGREGATE_SUMMARY_ONLY 1
5819#define AGGREGATE_AS_SET 1
5820
d62a17ae 5821static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5822 afi_t afi, safi_t safi)
718e3744 5823{
d62a17ae 5824 VTY_DECLVAR_CONTEXT(bgp, bgp);
5825 int ret;
5826 struct prefix p;
5827 struct bgp_node *rn;
5828 struct bgp_aggregate *aggregate;
718e3744 5829
d62a17ae 5830 /* Convert string to prefix structure. */
5831 ret = str2prefix(prefix_str, &p);
5832 if (!ret) {
5833 vty_out(vty, "Malformed prefix\n");
5834 return CMD_WARNING_CONFIG_FAILED;
5835 }
5836 apply_mask(&p);
5837
5838 /* Old configuration check. */
5839 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5840 if (!rn) {
5841 vty_out(vty,
5842 "%% There is no aggregate-address configuration.\n");
5843 return CMD_WARNING_CONFIG_FAILED;
5844 }
f6269b4f 5845
b1e62edd 5846 aggregate = bgp_aggregate_get_node_info(rn);
09990cdd 5847 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
c701010e 5848 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, 0, aggregate);
d62a17ae 5849
5850 /* Unlock aggregate address configuration. */
b1e62edd 5851 bgp_aggregate_set_node_info(rn, NULL);
d62a17ae 5852 bgp_aggregate_free(aggregate);
5853 bgp_unlock_node(rn);
5854 bgp_unlock_node(rn);
5855
5856 return CMD_SUCCESS;
5857}
5858
5859static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
d7c0a89a 5860 safi_t safi, uint8_t summary_only, uint8_t as_set)
d62a17ae 5861{
5862 VTY_DECLVAR_CONTEXT(bgp, bgp);
5863 int ret;
5864 struct prefix p;
5865 struct bgp_node *rn;
5866 struct bgp_aggregate *aggregate;
5867
5868 /* Convert string to prefix structure. */
5869 ret = str2prefix(prefix_str, &p);
5870 if (!ret) {
5871 vty_out(vty, "Malformed prefix\n");
5872 return CMD_WARNING_CONFIG_FAILED;
5873 }
5874 apply_mask(&p);
5875
3624ac81
DS
5876 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
5877 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
5878 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5879 prefix_str);
5880 return CMD_WARNING_CONFIG_FAILED;
5881 }
5882
d62a17ae 5883 /* Old configuration check. */
5884 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
5885
5886 if (rn->info) {
5887 vty_out(vty, "There is already same aggregate network.\n");
5888 /* try to remove the old entry */
5889 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
5890 if (ret) {
5891 vty_out(vty, "Error deleting aggregate.\n");
5892 bgp_unlock_node(rn);
5893 return CMD_WARNING_CONFIG_FAILED;
5894 }
5895 }
718e3744 5896
d62a17ae 5897 /* Make aggregate address structure. */
5898 aggregate = bgp_aggregate_new();
5899 aggregate->summary_only = summary_only;
5900 aggregate->as_set = as_set;
5901 aggregate->safi = safi;
b1e62edd 5902 bgp_aggregate_set_node_info(rn, aggregate);
718e3744 5903
d62a17ae 5904 /* Aggregate address insert into BGP routing table. */
f273fef1 5905 bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate);
718e3744 5906
d62a17ae 5907 return CMD_SUCCESS;
718e3744 5908}
5909
5910DEFUN (aggregate_address,
5911 aggregate_address_cmd,
e3e6107d 5912 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5913 "Configure BGP aggregate entries\n"
5914 "Aggregate prefix\n"
5915 "Generate AS set path information\n"
a636c635
DW
5916 "Filter more specific routes from updates\n"
5917 "Filter more specific routes from updates\n"
5918 "Generate AS set path information\n")
718e3744 5919{
d62a17ae 5920 int idx = 0;
5921 argv_find(argv, argc, "A.B.C.D/M", &idx);
5922 char *prefix = argv[idx]->arg;
5923 int as_set =
5924 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5925 idx = 0;
5926 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5927 ? AGGREGATE_SUMMARY_ONLY
5928 : 0;
e3e6107d 5929
d62a17ae 5930 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
5931 summary_only, as_set);
718e3744 5932}
5933
e3e6107d
QY
5934DEFUN (aggregate_address_mask,
5935 aggregate_address_mask_cmd,
5936 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5937 "Configure BGP aggregate entries\n"
5938 "Aggregate address\n"
5939 "Aggregate mask\n"
5940 "Generate AS set path information\n"
a636c635
DW
5941 "Filter more specific routes from updates\n"
5942 "Filter more specific routes from updates\n"
5943 "Generate AS set path information\n")
718e3744 5944{
d62a17ae 5945 int idx = 0;
5946 argv_find(argv, argc, "A.B.C.D", &idx);
5947 char *prefix = argv[idx]->arg;
5948 char *mask = argv[idx + 1]->arg;
5949 int as_set =
5950 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5951 idx = 0;
5952 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5953 ? AGGREGATE_SUMMARY_ONLY
5954 : 0;
5955
5956 char prefix_str[BUFSIZ];
5957 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
5958
5959 if (!ret) {
5960 vty_out(vty, "%% Inconsistent address and mask\n");
5961 return CMD_WARNING_CONFIG_FAILED;
5962 }
718e3744 5963
d62a17ae 5964 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5965 summary_only, as_set);
718e3744 5966}
5967
718e3744 5968DEFUN (no_aggregate_address,
5969 no_aggregate_address_cmd,
e3e6107d 5970 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5971 NO_STR
5972 "Configure BGP aggregate entries\n"
a636c635
DW
5973 "Aggregate prefix\n"
5974 "Generate AS set path information\n"
e3e6107d
QY
5975 "Filter more specific routes from updates\n"
5976 "Filter more specific routes from updates\n"
5977 "Generate AS set path information\n")
718e3744 5978{
d62a17ae 5979 int idx = 0;
5980 argv_find(argv, argc, "A.B.C.D/M", &idx);
5981 char *prefix = argv[idx]->arg;
5982 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 5983}
5984
718e3744 5985DEFUN (no_aggregate_address_mask,
5986 no_aggregate_address_mask_cmd,
e3e6107d 5987 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5988 NO_STR
5989 "Configure BGP aggregate entries\n"
5990 "Aggregate address\n"
a636c635
DW
5991 "Aggregate mask\n"
5992 "Generate AS set path information\n"
e3e6107d
QY
5993 "Filter more specific routes from updates\n"
5994 "Filter more specific routes from updates\n"
5995 "Generate AS set path information\n")
718e3744 5996{
d62a17ae 5997 int idx = 0;
5998 argv_find(argv, argc, "A.B.C.D", &idx);
5999 char *prefix = argv[idx]->arg;
6000 char *mask = argv[idx + 1]->arg;
718e3744 6001
d62a17ae 6002 char prefix_str[BUFSIZ];
6003 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6004
d62a17ae 6005 if (!ret) {
6006 vty_out(vty, "%% Inconsistent address and mask\n");
6007 return CMD_WARNING_CONFIG_FAILED;
6008 }
718e3744 6009
d62a17ae 6010 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6011}
6012
718e3744 6013DEFUN (ipv6_aggregate_address,
6014 ipv6_aggregate_address_cmd,
e3e6107d 6015 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6016 "Configure BGP aggregate entries\n"
6017 "Aggregate prefix\n"
6018 "Filter more specific routes from updates\n")
6019{
d62a17ae 6020 int idx = 0;
6021 argv_find(argv, argc, "X:X::X:X/M", &idx);
6022 char *prefix = argv[idx]->arg;
6023 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6024 ? AGGREGATE_SUMMARY_ONLY
6025 : 0;
6026 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6027 0);
718e3744 6028}
6029
6030DEFUN (no_ipv6_aggregate_address,
6031 no_ipv6_aggregate_address_cmd,
e3e6107d 6032 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6033 NO_STR
6034 "Configure BGP aggregate entries\n"
16cedbb0
QY
6035 "Aggregate prefix\n"
6036 "Filter more specific routes from updates\n")
718e3744 6037{
d62a17ae 6038 int idx = 0;
6039 argv_find(argv, argc, "X:X::X:X/M", &idx);
6040 char *prefix = argv[idx]->arg;
6041 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6042}
6043
718e3744 6044/* Redistribute route treatment. */
d62a17ae 6045void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6046 const union g_addr *nexthop, ifindex_t ifindex,
6047 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
6048 uint8_t type, unsigned short instance,
6049 route_tag_t tag)
d62a17ae 6050{
6051 struct bgp_info *new;
6052 struct bgp_info *bi;
6053 struct bgp_info info;
6054 struct bgp_node *bn;
6055 struct attr attr;
6056 struct attr *new_attr;
6057 afi_t afi;
6058 int ret;
6059 struct bgp_redist *red;
6060
6061 /* Make default attribute. */
6062 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff 6063
a4d82a8a 6064 switch (nhtype) {
9de1f7ff
DS
6065 case NEXTHOP_TYPE_IFINDEX:
6066 break;
6067 case NEXTHOP_TYPE_IPV4:
6068 case NEXTHOP_TYPE_IPV4_IFINDEX:
6069 attr.nexthop = nexthop->ipv4;
6070 break;
6071 case NEXTHOP_TYPE_IPV6:
6072 case NEXTHOP_TYPE_IPV6_IFINDEX:
6073 attr.mp_nexthop_global = nexthop->ipv6;
6074 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6075 break;
6076 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6077 switch (p->family) {
6078 case AF_INET:
9de1f7ff 6079 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6080 break;
6081 case AF_INET6:
9de1f7ff
DS
6082 memset(&attr.mp_nexthop_global, 0,
6083 sizeof(attr.mp_nexthop_global));
74489921 6084 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6085 break;
74489921 6086 }
9de1f7ff 6087 break;
d62a17ae 6088 }
74489921 6089 attr.nh_ifindex = ifindex;
f04a80a5 6090
d62a17ae 6091 attr.med = metric;
6092 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6093 attr.tag = tag;
718e3744 6094
d62a17ae 6095 afi = family2afi(p->family);
6aeb9e78 6096
d62a17ae 6097 red = bgp_redist_lookup(bgp, afi, type, instance);
6098 if (red) {
6099 struct attr attr_new;
718e3744 6100
d62a17ae 6101 /* Copy attribute for modification. */
6102 bgp_attr_dup(&attr_new, &attr);
718e3744 6103
d62a17ae 6104 if (red->redist_metric_flag)
6105 attr_new.med = red->redist_metric;
718e3744 6106
d62a17ae 6107 /* Apply route-map. */
6108 if (red->rmap.name) {
80ced710 6109 memset(&info, 0, sizeof(struct bgp_info));
d62a17ae 6110 info.peer = bgp->peer_self;
6111 info.attr = &attr_new;
718e3744 6112
d62a17ae 6113 SET_FLAG(bgp->peer_self->rmap_type,
6114 PEER_RMAP_TYPE_REDISTRIBUTE);
6115
6116 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
6117 &info);
6118
6119 bgp->peer_self->rmap_type = 0;
6120
6121 if (ret == RMAP_DENYMATCH) {
6122 /* Free uninterned attribute. */
6123 bgp_attr_flush(&attr_new);
6124
6125 /* Unintern original. */
6126 aspath_unintern(&attr.aspath);
6127 bgp_redistribute_delete(bgp, p, type, instance);
6128 return;
6129 }
6130 }
6131
7f323236
DW
6132 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6133 bgp_attr_add_gshut_community(&attr_new);
6134
d62a17ae 6135 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6136 SAFI_UNICAST, p, NULL);
6137
6138 new_attr = bgp_attr_intern(&attr_new);
6139
6140 for (bi = bn->info; bi; bi = bi->next)
6141 if (bi->peer == bgp->peer_self
6142 && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
6143 break;
6144
6145 if (bi) {
6146 /* Ensure the (source route) type is updated. */
6147 bi->type = type;
6148 if (attrhash_cmp(bi->attr, new_attr)
6149 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
6150 bgp_attr_unintern(&new_attr);
6151 aspath_unintern(&attr.aspath);
6152 bgp_unlock_node(bn);
6153 return;
6154 } else {
6155 /* The attribute is changed. */
6156 bgp_info_set_flag(bn, bi,
6157 BGP_INFO_ATTR_CHANGED);
6158
6159 /* Rewrite BGP route information. */
6160 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
6161 bgp_info_restore(bn, bi);
6162 else
6163 bgp_aggregate_decrement(bgp, p, bi, afi,
6164 SAFI_UNICAST);
6165 bgp_attr_unintern(&bi->attr);
6166 bi->attr = new_attr;
6167 bi->uptime = bgp_clock();
6168
6169 /* Process change. */
6170 bgp_aggregate_increment(bgp, p, bi, afi,
6171 SAFI_UNICAST);
6172 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6173 bgp_unlock_node(bn);
6174 aspath_unintern(&attr.aspath);
ddb5b488
PZ
6175
6176 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6177 || (bgp->inst_type
6178 == BGP_INSTANCE_TYPE_DEFAULT)) {
6179
6180 vpn_leak_from_vrf_update(
6181 bgp_get_default(), bgp, bi);
6182 }
d62a17ae 6183 return;
6184 }
6185 }
6186
6187 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6188 bgp->peer_self, new_attr, bn);
6189 SET_FLAG(new->flags, BGP_INFO_VALID);
6190
6191 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
6192 bgp_info_add(bn, new);
6193 bgp_unlock_node(bn);
6194 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
6195
6196 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6197 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6198
6199 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6200 }
d62a17ae 6201 }
6202
6203 /* Unintern original. */
6204 aspath_unintern(&attr.aspath);
718e3744 6205}
6206
d7c0a89a
QY
6207void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
6208 unsigned short instance)
718e3744 6209{
d62a17ae 6210 afi_t afi;
6211 struct bgp_node *rn;
6212 struct bgp_info *ri;
6213 struct bgp_redist *red;
718e3744 6214
d62a17ae 6215 afi = family2afi(p->family);
718e3744 6216
d62a17ae 6217 red = bgp_redist_lookup(bgp, afi, type, instance);
6218 if (red) {
6219 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6220 SAFI_UNICAST, p, NULL);
6221
6222 for (ri = rn->info; ri; ri = ri->next)
6223 if (ri->peer == bgp->peer_self && ri->type == type)
6224 break;
6225
6226 if (ri) {
ddb5b488
PZ
6227 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6228 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6229
6230 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6231 bgp, ri);
6232 }
d62a17ae 6233 bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
6234 bgp_info_delete(rn, ri);
6235 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6236 }
6237 bgp_unlock_node(rn);
6238 }
6239}
6240
6241/* Withdraw specified route type's route. */
6242void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 6243 unsigned short instance)
d62a17ae 6244{
6245 struct bgp_node *rn;
6246 struct bgp_info *ri;
6247 struct bgp_table *table;
6248
6249 table = bgp->rib[afi][SAFI_UNICAST];
6250
6251 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6252 for (ri = rn->info; ri; ri = ri->next)
6253 if (ri->peer == bgp->peer_self && ri->type == type
6254 && ri->instance == instance)
6255 break;
6256
6257 if (ri) {
ddb5b488
PZ
6258 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6259 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6260
6261 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6262 bgp, ri);
6263 }
d62a17ae 6264 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
6265 SAFI_UNICAST);
6266 bgp_info_delete(rn, ri);
6267 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6268 }
718e3744 6269 }
718e3744 6270}
6b0655a2 6271
718e3744 6272/* Static function to display route. */
9c92b5f7
MK
6273static void route_vty_out_route(struct prefix *p, struct vty *vty,
6274 json_object *json)
718e3744 6275{
be054588 6276 int len = 0;
d62a17ae 6277 char buf[BUFSIZ];
718e3744 6278
d62a17ae 6279 if (p->family == AF_INET) {
c6462ff4 6280 if (!json) {
89e5e9f0
PM
6281 len = vty_out(
6282 vty, "%s/%d",
6283 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6284 p->prefixlen);
c6462ff4
MK
6285 } else {
6286 json_object_string_add(json, "prefix",
6287 inet_ntop(p->family,
6288 &p->u.prefix, buf,
6289 BUFSIZ));
6290 json_object_int_add(json, "prefixLen", p->prefixlen);
6291 }
d62a17ae 6292 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6293 prefix2str(p, buf, PREFIX_STRLEN);
6294 len = vty_out(vty, "%s", buf);
6295 } else if (p->family == AF_EVPN) {
57f7feb6 6296 if (!json)
60466a63
QY
6297 len = vty_out(
6298 vty, "%s",
6299 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6300 BUFSIZ));
57f7feb6 6301 else
60466a63 6302 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
6303 } else if (p->family == AF_FLOWSPEC) {
6304 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
6305 json ?
6306 NLRI_STRING_FORMAT_JSON_SIMPLE :
6307 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 6308 } else {
c6462ff4 6309 if (!json)
60466a63
QY
6310 len = vty_out(
6311 vty, "%s/%d",
6312 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6313 p->prefixlen);
9c92b5f7 6314 }
d62a17ae 6315
9c92b5f7
MK
6316 if (!json) {
6317 len = 17 - len;
6318 if (len < 1)
6319 vty_out(vty, "\n%*s", 20, " ");
6320 else
6321 vty_out(vty, "%*s", len, " ");
6322 }
718e3744 6323}
6324
d62a17ae 6325enum bgp_display_type {
6326 normal_list,
718e3744 6327};
6328
b40d939b 6329/* Print the short form route status for a bgp_info */
d62a17ae 6330static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo,
6331 json_object *json_path)
718e3744 6332{
d62a17ae 6333 if (json_path) {
b05a1c8b 6334
d62a17ae 6335 /* Route status display. */
6336 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6337 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6338
d62a17ae 6339 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6340 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6341
d62a17ae 6342 if (binfo->extra && binfo->extra->suppress)
6343 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6344
d62a17ae 6345 if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6346 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6347 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6348
d62a17ae 6349 /* Selected */
6350 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6351 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6352
d62a17ae 6353 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6354 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6355
d62a17ae 6356 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6357 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6358
d62a17ae 6359 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6360 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6361
d62a17ae 6362 /* Internal route. */
6363 if ((binfo->peer->as)
6364 && (binfo->peer->as == binfo->peer->local_as))
6365 json_object_string_add(json_path, "pathFrom",
6366 "internal");
6367 else
6368 json_object_string_add(json_path, "pathFrom",
6369 "external");
b05a1c8b 6370
d62a17ae 6371 return;
6372 }
b05a1c8b 6373
d62a17ae 6374 /* Route status display. */
6375 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6376 vty_out(vty, "R");
6377 else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6378 vty_out(vty, "S");
6379 else if (binfo->extra && binfo->extra->suppress)
6380 vty_out(vty, "s");
6381 else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6382 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6383 vty_out(vty, "*");
6384 else
6385 vty_out(vty, " ");
6386
6387 /* Selected */
6388 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6389 vty_out(vty, "h");
6390 else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6391 vty_out(vty, "d");
6392 else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6393 vty_out(vty, ">");
6394 else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6395 vty_out(vty, "=");
6396 else
6397 vty_out(vty, " ");
718e3744 6398
d62a17ae 6399 /* Internal route. */
6400 if (binfo->peer && (binfo->peer->as)
6401 && (binfo->peer->as == binfo->peer->local_as))
6402 vty_out(vty, "i");
6403 else
6404 vty_out(vty, " ");
b40d939b 6405}
6406
6407/* called from terminal list command */
d62a17ae 6408void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6409 int display, safi_t safi, json_object *json_paths)
6410{
6411 struct attr *attr;
6412 json_object *json_path = NULL;
6413 json_object *json_nexthops = NULL;
6414 json_object *json_nexthop_global = NULL;
6415 json_object *json_nexthop_ll = NULL;
9df8b37c
PZ
6416 char vrf_id_str[VRF_NAMSIZ] = {0};
6417 bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
6418 ? true
6419 : false;
6420 bool nexthop_othervrf = false;
43089216 6421 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
9df8b37c 6422 const char *nexthop_vrfname = "Default";
d62a17ae 6423
6424 if (json_paths)
6425 json_path = json_object_new_object();
6426
6427 /* short status lead text */
6428 route_vty_short_status_out(vty, binfo, json_path);
6429
6430 if (!json_paths) {
6431 /* print prefix and mask */
6432 if (!display)
9c92b5f7 6433 route_vty_out_route(p, vty, json_path);
d62a17ae 6434 else
6435 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6436 } else {
b682f6de 6437 route_vty_out_route(p, vty, json_path);
d62a17ae 6438 }
47fc97cc 6439
d62a17ae 6440 /* Print attribute */
6441 attr = binfo->attr;
445c2480
DS
6442 if (!attr) {
6443 if (json_paths)
6444 json_object_array_add(json_paths, json_path);
6445 else
6446 vty_out(vty, "\n");
d62a17ae 6447
445c2480
DS
6448 return;
6449 }
6450
9df8b37c
PZ
6451 /*
6452 * If vrf id of nexthop is different from that of prefix,
6453 * set up printable string to append
6454 */
6455 if (binfo->extra && binfo->extra->bgp_orig) {
6456 const char *self = "";
6457
6458 if (nexthop_self)
6459 self = "<";
6460
6461 nexthop_othervrf = true;
6462 nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
6463
6464 if (binfo->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
6465 snprintf(vrf_id_str, sizeof(vrf_id_str),
6466 "@%s%s", VRFID_NONE_STR, self);
6467 else
6468 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
6469 binfo->extra->bgp_orig->vrf_id, self);
6470
6471 if (binfo->extra->bgp_orig->inst_type !=
6472 BGP_INSTANCE_TYPE_DEFAULT)
6473
6474 nexthop_vrfname = binfo->extra->bgp_orig->name;
6475 } else {
6476 const char *self = "";
6477
6478 if (nexthop_self)
6479 self = "<";
6480
6481 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
6482 }
6483
445c2480
DS
6484 /*
6485 * For ENCAP and EVPN routes, nexthop address family is not
6486 * neccessarily the same as the prefix address family.
6487 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6488 * EVPN routes are also exchanged with a MP nexthop. Currently,
6489 * this
6490 * is only IPv4, the value will be present in either
6491 * attr->nexthop or
6492 * attr->mp_nexthop_global_in
6493 */
6494 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6495 char buf[BUFSIZ];
6496 char nexthop[128];
6497 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6498
6499 switch (af) {
6500 case AF_INET:
6501 sprintf(nexthop, "%s",
a4d82a8a
PZ
6502 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
6503 BUFSIZ));
445c2480
DS
6504 break;
6505 case AF_INET6:
6506 sprintf(nexthop, "%s",
a4d82a8a
PZ
6507 inet_ntop(af, &attr->mp_nexthop_global, buf,
6508 BUFSIZ));
445c2480
DS
6509 break;
6510 default:
6511 sprintf(nexthop, "?");
6512 break;
d62a17ae 6513 }
d62a17ae 6514
445c2480
DS
6515 if (json_paths) {
6516 json_nexthop_global = json_object_new_object();
6517
a4d82a8a
PZ
6518 json_object_string_add(json_nexthop_global, "afi",
6519 (af == AF_INET) ? "ip" : "ipv6");
445c2480 6520 json_object_string_add(json_nexthop_global,
a4d82a8a 6521 (af == AF_INET) ? "ip" : "ipv6",
445c2480
DS
6522 nexthop);
6523 json_object_boolean_true_add(json_nexthop_global,
6524 "used");
6525 } else
9df8b37c 6526 vty_out(vty, "%s%s", nexthop, vrf_id_str);
445c2480
DS
6527 } else if (safi == SAFI_EVPN) {
6528 if (json_paths) {
6529 json_nexthop_global = json_object_new_object();
6530
6531 json_object_string_add(json_nexthop_global, "ip",
6532 inet_ntoa(attr->nexthop));
a4d82a8a
PZ
6533 json_object_string_add(json_nexthop_global, "afi",
6534 "ipv4");
445c2480
DS
6535 json_object_boolean_true_add(json_nexthop_global,
6536 "used");
6537 } else
9df8b37c
PZ
6538 vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
6539 vrf_id_str);
d33fc23b 6540 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
6541 if (attr->nexthop.s_addr != 0) {
6542 if (json_paths) {
6543 json_nexthop_global = json_object_new_object();
6544 json_object_string_add(
6545 json_nexthop_global, "ip",
6546 inet_ntoa(attr->nexthop));
6547 json_object_string_add(json_nexthop_global,
6548 "afi", "ipv4");
6549 json_object_boolean_true_add(json_nexthop_global,
6550 "used");
6551 } else {
6552 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6553 }
6554 }
d33fc23b 6555 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6556 if (json_paths) {
6557 json_nexthop_global = json_object_new_object();
d62a17ae 6558
a4d82a8a
PZ
6559 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
6560 json_object_string_add(
6561 json_nexthop_global, "ip",
6562 inet_ntoa(attr->mp_nexthop_global_in));
445c2480 6563 else
a4d82a8a
PZ
6564 json_object_string_add(
6565 json_nexthop_global, "ip",
6566 inet_ntoa(attr->nexthop));
445c2480 6567
a4d82a8a
PZ
6568 json_object_string_add(json_nexthop_global, "afi",
6569 "ipv4");
445c2480
DS
6570 json_object_boolean_true_add(json_nexthop_global,
6571 "used");
6572 } else {
9df8b37c
PZ
6573 char buf[BUFSIZ];
6574
d87ff2dd 6575 snprintf(buf, sizeof(buf), "%s%s",
6576 inet_ntoa(attr->nexthop), vrf_id_str);
9df8b37c 6577 vty_out(vty, "%-16s", buf);
d62a17ae 6578 }
445c2480 6579 }
b05a1c8b 6580
445c2480 6581 /* IPv6 Next Hop */
a4d82a8a 6582 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
6583 int len;
6584 char buf[BUFSIZ];
d62a17ae 6585
445c2480
DS
6586 if (json_paths) {
6587 json_nexthop_global = json_object_new_object();
a4d82a8a
PZ
6588 json_object_string_add(
6589 json_nexthop_global, "ip",
6590 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
6591 buf, BUFSIZ));
6592 json_object_string_add(json_nexthop_global, "afi",
6593 "ipv6");
6594 json_object_string_add(json_nexthop_global, "scope",
6595 "global");
445c2480
DS
6596
6597 /* We display both LL & GL if both have been
6598 * received */
6599 if ((attr->mp_nexthop_len == 32)
6600 || (binfo->peer->conf_if)) {
a4d82a8a 6601 json_nexthop_ll = json_object_new_object();
d62a17ae 6602 json_object_string_add(
445c2480 6603 json_nexthop_ll, "ip",
a4d82a8a
PZ
6604 inet_ntop(AF_INET6,
6605 &attr->mp_nexthop_local, buf,
6606 BUFSIZ));
6607 json_object_string_add(json_nexthop_ll, "afi",
6608 "ipv6");
6609 json_object_string_add(json_nexthop_ll, "scope",
445c2480 6610 "link-local");
d62a17ae 6611
a4d82a8a
PZ
6612 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
6613 &attr->mp_nexthop_local)
445c2480
DS
6614 != 0)
6615 && !attr->mp_nexthop_prefer_global)
d62a17ae 6616 json_object_boolean_true_add(
a4d82a8a 6617 json_nexthop_ll, "used");
445c2480
DS
6618 else
6619 json_object_boolean_true_add(
a4d82a8a 6620 json_nexthop_global, "used");
445c2480
DS
6621 } else
6622 json_object_boolean_true_add(
6623 json_nexthop_global, "used");
6624 } else {
6625 /* Display LL if LL/Global both in table unless
6626 * prefer-global is set */
6627 if (((attr->mp_nexthop_len == 32)
6628 && !attr->mp_nexthop_prefer_global)
6629 || (binfo->peer->conf_if)) {
6630 if (binfo->peer->conf_if) {
a4d82a8a
PZ
6631 len = vty_out(vty, "%s",
6632 binfo->peer->conf_if);
445c2480
DS
6633 len = 16 - len; /* len of IPv6
6634 addr + max
6635 len of def
6636 ifname */
6637
6638 if (len < 1)
a4d82a8a 6639 vty_out(vty, "\n%*s", 36, " ");
445c2480 6640 else
a4d82a8a 6641 vty_out(vty, "%*s", len, " ");
d62a17ae 6642 } else {
6643 len = vty_out(
9df8b37c 6644 vty, "%s%s",
d62a17ae 6645 inet_ntop(
6646 AF_INET6,
445c2480 6647 &attr->mp_nexthop_local,
9df8b37c
PZ
6648 buf, BUFSIZ),
6649 vrf_id_str);
d62a17ae 6650 len = 16 - len;
6651
6652 if (len < 1)
a4d82a8a 6653 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 6654 else
a4d82a8a 6655 vty_out(vty, "%*s", len, " ");
d62a17ae 6656 }
445c2480 6657 } else {
a4d82a8a 6658 len = vty_out(
9df8b37c 6659 vty, "%s%s",
a4d82a8a
PZ
6660 inet_ntop(AF_INET6,
6661 &attr->mp_nexthop_global, buf,
9df8b37c
PZ
6662 BUFSIZ),
6663 vrf_id_str);
445c2480
DS
6664 len = 16 - len;
6665
6666 if (len < 1)
6667 vty_out(vty, "\n%*s", 36, " ");
6668 else
6669 vty_out(vty, "%*s", len, " ");
d62a17ae 6670 }
6671 }
445c2480 6672 }
718e3744 6673
445c2480
DS
6674 /* MED/Metric */
6675 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6676 if (json_paths)
a4d82a8a 6677 json_object_int_add(json_path, "med", attr->med);
445c2480
DS
6678 else
6679 vty_out(vty, "%10u", attr->med);
6680 else if (!json_paths)
6681 vty_out(vty, " ");
d62a17ae 6682
445c2480
DS
6683 /* Local Pref */
6684 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
d62a17ae 6685 if (json_paths)
445c2480
DS
6686 json_object_int_add(json_path, "localpref",
6687 attr->local_pref);
d62a17ae 6688 else
445c2480
DS
6689 vty_out(vty, "%7u", attr->local_pref);
6690 else if (!json_paths)
6691 vty_out(vty, " ");
d62a17ae 6692
445c2480
DS
6693 if (json_paths)
6694 json_object_int_add(json_path, "weight", attr->weight);
6695 else
6696 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6697
445c2480
DS
6698 if (json_paths) {
6699 char buf[BUFSIZ];
a4d82a8a
PZ
6700 json_object_string_add(
6701 json_path, "peerId",
6702 sockunion2str(&binfo->peer->su, buf, SU_ADDRSTRLEN));
445c2480 6703 }
b05a1c8b 6704
445c2480
DS
6705 /* Print aspath */
6706 if (attr->aspath) {
d62a17ae 6707 if (json_paths)
445c2480
DS
6708 json_object_string_add(json_path, "aspath",
6709 attr->aspath->str);
d62a17ae 6710 else
445c2480 6711 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6712 }
f1aa5d8a 6713
445c2480
DS
6714 /* Print origin */
6715 if (json_paths)
a4d82a8a
PZ
6716 json_object_string_add(json_path, "origin",
6717 bgp_origin_long_str[attr->origin]);
445c2480
DS
6718 else
6719 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6720
9df8b37c
PZ
6721 if (json_paths) {
6722 if (nexthop_self)
6723 json_object_boolean_true_add(json_path,
6724 "announceNexthopSelf");
6725 if (nexthop_othervrf) {
6726 json_object_string_add(json_path, "nhVrfName",
6727 nexthop_vrfname);
6728
6729 json_object_int_add(json_path, "nhVrfId",
6730 ((nexthop_vrfid == VRF_UNKNOWN)
6731 ? -1
6732 : (int)nexthop_vrfid));
6733 }
6734 }
6735
d62a17ae 6736 if (json_paths) {
6737 if (json_nexthop_global || json_nexthop_ll) {
6738 json_nexthops = json_object_new_array();
f1aa5d8a 6739
d62a17ae 6740 if (json_nexthop_global)
6741 json_object_array_add(json_nexthops,
6742 json_nexthop_global);
f1aa5d8a 6743
d62a17ae 6744 if (json_nexthop_ll)
6745 json_object_array_add(json_nexthops,
6746 json_nexthop_ll);
f1aa5d8a 6747
d62a17ae 6748 json_object_object_add(json_path, "nexthops",
6749 json_nexthops);
6750 }
6751
6752 json_object_array_add(json_paths, json_path);
6753 } else {
6754 vty_out(vty, "\n");
65efcfce 6755#if ENABLE_BGP_VNC
d62a17ae 6756 /* prints an additional line, indented, with VNC info, if
6757 * present */
6758 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
6759 rfapi_vty_out_vncinfo(vty, p, binfo, safi);
65efcfce 6760#endif
d62a17ae 6761 }
6762}
718e3744 6763
6764/* called from terminal list command */
d62a17ae 6765void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 6766 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 6767{
6768 json_object *json_status = NULL;
6769 json_object *json_net = NULL;
6770 char buff[BUFSIZ];
6771 /* Route status display. */
6772 if (use_json) {
6773 json_status = json_object_new_object();
6774 json_net = json_object_new_object();
6775 } else {
6776 vty_out(vty, "*");
6777 vty_out(vty, ">");
6778 vty_out(vty, " ");
6779 }
718e3744 6780
d62a17ae 6781 /* print prefix and mask */
6782 if (use_json)
6783 json_object_string_add(
6784 json_net, "addrPrefix",
6785 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
6786 else
9c92b5f7 6787 route_vty_out_route(p, vty, NULL);
d62a17ae 6788
6789 /* Print attribute */
6790 if (attr) {
6791 if (use_json) {
6792 if (p->family == AF_INET
6793 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6794 || safi == SAFI_EVPN
6795 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6796 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6797 || safi == SAFI_EVPN)
6798 json_object_string_add(
6799 json_net, "nextHop",
6800 inet_ntoa(
6801 attr->mp_nexthop_global_in));
6802 else
6803 json_object_string_add(
6804 json_net, "nextHop",
6805 inet_ntoa(attr->nexthop));
6806 } else if (p->family == AF_INET6
6807 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6808 char buf[BUFSIZ];
6809
6810 json_object_string_add(
6811 json_net, "netHopGloabal",
6812 inet_ntop(AF_INET6,
6813 &attr->mp_nexthop_global, buf,
6814 BUFSIZ));
6815 }
6816
6817 if (attr->flag
6818 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6819 json_object_int_add(json_net, "metric",
6820 attr->med);
6821
6822 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6823 json_object_int_add(json_net, "localPref",
6824 attr->local_pref);
6825
6826 json_object_int_add(json_net, "weight", attr->weight);
6827
6828 /* Print aspath */
6829 if (attr->aspath)
6830 json_object_string_add(json_net, "asPath",
6831 attr->aspath->str);
6832
6833 /* Print origin */
6834 json_object_string_add(json_net, "bgpOriginCode",
6835 bgp_origin_str[attr->origin]);
6836 } else {
6837 if (p->family == AF_INET
6838 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6839 || safi == SAFI_EVPN
6840 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6841 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6842 || safi == SAFI_EVPN)
6843 vty_out(vty, "%-16s",
6844 inet_ntoa(
6845 attr->mp_nexthop_global_in));
6846 else
6847 vty_out(vty, "%-16s",
6848 inet_ntoa(attr->nexthop));
6849 } else if (p->family == AF_INET6
6850 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6851 int len;
6852 char buf[BUFSIZ];
6853
6854 len = vty_out(
6855 vty, "%s",
6856 inet_ntop(AF_INET6,
6857 &attr->mp_nexthop_global, buf,
6858 BUFSIZ));
6859 len = 16 - len;
6860 if (len < 1)
6861 vty_out(vty, "\n%*s", 36, " ");
6862 else
6863 vty_out(vty, "%*s", len, " ");
6864 }
6865 if (attr->flag
6866 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6867 vty_out(vty, "%10u", attr->med);
6868 else
6869 vty_out(vty, " ");
718e3744 6870
d62a17ae 6871 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6872 vty_out(vty, "%7u", attr->local_pref);
6873 else
6874 vty_out(vty, " ");
6875
6876 vty_out(vty, "%7u ", attr->weight);
6877
6878 /* Print aspath */
6879 if (attr->aspath)
6880 aspath_print_vty(vty, "%s", attr->aspath, " ");
6881
6882 /* Print origin */
6883 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6884 }
6885 }
6886 if (use_json) {
6887 json_object_boolean_true_add(json_status, "*");
6888 json_object_boolean_true_add(json_status, ">");
6889 json_object_object_add(json_net, "appliedStatusSymbols",
6890 json_status);
6891 char buf_cut[BUFSIZ];
6892 json_object_object_add(
6893 json_ar,
6894 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
6895 json_net);
6896 } else
6897 vty_out(vty, "\n");
6898}
6899
6900void route_vty_out_tag(struct vty *vty, struct prefix *p,
6901 struct bgp_info *binfo, int display, safi_t safi,
6902 json_object *json)
6903{
6904 json_object *json_out = NULL;
6905 struct attr *attr;
6906 mpls_label_t label = MPLS_INVALID_LABEL;
6907
6908 if (!binfo->extra)
6909 return;
6910
6911 if (json)
6912 json_out = json_object_new_object();
6913
6914 /* short status lead text */
6915 route_vty_short_status_out(vty, binfo, json_out);
6916
6917 /* print prefix and mask */
6918 if (json == NULL) {
6919 if (!display)
9c92b5f7 6920 route_vty_out_route(p, vty, NULL);
d62a17ae 6921 else
6922 vty_out(vty, "%*s", 17, " ");
6923 }
6924
6925 /* Print attribute */
6926 attr = binfo->attr;
6927 if (attr) {
6928 if (((p->family == AF_INET)
6929 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
a4d82a8a 6930 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
d62a17ae 6931 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6932 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6933 || safi == SAFI_EVPN) {
6934 if (json)
6935 json_object_string_add(
6936 json_out, "mpNexthopGlobalIn",
6937 inet_ntoa(
6938 attr->mp_nexthop_global_in));
6939 else
6940 vty_out(vty, "%-16s",
6941 inet_ntoa(
6942 attr->mp_nexthop_global_in));
6943 } else {
6944 if (json)
6945 json_object_string_add(
6946 json_out, "nexthop",
6947 inet_ntoa(attr->nexthop));
6948 else
6949 vty_out(vty, "%-16s",
6950 inet_ntoa(attr->nexthop));
6951 }
6952 } else if (((p->family == AF_INET6)
6953 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6954 || (safi == SAFI_EVPN
d62a17ae 6955 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6956 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
ff44f570
DS
6957 char buf_a[512];
6958 char buf_b[512];
d62a17ae 6959 char buf_c[BUFSIZ];
6960 if (attr->mp_nexthop_len
6961 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
6962 if (json)
6963 json_object_string_add(
6964 json_out, "mpNexthopGlobalIn",
6965 inet_ntop(
6966 AF_INET6,
6967 &attr->mp_nexthop_global,
11f9b450 6968 buf_a, sizeof(buf_a)));
d62a17ae 6969 else
6970 vty_out(vty, "%s",
6971 inet_ntop(
6972 AF_INET6,
6973 &attr->mp_nexthop_global,
11f9b450 6974 buf_a, sizeof(buf_a)));
d62a17ae 6975 } else if (attr->mp_nexthop_len
6976 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
6977 if (json) {
6978 inet_ntop(AF_INET6,
6979 &attr->mp_nexthop_global,
11f9b450 6980 buf_a, sizeof(buf_a));
d62a17ae 6981 inet_ntop(AF_INET6,
6982 &attr->mp_nexthop_local,
11f9b450 6983 buf_b, sizeof(buf_b));
d62a17ae 6984 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
6985 json_object_string_add(
6986 json_out,
6987 "mpNexthopGlobalLocal", buf_c);
6988 } else
6989 vty_out(vty, "%s(%s)",
6990 inet_ntop(
6991 AF_INET6,
6992 &attr->mp_nexthop_global,
11f9b450 6993 buf_a, sizeof(buf_a)),
d62a17ae 6994 inet_ntop(
6995 AF_INET6,
6996 &attr->mp_nexthop_local,
11f9b450 6997 buf_b, sizeof(buf_b)));
d62a17ae 6998 }
6999 }
7000 }
7001
b57ba6d2 7002 label = decode_label(&binfo->extra->label[0]);
d62a17ae 7003
7004 if (bgp_is_valid_label(&label)) {
7005 if (json) {
7006 json_object_int_add(json_out, "notag", label);
7007 json_object_array_add(json, json_out);
7008 } else {
7009 vty_out(vty, "notag/%d", label);
7010 vty_out(vty, "\n");
7011 }
7012 }
7013}
718e3744 7014
d62a17ae 7015void route_vty_out_overlay(struct vty *vty, struct prefix *p,
7016 struct bgp_info *binfo, int display,
7017 json_object *json_paths)
718e3744 7018{
d62a17ae 7019 struct attr *attr;
7020 char buf[BUFSIZ];
7021 json_object *json_path = NULL;
784d3a42 7022
d62a17ae 7023 if (json_paths)
7024 json_path = json_object_new_object();
856ca177 7025
d62a17ae 7026 if (!binfo->extra)
7027 return;
718e3744 7028
d62a17ae 7029 /* short status lead text */
7030 route_vty_short_status_out(vty, binfo, json_path);
856ca177 7031
d62a17ae 7032 /* print prefix and mask */
7033 if (!display)
9c92b5f7 7034 route_vty_out_route(p, vty, NULL);
d62a17ae 7035 else
7036 vty_out(vty, "%*s", 17, " ");
7037
7038 /* Print attribute */
7039 attr = binfo->attr;
7040 if (attr) {
7041 char buf1[BUFSIZ];
7042 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7043
7044 switch (af) {
7045 case AF_INET:
7046 vty_out(vty, "%-16s",
7047 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7048 BUFSIZ));
7049 break;
7050 case AF_INET6:
7051 vty_out(vty, "%s(%s)",
7052 inet_ntop(af, &attr->mp_nexthop_global, buf,
7053 BUFSIZ),
7054 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7055 BUFSIZ));
7056 break;
7057 default:
7058 vty_out(vty, "?");
7059 }
988258b4
QY
7060
7061 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
7062
7063 vty_out(vty, "%s", str);
7064 XFREE(MTYPE_TMP, str);
7065
3714a385 7066 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
988258b4
QY
7067 vty_out(vty, "/%s",
7068 inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
3714a385 7069 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
988258b4
QY
7070 vty_out(vty, "/%s",
7071 inet_ntop(AF_INET6,
7072 &(attr->evpn_overlay.gw_ip.ipv6), buf,
7073 BUFSIZ));
7074 }
7075 if (attr->ecommunity) {
7076 char *mac = NULL;
7077 struct ecommunity_val *routermac = ecommunity_lookup(
7078 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7079 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7080 if (routermac)
7081 mac = ecom_mac2str((char *)routermac->val);
7082 if (mac) {
7083 vty_out(vty, "/%s", (char *)mac);
7084 XFREE(MTYPE_TMP, mac);
7085 }
7086 }
7087 vty_out(vty, "\n");
718e3744 7088 }
718e3744 7089
d62a17ae 7090}
718e3744 7091
d62a17ae 7092/* dampening route */
7093static void damp_route_vty_out(struct vty *vty, struct prefix *p,
7094 struct bgp_info *binfo, int display, safi_t safi,
9f049418 7095 bool use_json, json_object *json)
d62a17ae 7096{
7097 struct attr *attr;
7098 int len;
7099 char timebuf[BGP_UPTIME_LEN];
7100
7101 /* short status lead text */
7102 route_vty_short_status_out(vty, binfo, json);
7103
7104 /* print prefix and mask */
7105 if (!use_json) {
7106 if (!display)
9c92b5f7 7107 route_vty_out_route(p, vty, NULL);
d62a17ae 7108 else
7109 vty_out(vty, "%*s", 17, " ");
7110 }
7111
7112 len = vty_out(vty, "%s", binfo->peer->host);
7113 len = 17 - len;
7114 if (len < 1) {
7115 if (!use_json)
7116 vty_out(vty, "\n%*s", 34, " ");
7117 } else {
7118 if (use_json)
7119 json_object_int_add(json, "peerHost", len);
7120 else
7121 vty_out(vty, "%*s", len, " ");
7122 }
7123
7124 if (use_json)
7125 bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN,
7126 use_json, json);
7127 else
996c9314
LB
7128 vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7129 BGP_UPTIME_LEN,
7130 use_json, json));
d62a17ae 7131
7132 /* Print attribute */
7133 attr = binfo->attr;
7134 if (attr) {
7135 /* Print aspath */
7136 if (attr->aspath) {
7137 if (use_json)
7138 json_object_string_add(json, "asPath",
7139 attr->aspath->str);
7140 else
7141 aspath_print_vty(vty, "%s", attr->aspath, " ");
7142 }
7143
7144 /* Print origin */
7145 if (use_json)
7146 json_object_string_add(json, "origin",
7147 bgp_origin_str[attr->origin]);
7148 else
7149 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7150 }
7151 if (!use_json)
7152 vty_out(vty, "\n");
7153}
718e3744 7154
d62a17ae 7155/* flap route */
7156static void flap_route_vty_out(struct vty *vty, struct prefix *p,
7157 struct bgp_info *binfo, int display, safi_t safi,
9f049418 7158 bool use_json, json_object *json)
784d3a42 7159{
d62a17ae 7160 struct attr *attr;
7161 struct bgp_damp_info *bdi;
7162 char timebuf[BGP_UPTIME_LEN];
7163 int len;
784d3a42 7164
d62a17ae 7165 if (!binfo->extra)
7166 return;
784d3a42 7167
d62a17ae 7168 bdi = binfo->extra->damp_info;
784d3a42 7169
d62a17ae 7170 /* short status lead text */
7171 route_vty_short_status_out(vty, binfo, json);
784d3a42 7172
d62a17ae 7173 /* print prefix and mask */
7174 if (!use_json) {
7175 if (!display)
9c92b5f7 7176 route_vty_out_route(p, vty, NULL);
d62a17ae 7177 else
7178 vty_out(vty, "%*s", 17, " ");
7179 }
784d3a42 7180
d62a17ae 7181 len = vty_out(vty, "%s", binfo->peer->host);
7182 len = 16 - len;
7183 if (len < 1) {
7184 if (!use_json)
7185 vty_out(vty, "\n%*s", 33, " ");
7186 } else {
7187 if (use_json)
7188 json_object_int_add(json, "peerHost", len);
7189 else
7190 vty_out(vty, "%*s", len, " ");
7191 }
784d3a42 7192
d62a17ae 7193 len = vty_out(vty, "%d", bdi->flap);
7194 len = 5 - len;
7195 if (len < 1) {
7196 if (!use_json)
7197 vty_out(vty, " ");
7198 } else {
7199 if (use_json)
7200 json_object_int_add(json, "bdiFlap", len);
7201 else
7202 vty_out(vty, "%*s", len, " ");
7203 }
7204
7205 if (use_json)
7206 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7207 json);
7208 else
996c9314
LB
7209 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7210 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7211
7212 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
7213 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7214 if (use_json)
7215 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7216 BGP_UPTIME_LEN, use_json, json);
7217 else
7218 vty_out(vty, "%s ",
7219 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7220 BGP_UPTIME_LEN,
7221 use_json, json));
7222 } else {
7223 if (!use_json)
7224 vty_out(vty, "%*s ", 8, " ");
7225 }
7226
7227 /* Print attribute */
7228 attr = binfo->attr;
7229 if (attr) {
7230 /* Print aspath */
7231 if (attr->aspath) {
7232 if (use_json)
7233 json_object_string_add(json, "asPath",
7234 attr->aspath->str);
7235 else
7236 aspath_print_vty(vty, "%s", attr->aspath, " ");
7237 }
7238
7239 /* Print origin */
7240 if (use_json)
7241 json_object_string_add(json, "origin",
7242 bgp_origin_str[attr->origin]);
7243 else
7244 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7245 }
7246 if (!use_json)
7247 vty_out(vty, "\n");
7248}
7249
7250static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7251 int *first, const char *header,
7252 json_object *json_adv_to)
7253{
7254 char buf1[INET6_ADDRSTRLEN];
7255 json_object *json_peer = NULL;
7256
7257 if (json_adv_to) {
7258 /* 'advertised-to' is a dictionary of peers we have advertised
7259 * this
7260 * prefix too. The key is the peer's IP or swpX, the value is
7261 * the
7262 * hostname if we know it and "" if not.
7263 */
7264 json_peer = json_object_new_object();
7265
7266 if (peer->hostname)
7267 json_object_string_add(json_peer, "hostname",
7268 peer->hostname);
7269
7270 if (peer->conf_if)
7271 json_object_object_add(json_adv_to, peer->conf_if,
7272 json_peer);
7273 else
7274 json_object_object_add(
7275 json_adv_to,
7276 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7277 json_peer);
7278 } else {
7279 if (*first) {
7280 vty_out(vty, "%s", header);
7281 *first = 0;
7282 }
7283
7284 if (peer->hostname
7285 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7286 if (peer->conf_if)
7287 vty_out(vty, " %s(%s)", peer->hostname,
7288 peer->conf_if);
7289 else
7290 vty_out(vty, " %s(%s)", peer->hostname,
7291 sockunion2str(&peer->su, buf1,
7292 SU_ADDRSTRLEN));
7293 } else {
7294 if (peer->conf_if)
7295 vty_out(vty, " %s", peer->conf_if);
7296 else
7297 vty_out(vty, " %s",
7298 sockunion2str(&peer->su, buf1,
7299 SU_ADDRSTRLEN));
7300 }
7301 }
784d3a42
PG
7302}
7303
d62a17ae 7304void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
7305 struct bgp_info *binfo, afi_t afi, safi_t safi,
7306 json_object *json_paths)
7307{
7308 char buf[INET6_ADDRSTRLEN];
7309 char buf1[BUFSIZ];
d62a17ae 7310 char buf2[EVPN_ROUTE_STRLEN];
d62a17ae 7311 struct attr *attr;
7312 int sockunion_vty_out(struct vty *, union sockunion *);
7313 time_t tbuf;
7314 json_object *json_bestpath = NULL;
7315 json_object *json_cluster_list = NULL;
7316 json_object *json_cluster_list_list = NULL;
7317 json_object *json_ext_community = NULL;
7318 json_object *json_last_update = NULL;
7fd077aa 7319 json_object *json_pmsi = NULL;
d62a17ae 7320 json_object *json_nexthop_global = NULL;
7321 json_object *json_nexthop_ll = NULL;
7322 json_object *json_nexthops = NULL;
7323 json_object *json_path = NULL;
7324 json_object *json_peer = NULL;
7325 json_object *json_string = NULL;
7326 json_object *json_adv_to = NULL;
7327 int first = 0;
7328 struct listnode *node, *nnode;
7329 struct peer *peer;
7330 int addpath_capable;
7331 int has_adj;
7332 unsigned int first_as;
9df8b37c
PZ
7333 bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
7334 ? true
7335 : false;
d62a17ae 7336
7337 if (json_paths) {
7338 json_path = json_object_new_object();
7339 json_peer = json_object_new_object();
7340 json_nexthop_global = json_object_new_object();
7341 }
7342
d62a17ae 7343 if (!json_paths && safi == SAFI_EVPN) {
b57ba6d2 7344 char tag_buf[30];
d62a17ae 7345
7346 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7347 vty_out(vty, " Route %s", buf2);
7348 tag_buf[0] = '\0';
b57ba6d2
MK
7349 if (binfo->extra && binfo->extra->num_labels) {
7350 bgp_evpn_label2str(binfo->extra->label,
a4d82a8a
PZ
7351 binfo->extra->num_labels, tag_buf,
7352 sizeof(tag_buf));
d62a17ae 7353 vty_out(vty, " VNI %s", tag_buf);
7354 }
7355 vty_out(vty, "\n");
7356 if (binfo->extra && binfo->extra->parent) {
7357 struct bgp_info *parent_ri;
7358 struct bgp_node *rn, *prn;
7359
7360 parent_ri = (struct bgp_info *)binfo->extra->parent;
7361 rn = parent_ri->net;
7362 if (rn && rn->prn) {
7363 prn = rn->prn;
7364 vty_out(vty, " Imported from %s:%s\n",
7365 prefix_rd2str(
7366 (struct prefix_rd *)&prn->p,
06b9f471 7367 buf1, sizeof(buf1)),
d62a17ae 7368 buf2);
7369 }
7370 }
7371 }
d62a17ae 7372
7373 attr = binfo->attr;
7374
7375 if (attr) {
7376 /* Line1 display AS-path, Aggregator */
7377 if (attr->aspath) {
7378 if (json_paths) {
68e1a55b
DS
7379 if (!attr->aspath->json)
7380 aspath_str_update(attr->aspath, true);
d62a17ae 7381 json_object_lock(attr->aspath->json);
7382 json_object_object_add(json_path, "aspath",
7383 attr->aspath->json);
7384 } else {
7385 if (attr->aspath->segments)
7386 aspath_print_vty(vty, " %s",
7387 attr->aspath, "");
7388 else
7389 vty_out(vty, " Local");
7390 }
7391 }
7392
7393 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) {
7394 if (json_paths)
7395 json_object_boolean_true_add(json_path,
7396 "removed");
7397 else
7398 vty_out(vty, ", (removed)");
7399 }
7400
7401 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) {
7402 if (json_paths)
7403 json_object_boolean_true_add(json_path,
7404 "stale");
7405 else
7406 vty_out(vty, ", (stale)");
7407 }
7408
7409 if (CHECK_FLAG(attr->flag,
7410 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7411 if (json_paths) {
7412 json_object_int_add(json_path, "aggregatorAs",
7413 attr->aggregator_as);
7414 json_object_string_add(
7415 json_path, "aggregatorId",
7416 inet_ntoa(attr->aggregator_addr));
7417 } else {
7418 vty_out(vty, ", (aggregated by %u %s)",
7419 attr->aggregator_as,
7420 inet_ntoa(attr->aggregator_addr));
7421 }
7422 }
7423
7424 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7425 PEER_FLAG_REFLECTOR_CLIENT)) {
7426 if (json_paths)
7427 json_object_boolean_true_add(
7428 json_path, "rxedFromRrClient");
7429 else
7430 vty_out(vty, ", (Received from a RR-client)");
7431 }
7432
7433 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7434 PEER_FLAG_RSERVER_CLIENT)) {
7435 if (json_paths)
7436 json_object_boolean_true_add(
7437 json_path, "rxedFromRsClient");
7438 else
7439 vty_out(vty, ", (Received from a RS-client)");
7440 }
7441
7442 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7443 if (json_paths)
7444 json_object_boolean_true_add(
7445 json_path, "dampeningHistoryEntry");
7446 else
7447 vty_out(vty, ", (history entry)");
7448 } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
7449 if (json_paths)
7450 json_object_boolean_true_add(
7451 json_path, "dampeningSuppressed");
7452 else
7453 vty_out(vty, ", (suppressed due to dampening)");
7454 }
7455
7456 if (!json_paths)
7457 vty_out(vty, "\n");
7458
7459 /* Line2 display Next-hop, Neighbor, Router-id */
7460 /* Display the nexthop */
a4d82a8a
PZ
7461 if ((p->family == AF_INET || p->family == AF_ETHERNET
7462 || p->family == AF_EVPN)
d62a17ae 7463 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7464 || safi == SAFI_EVPN
7465 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7466 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7467 || safi == SAFI_EVPN) {
7468 if (json_paths)
7469 json_object_string_add(
7470 json_nexthop_global, "ip",
7471 inet_ntoa(
7472 attr->mp_nexthop_global_in));
7473 else
7474 vty_out(vty, " %s",
7475 inet_ntoa(
7476 attr->mp_nexthop_global_in));
7477 } else {
7478 if (json_paths)
7479 json_object_string_add(
7480 json_nexthop_global, "ip",
7481 inet_ntoa(attr->nexthop));
7482 else
7483 vty_out(vty, " %s",
7484 inet_ntoa(attr->nexthop));
7485 }
7486
7487 if (json_paths)
7488 json_object_string_add(json_nexthop_global,
7489 "afi", "ipv4");
7490 } else {
7491 if (json_paths) {
7492 json_object_string_add(
7493 json_nexthop_global, "ip",
7494 inet_ntop(AF_INET6,
7495 &attr->mp_nexthop_global, buf,
7496 INET6_ADDRSTRLEN));
7497 json_object_string_add(json_nexthop_global,
7498 "afi", "ipv6");
7499 json_object_string_add(json_nexthop_global,
7500 "scope", "global");
7501 } else {
7502 vty_out(vty, " %s",
7503 inet_ntop(AF_INET6,
7504 &attr->mp_nexthop_global, buf,
7505 INET6_ADDRSTRLEN));
7506 }
7507 }
7508
7509 /* Display the IGP cost or 'inaccessible' */
7510 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7511 if (json_paths)
7512 json_object_boolean_false_add(
7513 json_nexthop_global, "accessible");
7514 else
7515 vty_out(vty, " (inaccessible)");
7516 } else {
7517 if (binfo->extra && binfo->extra->igpmetric) {
7518 if (json_paths)
7519 json_object_int_add(
7520 json_nexthop_global, "metric",
7521 binfo->extra->igpmetric);
7522 else
7523 vty_out(vty, " (metric %u)",
7524 binfo->extra->igpmetric);
7525 }
7526
7527 /* IGP cost is 0, display this only for json */
7528 else {
7529 if (json_paths)
7530 json_object_int_add(json_nexthop_global,
7531 "metric", 0);
7532 }
7533
7534 if (json_paths)
7535 json_object_boolean_true_add(
7536 json_nexthop_global, "accessible");
7537 }
7538
7539 /* Display peer "from" output */
7540 /* This path was originated locally */
7541 if (binfo->peer == bgp->peer_self) {
7542
7543 if (safi == SAFI_EVPN
7544 || (p->family == AF_INET
7545 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7546 if (json_paths)
7547 json_object_string_add(
7548 json_peer, "peerId", "0.0.0.0");
7549 else
7550 vty_out(vty, " from 0.0.0.0 ");
7551 } else {
7552 if (json_paths)
7553 json_object_string_add(json_peer,
7554 "peerId", "::");
7555 else
7556 vty_out(vty, " from :: ");
7557 }
7558
7559 if (json_paths)
7560 json_object_string_add(
7561 json_peer, "routerId",
7562 inet_ntoa(bgp->router_id));
7563 else
7564 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7565 }
7566
7567 /* We RXed this path from one of our peers */
7568 else {
7569
7570 if (json_paths) {
7571 json_object_string_add(
7572 json_peer, "peerId",
7573 sockunion2str(&binfo->peer->su, buf,
7574 SU_ADDRSTRLEN));
7575 json_object_string_add(
7576 json_peer, "routerId",
7577 inet_ntop(AF_INET,
7578 &binfo->peer->remote_id, buf1,
06b9f471 7579 sizeof(buf1)));
d62a17ae 7580
7581 if (binfo->peer->hostname)
7582 json_object_string_add(
7583 json_peer, "hostname",
7584 binfo->peer->hostname);
7585
7586 if (binfo->peer->domainname)
7587 json_object_string_add(
7588 json_peer, "domainname",
7589 binfo->peer->domainname);
7590
7591 if (binfo->peer->conf_if)
7592 json_object_string_add(
7593 json_peer, "interface",
7594 binfo->peer->conf_if);
7595 } else {
7596 if (binfo->peer->conf_if) {
7597 if (binfo->peer->hostname
7598 && bgp_flag_check(
7599 binfo->peer->bgp,
7600 BGP_FLAG_SHOW_HOSTNAME))
7601 vty_out(vty, " from %s(%s)",
7602 binfo->peer->hostname,
7603 binfo->peer->conf_if);
7604 else
7605 vty_out(vty, " from %s",
7606 binfo->peer->conf_if);
7607 } else {
7608 if (binfo->peer->hostname
7609 && bgp_flag_check(
7610 binfo->peer->bgp,
7611 BGP_FLAG_SHOW_HOSTNAME))
7612 vty_out(vty, " from %s(%s)",
7613 binfo->peer->hostname,
7614 binfo->peer->host);
7615 else
7616 vty_out(vty, " from %s",
7617 sockunion2str(
7618 &binfo->peer
7619 ->su,
7620 buf,
7621 SU_ADDRSTRLEN));
7622 }
7623
7624 if (attr->flag
7625 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7626 vty_out(vty, " (%s)",
7627 inet_ntoa(attr->originator_id));
7628 else
7629 vty_out(vty, " (%s)",
7630 inet_ntop(
7631 AF_INET,
7632 &binfo->peer->remote_id,
06b9f471 7633 buf1, sizeof(buf1)));
d62a17ae 7634 }
7635 }
7636
9df8b37c
PZ
7637 /*
7638 * Note when vrfid of nexthop is different from that of prefix
7639 */
7640 if (binfo->extra && binfo->extra->bgp_orig) {
7641 vrf_id_t nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
7642
7643 if (json_paths) {
7644 const char *vn;
7645
7646 if (binfo->extra->bgp_orig->inst_type ==
7647 BGP_INSTANCE_TYPE_DEFAULT)
7648
7649 vn = "Default";
7650 else
7651 vn = binfo->extra->bgp_orig->name;
7652
7653 json_object_string_add(json_path, "nhVrfName",
7654 vn);
7655
7656 if (nexthop_vrfid == VRF_UNKNOWN) {
7657 json_object_int_add(json_path,
7658 "nhVrfId", -1);
7659 } else {
7660 json_object_int_add(json_path,
7661 "nhVrfId", (int)nexthop_vrfid);
7662 }
7663 } else {
7664 if (nexthop_vrfid == VRF_UNKNOWN)
7665 vty_out(vty, " vrf ?");
7666 else
7667 vty_out(vty, " vrf %u", nexthop_vrfid);
7668 }
7669 }
7670
7671 if (nexthop_self) {
7672 if (json_paths) {
7673 json_object_boolean_true_add(json_path,
7674 "announceNexthopSelf");
7675 } else {
7676 vty_out(vty, " announce-nh-self");
7677 }
7678 }
7679
d62a17ae 7680 if (!json_paths)
7681 vty_out(vty, "\n");
7682
7683 /* display the link-local nexthop */
7684 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7685 if (json_paths) {
7686 json_nexthop_ll = json_object_new_object();
7687 json_object_string_add(
7688 json_nexthop_ll, "ip",
7689 inet_ntop(AF_INET6,
7690 &attr->mp_nexthop_local, buf,
7691 INET6_ADDRSTRLEN));
7692 json_object_string_add(json_nexthop_ll, "afi",
7693 "ipv6");
7694 json_object_string_add(json_nexthop_ll, "scope",
7695 "link-local");
7696
7697 json_object_boolean_true_add(json_nexthop_ll,
7698 "accessible");
7699
7700 if (!attr->mp_nexthop_prefer_global)
7701 json_object_boolean_true_add(
7702 json_nexthop_ll, "used");
7703 else
7704 json_object_boolean_true_add(
7705 json_nexthop_global, "used");
7706 } else {
7707 vty_out(vty, " (%s) %s\n",
7708 inet_ntop(AF_INET6,
7709 &attr->mp_nexthop_local, buf,
7710 INET6_ADDRSTRLEN),
7711 attr->mp_nexthop_prefer_global
7712 ? "(prefer-global)"
7713 : "(used)");
7714 }
7715 }
7716 /* If we do not have a link-local nexthop then we must flag the
7717 global as "used" */
7718 else {
7719 if (json_paths)
7720 json_object_boolean_true_add(
7721 json_nexthop_global, "used");
7722 }
718e3744 7723
d62a17ae 7724 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7725 * Int/Ext/Local, Atomic, best */
7726 if (json_paths)
7727 json_object_string_add(
7728 json_path, "origin",
7729 bgp_origin_long_str[attr->origin]);
7730 else
7731 vty_out(vty, " Origin %s",
7732 bgp_origin_long_str[attr->origin]);
7733
7734 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
7735 if (json_paths)
7736 json_object_int_add(json_path, "med",
7737 attr->med);
7738 else
7739 vty_out(vty, ", metric %u", attr->med);
7740 }
718e3744 7741
d62a17ae 7742 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7743 if (json_paths)
7744 json_object_int_add(json_path, "localpref",
7745 attr->local_pref);
7746 else
7747 vty_out(vty, ", localpref %u",
7748 attr->local_pref);
d62a17ae 7749 }
718e3744 7750
d62a17ae 7751 if (attr->weight != 0) {
7752 if (json_paths)
7753 json_object_int_add(json_path, "weight",
7754 attr->weight);
7755 else
7756 vty_out(vty, ", weight %u", attr->weight);
7757 }
718e3744 7758
d62a17ae 7759 if (attr->tag != 0) {
7760 if (json_paths)
7761 json_object_int_add(json_path, "tag",
7762 attr->tag);
7763 else
7764 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7765 attr->tag);
7766 }
718e3744 7767
d62a17ae 7768 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7769 if (json_paths)
7770 json_object_boolean_false_add(json_path,
7771 "valid");
7772 else
7773 vty_out(vty, ", invalid");
7774 } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7775 if (json_paths)
7776 json_object_boolean_true_add(json_path,
7777 "valid");
7778 else
7779 vty_out(vty, ", valid");
7780 }
718e3744 7781
d62a17ae 7782 if (binfo->peer != bgp->peer_self) {
7783 if (binfo->peer->as == binfo->peer->local_as) {
7784 if (CHECK_FLAG(bgp->config,
7785 BGP_CONFIG_CONFEDERATION)) {
7786 if (json_paths)
7787 json_object_string_add(
7788 json_peer, "type",
7789 "confed-internal");
7790 else
7791 vty_out(vty,
7792 ", confed-internal");
7793 } else {
7794 if (json_paths)
7795 json_object_string_add(
7796 json_peer, "type",
7797 "internal");
7798 else
7799 vty_out(vty, ", internal");
7800 }
7801 } else {
7802 if (bgp_confederation_peers_check(
7803 bgp, binfo->peer->as)) {
7804 if (json_paths)
7805 json_object_string_add(
7806 json_peer, "type",
7807 "confed-external");
7808 else
7809 vty_out(vty,
7810 ", confed-external");
7811 } else {
7812 if (json_paths)
7813 json_object_string_add(
7814 json_peer, "type",
7815 "external");
7816 else
7817 vty_out(vty, ", external");
7818 }
7819 }
7820 } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) {
7821 if (json_paths) {
7822 json_object_boolean_true_add(json_path,
7823 "aggregated");
7824 json_object_boolean_true_add(json_path,
7825 "local");
7826 } else {
7827 vty_out(vty, ", aggregated, local");
7828 }
7829 } else if (binfo->type != ZEBRA_ROUTE_BGP) {
7830 if (json_paths)
7831 json_object_boolean_true_add(json_path,
7832 "sourced");
7833 else
7834 vty_out(vty, ", sourced");
7835 } else {
7836 if (json_paths) {
7837 json_object_boolean_true_add(json_path,
7838 "sourced");
7839 json_object_boolean_true_add(json_path,
7840 "local");
7841 } else {
7842 vty_out(vty, ", sourced, local");
7843 }
7844 }
718e3744 7845
d62a17ae 7846 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
7847 if (json_paths)
7848 json_object_boolean_true_add(json_path,
7849 "atomicAggregate");
7850 else
7851 vty_out(vty, ", atomic-aggregate");
7852 }
718e3744 7853
d62a17ae 7854 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)
7855 || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)
7856 && bgp_info_mpath_count(binfo))) {
7857 if (json_paths)
7858 json_object_boolean_true_add(json_path,
7859 "multipath");
7860 else
7861 vty_out(vty, ", multipath");
7862 }
856ca177 7863
d62a17ae 7864 // Mark the bestpath(s)
7865 if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) {
7866 first_as = aspath_get_first_as(attr->aspath);
7867
7868 if (json_paths) {
7869 if (!json_bestpath)
7870 json_bestpath =
7871 json_object_new_object();
7872 json_object_int_add(json_bestpath,
7873 "bestpathFromAs", first_as);
7874 } else {
7875 if (first_as)
fb2b0934 7876 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 7877 first_as);
7878 else
7879 vty_out(vty,
7880 ", bestpath-from-AS Local");
7881 }
7882 }
718e3744 7883
d62a17ae 7884 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) {
7885 if (json_paths) {
7886 if (!json_bestpath)
7887 json_bestpath =
7888 json_object_new_object();
7889 json_object_boolean_true_add(json_bestpath,
7890 "overall");
7891 } else
7892 vty_out(vty, ", best");
7893 }
718e3744 7894
d62a17ae 7895 if (json_bestpath)
7896 json_object_object_add(json_path, "bestpath",
7897 json_bestpath);
7898
7899 if (!json_paths)
7900 vty_out(vty, "\n");
7901
7902 /* Line 4 display Community */
7903 if (attr->community) {
7904 if (json_paths) {
a69ea8ae 7905 if (!attr->community->json)
a4d82a8a 7906 community_str(attr->community, true);
d62a17ae 7907 json_object_lock(attr->community->json);
7908 json_object_object_add(json_path, "community",
7909 attr->community->json);
7910 } else {
7911 vty_out(vty, " Community: %s\n",
7912 attr->community->str);
7913 }
7914 }
718e3744 7915
d62a17ae 7916 /* Line 5 display Extended-community */
7917 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7918 if (json_paths) {
7919 json_ext_community = json_object_new_object();
7920 json_object_string_add(json_ext_community,
7921 "string",
7922 attr->ecommunity->str);
7923 json_object_object_add(json_path,
7924 "extendedCommunity",
7925 json_ext_community);
7926 } else {
7927 vty_out(vty, " Extended Community: %s\n",
7928 attr->ecommunity->str);
7929 }
7930 }
adbac85e 7931
d62a17ae 7932 /* Line 6 display Large community */
b96879c0
DS
7933 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
7934 if (json_paths) {
8d9b8ed9
PM
7935 if (!attr->lcommunity->json)
7936 lcommunity_str(attr->lcommunity, true);
7937 json_object_lock(attr->lcommunity->json);
b96879c0
DS
7938 json_object_object_add(json_path,
7939 "largeCommunity",
8d9b8ed9 7940 attr->lcommunity->json);
b96879c0
DS
7941 } else {
7942 vty_out(vty, " Large Community: %s\n",
7943 attr->lcommunity->str);
7944 }
7945 }
d62a17ae 7946
7947 /* Line 7 display Originator, Cluster-id */
7948 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7949 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
7950 if (attr->flag
7951 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
7952 if (json_paths)
7953 json_object_string_add(
7954 json_path, "originatorId",
7955 inet_ntoa(attr->originator_id));
7956 else
7957 vty_out(vty, " Originator: %s",
7958 inet_ntoa(attr->originator_id));
7959 }
7960
7961 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
7962 int i;
7963
7964 if (json_paths) {
7965 json_cluster_list =
7966 json_object_new_object();
7967 json_cluster_list_list =
7968 json_object_new_array();
7969
7970 for (i = 0;
7971 i < attr->cluster->length / 4;
7972 i++) {
7973 json_string = json_object_new_string(
7974 inet_ntoa(
7975 attr->cluster->list
7976 [i]));
7977 json_object_array_add(
7978 json_cluster_list_list,
7979 json_string);
7980 }
7981
7982 /* struct cluster_list does not have
7983 "str" variable like
7984 * aspath and community do. Add this
7985 someday if someone
7986 * asks for it.
7987 json_object_string_add(json_cluster_list,
7988 "string", attr->cluster->str);
7989 */
7990 json_object_object_add(
7991 json_cluster_list, "list",
7992 json_cluster_list_list);
7993 json_object_object_add(
7994 json_path, "clusterList",
7995 json_cluster_list);
7996 } else {
7997 vty_out(vty, ", Cluster list: ");
7998
7999 for (i = 0;
8000 i < attr->cluster->length / 4;
8001 i++) {
8002 vty_out(vty, "%s ",
8003 inet_ntoa(
8004 attr->cluster->list
8005 [i]));
8006 }
8007 }
8008 }
8009
8010 if (!json_paths)
8011 vty_out(vty, "\n");
8012 }
adbac85e 8013
d62a17ae 8014 if (binfo->extra && binfo->extra->damp_info)
8015 bgp_damp_info_vty(vty, binfo, json_path);
8016
6a527b2f 8017 /* Remote Label */
b57ba6d2 8018 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0])
6a527b2f 8019 && safi != SAFI_EVPN) {
a4d82a8a
PZ
8020 mpls_label_t label =
8021 label_pton(&binfo->extra->label[0]);
d62a17ae 8022 if (json_paths)
8023 json_object_int_add(json_path, "remoteLabel",
8024 label);
8025 else
8026 vty_out(vty, " Remote label: %d\n", label);
8027 }
b05a1c8b 8028
d62a17ae 8029 /* Label Index */
8030 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8031 if (json_paths)
8032 json_object_int_add(json_path, "labelIndex",
8033 attr->label_index);
8034 else
8035 vty_out(vty, " Label Index: %d\n",
8036 attr->label_index);
8037 }
520d5d76 8038
d62a17ae 8039 /* Line 8 display Addpath IDs */
8040 if (binfo->addpath_rx_id || binfo->addpath_tx_id) {
8041 if (json_paths) {
8042 json_object_int_add(json_path, "addpathRxId",
8043 binfo->addpath_rx_id);
8044 json_object_int_add(json_path, "addpathTxId",
8045 binfo->addpath_tx_id);
8046 } else {
8047 vty_out(vty, " AddPath ID: RX %u, TX %u\n",
8048 binfo->addpath_rx_id,
8049 binfo->addpath_tx_id);
8050 }
8051 }
718e3744 8052
d62a17ae 8053 /* If we used addpath to TX a non-bestpath we need to display
8054 * "Advertised to" on a path-by-path basis */
8055 if (bgp->addpath_tx_used[afi][safi]) {
8056 first = 1;
8057
8058 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8059 addpath_capable =
8060 bgp_addpath_encode_tx(peer, afi, safi);
8061 has_adj = bgp_adj_out_lookup(
8062 peer, binfo->net, binfo->addpath_tx_id);
8063
8064 if ((addpath_capable && has_adj)
8065 || (!addpath_capable && has_adj
8066 && CHECK_FLAG(binfo->flags,
8067 BGP_INFO_SELECTED))) {
8068 if (json_path && !json_adv_to)
8069 json_adv_to =
8070 json_object_new_object();
8071
8072 route_vty_out_advertised_to(
8073 vty, peer, &first,
8074 " Advertised to:",
8075 json_adv_to);
8076 }
8077 }
8078
8079 if (json_path) {
8080 if (json_adv_to) {
8081 json_object_object_add(json_path,
8082 "advertisedTo",
8083 json_adv_to);
8084 }
8085 } else {
8086 if (!first) {
8087 vty_out(vty, "\n");
8088 }
8089 }
8090 }
b05a1c8b 8091
d62a17ae 8092 /* Line 9 display Uptime */
8093 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
8094 if (json_paths) {
8095 json_last_update = json_object_new_object();
8096 json_object_int_add(json_last_update, "epoch", tbuf);
8097 json_object_string_add(json_last_update, "string",
8098 ctime(&tbuf));
8099 json_object_object_add(json_path, "lastUpdate",
8100 json_last_update);
8101 } else
8102 vty_out(vty, " Last update: %s", ctime(&tbuf));
7fd077aa 8103
8104 /* Line 10 display PMSI tunnel attribute, if present */
8105 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
b7d08f5a 8106 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
8107 attr->pmsi_tnl_type,
8108 PMSI_TNLTYPE_STR_DEFAULT);
8109
7fd077aa 8110 if (json_paths) {
8111 json_pmsi = json_object_new_object();
b7d08f5a 8112 json_object_string_add(json_pmsi,
8113 "tunnelType", str);
7fd077aa 8114 json_object_object_add(json_path, "pmsi",
8115 json_pmsi);
8116 } else
8117 vty_out(vty, " PMSI Tunnel Type: %s\n",
b7d08f5a 8118 str);
7fd077aa 8119 }
8120
d62a17ae 8121 }
f1aa5d8a 8122
d62a17ae 8123 /* We've constructed the json object for this path, add it to the json
8124 * array of paths
8125 */
8126 if (json_paths) {
8127 if (json_nexthop_global || json_nexthop_ll) {
8128 json_nexthops = json_object_new_array();
f1aa5d8a 8129
d62a17ae 8130 if (json_nexthop_global)
8131 json_object_array_add(json_nexthops,
8132 json_nexthop_global);
f1aa5d8a 8133
d62a17ae 8134 if (json_nexthop_ll)
8135 json_object_array_add(json_nexthops,
8136 json_nexthop_ll);
f1aa5d8a 8137
d62a17ae 8138 json_object_object_add(json_path, "nexthops",
8139 json_nexthops);
8140 }
8141
8142 json_object_object_add(json_path, "peer", json_peer);
8143 json_object_array_add(json_paths, json_path);
8144 } else
8145 vty_out(vty, "\n");
b366b518
BB
8146}
8147
96ade3ed 8148#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8149#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8150#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8151
d62a17ae 8152static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8153 const char *prefix_list_str, afi_t afi,
8154 safi_t safi, enum bgp_show_type type);
8155static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8156 const char *filter, afi_t afi, safi_t safi,
8157 enum bgp_show_type type);
8158static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8159 const char *rmap_str, afi_t afi, safi_t safi,
8160 enum bgp_show_type type);
8161static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8162 const char *com, int exact, afi_t afi,
8163 safi_t safi);
8164static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8165 const char *prefix, afi_t afi, safi_t safi,
8166 enum bgp_show_type type);
a4d82a8a
PZ
8167static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
8168 afi_t afi, safi_t safi, enum bgp_show_type type);
7f323236
DW
8169static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8170 const char *comstr, int exact, afi_t afi,
9f049418 8171 safi_t safi, bool use_json);
d62a17ae 8172
1ae44dfc
LB
8173
8174static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8175 struct bgp_table *table, enum bgp_show_type type,
9f049418 8176 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
8177 int is_last, unsigned long *output_cum,
8178 unsigned long *total_cum,
9386b588 8179 unsigned long *json_header_depth)
d62a17ae 8180{
8181 struct bgp_info *ri;
8182 struct bgp_node *rn;
8183 int header = 1;
8184 int display;
1ae44dfc
LB
8185 unsigned long output_count = 0;
8186 unsigned long total_count = 0;
d62a17ae 8187 struct prefix *p;
8188 char buf[BUFSIZ];
8189 char buf2[BUFSIZ];
8190 json_object *json_paths = NULL;
8191 int first = 1;
8192
1ae44dfc
LB
8193 if (output_cum && *output_cum != 0)
8194 header = 0;
8195
9386b588 8196 if (use_json && !*json_header_depth) {
d62a17ae 8197 vty_out(vty,
66f80d74
DS
8198 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8199 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
a8bf7d9c 8200 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
d62a17ae 8201 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
8202 : bgp->name,
8203 table->version, inet_ntoa(bgp->router_id));
9386b588
PZ
8204 *json_header_depth = 2;
8205 if (rd) {
445c2480 8206 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
8207 ++*json_header_depth;
8208 }
d62a17ae 8209 }
718e3744 8210
445c2480
DS
8211 if (use_json && rd) {
8212 vty_out(vty, " \"%s\" : { ", rd);
8213 }
8214
d62a17ae 8215 /* Start processing of routes. */
98ce9a06
DS
8216 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
8217 if (rn->info == NULL)
8218 continue;
d62a17ae 8219
98ce9a06 8220 display = 0;
98ce9a06
DS
8221 if (use_json)
8222 json_paths = json_object_new_array();
8223 else
8224 json_paths = NULL;
d62a17ae 8225
98ce9a06
DS
8226 for (ri = rn->info; ri; ri = ri->next) {
8227 total_count++;
8228 if (type == bgp_show_type_flap_statistics
8229 || type == bgp_show_type_flap_neighbor
8230 || type == bgp_show_type_dampend_paths
8231 || type == bgp_show_type_damp_neighbor) {
a4d82a8a 8232 if (!(ri->extra && ri->extra->damp_info))
98ce9a06
DS
8233 continue;
8234 }
8235 if (type == bgp_show_type_regexp) {
8236 regex_t *regex = output_arg;
d62a17ae 8237
98ce9a06
DS
8238 if (bgp_regexec(regex, ri->attr->aspath)
8239 == REG_NOMATCH)
8240 continue;
8241 }
8242 if (type == bgp_show_type_prefix_list) {
8243 struct prefix_list *plist = output_arg;
d62a17ae 8244
98ce9a06
DS
8245 if (prefix_list_apply(plist, &rn->p)
8246 != PREFIX_PERMIT)
8247 continue;
8248 }
8249 if (type == bgp_show_type_filter_list) {
8250 struct as_list *as_list = output_arg;
d62a17ae 8251
98ce9a06
DS
8252 if (as_list_apply(as_list, ri->attr->aspath)
8253 != AS_FILTER_PERMIT)
8254 continue;
8255 }
8256 if (type == bgp_show_type_route_map) {
8257 struct route_map *rmap = output_arg;
8258 struct bgp_info binfo;
8259 struct attr dummy_attr;
8260 int ret;
d62a17ae 8261
98ce9a06 8262 bgp_attr_dup(&dummy_attr, ri->attr);
d62a17ae 8263
98ce9a06
DS
8264 binfo.peer = ri->peer;
8265 binfo.attr = &dummy_attr;
d62a17ae 8266
a4d82a8a
PZ
8267 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
8268 &binfo);
98ce9a06
DS
8269 if (ret == RMAP_DENYMATCH)
8270 continue;
8271 }
8272 if (type == bgp_show_type_neighbor
8273 || type == bgp_show_type_flap_neighbor
8274 || type == bgp_show_type_damp_neighbor) {
8275 union sockunion *su = output_arg;
8276
8277 if (ri->peer == NULL
8278 || ri->peer->su_remote == NULL
a4d82a8a 8279 || !sockunion_same(ri->peer->su_remote, su))
98ce9a06
DS
8280 continue;
8281 }
8282 if (type == bgp_show_type_cidr_only) {
d7c0a89a 8283 uint32_t destination;
d62a17ae 8284
98ce9a06
DS
8285 destination = ntohl(rn->p.u.prefix4.s_addr);
8286 if (IN_CLASSC(destination)
8287 && rn->p.prefixlen == 24)
8288 continue;
8289 if (IN_CLASSB(destination)
8290 && rn->p.prefixlen == 16)
8291 continue;
8292 if (IN_CLASSA(destination)
8293 && rn->p.prefixlen == 8)
8294 continue;
8295 }
8296 if (type == bgp_show_type_prefix_longer) {
f7813c7c 8297 p = output_arg;
98ce9a06
DS
8298 if (!prefix_match(p, &rn->p))
8299 continue;
8300 }
8301 if (type == bgp_show_type_community_all) {
8302 if (!ri->attr->community)
8303 continue;
8304 }
8305 if (type == bgp_show_type_community) {
8306 struct community *com = output_arg;
d62a17ae 8307
98ce9a06
DS
8308 if (!ri->attr->community
8309 || !community_match(ri->attr->community,
8310 com))
8311 continue;
8312 }
8313 if (type == bgp_show_type_community_exact) {
8314 struct community *com = output_arg;
d62a17ae 8315
98ce9a06 8316 if (!ri->attr->community
a4d82a8a 8317 || !community_cmp(ri->attr->community, com))
98ce9a06
DS
8318 continue;
8319 }
8320 if (type == bgp_show_type_community_list) {
8321 struct community_list *list = output_arg;
d62a17ae 8322
a4d82a8a
PZ
8323 if (!community_list_match(ri->attr->community,
8324 list))
98ce9a06
DS
8325 continue;
8326 }
a4d82a8a 8327 if (type == bgp_show_type_community_list_exact) {
98ce9a06 8328 struct community_list *list = output_arg;
d62a17ae 8329
98ce9a06
DS
8330 if (!community_list_exact_match(
8331 ri->attr->community, list))
8332 continue;
8333 }
8334 if (type == bgp_show_type_lcommunity) {
8335 struct lcommunity *lcom = output_arg;
d62a17ae 8336
98ce9a06
DS
8337 if (!ri->attr->lcommunity
8338 || !lcommunity_match(ri->attr->lcommunity,
8339 lcom))
8340 continue;
8341 }
8342 if (type == bgp_show_type_lcommunity_list) {
8343 struct community_list *list = output_arg;
d62a17ae 8344
a4d82a8a
PZ
8345 if (!lcommunity_list_match(ri->attr->lcommunity,
8346 list))
98ce9a06
DS
8347 continue;
8348 }
8349 if (type == bgp_show_type_lcommunity_all) {
8350 if (!ri->attr->lcommunity)
8351 continue;
8352 }
8353 if (type == bgp_show_type_dampend_paths
8354 || type == bgp_show_type_damp_neighbor) {
8355 if (!CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)
8356 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
8357 continue;
8358 }
8359
8360 if (!use_json && header) {
996c9314 8361 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 8362 ", local router ID is %s, vrf id ",
98ce9a06
DS
8363 table->version,
8364 inet_ntoa(bgp->router_id));
9df8b37c
PZ
8365 if (bgp->vrf_id == VRF_UNKNOWN)
8366 vty_out(vty, "%s", VRFID_NONE_STR);
8367 else
8368 vty_out(vty, "%u", bgp->vrf_id);
8369 vty_out(vty, "\n");
98ce9a06 8370 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 8371 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 8372 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8373 if (type == bgp_show_type_dampend_paths
8374 || type == bgp_show_type_damp_neighbor)
98ce9a06 8375 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
8376 else if (type == bgp_show_type_flap_statistics
8377 || type == bgp_show_type_flap_neighbor)
98ce9a06 8378 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8379 else
98ce9a06
DS
8380 vty_out(vty, BGP_SHOW_HEADER);
8381 header = 0;
d62a17ae 8382 }
98ce9a06
DS
8383 if (rd != NULL && !display && !output_count) {
8384 if (!use_json)
8385 vty_out(vty,
8386 "Route Distinguisher: %s\n",
8387 rd);
d62a17ae 8388 }
98ce9a06
DS
8389 if (type == bgp_show_type_dampend_paths
8390 || type == bgp_show_type_damp_neighbor)
8391 damp_route_vty_out(vty, &rn->p, ri, display,
a4d82a8a 8392 safi, use_json, json_paths);
98ce9a06
DS
8393 else if (type == bgp_show_type_flap_statistics
8394 || type == bgp_show_type_flap_neighbor)
8395 flap_route_vty_out(vty, &rn->p, ri, display,
a4d82a8a 8396 safi, use_json, json_paths);
98ce9a06 8397 else
a4d82a8a
PZ
8398 route_vty_out(vty, &rn->p, ri, display, safi,
8399 json_paths);
98ce9a06 8400 display++;
d62a17ae 8401 }
8402
98ce9a06
DS
8403 if (display) {
8404 output_count++;
8405 if (!use_json)
8406 continue;
8407
8408 p = &rn->p;
8409 sprintf(buf2, "%s/%d",
a4d82a8a 8410 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
98ce9a06 8411 p->prefixlen);
8cc84563
DS
8412 if (first)
8413 vty_out(vty, "\"%s\": ", buf2);
8414 else
8415 vty_out(vty, ",\"%s\": ", buf2);
8416
98ce9a06 8417 vty_out(vty, "%s",
23b2a7ef 8418 json_object_to_json_string(json_paths));
98ce9a06 8419 json_object_free(json_paths);
449feb8e 8420 json_paths = NULL;
98ce9a06
DS
8421 first = 0;
8422 }
8423 }
8424
1ae44dfc
LB
8425 if (output_cum) {
8426 output_count += *output_cum;
8427 *output_cum = output_count;
8428 }
8429 if (total_cum) {
8430 total_count += *total_cum;
8431 *total_cum = total_count;
8432 }
d62a17ae 8433 if (use_json) {
9386b588 8434 if (rd) {
a4d82a8a 8435 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
8436 }
8437 if (is_last) {
a4d82a8a
PZ
8438 unsigned long i;
8439 for (i = 0; i < *json_header_depth; ++i)
8440 vty_out(vty, " } ");
9386b588 8441 }
d62a17ae 8442 } else {
1ae44dfc
LB
8443 if (is_last) {
8444 /* No route is displayed */
8445 if (output_count == 0) {
8446 if (type == bgp_show_type_normal)
8447 vty_out(vty,
8448 "No BGP prefixes displayed, %ld exist\n",
8449 total_count);
8450 } else
d62a17ae 8451 vty_out(vty,
1ae44dfc
LB
8452 "\nDisplayed %ld routes and %ld total paths\n",
8453 output_count, total_count);
8454 }
d62a17ae 8455 }
718e3744 8456
d62a17ae 8457 return CMD_SUCCESS;
718e3744 8458}
8459
1ae44dfc
LB
8460int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8461 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 8462 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
8463{
8464 struct bgp_node *rn, *next;
8465 unsigned long output_cum = 0;
8466 unsigned long total_cum = 0;
9386b588 8467 unsigned long json_header_depth = 0;
0136788c
LB
8468 bool show_msg;
8469
8470 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
8471
8472 for (rn = bgp_table_top(table); rn; rn = next) {
8473 next = bgp_route_next(rn);
8474 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8475 continue;
8476 if (rn->info != NULL) {
8477 struct prefix_rd prd;
06b9f471 8478 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8479
8480 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8481 prefix_rd2str(&prd, rd, sizeof(rd));
1ae44dfc 8482 bgp_show_table(vty, bgp, safi, rn->info, type,
a4d82a8a 8483 output_arg, use_json, rd, next == NULL,
9386b588
PZ
8484 &output_cum, &total_cum,
8485 &json_header_depth);
0136788c
LB
8486 if (next == NULL)
8487 show_msg = false;
1ae44dfc
LB
8488 }
8489 }
0136788c
LB
8490 if (show_msg) {
8491 if (output_cum == 0)
8492 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
8493 total_cum);
8494 else
8495 vty_out(vty,
8496 "\nDisplayed %ld routes and %ld total paths\n",
8497 output_cum, total_cum);
8498 }
1ae44dfc
LB
8499 return CMD_SUCCESS;
8500}
d62a17ae 8501static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 8502 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 8503{
d62a17ae 8504 struct bgp_table *table;
9386b588 8505 unsigned long json_header_depth = 0;
fee0f4c6 8506
d62a17ae 8507 if (bgp == NULL) {
8508 bgp = bgp_get_default();
8509 }
fee0f4c6 8510
d62a17ae 8511 if (bgp == NULL) {
8512 if (!use_json)
8513 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8514 else
8515 vty_out(vty, "{}\n");
d62a17ae 8516 return CMD_WARNING;
8517 }
4dd6177e 8518
1ae44dfc 8519 table = bgp->rib[afi][safi];
d62a17ae 8520 /* use MPLS and ENCAP specific shows until they are merged */
8521 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
8522 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
8523 output_arg, use_json);
d62a17ae 8524 }
dba3c1d3
PG
8525
8526 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
8527 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
8528 output_arg, use_json,
8529 1, NULL, NULL);
8530 }
d62a17ae 8531 /* labeled-unicast routes live in the unicast table */
8532 else if (safi == SAFI_LABELED_UNICAST)
8533 safi = SAFI_UNICAST;
fee0f4c6 8534
1ae44dfc 8535 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 8536 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 8537}
8538
d62a17ae 8539static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 8540 safi_t safi, bool use_json)
f186de26 8541{
d62a17ae 8542 struct listnode *node, *nnode;
8543 struct bgp *bgp;
8544 int is_first = 1;
9f049418 8545 bool route_output = false;
f186de26 8546
d62a17ae 8547 if (use_json)
8548 vty_out(vty, "{\n");
9f689658 8549
d62a17ae 8550 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 8551 route_output = true;
d62a17ae 8552 if (use_json) {
8553 if (!is_first)
8554 vty_out(vty, ",\n");
8555 else
8556 is_first = 0;
8557
8558 vty_out(vty, "\"%s\":",
8559 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8560 ? "Default"
8561 : bgp->name);
8562 } else {
8563 vty_out(vty, "\nInstance %s:\n",
8564 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8565 ? "Default"
8566 : bgp->name);
8567 }
8568 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8569 use_json);
8570 }
9f689658 8571
d62a17ae 8572 if (use_json)
8573 vty_out(vty, "}\n");
9f049418
DS
8574 else if (!route_output)
8575 vty_out(vty, "%% BGP instance not found\n");
f186de26 8576}
8577
718e3744 8578/* Header of detailed BGP route information */
d62a17ae 8579void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8580 struct bgp_node *rn, struct prefix_rd *prd,
8581 afi_t afi, safi_t safi, json_object *json)
8582{
8583 struct bgp_info *ri;
8584 struct prefix *p;
8585 struct peer *peer;
8586 struct listnode *node, *nnode;
06b9f471 8587 char buf1[RD_ADDRSTRLEN];
d62a17ae 8588 char buf2[INET6_ADDRSTRLEN];
d62a17ae 8589 char buf3[EVPN_ROUTE_STRLEN];
0291c246 8590 char prefix_str[BUFSIZ];
d62a17ae 8591 int count = 0;
8592 int best = 0;
8593 int suppress = 0;
c5f1e1b2
C
8594 int accept_own = 0;
8595 int route_filter_translated_v4 = 0;
8596 int route_filter_v4 = 0;
8597 int route_filter_translated_v6 = 0;
8598 int route_filter_v6 = 0;
8599 int llgr_stale = 0;
8600 int no_llgr = 0;
8601 int accept_own_nexthop = 0;
8602 int blackhole = 0;
d62a17ae 8603 int no_export = 0;
8604 int no_advertise = 0;
8605 int local_as = 0;
c5f1e1b2 8606 int no_peer = 0;
d62a17ae 8607 int first = 1;
8608 int has_valid_label = 0;
8609 mpls_label_t label = 0;
8610 json_object *json_adv_to = NULL;
9bedbb1e 8611
d62a17ae 8612 p = &rn->p;
8613 has_valid_label = bgp_is_valid_label(&rn->local_label);
8614
8615 if (has_valid_label)
8616 label = label_pton(&rn->local_label);
8617
8618 if (json) {
8619 if (has_valid_label)
8620 json_object_int_add(json, "localLabel", label);
8621
60466a63
QY
8622 json_object_string_add(
8623 json, "prefix",
8624 prefix2str(p, prefix_str, sizeof(prefix_str)));
d62a17ae 8625 } else {
d62a17ae 8626 if (safi == SAFI_EVPN)
8627 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 8628 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 8629 : "",
8630 prd ? ":" : "",
8631 bgp_evpn_route2str((struct prefix_evpn *)p,
8632 buf3, sizeof(buf3)));
8633 else
8634 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8635 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8636 ? prefix_rd2str(prd, buf1,
06b9f471 8637 sizeof(buf1))
d62a17ae 8638 : ""),
8639 safi == SAFI_MPLS_VPN ? ":" : "",
8640 inet_ntop(p->family, &p->u.prefix, buf2,
8641 INET6_ADDRSTRLEN),
8642 p->prefixlen);
cd1964ff 8643
d62a17ae 8644 if (has_valid_label)
8645 vty_out(vty, "Local label: %d\n", label);
d62a17ae 8646 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 8647 vty_out(vty, "not allocated\n");
8648 }
718e3744 8649
d62a17ae 8650 for (ri = rn->info; ri; ri = ri->next) {
8651 count++;
8652 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
8653 best = count;
8654 if (ri->extra && ri->extra->suppress)
8655 suppress = 1;
8656 if (ri->attr->community != NULL) {
8657 if (community_include(ri->attr->community,
8658 COMMUNITY_NO_ADVERTISE))
8659 no_advertise = 1;
8660 if (community_include(ri->attr->community,
8661 COMMUNITY_NO_EXPORT))
8662 no_export = 1;
8663 if (community_include(ri->attr->community,
8664 COMMUNITY_LOCAL_AS))
8665 local_as = 1;
8666 }
8667 }
718e3744 8668 }
718e3744 8669
d62a17ae 8670 if (!json) {
8671 vty_out(vty, "Paths: (%d available", count);
8672 if (best) {
8673 vty_out(vty, ", best #%d", best);
8674 if (safi == SAFI_UNICAST)
8675 vty_out(vty, ", table %s",
8676 (bgp->inst_type
8677 == BGP_INSTANCE_TYPE_DEFAULT)
8678 ? "Default-IP-Routing-Table"
8679 : bgp->name);
8680 } else
8681 vty_out(vty, ", no best path");
8682
c5f1e1b2
C
8683 if (accept_own)
8684 vty_out(vty,
8685 ", accept own local route exported and imported in different VRF");
8686 else if (route_filter_translated_v4)
8687 vty_out(vty,
8688 ", mark translated RTs for VPNv4 route filtering");
8689 else if (route_filter_v4)
8690 vty_out(vty,
8691 ", attach RT as-is for VPNv4 route filtering");
8692 else if (route_filter_translated_v6)
8693 vty_out(vty,
8694 ", mark translated RTs for VPNv6 route filtering");
8695 else if (route_filter_v6)
8696 vty_out(vty,
8697 ", attach RT as-is for VPNv6 route filtering");
8698 else if (llgr_stale)
8699 vty_out(vty,
8700 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8701 else if (no_llgr)
8702 vty_out(vty,
8703 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8704 else if (accept_own_nexthop)
8705 vty_out(vty,
8706 ", accept local nexthop");
8707 else if (blackhole)
8708 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 8709 else if (no_export)
8710 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
8711 else if (no_advertise)
8712 vty_out(vty, ", not advertised to any peer");
d62a17ae 8713 else if (local_as)
8714 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
8715 else if (no_peer)
8716 vty_out(vty,
8717 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 8718
8719 if (suppress)
8720 vty_out(vty,
8721 ", Advertisements suppressed by an aggregate.");
8722 vty_out(vty, ")\n");
8723 }
718e3744 8724
d62a17ae 8725 /* If we are not using addpath then we can display Advertised to and
8726 * that will
8727 * show what peers we advertised the bestpath to. If we are using
8728 * addpath
8729 * though then we must display Advertised to on a path-by-path basis. */
8730 if (!bgp->addpath_tx_used[afi][safi]) {
8731 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8732 if (bgp_adj_out_lookup(peer, rn, 0)) {
8733 if (json && !json_adv_to)
8734 json_adv_to = json_object_new_object();
8735
8736 route_vty_out_advertised_to(
8737 vty, peer, &first,
8738 " Advertised to non peer-group peers:\n ",
8739 json_adv_to);
8740 }
8741 }
8742
8743 if (json) {
8744 if (json_adv_to) {
8745 json_object_object_add(json, "advertisedTo",
8746 json_adv_to);
8747 }
8748 } else {
8749 if (first)
8750 vty_out(vty, " Not advertised to any peer");
8751 vty_out(vty, "\n");
8752 }
8753 }
718e3744 8754}
8755
8756/* Display specified route of BGP table. */
d62a17ae 8757static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
8758 struct bgp_table *rib, const char *ip_str,
8759 afi_t afi, safi_t safi,
8760 struct prefix_rd *prd, int prefix_check,
9f049418 8761 enum bgp_path_type pathtype, bool use_json)
d62a17ae 8762{
8763 int ret;
8764 int header;
8765 int display = 0;
8766 struct prefix match;
8767 struct bgp_node *rn;
8768 struct bgp_node *rm;
8769 struct bgp_info *ri;
8770 struct bgp_table *table;
8771 json_object *json = NULL;
8772 json_object *json_paths = NULL;
8773
8774 /* Check IP address argument. */
8775 ret = str2prefix(ip_str, &match);
8776 if (!ret) {
8777 vty_out(vty, "address is malformed\n");
8778 return CMD_WARNING;
8779 }
718e3744 8780
d62a17ae 8781 match.family = afi2family(afi);
b05a1c8b 8782
d62a17ae 8783 if (use_json) {
8784 json = json_object_new_object();
8785 json_paths = json_object_new_array();
8786 }
718e3744 8787
d62a17ae 8788 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
8789 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
8790 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
8791 continue;
8792
ea47320b
DL
8793 if ((table = rn->info) == NULL)
8794 continue;
d62a17ae 8795
ea47320b
DL
8796 header = 1;
8797
8798 if ((rm = bgp_node_match(table, &match)) == NULL)
8799 continue;
d62a17ae 8800
ea47320b
DL
8801 if (prefix_check
8802 && rm->p.prefixlen != match.prefixlen) {
8803 bgp_unlock_node(rm);
8804 continue;
8805 }
d62a17ae 8806
ea47320b
DL
8807 for (ri = rm->info; ri; ri = ri->next) {
8808 if (header) {
60466a63
QY
8809 route_vty_out_detail_header(
8810 vty, bgp, rm,
8811 (struct prefix_rd *)&rn->p,
ea47320b
DL
8812 AFI_IP, safi, json);
8813 header = 0;
d62a17ae 8814 }
ea47320b
DL
8815 display++;
8816
8817 if (pathtype == BGP_PATH_ALL
8818 || (pathtype == BGP_PATH_BESTPATH
8819 && CHECK_FLAG(ri->flags,
8820 BGP_INFO_SELECTED))
8821 || (pathtype == BGP_PATH_MULTIPATH
8822 && (CHECK_FLAG(ri->flags,
8823 BGP_INFO_MULTIPATH)
8824 || CHECK_FLAG(ri->flags,
60466a63 8825 BGP_INFO_SELECTED))))
ea47320b
DL
8826 route_vty_out_detail(vty, bgp, &rm->p,
8827 ri, AFI_IP, safi,
8828 json_paths);
d62a17ae 8829 }
ea47320b
DL
8830
8831 bgp_unlock_node(rm);
d62a17ae 8832 }
98a9dbc7 8833 } else if (safi == SAFI_FLOWSPEC) {
63a0b7a9
PG
8834 display = bgp_flowspec_display_match_per_ip(afi, rib,
8835 &match, prefix_check,
8836 vty,
8837 use_json,
8838 json_paths);
d62a17ae 8839 } else {
8840 header = 1;
8841
8842 if ((rn = bgp_node_match(rib, &match)) != NULL) {
8843 if (!prefix_check
8844 || rn->p.prefixlen == match.prefixlen) {
8845 for (ri = rn->info; ri; ri = ri->next) {
8846 if (header) {
8847 route_vty_out_detail_header(
8848 vty, bgp, rn, NULL, afi,
8849 safi, json);
8850 header = 0;
8851 }
8852 display++;
8853
8854 if (pathtype == BGP_PATH_ALL
8855 || (pathtype == BGP_PATH_BESTPATH
8856 && CHECK_FLAG(
8857 ri->flags,
8858 BGP_INFO_SELECTED))
8859 || (pathtype == BGP_PATH_MULTIPATH
8860 && (CHECK_FLAG(
8861 ri->flags,
8862 BGP_INFO_MULTIPATH)
8863 || CHECK_FLAG(
8864 ri->flags,
8865 BGP_INFO_SELECTED))))
8866 route_vty_out_detail(
8867 vty, bgp, &rn->p, ri,
8868 afi, safi, json_paths);
8869 }
8870 }
8871
8872 bgp_unlock_node(rn);
8873 }
8874 }
e5eee9af 8875
d62a17ae 8876 if (use_json) {
8877 if (display)
8878 json_object_object_add(json, "paths", json_paths);
8879
996c9314
LB
8880 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8881 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 8882 json_object_free(json);
8883 } else {
8884 if (!display) {
8885 vty_out(vty, "%% Network not in table\n");
8886 return CMD_WARNING;
8887 }
8888 }
b05a1c8b 8889
d62a17ae 8890 return CMD_SUCCESS;
718e3744 8891}
8892
fee0f4c6 8893/* Display specified route of Main RIB */
d62a17ae 8894static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
8895 afi_t afi, safi_t safi, struct prefix_rd *prd,
8896 int prefix_check, enum bgp_path_type pathtype,
9f049418 8897 bool use_json)
d62a17ae 8898{
9b86009a 8899 if (!bgp) {
d62a17ae 8900 bgp = bgp_get_default();
9b86009a
RW
8901 if (!bgp) {
8902 if (!use_json)
8903 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8904 else
8905 vty_out(vty, "{}\n");
9b86009a
RW
8906 return CMD_WARNING;
8907 }
8908 }
d62a17ae 8909
8910 /* labeled-unicast routes live in the unicast table */
8911 if (safi == SAFI_LABELED_UNICAST)
8912 safi = SAFI_UNICAST;
8913
8914 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
8915 afi, safi, prd, prefix_check, pathtype,
8916 use_json);
8917}
8918
8919static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
8920 struct cmd_token **argv, afi_t afi, safi_t safi,
088f1098 8921 bool uj)
d62a17ae 8922{
8923 struct lcommunity *lcom;
8924 struct buffer *b;
8925 int i;
8926 char *str;
8927 int first = 0;
8928
8929 b = buffer_new(1024);
8930 for (i = 0; i < argc; i++) {
8931 if (first)
8932 buffer_putc(b, ' ');
8933 else {
8934 if (strmatch(argv[i]->text, "AA:BB:CC")) {
8935 first = 1;
8936 buffer_putstr(b, argv[i]->arg);
8937 }
8938 }
8939 }
8940 buffer_putc(b, '\0');
57d187bc 8941
d62a17ae 8942 str = buffer_getstr(b);
8943 buffer_free(b);
57d187bc 8944
d62a17ae 8945 lcom = lcommunity_str2com(str);
8946 XFREE(MTYPE_TMP, str);
8947 if (!lcom) {
8948 vty_out(vty, "%% Large-community malformed\n");
8949 return CMD_WARNING;
8950 }
57d187bc 8951
d62a17ae 8952 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
8953 uj);
57d187bc
JS
8954}
8955
d62a17ae 8956static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
8957 const char *lcom, afi_t afi, safi_t safi,
088f1098 8958 bool uj)
57d187bc 8959{
d62a17ae 8960 struct community_list *list;
57d187bc 8961
d62a17ae 8962 list = community_list_lookup(bgp_clist, lcom,
8963 LARGE_COMMUNITY_LIST_MASTER);
8964 if (list == NULL) {
8965 vty_out(vty, "%% %s is not a valid large-community-list name\n",
8966 lcom);
8967 return CMD_WARNING;
8968 }
57d187bc 8969
d62a17ae 8970 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
8971 list, uj);
fee0f4c6 8972}
8973
52951b63
DS
8974DEFUN (show_ip_bgp_large_community_list,
8975 show_ip_bgp_large_community_list_cmd,
4dd6177e 8976 "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
8977 SHOW_STR
8978 IP_STR
8979 BGP_STR
8980 BGP_INSTANCE_HELP_STR
9bedbb1e 8981 BGP_AFI_HELP_STR
4dd6177e 8982 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
8983 "Display routes matching the large-community-list\n"
8984 "large-community-list number\n"
8985 "large-community-list name\n"
8986 JSON_STR)
8987{
d62a17ae 8988 char *vrf = NULL;
8989 afi_t afi = AFI_IP6;
8990 safi_t safi = SAFI_UNICAST;
8991 int idx = 0;
8992
8993 if (argv_find(argv, argc, "ip", &idx))
8994 afi = AFI_IP;
8995 if (argv_find(argv, argc, "view", &idx)
8996 || argv_find(argv, argc, "vrf", &idx))
8997 vrf = argv[++idx]->arg;
8998 if (argv_find(argv, argc, "ipv4", &idx)
8999 || argv_find(argv, argc, "ipv6", &idx)) {
9000 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9001 if (argv_find(argv, argc, "unicast", &idx)
9002 || argv_find(argv, argc, "multicast", &idx))
9003 safi = bgp_vty_safi_from_str(argv[idx]->text);
9004 }
9005
9f049418 9006 bool uj = use_json(argc, argv);
d62a17ae 9007
9008 struct bgp *bgp = bgp_lookup_by_name(vrf);
9009 if (bgp == NULL) {
9010 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9011 return CMD_WARNING;
9012 }
9013
9014 argv_find(argv, argc, "large-community-list", &idx);
9015 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
9016 uj);
52951b63
DS
9017}
9018DEFUN (show_ip_bgp_large_community,
9019 show_ip_bgp_large_community_cmd,
4dd6177e 9020 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
9021 SHOW_STR
9022 IP_STR
9023 BGP_STR
9024 BGP_INSTANCE_HELP_STR
9bedbb1e 9025 BGP_AFI_HELP_STR
4dd6177e 9026 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
9027 "Display routes matching the large-communities\n"
9028 "List of large-community numbers\n"
9029 JSON_STR)
9030{
d62a17ae 9031 char *vrf = NULL;
9032 afi_t afi = AFI_IP6;
9033 safi_t safi = SAFI_UNICAST;
9034 int idx = 0;
9035
9036 if (argv_find(argv, argc, "ip", &idx))
9037 afi = AFI_IP;
9038 if (argv_find(argv, argc, "view", &idx)
9039 || argv_find(argv, argc, "vrf", &idx))
9040 vrf = argv[++idx]->arg;
9041 if (argv_find(argv, argc, "ipv4", &idx)
9042 || argv_find(argv, argc, "ipv6", &idx)) {
9043 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
9044 if (argv_find(argv, argc, "unicast", &idx)
9045 || argv_find(argv, argc, "multicast", &idx))
9046 safi = bgp_vty_safi_from_str(argv[idx]->text);
9047 }
9048
9f049418 9049 bool uj = use_json(argc, argv);
d62a17ae 9050
9051 struct bgp *bgp = bgp_lookup_by_name(vrf);
9052 if (bgp == NULL) {
9053 vty_out(vty, "Can't find BGP instance %s\n", vrf);
9054 return CMD_WARNING;
9055 }
9056
9057 if (argv_find(argv, argc, "AA:BB:CC", &idx))
9058 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
9059 else
9060 return bgp_show(vty, bgp, afi, safi,
9061 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
9062}
9063
d62a17ae 9064static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9065 safi_t safi);
e01ca200 9066
7b2ff250
DW
9067
9068/* BGP route print out function without JSON */
af462945
DS
9069DEFUN (show_ip_bgp,
9070 show_ip_bgp_cmd,
4dd6177e 9071 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
9072 <dampening <parameters>\
9073 |route-map WORD\
9074 |prefix-list WORD\
9075 |filter-list WORD\
9076 |statistics\
c5f1e1b2
C
9077 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
9078 no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
9079 route-filter-v6|route-filter-v4|route-filter-translated-v6|\
9080 route-filter-translated-v4> [exact-match]\
7b2ff250
DW
9081 |community-list <(1-500)|WORD> [exact-match]\
9082 |A.B.C.D/M longer-prefixes\
9083 |X:X::X:X/M longer-prefixes\
9084 >",
718e3744 9085 SHOW_STR
9086 IP_STR
9087 BGP_STR
a636c635 9088 BGP_INSTANCE_HELP_STR
4f280b15 9089 BGP_AFI_HELP_STR
4dd6177e 9090 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 9091 "Display detailed information about dampening\n"
af462945 9092 "Display detail of configured dampening parameters\n"
a636c635
DW
9093 "Display routes matching the route-map\n"
9094 "A route-map to match on\n"
9095 "Display routes conforming to the prefix-list\n"
8c3deaae 9096 "Prefix-list name\n"
a636c635
DW
9097 "Display routes conforming to the filter-list\n"
9098 "Regular expression access list name\n"
e01ca200 9099 "BGP RIB advertisement statistics\n"
c5f1e1b2
C
9100 "Display routes matching the communities\n"
9101 COMMUNITY_AANN_STR
9102 "Do not send outside local AS (well-known community)\n"
9103 "Do not advertise to any peer (well-known community)\n"
9104 "Do not export to next AS (well-known community)\n"
9105 "Graceful shutdown (well-known community)\n"
9106 "Do not export to any peer (well-known community)\n"
9107 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9108 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9109 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9110 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9111 "Should accept VPN route with local nexthop (well-known community)\n"
9112 "RT VPNv6 route filtering (well-known community)\n"
9113 "RT VPNv4 route filtering (well-known community)\n"
9114 "RT translated VPNv6 route filtering (well-known community)\n"
9115 "RT translated VPNv4 route filtering (well-known community)\n"
9116 "Exact match of the communities\n"
a636c635
DW
9117 "Display routes matching the community-list\n"
9118 "community-list number\n"
9119 "community-list name\n"
9120 "Exact match of the communities\n"
0c7b1b01 9121 "IPv4 prefix\n"
8c3deaae 9122 "Display route and more specific routes\n"
0c7b1b01 9123 "IPv6 prefix\n"
7b2ff250 9124 "Display route and more specific routes\n")
718e3744 9125{
d62a17ae 9126 afi_t afi = AFI_IP6;
9127 safi_t safi = SAFI_UNICAST;
9128 int exact_match = 0;
d62a17ae 9129 struct bgp *bgp = NULL;
9130 int idx = 0;
9131
9132 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9133 &bgp, false);
d62a17ae 9134 if (!idx)
9135 return CMD_WARNING;
9136
d62a17ae 9137 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 9138 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 9139 return bgp_show_dampening_parameters(vty, afi, safi);
9140 }
c016b6c7 9141
d62a17ae 9142 if (argv_find(argv, argc, "prefix-list", &idx))
9143 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
9144 safi, bgp_show_type_prefix_list);
9145
9146 if (argv_find(argv, argc, "filter-list", &idx))
9147 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
9148 safi, bgp_show_type_filter_list);
9149
9150 if (argv_find(argv, argc, "statistics", &idx))
9151 return bgp_table_stats(vty, bgp, afi, safi);
9152
9153 if (argv_find(argv, argc, "route-map", &idx))
9154 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
9155 safi, bgp_show_type_route_map);
9156
d62a17ae 9157 if (argv_find(argv, argc, "community-list", &idx)) {
9158 const char *clist_number_or_name = argv[++idx]->arg;
9159 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
9160 exact_match = 1;
9161 return bgp_show_community_list(vty, bgp, clist_number_or_name,
9162 exact_match, afi, safi);
9163 }
9164 /* prefix-longer */
9165 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9166 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9167 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
9168 safi,
9169 bgp_show_type_prefix_longer);
9170
7b2ff250
DW
9171 return CMD_WARNING;
9172}
9173
9174/* BGP route print out function with JSON */
9175DEFUN (show_ip_bgp_json,
9176 show_ip_bgp_json_cmd,
9177 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
9178 [<\
9179 cidr-only\
9180 |dampening <flap-statistics|dampened-paths>\
d0086e8e 9181 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
7b2ff250
DW
9182 >] [json]",
9183 SHOW_STR
9184 IP_STR
9185 BGP_STR
9186 BGP_INSTANCE_HELP_STR
9187 BGP_AFI_HELP_STR
9188 BGP_SAFI_WITH_LABEL_HELP_STR
9189 "Display only routes with non-natural netmasks\n"
9190 "Display detailed information about dampening\n"
9191 "Display flap statistics of routes\n"
9192 "Display paths suppressed due to dampening\n"
9193 "Display routes matching the communities\n"
d0086e8e
AD
9194 COMMUNITY_AANN_STR
9195 "Do not send outside local AS (well-known community)\n"
9196 "Do not advertise to any peer (well-known community)\n"
9197 "Do not export to next AS (well-known community)\n"
9198 "Graceful shutdown (well-known community)\n"
9199 "Exact match of the communities\n"
7b2ff250
DW
9200 JSON_STR)
9201{
9202 afi_t afi = AFI_IP6;
9203 safi_t safi = SAFI_UNICAST;
9204 enum bgp_show_type sh_type = bgp_show_type_normal;
9205 struct bgp *bgp = NULL;
9206 int idx = 0;
d0086e8e
AD
9207 int idx_community_type = 0;
9208 int exact_match = 0;
9f049418
DS
9209 bool uj = use_json(argc, argv);
9210
9211 if (uj)
9212 argc--;
7b2ff250
DW
9213
9214 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9215 &bgp, uj);
7b2ff250
DW
9216 if (!idx)
9217 return CMD_WARNING;
9218
7b2ff250
DW
9219 if (argv_find(argv, argc, "cidr-only", &idx))
9220 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
9221 NULL, uj);
9222
9223 if (argv_find(argv, argc, "dampening", &idx)) {
9224 if (argv_find(argv, argc, "dampened-paths", &idx))
9225 return bgp_show(vty, bgp, afi, safi,
9226 bgp_show_type_dampend_paths, NULL, uj);
9227 else if (argv_find(argv, argc, "flap-statistics", &idx))
9228 return bgp_show(vty, bgp, afi, safi,
9229 bgp_show_type_flap_statistics, NULL,
9230 uj);
9231 }
9232
9233 if (argv_find(argv, argc, "community", &idx)) {
d0086e8e
AD
9234
9235 /* show a specific community */
9236 if (argv_find(argv, argc, "local-AS", &idx_community_type) ||
9237 argv_find(argv, argc, "no-advertise",
9238 &idx_community_type) ||
9239 argv_find(argv, argc, "no-export",
9240 &idx_community_type) ||
9241 argv_find(argv, argc, "graceful-shutdown",
9242 &idx_community_type) ||
9243 argv_find(argv, argc, "AA:NN", &idx_community_type)) {
9244 if (argv_find(argv, argc, "exact-match", &idx))
9245 exact_match = 1;
9246
9247 return (bgp_show_community(vty, bgp,
9248 argv[idx_community_type]->arg,
9249 exact_match, afi, safi, uj));
9250 } else {
9251
9252 /* show all communities */
9253 return (bgp_show(vty, bgp, afi, safi,
9254 bgp_show_type_community_all, NULL,
9255 uj));
9256 }
7b2ff250 9257 }
d0086e8e 9258
1ae44dfc 9259 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 9260}
47fc97cc 9261
718e3744 9262DEFUN (show_ip_bgp_route,
9263 show_ip_bgp_route_cmd,
4dd6177e 9264 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 9265 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 9266 SHOW_STR
9267 IP_STR
9268 BGP_STR
a636c635 9269 BGP_INSTANCE_HELP_STR
4f280b15 9270 BGP_AFI_HELP_STR
4dd6177e 9271 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 9272 "Network in the BGP routing table to display\n"
0c7b1b01 9273 "IPv4 prefix\n"
8c3deaae 9274 "Network in the BGP routing table to display\n"
0c7b1b01 9275 "IPv6 prefix\n"
4092b06c 9276 "Display only the bestpath\n"
b05a1c8b 9277 "Display only multipaths\n"
9973d184 9278 JSON_STR)
4092b06c 9279{
d62a17ae 9280 int prefix_check = 0;
ae19d7dd 9281
d62a17ae 9282 afi_t afi = AFI_IP6;
9283 safi_t safi = SAFI_UNICAST;
9284 char *prefix = NULL;
9285 struct bgp *bgp = NULL;
9286 enum bgp_path_type path_type;
9f049418 9287 bool uj = use_json(argc, argv);
b05a1c8b 9288
d62a17ae 9289 int idx = 0;
ae19d7dd 9290
d62a17ae 9291 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9292 &bgp, uj);
d62a17ae 9293 if (!idx)
9294 return CMD_WARNING;
c41247f5 9295
d62a17ae 9296 if (!bgp) {
9297 vty_out(vty,
9298 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9299 return CMD_WARNING;
9300 }
a636c635 9301
d62a17ae 9302 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9303 if (argv_find(argv, argc, "A.B.C.D", &idx)
9304 || argv_find(argv, argc, "X:X::X:X", &idx))
9305 prefix_check = 0;
9306 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9307 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9308 prefix_check = 1;
9309
9310 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9311 && afi != AFI_IP6) {
9312 vty_out(vty,
9313 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9314 return CMD_WARNING;
9315 }
9316 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9317 && afi != AFI_IP) {
9318 vty_out(vty,
9319 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9320 return CMD_WARNING;
9321 }
9322
9323 prefix = argv[idx]->arg;
9324
9325 /* [<bestpath|multipath>] */
9326 if (argv_find(argv, argc, "bestpath", &idx))
9327 path_type = BGP_PATH_BESTPATH;
9328 else if (argv_find(argv, argc, "multipath", &idx))
9329 path_type = BGP_PATH_MULTIPATH;
9330 else
9331 path_type = BGP_PATH_ALL;
a636c635 9332
d62a17ae 9333 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9334 path_type, uj);
4092b06c
DS
9335}
9336
8c3deaae
QY
9337DEFUN (show_ip_bgp_regexp,
9338 show_ip_bgp_regexp_cmd,
4dd6177e 9339 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9340 SHOW_STR
9341 IP_STR
9342 BGP_STR
b00b230a 9343 BGP_INSTANCE_HELP_STR
4f280b15 9344 BGP_AFI_HELP_STR
4dd6177e 9345 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9346 "Display routes matching the AS path regular expression\n"
9347 "A regular-expression to match the BGP AS paths\n")
9348{
d62a17ae 9349 afi_t afi = AFI_IP6;
9350 safi_t safi = SAFI_UNICAST;
9351 struct bgp *bgp = NULL;
8c3deaae 9352
d62a17ae 9353 int idx = 0;
9354 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 9355 &bgp, false);
d62a17ae 9356 if (!idx)
9357 return CMD_WARNING;
8c3deaae 9358
d62a17ae 9359 // get index of regex
9360 argv_find(argv, argc, "regexp", &idx);
9361 idx++;
8c3deaae 9362
d62a17ae 9363 char *regstr = argv_concat(argv, argc, idx);
e889891d 9364 int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
d62a17ae 9365 bgp_show_type_regexp);
9366 XFREE(MTYPE_TMP, regstr);
9367 return rc;
8c3deaae
QY
9368}
9369
a636c635
DW
9370DEFUN (show_ip_bgp_instance_all,
9371 show_ip_bgp_instance_all_cmd,
4dd6177e 9372 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9373 SHOW_STR
a636c635 9374 IP_STR
4092b06c 9375 BGP_STR
a636c635 9376 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9377 BGP_AFI_HELP_STR
4dd6177e 9378 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9379 JSON_STR)
4092b06c 9380{
d62a17ae 9381 afi_t afi = AFI_IP;
9382 safi_t safi = SAFI_UNICAST;
9383 struct bgp *bgp = NULL;
d62a17ae 9384 int idx = 0;
9f049418 9385 bool uj = use_json(argc, argv);
ae19d7dd 9386
d62a17ae 9387 if (uj)
9388 argc--;
e3e29b32 9389
9f049418
DS
9390 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9391 &bgp, uj);
9392 if (!idx)
9393 return CMD_WARNING;
9394
d62a17ae 9395 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9396 return CMD_SUCCESS;
e3e29b32
LB
9397}
9398
a4d82a8a
PZ
9399static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
9400 afi_t afi, safi_t safi, enum bgp_show_type type)
718e3744 9401{
d62a17ae 9402 regex_t *regex;
9403 int rc;
e3e29b32 9404
d62a17ae 9405 regex = bgp_regcomp(regstr);
9406 if (!regex) {
9407 vty_out(vty, "Can't compile regexp %s\n", regstr);
9408 return CMD_WARNING;
9409 }
a636c635 9410
e889891d 9411 rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
d62a17ae 9412 bgp_regex_free(regex);
9413 return rc;
e3e29b32
LB
9414}
9415
d62a17ae 9416static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9417 const char *prefix_list_str, afi_t afi,
9418 safi_t safi, enum bgp_show_type type)
e3e29b32 9419{
d62a17ae 9420 struct prefix_list *plist;
718e3744 9421
d62a17ae 9422 plist = prefix_list_lookup(afi, prefix_list_str);
9423 if (plist == NULL) {
9424 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9425 prefix_list_str);
9426 return CMD_WARNING;
9427 }
718e3744 9428
d62a17ae 9429 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9430}
9431
d62a17ae 9432static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9433 const char *filter, afi_t afi, safi_t safi,
9434 enum bgp_show_type type)
4092b06c 9435{
d62a17ae 9436 struct as_list *as_list;
718e3744 9437
d62a17ae 9438 as_list = as_list_lookup(filter);
9439 if (as_list == NULL) {
9440 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9441 filter);
9442 return CMD_WARNING;
9443 }
a636c635 9444
d62a17ae 9445 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9446}
9447
d62a17ae 9448static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9449 const char *rmap_str, afi_t afi, safi_t safi,
9450 enum bgp_show_type type)
718e3744 9451{
d62a17ae 9452 struct route_map *rmap;
bb46e94f 9453
d62a17ae 9454 rmap = route_map_lookup_by_name(rmap_str);
9455 if (!rmap) {
9456 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9457 return CMD_WARNING;
9458 }
9459
9460 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9461}
9462
7f323236
DW
9463static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9464 const char *comstr, int exact, afi_t afi,
9f049418 9465 safi_t safi, bool use_json)
d62a17ae 9466{
9467 struct community *com;
d62a17ae 9468 int ret = 0;
9469
7f323236 9470 com = community_str2com(comstr);
d62a17ae 9471 if (!com) {
7f323236 9472 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 9473 return CMD_WARNING;
9474 }
9475
9476 ret = bgp_show(vty, bgp, afi, safi,
9477 (exact ? bgp_show_type_community_exact
9478 : bgp_show_type_community),
d0086e8e 9479 com, use_json);
d62a17ae 9480 community_free(com);
46c3ce83 9481
d62a17ae 9482 return ret;
718e3744 9483}
9484
d62a17ae 9485static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9486 const char *com, int exact, afi_t afi,
9487 safi_t safi)
50ef26d4 9488{
d62a17ae 9489 struct community_list *list;
50ef26d4 9490
d62a17ae 9491 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9492 if (list == NULL) {
9493 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9494 return CMD_WARNING;
9495 }
718e3744 9496
d62a17ae 9497 return bgp_show(vty, bgp, afi, safi,
9498 (exact ? bgp_show_type_community_list_exact
9499 : bgp_show_type_community_list),
9500 list, 0);
50ef26d4 9501}
9502
d62a17ae 9503static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9504 const char *prefix, afi_t afi, safi_t safi,
9505 enum bgp_show_type type)
718e3744 9506{
d62a17ae 9507 int ret;
9508 struct prefix *p;
47fc97cc 9509
d62a17ae 9510 p = prefix_new();
95cbbd2a 9511
d62a17ae 9512 ret = str2prefix(prefix, p);
9513 if (!ret) {
9514 vty_out(vty, "%% Malformed Prefix\n");
9515 return CMD_WARNING;
9516 }
47e9b292 9517
d62a17ae 9518 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9519 prefix_free(p);
9520 return ret;
9521}
9522
9523static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
9f049418 9524 const char *ip_str, bool use_json)
d62a17ae 9525{
9526 int ret;
9527 struct peer *peer;
9528 union sockunion su;
9529
9530 /* Get peer sockunion. */
9531 ret = str2sockunion(ip_str, &su);
9532 if (ret < 0) {
9533 peer = peer_lookup_by_conf_if(bgp, ip_str);
9534 if (!peer) {
9535 peer = peer_lookup_by_hostname(bgp, ip_str);
9536
9537 if (!peer) {
9538 if (use_json) {
9539 json_object *json_no = NULL;
9540 json_no = json_object_new_object();
9541 json_object_string_add(
9542 json_no,
9543 "malformedAddressOrName",
9544 ip_str);
9545 vty_out(vty, "%s\n",
66f80d74 9546 json_object_to_json_string_ext(
a4d82a8a
PZ
9547 json_no,
9548 JSON_C_TO_STRING_PRETTY));
d62a17ae 9549 json_object_free(json_no);
9550 } else
9551 vty_out(vty,
9552 "%% Malformed address or name: %s\n",
9553 ip_str);
9554 return NULL;
9555 }
9556 }
9557 return peer;
9558 }
718e3744 9559
d62a17ae 9560 /* Peer structure lookup. */
9561 peer = peer_lookup(bgp, &su);
9562 if (!peer) {
9563 if (use_json) {
9564 json_object *json_no = NULL;
9565 json_no = json_object_new_object();
9566 json_object_string_add(json_no, "warning",
9e6e6f46 9567 "No such neighbor in this view/vrf");
d62a17ae 9568 vty_out(vty, "%s\n",
a4d82a8a
PZ
9569 json_object_to_json_string_ext(
9570 json_no, JSON_C_TO_STRING_PRETTY));
d62a17ae 9571 json_object_free(json_no);
9572 } else
9e6e6f46 9573 vty_out(vty, "No such neighbor in this view/vrf\n");
d62a17ae 9574 return NULL;
9575 }
2815e61f 9576
d62a17ae 9577 return peer;
9578}
9579
9580enum bgp_stats {
9581 BGP_STATS_MAXBITLEN = 0,
9582 BGP_STATS_RIB,
9583 BGP_STATS_PREFIXES,
9584 BGP_STATS_TOTPLEN,
9585 BGP_STATS_UNAGGREGATEABLE,
9586 BGP_STATS_MAX_AGGREGATEABLE,
9587 BGP_STATS_AGGREGATES,
9588 BGP_STATS_SPACE,
9589 BGP_STATS_ASPATH_COUNT,
9590 BGP_STATS_ASPATH_MAXHOPS,
9591 BGP_STATS_ASPATH_TOTHOPS,
9592 BGP_STATS_ASPATH_MAXSIZE,
9593 BGP_STATS_ASPATH_TOTSIZE,
9594 BGP_STATS_ASN_HIGHEST,
9595 BGP_STATS_MAX,
a636c635 9596};
2815e61f 9597
d62a17ae 9598static const char *table_stats_strs[] = {
9d303b37
DL
9599 [BGP_STATS_PREFIXES] = "Total Prefixes",
9600 [BGP_STATS_TOTPLEN] = "Average prefix length",
9601 [BGP_STATS_RIB] = "Total Advertisements",
9602 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9603 [BGP_STATS_MAX_AGGREGATEABLE] =
9604 "Maximum aggregateable prefixes",
9605 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9606 [BGP_STATS_SPACE] = "Address space advertised",
9607 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9608 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9609 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9610 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9611 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9612 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9613 [BGP_STATS_MAX] = NULL,
a636c635 9614};
2815e61f 9615
d62a17ae 9616struct bgp_table_stats {
9617 struct bgp_table *table;
9618 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 9619 double total_space;
ff7924f6
PJ
9620};
9621
a636c635
DW
9622#if 0
9623#define TALLY_SIGFIG 100000
9624static unsigned long
9625ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9626{
a636c635
DW
9627 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9628 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9629 unsigned long ret = newtot / count;
07d0c4ed 9630
a636c635
DW
9631 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9632 return ret + 1;
9633 else
9634 return ret;
9635}
9636#endif
ff7924f6 9637
d62a17ae 9638static int bgp_table_stats_walker(struct thread *t)
2815e61f 9639{
d62a17ae 9640 struct bgp_node *rn;
9641 struct bgp_node *top;
9642 struct bgp_table_stats *ts = THREAD_ARG(t);
9643 unsigned int space = 0;
a636c635 9644
d62a17ae 9645 if (!(top = bgp_table_top(ts->table)))
9646 return 0;
2815e61f 9647
d62a17ae 9648 switch (top->p.family) {
9649 case AF_INET:
9650 space = IPV4_MAX_BITLEN;
9651 break;
9652 case AF_INET6:
9653 space = IPV6_MAX_BITLEN;
9654 break;
9655 }
9656
9657 ts->counts[BGP_STATS_MAXBITLEN] = space;
9658
9659 for (rn = top; rn; rn = bgp_route_next(rn)) {
9660 struct bgp_info *ri;
9661 struct bgp_node *prn = bgp_node_parent_nolock(rn);
9662 unsigned int rinum = 0;
9663
9664 if (rn == top)
9665 continue;
9666
9667 if (!rn->info)
9668 continue;
9669
9670 ts->counts[BGP_STATS_PREFIXES]++;
9671 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9672
a636c635
DW
9673#if 0
9674 ts->counts[BGP_STATS_AVGPLEN]
9675 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9676 ts->counts[BGP_STATS_AVGPLEN],
9677 rn->p.prefixlen);
9678#endif
d62a17ae 9679
9680 /* check if the prefix is included by any other announcements */
9681 while (prn && !prn->info)
9682 prn = bgp_node_parent_nolock(prn);
9683
9684 if (prn == NULL || prn == top) {
9685 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9686 /* announced address space */
9687 if (space)
a4d82a8a
PZ
9688 ts->total_space +=
9689 pow(2.0, space - rn->p.prefixlen);
d62a17ae 9690 } else if (prn->info)
9691 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9692
9693 for (ri = rn->info; ri; ri = ri->next) {
9694 rinum++;
9695 ts->counts[BGP_STATS_RIB]++;
9696
9697 if (ri->attr
9698 && (CHECK_FLAG(ri->attr->flag,
9699 ATTR_FLAG_BIT(
9700 BGP_ATTR_ATOMIC_AGGREGATE))))
9701 ts->counts[BGP_STATS_AGGREGATES]++;
9702
9703 /* as-path stats */
9704 if (ri->attr && ri->attr->aspath) {
9705 unsigned int hops =
9706 aspath_count_hops(ri->attr->aspath);
9707 unsigned int size =
9708 aspath_size(ri->attr->aspath);
9709 as_t highest = aspath_highest(ri->attr->aspath);
9710
9711 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9712
9713 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
9714 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
9715 hops;
9716
9717 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
9718 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
9719 size;
9720
9721 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
9722 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 9723#if 0
07d0c4ed 9724 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
9725 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9726 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
9727 hops);
9728 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
9729 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9730 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
9731 size);
9732#endif
d62a17ae 9733 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
9734 ts->counts[BGP_STATS_ASN_HIGHEST] =
9735 highest;
9736 }
9737 }
9738 }
9739 return 0;
2815e61f 9740}
ff7924f6 9741
d62a17ae 9742static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9743 safi_t safi)
2815e61f 9744{
d62a17ae 9745 struct bgp_table_stats ts;
9746 unsigned int i;
019386c2 9747
d62a17ae 9748 if (!bgp->rib[afi][safi]) {
9749 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9750 afi, safi);
9751 return CMD_WARNING;
9752 }
019386c2 9753
d62a17ae 9754 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 9755
d62a17ae 9756 /* labeled-unicast routes live in the unicast table */
9757 if (safi == SAFI_LABELED_UNICAST)
9758 safi = SAFI_UNICAST;
019386c2 9759
d62a17ae 9760 memset(&ts, 0, sizeof(ts));
9761 ts.table = bgp->rib[afi][safi];
9762 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 9763
d62a17ae 9764 for (i = 0; i < BGP_STATS_MAX; i++) {
9765 if (!table_stats_strs[i])
9766 continue;
9767
9768 switch (i) {
a636c635
DW
9769#if 0
9770 case BGP_STATS_ASPATH_AVGHOPS:
9771 case BGP_STATS_ASPATH_AVGSIZE:
9772 case BGP_STATS_AVGPLEN:
9773 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9774 vty_out (vty, "%12.2f",
9775 (float)ts.counts[i] / (float)TALLY_SIGFIG);
9776 break;
9777#endif
d62a17ae 9778 case BGP_STATS_ASPATH_TOTHOPS:
9779 case BGP_STATS_ASPATH_TOTSIZE:
9780 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9781 vty_out(vty, "%12.2f",
9782 ts.counts[i]
9783 ? (float)ts.counts[i]
9784 / (float)ts.counts
9785 [BGP_STATS_ASPATH_COUNT]
9786 : 0);
9787 break;
9788 case BGP_STATS_TOTPLEN:
9789 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9790 vty_out(vty, "%12.2f",
9791 ts.counts[i]
9792 ? (float)ts.counts[i]
9793 / (float)ts.counts
9794 [BGP_STATS_PREFIXES]
9795 : 0);
9796 break;
9797 case BGP_STATS_SPACE:
9798 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
9799 vty_out(vty, "%12g\n", ts.total_space);
9800
9801 if (afi == AFI_IP6) {
9802 vty_out(vty, "%30s: ", "/32 equivalent ");
9803 vty_out(vty, "%12g\n",
a4d82a8a 9804 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
9805 vty_out(vty, "%30s: ", "/48 equivalent ");
9806 vty_out(vty, "%12g\n",
a4d82a8a 9807 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
9808 } else {
9809 vty_out(vty, "%30s: ", "% announced ");
9810 vty_out(vty, "%12.2f\n",
9811 ts.total_space * 100. * pow(2.0, -32));
9812 vty_out(vty, "%30s: ", "/8 equivalent ");
9813 vty_out(vty, "%12.2f\n",
a4d82a8a 9814 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
9815 vty_out(vty, "%30s: ", "/24 equivalent ");
9816 vty_out(vty, "%12.2f\n",
a4d82a8a 9817 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 9818 }
d62a17ae 9819 break;
9820 default:
9821 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9822 vty_out(vty, "%12llu", ts.counts[i]);
9823 }
ff7924f6 9824
d62a17ae 9825 vty_out(vty, "\n");
9826 }
9827 return CMD_SUCCESS;
9828}
9829
9830enum bgp_pcounts {
9831 PCOUNT_ADJ_IN = 0,
9832 PCOUNT_DAMPED,
9833 PCOUNT_REMOVED,
9834 PCOUNT_HISTORY,
9835 PCOUNT_STALE,
9836 PCOUNT_VALID,
9837 PCOUNT_ALL,
9838 PCOUNT_COUNTED,
9839 PCOUNT_PFCNT, /* the figure we display to users */
9840 PCOUNT_MAX,
a636c635 9841};
718e3744 9842
d62a17ae 9843static const char *pcount_strs[] = {
9d303b37
DL
9844 [PCOUNT_ADJ_IN] = "Adj-in",
9845 [PCOUNT_DAMPED] = "Damped",
9846 [PCOUNT_REMOVED] = "Removed",
9847 [PCOUNT_HISTORY] = "History",
9848 [PCOUNT_STALE] = "Stale",
9849 [PCOUNT_VALID] = "Valid",
9850 [PCOUNT_ALL] = "All RIB",
9851 [PCOUNT_COUNTED] = "PfxCt counted",
9852 [PCOUNT_PFCNT] = "Useable",
9853 [PCOUNT_MAX] = NULL,
a636c635 9854};
718e3744 9855
d62a17ae 9856struct peer_pcounts {
9857 unsigned int count[PCOUNT_MAX];
9858 const struct peer *peer;
9859 const struct bgp_table *table;
a636c635 9860};
47fc97cc 9861
d62a17ae 9862static int bgp_peer_count_walker(struct thread *t)
9863{
9864 struct bgp_node *rn;
9865 struct peer_pcounts *pc = THREAD_ARG(t);
9866 const struct peer *peer = pc->peer;
9867
9868 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
9869 struct bgp_adj_in *ain;
9870 struct bgp_info *ri;
9871
9872 for (ain = rn->adj_in; ain; ain = ain->next)
9873 if (ain->peer == peer)
9874 pc->count[PCOUNT_ADJ_IN]++;
9875
9876 for (ri = rn->info; ri; ri = ri->next) {
d62a17ae 9877 if (ri->peer != peer)
9878 continue;
9879
9880 pc->count[PCOUNT_ALL]++;
9881
9882 if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED))
9883 pc->count[PCOUNT_DAMPED]++;
9884 if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
9885 pc->count[PCOUNT_HISTORY]++;
9886 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
9887 pc->count[PCOUNT_REMOVED]++;
9888 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
9889 pc->count[PCOUNT_STALE]++;
9890 if (CHECK_FLAG(ri->flags, BGP_INFO_VALID))
9891 pc->count[PCOUNT_VALID]++;
9892 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9893 pc->count[PCOUNT_PFCNT]++;
9894
9895 if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
9896 pc->count[PCOUNT_COUNTED]++;
9897 if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
1c50c1c0
QY
9898 flog_err(
9899 EC_LIB_DEVELOPMENT,
9900 "Attempting to count but flags say it is unusable");
d62a17ae 9901 } else {
9902 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
1c50c1c0
QY
9903 flog_err(
9904 EC_LIB_DEVELOPMENT,
9905 "Not counted but flags say we should");
d62a17ae 9906 }
9907 }
9908 }
9909 return 0;
718e3744 9910}
9911
d62a17ae 9912static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 9913 safi_t safi, bool use_json)
856ca177 9914{
d62a17ae 9915 struct peer_pcounts pcounts = {.peer = peer};
9916 unsigned int i;
9917 json_object *json = NULL;
9918 json_object *json_loop = NULL;
856ca177 9919
d62a17ae 9920 if (use_json) {
9921 json = json_object_new_object();
9922 json_loop = json_object_new_object();
9923 }
718e3744 9924
d62a17ae 9925 if (!peer || !peer->bgp || !peer->afc[afi][safi]
9926 || !peer->bgp->rib[afi][safi]) {
9927 if (use_json) {
9928 json_object_string_add(
9929 json, "warning",
9930 "No such neighbor or address family");
9931 vty_out(vty, "%s\n", json_object_to_json_string(json));
9932 json_object_free(json);
9933 } else
9934 vty_out(vty, "%% No such neighbor or address family\n");
9935
9936 return CMD_WARNING;
9937 }
2a71e9ce 9938
d62a17ae 9939 memset(&pcounts, 0, sizeof(pcounts));
9940 pcounts.peer = peer;
9941 pcounts.table = peer->bgp->rib[afi][safi];
9942
9943 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
9944 * stats for the thread-walk (i.e. ensure this can't be blamed on
9945 * on just vty_read()).
9946 */
d62a17ae 9947 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
9948
9949 if (use_json) {
9950 json_object_string_add(json, "prefixCountsFor", peer->host);
9951 json_object_string_add(json, "multiProtocol",
9952 afi_safi_print(afi, safi));
9953 json_object_int_add(json, "pfxCounter",
9954 peer->pcount[afi][safi]);
9955
9956 for (i = 0; i < PCOUNT_MAX; i++)
9957 json_object_int_add(json_loop, pcount_strs[i],
9958 pcounts.count[i]);
9959
9960 json_object_object_add(json, "ribTableWalkCounters", json_loop);
9961
9962 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
9963 json_object_string_add(json, "pfxctDriftFor",
9964 peer->host);
9965 json_object_string_add(
9966 json, "recommended",
9967 "Please report this bug, with the above command output");
9968 }
996c9314
LB
9969 vty_out(vty, "%s\n", json_object_to_json_string_ext(
9970 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 9971 json_object_free(json);
9972 } else {
9973
9974 if (peer->hostname
9975 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
9976 vty_out(vty, "Prefix counts for %s/%s, %s\n",
9977 peer->hostname, peer->host,
9978 afi_safi_print(afi, safi));
9979 } else {
9980 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
9981 afi_safi_print(afi, safi));
9982 }
9983
9984 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
9985 vty_out(vty, "\nCounts from RIB table walk:\n\n");
9986
9987 for (i = 0; i < PCOUNT_MAX; i++)
9988 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
9989 pcounts.count[i]);
9990
9991 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
9992 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
9993 vty_out(vty,
9994 "Please report this bug, with the above command output\n");
9995 }
9996 }
9997
9998 return CMD_SUCCESS;
718e3744 9999}
10000
a636c635
DW
10001DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
10002 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 10003 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10004 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 10005 SHOW_STR
10006 IP_STR
10007 BGP_STR
8386ac43 10008 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
10009 BGP_AFI_HELP_STR
10010 BGP_SAFI_HELP_STR
0b16f239
DS
10011 "Detailed information on TCP and BGP neighbor connections\n"
10012 "Neighbor to display information about\n"
10013 "Neighbor to display information about\n"
91d37724 10014 "Neighbor on BGP configured interface\n"
a636c635 10015 "Display detailed prefix count information\n"
9973d184 10016 JSON_STR)
0b16f239 10017{
d62a17ae 10018 afi_t afi = AFI_IP6;
10019 safi_t safi = SAFI_UNICAST;
10020 struct peer *peer;
10021 int idx = 0;
10022 struct bgp *bgp = NULL;
9f049418
DS
10023 bool uj = use_json(argc, argv);
10024
10025 if (uj)
10026 argc--;
856ca177 10027
d62a17ae 10028 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10029 &bgp, uj);
d62a17ae 10030 if (!idx)
10031 return CMD_WARNING;
0b16f239 10032
d62a17ae 10033 argv_find(argv, argc, "neighbors", &idx);
10034 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
10035 if (!peer)
10036 return CMD_WARNING;
bb46e94f 10037
d62a17ae 10038 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 10039}
0b16f239 10040
d6902373
PG
10041#ifdef KEEP_OLD_VPN_COMMANDS
10042DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
10043 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
10044 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
10045 SHOW_STR
10046 IP_STR
10047 BGP_STR
d6902373 10048 BGP_VPNVX_HELP_STR
91d37724 10049 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
10050 "Detailed information on TCP and BGP neighbor connections\n"
10051 "Neighbor to display information about\n"
10052 "Neighbor to display information about\n"
91d37724 10053 "Neighbor on BGP configured interface\n"
a636c635 10054 "Display detailed prefix count information\n"
9973d184 10055 JSON_STR)
a636c635 10056{
d62a17ae 10057 int idx_peer = 6;
10058 struct peer *peer;
9f049418 10059 bool uj = use_json(argc, argv);
a636c635 10060
d62a17ae 10061 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
10062 if (!peer)
10063 return CMD_WARNING;
10064
10065 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
10066}
10067
d6902373
PG
10068DEFUN (show_ip_bgp_vpn_all_route_prefix,
10069 show_ip_bgp_vpn_all_route_prefix_cmd,
10070 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
10071 SHOW_STR
10072 IP_STR
10073 BGP_STR
d6902373 10074 BGP_VPNVX_HELP_STR
91d37724
QY
10075 "Display information about all VPNv4 NLRIs\n"
10076 "Network in the BGP routing table to display\n"
3a2d747c 10077 "Network in the BGP routing table to display\n"
9973d184 10078 JSON_STR)
91d37724 10079{
d62a17ae 10080 int idx = 0;
10081 char *network = NULL;
10082 struct bgp *bgp = bgp_get_default();
10083 if (!bgp) {
10084 vty_out(vty, "Can't find default instance\n");
10085 return CMD_WARNING;
10086 }
87e34b58 10087
d62a17ae 10088 if (argv_find(argv, argc, "A.B.C.D", &idx))
10089 network = argv[idx]->arg;
10090 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10091 network = argv[idx]->arg;
10092 else {
10093 vty_out(vty, "Unable to figure out Network\n");
10094 return CMD_WARNING;
10095 }
87e34b58 10096
d62a17ae 10097 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
10098 BGP_PATH_ALL, use_json(argc, argv));
91d37724 10099}
d6902373 10100#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 10101
4c63a661
PG
10102DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
10103 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
10104 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10105 SHOW_STR
10106 IP_STR
10107 BGP_STR
10108 L2VPN_HELP_STR
10109 EVPN_HELP_STR
10110 "Display information about all EVPN NLRIs\n"
10111 "Network in the BGP routing table to display\n"
10112 "Network in the BGP routing table to display\n"
10113 JSON_STR)
10114{
d62a17ae 10115 int idx = 0;
10116 char *network = NULL;
a636c635 10117
d62a17ae 10118 if (argv_find(argv, argc, "A.B.C.D", &idx))
10119 network = argv[idx]->arg;
10120 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
10121 network = argv[idx]->arg;
10122 else {
10123 vty_out(vty, "Unable to figure out Network\n");
10124 return CMD_WARNING;
10125 }
10126 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
10127 BGP_PATH_ALL, use_json(argc, argv));
10128}
10129
10130static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10131 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10132 const char *rmap_name, bool use_json,
6392aaa6 10133 json_object *json)
d62a17ae 10134{
10135 struct bgp_table *table;
10136 struct bgp_adj_in *ain;
10137 struct bgp_adj_out *adj;
10138 unsigned long output_count;
10139 unsigned long filtered_count;
10140 struct bgp_node *rn;
10141 int header1 = 1;
10142 struct bgp *bgp;
10143 int header2 = 1;
10144 struct attr attr;
10145 int ret;
10146 struct update_subgroup *subgrp;
10147 json_object *json_scode = NULL;
10148 json_object *json_ocode = NULL;
10149 json_object *json_ar = NULL;
10150 struct peer_af *paf;
f99def61 10151 bool route_filtered;
d62a17ae 10152
10153 if (use_json) {
10154 json_scode = json_object_new_object();
10155 json_ocode = json_object_new_object();
10156 json_ar = json_object_new_object();
10157
10158 json_object_string_add(json_scode, "suppressed", "s");
10159 json_object_string_add(json_scode, "damped", "d");
10160 json_object_string_add(json_scode, "history", "h");
10161 json_object_string_add(json_scode, "valid", "*");
10162 json_object_string_add(json_scode, "best", ">");
10163 json_object_string_add(json_scode, "multipath", "=");
10164 json_object_string_add(json_scode, "internal", "i");
10165 json_object_string_add(json_scode, "ribFailure", "r");
10166 json_object_string_add(json_scode, "stale", "S");
10167 json_object_string_add(json_scode, "removed", "R");
10168
10169 json_object_string_add(json_ocode, "igp", "i");
10170 json_object_string_add(json_ocode, "egp", "e");
10171 json_object_string_add(json_ocode, "incomplete", "?");
10172 }
a636c635 10173
d62a17ae 10174 bgp = peer->bgp;
a636c635 10175
d62a17ae 10176 if (!bgp) {
10177 if (use_json) {
10178 json_object_string_add(json, "alert", "no BGP");
10179 vty_out(vty, "%s\n", json_object_to_json_string(json));
10180 json_object_free(json);
10181 } else
10182 vty_out(vty, "%% No bgp\n");
10183 return;
10184 }
a636c635 10185
d62a17ae 10186 table = bgp->rib[afi][safi];
10187
10188 output_count = filtered_count = 0;
10189 subgrp = peer_subgroup(peer, afi, safi);
10190
6392aaa6 10191 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 10192 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
10193 if (use_json) {
10194 json_object_int_add(json, "bgpTableVersion",
10195 table->version);
10196 json_object_string_add(json, "bgpLocalRouterId",
10197 inet_ntoa(bgp->router_id));
10198 json_object_object_add(json, "bgpStatusCodes",
10199 json_scode);
10200 json_object_object_add(json, "bgpOriginCodes",
10201 json_ocode);
07d0c4ed
DA
10202 json_object_string_add(
10203 json, "bgpOriginatingDefaultNetwork",
10204 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10205 } else {
996c9314 10206 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 10207 ", local router ID is %s, vrf id ",
d62a17ae 10208 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
10209 if (bgp->vrf_id == VRF_UNKNOWN)
10210 vty_out(vty, "%s", VRFID_NONE_STR);
10211 else
10212 vty_out(vty, "%u", bgp->vrf_id);
10213 vty_out(vty, "\n");
d62a17ae 10214 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10215 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 10216 vty_out(vty, BGP_SHOW_OCODE_HEADER);
10217
07d0c4ed
DA
10218 vty_out(vty, "Originating default network %s\n\n",
10219 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 10220 }
10221 header1 = 0;
10222 }
a636c635 10223
d62a17ae 10224 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
10225 if (type == bgp_show_adj_route_received
10226 || type == bgp_show_adj_route_filtered) {
d62a17ae 10227 for (ain = rn->adj_in; ain; ain = ain->next) {
6392aaa6 10228 if (ain->peer != peer || !ain->attr)
ea47320b 10229 continue;
6392aaa6 10230
ea47320b
DL
10231 if (header1) {
10232 if (use_json) {
10233 json_object_int_add(
60466a63 10234 json, "bgpTableVersion",
ea47320b
DL
10235 0);
10236 json_object_string_add(
10237 json,
10238 "bgpLocalRouterId",
10239 inet_ntoa(
10240 bgp->router_id));
10241 json_object_object_add(
60466a63 10242 json, "bgpStatusCodes",
ea47320b
DL
10243 json_scode);
10244 json_object_object_add(
60466a63 10245 json, "bgpOriginCodes",
ea47320b
DL
10246 json_ocode);
10247 } else {
10248 vty_out(vty,
9df8b37c 10249 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 10250 inet_ntoa(
9df8b37c
PZ
10251 bgp->router_id));
10252 if (bgp->vrf_id == VRF_UNKNOWN)
10253 vty_out(vty, "%s",
10254 VRFID_NONE_STR);
10255 else
10256 vty_out(vty, "%u",
10257 bgp->vrf_id);
10258 vty_out(vty, "\n");
ea47320b
DL
10259 vty_out(vty,
10260 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10261 vty_out(vty,
10262 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
10263 vty_out(vty,
10264 BGP_SHOW_OCODE_HEADER);
d62a17ae 10265 }
ea47320b
DL
10266 header1 = 0;
10267 }
10268 if (header2) {
10269 if (!use_json)
10270 vty_out(vty, BGP_SHOW_HEADER);
10271 header2 = 0;
10272 }
6392aaa6
PM
10273
10274 bgp_attr_dup(&attr, ain->attr);
f99def61
AD
10275 route_filtered = false;
10276
10277 /* Filter prefix using distribute list,
10278 * filter list or prefix list
10279 */
10280 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
10281 safi)) == FILTER_DENY)
10282 route_filtered = true;
10283
10284 /* Filter prefix using route-map */
6392aaa6 10285 ret = bgp_input_modifier(peer, &rn->p, &attr,
13c8e163 10286 afi, safi, rmap_name);
6392aaa6 10287
13c8e163
AD
10288 if (type == bgp_show_adj_route_filtered &&
10289 !route_filtered && ret != RMAP_DENY) {
b755861b 10290 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10291 continue;
d62a17ae 10292 }
6392aaa6 10293
13c8e163
AD
10294 if (type == bgp_show_adj_route_received &&
10295 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
10296 filtered_count++;
10297
10298 route_vty_out_tmp(vty, &rn->p, &attr, safi,
10299 use_json, json_ar);
b755861b 10300 bgp_attr_undup(&attr, ain->attr);
6392aaa6 10301 output_count++;
d62a17ae 10302 }
6392aaa6 10303 } else if (type == bgp_show_adj_route_advertised) {
d62a17ae 10304 for (adj = rn->adj_out; adj; adj = adj->next)
924c3f6a 10305 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 10306 if (paf->peer != peer || !adj->attr)
924c3f6a 10307 continue;
d62a17ae 10308
924c3f6a
DS
10309 if (header1) {
10310 if (use_json) {
10311 json_object_int_add(
10312 json,
10313 "bgpTableVersion",
10314 table->version);
10315 json_object_string_add(
10316 json,
10317 "bgpLocalRouterId",
10318 inet_ntoa(
10319 bgp->router_id));
10320 json_object_object_add(
10321 json,
10322 "bgpStatusCodes",
10323 json_scode);
10324 json_object_object_add(
10325 json,
10326 "bgpOriginCodes",
10327 json_ocode);
10328 } else {
10329 vty_out(vty,
10330 "BGP table version is %" PRIu64
9df8b37c 10331 ", local router ID is %s, vrf id ",
924c3f6a
DS
10332 table->version,
10333 inet_ntoa(
10334 bgp->router_id));
9df8b37c
PZ
10335 if (bgp->vrf_id ==
10336 VRF_UNKNOWN)
10337 vty_out(vty,
10338 "%s",
10339 VRFID_NONE_STR);
10340 else
10341 vty_out(vty,
10342 "%u",
10343 bgp->vrf_id);
10344 vty_out(vty, "\n");
924c3f6a
DS
10345 vty_out(vty,
10346 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
10347 vty_out(vty,
10348 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
10349 vty_out(vty,
10350 BGP_SHOW_OCODE_HEADER);
a2addae8 10351 }
924c3f6a
DS
10352 header1 = 0;
10353 }
924c3f6a
DS
10354 if (header2) {
10355 if (!use_json)
10356 vty_out(vty,
10357 BGP_SHOW_HEADER);
10358 header2 = 0;
10359 }
d62a17ae 10360
b755861b
PM
10361 bgp_attr_dup(&attr, adj->attr);
10362 ret = bgp_output_modifier(
10363 peer, &rn->p, &attr, afi, safi,
10364 rmap_name);
f46d8e1e 10365
b755861b
PM
10366 if (ret != RMAP_DENY) {
10367 route_vty_out_tmp(vty, &rn->p,
10368 &attr, safi,
10369 use_json,
10370 json_ar);
10371 output_count++;
10372 } else {
10373 filtered_count++;
a2addae8 10374 }
b755861b
PM
10375
10376 bgp_attr_undup(&attr, adj->attr);
924c3f6a 10377 }
d62a17ae 10378 }
10379 }
d62a17ae 10380
d62a17ae 10381 if (use_json) {
6392aaa6
PM
10382 json_object_object_add(json, "advertisedRoutes", json_ar);
10383 json_object_int_add(json, "totalPrefixCounter", output_count);
10384 json_object_int_add(json, "filteredPrefixCounter",
10385 filtered_count);
10386
996c9314
LB
10387 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10388 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 10389 json_object_free(json);
6392aaa6
PM
10390 } else if (output_count > 0) {
10391 if (filtered_count > 0)
10392 vty_out(vty,
10393 "\nTotal number of prefixes %ld (%ld filtered)\n",
10394 output_count, filtered_count);
10395 else
10396 vty_out(vty, "\nTotal number of prefixes %ld\n",
10397 output_count);
d62a17ae 10398 }
a636c635 10399}
2a71e9ce 10400
d62a17ae 10401static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 10402 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 10403 const char *rmap_name, bool use_json)
0b16f239 10404{
d62a17ae 10405 json_object *json = NULL;
0b16f239 10406
d62a17ae 10407 if (use_json)
10408 json = json_object_new_object();
0b16f239 10409
d62a17ae 10410 /* labeled-unicast routes live in the unicast table */
10411 if (safi == SAFI_LABELED_UNICAST)
10412 safi = SAFI_UNICAST;
4dd6177e 10413
d62a17ae 10414 if (!peer || !peer->afc[afi][safi]) {
10415 if (use_json) {
10416 json_object_string_add(
10417 json, "warning",
10418 "No such neighbor or address family");
10419 vty_out(vty, "%s\n", json_object_to_json_string(json));
10420 json_object_free(json);
10421 } else
10422 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10423
d62a17ae 10424 return CMD_WARNING;
10425 }
10426
6392aaa6
PM
10427 if ((type == bgp_show_adj_route_received
10428 || type == bgp_show_adj_route_filtered)
d62a17ae 10429 && !CHECK_FLAG(peer->af_flags[afi][safi],
10430 PEER_FLAG_SOFT_RECONFIG)) {
10431 if (use_json) {
10432 json_object_string_add(
10433 json, "warning",
10434 "Inbound soft reconfiguration not enabled");
10435 vty_out(vty, "%s\n", json_object_to_json_string(json));
10436 json_object_free(json);
10437 } else
10438 vty_out(vty,
10439 "%% Inbound soft reconfiguration not enabled\n");
10440
10441 return CMD_WARNING;
10442 }
0b16f239 10443
6392aaa6 10444 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 10445
d62a17ae 10446 return CMD_SUCCESS;
a636c635 10447}
50ef26d4 10448
a636c635
DW
10449DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10450 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10451 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 10452 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 10453 SHOW_STR
10454 IP_STR
10455 BGP_STR
a636c635 10456 BGP_INSTANCE_HELP_STR
7395a2c9 10457 BGP_AFI_HELP_STR
4dd6177e 10458 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10459 "Detailed information on TCP and BGP neighbor connections\n"
10460 "Neighbor to display information about\n"
10461 "Neighbor to display information about\n"
91d37724 10462 "Neighbor on BGP configured interface\n"
a636c635 10463 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
10464 "Display the received routes from neighbor\n"
10465 "Display the filtered routes received from neighbor\n"
a636c635
DW
10466 "Route-map to modify the attributes\n"
10467 "Name of the route map\n"
9973d184 10468 JSON_STR)
718e3744 10469{
d62a17ae 10470 afi_t afi = AFI_IP6;
10471 safi_t safi = SAFI_UNICAST;
10472 char *rmap_name = NULL;
10473 char *peerstr = NULL;
d62a17ae 10474 struct bgp *bgp = NULL;
10475 struct peer *peer;
6392aaa6 10476 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 10477 int idx = 0;
9f049418 10478 bool uj = use_json(argc, argv);
6392aaa6 10479
d62a17ae 10480 if (uj)
10481 argc--;
30a6a167 10482
9f049418
DS
10483 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10484 &bgp, uj);
10485 if (!idx)
10486 return CMD_WARNING;
10487
d62a17ae 10488 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10489 argv_find(argv, argc, "neighbors", &idx);
10490 peerstr = argv[++idx]->arg;
8c3deaae 10491
d62a17ae 10492 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10493 if (!peer)
10494 return CMD_WARNING;
856ca177 10495
d62a17ae 10496 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
10497 type = bgp_show_adj_route_advertised;
10498 else if (argv_find(argv, argc, "received-routes", &idx))
10499 type = bgp_show_adj_route_received;
10500 else if (argv_find(argv, argc, "filtered-routes", &idx))
10501 type = bgp_show_adj_route_filtered;
10502
d62a17ae 10503 if (argv_find(argv, argc, "route-map", &idx))
10504 rmap_name = argv[++idx]->arg;
95cbbd2a 10505
6392aaa6 10506 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
10507}
10508
718e3744 10509DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10510 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10511 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10512 SHOW_STR
10513 IP_STR
10514 BGP_STR
8c3deaae
QY
10515 "Address Family\n"
10516 "Address Family\n"
718e3744 10517 "Address Family modifier\n"
10518 "Detailed information on TCP and BGP neighbor connections\n"
10519 "Neighbor to display information about\n"
10520 "Neighbor to display information about\n"
91d37724 10521 "Neighbor on BGP configured interface\n"
718e3744 10522 "Display information received from a BGP neighbor\n"
856ca177 10523 "Display the prefixlist filter\n"
9973d184 10524 JSON_STR)
718e3744 10525{
d62a17ae 10526 afi_t afi = AFI_IP6;
10527 safi_t safi = SAFI_UNICAST;
10528 char *peerstr = NULL;
10529
10530 char name[BUFSIZ];
10531 union sockunion su;
10532 struct peer *peer;
10533 int count, ret;
10534
10535 int idx = 0;
10536
10537 /* show [ip] bgp */
10538 if (argv_find(argv, argc, "ip", &idx))
10539 afi = AFI_IP;
10540 /* [<ipv4|ipv6> [unicast]] */
10541 if (argv_find(argv, argc, "ipv4", &idx))
10542 afi = AFI_IP;
10543 if (argv_find(argv, argc, "ipv6", &idx))
10544 afi = AFI_IP6;
10545 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10546 argv_find(argv, argc, "neighbors", &idx);
10547 peerstr = argv[++idx]->arg;
10548
9f049418 10549 bool uj = use_json(argc, argv);
d62a17ae 10550
10551 ret = str2sockunion(peerstr, &su);
10552 if (ret < 0) {
10553 peer = peer_lookup_by_conf_if(NULL, peerstr);
10554 if (!peer) {
10555 if (uj)
10556 vty_out(vty, "{}\n");
10557 else
10558 vty_out(vty,
10559 "%% Malformed address or name: %s\n",
10560 peerstr);
10561 return CMD_WARNING;
10562 }
10563 } else {
10564 peer = peer_lookup(NULL, &su);
10565 if (!peer) {
10566 if (uj)
10567 vty_out(vty, "{}\n");
10568 else
10569 vty_out(vty, "No peer\n");
10570 return CMD_WARNING;
10571 }
10572 }
718e3744 10573
d62a17ae 10574 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10575 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10576 if (count) {
10577 if (!uj)
10578 vty_out(vty, "Address Family: %s\n",
10579 afi_safi_print(afi, safi));
10580 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10581 } else {
10582 if (uj)
10583 vty_out(vty, "{}\n");
10584 else
10585 vty_out(vty, "No functional output\n");
10586 }
718e3744 10587
d62a17ae 10588 return CMD_SUCCESS;
10589}
10590
10591static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10592 afi_t afi, safi_t safi,
9f049418 10593 enum bgp_show_type type, bool use_json)
d62a17ae 10594{
8a893163
DW
10595 /* labeled-unicast routes live in the unicast table */
10596 if (safi == SAFI_LABELED_UNICAST)
10597 safi = SAFI_UNICAST;
10598
d62a17ae 10599 if (!peer || !peer->afc[afi][safi]) {
10600 if (use_json) {
10601 json_object *json_no = NULL;
10602 json_no = json_object_new_object();
10603 json_object_string_add(
10604 json_no, "warning",
10605 "No such neighbor or address family");
10606 vty_out(vty, "%s\n",
10607 json_object_to_json_string(json_no));
10608 json_object_free(json_no);
10609 } else
10610 vty_out(vty, "%% No such neighbor or address family\n");
10611 return CMD_WARNING;
10612 }
47fc97cc 10613
d62a17ae 10614 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10615}
10616
dba3c1d3
PG
10617DEFUN (show_ip_bgp_flowspec_routes_detailed,
10618 show_ip_bgp_flowspec_routes_detailed_cmd,
10619 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
10620 SHOW_STR
10621 IP_STR
10622 BGP_STR
10623 BGP_INSTANCE_HELP_STR
10624 BGP_AFI_HELP_STR
10625 "SAFI Flowspec\n"
10626 "Detailed information on flowspec entries\n"
10627 JSON_STR)
10628{
10629 afi_t afi = AFI_IP;
10630 safi_t safi = SAFI_UNICAST;
10631 struct bgp *bgp = NULL;
10632 int idx = 0;
9f049418
DS
10633 bool uj = use_json(argc, argv);
10634
10635 if (uj)
10636 argc--;
dba3c1d3
PG
10637
10638 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10639 &bgp, uj);
dba3c1d3
PG
10640 if (!idx)
10641 return CMD_WARNING;
10642
9f049418 10643 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
10644}
10645
718e3744 10646DEFUN (show_ip_bgp_neighbor_routes,
10647 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10648 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10649 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10650 SHOW_STR
10651 IP_STR
10652 BGP_STR
8386ac43 10653 BGP_INSTANCE_HELP_STR
4f280b15 10654 BGP_AFI_HELP_STR
4dd6177e 10655 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10656 "Detailed information on TCP and BGP neighbor connections\n"
10657 "Neighbor to display information about\n"
10658 "Neighbor to display information about\n"
91d37724 10659 "Neighbor on BGP configured interface\n"
2525cf39 10660 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10661 "Display the dampened routes received from neighbor\n"
10662 "Display routes learned from neighbor\n"
9973d184 10663 JSON_STR)
718e3744 10664{
d62a17ae 10665 char *peerstr = NULL;
10666 struct bgp *bgp = NULL;
10667 afi_t afi = AFI_IP6;
10668 safi_t safi = SAFI_UNICAST;
10669 struct peer *peer;
10670 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 10671 int idx = 0;
9f049418
DS
10672 bool uj = use_json(argc, argv);
10673
10674 if (uj)
10675 argc--;
bb46e94f 10676
d62a17ae 10677 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10678 &bgp, uj);
d62a17ae 10679 if (!idx)
10680 return CMD_WARNING;
c493f2d8 10681
d62a17ae 10682 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10683 argv_find(argv, argc, "neighbors", &idx);
10684 peerstr = argv[++idx]->arg;
8c3deaae 10685
d62a17ae 10686 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 10687 if (!peer)
d62a17ae 10688 return CMD_WARNING;
bb46e94f 10689
d62a17ae 10690 if (argv_find(argv, argc, "flap-statistics", &idx))
10691 sh_type = bgp_show_type_flap_neighbor;
10692 else if (argv_find(argv, argc, "dampened-routes", &idx))
10693 sh_type = bgp_show_type_damp_neighbor;
10694 else if (argv_find(argv, argc, "routes", &idx))
10695 sh_type = bgp_show_type_neighbor;
2525cf39 10696
d62a17ae 10697 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 10698}
6b0655a2 10699
734b349e 10700struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10701
d62a17ae 10702struct bgp_distance {
10703 /* Distance value for the IP source prefix. */
d7c0a89a 10704 uint8_t distance;
718e3744 10705
d62a17ae 10706 /* Name of the access-list to be matched. */
10707 char *access_list;
718e3744 10708};
10709
4f280b15
LB
10710DEFUN (show_bgp_afi_vpn_rd_route,
10711 show_bgp_afi_vpn_rd_route_cmd,
d114b977 10712 "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
10713 SHOW_STR
10714 BGP_STR
10715 BGP_AFI_HELP_STR
10716 "Address Family modifier\n"
10717 "Display information for a route distinguisher\n"
10718 "Route Distinguisher\n"
7395a2c9
DS
10719 "Network in the BGP routing table to display\n"
10720 "Network in the BGP routing table to display\n"
10721 JSON_STR)
4f280b15 10722{
d62a17ae 10723 int ret;
10724 struct prefix_rd prd;
10725 afi_t afi = AFI_MAX;
10726 int idx = 0;
4f280b15 10727
ff6566f3
DS
10728 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
10729 vty_out(vty, "%% Malformed Address Family\n");
10730 return CMD_WARNING;
10731 }
10732
d62a17ae 10733 ret = str2prefix_rd(argv[5]->arg, &prd);
10734 if (!ret) {
10735 vty_out(vty, "%% Malformed Route Distinguisher\n");
10736 return CMD_WARNING;
10737 }
ff6566f3 10738
d62a17ae 10739 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
10740 0, BGP_PATH_ALL, use_json(argc, argv));
4f280b15
LB
10741}
10742
d62a17ae 10743static struct bgp_distance *bgp_distance_new(void)
718e3744 10744{
d62a17ae 10745 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 10746}
10747
d62a17ae 10748static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 10749{
d62a17ae 10750 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 10751}
10752
d62a17ae 10753static int bgp_distance_set(struct vty *vty, const char *distance_str,
10754 const char *ip_str, const char *access_list_str)
718e3744 10755{
d62a17ae 10756 int ret;
10757 afi_t afi;
10758 safi_t safi;
10759 struct prefix p;
d7c0a89a 10760 uint8_t distance;
d62a17ae 10761 struct bgp_node *rn;
10762 struct bgp_distance *bdistance;
718e3744 10763
d62a17ae 10764 afi = bgp_node_afi(vty);
10765 safi = bgp_node_safi(vty);
734b349e 10766
d62a17ae 10767 ret = str2prefix(ip_str, &p);
10768 if (ret == 0) {
10769 vty_out(vty, "Malformed prefix\n");
10770 return CMD_WARNING_CONFIG_FAILED;
10771 }
718e3744 10772
d62a17ae 10773 distance = atoi(distance_str);
718e3744 10774
d62a17ae 10775 /* Get BGP distance node. */
10776 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
ca2e160d
DS
10777 bdistance = bgp_distance_get_node(rn);
10778 if (bdistance)
d62a17ae 10779 bgp_unlock_node(rn);
ca2e160d 10780 else {
d62a17ae 10781 bdistance = bgp_distance_new();
a78beeb5 10782 bgp_distance_set_node_info(rn, bdistance);
d62a17ae 10783 }
718e3744 10784
d62a17ae 10785 /* Set distance value. */
10786 bdistance->distance = distance;
718e3744 10787
d62a17ae 10788 /* Reset access-list configuration. */
10789 if (bdistance->access_list) {
10790 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10791 bdistance->access_list = NULL;
10792 }
10793 if (access_list_str)
10794 bdistance->access_list =
10795 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 10796
d62a17ae 10797 return CMD_SUCCESS;
718e3744 10798}
10799
d62a17ae 10800static int bgp_distance_unset(struct vty *vty, const char *distance_str,
10801 const char *ip_str, const char *access_list_str)
718e3744 10802{
d62a17ae 10803 int ret;
10804 afi_t afi;
10805 safi_t safi;
10806 struct prefix p;
10807 int distance;
10808 struct bgp_node *rn;
10809 struct bgp_distance *bdistance;
718e3744 10810
d62a17ae 10811 afi = bgp_node_afi(vty);
10812 safi = bgp_node_safi(vty);
734b349e 10813
d62a17ae 10814 ret = str2prefix(ip_str, &p);
10815 if (ret == 0) {
10816 vty_out(vty, "Malformed prefix\n");
10817 return CMD_WARNING_CONFIG_FAILED;
10818 }
718e3744 10819
d62a17ae 10820 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
10821 (struct prefix *)&p);
10822 if (!rn) {
10823 vty_out(vty, "Can't find specified prefix\n");
10824 return CMD_WARNING_CONFIG_FAILED;
10825 }
718e3744 10826
ca2e160d 10827 bdistance = bgp_distance_get_node(rn);
d62a17ae 10828 distance = atoi(distance_str);
1f9a9fff 10829
d62a17ae 10830 if (bdistance->distance != distance) {
10831 vty_out(vty, "Distance does not match configured\n");
10832 return CMD_WARNING_CONFIG_FAILED;
10833 }
718e3744 10834
d62a17ae 10835 if (bdistance->access_list)
10836 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10837 bgp_distance_free(bdistance);
718e3744 10838
d62a17ae 10839 rn->info = NULL;
10840 bgp_unlock_node(rn);
10841 bgp_unlock_node(rn);
718e3744 10842
d62a17ae 10843 return CMD_SUCCESS;
718e3744 10844}
10845
718e3744 10846/* Apply BGP information to distance method. */
d7c0a89a
QY
10847uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
10848 safi_t safi, struct bgp *bgp)
d62a17ae 10849{
10850 struct bgp_node *rn;
10851 struct prefix q;
10852 struct peer *peer;
10853 struct bgp_distance *bdistance;
10854 struct access_list *alist;
10855 struct bgp_static *bgp_static;
10856
10857 if (!bgp)
10858 return 0;
10859
10860 peer = rinfo->peer;
10861
10862 /* Check source address. */
10863 sockunion2hostprefix(&peer->su, &q);
10864 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
10865 if (rn) {
ca2e160d 10866 bdistance = bgp_distance_get_node(rn);
d62a17ae 10867 bgp_unlock_node(rn);
10868
10869 if (bdistance->access_list) {
10870 alist = access_list_lookup(afi, bdistance->access_list);
10871 if (alist
10872 && access_list_apply(alist, p) == FILTER_PERMIT)
10873 return bdistance->distance;
10874 } else
10875 return bdistance->distance;
718e3744 10876 }
718e3744 10877
d62a17ae 10878 /* Backdoor check. */
10879 rn = bgp_node_lookup(bgp->route[afi][safi], p);
10880 if (rn) {
a78beeb5 10881 bgp_static = bgp_static_get_node_info(rn);
d62a17ae 10882 bgp_unlock_node(rn);
718e3744 10883
d62a17ae 10884 if (bgp_static->backdoor) {
10885 if (bgp->distance_local[afi][safi])
10886 return bgp->distance_local[afi][safi];
10887 else
10888 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10889 }
718e3744 10890 }
718e3744 10891
d62a17ae 10892 if (peer->sort == BGP_PEER_EBGP) {
10893 if (bgp->distance_ebgp[afi][safi])
10894 return bgp->distance_ebgp[afi][safi];
10895 return ZEBRA_EBGP_DISTANCE_DEFAULT;
10896 } else {
10897 if (bgp->distance_ibgp[afi][safi])
10898 return bgp->distance_ibgp[afi][safi];
10899 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10900 }
718e3744 10901}
10902
10903DEFUN (bgp_distance,
10904 bgp_distance_cmd,
6147e2c6 10905 "distance bgp (1-255) (1-255) (1-255)",
718e3744 10906 "Define an administrative distance\n"
10907 "BGP distance\n"
10908 "Distance for routes external to the AS\n"
10909 "Distance for routes internal to the AS\n"
10910 "Distance for local routes\n")
10911{
d62a17ae 10912 VTY_DECLVAR_CONTEXT(bgp, bgp);
10913 int idx_number = 2;
10914 int idx_number_2 = 3;
10915 int idx_number_3 = 4;
10916 afi_t afi;
10917 safi_t safi;
718e3744 10918
d62a17ae 10919 afi = bgp_node_afi(vty);
10920 safi = bgp_node_safi(vty);
718e3744 10921
d62a17ae 10922 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
10923 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
10924 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
10925 return CMD_SUCCESS;
718e3744 10926}
10927
10928DEFUN (no_bgp_distance,
10929 no_bgp_distance_cmd,
a636c635 10930 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 10931 NO_STR
10932 "Define an administrative distance\n"
10933 "BGP distance\n"
10934 "Distance for routes external to the AS\n"
10935 "Distance for routes internal to the AS\n"
10936 "Distance for local routes\n")
10937{
d62a17ae 10938 VTY_DECLVAR_CONTEXT(bgp, bgp);
10939 afi_t afi;
10940 safi_t safi;
718e3744 10941
d62a17ae 10942 afi = bgp_node_afi(vty);
10943 safi = bgp_node_safi(vty);
718e3744 10944
d62a17ae 10945 bgp->distance_ebgp[afi][safi] = 0;
10946 bgp->distance_ibgp[afi][safi] = 0;
10947 bgp->distance_local[afi][safi] = 0;
10948 return CMD_SUCCESS;
718e3744 10949}
10950
718e3744 10951
10952DEFUN (bgp_distance_source,
10953 bgp_distance_source_cmd,
6147e2c6 10954 "distance (1-255) A.B.C.D/M",
718e3744 10955 "Define an administrative distance\n"
10956 "Administrative distance\n"
10957 "IP source prefix\n")
10958{
d62a17ae 10959 int idx_number = 1;
10960 int idx_ipv4_prefixlen = 2;
10961 bgp_distance_set(vty, argv[idx_number]->arg,
10962 argv[idx_ipv4_prefixlen]->arg, NULL);
10963 return CMD_SUCCESS;
718e3744 10964}
10965
10966DEFUN (no_bgp_distance_source,
10967 no_bgp_distance_source_cmd,
6147e2c6 10968 "no distance (1-255) A.B.C.D/M",
718e3744 10969 NO_STR
10970 "Define an administrative distance\n"
10971 "Administrative distance\n"
10972 "IP source prefix\n")
10973{
d62a17ae 10974 int idx_number = 2;
10975 int idx_ipv4_prefixlen = 3;
10976 bgp_distance_unset(vty, argv[idx_number]->arg,
10977 argv[idx_ipv4_prefixlen]->arg, NULL);
10978 return CMD_SUCCESS;
718e3744 10979}
10980
10981DEFUN (bgp_distance_source_access_list,
10982 bgp_distance_source_access_list_cmd,
6147e2c6 10983 "distance (1-255) A.B.C.D/M WORD",
718e3744 10984 "Define an administrative distance\n"
10985 "Administrative distance\n"
10986 "IP source prefix\n"
10987 "Access list name\n")
10988{
d62a17ae 10989 int idx_number = 1;
10990 int idx_ipv4_prefixlen = 2;
10991 int idx_word = 3;
10992 bgp_distance_set(vty, argv[idx_number]->arg,
10993 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
10994 return CMD_SUCCESS;
718e3744 10995}
10996
10997DEFUN (no_bgp_distance_source_access_list,
10998 no_bgp_distance_source_access_list_cmd,
6147e2c6 10999 "no distance (1-255) A.B.C.D/M WORD",
718e3744 11000 NO_STR
11001 "Define an administrative distance\n"
11002 "Administrative distance\n"
11003 "IP source prefix\n"
11004 "Access list name\n")
11005{
d62a17ae 11006 int idx_number = 2;
11007 int idx_ipv4_prefixlen = 3;
11008 int idx_word = 4;
11009 bgp_distance_unset(vty, argv[idx_number]->arg,
11010 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
11011 return CMD_SUCCESS;
718e3744 11012}
6b0655a2 11013
734b349e
MZ
11014DEFUN (ipv6_bgp_distance_source,
11015 ipv6_bgp_distance_source_cmd,
39e92c06 11016 "distance (1-255) X:X::X:X/M",
734b349e
MZ
11017 "Define an administrative distance\n"
11018 "Administrative distance\n"
11019 "IP source prefix\n")
11020{
d62a17ae 11021 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
11022 return CMD_SUCCESS;
734b349e
MZ
11023}
11024
11025DEFUN (no_ipv6_bgp_distance_source,
11026 no_ipv6_bgp_distance_source_cmd,
39e92c06 11027 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
11028 NO_STR
11029 "Define an administrative distance\n"
11030 "Administrative distance\n"
11031 "IP source prefix\n")
11032{
d62a17ae 11033 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
11034 return CMD_SUCCESS;
734b349e
MZ
11035}
11036
11037DEFUN (ipv6_bgp_distance_source_access_list,
11038 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11039 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11040 "Define an administrative distance\n"
11041 "Administrative distance\n"
11042 "IP source prefix\n"
11043 "Access list name\n")
11044{
d62a17ae 11045 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
11046 return CMD_SUCCESS;
734b349e
MZ
11047}
11048
11049DEFUN (no_ipv6_bgp_distance_source_access_list,
11050 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 11051 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
11052 NO_STR
11053 "Define an administrative distance\n"
11054 "Administrative distance\n"
11055 "IP source prefix\n"
11056 "Access list name\n")
11057{
d62a17ae 11058 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
11059 return CMD_SUCCESS;
734b349e
MZ
11060}
11061
718e3744 11062DEFUN (bgp_damp_set,
11063 bgp_damp_set_cmd,
31500417 11064 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11065 "BGP Specific commands\n"
11066 "Enable route-flap dampening\n"
11067 "Half-life time for the penalty\n"
11068 "Value to start reusing a route\n"
11069 "Value to start suppressing a route\n"
11070 "Maximum duration to suppress a stable route\n")
11071{
d62a17ae 11072 VTY_DECLVAR_CONTEXT(bgp, bgp);
11073 int idx_half_life = 2;
11074 int idx_reuse = 3;
11075 int idx_suppress = 4;
11076 int idx_max_suppress = 5;
11077 int half = DEFAULT_HALF_LIFE * 60;
11078 int reuse = DEFAULT_REUSE;
11079 int suppress = DEFAULT_SUPPRESS;
11080 int max = 4 * half;
11081
11082 if (argc == 6) {
11083 half = atoi(argv[idx_half_life]->arg) * 60;
11084 reuse = atoi(argv[idx_reuse]->arg);
11085 suppress = atoi(argv[idx_suppress]->arg);
11086 max = atoi(argv[idx_max_suppress]->arg) * 60;
11087 } else if (argc == 3) {
11088 half = atoi(argv[idx_half_life]->arg) * 60;
11089 max = 4 * half;
11090 }
718e3744 11091
d62a17ae 11092 if (suppress < reuse) {
11093 vty_out(vty,
11094 "Suppress value cannot be less than reuse value \n");
11095 return 0;
11096 }
7ebe9748 11097
d62a17ae 11098 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
11099 reuse, suppress, max);
718e3744 11100}
11101
718e3744 11102DEFUN (bgp_damp_unset,
11103 bgp_damp_unset_cmd,
d04c479d 11104 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 11105 NO_STR
11106 "BGP Specific commands\n"
16cedbb0
QY
11107 "Enable route-flap dampening\n"
11108 "Half-life time for the penalty\n"
11109 "Value to start reusing a route\n"
11110 "Value to start suppressing a route\n"
11111 "Maximum duration to suppress a stable route\n")
718e3744 11112{
d62a17ae 11113 VTY_DECLVAR_CONTEXT(bgp, bgp);
11114 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 11115}
11116
718e3744 11117/* Display specified route of BGP table. */
d62a17ae 11118static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
11119 const char *ip_str, afi_t afi, safi_t safi,
11120 struct prefix_rd *prd, int prefix_check)
11121{
11122 int ret;
11123 struct prefix match;
11124 struct bgp_node *rn;
11125 struct bgp_node *rm;
11126 struct bgp_info *ri;
11127 struct bgp_info *ri_temp;
11128 struct bgp *bgp;
11129 struct bgp_table *table;
11130
11131 /* BGP structure lookup. */
11132 if (view_name) {
11133 bgp = bgp_lookup_by_name(view_name);
11134 if (bgp == NULL) {
11135 vty_out(vty, "%% Can't find BGP instance %s\n",
11136 view_name);
11137 return CMD_WARNING;
11138 }
11139 } else {
11140 bgp = bgp_get_default();
11141 if (bgp == NULL) {
11142 vty_out(vty, "%% No BGP process is configured\n");
11143 return CMD_WARNING;
11144 }
718e3744 11145 }
718e3744 11146
d62a17ae 11147 /* Check IP address argument. */
11148 ret = str2prefix(ip_str, &match);
11149 if (!ret) {
11150 vty_out(vty, "%% address is malformed\n");
11151 return CMD_WARNING;
11152 }
718e3744 11153
d62a17ae 11154 match.family = afi2family(afi);
11155
11156 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
11157 || (safi == SAFI_EVPN)) {
11158 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11159 rn = bgp_route_next(rn)) {
11160 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11161 continue;
ea47320b
DL
11162 if ((table = rn->info) == NULL)
11163 continue;
11164 if ((rm = bgp_node_match(table, &match)) == NULL)
11165 continue;
d62a17ae 11166
ea47320b
DL
11167 if (!prefix_check
11168 || rm->p.prefixlen == match.prefixlen) {
11169 ri = rm->info;
11170 while (ri) {
60466a63 11171 if (ri->extra && ri->extra->damp_info) {
ea47320b
DL
11172 ri_temp = ri->next;
11173 bgp_damp_info_free(
60466a63
QY
11174 ri->extra->damp_info,
11175 1);
ea47320b
DL
11176 ri = ri_temp;
11177 } else
11178 ri = ri->next;
d62a17ae 11179 }
ea47320b
DL
11180 }
11181
11182 bgp_unlock_node(rm);
d62a17ae 11183 }
11184 } else {
11185 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11186 != NULL) {
11187 if (!prefix_check
11188 || rn->p.prefixlen == match.prefixlen) {
11189 ri = rn->info;
11190 while (ri) {
11191 if (ri->extra && ri->extra->damp_info) {
11192 ri_temp = ri->next;
11193 bgp_damp_info_free(
11194 ri->extra->damp_info,
11195 1);
11196 ri = ri_temp;
11197 } else
11198 ri = ri->next;
11199 }
11200 }
11201
11202 bgp_unlock_node(rn);
11203 }
11204 }
718e3744 11205
d62a17ae 11206 return CMD_SUCCESS;
718e3744 11207}
11208
11209DEFUN (clear_ip_bgp_dampening,
11210 clear_ip_bgp_dampening_cmd,
11211 "clear ip bgp dampening",
11212 CLEAR_STR
11213 IP_STR
11214 BGP_STR
11215 "Clear route flap dampening information\n")
11216{
d62a17ae 11217 bgp_damp_info_clean();
11218 return CMD_SUCCESS;
718e3744 11219}
11220
11221DEFUN (clear_ip_bgp_dampening_prefix,
11222 clear_ip_bgp_dampening_prefix_cmd,
11223 "clear ip bgp dampening A.B.C.D/M",
11224 CLEAR_STR
11225 IP_STR
11226 BGP_STR
11227 "Clear route flap dampening information\n"
0c7b1b01 11228 "IPv4 prefix\n")
718e3744 11229{
d62a17ae 11230 int idx_ipv4_prefixlen = 4;
11231 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11232 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11233}
11234
11235DEFUN (clear_ip_bgp_dampening_address,
11236 clear_ip_bgp_dampening_address_cmd,
11237 "clear ip bgp dampening A.B.C.D",
11238 CLEAR_STR
11239 IP_STR
11240 BGP_STR
11241 "Clear route flap dampening information\n"
11242 "Network to clear damping information\n")
11243{
d62a17ae 11244 int idx_ipv4 = 4;
11245 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11246 SAFI_UNICAST, NULL, 0);
718e3744 11247}
11248
11249DEFUN (clear_ip_bgp_dampening_address_mask,
11250 clear_ip_bgp_dampening_address_mask_cmd,
11251 "clear ip bgp dampening A.B.C.D A.B.C.D",
11252 CLEAR_STR
11253 IP_STR
11254 BGP_STR
11255 "Clear route flap dampening information\n"
11256 "Network to clear damping information\n"
11257 "Network mask\n")
11258{
d62a17ae 11259 int idx_ipv4 = 4;
11260 int idx_ipv4_2 = 5;
11261 int ret;
11262 char prefix_str[BUFSIZ];
718e3744 11263
d62a17ae 11264 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11265 prefix_str);
11266 if (!ret) {
11267 vty_out(vty, "%% Inconsistent address and mask\n");
11268 return CMD_WARNING;
11269 }
718e3744 11270
d62a17ae 11271 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11272 NULL, 0);
718e3744 11273}
6b0655a2 11274
587ff0fd 11275/* also used for encap safi */
2b791107
DL
11276static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11277 afi_t afi, safi_t safi)
d62a17ae 11278{
11279 struct bgp_node *prn;
11280 struct bgp_node *rn;
11281 struct bgp_table *table;
11282 struct prefix *p;
11283 struct prefix_rd *prd;
11284 struct bgp_static *bgp_static;
11285 mpls_label_t label;
11286 char buf[SU_ADDRSTRLEN];
11287 char rdbuf[RD_ADDRSTRLEN];
11288
11289 /* Network configuration. */
11290 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11291 prn = bgp_route_next(prn)) {
11292 if ((table = prn->info) == NULL)
11293 continue;
d62a17ae 11294
60466a63 11295 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
a78beeb5
DS
11296 bgp_static = bgp_static_get_node_info(rn);
11297 if (bgp_static == NULL)
ea47320b 11298 continue;
d62a17ae 11299
ea47320b
DL
11300 p = &rn->p;
11301 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11302
ea47320b 11303 /* "network" configuration display. */
06b9f471 11304 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11305 label = decode_label(&bgp_static->label);
11306
11307 vty_out(vty, " network %s/%d rd %s",
11308 inet_ntop(p->family, &p->u.prefix, buf,
11309 SU_ADDRSTRLEN),
11310 p->prefixlen, rdbuf);
11311 if (safi == SAFI_MPLS_VPN)
11312 vty_out(vty, " label %u", label);
11313
11314 if (bgp_static->rmap.name)
11315 vty_out(vty, " route-map %s",
11316 bgp_static->rmap.name);
e2a86ad9
DS
11317
11318 if (bgp_static->backdoor)
11319 vty_out(vty, " backdoor");
11320
ea47320b
DL
11321 vty_out(vty, "\n");
11322 }
11323 }
d62a17ae 11324}
11325
2b791107
DL
11326static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11327 afi_t afi, safi_t safi)
d62a17ae 11328{
11329 struct bgp_node *prn;
11330 struct bgp_node *rn;
11331 struct bgp_table *table;
11332 struct prefix *p;
11333 struct prefix_rd *prd;
11334 struct bgp_static *bgp_static;
ff44f570 11335 char buf[PREFIX_STRLEN * 2];
d62a17ae 11336 char buf2[SU_ADDRSTRLEN];
11337 char rdbuf[RD_ADDRSTRLEN];
11338
11339 /* Network configuration. */
11340 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11341 prn = bgp_route_next(prn)) {
11342 if ((table = prn->info) == NULL)
11343 continue;
d62a17ae 11344
60466a63 11345 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
a78beeb5
DS
11346 bgp_static = bgp_static_get_node_info(rn);
11347 if (bgp_static == NULL)
ea47320b 11348 continue;
d62a17ae 11349
ea47320b
DL
11350 char *macrouter = NULL;
11351 char *esi = NULL;
d62a17ae 11352
ea47320b
DL
11353 if (bgp_static->router_mac)
11354 macrouter = prefix_mac2str(
11355 bgp_static->router_mac, NULL, 0);
11356 if (bgp_static->eth_s_id)
11357 esi = esi2str(bgp_static->eth_s_id);
11358 p = &rn->p;
11359 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11360
ea47320b 11361 /* "network" configuration display. */
06b9f471 11362 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11363 if (p->u.prefix_evpn.route_type == 5) {
11364 char local_buf[PREFIX_STRLEN];
3714a385 11365 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
11366 struct prefix_evpn *)p)
11367 ? AF_INET
11368 : AF_INET6;
3714a385 11369 inet_ntop(family,
11370 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
11371 local_buf, PREFIX_STRLEN);
11372 sprintf(buf, "%s/%u", local_buf,
3714a385 11373 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
11374 } else {
11375 prefix2str(p, buf, sizeof(buf));
11376 }
ea47320b 11377
a4d82a8a
PZ
11378 if (bgp_static->gatewayIp.family == AF_INET
11379 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
11380 inet_ntop(bgp_static->gatewayIp.family,
11381 &bgp_static->gatewayIp.u.prefix, buf2,
11382 sizeof(buf2));
ea47320b 11383 vty_out(vty,
7bcc8dac 11384 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 11385 buf, rdbuf,
11386 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 11387 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11388 macrouter);
11389
11390 if (macrouter)
11391 XFREE(MTYPE_TMP, macrouter);
11392 if (esi)
11393 XFREE(MTYPE_TMP, esi);
11394 }
11395 }
3da6fcd5
PG
11396}
11397
718e3744 11398/* Configuration of static route announcement and aggregate
11399 information. */
2b791107
DL
11400void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11401 safi_t safi)
d62a17ae 11402{
11403 struct bgp_node *rn;
11404 struct prefix *p;
11405 struct bgp_static *bgp_static;
11406 struct bgp_aggregate *bgp_aggregate;
11407 char buf[SU_ADDRSTRLEN];
11408
2b791107
DL
11409 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11410 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11411 return;
11412 }
d62a17ae 11413
2b791107
DL
11414 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11415 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11416 return;
11417 }
d62a17ae 11418
11419 /* Network configuration. */
11420 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 11421 rn = bgp_route_next(rn)) {
a78beeb5
DS
11422 bgp_static = bgp_static_get_node_info(rn);
11423 if (bgp_static == NULL)
ea47320b 11424 continue;
d62a17ae 11425
ea47320b 11426 p = &rn->p;
d62a17ae 11427
ea47320b 11428 /* "network" configuration display. */
60466a63 11429 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
d7c0a89a 11430 uint32_t destination;
ea47320b 11431 struct in_addr netmask;
d62a17ae 11432
ea47320b
DL
11433 destination = ntohl(p->u.prefix4.s_addr);
11434 masklen2ip(p->prefixlen, &netmask);
11435 vty_out(vty, " network %s",
11436 inet_ntop(p->family, &p->u.prefix, buf,
11437 SU_ADDRSTRLEN));
d62a17ae 11438
ea47320b
DL
11439 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11440 || (IN_CLASSB(destination) && p->prefixlen == 16)
11441 || (IN_CLASSA(destination) && p->prefixlen == 8)
11442 || p->u.prefix4.s_addr == 0) {
11443 /* Natural mask is not display. */
11444 } else
11445 vty_out(vty, " mask %s", inet_ntoa(netmask));
11446 } else {
11447 vty_out(vty, " network %s/%d",
11448 inet_ntop(p->family, &p->u.prefix, buf,
11449 SU_ADDRSTRLEN),
11450 p->prefixlen);
11451 }
d62a17ae 11452
ea47320b
DL
11453 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11454 vty_out(vty, " label-index %u",
11455 bgp_static->label_index);
d62a17ae 11456
ea47320b
DL
11457 if (bgp_static->rmap.name)
11458 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
11459
11460 if (bgp_static->backdoor)
11461 vty_out(vty, " backdoor");
718e3744 11462
ea47320b
DL
11463 vty_out(vty, "\n");
11464 }
11465
d62a17ae 11466 /* Aggregate-address configuration. */
11467 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 11468 rn = bgp_route_next(rn)) {
b1e62edd
DS
11469 bgp_aggregate = bgp_aggregate_get_node_info(rn);
11470 if (bgp_aggregate == NULL)
ea47320b 11471 continue;
d62a17ae 11472
ea47320b 11473 p = &rn->p;
d62a17ae 11474
ea47320b
DL
11475 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11476 struct in_addr netmask;
d62a17ae 11477
ea47320b
DL
11478 masklen2ip(p->prefixlen, &netmask);
11479 vty_out(vty, " aggregate-address %s %s",
11480 inet_ntop(p->family, &p->u.prefix, buf,
11481 SU_ADDRSTRLEN),
11482 inet_ntoa(netmask));
11483 } else {
11484 vty_out(vty, " aggregate-address %s/%d",
11485 inet_ntop(p->family, &p->u.prefix, buf,
11486 SU_ADDRSTRLEN),
11487 p->prefixlen);
11488 }
d62a17ae 11489
ea47320b
DL
11490 if (bgp_aggregate->as_set)
11491 vty_out(vty, " as-set");
d62a17ae 11492
ea47320b
DL
11493 if (bgp_aggregate->summary_only)
11494 vty_out(vty, " summary-only");
718e3744 11495
ea47320b
DL
11496 vty_out(vty, "\n");
11497 }
d62a17ae 11498}
734b349e 11499
2b791107 11500void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11501 safi_t safi)
d62a17ae 11502{
11503 struct bgp_node *rn;
11504 struct bgp_distance *bdistance;
11505
11506 /* Distance configuration. */
11507 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11508 && bgp->distance_local[afi][safi]
11509 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11510 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11511 || bgp->distance_local[afi][safi]
11512 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11513 vty_out(vty, " distance bgp %d %d %d\n",
11514 bgp->distance_ebgp[afi][safi],
11515 bgp->distance_ibgp[afi][safi],
11516 bgp->distance_local[afi][safi]);
11517 }
734b349e 11518
d62a17ae 11519 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d
DS
11520 rn = bgp_route_next(rn)) {
11521 bdistance = bgp_distance_get_node(rn);
11522 if (bdistance != NULL) {
d62a17ae 11523 char buf[PREFIX_STRLEN];
11524
d62a17ae 11525 vty_out(vty, " distance %d %s %s\n",
11526 bdistance->distance,
11527 prefix2str(&rn->p, buf, sizeof(buf)),
11528 bdistance->access_list ? bdistance->access_list
11529 : "");
11530 }
ca2e160d 11531 }
718e3744 11532}
11533
11534/* Allocate routing table structure and install commands. */
d62a17ae 11535void bgp_route_init(void)
11536{
11537 afi_t afi;
11538 safi_t safi;
11539
11540 /* Init BGP distance table. */
05c7a1cc 11541 FOREACH_AFI_SAFI (afi, safi)
960035b2 11542 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 11543
11544 /* IPv4 BGP commands. */
11545 install_element(BGP_NODE, &bgp_table_map_cmd);
11546 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 11547 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 11548
11549 install_element(BGP_NODE, &aggregate_address_cmd);
11550 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11551 install_element(BGP_NODE, &no_aggregate_address_cmd);
11552 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11553
11554 /* IPv4 unicast configuration. */
11555 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11556 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 11557 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 11558
11559 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11560 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11561 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11562 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11563
11564 /* IPv4 multicast configuration. */
11565 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11566 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 11567 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 11568 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11569 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11570 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11571 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11572
11573 /* IPv4 labeled-unicast configuration. */
11574 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11575 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11576 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11577 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11578 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11579
11580 install_element(VIEW_NODE,
11581 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11582 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11583 install_element(VIEW_NODE,
11584 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11585#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11586 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11587#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11588 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11589 install_element(VIEW_NODE,
11590 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11591
d62a17ae 11592 /* BGP dampening clear commands */
11593 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11594 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11595
d62a17ae 11596 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11597 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11598
11599 /* prefix count */
11600 install_element(ENABLE_NODE,
11601 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11602#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11603 install_element(ENABLE_NODE,
11604 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11605#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11606
d62a17ae 11607 /* New config IPv6 BGP commands. */
11608 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11609 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11610 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 11611
11612 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11613 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11614
11615 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 11616
d62a17ae 11617 install_element(BGP_NODE, &bgp_distance_cmd);
11618 install_element(BGP_NODE, &no_bgp_distance_cmd);
11619 install_element(BGP_NODE, &bgp_distance_source_cmd);
11620 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11621 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11622 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11623 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11624 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11625 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11626 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11627 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11628 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11629 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11630 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11631 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11632 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11633 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11634 install_element(BGP_IPV4M_NODE,
11635 &no_bgp_distance_source_access_list_cmd);
11636 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11637 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11638 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11639 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11640 install_element(BGP_IPV6_NODE,
11641 &ipv6_bgp_distance_source_access_list_cmd);
11642 install_element(BGP_IPV6_NODE,
11643 &no_ipv6_bgp_distance_source_access_list_cmd);
11644 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11645 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11646 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11647 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11648 install_element(BGP_IPV6M_NODE,
11649 &ipv6_bgp_distance_source_access_list_cmd);
11650 install_element(BGP_IPV6M_NODE,
11651 &no_ipv6_bgp_distance_source_access_list_cmd);
11652
11653 install_element(BGP_NODE, &bgp_damp_set_cmd);
11654 install_element(BGP_NODE, &bgp_damp_unset_cmd);
11655 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
11656 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
11657
11658 /* IPv4 Multicast Mode */
11659 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
11660 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
11661
11662 /* Large Communities */
11663 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11664 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
11665
11666 /* show bgp ipv4 flowspec detailed */
11667 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
11668
d62a17ae 11669}
11670
11671void bgp_route_finish(void)
11672{
11673 afi_t afi;
11674 safi_t safi;
11675
05c7a1cc
QY
11676 FOREACH_AFI_SAFI (afi, safi) {
11677 bgp_table_unlock(bgp_distance_table[afi][safi]);
11678 bgp_distance_table[afi][safi] = NULL;
11679 }
228da428 11680}