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