]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #5761 from qlyoung/fix-bgp-gr-cruft
[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
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
718e3744 72
65efcfce 73#if ENABLE_BGP_VNC
f8b6f499
LB
74#include "bgpd/rfapi/rfapi_backend.h"
75#include "bgpd/rfapi/vnc_import_bgp.h"
76#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 77#endif
aee875b5
PG
78#include "bgpd/bgp_encap_types.h"
79#include "bgpd/bgp_encap_tlv.h"
684a7227 80#include "bgpd/bgp_evpn.h"
3da6fcd5 81#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 82#include "bgpd/bgp_flowspec.h"
98a9dbc7 83#include "bgpd/bgp_flowspec_util.h"
45918cfb 84#include "bgpd/bgp_pbr.h"
65efcfce 85
e2a86ad9
DS
86#ifndef VTYSH_EXTRACT_PL
87#include "bgpd/bgp_route_clippy.c"
88#endif
aee875b5 89
718e3744 90/* Extern from bgp_dump.c */
dde72586
SH
91extern const char *bgp_origin_str[];
92extern const char *bgp_origin_long_str[];
36235319 93const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 94/* PMSI strings. */
95#define PMSI_TNLTYPE_STR_NO_INFO "No info"
96#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
97static const struct message bgp_pmsi_tnltype_str[] = {
98 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
99 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
100 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
101 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
102 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
103 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
104 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
105 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 106 {0}
107};
b7d08f5a 108
9df8b37c
PZ
109#define VRFID_NONE_STR "-"
110
4a11bf2c
DL
111DEFINE_HOOK(bgp_process,
112 (struct bgp *bgp, afi_t afi, safi_t safi,
113 struct bgp_node *bn, struct peer *peer, bool withdraw),
114 (bgp, afi, safi, bn, peer, withdraw))
115
116
d62a17ae 117struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
118 safi_t safi, struct prefix *p,
119 struct prefix_rd *prd)
120{
121 struct bgp_node *rn;
122 struct bgp_node *prn = NULL;
123
124 assert(table);
125 if (!table)
126 return NULL;
127
128 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
129 || (safi == SAFI_EVPN)) {
130 prn = bgp_node_get(table, (struct prefix *)prd);
131
67009e22
DS
132 if (!bgp_node_has_bgp_path_info_data(prn))
133 bgp_node_set_bgp_table_info(
134 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 135 else
136 bgp_unlock_node(prn);
67009e22 137 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 138 }
718e3744 139
d62a17ae 140 rn = bgp_node_get(table, p);
718e3744 141
d62a17ae 142 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
143 || (safi == SAFI_EVPN))
144 rn->prn = prn;
718e3744 145
d62a17ae 146 return rn;
718e3744 147}
6b0655a2 148
d62a17ae 149struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
150 safi_t safi, struct prefix *p,
151 struct prefix_rd *prd)
128ea8ab 152{
d62a17ae 153 struct bgp_node *rn;
154 struct bgp_node *prn = NULL;
128ea8ab 155
d62a17ae 156 if (!table)
157 return NULL;
128ea8ab 158
d62a17ae 159 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
160 || (safi == SAFI_EVPN)) {
161 prn = bgp_node_lookup(table, (struct prefix *)prd);
162 if (!prn)
163 return NULL;
128ea8ab 164
6f94b685 165 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 166 bgp_unlock_node(prn);
167 return NULL;
168 }
128ea8ab 169
67009e22 170 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 171 }
128ea8ab 172
d62a17ae 173 rn = bgp_node_lookup(table, p);
128ea8ab 174
d62a17ae 175 return rn;
128ea8ab 176}
177
18ee8310
DS
178/* Allocate bgp_path_info_extra */
179static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 180{
4b7e6066
DS
181 struct bgp_path_info_extra *new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
183 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
184 new->label[0] = MPLS_INVALID_LABEL;
185 new->num_labels = 0;
3e3708cb
PG
186 new->bgp_fs_pbr = NULL;
187 new->bgp_fs_iprule = NULL;
d62a17ae 188 return new;
fb982c25
PJ
189}
190
a2e219fe 191void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 192{
4b7e6066 193 struct bgp_path_info_extra *e;
d62a17ae 194
c93a3b77
DS
195 if (!extra || !*extra)
196 return;
d62a17ae 197
c93a3b77
DS
198 e = *extra;
199 if (e->damp_info)
a935f597
DA
200 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
201 e->damp_info->safi);
d62a17ae 202
c93a3b77
DS
203 e->damp_info = NULL;
204 if (e->parent) {
40381db7 205 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 206
40381db7 207 if (bpi->net) {
0e70e6c8
DL
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
211 *
40381db7
DS
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
0e70e6c8
DL
215 */
216 unsigned refcount;
217
40381db7
DS
218 bpi = bgp_path_info_lock(bpi);
219 refcount = bpi->net->lock - 1;
220 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 221 if (!refcount)
40381db7
DS
222 bpi->net = NULL;
223 bgp_path_info_unlock(bpi);
0e70e6c8 224 }
18ee8310 225 bgp_path_info_unlock(e->parent);
c93a3b77 226 e->parent = NULL;
d62a17ae 227 }
c93a3b77
DS
228
229 if (e->bgp_orig)
230 bgp_unlock(e->bgp_orig);
c26edcda 231
ce3c0614
PG
232 if ((*extra)->bgp_fs_iprule)
233 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 234 if ((*extra)->bgp_fs_pbr)
6a154c88 235 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 236 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
237}
238
18ee8310
DS
239/* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
fb982c25 241 */
40381db7 242struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 243{
40381db7
DS
244 if (!pi->extra)
245 pi->extra = bgp_path_info_extra_new();
246 return pi->extra;
fb982c25
PJ
247}
248
718e3744 249/* Free bgp route information. */
9b6d8fcf 250static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 251{
05864da7 252 bgp_attr_unintern(&path->attr);
fb018d25 253
9b6d8fcf
DS
254 bgp_unlink_nexthop(path);
255 bgp_path_info_extra_free(&path->extra);
256 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
257 if (path->net)
258 bgp_addpath_free_info_data(&path->tx_addpath,
259 &path->net->tx_addpath);
718e3744 260
9b6d8fcf 261 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 262
9b6d8fcf 263 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 264}
265
9b6d8fcf 266struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 267{
9b6d8fcf
DS
268 path->lock++;
269 return path;
200df115 270}
271
9b6d8fcf 272struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 273{
9b6d8fcf
DS
274 assert(path && path->lock > 0);
275 path->lock--;
d62a17ae 276
9b6d8fcf 277 if (path->lock == 0) {
200df115 278#if 0
279 zlog_debug ("%s: unlocked and freeing", __func__);
280 zlog_backtrace (LOG_DEBUG);
281#endif
9b6d8fcf 282 bgp_path_info_free(path);
d62a17ae 283 return NULL;
284 }
200df115 285
286#if 0
9b6d8fcf 287 if (path->lock == 1)
200df115 288 {
289 zlog_debug ("%s: unlocked to 1", __func__);
290 zlog_backtrace (LOG_DEBUG);
291 }
292#endif
d62a17ae 293
9b6d8fcf 294 return path;
200df115 295}
296
f009ff26 297/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
298static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
299{
300 struct peer *peer;
301 struct bgp_path_info *old_pi, *nextpi;
302 bool set_flag = 0;
303 struct bgp *bgp = NULL;
304 struct bgp_table *table = NULL;
305 afi_t afi = 0;
306 safi_t safi = 0;
307 char buf[PREFIX2STR_BUFFER];
308
309 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
310 * then the route selection is deferred
311 */
2ba1fe69 312 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 313 return 0;
314
5f9c1aa2 315 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
316 if (BGP_DEBUG(update, UPDATE_OUT)) {
317 prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
36235319
QY
318 zlog_debug(
319 "Route %s is in workqueue and being processed, not deferred.",
5f9c1aa2 320 buf);
321 }
322 return 0;
323 }
324
f009ff26 325 table = bgp_node_table(rn);
326 if (table) {
327 bgp = table->bgp;
328 afi = table->afi;
329 safi = table->safi;
330 }
331
332 for (old_pi = bgp_node_get_bgp_path_info(rn);
333 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
334 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
335 continue;
336
337 /* Route selection is deferred if there is a stale path which
338 * which indicates peer is in restart mode
339 */
36235319
QY
340 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
341 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
f009ff26 342 set_flag = 1;
343 } else {
344 /* If the peer is graceful restart capable and peer is
345 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
346 */
347 peer = old_pi->peer;
36235319
QY
348 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
349 && BGP_PEER_RESTARTING_MODE(peer)
350 && (old_pi
351 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
f009ff26 352 set_flag = 1;
353 }
354 }
355 if (set_flag)
356 break;
357 }
358
359 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
360 * is active
361 */
2ba1fe69 362 if (set_flag && table) {
f009ff26 363 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
364 SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
365 prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
366 if (rn->rt_node == NULL)
367 rn->rt_node = listnode_add(
368 bgp->gr_info[afi][safi].route_list, rn);
369 if (BGP_DEBUG(update, UPDATE_OUT))
370 zlog_debug("DEFER route %s, rn %p, node %p",
36235319 371 buf, rn, rn->rt_node);
f009ff26 372 return 0;
373 }
374 }
375 return -1;
376}
377
40381db7 378void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 379{
4b7e6066 380 struct bgp_path_info *top;
718e3744 381
6f94b685 382 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 383
6f94b685 384 pi->next = top;
40381db7 385 pi->prev = NULL;
d62a17ae 386 if (top)
40381db7 387 top->prev = pi;
6f94b685 388 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 389
40381db7 390 bgp_path_info_lock(pi);
d62a17ae 391 bgp_lock_node(rn);
40381db7 392 peer_lock(pi->peer); /* bgp_path_info peer reference */
f009ff26 393 bgp_node_set_defer_flag(rn, false);
718e3744 394}
395
d62a17ae 396/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 397 completion callback *only* */
40381db7 398void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 399{
40381db7
DS
400 if (pi->next)
401 pi->next->prev = pi->prev;
402 if (pi->prev)
403 pi->prev->next = pi->next;
d62a17ae 404 else
6f94b685 405 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 406
40381db7
DS
407 bgp_path_info_mpath_dequeue(pi);
408 bgp_path_info_unlock(pi);
d62a17ae 409 bgp_unlock_node(rn);
718e3744 410}
411
40381db7 412void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 413{
40381db7 414 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 415 /* set of previous already took care of pcount */
40381db7 416 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 417}
418
18ee8310 419/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
420 called when a route is deleted and then quickly re-added before the
421 deletion has been processed */
40381db7 422void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 423{
40381db7 424 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 425 /* unset of previous already took care of pcount */
40381db7 426 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
427}
428
d62a17ae 429/* Adjust pcount as required */
40381db7 430static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 431{
d62a17ae 432 struct bgp_table *table;
67174041 433
d62a17ae 434 assert(rn && bgp_node_table(rn));
40381db7 435 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 436
d62a17ae 437 table = bgp_node_table(rn);
67174041 438
40381db7 439 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 440 return;
441
40381db7
DS
442 if (!BGP_PATH_COUNTABLE(pi)
443 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 444
40381db7 445 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 446
447 /* slight hack, but more robust against errors. */
40381db7
DS
448 if (pi->peer->pcount[table->afi][table->safi])
449 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 450 else
450971aa 451 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 452 "Asked to decrement 0 prefix count for peer");
40381db7
DS
453 } else if (BGP_PATH_COUNTABLE(pi)
454 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
455 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
456 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 457 }
1a392d46
PJ
458}
459
40381db7
DS
460static int bgp_label_index_differs(struct bgp_path_info *pi1,
461 struct bgp_path_info *pi2)
28d58fd7 462{
40381db7 463 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 464}
1a392d46 465
18ee8310 466/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
467 * This is here primarily to keep prefix-count in check.
468 */
40381db7 469void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 470 uint32_t flag)
1a392d46 471{
40381db7 472 SET_FLAG(pi->flags, flag);
d62a17ae 473
474 /* early bath if we know it's not a flag that changes countability state
475 */
476 if (!CHECK_FLAG(flag,
1defdda8 477 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 478 return;
479
40381db7 480 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
481}
482
40381db7 483void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 484 uint32_t flag)
1a392d46 485{
40381db7 486 UNSET_FLAG(pi->flags, flag);
d62a17ae 487
488 /* early bath if we know it's not a flag that changes countability state
489 */
490 if (!CHECK_FLAG(flag,
1defdda8 491 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 492 return;
493
40381db7 494 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
495}
496
718e3744 497/* Get MED value. If MED value is missing and "bgp bestpath
498 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 499static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 500{
501 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
502 return attr->med;
503 else {
504 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
505 return BGP_MED_MAX;
506 else
507 return 0;
508 }
718e3744 509}
510
40381db7 511void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 512{
40381db7
DS
513 if (pi->addpath_rx_id)
514 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
515 pi->addpath_rx_id);
d62a17ae 516 else
40381db7 517 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 518}
9fbdd100 519
d62a17ae 520/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
521 */
18ee8310
DS
522static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
523 struct bgp_path_info *exist, int *paths_eq,
524 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
525 char *pfx_buf, afi_t afi, safi_t safi,
526 enum bgp_path_selection_reason *reason)
d62a17ae 527{
528 struct attr *newattr, *existattr;
529 bgp_peer_sort_t new_sort;
530 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
531 uint32_t new_pref;
532 uint32_t exist_pref;
533 uint32_t new_med;
534 uint32_t exist_med;
535 uint32_t new_weight;
536 uint32_t exist_weight;
d62a17ae 537 uint32_t newm, existm;
538 struct in_addr new_id;
539 struct in_addr exist_id;
540 int new_cluster;
541 int exist_cluster;
542 int internal_as_route;
543 int confed_as_route;
04d14c8b 544 int ret = 0;
d62a17ae 545 char new_buf[PATH_ADDPATH_STR_BUFFER];
546 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
547 uint32_t new_mm_seq;
548 uint32_t exist_mm_seq;
6d8c603a 549 int nh_cmp;
d62a17ae 550
551 *paths_eq = 0;
552
553 /* 0. Null check. */
554 if (new == NULL) {
fdf81fa0 555 *reason = bgp_path_selection_none;
d62a17ae 556 if (debug)
557 zlog_debug("%s: new is NULL", pfx_buf);
558 return 0;
559 }
2ec1e66f 560
d62a17ae 561 if (debug)
18ee8310 562 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 563
d62a17ae 564 if (exist == NULL) {
fdf81fa0 565 *reason = bgp_path_selection_first;
d62a17ae 566 if (debug)
567 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
568 new_buf);
569 return 1;
570 }
2ec1e66f 571
d62a17ae 572 if (debug) {
18ee8310 573 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 574 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
575 pfx_buf, new_buf, new->flags, exist_buf,
576 exist->flags);
577 }
8ff56318 578
d62a17ae 579 newattr = new->attr;
580 existattr = exist->attr;
581
582 /* For EVPN routes, we cannot just go by local vs remote, we have to
583 * look at the MAC mobility sequence number, if present.
584 */
585 if (safi == SAFI_EVPN) {
586 /* This is an error condition described in RFC 7432 Section
587 * 15.2. The RFC
588 * states that in this scenario "the PE MUST alert the operator"
589 * but it
590 * does not state what other action to take. In order to provide
591 * some
592 * consistency in this scenario we are going to prefer the path
593 * with the
594 * sticky flag.
595 */
596 if (newattr->sticky != existattr->sticky) {
597 if (!debug) {
598 prefix2str(&new->net->p, pfx_buf,
599 sizeof(*pfx_buf)
600 * PREFIX2STR_BUFFER);
18ee8310
DS
601 bgp_path_info_path_with_addpath_rx_str(new,
602 new_buf);
603 bgp_path_info_path_with_addpath_rx_str(
604 exist, exist_buf);
d62a17ae 605 }
606
607 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 608 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
609 if (debug)
610 zlog_debug(
611 "%s: %s wins over %s due to sticky MAC flag",
612 pfx_buf, new_buf, exist_buf);
d62a17ae 613 return 1;
614 }
615
616 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 617 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
618 if (debug)
619 zlog_debug(
620 "%s: %s loses to %s due to sticky MAC flag",
621 pfx_buf, new_buf, exist_buf);
d62a17ae 622 return 0;
623 }
624 }
128ea8ab 625
d62a17ae 626 new_mm_seq = mac_mobility_seqnum(newattr);
627 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 628
d62a17ae 629 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 630 *reason = bgp_path_selection_evpn_seq;
d62a17ae 631 if (debug)
632 zlog_debug(
633 "%s: %s wins over %s due to MM seq %u > %u",
634 pfx_buf, new_buf, exist_buf, new_mm_seq,
635 exist_mm_seq);
636 return 1;
637 }
8ff56318 638
d62a17ae 639 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 640 *reason = bgp_path_selection_evpn_seq;
d62a17ae 641 if (debug)
642 zlog_debug(
643 "%s: %s loses to %s due to MM seq %u < %u",
644 pfx_buf, new_buf, exist_buf, new_mm_seq,
645 exist_mm_seq);
646 return 0;
647 }
6d8c603a
AK
648
649 /*
650 * if sequence numbers are the same path with the lowest IP
651 * wins
652 */
653 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
654 if (nh_cmp < 0) {
fdf81fa0 655 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
656 if (debug)
657 zlog_debug(
658 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
659 pfx_buf, new_buf, exist_buf, new_mm_seq,
660 inet_ntoa(new->attr->nexthop));
661 return 1;
662 }
663 if (nh_cmp > 0) {
fdf81fa0 664 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
665 if (debug)
666 zlog_debug(
667 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
668 pfx_buf, new_buf, exist_buf, new_mm_seq,
669 inet_ntoa(new->attr->nexthop));
670 return 0;
671 }
d62a17ae 672 }
9fbdd100 673
d62a17ae 674 /* 1. Weight check. */
d62a17ae 675 new_weight = newattr->weight;
676 exist_weight = existattr->weight;
8ff56318 677
d62a17ae 678 if (new_weight > exist_weight) {
fdf81fa0 679 *reason = bgp_path_selection_weight;
d62a17ae 680 if (debug)
681 zlog_debug("%s: %s wins over %s due to weight %d > %d",
682 pfx_buf, new_buf, exist_buf, new_weight,
683 exist_weight);
684 return 1;
685 }
718e3744 686
d62a17ae 687 if (new_weight < exist_weight) {
fdf81fa0 688 *reason = bgp_path_selection_weight;
d62a17ae 689 if (debug)
690 zlog_debug("%s: %s loses to %s due to weight %d < %d",
691 pfx_buf, new_buf, exist_buf, new_weight,
692 exist_weight);
693 return 0;
694 }
9fbdd100 695
d62a17ae 696 /* 2. Local preference check. */
697 new_pref = exist_pref = bgp->default_local_pref;
698
699 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
700 new_pref = newattr->local_pref;
701 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
702 exist_pref = existattr->local_pref;
703
704 if (new_pref > exist_pref) {
fdf81fa0 705 *reason = bgp_path_selection_local_pref;
d62a17ae 706 if (debug)
707 zlog_debug(
708 "%s: %s wins over %s due to localpref %d > %d",
709 pfx_buf, new_buf, exist_buf, new_pref,
710 exist_pref);
711 return 1;
712 }
718e3744 713
d62a17ae 714 if (new_pref < exist_pref) {
fdf81fa0 715 *reason = bgp_path_selection_local_pref;
d62a17ae 716 if (debug)
717 zlog_debug(
718 "%s: %s loses to %s due to localpref %d < %d",
719 pfx_buf, new_buf, exist_buf, new_pref,
720 exist_pref);
721 return 0;
722 }
9fbdd100 723
d62a17ae 724 /* 3. Local route check. We prefer:
725 * - BGP_ROUTE_STATIC
726 * - BGP_ROUTE_AGGREGATE
727 * - BGP_ROUTE_REDISTRIBUTE
728 */
90f4f482 729 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
730 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 731 *reason = bgp_path_selection_local_route;
d62a17ae 732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s due to preferred BGP_ROUTE type",
735 pfx_buf, new_buf, exist_buf);
736 return 1;
737 }
718e3744 738
90f4f482 739 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 740 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 741 *reason = bgp_path_selection_local_route;
d62a17ae 742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s due to preferred BGP_ROUTE type",
745 pfx_buf, new_buf, exist_buf);
746 return 0;
6811845b 747 }
718e3744 748
d62a17ae 749 /* 4. AS path length check. */
750 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
751 int exist_hops = aspath_count_hops(existattr->aspath);
752 int exist_confeds = aspath_count_confeds(existattr->aspath);
753
754 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
755 int aspath_hops;
756
757 aspath_hops = aspath_count_hops(newattr->aspath);
758 aspath_hops += aspath_count_confeds(newattr->aspath);
759
760 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 761 *reason = bgp_path_selection_confed_as_path;
d62a17ae 762 if (debug)
763 zlog_debug(
764 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
765 pfx_buf, new_buf, exist_buf,
766 aspath_hops,
767 (exist_hops + exist_confeds));
768 return 1;
769 }
770
771 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 772 *reason = bgp_path_selection_confed_as_path;
d62a17ae 773 if (debug)
774 zlog_debug(
775 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
776 pfx_buf, new_buf, exist_buf,
777 aspath_hops,
778 (exist_hops + exist_confeds));
779 return 0;
780 }
781 } else {
782 int newhops = aspath_count_hops(newattr->aspath);
783
784 if (newhops < exist_hops) {
fdf81fa0 785 *reason = bgp_path_selection_as_path;
d62a17ae 786 if (debug)
787 zlog_debug(
788 "%s: %s wins over %s due to aspath hopcount %d < %d",
789 pfx_buf, new_buf, exist_buf,
790 newhops, exist_hops);
791 return 1;
792 }
793
794 if (newhops > exist_hops) {
fdf81fa0 795 *reason = bgp_path_selection_as_path;
d62a17ae 796 if (debug)
797 zlog_debug(
798 "%s: %s loses to %s due to aspath hopcount %d > %d",
799 pfx_buf, new_buf, exist_buf,
800 newhops, exist_hops);
801 return 0;
802 }
803 }
804 }
9fbdd100 805
d62a17ae 806 /* 5. Origin check. */
807 if (newattr->origin < existattr->origin) {
fdf81fa0 808 *reason = bgp_path_selection_origin;
d62a17ae 809 if (debug)
810 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
811 pfx_buf, new_buf, exist_buf,
812 bgp_origin_long_str[newattr->origin],
813 bgp_origin_long_str[existattr->origin]);
814 return 1;
815 }
718e3744 816
d62a17ae 817 if (newattr->origin > existattr->origin) {
fdf81fa0 818 *reason = bgp_path_selection_origin;
d62a17ae 819 if (debug)
820 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
821 pfx_buf, new_buf, exist_buf,
822 bgp_origin_long_str[newattr->origin],
823 bgp_origin_long_str[existattr->origin]);
824 return 0;
825 }
718e3744 826
d62a17ae 827 /* 6. MED check. */
828 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
829 && aspath_count_hops(existattr->aspath) == 0);
830 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
831 && aspath_count_confeds(existattr->aspath) > 0
832 && aspath_count_hops(newattr->aspath) == 0
833 && aspath_count_hops(existattr->aspath) == 0);
834
835 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
836 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
837 || aspath_cmp_left(newattr->aspath, existattr->aspath)
838 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
839 || internal_as_route) {
840 new_med = bgp_med_value(new->attr, bgp);
841 exist_med = bgp_med_value(exist->attr, bgp);
842
843 if (new_med < exist_med) {
fdf81fa0 844 *reason = bgp_path_selection_med;
d62a17ae 845 if (debug)
846 zlog_debug(
847 "%s: %s wins over %s due to MED %d < %d",
848 pfx_buf, new_buf, exist_buf, new_med,
849 exist_med);
850 return 1;
851 }
8ff56318 852
d62a17ae 853 if (new_med > exist_med) {
fdf81fa0 854 *reason = bgp_path_selection_med;
d62a17ae 855 if (debug)
856 zlog_debug(
857 "%s: %s loses to %s due to MED %d > %d",
858 pfx_buf, new_buf, exist_buf, new_med,
859 exist_med);
860 return 0;
861 }
862 }
9fbdd100 863
d62a17ae 864 /* 7. Peer type check. */
865 new_sort = new->peer->sort;
866 exist_sort = exist->peer->sort;
867
868 if (new_sort == BGP_PEER_EBGP
869 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 870 *reason = bgp_path_selection_peer;
d62a17ae 871 if (debug)
872 zlog_debug(
873 "%s: %s wins over %s due to eBGP peer > iBGP peer",
874 pfx_buf, new_buf, exist_buf);
875 return 1;
876 }
718e3744 877
d62a17ae 878 if (exist_sort == BGP_PEER_EBGP
879 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 880 *reason = bgp_path_selection_peer;
d62a17ae 881 if (debug)
882 zlog_debug(
883 "%s: %s loses to %s due to iBGP peer < eBGP peer",
884 pfx_buf, new_buf, exist_buf);
885 return 0;
886 }
8ff56318 887
d62a17ae 888 /* 8. IGP metric check. */
889 newm = existm = 0;
8ff56318 890
d62a17ae 891 if (new->extra)
892 newm = new->extra->igpmetric;
893 if (exist->extra)
894 existm = exist->extra->igpmetric;
9fbdd100 895
d62a17ae 896 if (newm < existm) {
897 if (debug)
898 zlog_debug(
899 "%s: %s wins over %s due to IGP metric %d < %d",
900 pfx_buf, new_buf, exist_buf, newm, existm);
901 ret = 1;
902 }
718e3744 903
d62a17ae 904 if (newm > existm) {
905 if (debug)
906 zlog_debug(
907 "%s: %s loses to %s due to IGP metric %d > %d",
908 pfx_buf, new_buf, exist_buf, newm, existm);
909 ret = 0;
5e242b0d 910 }
5e242b0d 911
d62a17ae 912 /* 9. Same IGP metric. Compare the cluster list length as
913 representative of IGP hops metric. Rewrite the metric value
914 pair (newm, existm) with the cluster list length. Prefer the
915 path with smaller cluster list length. */
916 if (newm == existm) {
917 if (peer_sort(new->peer) == BGP_PEER_IBGP
918 && peer_sort(exist->peer) == BGP_PEER_IBGP
919 && (mpath_cfg == NULL
920 || CHECK_FLAG(
921 mpath_cfg->ibgp_flags,
922 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
923 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
924 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
925
926 if (newm < existm) {
927 if (debug)
928 zlog_debug(
929 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
930 pfx_buf, new_buf, exist_buf,
931 newm, existm);
932 ret = 1;
933 }
934
935 if (newm > existm) {
936 if (debug)
937 zlog_debug(
938 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
939 pfx_buf, new_buf, exist_buf,
940 newm, existm);
941 ret = 0;
942 }
943 }
944 }
31a4638f 945
d62a17ae 946 /* 10. confed-external vs. confed-internal */
947 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
948 if (new_sort == BGP_PEER_CONFED
949 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 950 *reason = bgp_path_selection_confed;
d62a17ae 951 if (debug)
952 zlog_debug(
953 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
954 pfx_buf, new_buf, exist_buf);
955 return 1;
956 }
718e3744 957
d62a17ae 958 if (exist_sort == BGP_PEER_CONFED
959 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 960 *reason = bgp_path_selection_confed;
d62a17ae 961 if (debug)
962 zlog_debug(
963 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
964 pfx_buf, new_buf, exist_buf);
965 return 0;
966 }
967 }
718e3744 968
d62a17ae 969 /* 11. Maximum path check. */
970 if (newm == existm) {
971 /* If one path has a label but the other does not, do not treat
972 * them as equals for multipath
973 */
a4d82a8a 974 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 975 != (exist->extra
b57ba6d2 976 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 977 if (debug)
978 zlog_debug(
979 "%s: %s and %s cannot be multipath, one has a label while the other does not",
980 pfx_buf, new_buf, exist_buf);
981 } else if (bgp_flag_check(bgp,
982 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
983
984 /*
985 * For the two paths, all comparison steps till IGP
986 * metric
987 * have succeeded - including AS_PATH hop count. Since
988 * 'bgp
989 * bestpath as-path multipath-relax' knob is on, we
990 * don't need
991 * an exact match of AS_PATH. Thus, mark the paths are
992 * equal.
993 * That will trigger both these paths to get into the
994 * multipath
995 * array.
996 */
997 *paths_eq = 1;
998
999 if (debug)
1000 zlog_debug(
1001 "%s: %s and %s are equal via multipath-relax",
1002 pfx_buf, new_buf, exist_buf);
1003 } else if (new->peer->sort == BGP_PEER_IBGP) {
1004 if (aspath_cmp(new->attr->aspath,
1005 exist->attr->aspath)) {
1006 *paths_eq = 1;
1007
1008 if (debug)
1009 zlog_debug(
1010 "%s: %s and %s are equal via matching aspaths",
1011 pfx_buf, new_buf, exist_buf);
1012 }
1013 } else if (new->peer->as == exist->peer->as) {
1014 *paths_eq = 1;
1015
1016 if (debug)
1017 zlog_debug(
1018 "%s: %s and %s are equal via same remote-as",
1019 pfx_buf, new_buf, exist_buf);
1020 }
1021 } else {
1022 /*
1023 * TODO: If unequal cost ibgp multipath is enabled we can
1024 * mark the paths as equal here instead of returning
1025 */
1026 if (debug) {
1027 if (ret == 1)
1028 zlog_debug(
1029 "%s: %s wins over %s after IGP metric comparison",
1030 pfx_buf, new_buf, exist_buf);
1031 else
1032 zlog_debug(
1033 "%s: %s loses to %s after IGP metric comparison",
1034 pfx_buf, new_buf, exist_buf);
1035 }
fdf81fa0 1036 *reason = bgp_path_selection_igp_metric;
d62a17ae 1037 return ret;
1038 }
718e3744 1039
d62a17ae 1040 /* 12. If both paths are external, prefer the path that was received
1041 first (the oldest one). This step minimizes route-flap, since a
1042 newer path won't displace an older one, even if it was the
1043 preferred route based on the additional decision criteria below. */
1044 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
1045 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1046 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1047 *reason = bgp_path_selection_older;
d62a17ae 1048 if (debug)
1049 zlog_debug(
1050 "%s: %s wins over %s due to oldest external",
1051 pfx_buf, new_buf, exist_buf);
1052 return 1;
1053 }
9fbdd100 1054
1defdda8 1055 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1056 *reason = bgp_path_selection_older;
d62a17ae 1057 if (debug)
1058 zlog_debug(
1059 "%s: %s loses to %s due to oldest external",
1060 pfx_buf, new_buf, exist_buf);
1061 return 0;
1062 }
1063 }
718e3744 1064
d62a17ae 1065 /* 13. Router-ID comparision. */
1066 /* If one of the paths is "stale", the corresponding peer router-id will
1067 * be 0 and would always win over the other path. If originator id is
1068 * used for the comparision, it will decide which path is better.
1069 */
1070 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1071 new_id.s_addr = newattr->originator_id.s_addr;
1072 else
1073 new_id.s_addr = new->peer->remote_id.s_addr;
1074 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1075 exist_id.s_addr = existattr->originator_id.s_addr;
1076 else
1077 exist_id.s_addr = exist->peer->remote_id.s_addr;
1078
1079 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1080 *reason = bgp_path_selection_router_id;
d62a17ae 1081 if (debug)
1082 zlog_debug(
1083 "%s: %s wins over %s due to Router-ID comparison",
1084 pfx_buf, new_buf, exist_buf);
1085 return 1;
1086 }
718e3744 1087
d62a17ae 1088 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1089 *reason = bgp_path_selection_router_id;
d62a17ae 1090 if (debug)
1091 zlog_debug(
1092 "%s: %s loses to %s due to Router-ID comparison",
1093 pfx_buf, new_buf, exist_buf);
1094 return 0;
1095 }
9fbdd100 1096
d62a17ae 1097 /* 14. Cluster length comparision. */
1098 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1099 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1100
1101 if (new_cluster < exist_cluster) {
fdf81fa0 1102 *reason = bgp_path_selection_cluster_length;
d62a17ae 1103 if (debug)
1104 zlog_debug(
1105 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1106 pfx_buf, new_buf, exist_buf, new_cluster,
1107 exist_cluster);
1108 return 1;
1109 }
718e3744 1110
d62a17ae 1111 if (new_cluster > exist_cluster) {
fdf81fa0 1112 *reason = bgp_path_selection_cluster_length;
d62a17ae 1113 if (debug)
1114 zlog_debug(
1115 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1116 pfx_buf, new_buf, exist_buf, new_cluster,
1117 exist_cluster);
1118 return 0;
1119 }
9fbdd100 1120
d62a17ae 1121 /* 15. Neighbor address comparision. */
1122 /* Do this only if neither path is "stale" as stale paths do not have
1123 * valid peer information (as the connection may or may not be up).
1124 */
1defdda8 1125 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1126 *reason = bgp_path_selection_stale;
d62a17ae 1127 if (debug)
1128 zlog_debug(
1129 "%s: %s wins over %s due to latter path being STALE",
1130 pfx_buf, new_buf, exist_buf);
1131 return 1;
1132 }
0de5153c 1133
1defdda8 1134 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1135 *reason = bgp_path_selection_stale;
d62a17ae 1136 if (debug)
1137 zlog_debug(
1138 "%s: %s loses to %s due to former path being STALE",
1139 pfx_buf, new_buf, exist_buf);
1140 return 0;
1141 }
718e3744 1142
d62a17ae 1143 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1144 if (new->peer->su_remote == NULL) {
1145 *reason = bgp_path_selection_local_configured;
d62a17ae 1146 return 0;
fdf81fa0
DS
1147 }
1148 if (exist->peer->su_remote == NULL) {
1149 *reason = bgp_path_selection_local_configured;
d62a17ae 1150 return 1;
fdf81fa0 1151 }
9fbdd100 1152
d62a17ae 1153 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1154
1155 if (ret == 1) {
fdf81fa0 1156 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1157 if (debug)
1158 zlog_debug(
1159 "%s: %s loses to %s due to Neighor IP comparison",
1160 pfx_buf, new_buf, exist_buf);
1161 return 0;
1162 }
1163
1164 if (ret == -1) {
fdf81fa0 1165 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1166 if (debug)
1167 zlog_debug(
1168 "%s: %s wins over %s due to Neighor IP comparison",
1169 pfx_buf, new_buf, exist_buf);
1170 return 1;
1171 }
9fbdd100 1172
fdf81fa0 1173 *reason = bgp_path_selection_default;
d62a17ae 1174 if (debug)
1175 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1176 pfx_buf, new_buf, exist_buf);
718e3744 1177
d62a17ae 1178 return 1;
718e3744 1179}
1180
65efcfce
LB
1181/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1182 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1183 * multipath is enabled
65efcfce 1184 * This version is compatible with */
18ee8310
DS
1185int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1186 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1187 afi_t afi, safi_t safi,
1188 enum bgp_path_selection_reason *reason)
d62a17ae 1189{
1190 int paths_eq;
1191 int ret;
18ee8310 1192 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1193 afi, safi, reason);
d62a17ae 1194
1195 if (paths_eq)
1196 ret = 0;
1197 else {
1198 if (ret == 1)
1199 ret = -1;
1200 else
1201 ret = 1;
1202 }
1203 return ret;
65efcfce
LB
1204}
1205
d62a17ae 1206static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1207 struct attr *attr, afi_t afi,
1208 safi_t safi)
718e3744 1209{
d62a17ae 1210 struct bgp_filter *filter;
718e3744 1211
d62a17ae 1212 filter = &peer->filter[afi][safi];
718e3744 1213
d62a17ae 1214#define FILTER_EXIST_WARN(F, f, filter) \
1215 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1216 zlog_debug("%s: Could not find configured input %s-list %s!", \
1217 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1218
1219 if (DISTRIBUTE_IN_NAME(filter)) {
1220 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1221
1222 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1223 return FILTER_DENY;
1224 }
1225
1226 if (PREFIX_LIST_IN_NAME(filter)) {
1227 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1228
1229 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1230 return FILTER_DENY;
1231 }
1232
1233 if (FILTER_LIST_IN_NAME(filter)) {
1234 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1235
1236 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1237 == AS_FILTER_DENY)
1238 return FILTER_DENY;
1239 }
1240
1241 return FILTER_PERMIT;
650f76c2 1242#undef FILTER_EXIST_WARN
718e3744 1243}
1244
d62a17ae 1245static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1246 struct attr *attr, afi_t afi,
1247 safi_t safi)
718e3744 1248{
d62a17ae 1249 struct bgp_filter *filter;
1250
1251 filter = &peer->filter[afi][safi];
1252
1253#define FILTER_EXIST_WARN(F, f, filter) \
1254 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1255 zlog_debug("%s: Could not find configured output %s-list %s!", \
1256 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1257
d62a17ae 1258 if (DISTRIBUTE_OUT_NAME(filter)) {
1259 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1260
d62a17ae 1261 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1262 return FILTER_DENY;
1263 }
1264
1265 if (PREFIX_LIST_OUT_NAME(filter)) {
1266 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1267
d62a17ae 1268 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1269 == PREFIX_DENY)
1270 return FILTER_DENY;
1271 }
718e3744 1272
d62a17ae 1273 if (FILTER_LIST_OUT_NAME(filter)) {
1274 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1275
d62a17ae 1276 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1277 == AS_FILTER_DENY)
1278 return FILTER_DENY;
1279 }
718e3744 1280
d62a17ae 1281 return FILTER_PERMIT;
650f76c2 1282#undef FILTER_EXIST_WARN
718e3744 1283}
1284
1285/* If community attribute includes no_export then return 1. */
d62a17ae 1286static int bgp_community_filter(struct peer *peer, struct attr *attr)
1287{
1288 if (attr->community) {
1289 /* NO_ADVERTISE check. */
1290 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1291 return 1;
1292
1293 /* NO_EXPORT check. */
1294 if (peer->sort == BGP_PEER_EBGP
1295 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1296 return 1;
1297
1298 /* NO_EXPORT_SUBCONFED check. */
1299 if (peer->sort == BGP_PEER_EBGP
1300 || peer->sort == BGP_PEER_CONFED)
1301 if (community_include(attr->community,
1302 COMMUNITY_NO_EXPORT_SUBCONFED))
1303 return 1;
1304 }
1305 return 0;
718e3744 1306}
1307
1308/* Route reflection loop check. */
d62a17ae 1309static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1310{
d62a17ae 1311 struct in_addr cluster_id;
718e3744 1312
d62a17ae 1313 if (attr->cluster) {
1314 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1315 cluster_id = peer->bgp->cluster_id;
1316 else
1317 cluster_id = peer->bgp->router_id;
1318
1319 if (cluster_loop_check(attr->cluster, cluster_id))
1320 return 1;
1321 }
1322 return 0;
718e3744 1323}
6b0655a2 1324
d62a17ae 1325static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1326 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1327 const char *rmap_name, mpls_label_t *label,
196c6b09 1328 uint32_t num_labels, struct bgp_node *rn)
718e3744 1329{
d62a17ae 1330 struct bgp_filter *filter;
82b692c0
LK
1331 struct bgp_path_info rmap_path = { 0 };
1332 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1333 route_map_result_t ret;
1334 struct route_map *rmap = NULL;
718e3744 1335
d62a17ae 1336 filter = &peer->filter[afi][safi];
718e3744 1337
d62a17ae 1338 /* Apply default weight value. */
1339 if (peer->weight[afi][safi])
1340 attr->weight = peer->weight[afi][safi];
718e3744 1341
d62a17ae 1342 if (rmap_name) {
1343 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1344
d62a17ae 1345 if (rmap == NULL)
1346 return RMAP_DENY;
1347 } else {
1348 if (ROUTE_MAP_IN_NAME(filter)) {
1349 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1350
d62a17ae 1351 if (rmap == NULL)
1352 return RMAP_DENY;
1353 }
1354 }
0b16f239 1355
d62a17ae 1356 /* Route map apply. */
1357 if (rmap) {
40381db7 1358 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1359 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1360 rmap_path.peer = peer;
1361 rmap_path.attr = attr;
82b692c0 1362 rmap_path.extra = &extra;
196c6b09
LK
1363 rmap_path.net = rn;
1364
82b692c0
LK
1365 extra.num_labels = num_labels;
1366 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1367 memcpy(extra.label, label,
1368 num_labels * sizeof(mpls_label_t));
718e3744 1369
d62a17ae 1370 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1371
d62a17ae 1372 /* Apply BGP route map to the attribute. */
40381db7 1373 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1374
d62a17ae 1375 peer->rmap_type = 0;
0b16f239 1376
1f2263be 1377 if (ret == RMAP_DENYMATCH)
d62a17ae 1378 return RMAP_DENY;
0b16f239 1379 }
d62a17ae 1380 return RMAP_PERMIT;
0b16f239
DS
1381}
1382
d62a17ae 1383static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1384 struct attr *attr, afi_t afi, safi_t safi,
1385 const char *rmap_name)
0b16f239 1386{
40381db7 1387 struct bgp_path_info rmap_path;
d62a17ae 1388 route_map_result_t ret;
1389 struct route_map *rmap = NULL;
d7c0a89a 1390 uint8_t rmap_type;
0b16f239 1391
b787157a
DS
1392 /*
1393 * So if we get to this point and have no rmap_name
1394 * we want to just show the output as it currently
1395 * exists.
1396 */
1397 if (!rmap_name)
1398 return RMAP_PERMIT;
0b16f239 1399
d62a17ae 1400 /* Apply default weight value. */
1401 if (peer->weight[afi][safi])
1402 attr->weight = peer->weight[afi][safi];
0b16f239 1403
b787157a 1404 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1405
b787157a
DS
1406 /*
1407 * If we have a route map name and we do not find
1408 * the routemap that means we have an implicit
1409 * deny.
1410 */
1411 if (rmap == NULL)
1412 return RMAP_DENY;
0b16f239 1413
40381db7 1414 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1415 /* Route map apply. */
b787157a 1416 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1417 rmap_path.peer = peer;
1418 rmap_path.attr = attr;
0b16f239 1419
0f672529 1420 rmap_type = peer->rmap_type;
b787157a 1421 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1422
b787157a 1423 /* Apply BGP route map to the attribute. */
40381db7 1424 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1425
0f672529 1426 peer->rmap_type = rmap_type;
b787157a
DS
1427
1428 if (ret == RMAP_DENYMATCH)
1429 /*
1430 * caller has multiple error paths with bgp_attr_flush()
1431 */
1432 return RMAP_DENY;
ac41b2a2 1433
d62a17ae 1434 return RMAP_PERMIT;
718e3744 1435}
6b0655a2 1436
5000f21c 1437/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1438static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1439 struct peer *peer, struct attr *attr)
1440{
1441 if (peer->sort == BGP_PEER_EBGP
1442 && (peer_af_flag_check(peer, afi, safi,
1443 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1444 || peer_af_flag_check(peer, afi, safi,
1445 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1446 || peer_af_flag_check(peer, afi, safi,
1447 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1448 || peer_af_flag_check(peer, afi, safi,
1449 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1450 // Take action on the entire aspath
1451 if (peer_af_flag_check(peer, afi, safi,
1452 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1453 || peer_af_flag_check(peer, afi, safi,
1454 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1455 if (peer_af_flag_check(
1456 peer, afi, safi,
1457 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1458 attr->aspath = aspath_replace_private_asns(
bf26b80e 1459 attr->aspath, bgp->as, peer->as);
d62a17ae 1460
1461 // The entire aspath consists of private ASNs so create
1462 // an empty aspath
1463 else if (aspath_private_as_check(attr->aspath))
1464 attr->aspath = aspath_empty_get();
1465
1466 // There are some public and some private ASNs, remove
1467 // the private ASNs
1468 else
1469 attr->aspath = aspath_remove_private_asns(
bf26b80e 1470 attr->aspath, peer->as);
d62a17ae 1471 }
1472
1473 // 'all' was not specified so the entire aspath must be private
1474 // ASNs
1475 // for us to do anything
1476 else if (aspath_private_as_check(attr->aspath)) {
1477 if (peer_af_flag_check(
1478 peer, afi, safi,
1479 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1480 attr->aspath = aspath_replace_private_asns(
bf26b80e 1481 attr->aspath, bgp->as, peer->as);
d62a17ae 1482 else
1483 attr->aspath = aspath_empty_get();
1484 }
1485 }
5000f21c
DS
1486}
1487
c7122e14 1488/* If this is an EBGP peer with as-override */
d62a17ae 1489static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1490 struct peer *peer, struct attr *attr)
1491{
1492 if (peer->sort == BGP_PEER_EBGP
1493 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1494 if (aspath_single_asn_check(attr->aspath, peer->as))
1495 attr->aspath = aspath_replace_specific_asn(
1496 attr->aspath, peer->as, bgp->as);
1497 }
1498}
1499
7f323236
DW
1500void bgp_attr_add_gshut_community(struct attr *attr)
1501{
1502 struct community *old;
1503 struct community *new;
1504 struct community *merge;
1505 struct community *gshut;
1506
1507 old = attr->community;
1508 gshut = community_str2com("graceful-shutdown");
1509
990f4f91 1510 assert(gshut);
1511
7f323236
DW
1512 if (old) {
1513 merge = community_merge(community_dup(old), gshut);
1514
a4d82a8a 1515 if (old->refcnt == 0)
3c1f53de 1516 community_free(&old);
7f323236
DW
1517
1518 new = community_uniq_sort(merge);
3c1f53de 1519 community_free(&merge);
7f323236
DW
1520 } else {
1521 new = community_dup(gshut);
1522 }
1523
3c1f53de 1524 community_free(&gshut);
7f323236
DW
1525 attr->community = new;
1526 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1527
1528 /* When we add the graceful-shutdown community we must also
1529 * lower the local-preference */
1530 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1531 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1532}
1533
1534
d7c0a89a 1535static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1536{
960035b2 1537 if (family == AF_INET) {
d62a17ae 1538 attr->nexthop.s_addr = 0;
960035b2
PZ
1539 attr->mp_nexthop_global_in.s_addr = 0;
1540 }
d62a17ae 1541 if (family == AF_INET6)
1542 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1543 if (family == AF_EVPN)
1544 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1545}
1546
40381db7 1547int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1548 struct update_subgroup *subgrp, struct prefix *p,
1549 struct attr *attr)
1550{
1551 struct bgp_filter *filter;
1552 struct peer *from;
1553 struct peer *peer;
1554 struct peer *onlypeer;
1555 struct bgp *bgp;
40381db7 1556 struct attr *piattr;
d62a17ae 1557 char buf[PREFIX_STRLEN];
b68885f9 1558 route_map_result_t ret;
d62a17ae 1559 int transparent;
1560 int reflect;
1561 afi_t afi;
1562 safi_t safi;
1563 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1564
1565 if (DISABLE_BGP_ANNOUNCE)
1566 return 0;
1567
1568 afi = SUBGRP_AFI(subgrp);
1569 safi = SUBGRP_SAFI(subgrp);
1570 peer = SUBGRP_PEER(subgrp);
1571 onlypeer = NULL;
1572 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1573 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1574
40381db7 1575 from = pi->peer;
d62a17ae 1576 filter = &peer->filter[afi][safi];
1577 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1578 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1579 : pi->attr;
3f9c7369 1580
65efcfce 1581#if ENABLE_BGP_VNC
d62a17ae 1582 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1583 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1584 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1585
1586 /*
1587 * direct and direct_ext type routes originate internally even
1588 * though they can have peer pointers that reference other
1589 * systems
1590 */
1591 prefix2str(p, buf, PREFIX_STRLEN);
1592 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1593 __func__, buf);
1594 samepeer_safe = 1;
1595 }
65efcfce
LB
1596#endif
1597
ddb5b488
PZ
1598 if (((afi == AFI_IP) || (afi == AFI_IP6))
1599 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1600 && (pi->type == ZEBRA_ROUTE_BGP)
1601 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1602
1603 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1604
1605 samepeer_safe = 1;
1606 }
1607
d62a17ae 1608 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1609 * pi is valid */
1610 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1611 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1612 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1613 return 0;
1614 }
adbac85e 1615
d62a17ae 1616 /* If this is not the bestpath then check to see if there is an enabled
1617 * addpath
1618 * feature that requires us to advertise it */
40381db7 1619 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1620 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1621 return 0;
1622 }
1623 }
06370dac 1624
d62a17ae 1625 /* Aggregate-address suppress check. */
40381db7 1626 if (pi->extra && pi->extra->suppress)
d62a17ae 1627 if (!UNSUPPRESS_MAP_NAME(filter)) {
1628 return 0;
1629 }
3f9c7369 1630
13b7e7f0
DS
1631 /*
1632 * If we are doing VRF 2 VRF leaking via the import
1633 * statement, we want to prevent the route going
1634 * off box as that the RT and RD created are localy
1635 * significant and globaly useless.
1636 */
40381db7
DS
1637 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1638 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1639 return 0;
1640
d62a17ae 1641 /* If it's labeled safi, make sure the route has a valid label. */
1642 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1643 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1644 if (!bgp_is_valid_label(&label)) {
1645 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1646 zlog_debug("u%" PRIu64 ":s%" PRIu64
1647 " %s/%d is filtered - no label (%p)",
1648 subgrp->update_group->id, subgrp->id,
1649 inet_ntop(p->family, &p->u.prefix,
1650 buf, SU_ADDRSTRLEN),
1651 p->prefixlen, &label);
1652 return 0;
1653 }
1654 }
cd1964ff 1655
d62a17ae 1656 /* Do not send back route to sender. */
1657 if (onlypeer && from == onlypeer) {
1658 return 0;
1659 }
3f9c7369 1660
d62a17ae 1661 /* Do not send the default route in the BGP table if the neighbor is
1662 * configured for default-originate */
1663 if (CHECK_FLAG(peer->af_flags[afi][safi],
1664 PEER_FLAG_DEFAULT_ORIGINATE)) {
1665 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1666 return 0;
1667 else if (p->family == AF_INET6 && p->prefixlen == 0)
1668 return 0;
1669 }
4125bb67 1670
d62a17ae 1671 /* Transparency check. */
1672 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1673 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1674 transparent = 1;
1675 else
1676 transparent = 0;
1677
1678 /* If community is not disabled check the no-export and local. */
40381db7 1679 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1680 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1681 zlog_debug(
1682 "subgrpannouncecheck: community filter check fail");
1683 return 0;
1684 }
3f9c7369 1685
d62a17ae 1686 /* If the attribute has originator-id and it is same as remote
1687 peer's id. */
40381db7
DS
1688 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1689 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1690 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1691 zlog_debug(
1692 "%s [Update:SEND] %s originator-id is same as "
1693 "remote router-id",
1694 onlypeer->host,
1695 prefix2str(p, buf, sizeof(buf)));
1696 return 0;
1697 }
3f9c7369 1698
d62a17ae 1699 /* ORF prefix-list filter check */
1700 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1701 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1702 || CHECK_FLAG(peer->af_cap[afi][safi],
1703 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1704 if (peer->orf_plist[afi][safi]) {
1705 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1706 == PREFIX_DENY) {
1707 if (bgp_debug_update(NULL, p,
1708 subgrp->update_group, 0))
1709 zlog_debug(
1710 "%s [Update:SEND] %s is filtered via ORF",
1711 peer->host,
1712 prefix2str(p, buf,
1713 sizeof(buf)));
1714 return 0;
1715 }
1716 }
1717
1718 /* Output filter check. */
40381db7 1719 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1720 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1721 zlog_debug("%s [Update:SEND] %s is filtered",
1722 peer->host, prefix2str(p, buf, sizeof(buf)));
1723 return 0;
1724 }
3f9c7369 1725
d62a17ae 1726 /* AS path loop check. */
2b31007c
RZ
1727 if (onlypeer && onlypeer->as_path_loop_detection
1728 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1729 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1730 zlog_debug(
1731 "%s [Update:SEND] suppress announcement to peer AS %u "
1732 "that is part of AS path.",
1733 onlypeer->host, onlypeer->as);
1734 return 0;
1735 }
3f9c7369 1736
d62a17ae 1737 /* If we're a CONFED we need to loop check the CONFED ID too */
1738 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1739 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1740 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1741 zlog_debug(
1742 "%s [Update:SEND] suppress announcement to peer AS %u"
1743 " is AS path.",
1744 peer->host, bgp->confed_id);
1745 return 0;
1746 }
3f9c7369 1747 }
3f9c7369 1748
d62a17ae 1749 /* Route-Reflect check. */
1750 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1751 reflect = 1;
1752 else
1753 reflect = 0;
1754
1755 /* IBGP reflection check. */
1756 if (reflect && !samepeer_safe) {
1757 /* A route from a Client peer. */
1758 if (CHECK_FLAG(from->af_flags[afi][safi],
1759 PEER_FLAG_REFLECTOR_CLIENT)) {
1760 /* Reflect to all the Non-Client peers and also to the
1761 Client peers other than the originator. Originator
1762 check
1763 is already done. So there is noting to do. */
1764 /* no bgp client-to-client reflection check. */
1765 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1766 if (CHECK_FLAG(peer->af_flags[afi][safi],
1767 PEER_FLAG_REFLECTOR_CLIENT))
1768 return 0;
1769 } else {
1770 /* A route from a Non-client peer. Reflect to all other
1771 clients. */
1772 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1773 PEER_FLAG_REFLECTOR_CLIENT))
1774 return 0;
1775 }
1776 }
3f9c7369 1777
d62a17ae 1778 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1779 *attr = *piattr;
d62a17ae 1780
1781 /* If local-preference is not set. */
1782 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1783 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1784 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1785 attr->local_pref = bgp->default_local_pref;
3f9c7369 1786 }
3f9c7369 1787
d62a17ae 1788 /* If originator-id is not set and the route is to be reflected,
1789 set the originator id */
1790 if (reflect
1791 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1792 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1793 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1794 }
3f9c7369 1795
d62a17ae 1796 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1797 */
1798 if (peer->sort == BGP_PEER_EBGP
1799 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1800 if (from != bgp->peer_self && !transparent
1801 && !CHECK_FLAG(peer->af_flags[afi][safi],
1802 PEER_FLAG_MED_UNCHANGED))
1803 attr->flag &=
1804 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1805 }
3f9c7369 1806
d62a17ae 1807 /* Since the nexthop attribute can vary per peer, it is not explicitly
1808 * set
1809 * in announce check, only certain flags and length (or number of
1810 * nexthops
1811 * -- for IPv6/MP_REACH) are set here in order to guide the update
1812 * formation
1813 * code in setting the nexthop(s) on a per peer basis in
1814 * reformat_peer().
1815 * Typically, the source nexthop in the attribute is preserved but in
1816 * the
1817 * scenarios where we know it will always be overwritten, we reset the
1818 * nexthop to "0" in an attempt to achieve better Update packing. An
1819 * example of this is when a prefix from each of 2 IBGP peers needs to
1820 * be
1821 * announced to an EBGP peer (and they have the same attributes barring
1822 * their nexthop).
1823 */
1824 if (reflect)
1825 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1826
1827#define NEXTHOP_IS_V6 \
1828 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1829 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1830 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1831 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1832
1833 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1834 * if
1835 * the peer (group) is configured to receive link-local nexthop
1836 * unchanged
c728d027
DA
1837 * and it is available in the prefix OR we're not reflecting the route,
1838 * link-local nexthop address is valid and
d62a17ae 1839 * the peer (group) to whom we're going to announce is on a shared
1840 * network
1841 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1842 * By checking if nexthop LL address is valid we are sure that
1843 * we do not announce LL address as `::`.
d62a17ae 1844 */
1845 if (NEXTHOP_IS_V6) {
1846 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1847 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1848 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1849 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1850 || (!reflect
1851 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1852 && peer->shared_network
d62a17ae 1853 && (from == bgp->peer_self
1854 || peer->sort == BGP_PEER_EBGP))) {
1855 attr->mp_nexthop_len =
1856 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1857 }
3f9c7369 1858
d62a17ae 1859 /* Clear off link-local nexthop in source, whenever it is not
1860 * needed to
1861 * ensure more prefixes share the same attribute for
1862 * announcement.
1863 */
1864 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1865 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1866 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1867 }
3f9c7369 1868
d62a17ae 1869 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1870 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1871
1872 /* Route map & unsuppress-map apply. */
40381db7 1873 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1874 struct bgp_path_info rmap_path = {0};
1875 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1876 struct attr dummy_attr = {0};
d62a17ae 1877
40381db7
DS
1878 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
1879 rmap_path.peer = peer;
1880 rmap_path.attr = attr;
196c6b09 1881 rmap_path.net = rn;
d37ba549 1882
40381db7
DS
1883 if (pi->extra) {
1884 memcpy(&dummy_rmap_path_extra, pi->extra,
4b7e6066 1885 sizeof(struct bgp_path_info_extra));
40381db7 1886 rmap_path.extra = &dummy_rmap_path_extra;
16f7ce2b
MK
1887 }
1888
d62a17ae 1889 /* don't confuse inbound and outbound setting */
1890 RESET_FLAG(attr->rmap_change_flags);
1891
1892 /*
1893 * The route reflector is not allowed to modify the attributes
1894 * of the reflected IBGP routes unless explicitly allowed.
1895 */
1896 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1897 && !bgp_flag_check(bgp,
1898 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1899 dummy_attr = *attr;
40381db7 1900 rmap_path.attr = &dummy_attr;
d62a17ae 1901 }
3f9c7369 1902
d62a17ae 1903 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1904
40381db7 1905 if (pi->extra && pi->extra->suppress)
d62a17ae 1906 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1907 RMAP_BGP, &rmap_path);
d62a17ae 1908 else
1909 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1910 RMAP_BGP, &rmap_path);
d62a17ae 1911
1912 peer->rmap_type = 0;
1913
1914 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1915 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1916 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1917 peer->host, prefix2str(p, buf, sizeof(buf)));
1918
d62a17ae 1919 bgp_attr_flush(attr);
1920 return 0;
1921 }
3f9c7369 1922 }
3f9c7369 1923
9dac9fc8
DA
1924 /* RFC 8212 to prevent route leaks.
1925 * This specification intends to improve this situation by requiring the
1926 * explicit configuration of both BGP Import and Export Policies for any
1927 * External BGP (EBGP) session such as customers, peers, or
1928 * confederation boundaries for all enabled address families. Through
1929 * codification of the aforementioned requirement, operators will
1930 * benefit from consistent behavior across different BGP
1931 * implementations.
1932 */
1933 if (peer->bgp->ebgp_requires_policy
1934 == DEFAULT_EBGP_POLICY_ENABLED)
1935 if (!bgp_outbound_policy_exists(peer, filter))
1936 return 0;
1937
fb29348a
DA
1938 /* draft-ietf-idr-deprecate-as-set-confed-set
1939 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1940 * Eventually, This document (if approved) updates RFC 4271
1941 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1942 * and obsoletes RFC 6472.
1943 */
1944 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
1945 if (aspath_check_as_sets(attr->aspath))
1946 return 0;
1947
7f323236 1948 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1949 if (peer->sort == BGP_PEER_IBGP
1950 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1951 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1952 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1953 } else {
1954 bgp_attr_add_gshut_community(attr);
1955 }
1956 }
1957
d62a17ae 1958 /* After route-map has been applied, we check to see if the nexthop to
1959 * be carried in the attribute (that is used for the announcement) can
1960 * be cleared off or not. We do this in all cases where we would be
1961 * setting the nexthop to "ourselves". For IPv6, we only need to
1962 * consider
1963 * the global nexthop here; the link-local nexthop would have been
1964 * cleared
1965 * already, and if not, it is required by the update formation code.
1966 * Also see earlier comments in this function.
1967 */
1968 /*
1969 * If route-map has performed some operation on the nexthop or the peer
1970 * configuration says to pass it unchanged, we cannot reset the nexthop
1971 * here, so only attempt to do it if these aren't true. Note that the
1972 * route-map handler itself might have cleared the nexthop, if for
1973 * example,
1974 * it is configured as 'peer-address'.
1975 */
1976 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1977 piattr->rmap_change_flags)
d62a17ae 1978 && !transparent
1979 && !CHECK_FLAG(peer->af_flags[afi][safi],
1980 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1981 /* We can reset the nexthop, if setting (or forcing) it to
1982 * 'self' */
1983 if (CHECK_FLAG(peer->af_flags[afi][safi],
1984 PEER_FLAG_NEXTHOP_SELF)
1985 || CHECK_FLAG(peer->af_flags[afi][safi],
1986 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1987 if (!reflect
1988 || CHECK_FLAG(peer->af_flags[afi][safi],
1989 PEER_FLAG_FORCE_NEXTHOP_SELF))
1990 subgroup_announce_reset_nhop(
1991 (peer_cap_enhe(peer, afi, safi)
1992 ? AF_INET6
1993 : p->family),
1994 attr);
1995 } else if (peer->sort == BGP_PEER_EBGP) {
1996 /* Can also reset the nexthop if announcing to EBGP, but
1997 * only if
1998 * no peer in the subgroup is on a shared subnet.
1999 * Note: 3rd party nexthop currently implemented for
2000 * IPv4 only.
2001 */
737af885
BS
2002 if ((p->family == AF_INET) &&
2003 (!bgp_subgrp_multiaccess_check_v4(
2004 piattr->nexthop,
2005 subgrp)))
d62a17ae 2006 subgroup_announce_reset_nhop(
2007 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2008 ? AF_INET6
2009 : p->family),
737af885
BS
2010 attr);
2011
2012 if ((p->family == AF_INET6) &&
2013 (!bgp_subgrp_multiaccess_check_v6(
2014 piattr->mp_nexthop_global,
2015 subgrp)))
2016 subgroup_announce_reset_nhop(
2017 (peer_cap_enhe(peer, afi, safi)
2018 ? AF_INET6
2019 : p->family),
2020 attr);
2021
2022
2023
40381db7 2024 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2025 /*
2026 * This flag is used for leaked vpn-vrf routes
2027 */
2028 int family = p->family;
2029
2030 if (peer_cap_enhe(peer, afi, safi))
2031 family = AF_INET6;
2032
2033 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2034 zlog_debug(
1defdda8 2035 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2036 __func__, family2str(family));
2037 subgroup_announce_reset_nhop(family, attr);
d62a17ae 2038 }
63696f1d 2039 }
960035b2 2040
63696f1d 2041 /* If IPv6/MP and nexthop does not have any override and happens
2042 * to
2043 * be a link-local address, reset it so that we don't pass along
2044 * the
2045 * source's link-local IPv6 address to recipients who may not be
2046 * on
2047 * the same interface.
2048 */
2049 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2050 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
2051 subgroup_announce_reset_nhop(AF_INET6, attr);
d62a17ae 2052 }
3f9c7369 2053
d62a17ae 2054 return 1;
3f9c7369
DS
2055}
2056
f009ff26 2057static int bgp_route_select_timer_expire(struct thread *thread)
2058{
2059 struct afi_safi_info *info;
2060 afi_t afi;
2061 safi_t safi;
2062 struct bgp *bgp;
2063
2064 info = THREAD_ARG(thread);
2065 afi = info->afi;
2066 safi = info->safi;
2067 bgp = info->bgp;
2068
2069 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2070 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2071 safi);
f009ff26 2072
2073 bgp->gr_info[afi][safi].t_route_select = NULL;
2074
2075 XFREE(MTYPE_TMP, info);
2076
2077 /* Best path selection */
2078 return bgp_best_path_select_defer(bgp, afi, safi);
2079}
2080
d62a17ae 2081void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
2082 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2083 struct bgp_path_info_pair *result, afi_t afi,
2084 safi_t safi)
2085{
2086 struct bgp_path_info *new_select;
2087 struct bgp_path_info *old_select;
40381db7
DS
2088 struct bgp_path_info *pi;
2089 struct bgp_path_info *pi1;
2090 struct bgp_path_info *pi2;
2091 struct bgp_path_info *nextpi = NULL;
d62a17ae 2092 int paths_eq, do_mpath, debug;
2093 struct list mp_list;
2094 char pfx_buf[PREFIX2STR_BUFFER];
2095 char path_buf[PATH_ADDPATH_STR_BUFFER];
2096
2097 bgp_mp_list_init(&mp_list);
2098 do_mpath =
2099 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2100
2101 debug = bgp_debug_bestpath(&rn->p);
2102
2103 if (debug)
2104 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2105
2106 /* bgp deterministic-med */
2107 new_select = NULL;
2108 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
2109
1defdda8 2110 /* Clear BGP_PATH_DMED_SELECTED for all paths */
6f94b685
DS
2111 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2112 pi1 = pi1->next)
40381db7 2113 bgp_path_info_unset_flag(rn, pi1,
18ee8310 2114 BGP_PATH_DMED_SELECTED);
d62a17ae 2115
6f94b685
DS
2116 for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
2117 pi1 = pi1->next) {
40381db7 2118 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2119 continue;
40381db7 2120 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2121 continue;
ea8b2282 2122 if (pi1->peer != bgp->peer_self)
40381db7 2123 if (pi1->peer->status != Established)
d62a17ae 2124 continue;
2125
40381db7
DS
2126 new_select = pi1;
2127 if (pi1->next) {
2128 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2129 if (CHECK_FLAG(pi2->flags,
1defdda8 2130 BGP_PATH_DMED_CHECK))
d62a17ae 2131 continue;
40381db7 2132 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2133 continue;
ea8b2282 2134 if (pi2->peer != bgp->peer_self
d62a17ae 2135 && !CHECK_FLAG(
ea8b2282
DS
2136 pi2->peer->sflags,
2137 PEER_STATUS_NSF_WAIT))
40381db7 2138 if (pi2->peer->status
d62a17ae 2139 != Established)
2140 continue;
2141
121e245d
DS
2142 if (!aspath_cmp_left(pi1->attr->aspath,
2143 pi2->attr->aspath)
2144 && !aspath_cmp_left_confed(
40381db7 2145 pi1->attr->aspath,
121e245d
DS
2146 pi2->attr->aspath))
2147 continue;
d62a17ae 2148
121e245d
DS
2149 if (bgp_path_info_cmp(
2150 bgp, pi2, new_select,
2151 &paths_eq, mpath_cfg, debug,
fdf81fa0
DS
2152 pfx_buf, afi, safi,
2153 &rn->reason)) {
121e245d
DS
2154 bgp_path_info_unset_flag(
2155 rn, new_select,
2156 BGP_PATH_DMED_SELECTED);
2157 new_select = pi2;
d62a17ae 2158 }
121e245d
DS
2159
2160 bgp_path_info_set_flag(
2161 rn, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2162 }
2163 }
18ee8310
DS
2164 bgp_path_info_set_flag(rn, new_select,
2165 BGP_PATH_DMED_CHECK);
2166 bgp_path_info_set_flag(rn, new_select,
2167 BGP_PATH_DMED_SELECTED);
d62a17ae 2168
2169 if (debug) {
18ee8310
DS
2170 bgp_path_info_path_with_addpath_rx_str(
2171 new_select, path_buf);
c66faab1 2172 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2173 pfx_buf, path_buf,
2174 aspath_get_first_as(
2175 new_select->attr->aspath));
2176 }
2177 }
2178 }
96450faf 2179
d62a17ae 2180 /* Check old selected route and new selected route. */
2181 old_select = NULL;
2182 new_select = NULL;
6f94b685
DS
2183 for (pi = bgp_node_get_bgp_path_info(rn);
2184 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
40381db7
DS
2185 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2186 old_select = pi;
d62a17ae 2187
40381db7 2188 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2189 /* reap REMOVED routes, if needs be
2190 * selected route must stay for a while longer though
2191 */
40381db7
DS
2192 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2193 && (pi != old_select))
2194 bgp_path_info_reap(rn, pi);
d62a17ae 2195
ddb5b488 2196 if (debug)
40381db7
DS
2197 zlog_debug("%s: pi %p in holddown", __func__,
2198 pi);
ddb5b488 2199
d62a17ae 2200 continue;
2201 }
96450faf 2202
40381db7
DS
2203 if (pi->peer && pi->peer != bgp->peer_self
2204 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2205 if (pi->peer->status != Established) {
ddb5b488
PZ
2206
2207 if (debug)
2208 zlog_debug(
40381db7
DS
2209 "%s: pi %p non self peer %s not estab state",
2210 __func__, pi, pi->peer->host);
ddb5b488 2211
d62a17ae 2212 continue;
ddb5b488 2213 }
9fbdd100 2214
d62a17ae 2215 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
40381db7
DS
2216 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
2217 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2218 if (debug)
40381db7 2219 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2220 continue;
2221 }
9fbdd100 2222
40381db7 2223 bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
06370dac 2224
40381db7 2225 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
fdf81fa0 2226 debug, pfx_buf, afi, safi, &rn->reason)) {
40381db7 2227 new_select = pi;
d62a17ae 2228 }
2229 }
718e3744 2230
d62a17ae 2231 /* Now that we know which path is the bestpath see if any of the other
2232 * paths
2233 * qualify as multipaths
2234 */
2235 if (debug) {
2236 if (new_select)
18ee8310
DS
2237 bgp_path_info_path_with_addpath_rx_str(new_select,
2238 path_buf);
d62a17ae 2239 else
2240 sprintf(path_buf, "NONE");
2241 zlog_debug(
2242 "%s: After path selection, newbest is %s oldbest was %s",
2243 pfx_buf, path_buf,
2244 old_select ? old_select->peer->host : "NONE");
96450faf 2245 }
9fbdd100 2246
d62a17ae 2247 if (do_mpath && new_select) {
6f94b685
DS
2248 for (pi = bgp_node_get_bgp_path_info(rn);
2249 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2250
2251 if (debug)
18ee8310 2252 bgp_path_info_path_with_addpath_rx_str(
40381db7 2253 pi, path_buf);
d62a17ae 2254
40381db7 2255 if (pi == new_select) {
d62a17ae 2256 if (debug)
2257 zlog_debug(
2258 "%s: %s is the bestpath, add to the multipath list",
2259 pfx_buf, path_buf);
40381db7 2260 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2261 continue;
2262 }
2263
40381db7 2264 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2265 continue;
2266
40381db7
DS
2267 if (pi->peer && pi->peer != bgp->peer_self
2268 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2269 PEER_STATUS_NSF_WAIT))
40381db7 2270 if (pi->peer->status != Established)
d62a17ae 2271 continue;
2272
40381db7 2273 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2274 if (debug)
2275 zlog_debug(
2276 "%s: %s has the same nexthop as the bestpath, skip it",
2277 pfx_buf, path_buf);
2278 continue;
2279 }
2280
40381db7 2281 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0
DS
2282 mpath_cfg, debug, pfx_buf, afi, safi,
2283 &rn->reason);
d62a17ae 2284
2285 if (paths_eq) {
2286 if (debug)
2287 zlog_debug(
2288 "%s: %s is equivalent to the bestpath, add to the multipath list",
2289 pfx_buf, path_buf);
40381db7 2290 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2291 }
2292 }
2293 }
fee0f4c6 2294
18ee8310
DS
2295 bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list,
2296 mpath_cfg);
2297 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2298 bgp_mp_list_clear(&mp_list);
96450faf 2299
dcc68b5e
MS
2300 bgp_addpath_update_ids(bgp, rn, afi, safi);
2301
d62a17ae 2302 result->old = old_select;
2303 result->new = new_select;
96450faf 2304
d62a17ae 2305 return;
fee0f4c6 2306}
2307
3f9c7369
DS
2308/*
2309 * A new route/change in bestpath of an existing route. Evaluate the path
2310 * for advertisement to the subgroup.
2311 */
d62a17ae 2312int subgroup_process_announce_selected(struct update_subgroup *subgrp,
4b7e6066 2313 struct bgp_path_info *selected,
d62a17ae 2314 struct bgp_node *rn,
d7c0a89a 2315 uint32_t addpath_tx_id)
d62a17ae 2316{
2317 struct prefix *p;
2318 struct peer *onlypeer;
2319 struct attr attr;
2320 afi_t afi;
2321 safi_t safi;
adbac85e 2322
d62a17ae 2323 p = &rn->p;
2324 afi = SUBGRP_AFI(subgrp);
2325 safi = SUBGRP_SAFI(subgrp);
2326 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2327 : NULL);
2328
e0207895
PZ
2329 if (BGP_DEBUG(update, UPDATE_OUT)) {
2330 char buf_prefix[PREFIX_STRLEN];
2331 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2332 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2333 selected);
e0207895
PZ
2334 }
2335
d62a17ae 2336 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2337 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2338 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 2339 return 0;
2340
2341 memset(&attr, 0, sizeof(struct attr));
2342 /* It's initialized in bgp_announce_check() */
2343
2344 /* Announcement to the subgroup. If the route is filtered withdraw it.
2345 */
2346 if (selected) {
2347 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
2348 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
2349 else
2350 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
dcc68b5e 2351 addpath_tx_id);
d62a17ae 2352 }
2353
2354 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2355 else {
2356 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
2357 }
558d1fec 2358
d62a17ae 2359 return 0;
200df115 2360}
fee0f4c6 2361
3064bf43 2362/*
e1072051 2363 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2364 * This is called at the end of route processing.
3064bf43 2365 */
d62a17ae 2366void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 2367{
40381db7 2368 struct bgp_path_info *pi;
3064bf43 2369
6f94b685 2370 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 2371 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2372 continue;
40381db7
DS
2373 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2374 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2375 }
3064bf43 2376}
2377
2378/*
2379 * Has the route changed from the RIB's perspective? This is invoked only
2380 * if the route selection returns the same best route as earlier - to
2381 * determine if we need to update zebra or not.
2382 */
4b7e6066
DS
2383int bgp_zebra_has_route_changed(struct bgp_node *rn,
2384 struct bgp_path_info *selected)
d62a17ae 2385{
4b7e6066 2386 struct bgp_path_info *mpinfo;
d62a17ae 2387
2bb9eff4
DS
2388 /* If this is multipath, check all selected paths for any nexthop
2389 * change or attribute change. Some attribute changes (e.g., community)
2390 * aren't of relevance to the RIB, but we'll update zebra to ensure
2391 * we handle the case of BGP nexthop change. This is the behavior
2392 * when the best path has an attribute change anyway.
d62a17ae 2393 */
1defdda8
DS
2394 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
2395 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
d62a17ae 2396 return 1;
2397
2bb9eff4
DS
2398 /*
2399 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2400 */
18ee8310
DS
2401 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2402 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2403 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2404 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
d62a17ae 2405 return 1;
2406 }
3064bf43 2407
d62a17ae 2408 /* Nothing has changed from the RIB's perspective. */
2409 return 0;
3064bf43 2410}
2411
d62a17ae 2412struct bgp_process_queue {
2413 struct bgp *bgp;
a4d82a8a 2414 STAILQ_HEAD(, bgp_node) pqueue;
aac24838
JB
2415#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2416 unsigned int flags;
2417 unsigned int queued;
200df115 2418};
2419
3103e8d2
DS
2420/*
2421 * old_select = The old best path
2422 * new_select = the new best path
2423 *
2424 * if (!old_select && new_select)
2425 * We are sending new information on.
2426 *
2427 * if (old_select && new_select) {
2428 * if (new_select != old_select)
2429 * We have a new best path send a change
2430 * else
2431 * We've received a update with new attributes that needs
2432 * to be passed on.
2433 * }
2434 *
2435 * if (old_select && !new_select)
2436 * We have no eligible route that we can announce or the rn
2437 * is being removed.
2438 */
aac24838
JB
2439static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2440 afi_t afi, safi_t safi)
d62a17ae 2441{
4b7e6066
DS
2442 struct bgp_path_info *new_select;
2443 struct bgp_path_info *old_select;
2444 struct bgp_path_info_pair old_and_new;
ddb5b488
PZ
2445 char pfx_buf[PREFIX2STR_BUFFER];
2446 int debug = 0;
d62a17ae 2447
f4c713ae
LB
2448 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
2449 if (rn)
2450 debug = bgp_debug_bestpath(&rn->p);
2451 if (debug) {
2452 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2453 zlog_debug(
2454 "%s: bgp delete in progress, ignoring event, p=%s",
2455 __func__, pfx_buf);
2456 }
2457 return;
2458 }
d62a17ae 2459 /* Is it end of initial update? (after startup) */
2460 if (!rn) {
2461 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2462 sizeof(bgp->update_delay_zebra_resume_time));
2463
2464 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2465 FOREACH_AFI_SAFI (afi, safi) {
2466 if (bgp_fibupd_safi(safi))
2467 bgp_zebra_announce_table(bgp, afi, safi);
2468 }
d62a17ae 2469 bgp->main_peers_update_hold = 0;
2470
2471 bgp_start_routeadv(bgp);
aac24838 2472 return;
d62a17ae 2473 }
cb1faec9 2474
b575a12c
A
2475 struct prefix *p = &rn->p;
2476
ddb5b488
PZ
2477 debug = bgp_debug_bestpath(&rn->p);
2478 if (debug) {
2479 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2480 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
2481 afi2str(afi), safi2str(safi));
2482 }
2483
f009ff26 2484 /* The best path calculation for the route is deferred if
2485 * BGP_NODE_SELECT_DEFER is set
2486 */
2487 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2488 if (BGP_DEBUG(update, UPDATE_OUT))
2ba1fe69 2489 zlog_debug("SELECT_DEFER falg set for route %p", rn);
f009ff26 2490 return;
2491 }
2492
d62a17ae 2493 /* Best path selection. */
2494 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2495 afi, safi);
2496 old_select = old_and_new.old;
2497 new_select = old_and_new.new;
2498
2499 /* Do we need to allocate or free labels?
2500 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2501 * necessary to do this upon changes to best path. Exceptions:
2502 * - label index has changed -> recalculate resulting label
2503 * - path_info sub_type changed -> switch to/from implicit-null
2504 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2505 */
318cac96 2506 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2507 if (new_select) {
2508 if (!old_select
2509 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2510 || new_select->sub_type != old_select->sub_type
2511 || !bgp_is_valid_label(&rn->local_label)) {
2512 /* Enforced penultimate hop popping:
2513 * implicit-null for local routes, aggregate
2514 * and redistributed routes
2515 */
d62a17ae 2516 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2517 || new_select->sub_type
2518 == BGP_ROUTE_AGGREGATE
2519 || new_select->sub_type
2520 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2521 if (CHECK_FLAG(
2522 rn->flags,
2523 BGP_NODE_REGISTERED_FOR_LABEL))
2524 bgp_unregister_for_label(rn);
70e98a7f 2525 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2526 &rn->local_label);
2527 bgp_set_valid_label(&rn->local_label);
2528 } else
2529 bgp_register_for_label(rn, new_select);
2530 }
a4d82a8a
PZ
2531 } else if (CHECK_FLAG(rn->flags,
2532 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2533 bgp_unregister_for_label(rn);
318cac96
DW
2534 }
2535 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2536 bgp_unregister_for_label(rn);
d62a17ae 2537 }
cd1964ff 2538
ddb5b488
PZ
2539 if (debug) {
2540 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2541 zlog_debug(
2542 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2543 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2544 old_select, new_select);
2545 }
2546
d62a17ae 2547 /* If best route remains the same and this is not due to user-initiated
2548 * clear, see exactly what needs to be done.
2549 */
d62a17ae 2550 if (old_select && old_select == new_select
2551 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2552 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2553 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2554 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2555#if ENABLE_BGP_VNC
d62a17ae 2556 vnc_import_bgp_add_route(bgp, p, old_select);
2557 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2558#endif
bb744275 2559 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2560 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2561
2562 if (new_select->type == ZEBRA_ROUTE_BGP
2563 && (new_select->sub_type == BGP_ROUTE_NORMAL
2564 || new_select->sub_type
2565 == BGP_ROUTE_IMPORTED))
2566
2567 bgp_zebra_announce(rn, p, old_select,
2568 bgp, afi, safi);
2569 }
d62a17ae 2570 }
1defdda8 2571 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2572 bgp_zebra_clear_route_change_flags(rn);
2573
2574 /* If there is a change of interest to peers, reannounce the
2575 * route. */
1defdda8 2576 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2577 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2578 group_announce_route(bgp, afi, safi, rn, new_select);
2579
2580 /* unicast routes must also be annouced to
2581 * labeled-unicast update-groups */
2582 if (safi == SAFI_UNICAST)
2583 group_announce_route(bgp, afi,
2584 SAFI_LABELED_UNICAST, rn,
2585 new_select);
2586
1defdda8 2587 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2588 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2589 }
fee0f4c6 2590
d62a17ae 2591 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2592 return;
d62a17ae 2593 }
8ad7271d 2594
d62a17ae 2595 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2596 */
2597 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2598
2599 /* bestpath has changed; bump version */
2600 if (old_select || new_select) {
2601 bgp_bump_version(rn);
2602
2603 if (!bgp->t_rmap_def_originate_eval) {
2604 bgp_lock(bgp);
2605 thread_add_timer(
2606 bm->master,
2607 update_group_refresh_default_originate_route_map,
2608 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2609 &bgp->t_rmap_def_originate_eval);
2610 }
2611 }
3f9c7369 2612
d62a17ae 2613 if (old_select)
18ee8310 2614 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2615 if (new_select) {
ddb5b488
PZ
2616 if (debug)
2617 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2618 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2619 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2620 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2621 }
338b3424 2622
65efcfce 2623#if ENABLE_BGP_VNC
d62a17ae 2624 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2625 if (old_select != new_select) {
2626 if (old_select) {
2627 vnc_import_bgp_exterior_del_route(bgp, p,
2628 old_select);
2629 vnc_import_bgp_del_route(bgp, p, old_select);
2630 }
2631 if (new_select) {
2632 vnc_import_bgp_exterior_add_route(bgp, p,
2633 new_select);
2634 vnc_import_bgp_add_route(bgp, p, new_select);
2635 }
2636 }
2637 }
65efcfce
LB
2638#endif
2639
d62a17ae 2640 group_announce_route(bgp, afi, safi, rn, new_select);
2641
2642 /* unicast routes must also be annouced to labeled-unicast update-groups
2643 */
2644 if (safi == SAFI_UNICAST)
2645 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2646 new_select);
2647
2648 /* FIB update. */
2649 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2650 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2651 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2652 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2653 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2654 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2655
2656 /* if this is an evpn imported type-5 prefix,
2657 * we need to withdraw the route first to clear
2658 * the nh neigh and the RMAC entry.
2659 */
2660 if (old_select &&
2661 is_route_parent_evpn(old_select))
2662 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2663
d62a17ae 2664 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2665 } else {
d62a17ae 2666 /* Withdraw the route from the kernel. */
2667 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2668 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2669 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2670 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2671
568e10ca 2672 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2673 }
718e3744 2674 }
3064bf43 2675
5424b7ba
MK
2676 /* advertise/withdraw type-5 routes */
2677 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2678 if (advertise_type5_routes(bgp, afi) &&
2679 new_select &&
2680 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2681
2682 /* apply the route-map */
2683 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2684 route_map_result_t ret;
7e4ed18e 2685
3518f352
DS
2686 ret = route_map_apply(
2687 bgp->adv_cmd_rmap[afi][safi].map,
2688 &rn->p, RMAP_BGP, new_select);
b68885f9 2689 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2690 bgp_evpn_advertise_type5_route(
2691 bgp, &rn->p, new_select->attr,
2692 afi, safi);
c27ee4c4 2693 else
2694 bgp_evpn_withdraw_type5_route(
2695 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2696 } else {
2697 bgp_evpn_advertise_type5_route(bgp,
2698 &rn->p,
2699 new_select->attr,
2700 afi, safi);
2701
2702 }
f106e3a7 2703 } else if (advertise_type5_routes(bgp, afi) &&
2704 old_select &&
2705 is_route_injectable_into_evpn(old_select))
31310b25 2706 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2707 }
2708
d62a17ae 2709 /* Clear any route change flags. */
2710 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2711
18ee8310 2712 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2713 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2714 bgp_path_info_reap(rn, old_select);
d62a17ae 2715
2716 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2717 return;
718e3744 2718}
2719
f009ff26 2720/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2721int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2722{
2723 struct bgp_node *rn;
2724 int cnt = 0;
2725 struct afi_safi_info *thread_info;
2726 struct listnode *node = NULL, *nnode = NULL;
2727
2728 if (bgp->gr_info[afi][safi].t_route_select)
2729 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2730
2731 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2732 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2733 get_afi_safi_str(afi, safi, false),
2734 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2735 }
2736
2737 /* Process the route list */
2738 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2739 while (node) {
2740 rn = listgetdata(node);
2741 nnode = node->next;
2742 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
2743 rn->rt_node = NULL;
2744
2745 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2746 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
2747 bgp_process_main_one(bgp, rn, afi, safi);
2748 cnt++;
2749 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2750 break;
2751 }
2752 node = nnode;
2753 }
2754
9e3b51a7 2755 /* Send EOR message when all routes are processed */
2756 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2757 bgp_send_delayed_eor(bgp);
8c48b3b6 2758 /* Send route processing complete message to RIB */
2759 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2760 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2761 return 0;
9e3b51a7 2762 }
f009ff26 2763
2764 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2765
2766 thread_info->afi = afi;
2767 thread_info->safi = safi;
2768 thread_info->bgp = bgp;
2769
2770 /* If there are more routes to be processed, start the
2771 * selection timer
2772 */
2773 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2774 BGP_ROUTE_SELECT_DELAY,
2775 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2776 return 0;
2777}
2778
aac24838 2779static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2780{
aac24838
JB
2781 struct bgp_process_queue *pqnode = data;
2782 struct bgp *bgp = pqnode->bgp;
d62a17ae 2783 struct bgp_table *table;
ac021f40 2784 struct bgp_node *rn;
aac24838
JB
2785
2786 /* eoiu marker */
2787 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2788 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2789 /* should always have dedicated wq call */
2790 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2791 return WQ_SUCCESS;
2792 }
2793
ac021f40
LB
2794 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2795 rn = STAILQ_FIRST(&pqnode->pqueue);
2796 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2797 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2798 table = bgp_node_table(rn);
ac021f40 2799 /* note, new RNs may be added as part of processing */
aac24838 2800 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2801
aac24838 2802 bgp_unlock_node(rn);
d62a17ae 2803 bgp_table_unlock(table);
2804 }
aac24838
JB
2805
2806 return WQ_SUCCESS;
2807}
2808
2809static void bgp_processq_del(struct work_queue *wq, void *data)
2810{
2811 struct bgp_process_queue *pqnode = data;
2812
2813 bgp_unlock(pqnode->bgp);
2814
2815 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2816}
2817
d62a17ae 2818void bgp_process_queue_init(void)
200df115 2819{
0ce1ca80 2820 if (!bm->process_main_queue)
d62a17ae 2821 bm->process_main_queue =
2822 work_queue_new(bm->master, "process_main_queue");
2823
aac24838 2824 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2825 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2826 bm->process_main_queue->spec.max_retries = 0;
2827 bm->process_main_queue->spec.hold = 50;
2828 /* Use a higher yield value of 50ms for main queue processing */
2829 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2830}
2831
cfe8d15a 2832static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2833{
2834 struct bgp_process_queue *pqnode;
2835
a4d82a8a
PZ
2836 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2837 sizeof(struct bgp_process_queue));
aac24838
JB
2838
2839 /* unlocked in bgp_processq_del */
2840 pqnode->bgp = bgp_lock(bgp);
2841 STAILQ_INIT(&pqnode->pqueue);
2842
aac24838
JB
2843 return pqnode;
2844}
2845
d62a17ae 2846void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2847{
aac24838
JB
2848#define ARBITRARY_PROCESS_QLEN 10000
2849 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2850 struct bgp_process_queue *pqnode;
cfe8d15a 2851 int pqnode_reuse = 0;
495f0b13 2852
d62a17ae 2853 /* already scheduled for processing? */
2854 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2855 return;
2e02b9b2 2856
f009ff26 2857 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2858 * the workqueue
2859 */
2860 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2861 if (BGP_DEBUG(update, UPDATE_OUT))
2862 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
36235319 2863 rn);
f009ff26 2864 return;
2865 }
2866
aac24838 2867 if (wq == NULL)
d62a17ae 2868 return;
2869
aac24838 2870 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2871 limit only if is from the same BGP view and it's not an EOIU marker
2872 */
aac24838
JB
2873 if (work_queue_item_count(wq)) {
2874 struct work_queue_item *item = work_queue_last_item(wq);
2875 pqnode = item->data;
228da428 2876
a4d82a8a
PZ
2877 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2878 || pqnode->bgp != bgp
2879 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2880 pqnode = bgp_processq_alloc(bgp);
2881 else
2882 pqnode_reuse = 1;
aac24838 2883 } else
cfe8d15a 2884 pqnode = bgp_processq_alloc(bgp);
aac24838 2885 /* all unlocked in bgp_process_wq */
d62a17ae 2886 bgp_table_lock(bgp_node_table(rn));
aac24838 2887
d62a17ae 2888 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2889 bgp_lock_node(rn);
2890
60466a63
QY
2891 /* can't be enqueued twice */
2892 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2893 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2894 pqnode->queued++;
2895
cfe8d15a
LB
2896 if (!pqnode_reuse)
2897 work_queue_add(wq, pqnode);
2898
d62a17ae 2899 return;
fee0f4c6 2900}
0a486e5f 2901
d62a17ae 2902void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2903{
d62a17ae 2904 struct bgp_process_queue *pqnode;
cb1faec9 2905
d62a17ae 2906 if (bm->process_main_queue == NULL)
2907 return;
2e02b9b2 2908
cfe8d15a 2909 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2910
aac24838 2911 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2912 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2913}
2914
d62a17ae 2915static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2916{
d62a17ae 2917 struct peer *peer;
0a486e5f 2918
d62a17ae 2919 peer = THREAD_ARG(thread);
2920 peer->t_pmax_restart = NULL;
0a486e5f 2921
d62a17ae 2922 if (bgp_debug_neighbor_events(peer))
2923 zlog_debug(
2924 "%s Maximum-prefix restart timer expired, restore peering",
2925 peer->host);
0a486e5f 2926
a9bafa95
DS
2927 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
2928 zlog_debug("%s: %s peer_clear failed",
2929 __PRETTY_FUNCTION__, peer->host);
0a486e5f 2930
d62a17ae 2931 return 0;
0a486e5f 2932}
2933
d62a17ae 2934int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2935 int always)
718e3744 2936{
d62a17ae 2937 iana_afi_t pkt_afi;
5c525538 2938 iana_safi_t pkt_safi;
9cabb64b 2939
d62a17ae 2940 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2941 return 0;
e0701b79 2942
d62a17ae 2943 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2944 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2945 PEER_STATUS_PREFIX_LIMIT)
2946 && !always)
2947 return 0;
e0701b79 2948
d62a17ae 2949 zlog_info(
a0a87037
DA
2950 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2951 " exceed, limit %" PRIu32,
5cb5f4d0 2952 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2953 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2954 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2955
2956 if (CHECK_FLAG(peer->af_flags[afi][safi],
2957 PEER_FLAG_MAX_PREFIX_WARNING))
2958 return 0;
2959
2960 /* Convert AFI, SAFI to values for packet. */
2961 pkt_afi = afi_int2iana(afi);
2962 pkt_safi = safi_int2iana(safi);
2963 {
d7c0a89a 2964 uint8_t ndata[7];
d62a17ae 2965
2966 ndata[0] = (pkt_afi >> 8);
2967 ndata[1] = pkt_afi;
2968 ndata[2] = pkt_safi;
2969 ndata[3] = (peer->pmax[afi][safi] >> 24);
2970 ndata[4] = (peer->pmax[afi][safi] >> 16);
2971 ndata[5] = (peer->pmax[afi][safi] >> 8);
2972 ndata[6] = (peer->pmax[afi][safi]);
2973
2974 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2975 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2976 BGP_NOTIFY_CEASE_MAX_PREFIX,
2977 ndata, 7);
2978 }
2979
2980 /* Dynamic peers will just close their connection. */
2981 if (peer_dynamic_neighbor(peer))
2982 return 1;
2983
2984 /* restart timer start */
2985 if (peer->pmax_restart[afi][safi]) {
2986 peer->v_pmax_restart =
2987 peer->pmax_restart[afi][safi] * 60;
2988
2989 if (bgp_debug_neighbor_events(peer))
2990 zlog_debug(
2991 "%s Maximum-prefix restart timer started for %d secs",
2992 peer->host, peer->v_pmax_restart);
2993
2994 BGP_TIMER_ON(peer->t_pmax_restart,
2995 bgp_maximum_prefix_restart_timer,
2996 peer->v_pmax_restart);
2997 }
2998
2999 return 1;
3000 } else
3001 UNSET_FLAG(peer->af_sflags[afi][safi],
3002 PEER_STATUS_PREFIX_LIMIT);
3003
3004 if (peer->pcount[afi][safi]
3005 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3006 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3007 PEER_STATUS_PREFIX_THRESHOLD)
3008 && !always)
3009 return 0;
3010
3011 zlog_info(
a0a87037
DA
3012 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3013 ", max %" PRIu32,
5cb5f4d0 3014 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3015 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3016 SET_FLAG(peer->af_sflags[afi][safi],
3017 PEER_STATUS_PREFIX_THRESHOLD);
3018 } else
3019 UNSET_FLAG(peer->af_sflags[afi][safi],
3020 PEER_STATUS_PREFIX_THRESHOLD);
3021 return 0;
718e3744 3022}
3023
b40d939b 3024/* Unconditionally remove the route from the RIB, without taking
3025 * damping into consideration (eg, because the session went down)
3026 */
40381db7 3027void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 3028 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3029{
f009ff26 3030
3031 struct bgp *bgp = NULL;
3032 bool delete_route = false;
3033
40381db7 3034 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 3035
f009ff26 3036 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
40381db7 3037 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 3038
f009ff26 3039 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3040 * flag
3041 */
3042 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3043 delete_route = true;
36235319
QY
3044 else if (bgp_node_set_defer_flag(rn, true) < 0)
3045 delete_route = true;
f009ff26 3046 if (delete_route) {
3047 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
3048 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3049 bgp = pi->peer->bgp;
36235319
QY
3050 if ((rn->rt_node)
3051 && (bgp->gr_info[afi][safi].route_list)) {
3052 list_delete_node(bgp->gr_info[afi][safi]
3053 .route_list,
3054 rn->rt_node);
f009ff26 3055 rn->rt_node = NULL;
3056 }
3057 }
3058 }
3059 }
4a11bf2c 3060
f009ff26 3061 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
d62a17ae 3062 bgp_process(peer->bgp, rn, afi, safi);
3063}
3064
40381db7 3065static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 3066 struct peer *peer, afi_t afi, safi_t safi,
3067 struct prefix_rd *prd)
3068{
d62a17ae 3069 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3070 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3071 */
3072 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3073 && peer->sort == BGP_PEER_EBGP)
40381db7 3074 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 3075 == BGP_DAMP_SUPPRESSED) {
40381db7 3076 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 3077 safi);
3078 return;
3079 }
3080
65efcfce 3081#if ENABLE_BGP_VNC
d62a17ae 3082 if (safi == SAFI_MPLS_VPN) {
3083 struct bgp_node *prn = NULL;
3084 struct bgp_table *table = NULL;
3085
3086 prn = bgp_node_get(peer->bgp->rib[afi][safi],
3087 (struct prefix *)prd);
67009e22
DS
3088 if (bgp_node_has_bgp_path_info_data(prn)) {
3089 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3090
3091 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3092 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 3093 }
3094 bgp_unlock_node(prn);
3095 }
3096 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3097 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3098
40381db7 3099 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 3100 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 3101 pi);
d62a17ae 3102 }
65efcfce 3103 }
d62a17ae 3104#endif
128ea8ab 3105
d62a17ae 3106 /* If this is an EVPN route, process for un-import. */
3107 if (safi == SAFI_EVPN)
40381db7 3108 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 3109
40381db7 3110 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 3111}
3112
4b7e6066
DS
3113struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3114 struct peer *peer, struct attr *attr,
3115 struct bgp_node *rn)
fb018d25 3116{
4b7e6066 3117 struct bgp_path_info *new;
fb018d25 3118
d62a17ae 3119 /* Make new BGP info. */
4b7e6066 3120 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3121 new->type = type;
3122 new->instance = instance;
3123 new->sub_type = sub_type;
3124 new->peer = peer;
3125 new->attr = attr;
3126 new->uptime = bgp_clock();
3127 new->net = rn;
d62a17ae 3128 return new;
fb018d25
DS
3129}
3130
d62a17ae 3131static void overlay_index_update(struct attr *attr,
3132 struct eth_segment_id *eth_s_id,
3133 union gw_addr *gw_ip)
684a7227 3134{
d62a17ae 3135 if (!attr)
3136 return;
684a7227 3137
d62a17ae 3138 if (eth_s_id == NULL) {
3139 memset(&(attr->evpn_overlay.eth_s_id), 0,
3140 sizeof(struct eth_segment_id));
3141 } else {
3142 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3143 sizeof(struct eth_segment_id));
3144 }
3145 if (gw_ip == NULL) {
3146 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3147 } else {
3148 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3149 sizeof(union gw_addr));
3150 }
684a7227
PG
3151}
3152
40381db7 3153static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3154 struct eth_segment_id *eth_s_id,
3155 union gw_addr *gw_ip)
3156{
40381db7
DS
3157 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3158 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3159 union {
3160 struct eth_segment_id esi;
3161 union gw_addr ip;
3162 } temp;
d62a17ae 3163
3164 if (afi != AFI_L2VPN)
3165 return true;
11ebf4ed 3166
05864da7
DS
3167 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3168 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3169
3170 if (gw_ip == NULL) {
3171 memset(&temp, 0, sizeof(temp));
40381db7 3172 path_gw_ip_remote = &temp.ip;
11ebf4ed 3173 } else
40381db7 3174 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3175
3176 if (eth_s_id == NULL) {
3177 memset(&temp, 0, sizeof(temp));
40381db7 3178 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3179 } else
40381db7 3180 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3181
40381db7 3182 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3183 return false;
11ebf4ed 3184
40381db7 3185 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3186 sizeof(struct eth_segment_id));
684a7227
PG
3187}
3188
c265ee22 3189/* Check if received nexthop is valid or not. */
d62a17ae 3190static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
949b0f24 3191 uint8_t type, uint8_t stype,
3192 struct attr *attr, struct bgp_node *rn)
d62a17ae 3193{
3194 int ret = 0;
3195
3196 /* Only validated for unicast and multicast currently. */
3197 /* Also valid for EVPN where the nexthop is an IP address. */
3198 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3199 return 0;
3200
3201 /* If NEXT_HOP is present, validate it. */
3202 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
3203 if (attr->nexthop.s_addr == 0
3204 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
949b0f24 3205 || bgp_nexthop_self(bgp, afi, type, stype,
3206 attr, rn))
d62a17ae 3207 return 1;
3208 }
c265ee22 3209
d62a17ae 3210 /* If MP_NEXTHOP is present, validate it. */
3211 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3212 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3213 * it is not an IPv6 link-local address.
3214 */
3215 if (attr->mp_nexthop_len) {
3216 switch (attr->mp_nexthop_len) {
3217 case BGP_ATTR_NHLEN_IPV4:
3218 case BGP_ATTR_NHLEN_VPNV4:
3219 ret = (attr->mp_nexthop_global_in.s_addr == 0
3220 || IPV4_CLASS_DE(ntohl(
3221 attr->mp_nexthop_global_in.s_addr))
949b0f24 3222 || bgp_nexthop_self(bgp, afi, type, stype,
3223 attr, rn));
d62a17ae 3224 break;
3225
3226 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3227 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3228 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3229 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3230 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3231 || IN6_IS_ADDR_MULTICAST(
949b0f24 3232 &attr->mp_nexthop_global)
3233 || bgp_nexthop_self(bgp, afi, type, stype,
3234 attr, rn));
d62a17ae 3235 break;
3236
3237 default:
3238 ret = 1;
3239 break;
3240 }
3241 }
c265ee22 3242
d62a17ae 3243 return ret;
3244}
3245
d7c0a89a 3246int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3247 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3248 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3249 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3250 struct bgp_route_evpn *evpn)
d62a17ae 3251{
3252 int ret;
3253 int aspath_loop_count = 0;
3254 struct bgp_node *rn;
3255 struct bgp *bgp;
3256 struct attr new_attr;
3257 struct attr *attr_new;
40381db7 3258 struct bgp_path_info *pi;
4b7e6066
DS
3259 struct bgp_path_info *new;
3260 struct bgp_path_info_extra *extra;
d62a17ae 3261 const char *reason;
3262 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3263 int connected = 0;
3264 int do_loop_check = 1;
3265 int has_valid_label = 0;
7c312383 3266 afi_t nh_afi;
949b0f24 3267 uint8_t pi_type = 0;
3268 uint8_t pi_sub_type = 0;
3269
65efcfce 3270#if ENABLE_BGP_VNC
d62a17ae 3271 int vnc_implicit_withdraw = 0;
65efcfce 3272#endif
d62a17ae 3273 int same_attr = 0;
718e3744 3274
d62a17ae 3275 memset(&new_attr, 0, sizeof(struct attr));
3276 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3277 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3278
d62a17ae 3279 bgp = peer->bgp;
3280 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3281 /* TODO: Check to see if we can get rid of "is_valid_label" */
3282 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3283 has_valid_label = (num_labels > 0) ? 1 : 0;
3284 else
3285 has_valid_label = bgp_is_valid_label(label);
718e3744 3286
d62a17ae 3287 /* When peer's soft reconfiguration enabled. Record input packet in
3288 Adj-RIBs-In. */
3289 if (!soft_reconfig
3290 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3291 && peer != bgp->peer_self)
3292 bgp_adj_in_set(rn, peer, attr, addpath_id);
3293
3294 /* Check previously received route. */
6f94b685 3295 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3296 if (pi->peer == peer && pi->type == type
3297 && pi->sub_type == sub_type
3298 && pi->addpath_rx_id == addpath_id)
d62a17ae 3299 break;
3300
3301 /* AS path local-as loop check. */
3302 if (peer->change_local_as) {
c4368918
DW
3303 if (peer->allowas_in[afi][safi])
3304 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3305 else if (!CHECK_FLAG(peer->flags,
3306 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3307 aspath_loop_count = 1;
3308
3309 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3310 > aspath_loop_count) {
b4d46cc9 3311 peer->stat_pfx_aspath_loop++;
d62a17ae 3312 reason = "as-path contains our own AS;";
3313 goto filtered;
3314 }
718e3744 3315 }
718e3744 3316
d62a17ae 3317 /* If the peer is configured for "allowas-in origin" and the last ASN in
3318 * the
3319 * as-path is our ASN then we do not need to call aspath_loop_check
3320 */
3321 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3322 if (aspath_get_last_as(attr->aspath) == bgp->as)
3323 do_loop_check = 0;
3324
3325 /* AS path loop check. */
3326 if (do_loop_check) {
3327 if (aspath_loop_check(attr->aspath, bgp->as)
3328 > peer->allowas_in[afi][safi]
3329 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3330 && aspath_loop_check(attr->aspath, bgp->confed_id)
3331 > peer->allowas_in[afi][safi])) {
b4d46cc9 3332 peer->stat_pfx_aspath_loop++;
d62a17ae 3333 reason = "as-path contains our own AS;";
3334 goto filtered;
3335 }
3336 }
aac9ef6c 3337
d62a17ae 3338 /* Route reflector originator ID check. */
3339 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3340 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3341 peer->stat_pfx_originator_loop++;
d62a17ae 3342 reason = "originator is us;";
3343 goto filtered;
3344 }
718e3744 3345
d62a17ae 3346 /* Route reflector cluster ID check. */
3347 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3348 peer->stat_pfx_cluster_loop++;
d62a17ae 3349 reason = "reflected from the same cluster;";
3350 goto filtered;
3351 }
718e3744 3352
d62a17ae 3353 /* Apply incoming filter. */
3354 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3355 peer->stat_pfx_filter++;
d62a17ae 3356 reason = "filter;";
3357 goto filtered;
3358 }
718e3744 3359
a8b72dc6
DA
3360 /* RFC 8212 to prevent route leaks.
3361 * This specification intends to improve this situation by requiring the
3362 * explicit configuration of both BGP Import and Export Policies for any
3363 * External BGP (EBGP) session such as customers, peers, or
3364 * confederation boundaries for all enabled address families. Through
3365 * codification of the aforementioned requirement, operators will
3366 * benefit from consistent behavior across different BGP
3367 * implementations.
3368 */
3369 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3370 if (!bgp_inbound_policy_exists(peer,
3371 &peer->filter[afi][safi])) {
3372 reason = "inbound policy missing";
3373 goto filtered;
3374 }
3375
fb29348a
DA
3376 /* draft-ietf-idr-deprecate-as-set-confed-set
3377 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3378 * Eventually, This document (if approved) updates RFC 4271
3379 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3380 * and obsoletes RFC 6472.
3381 */
3382 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
3383 if (aspath_check_as_sets(attr->aspath)) {
3384 reason =
3385 "as-path contains AS_SET or AS_CONFED_SET type;";
3386 goto filtered;
3387 }
3388
6f4f49b2 3389 new_attr = *attr;
d62a17ae 3390
3391 /* Apply incoming route-map.
3392 * NB: new_attr may now contain newly allocated values from route-map
3393 * "set"
3394 * commands, so we need bgp_attr_flush in the error paths, until we
3395 * intern
3396 * the attr (which takes over the memory references) */
82b692c0 3397 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3398 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3399 peer->stat_pfx_filter++;
d62a17ae 3400 reason = "route-map;";
3401 bgp_attr_flush(&new_attr);
3402 goto filtered;
3403 }
718e3744 3404
05864da7 3405 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3406 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3407 /* remove from RIB previous entry */
3408 bgp_zebra_withdraw(p, pi, bgp, safi);
3409 }
3410
7f323236
DW
3411 if (peer->sort == BGP_PEER_EBGP) {
3412
a4d82a8a
PZ
3413 /* If we receive the graceful-shutdown community from an eBGP
3414 * peer we must lower local-preference */
3415 if (new_attr.community
3416 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3417 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3418 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3419
a4d82a8a
PZ
3420 /* If graceful-shutdown is configured then add the GSHUT
3421 * community to all paths received from eBGP peers */
3422 } else if (bgp_flag_check(peer->bgp,
3423 BGP_FLAG_GRACEFUL_SHUTDOWN)) {
7f323236
DW
3424 bgp_attr_add_gshut_community(&new_attr);
3425 }
3426 }
3427
949b0f24 3428 if (pi) {
3429 pi_type = pi->type;
3430 pi_sub_type = pi->sub_type;
3431 }
3432
d62a17ae 3433 /* next hop check. */
a4d82a8a 3434 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
949b0f24 3435 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type,
3436 pi_sub_type, &new_attr, rn)) {
b4d46cc9 3437 peer->stat_pfx_nh_invalid++;
d62a17ae 3438 reason = "martian or self next-hop;";
3439 bgp_attr_flush(&new_attr);
3440 goto filtered;
3441 }
718e3744 3442
5c14a191 3443 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3444 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3445 reason = "self mac;";
3446 goto filtered;
3447 }
3448
d62a17ae 3449 attr_new = bgp_attr_intern(&new_attr);
3450
3451 /* If the update is implicit withdraw. */
40381db7
DS
3452 if (pi) {
3453 pi->uptime = bgp_clock();
3454 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3455
4a11bf2c
DL
3456 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3457
d62a17ae 3458 /* Same attribute comes in. */
40381db7
DS
3459 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3460 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3461 && (!has_valid_label
40381db7 3462 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3463 num_labels * sizeof(mpls_label_t))
d62a17ae 3464 == 0)
3465 && (overlay_index_equal(
40381db7 3466 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3467 evpn == NULL ? NULL : &evpn->gw_ip))) {
3468 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3469 BGP_CONFIG_DAMPENING)
3470 && peer->sort == BGP_PEER_EBGP
40381db7 3471 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3472 if (bgp_debug_update(peer, p, NULL, 1)) {
3473 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3474 afi, safi, prd, p, label,
3475 num_labels, addpath_id ? 1 : 0,
3476 addpath_id, pfx_buf,
3477 sizeof(pfx_buf));
d62a17ae 3478 zlog_debug("%s rcvd %s", peer->host,
3479 pfx_buf);
3480 }
3481
40381db7 3482 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3483 != BGP_DAMP_SUPPRESSED) {
40381db7 3484 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3485 safi);
3486 bgp_process(bgp, rn, afi, safi);
3487 }
3488 } else /* Duplicate - odd */
3489 {
3490 if (bgp_debug_update(peer, p, NULL, 1)) {
3491 if (!peer->rcvd_attr_printed) {
3492 zlog_debug(
3493 "%s rcvd UPDATE w/ attr: %s",
3494 peer->host,
3495 peer->rcvd_attr_str);
3496 peer->rcvd_attr_printed = 1;
3497 }
3498
3499 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3500 afi, safi, prd, p, label,
3501 num_labels, addpath_id ? 1 : 0,
3502 addpath_id, pfx_buf,
3503 sizeof(pfx_buf));
d62a17ae 3504 zlog_debug(
3505 "%s rcvd %s...duplicate ignored",
3506 peer->host, pfx_buf);
3507 }
3508
3509 /* graceful restart STALE flag unset. */
40381db7 3510 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3511 bgp_path_info_unset_flag(
40381db7 3512 rn, pi, BGP_PATH_STALE);
f009ff26 3513 bgp_node_set_defer_flag(rn, false);
d62a17ae 3514 bgp_process(bgp, rn, afi, safi);
3515 }
3516 }
3517
3518 bgp_unlock_node(rn);
3519 bgp_attr_unintern(&attr_new);
3520
3521 return 0;
3522 }
718e3744 3523
d62a17ae 3524 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3525 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3526 if (bgp_debug_update(peer, p, NULL, 1)) {
3527 bgp_debug_rdpfxpath2str(
a4d82a8a 3528 afi, safi, prd, p, label, num_labels,
d62a17ae 3529 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3530 sizeof(pfx_buf));
3531 zlog_debug(
3532 "%s rcvd %s, flapped quicker than processing",
3533 peer->host, pfx_buf);
3534 }
3535
40381db7 3536 bgp_path_info_restore(rn, pi);
d62a17ae 3537 }
718e3744 3538
d62a17ae 3539 /* Received Logging. */
3540 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3541 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3542 num_labels, addpath_id ? 1 : 0,
3543 addpath_id, pfx_buf,
3544 sizeof(pfx_buf));
d62a17ae 3545 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3546 }
718e3744 3547
d62a17ae 3548 /* graceful restart STALE flag unset. */
f009ff26 3549 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
40381db7 3550 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
f009ff26 3551 bgp_node_set_defer_flag(rn, false);
3552 }
d62a17ae 3553
3554 /* The attribute is changed. */
40381db7 3555 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3556
3557 /* implicit withdraw, decrement aggregate and pcount here.
3558 * only if update is accepted, they'll increment below.
3559 */
40381db7 3560 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3561
3562 /* Update bgp route dampening information. */
3563 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3564 && peer->sort == BGP_PEER_EBGP) {
3565 /* This is implicit withdraw so we should update
3566 dampening
3567 information. */
40381db7
DS
3568 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3569 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3570 }
65efcfce 3571#if ENABLE_BGP_VNC
d62a17ae 3572 if (safi == SAFI_MPLS_VPN) {
3573 struct bgp_node *prn = NULL;
3574 struct bgp_table *table = NULL;
3575
3576 prn = bgp_node_get(bgp->rib[afi][safi],
3577 (struct prefix *)prd);
67009e22
DS
3578 if (bgp_node_has_bgp_path_info_data(prn)) {
3579 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3580
3581 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3582 bgp, prd, table, p, pi);
d62a17ae 3583 }
3584 bgp_unlock_node(prn);
3585 }
3586 if ((afi == AFI_IP || afi == AFI_IP6)
3587 && (safi == SAFI_UNICAST)) {
40381db7 3588 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3589 /*
3590 * Implicit withdraw case.
3591 */
3592 ++vnc_implicit_withdraw;
40381db7
DS
3593 vnc_import_bgp_del_route(bgp, p, pi);
3594 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3595 }
3596 }
65efcfce 3597#endif
128ea8ab 3598
d62a17ae 3599 /* Special handling for EVPN update of an existing route. If the
3600 * extended community attribute has changed, we need to
3601 * un-import
3602 * the route using its existing extended community. It will be
3603 * subsequently processed for import with the new extended
3604 * community.
3605 */
3606 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3607 if ((pi->attr->flag
d62a17ae 3608 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3609 && (attr_new->flag
3610 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3611 int cmp;
3612
40381db7 3613 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3614 attr_new->ecommunity);
3615 if (!cmp) {
3616 if (bgp_debug_update(peer, p, NULL, 1))
3617 zlog_debug(
3618 "Change in EXT-COMM, existing %s new %s",
3619 ecommunity_str(
40381db7 3620 pi->attr->ecommunity),
d62a17ae 3621 ecommunity_str(
3622 attr_new->ecommunity));
3623 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3624 p, pi);
d62a17ae 3625 }
3626 }
3627 }
718e3744 3628
d62a17ae 3629 /* Update to new attribute. */
40381db7
DS
3630 bgp_attr_unintern(&pi->attr);
3631 pi->attr = attr_new;
d62a17ae 3632
3633 /* Update MPLS label */
3634 if (has_valid_label) {
40381db7 3635 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3636 if (extra->label != label) {
3637 memcpy(&extra->label, label,
dbd587da 3638 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3639 extra->num_labels = num_labels;
3640 }
b57ba6d2
MK
3641 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3642 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3643 }
718e3744 3644
e496b420
HS
3645 /* Update SRv6 SID */
3646 if (attr->srv6_l3vpn) {
3647 extra = bgp_path_info_extra_get(pi);
3648 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3649 sid_copy(&extra->sid[0],
3650 &attr->srv6_l3vpn->sid);
3651 extra->num_sids = 1;
3652 }
3653 } else if (attr->srv6_vpn) {
3654 extra = bgp_path_info_extra_get(pi);
3655 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3656 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3657 extra->num_sids = 1;
3658 }
3659 }
3660
65efcfce 3661#if ENABLE_BGP_VNC
d62a17ae 3662 if ((afi == AFI_IP || afi == AFI_IP6)
3663 && (safi == SAFI_UNICAST)) {
3664 if (vnc_implicit_withdraw) {
3665 /*
3666 * Add back the route with its new attributes
3667 * (e.g., nexthop).
3668 * The route is still selected, until the route
3669 * selection
3670 * queued by bgp_process actually runs. We have
3671 * to make this
3672 * update to the VNC side immediately to avoid
3673 * racing against
3674 * configuration changes (e.g., route-map
3675 * changes) which
3676 * trigger re-importation of the entire RIB.
3677 */
40381db7
DS
3678 vnc_import_bgp_add_route(bgp, p, pi);
3679 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3680 }
3681 }
65efcfce 3682#endif
d62a17ae 3683 /* Update Overlay Index */
3684 if (afi == AFI_L2VPN) {
3685 overlay_index_update(
40381db7 3686 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3687 evpn == NULL ? NULL : &evpn->gw_ip);
3688 }
65efcfce 3689
d62a17ae 3690 /* Update bgp route dampening information. */
3691 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3692 && peer->sort == BGP_PEER_EBGP) {
3693 /* Now we do normal update dampening. */
40381db7 3694 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3695 if (ret == BGP_DAMP_SUPPRESSED) {
3696 bgp_unlock_node(rn);
3697 return 0;
3698 }
3699 }
128ea8ab 3700
d62a17ae 3701 /* Nexthop reachability check - for unicast and
3702 * labeled-unicast.. */
7c312383
AD
3703 if (((afi == AFI_IP || afi == AFI_IP6)
3704 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3705 || (safi == SAFI_EVPN &&
3706 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3707 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3708 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3709 && !CHECK_FLAG(peer->flags,
3710 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3711 && !bgp_flag_check(
3712 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3713 connected = 1;
3714 else
3715 connected = 0;
3716
960035b2
PZ
3717 struct bgp *bgp_nexthop = bgp;
3718
40381db7
DS
3719 if (pi->extra && pi->extra->bgp_orig)
3720 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3721
7c312383
AD
3722 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3723
3724 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3725 pi, NULL, connected)
a4d82a8a 3726 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3727 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3728 else {
3729 if (BGP_DEBUG(nht, NHT)) {
3730 char buf1[INET6_ADDRSTRLEN];
3731 inet_ntop(AF_INET,
3732 (const void *)&attr_new
3733 ->nexthop,
3734 buf1, INET6_ADDRSTRLEN);
3735 zlog_debug("%s(%s): NH unresolved",
3736 __FUNCTION__, buf1);
3737 }
40381db7 3738 bgp_path_info_unset_flag(rn, pi,
18ee8310 3739 BGP_PATH_VALID);
d62a17ae 3740 }
3741 } else
40381db7 3742 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3743
3744#if ENABLE_BGP_VNC
3745 if (safi == SAFI_MPLS_VPN) {
3746 struct bgp_node *prn = NULL;
3747 struct bgp_table *table = NULL;
3748
3749 prn = bgp_node_get(bgp->rib[afi][safi],
3750 (struct prefix *)prd);
67009e22
DS
3751 if (bgp_node_has_bgp_path_info_data(prn)) {
3752 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3753
3754 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3755 bgp, prd, table, p, pi);
d62a17ae 3756 }
3757 bgp_unlock_node(prn);
3758 }
3759#endif
718e3744 3760
d62a17ae 3761 /* If this is an EVPN route and some attribute has changed,
3762 * process
3763 * route for import. If the extended community has changed, we
3764 * would
3765 * have done the un-import earlier and the import would result
3766 * in the
3767 * route getting injected into appropriate L2 VNIs. If it is
3768 * just
3769 * some other attribute change, the import will result in
3770 * updating
3771 * the attributes for the route in the VNI(s).
3772 */
7c312383
AD
3773 if (safi == SAFI_EVPN && !same_attr &&
3774 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3775 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3776
3777 /* Process change. */
40381db7 3778 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3779
3780 bgp_process(bgp, rn, afi, safi);
3781 bgp_unlock_node(rn);
558d1fec 3782
ddb5b488
PZ
3783 if (SAFI_UNICAST == safi
3784 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3785 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3786
40381db7 3787 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3788 }
3789 if ((SAFI_MPLS_VPN == safi)
3790 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3791
40381db7 3792 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3793 }
3794
28070ee3 3795#if ENABLE_BGP_VNC
d62a17ae 3796 if (SAFI_MPLS_VPN == safi) {
3797 mpls_label_t label_decoded = decode_label(label);
28070ee3 3798
d62a17ae 3799 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3800 type, sub_type, &label_decoded);
3801 }
3802 if (SAFI_ENCAP == safi) {
3803 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3804 type, sub_type, NULL);
3805 }
28070ee3
PZ
3806#endif
3807
d62a17ae 3808 return 0;
3809 } // End of implicit withdraw
718e3744 3810
d62a17ae 3811 /* Received Logging. */
3812 if (bgp_debug_update(peer, p, NULL, 1)) {
3813 if (!peer->rcvd_attr_printed) {
3814 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3815 peer->rcvd_attr_str);
3816 peer->rcvd_attr_printed = 1;
3817 }
718e3744 3818
a4d82a8a 3819 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3820 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3821 sizeof(pfx_buf));
3822 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3823 }
718e3744 3824
d62a17ae 3825 /* Make new BGP info. */
3826 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3827
d62a17ae 3828 /* Update MPLS label */
3829 if (has_valid_label) {
18ee8310 3830 extra = bgp_path_info_extra_get(new);
8ba71050 3831 if (extra->label != label) {
dbd587da
QY
3832 memcpy(&extra->label, label,
3833 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3834 extra->num_labels = num_labels;
3835 }
b57ba6d2
MK
3836 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3837 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3838 }
718e3744 3839
e496b420
HS
3840 /* Update SRv6 SID */
3841 if (safi == SAFI_MPLS_VPN) {
3842 extra = bgp_path_info_extra_get(new);
3843 if (attr->srv6_l3vpn) {
3844 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3845 extra->num_sids = 1;
3846 } else if (attr->srv6_vpn) {
3847 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3848 extra->num_sids = 1;
3849 }
3850 }
3851
d62a17ae 3852 /* Update Overlay Index */
3853 if (afi == AFI_L2VPN) {
3854 overlay_index_update(new->attr,
3855 evpn == NULL ? NULL : &evpn->eth_s_id,
3856 evpn == NULL ? NULL : &evpn->gw_ip);
3857 }
3858 /* Nexthop reachability check. */
7c312383
AD
3859 if (((afi == AFI_IP || afi == AFI_IP6)
3860 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3861 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3862 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3863 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3864 && !CHECK_FLAG(peer->flags,
3865 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3866 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3867 connected = 1;
3868 else
3869 connected = 0;
3870
7c312383
AD
3871 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3872
3873 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3874 connected)
a4d82a8a 3875 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3876 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3877 else {
3878 if (BGP_DEBUG(nht, NHT)) {
3879 char buf1[INET6_ADDRSTRLEN];
3880 inet_ntop(AF_INET,
3881 (const void *)&attr_new->nexthop,
3882 buf1, INET6_ADDRSTRLEN);
3883 zlog_debug("%s(%s): NH unresolved",
3884 __FUNCTION__, buf1);
3885 }
18ee8310 3886 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3887 }
3888 } else
18ee8310 3889 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3890
d62a17ae 3891 /* Addpath ID */
3892 new->addpath_rx_id = addpath_id;
3893
3894 /* Increment prefix */
3895 bgp_aggregate_increment(bgp, p, new, afi, safi);
3896
3897 /* Register new BGP information. */
18ee8310 3898 bgp_path_info_add(rn, new);
d62a17ae 3899
3900 /* route_node_get lock */
3901 bgp_unlock_node(rn);
558d1fec 3902
65efcfce 3903#if ENABLE_BGP_VNC
d62a17ae 3904 if (safi == SAFI_MPLS_VPN) {
3905 struct bgp_node *prn = NULL;
3906 struct bgp_table *table = NULL;
3907
3908 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3909 if (bgp_node_has_bgp_path_info_data(prn)) {
3910 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3911
3912 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3913 bgp, prd, table, p, new);
3914 }
3915 bgp_unlock_node(prn);
3916 }
65efcfce
LB
3917#endif
3918
d62a17ae 3919 /* If maximum prefix count is configured and current prefix
3920 count exeed it. */
3921 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3922 return -1;
718e3744 3923
d62a17ae 3924 /* If this is an EVPN route, process for import. */
7c312383 3925 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3926 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3927
4a11bf2c
DL
3928 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3929
d62a17ae 3930 /* Process change. */
3931 bgp_process(bgp, rn, afi, safi);
718e3744 3932
ddb5b488
PZ
3933 if (SAFI_UNICAST == safi
3934 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3935 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3936 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3937 }
3938 if ((SAFI_MPLS_VPN == safi)
3939 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3940
3941 vpn_leak_to_vrf_update(bgp, new);
3942 }
28070ee3 3943#if ENABLE_BGP_VNC
d62a17ae 3944 if (SAFI_MPLS_VPN == safi) {
3945 mpls_label_t label_decoded = decode_label(label);
28070ee3 3946
d62a17ae 3947 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3948 sub_type, &label_decoded);
3949 }
3950 if (SAFI_ENCAP == safi) {
3951 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3952 sub_type, NULL);
3953 }
28070ee3
PZ
3954#endif
3955
d62a17ae 3956 return 0;
718e3744 3957
d62a17ae 3958/* This BGP update is filtered. Log the reason then update BGP
3959 entry. */
3960filtered:
4a11bf2c
DL
3961 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3962
d62a17ae 3963 if (bgp_debug_update(peer, p, NULL, 1)) {
3964 if (!peer->rcvd_attr_printed) {
3965 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3966 peer->rcvd_attr_str);
3967 peer->rcvd_attr_printed = 1;
3968 }
718e3744 3969
a4d82a8a 3970 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3971 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3972 sizeof(pfx_buf));
3973 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3974 peer->host, pfx_buf, reason);
3975 }
128ea8ab 3976
40381db7 3977 if (pi) {
d62a17ae 3978 /* If this is an EVPN route, un-import it as it is now filtered.
3979 */
3980 if (safi == SAFI_EVPN)
40381db7 3981 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3982
ddb5b488
PZ
3983 if (SAFI_UNICAST == safi
3984 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3985 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3986
40381db7 3987 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3988 }
3989 if ((SAFI_MPLS_VPN == safi)
3990 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3991
40381db7 3992 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3993 }
3994
40381db7 3995 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3996 }
3997
3998 bgp_unlock_node(rn);
558d1fec 3999
97736e32 4000#if ENABLE_BGP_VNC
d62a17ae 4001 /*
4002 * Filtered update is treated as an implicit withdrawal (see
4003 * bgp_rib_remove()
4004 * a few lines above)
4005 */
4006 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4007 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4008 0);
4009 }
97736e32
PZ
4010#endif
4011
d62a17ae 4012 return 0;
718e3744 4013}
4014
d7c0a89a 4015int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 4016 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4017 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4018 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4019{
d62a17ae 4020 struct bgp *bgp;
4021 char pfx_buf[BGP_PRD_PATH_STRLEN];
4022 struct bgp_node *rn;
40381db7 4023 struct bgp_path_info *pi;
718e3744 4024
28070ee3 4025#if ENABLE_BGP_VNC
d62a17ae 4026 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4027 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4028 0);
4029 }
28070ee3
PZ
4030#endif
4031
d62a17ae 4032 bgp = peer->bgp;
4033
4034 /* Lookup node. */
4035 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4036
4037 /* If peer is soft reconfiguration enabled. Record input packet for
4038 * further calculation.
4039 *
4040 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4041 * routes that are filtered. This tanks out Quagga RS pretty badly due
4042 * to
4043 * the iteration over all RS clients.
4044 * Since we need to remove the entry from adj_in anyway, do that first
4045 * and
4046 * if there was no entry, we don't need to do anything more.
4047 */
4048 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4049 && peer != bgp->peer_self)
4050 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
4051 peer->stat_pfx_dup_withdraw++;
4052
d62a17ae 4053 if (bgp_debug_update(peer, p, NULL, 1)) {
4054 bgp_debug_rdpfxpath2str(
a4d82a8a 4055 afi, safi, prd, p, label, num_labels,
d62a17ae 4056 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4057 sizeof(pfx_buf));
4058 zlog_debug(
4059 "%s withdrawing route %s not in adj-in",
4060 peer->host, pfx_buf);
4061 }
4062 bgp_unlock_node(rn);
4063 return 0;
4064 }
cd808e74 4065
d62a17ae 4066 /* Lookup withdrawn route. */
6f94b685 4067 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4068 if (pi->peer == peer && pi->type == type
4069 && pi->sub_type == sub_type
4070 && pi->addpath_rx_id == addpath_id)
d62a17ae 4071 break;
4072
4073 /* Logging. */
4074 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4075 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4076 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4077 sizeof(pfx_buf));
4078 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4079 pfx_buf);
4080 }
718e3744 4081
d62a17ae 4082 /* Withdraw specified route from routing table. */
40381db7
DS
4083 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4084 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
4085 if (SAFI_UNICAST == safi
4086 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4087 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4088 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4089 }
4090 if ((SAFI_MPLS_VPN == safi)
4091 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4092
40381db7 4093 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4094 }
4095 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4096 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4097 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4098 sizeof(pfx_buf));
4099 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4100 }
718e3744 4101
d62a17ae 4102 /* Unlock bgp_node_get() lock. */
4103 bgp_unlock_node(rn);
4104
4105 return 0;
718e3744 4106}
6b0655a2 4107
d62a17ae 4108void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4109 int withdraw)
718e3744 4110{
d62a17ae 4111 struct update_subgroup *subgrp;
4112 subgrp = peer_subgroup(peer, afi, safi);
4113 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4114}
6182d65b 4115
718e3744 4116
3f9c7369
DS
4117/*
4118 * bgp_stop_announce_route_timer
4119 */
d62a17ae 4120void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4121{
d62a17ae 4122 if (!paf->t_announce_route)
4123 return;
4124
4125 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4126}
6b0655a2 4127
3f9c7369
DS
4128/*
4129 * bgp_announce_route_timer_expired
4130 *
4131 * Callback that is invoked when the route announcement timer for a
4132 * peer_af expires.
4133 */
d62a17ae 4134static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4135{
d62a17ae 4136 struct peer_af *paf;
4137 struct peer *peer;
558d1fec 4138
d62a17ae 4139 paf = THREAD_ARG(t);
4140 peer = paf->peer;
718e3744 4141
d62a17ae 4142 if (peer->status != Established)
4143 return 0;
3f9c7369 4144
d62a17ae 4145 if (!peer->afc_nego[paf->afi][paf->safi])
4146 return 0;
3f9c7369 4147
d62a17ae 4148 peer_af_announce_route(paf, 1);
4149 return 0;
718e3744 4150}
4151
3f9c7369
DS
4152/*
4153 * bgp_announce_route
4154 *
4155 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4156 */
d62a17ae 4157void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4158{
4159 struct peer_af *paf;
4160 struct update_subgroup *subgrp;
4161
4162 paf = peer_af_find(peer, afi, safi);
4163 if (!paf)
4164 return;
4165 subgrp = PAF_SUBGRP(paf);
4166
4167 /*
4168 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4169 * or a refresh has already been triggered.
4170 */
4171 if (!subgrp || paf->t_announce_route)
4172 return;
4173
4174 /*
4175 * Start a timer to stagger/delay the announce. This serves
4176 * two purposes - announcement can potentially be combined for
4177 * multiple peers and the announcement doesn't happen in the
4178 * vty context.
4179 */
4180 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4181 (subgrp->peer_count == 1)
4182 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4183 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4184 &paf->t_announce_route);
3f9c7369
DS
4185}
4186
4187/*
4188 * Announce routes from all AF tables to a peer.
4189 *
4190 * This should ONLY be called when there is a need to refresh the
4191 * routes to the peer based on a policy change for this peer alone
4192 * or a route refresh request received from the peer.
4193 * The operation will result in splitting the peer from its existing
4194 * subgroups and putting it in new subgroups.
4195 */
d62a17ae 4196void bgp_announce_route_all(struct peer *peer)
718e3744 4197{
d62a17ae 4198 afi_t afi;
4199 safi_t safi;
4200
05c7a1cc
QY
4201 FOREACH_AFI_SAFI (afi, safi)
4202 bgp_announce_route(peer, afi, safi);
718e3744 4203}
6b0655a2 4204
d62a17ae 4205static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4206 struct bgp_table *table,
4207 struct prefix_rd *prd)
718e3744 4208{
d62a17ae 4209 int ret;
4210 struct bgp_node *rn;
4211 struct bgp_adj_in *ain;
718e3744 4212
d62a17ae 4213 if (!table)
4214 table = peer->bgp->rib[afi][safi];
718e3744 4215
d62a17ae 4216 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4217 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
4218 if (ain->peer != peer)
4219 continue;
8692c506 4220
d7d15889 4221 struct bgp_path_info *pi;
d7c0a89a 4222 uint32_t num_labels = 0;
b57ba6d2 4223 mpls_label_t *label_pnt = NULL;
8cb687c2 4224 struct bgp_route_evpn evpn;
b57ba6d2 4225
d7d15889
DS
4226 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4227 pi = pi->next)
4228 if (pi->peer == peer)
4229 break;
4230
40381db7
DS
4231 if (pi && pi->extra)
4232 num_labels = pi->extra->num_labels;
b57ba6d2 4233 if (num_labels)
40381db7 4234 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4235 if (pi)
4236 memcpy(&evpn, &pi->attr->evpn_overlay,
4237 sizeof(evpn));
4238 else
4239 memset(&evpn, 0, sizeof(evpn));
8692c506 4240
ea47320b
DL
4241 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
4242 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4243 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4244 num_labels, 1, &evpn);
ea47320b
DL
4245
4246 if (ret < 0) {
4247 bgp_unlock_node(rn);
4248 return;
d62a17ae 4249 }
4250 }
718e3744 4251}
4252
d62a17ae 4253void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4254{
d62a17ae 4255 struct bgp_node *rn;
4256 struct bgp_table *table;
718e3744 4257
d62a17ae 4258 if (peer->status != Established)
4259 return;
718e3744 4260
d62a17ae 4261 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4262 && (safi != SAFI_EVPN))
4263 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4264 else
4265 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4266 rn = bgp_route_next(rn)) {
4267 table = bgp_node_get_bgp_table_info(rn);
4268 if (table != NULL) {
d62a17ae 4269 struct prefix_rd prd;
67009e22 4270
d62a17ae 4271 prd.family = AF_UNSPEC;
4272 prd.prefixlen = 64;
4273 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 4274
d62a17ae 4275 bgp_soft_reconfig_table(peer, afi, safi, table,
4276 &prd);
4277 }
67009e22 4278 }
718e3744 4279}
6b0655a2 4280
228da428 4281
d62a17ae 4282struct bgp_clear_node_queue {
4283 struct bgp_node *rn;
228da428
CC
4284};
4285
d62a17ae 4286static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4287{
d62a17ae 4288 struct bgp_clear_node_queue *cnq = data;
4289 struct bgp_node *rn = cnq->rn;
4290 struct peer *peer = wq->spec.data;
40381db7 4291 struct bgp_path_info *pi;
3103e8d2 4292 struct bgp *bgp;
d62a17ae 4293 afi_t afi = bgp_node_table(rn)->afi;
4294 safi_t safi = bgp_node_table(rn)->safi;
4295
4296 assert(rn && peer);
3103e8d2 4297 bgp = peer->bgp;
d62a17ae 4298
4299 /* It is possible that we have multiple paths for a prefix from a peer
4300 * if that peer is using AddPath.
4301 */
6f94b685 4302 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4303 if (pi->peer != peer)
ea47320b
DL
4304 continue;
4305
4306 /* graceful restart STALE flag set. */
4307 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4308 && peer->nsf[afi][safi]
40381db7
DS
4309 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4310 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4311 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4312 else {
4313 /* If this is an EVPN route, process for
4314 * un-import. */
4315 if (safi == SAFI_EVPN)
40381db7
DS
4316 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4317 pi);
3103e8d2
DS
4318 /* Handle withdraw for VRF route-leaking and L3VPN */
4319 if (SAFI_UNICAST == safi
4320 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4321 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4322 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4323 bgp, pi);
960035b2 4324 }
3103e8d2 4325 if (SAFI_MPLS_VPN == safi &&
960035b2 4326 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4327 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4328 }
3103e8d2 4329
40381db7 4330 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4331 }
ea47320b 4332 }
d62a17ae 4333 return WQ_SUCCESS;
200df115 4334}
4335
d62a17ae 4336static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4337{
d62a17ae 4338 struct bgp_clear_node_queue *cnq = data;
4339 struct bgp_node *rn = cnq->rn;
4340 struct bgp_table *table = bgp_node_table(rn);
228da428 4341
d62a17ae 4342 bgp_unlock_node(rn);
4343 bgp_table_unlock(table);
4344 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4345}
4346
d62a17ae 4347static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4348{
d62a17ae 4349 struct peer *peer = wq->spec.data;
64e580a7 4350
d62a17ae 4351 /* Tickle FSM to start moving again */
4352 BGP_EVENT_ADD(peer, Clearing_Completed);
4353
4354 peer_unlock(peer); /* bgp_clear_route */
200df115 4355}
718e3744 4356
d62a17ae 4357static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4358{
d62a17ae 4359 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4360
4361 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4362#undef CLEAR_QUEUE_NAME_LEN
4363
0ce1ca80 4364 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4365 peer->clear_node_queue->spec.hold = 10;
4366 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4367 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4368 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4369 peer->clear_node_queue->spec.max_retries = 0;
4370
4371 /* we only 'lock' this peer reference when the queue is actually active
4372 */
4373 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4374}
4375
d62a17ae 4376static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4377 struct bgp_table *table)
65ca75e0 4378{
d62a17ae 4379 struct bgp_node *rn;
4380 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4381
d62a17ae 4382 if (!table)
4383 table = peer->bgp->rib[afi][safi];
dc83d712 4384
d62a17ae 4385 /* If still no table => afi/safi isn't configured at all or smth. */
4386 if (!table)
4387 return;
dc83d712 4388
d62a17ae 4389 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4390 struct bgp_path_info *pi, *next;
d62a17ae 4391 struct bgp_adj_in *ain;
4392 struct bgp_adj_in *ain_next;
4393
4394 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4395 * queued for every clearing peer, regardless of whether it is
4396 * relevant to the peer at hand.
4397 *
4398 * Overview: There are 3 different indices which need to be
4399 * scrubbed, potentially, when a peer is removed:
4400 *
4401 * 1 peer's routes visible via the RIB (ie accepted routes)
4402 * 2 peer's routes visible by the (optional) peer's adj-in index
4403 * 3 other routes visible by the peer's adj-out index
4404 *
4405 * 3 there is no hurry in scrubbing, once the struct peer is
4406 * removed from bgp->peer, we could just GC such deleted peer's
4407 * adj-outs at our leisure.
4408 *
4409 * 1 and 2 must be 'scrubbed' in some way, at least made
4410 * invisible via RIB index before peer session is allowed to be
4411 * brought back up. So one needs to know when such a 'search' is
4412 * complete.
4413 *
4414 * Ideally:
4415 *
4416 * - there'd be a single global queue or a single RIB walker
4417 * - rather than tracking which route_nodes still need to be
4418 * examined on a peer basis, we'd track which peers still
4419 * aren't cleared
4420 *
4421 * Given that our per-peer prefix-counts now should be reliable,
4422 * this may actually be achievable. It doesn't seem to be a huge
4423 * problem at this time,
4424 *
4425 * It is possible that we have multiple paths for a prefix from
4426 * a peer
4427 * if that peer is using AddPath.
4428 */
4429 ain = rn->adj_in;
4430 while (ain) {
4431 ain_next = ain->next;
4432
4433 if (ain->peer == peer) {
4434 bgp_adj_in_remove(rn, ain);
4435 bgp_unlock_node(rn);
4436 }
4437
4438 ain = ain_next;
4439 }
4440
6f94b685 4441 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4442 next = pi->next;
4443 if (pi->peer != peer)
d62a17ae 4444 continue;
4445
4446 if (force)
40381db7 4447 bgp_path_info_reap(rn, pi);
d62a17ae 4448 else {
4449 struct bgp_clear_node_queue *cnq;
4450
4451 /* both unlocked in bgp_clear_node_queue_del */
4452 bgp_table_lock(bgp_node_table(rn));
4453 bgp_lock_node(rn);
4454 cnq = XCALLOC(
4455 MTYPE_BGP_CLEAR_NODE_QUEUE,
4456 sizeof(struct bgp_clear_node_queue));
4457 cnq->rn = rn;
4458 work_queue_add(peer->clear_node_queue, cnq);
4459 break;
4460 }
4461 }
4462 }
4463 return;
4464}
4465
4466void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4467{
4468 struct bgp_node *rn;
4469 struct bgp_table *table;
4470
4471 if (peer->clear_node_queue == NULL)
4472 bgp_clear_node_queue_init(peer);
4473
4474 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4475 * Idle until it receives a Clearing_Completed event. This protects
4476 * against peers which flap faster than we can we clear, which could
4477 * lead to:
4478 *
4479 * a) race with routes from the new session being installed before
4480 * clear_route_node visits the node (to delete the route of that
4481 * peer)
4482 * b) resource exhaustion, clear_route_node likely leads to an entry
4483 * on the process_main queue. Fast-flapping could cause that queue
4484 * to grow and grow.
4485 */
4486
4487 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4488 * the unlock will happen upon work-queue completion; other wise, the
4489 * unlock happens at the end of this function.
4490 */
4491 if (!peer->clear_node_queue->thread)
4492 peer_lock(peer);
4493
4494 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4495 bgp_clear_route_table(peer, afi, safi, NULL);
4496 else
4497 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4498 rn = bgp_route_next(rn)) {
4499 table = bgp_node_get_bgp_table_info(rn);
4500 if (!table)
4501 continue;
4502
4503 bgp_clear_route_table(peer, afi, safi, table);
4504 }
d62a17ae 4505
4506 /* unlock if no nodes got added to the clear-node-queue. */
4507 if (!peer->clear_node_queue->thread)
4508 peer_unlock(peer);
718e3744 4509}
d62a17ae 4510
4511void bgp_clear_route_all(struct peer *peer)
718e3744 4512{
d62a17ae 4513 afi_t afi;
4514 safi_t safi;
718e3744 4515
05c7a1cc
QY
4516 FOREACH_AFI_SAFI (afi, safi)
4517 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4518
4519#if ENABLE_BGP_VNC
d62a17ae 4520 rfapiProcessPeerDown(peer);
65efcfce 4521#endif
718e3744 4522}
4523
d62a17ae 4524void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4525{
d62a17ae 4526 struct bgp_table *table;
4527 struct bgp_node *rn;
4528 struct bgp_adj_in *ain;
4529 struct bgp_adj_in *ain_next;
718e3744 4530
d62a17ae 4531 table = peer->bgp->rib[afi][safi];
718e3744 4532
d62a17ae 4533 /* It is possible that we have multiple paths for a prefix from a peer
4534 * if that peer is using AddPath.
4535 */
4536 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4537 ain = rn->adj_in;
43143c8f 4538
d62a17ae 4539 while (ain) {
4540 ain_next = ain->next;
43143c8f 4541
d62a17ae 4542 if (ain->peer == peer) {
4543 bgp_adj_in_remove(rn, ain);
4544 bgp_unlock_node(rn);
4545 }
43143c8f 4546
d62a17ae 4547 ain = ain_next;
4548 }
4549 }
718e3744 4550}
93406d87 4551
d62a17ae 4552void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4553{
4554 struct bgp_node *rn;
40381db7 4555 struct bgp_path_info *pi;
d62a17ae 4556 struct bgp_table *table;
4557
4558 if (safi == SAFI_MPLS_VPN) {
4559 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4560 rn = bgp_route_next(rn)) {
4561 struct bgp_node *rm;
d62a17ae 4562
4563 /* look for neighbor in tables */
67009e22
DS
4564 table = bgp_node_get_bgp_table_info(rn);
4565 if (!table)
ea47320b
DL
4566 continue;
4567
4568 for (rm = bgp_table_top(table); rm;
4569 rm = bgp_route_next(rm))
6f94b685
DS
4570 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4571 pi = pi->next) {
40381db7 4572 if (pi->peer != peer)
ea47320b 4573 continue;
40381db7 4574 if (!CHECK_FLAG(pi->flags,
1defdda8 4575 BGP_PATH_STALE))
ea47320b
DL
4576 break;
4577
40381db7 4578 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4579 break;
4580 }
d62a17ae 4581 }
4582 } else {
4583 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4584 rn = bgp_route_next(rn))
6f94b685
DS
4585 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4586 pi = pi->next) {
40381db7 4587 if (pi->peer != peer)
ea47320b 4588 continue;
40381db7 4589 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4590 break;
40381db7 4591 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4592 break;
4593 }
d62a17ae 4594 }
93406d87 4595}
6b0655a2 4596
9dac9fc8
DA
4597int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4598{
e0df4c04
DA
4599 if (peer->sort == BGP_PEER_IBGP)
4600 return 1;
4601
9dac9fc8
DA
4602 if (peer->sort == BGP_PEER_EBGP
4603 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4604 || FILTER_LIST_OUT_NAME(filter)
4605 || DISTRIBUTE_OUT_NAME(filter)))
4606 return 1;
4607 return 0;
4608}
4609
4610int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4611{
e0df4c04
DA
4612 if (peer->sort == BGP_PEER_IBGP)
4613 return 1;
4614
9dac9fc8
DA
4615 if (peer->sort == BGP_PEER_EBGP
4616 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4617 || FILTER_LIST_IN_NAME(filter)
4618 || DISTRIBUTE_IN_NAME(filter)))
4619 return 1;
4620 return 0;
4621}
4622
568e10ca 4623static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4624 safi_t safi)
bb86c601 4625{
d62a17ae 4626 struct bgp_node *rn;
40381db7 4627 struct bgp_path_info *pi;
4b7e6066 4628 struct bgp_path_info *next;
bb86c601 4629
d62a17ae 4630 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4631 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4632 next = pi->next;
1b7bb747
CS
4633
4634 /* Unimport EVPN routes from VRFs */
4635 if (safi == SAFI_EVPN)
4636 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4637 SAFI_EVPN,
4638 &rn->p, pi);
4639
40381db7
DS
4640 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4641 && pi->type == ZEBRA_ROUTE_BGP
4642 && (pi->sub_type == BGP_ROUTE_NORMAL
4643 || pi->sub_type == BGP_ROUTE_AGGREGATE
4644 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4645
d62a17ae 4646 if (bgp_fibupd_safi(safi))
40381db7
DS
4647 bgp_zebra_withdraw(&rn->p, pi, bgp,
4648 safi);
4649 bgp_path_info_reap(rn, pi);
d62a17ae 4650 }
4651 }
bb86c601
LB
4652}
4653
718e3744 4654/* Delete all kernel routes. */
d62a17ae 4655void bgp_cleanup_routes(struct bgp *bgp)
4656{
4657 afi_t afi;
4658 struct bgp_node *rn;
67009e22 4659 struct bgp_table *table;
d62a17ae 4660
4661 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4662 if (afi == AFI_L2VPN)
4663 continue;
568e10ca 4664 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4665 SAFI_UNICAST);
d62a17ae 4666 /*
4667 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4668 */
4669 if (afi != AFI_L2VPN) {
4670 safi_t safi;
4671 safi = SAFI_MPLS_VPN;
4672 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4673 rn = bgp_route_next(rn)) {
67009e22
DS
4674 table = bgp_node_get_bgp_table_info(rn);
4675 if (table != NULL) {
4676 bgp_cleanup_table(bgp, table, safi);
4677 bgp_table_finish(&table);
4678 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4679 bgp_unlock_node(rn);
4680 }
4681 }
4682 safi = SAFI_ENCAP;
4683 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4684 rn = bgp_route_next(rn)) {
67009e22
DS
4685 table = bgp_node_get_bgp_table_info(rn);
4686 if (table != NULL) {
4687 bgp_cleanup_table(bgp, table, safi);
4688 bgp_table_finish(&table);
4689 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4690 bgp_unlock_node(rn);
4691 }
4692 }
4693 }
4694 }
4695 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4696 rn = bgp_route_next(rn)) {
67009e22
DS
4697 table = bgp_node_get_bgp_table_info(rn);
4698 if (table != NULL) {
4699 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4700 bgp_table_finish(&table);
4701 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4702 bgp_unlock_node(rn);
4703 }
bb86c601 4704 }
718e3744 4705}
4706
d62a17ae 4707void bgp_reset(void)
718e3744 4708{
d62a17ae 4709 vty_reset();
4710 bgp_zclient_reset();
4711 access_list_reset();
4712 prefix_list_reset();
718e3744 4713}
6b0655a2 4714
d62a17ae 4715static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4716{
d62a17ae 4717 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4718 && CHECK_FLAG(peer->af_cap[afi][safi],
4719 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4720}
4721
718e3744 4722/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4723 value. */
d62a17ae 4724int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4725 struct bgp_nlri *packet)
4726{
d7c0a89a
QY
4727 uint8_t *pnt;
4728 uint8_t *lim;
d62a17ae 4729 struct prefix p;
4730 int psize;
4731 int ret;
4732 afi_t afi;
4733 safi_t safi;
4734 int addpath_encoded;
d7c0a89a 4735 uint32_t addpath_id;
d62a17ae 4736
d62a17ae 4737 pnt = packet->nlri;
4738 lim = pnt + packet->length;
4739 afi = packet->afi;
4740 safi = packet->safi;
4741 addpath_id = 0;
4742 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4743
4744 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4745 syntactic validity. If the field is syntactically incorrect,
4746 then the Error Subcode is set to Invalid Network Field. */
4747 for (; pnt < lim; pnt += psize) {
4748 /* Clear prefix structure. */
4749 memset(&p, 0, sizeof(struct prefix));
4750
4751 if (addpath_encoded) {
4752
4753 /* When packet overflow occurs return immediately. */
761ed665 4754 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4755 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4756
a3a850a1 4757 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4758 addpath_id = ntohl(addpath_id);
d62a17ae 4759 pnt += BGP_ADDPATH_ID_LEN;
4760 }
718e3744 4761
d62a17ae 4762 /* Fetch prefix length. */
4763 p.prefixlen = *pnt++;
4764 /* afi/safi validity already verified by caller,
4765 * bgp_update_receive */
4766 p.family = afi2family(afi);
4767
4768 /* Prefix length check. */
4769 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4770 flog_err(
e50f7cfd 4771 EC_BGP_UPDATE_RCV,
14454c9f 4772 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4773 peer->host, p.prefixlen, packet->afi);
513386b5 4774 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4775 }
6b0655a2 4776
d62a17ae 4777 /* Packet size overflow check. */
4778 psize = PSIZE(p.prefixlen);
4779
4780 /* When packet overflow occur return immediately. */
4781 if (pnt + psize > lim) {
af4c2728 4782 flog_err(
e50f7cfd 4783 EC_BGP_UPDATE_RCV,
d62a17ae 4784 "%s [Error] Update packet error (prefix length %d overflows packet)",
4785 peer->host, p.prefixlen);
513386b5 4786 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4787 }
4788
4789 /* Defensive coding, double-check the psize fits in a struct
4790 * prefix */
4791 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4792 flog_err(
e50f7cfd 4793 EC_BGP_UPDATE_RCV,
d62a17ae 4794 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4795 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4796 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4797 }
4798
4799 /* Fetch prefix from NLRI packet. */
a85297a7 4800 memcpy(p.u.val, pnt, psize);
d62a17ae 4801
4802 /* Check address. */
4803 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4804 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4805 /* From RFC4271 Section 6.3:
4806 *
4807 * If a prefix in the NLRI field is semantically
4808 * incorrect
4809 * (e.g., an unexpected multicast IP address),
4810 * an error SHOULD
4811 * be logged locally, and the prefix SHOULD be
4812 * ignored.
a4d82a8a 4813 */
af4c2728 4814 flog_err(
e50f7cfd 4815 EC_BGP_UPDATE_RCV,
d62a17ae 4816 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4817 peer->host, inet_ntoa(p.u.prefix4));
4818 continue;
4819 }
4820 }
4821
4822 /* Check address. */
4823 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4824 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4825 char buf[BUFSIZ];
4826
af4c2728 4827 flog_err(
e50f7cfd 4828 EC_BGP_UPDATE_RCV,
d62a17ae 4829 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4830 peer->host,
4831 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4832 BUFSIZ));
4833
4834 continue;
4835 }
4836 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4837 char buf[BUFSIZ];
4838
af4c2728 4839 flog_err(
e50f7cfd 4840 EC_BGP_UPDATE_RCV,
d62a17ae 4841 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4842 peer->host,
4843 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4844 BUFSIZ));
4845
4846 continue;
4847 }
4848 }
4849
4850 /* Normal process. */
4851 if (attr)
4852 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4853 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4854 NULL, NULL, 0, 0, NULL);
d62a17ae 4855 else
4856 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4857 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4858 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4859 NULL);
d62a17ae 4860
513386b5
DA
4861 /* Do not send BGP notification twice when maximum-prefix count
4862 * overflow. */
4863 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4864 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4865
4866 /* Address family configuration mismatch. */
d62a17ae 4867 if (ret < 0)
513386b5 4868 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4869 }
4870
4871 /* Packet length consistency check. */
4872 if (pnt != lim) {
af4c2728 4873 flog_err(
e50f7cfd 4874 EC_BGP_UPDATE_RCV,
d62a17ae 4875 "%s [Error] Update packet error (prefix length mismatch with total length)",
4876 peer->host);
513386b5 4877 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4878 }
6b0655a2 4879
513386b5 4880 return BGP_NLRI_PARSE_OK;
718e3744 4881}
4882
d62a17ae 4883static struct bgp_static *bgp_static_new(void)
718e3744 4884{
d62a17ae 4885 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4886}
4887
d62a17ae 4888static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4889{
0a22ddfb 4890 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4891 route_map_counter_decrement(bgp_static->rmap.map);
4892
0a22ddfb 4893 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4894 XFREE(MTYPE_BGP_STATIC, bgp_static);
4895}
4896
4897void bgp_static_update(struct bgp *bgp, struct prefix *p,
4898 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4899{
4900 struct bgp_node *rn;
40381db7 4901 struct bgp_path_info *pi;
4b7e6066 4902 struct bgp_path_info *new;
40381db7 4903 struct bgp_path_info rmap_path;
d62a17ae 4904 struct attr attr;
4905 struct attr *attr_new;
b68885f9 4906 route_map_result_t ret;
65efcfce 4907#if ENABLE_BGP_VNC
d62a17ae 4908 int vnc_implicit_withdraw = 0;
65efcfce 4909#endif
fee0f4c6 4910
d62a17ae 4911 assert(bgp_static);
4912 if (!bgp_static)
4913 return;
dd8103a9 4914
d62a17ae 4915 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4916
d62a17ae 4917 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4918
d62a17ae 4919 attr.nexthop = bgp_static->igpnexthop;
4920 attr.med = bgp_static->igpmetric;
4921 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4922
d62a17ae 4923 if (bgp_static->atomic)
4924 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4925
d62a17ae 4926 /* Store label index, if required. */
4927 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4928 attr.label_index = bgp_static->label_index;
4929 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4930 }
718e3744 4931
d62a17ae 4932 /* Apply route-map. */
4933 if (bgp_static->rmap.name) {
4934 struct attr attr_tmp = attr;
80ced710 4935
40381db7
DS
4936 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4937 rmap_path.peer = bgp->peer_self;
4938 rmap_path.attr = &attr_tmp;
fee0f4c6 4939
d62a17ae 4940 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4941
40381db7
DS
4942 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4943 &rmap_path);
fee0f4c6 4944
d62a17ae 4945 bgp->peer_self->rmap_type = 0;
718e3744 4946
d62a17ae 4947 if (ret == RMAP_DENYMATCH) {
4948 /* Free uninterned attribute. */
4949 bgp_attr_flush(&attr_tmp);
718e3744 4950
d62a17ae 4951 /* Unintern original. */
4952 aspath_unintern(&attr.aspath);
4953 bgp_static_withdraw(bgp, p, afi, safi);
4954 return;
4955 }
7f323236
DW
4956
4957 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4958 bgp_attr_add_gshut_community(&attr_tmp);
4959
d62a17ae 4960 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4961 } else {
4962
4963 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4964 bgp_attr_add_gshut_community(&attr);
4965
d62a17ae 4966 attr_new = bgp_attr_intern(&attr);
7f323236 4967 }
718e3744 4968
6f94b685 4969 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4970 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4971 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4972 break;
4973
40381db7
DS
4974 if (pi) {
4975 if (attrhash_cmp(pi->attr, attr_new)
4976 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
d62a17ae 4977 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4978 bgp_unlock_node(rn);
4979 bgp_attr_unintern(&attr_new);
4980 aspath_unintern(&attr.aspath);
4981 return;
4982 } else {
4983 /* The attribute is changed. */
40381db7 4984 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4985
4986 /* Rewrite BGP route information. */
40381db7
DS
4987 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4988 bgp_path_info_restore(rn, pi);
d62a17ae 4989 else
40381db7 4990 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4991#if ENABLE_BGP_VNC
d62a17ae 4992 if ((afi == AFI_IP || afi == AFI_IP6)
4993 && (safi == SAFI_UNICAST)) {
40381db7 4994 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4995 /*
4996 * Implicit withdraw case.
40381db7 4997 * We have to do this before pi is
d62a17ae 4998 * changed
4999 */
5000 ++vnc_implicit_withdraw;
40381db7 5001 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5002 vnc_import_bgp_exterior_del_route(
40381db7 5003 bgp, p, pi);
d62a17ae 5004 }
5005 }
65efcfce 5006#endif
40381db7
DS
5007 bgp_attr_unintern(&pi->attr);
5008 pi->attr = attr_new;
5009 pi->uptime = bgp_clock();
65efcfce 5010#if ENABLE_BGP_VNC
d62a17ae 5011 if ((afi == AFI_IP || afi == AFI_IP6)
5012 && (safi == SAFI_UNICAST)) {
5013 if (vnc_implicit_withdraw) {
40381db7 5014 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5015 vnc_import_bgp_exterior_add_route(
40381db7 5016 bgp, p, pi);
d62a17ae 5017 }
5018 }
65efcfce 5019#endif
718e3744 5020
d62a17ae 5021 /* Nexthop reachability check. */
5022 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
5023 && (safi == SAFI_UNICAST
5024 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5025
5026 struct bgp *bgp_nexthop = bgp;
5027
40381db7
DS
5028 if (pi->extra && pi->extra->bgp_orig)
5029 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5030
5031 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
5032 afi, pi, NULL, 0))
5033 bgp_path_info_set_flag(rn, pi,
18ee8310 5034 BGP_PATH_VALID);
d62a17ae 5035 else {
5036 if (BGP_DEBUG(nht, NHT)) {
5037 char buf1[INET6_ADDRSTRLEN];
5038 inet_ntop(p->family,
5039 &p->u.prefix, buf1,
5040 INET6_ADDRSTRLEN);
5041 zlog_debug(
5042 "%s(%s): Route not in table, not advertising",
5043 __FUNCTION__, buf1);
5044 }
18ee8310 5045 bgp_path_info_unset_flag(
40381db7 5046 rn, pi, BGP_PATH_VALID);
d62a17ae 5047 }
5048 } else {
5049 /* Delete the NHT structure if any, if we're
5050 * toggling between
5051 * enabling/disabling import check. We
5052 * deregister the route
5053 * from NHT to avoid overloading NHT and the
5054 * process interaction
5055 */
40381db7
DS
5056 bgp_unlink_nexthop(pi);
5057 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 5058 }
5059 /* Process change. */
40381db7 5060 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5061 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5062
5063 if (SAFI_UNICAST == safi
5064 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5065 || bgp->inst_type
5066 == BGP_INSTANCE_TYPE_DEFAULT)) {
5067 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5068 pi);
ddb5b488
PZ
5069 }
5070
d62a17ae 5071 bgp_unlock_node(rn);
5072 aspath_unintern(&attr.aspath);
5073 return;
5074 }
718e3744 5075 }
718e3744 5076
d62a17ae 5077 /* Make new BGP info. */
5078 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5079 attr_new, rn);
5080 /* Nexthop reachability check. */
5081 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
5082 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5083 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 5084 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5085 else {
5086 if (BGP_DEBUG(nht, NHT)) {
5087 char buf1[INET6_ADDRSTRLEN];
5088 inet_ntop(p->family, &p->u.prefix, buf1,
5089 INET6_ADDRSTRLEN);
5090 zlog_debug(
5091 "%s(%s): Route not in table, not advertising",
5092 __FUNCTION__, buf1);
5093 }
18ee8310 5094 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5095 }
5096 } else {
5097 /* Delete the NHT structure if any, if we're toggling between
5098 * enabling/disabling import check. We deregister the route
5099 * from NHT to avoid overloading NHT and the process interaction
5100 */
5101 bgp_unlink_nexthop(new);
5102
18ee8310 5103 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 5104 }
078430f6 5105
d62a17ae 5106 /* Aggregate address increment. */
5107 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5108
d62a17ae 5109 /* Register new BGP information. */
18ee8310 5110 bgp_path_info_add(rn, new);
718e3744 5111
d62a17ae 5112 /* route_node_get lock */
5113 bgp_unlock_node(rn);
5114
5115 /* Process change. */
5116 bgp_process(bgp, rn, afi, safi);
5117
ddb5b488
PZ
5118 if (SAFI_UNICAST == safi
5119 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5120 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5121 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5122 }
5123
d62a17ae 5124 /* Unintern original. */
5125 aspath_unintern(&attr.aspath);
718e3744 5126}
5127
d62a17ae 5128void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
5129 safi_t safi)
718e3744 5130{
d62a17ae 5131 struct bgp_node *rn;
40381db7 5132 struct bgp_path_info *pi;
718e3744 5133
d62a17ae 5134 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5135
d62a17ae 5136 /* Check selected route and self inserted route. */
6f94b685 5137 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5138 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5139 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5140 break;
5141
5142 /* Withdraw static BGP route from routing table. */
40381db7 5143 if (pi) {
ddb5b488
PZ
5144 if (SAFI_UNICAST == safi
5145 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5146 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5147 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5148 }
40381db7
DS
5149 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5150 bgp_unlink_nexthop(pi);
5151 bgp_path_info_delete(rn, pi);
d62a17ae 5152 bgp_process(bgp, rn, afi, safi);
5153 }
718e3744 5154
d62a17ae 5155 /* Unlock bgp_node_lookup. */
5156 bgp_unlock_node(rn);
718e3744 5157}
5158
137446f9
LB
5159/*
5160 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5161 */
d62a17ae 5162static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
5163 afi_t afi, safi_t safi,
5164 struct prefix_rd *prd)
718e3744 5165{
d62a17ae 5166 struct bgp_node *rn;
40381db7 5167 struct bgp_path_info *pi;
718e3744 5168
d62a17ae 5169 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5170
d62a17ae 5171 /* Check selected route and self inserted route. */
6f94b685 5172 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5173 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5174 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5175 break;
718e3744 5176
d62a17ae 5177 /* Withdraw static BGP route from routing table. */
40381db7 5178 if (pi) {
65efcfce 5179#if ENABLE_BGP_VNC
d62a17ae 5180 rfapiProcessWithdraw(
40381db7 5181 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5182 1); /* Kill, since it is an administrative change */
65efcfce 5183#endif
ddb5b488
PZ
5184 if (SAFI_MPLS_VPN == safi
5185 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5186 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5187 }
40381db7
DS
5188 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5189 bgp_path_info_delete(rn, pi);
d62a17ae 5190 bgp_process(bgp, rn, afi, safi);
5191 }
718e3744 5192
d62a17ae 5193 /* Unlock bgp_node_lookup. */
5194 bgp_unlock_node(rn);
718e3744 5195}
5196
d62a17ae 5197static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
5198 struct bgp_static *bgp_static, afi_t afi,
5199 safi_t safi)
137446f9 5200{
d62a17ae 5201 struct bgp_node *rn;
4b7e6066 5202 struct bgp_path_info *new;
d62a17ae 5203 struct attr *attr_new;
5204 struct attr attr = {0};
40381db7 5205 struct bgp_path_info *pi;
65efcfce 5206#if ENABLE_BGP_VNC
d62a17ae 5207 mpls_label_t label = 0;
65efcfce 5208#endif
d7c0a89a 5209 uint32_t num_labels = 0;
d62a17ae 5210 union gw_addr add;
137446f9 5211
d62a17ae 5212 assert(bgp_static);
137446f9 5213
b57ba6d2
MK
5214 if (bgp_static->label != MPLS_INVALID_LABEL)
5215 num_labels = 1;
d62a17ae 5216 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5217 &bgp_static->prd);
137446f9 5218
d62a17ae 5219 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5220
d62a17ae 5221 attr.nexthop = bgp_static->igpnexthop;
5222 attr.med = bgp_static->igpmetric;
5223 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5224
d62a17ae 5225 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5226 || (safi == SAFI_ENCAP)) {
5227 if (afi == AFI_IP) {
5228 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5229 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5230 }
5231 }
5232 if (afi == AFI_L2VPN) {
5233 if (bgp_static->gatewayIp.family == AF_INET)
5234 add.ipv4.s_addr =
5235 bgp_static->gatewayIp.u.prefix4.s_addr;
5236 else if (bgp_static->gatewayIp.family == AF_INET6)
5237 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5238 sizeof(struct in6_addr));
5239 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5240 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5241 struct bgp_encap_type_vxlan bet;
5242 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5243 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5244 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5245 }
5246 if (bgp_static->router_mac) {
5247 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5248 }
5249 }
5250 /* Apply route-map. */
5251 if (bgp_static->rmap.name) {
5252 struct attr attr_tmp = attr;
40381db7 5253 struct bgp_path_info rmap_path;
b68885f9 5254 route_map_result_t ret;
137446f9 5255
40381db7
DS
5256 rmap_path.peer = bgp->peer_self;
5257 rmap_path.attr = &attr_tmp;
137446f9 5258
d62a17ae 5259 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5260
40381db7
DS
5261 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5262 &rmap_path);
137446f9 5263
d62a17ae 5264 bgp->peer_self->rmap_type = 0;
137446f9 5265
d62a17ae 5266 if (ret == RMAP_DENYMATCH) {
5267 /* Free uninterned attribute. */
5268 bgp_attr_flush(&attr_tmp);
137446f9 5269
d62a17ae 5270 /* Unintern original. */
5271 aspath_unintern(&attr.aspath);
5272 bgp_static_withdraw_safi(bgp, p, afi, safi,
5273 &bgp_static->prd);
5274 return;
5275 }
137446f9 5276
d62a17ae 5277 attr_new = bgp_attr_intern(&attr_tmp);
5278 } else {
5279 attr_new = bgp_attr_intern(&attr);
5280 }
137446f9 5281
6f94b685 5282 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5283 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5284 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5285 break;
5286
40381db7 5287 if (pi) {
d62a17ae 5288 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5289 if (attrhash_cmp(pi->attr, attr_new)
5290 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5291 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5292 bgp_unlock_node(rn);
5293 bgp_attr_unintern(&attr_new);
5294 aspath_unintern(&attr.aspath);
5295 return;
5296 } else {
5297 /* The attribute is changed. */
40381db7 5298 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5299
5300 /* Rewrite BGP route information. */
40381db7
DS
5301 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5302 bgp_path_info_restore(rn, pi);
d62a17ae 5303 else
40381db7
DS
5304 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5305 bgp_attr_unintern(&pi->attr);
5306 pi->attr = attr_new;
5307 pi->uptime = bgp_clock();
65efcfce 5308#if ENABLE_BGP_VNC
40381db7
DS
5309 if (pi->extra)
5310 label = decode_label(&pi->extra->label[0]);
65efcfce 5311#endif
137446f9 5312
d62a17ae 5313 /* Process change. */
40381db7 5314 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5315 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5316
5317 if (SAFI_MPLS_VPN == safi
5318 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5319 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5320 }
65efcfce 5321#if ENABLE_BGP_VNC
40381db7
DS
5322 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5323 pi->attr, afi, safi, pi->type,
5324 pi->sub_type, &label);
65efcfce 5325#endif
d62a17ae 5326 bgp_unlock_node(rn);
5327 aspath_unintern(&attr.aspath);
5328 return;
5329 }
5330 }
137446f9
LB
5331
5332
d62a17ae 5333 /* Make new BGP info. */
5334 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5335 attr_new, rn);
1defdda8 5336 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5337 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5338 if (num_labels) {
5339 new->extra->label[0] = bgp_static->label;
5340 new->extra->num_labels = num_labels;
5341 }
65efcfce 5342#if ENABLE_BGP_VNC
d62a17ae 5343 label = decode_label(&bgp_static->label);
65efcfce 5344#endif
137446f9 5345
d62a17ae 5346 /* Aggregate address increment. */
5347 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5348
d62a17ae 5349 /* Register new BGP information. */
18ee8310 5350 bgp_path_info_add(rn, new);
d62a17ae 5351 /* route_node_get lock */
5352 bgp_unlock_node(rn);
137446f9 5353
d62a17ae 5354 /* Process change. */
5355 bgp_process(bgp, rn, afi, safi);
137446f9 5356
ddb5b488
PZ
5357 if (SAFI_MPLS_VPN == safi
5358 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5359 vpn_leak_to_vrf_update(bgp, new);
5360 }
65efcfce 5361#if ENABLE_BGP_VNC
d62a17ae 5362 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5363 safi, new->type, new->sub_type, &label);
65efcfce
LB
5364#endif
5365
d62a17ae 5366 /* Unintern original. */
5367 aspath_unintern(&attr.aspath);
137446f9
LB
5368}
5369
718e3744 5370/* Configure static BGP network. When user don't run zebra, static
5371 route should be installed as valid. */
e2a86ad9
DS
5372static int bgp_static_set(struct vty *vty, const char *negate,
5373 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5374 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5375{
5376 VTY_DECLVAR_CONTEXT(bgp, bgp);
5377 int ret;
5378 struct prefix p;
5379 struct bgp_static *bgp_static;
5380 struct bgp_node *rn;
d7c0a89a 5381 uint8_t need_update = 0;
d62a17ae 5382
5383 /* Convert IP prefix string to struct prefix. */
5384 ret = str2prefix(ip_str, &p);
5385 if (!ret) {
5386 vty_out(vty, "%% Malformed prefix\n");
5387 return CMD_WARNING_CONFIG_FAILED;
5388 }
5389 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5390 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5391 return CMD_WARNING_CONFIG_FAILED;
5392 }
718e3744 5393
d62a17ae 5394 apply_mask(&p);
718e3744 5395
e2a86ad9 5396 if (negate) {
718e3744 5397
e2a86ad9
DS
5398 /* Set BGP static route configuration. */
5399 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5400
e2a86ad9 5401 if (!rn) {
a4d82a8a 5402 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5403 return CMD_WARNING_CONFIG_FAILED;
5404 }
5405
5a8ba9fc 5406 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5407
e2a86ad9
DS
5408 if ((label_index != BGP_INVALID_LABEL_INDEX)
5409 && (label_index != bgp_static->label_index)) {
5410 vty_out(vty,
5411 "%% label-index doesn't match static route\n");
5412 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5413 }
d62a17ae 5414
e2a86ad9
DS
5415 if ((rmap && bgp_static->rmap.name)
5416 && strcmp(rmap, bgp_static->rmap.name)) {
5417 vty_out(vty,
5418 "%% route-map name doesn't match static route\n");
5419 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5420 }
718e3744 5421
e2a86ad9
DS
5422 /* Update BGP RIB. */
5423 if (!bgp_static->backdoor)
5424 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5425
e2a86ad9
DS
5426 /* Clear configuration. */
5427 bgp_static_free(bgp_static);
5a8ba9fc 5428 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5429 bgp_unlock_node(rn);
5430 bgp_unlock_node(rn);
5431 } else {
718e3744 5432
e2a86ad9
DS
5433 /* Set BGP static route configuration. */
5434 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5435
5a8ba9fc 5436 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5437 if (bgp_static) {
e2a86ad9 5438 /* Configuration change. */
e2a86ad9
DS
5439 /* Label index cannot be changed. */
5440 if (bgp_static->label_index != label_index) {
5441 vty_out(vty, "%% cannot change label-index\n");
5442 return CMD_WARNING_CONFIG_FAILED;
5443 }
d62a17ae 5444
e2a86ad9 5445 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5446 if (bgp_static->valid
5447 && bgp_static->backdoor != backdoor)
e2a86ad9 5448 need_update = 1;
718e3744 5449
e2a86ad9 5450 bgp_static->backdoor = backdoor;
718e3744 5451
e2a86ad9 5452 if (rmap) {
0a22ddfb
QY
5453 XFREE(MTYPE_ROUTE_MAP_NAME,
5454 bgp_static->rmap.name);
b4897fa5 5455 route_map_counter_decrement(
5456 bgp_static->rmap.map);
e2a86ad9
DS
5457 bgp_static->rmap.name =
5458 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5459 bgp_static->rmap.map =
5460 route_map_lookup_by_name(rmap);
b4897fa5 5461 route_map_counter_increment(
5462 bgp_static->rmap.map);
e2a86ad9 5463 } else {
0a22ddfb
QY
5464 XFREE(MTYPE_ROUTE_MAP_NAME,
5465 bgp_static->rmap.name);
b4897fa5 5466 route_map_counter_decrement(
5467 bgp_static->rmap.map);
e2a86ad9
DS
5468 bgp_static->rmap.map = NULL;
5469 bgp_static->valid = 0;
5470 }
5471 bgp_unlock_node(rn);
5472 } else {
5473 /* New configuration. */
5474 bgp_static = bgp_static_new();
5475 bgp_static->backdoor = backdoor;
5476 bgp_static->valid = 0;
5477 bgp_static->igpmetric = 0;
5478 bgp_static->igpnexthop.s_addr = 0;
5479 bgp_static->label_index = label_index;
718e3744 5480
e2a86ad9 5481 if (rmap) {
0a22ddfb
QY
5482 XFREE(MTYPE_ROUTE_MAP_NAME,
5483 bgp_static->rmap.name);
b4897fa5 5484 route_map_counter_decrement(
5485 bgp_static->rmap.map);
e2a86ad9
DS
5486 bgp_static->rmap.name =
5487 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5488 bgp_static->rmap.map =
5489 route_map_lookup_by_name(rmap);
b4897fa5 5490 route_map_counter_increment(
5491 bgp_static->rmap.map);
e2a86ad9 5492 }
5a8ba9fc 5493 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5494 }
d62a17ae 5495
e2a86ad9
DS
5496 bgp_static->valid = 1;
5497 if (need_update)
5498 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5499
e2a86ad9
DS
5500 if (!bgp_static->backdoor)
5501 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5502 }
d62a17ae 5503
5504 return CMD_SUCCESS;
5505}
5506
5507void bgp_static_add(struct bgp *bgp)
5508{
5509 afi_t afi;
5510 safi_t safi;
5511 struct bgp_node *rn;
5512 struct bgp_node *rm;
5513 struct bgp_table *table;
5514 struct bgp_static *bgp_static;
5515
05c7a1cc
QY
5516 FOREACH_AFI_SAFI (afi, safi)
5517 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5518 rn = bgp_route_next(rn)) {
67009e22 5519 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5520 continue;
ea47320b 5521
05c7a1cc
QY
5522 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5523 || (safi == SAFI_EVPN)) {
67009e22 5524 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5525
5526 for (rm = bgp_table_top(table); rm;
5527 rm = bgp_route_next(rm)) {
a78beeb5 5528 bgp_static =
5a8ba9fc
DS
5529 bgp_node_get_bgp_static_info(
5530 rm);
05c7a1cc
QY
5531 bgp_static_update_safi(bgp, &rm->p,
5532 bgp_static, afi,
5533 safi);
d62a17ae 5534 }
05c7a1cc 5535 } else {
5a8ba9fc
DS
5536 bgp_static_update(
5537 bgp, &rn->p,
5538 bgp_node_get_bgp_static_info(rn), afi,
5539 safi);
ea47320b 5540 }
05c7a1cc 5541 }
6aeb9e78
DS
5542}
5543
718e3744 5544/* Called from bgp_delete(). Delete all static routes from the BGP
5545 instance. */
d62a17ae 5546void bgp_static_delete(struct bgp *bgp)
5547{
5548 afi_t afi;
5549 safi_t safi;
5550 struct bgp_node *rn;
5551 struct bgp_node *rm;
5552 struct bgp_table *table;
5553 struct bgp_static *bgp_static;
5554
05c7a1cc
QY
5555 FOREACH_AFI_SAFI (afi, safi)
5556 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5557 rn = bgp_route_next(rn)) {
67009e22 5558 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5559 continue;
ea47320b 5560
05c7a1cc
QY
5561 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5562 || (safi == SAFI_EVPN)) {
67009e22 5563 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5564
5565 for (rm = bgp_table_top(table); rm;
5566 rm = bgp_route_next(rm)) {
a78beeb5 5567 bgp_static =
5a8ba9fc
DS
5568 bgp_node_get_bgp_static_info(
5569 rm);
c7d14ba6
PG
5570 if (!bgp_static)
5571 continue;
5572
05c7a1cc
QY
5573 bgp_static_withdraw_safi(
5574 bgp, &rm->p, AFI_IP, safi,
5575 (struct prefix_rd *)&rn->p);
ea47320b 5576 bgp_static_free(bgp_static);
5a8ba9fc 5577 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5578 bgp_unlock_node(rn);
d62a17ae 5579 }
05c7a1cc 5580 } else {
5a8ba9fc 5581 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5582 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5583 bgp_static_free(bgp_static);
5a8ba9fc 5584 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5585 bgp_unlock_node(rn);
ea47320b 5586 }
05c7a1cc 5587 }
d62a17ae 5588}
5589
5590void bgp_static_redo_import_check(struct bgp *bgp)
5591{
5592 afi_t afi;
5593 safi_t safi;
5594 struct bgp_node *rn;
5595 struct bgp_node *rm;
5596 struct bgp_table *table;
5597 struct bgp_static *bgp_static;
5598
5599 /* Use this flag to force reprocessing of the route */
5600 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5601 FOREACH_AFI_SAFI (afi, safi) {
5602 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5603 rn = bgp_route_next(rn)) {
67009e22 5604 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5605 continue;
ea47320b 5606
05c7a1cc
QY
5607 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5608 || (safi == SAFI_EVPN)) {
67009e22 5609 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5610
5611 for (rm = bgp_table_top(table); rm;
5612 rm = bgp_route_next(rm)) {
a78beeb5 5613 bgp_static =
5a8ba9fc
DS
5614 bgp_node_get_bgp_static_info(
5615 rm);
05c7a1cc
QY
5616 bgp_static_update_safi(bgp, &rm->p,
5617 bgp_static, afi,
5618 safi);
d62a17ae 5619 }
05c7a1cc 5620 } else {
5a8ba9fc 5621 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5622 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5623 safi);
ea47320b 5624 }
05c7a1cc
QY
5625 }
5626 }
d62a17ae 5627 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
5628}
5629
5630static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5631 safi_t safi)
5632{
5633 struct bgp_table *table;
5634 struct bgp_node *rn;
40381db7 5635 struct bgp_path_info *pi;
d62a17ae 5636
dfb6fd1d
NT
5637 /* Do not install the aggregate route if BGP is in the
5638 * process of termination.
5639 */
5640 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
5641 (bgp->peer_self == NULL))
5642 return;
5643
d62a17ae 5644 table = bgp->rib[afi][safi];
5645 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5646 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5647 if (pi->peer == bgp->peer_self
5648 && ((pi->type == ZEBRA_ROUTE_BGP
5649 && pi->sub_type == BGP_ROUTE_STATIC)
5650 || (pi->type != ZEBRA_ROUTE_BGP
5651 && pi->sub_type
d62a17ae 5652 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5653 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5654 safi);
40381db7
DS
5655 bgp_unlink_nexthop(pi);
5656 bgp_path_info_delete(rn, pi);
d62a17ae 5657 bgp_process(bgp, rn, afi, safi);
5658 }
5659 }
5660 }
ad4cbda1 5661}
5662
5663/*
5664 * Purge all networks and redistributed routes from routing table.
5665 * Invoked upon the instance going down.
5666 */
d62a17ae 5667void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5668{
d62a17ae 5669 afi_t afi;
5670 safi_t safi;
ad4cbda1 5671
05c7a1cc
QY
5672 FOREACH_AFI_SAFI (afi, safi)
5673 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5674}
5675
137446f9
LB
5676/*
5677 * gpz 110624
5678 * Currently this is used to set static routes for VPN and ENCAP.
5679 * I think it can probably be factored with bgp_static_set.
5680 */
d62a17ae 5681int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5682 const char *ip_str, const char *rd_str,
5683 const char *label_str, const char *rmap_str,
5684 int evpn_type, const char *esi, const char *gwip,
5685 const char *ethtag, const char *routermac)
5686{
5687 VTY_DECLVAR_CONTEXT(bgp, bgp);
5688 int ret;
5689 struct prefix p;
5690 struct prefix_rd prd;
5691 struct bgp_node *prn;
5692 struct bgp_node *rn;
5693 struct bgp_table *table;
5694 struct bgp_static *bgp_static;
5695 mpls_label_t label = MPLS_INVALID_LABEL;
5696 struct prefix gw_ip;
5697
5698 /* validate ip prefix */
5699 ret = str2prefix(ip_str, &p);
5700 if (!ret) {
5701 vty_out(vty, "%% Malformed prefix\n");
5702 return CMD_WARNING_CONFIG_FAILED;
5703 }
5704 apply_mask(&p);
5705 if ((afi == AFI_L2VPN)
5706 && (bgp_build_evpn_prefix(evpn_type,
5707 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5708 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5709 return CMD_WARNING_CONFIG_FAILED;
5710 }
718e3744 5711
d62a17ae 5712 ret = str2prefix_rd(rd_str, &prd);
5713 if (!ret) {
5714 vty_out(vty, "%% Malformed rd\n");
5715 return CMD_WARNING_CONFIG_FAILED;
5716 }
718e3744 5717
d62a17ae 5718 if (label_str) {
5719 unsigned long label_val;
5720 label_val = strtoul(label_str, NULL, 10);
5721 encode_label(label_val, &label);
5722 }
9bedbb1e 5723
d62a17ae 5724 if (safi == SAFI_EVPN) {
5725 if (esi && str2esi(esi, NULL) == 0) {
5726 vty_out(vty, "%% Malformed ESI\n");
5727 return CMD_WARNING_CONFIG_FAILED;
5728 }
5729 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5730 vty_out(vty, "%% Malformed Router MAC\n");
5731 return CMD_WARNING_CONFIG_FAILED;
5732 }
5733 if (gwip) {
5734 memset(&gw_ip, 0, sizeof(struct prefix));
5735 ret = str2prefix(gwip, &gw_ip);
5736 if (!ret) {
5737 vty_out(vty, "%% Malformed GatewayIp\n");
5738 return CMD_WARNING_CONFIG_FAILED;
5739 }
5740 if ((gw_ip.family == AF_INET
3714a385 5741 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5742 (struct prefix_evpn *)&p))
5743 || (gw_ip.family == AF_INET6
3714a385 5744 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5745 (struct prefix_evpn *)&p))) {
5746 vty_out(vty,
5747 "%% GatewayIp family differs with IP prefix\n");
5748 return CMD_WARNING_CONFIG_FAILED;
5749 }
5750 }
5751 }
5752 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5753 if (!bgp_node_has_bgp_path_info_data(prn))
5754 bgp_node_set_bgp_table_info(prn,
5755 bgp_table_init(bgp, afi, safi));
67009e22 5756 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5757
5758 rn = bgp_node_get(table, &p);
5759
67009e22 5760 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5761 vty_out(vty, "%% Same network configuration exists\n");
5762 bgp_unlock_node(rn);
5763 } else {
5764 /* New configuration. */
5765 bgp_static = bgp_static_new();
5766 bgp_static->backdoor = 0;
5767 bgp_static->valid = 0;
5768 bgp_static->igpmetric = 0;
5769 bgp_static->igpnexthop.s_addr = 0;
5770 bgp_static->label = label;
5771 bgp_static->prd = prd;
5772
5773 if (rmap_str) {
0a22ddfb 5774 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5775 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5776 bgp_static->rmap.name =
5777 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5778 bgp_static->rmap.map =
5779 route_map_lookup_by_name(rmap_str);
b4897fa5 5780 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5781 }
718e3744 5782
d62a17ae 5783 if (safi == SAFI_EVPN) {
5784 if (esi) {
5785 bgp_static->eth_s_id =
5786 XCALLOC(MTYPE_ATTR,
5787 sizeof(struct eth_segment_id));
5788 str2esi(esi, bgp_static->eth_s_id);
5789 }
5790 if (routermac) {
5791 bgp_static->router_mac =
28328ea9 5792 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5793 (void)prefix_str2mac(routermac,
5794 bgp_static->router_mac);
d62a17ae 5795 }
5796 if (gwip)
5797 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5798 }
5a8ba9fc 5799 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5800
d62a17ae 5801 bgp_static->valid = 1;
5802 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5803 }
718e3744 5804
d62a17ae 5805 return CMD_SUCCESS;
718e3744 5806}
5807
5808/* Configure static BGP network. */
d62a17ae 5809int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5810 const char *ip_str, const char *rd_str,
5811 const char *label_str, int evpn_type, const char *esi,
5812 const char *gwip, const char *ethtag)
5813{
5814 VTY_DECLVAR_CONTEXT(bgp, bgp);
5815 int ret;
5816 struct prefix p;
5817 struct prefix_rd prd;
5818 struct bgp_node *prn;
5819 struct bgp_node *rn;
5820 struct bgp_table *table;
5821 struct bgp_static *bgp_static;
5822 mpls_label_t label = MPLS_INVALID_LABEL;
5823
5824 /* Convert IP prefix string to struct prefix. */
5825 ret = str2prefix(ip_str, &p);
5826 if (!ret) {
5827 vty_out(vty, "%% Malformed prefix\n");
5828 return CMD_WARNING_CONFIG_FAILED;
5829 }
5830 apply_mask(&p);
5831 if ((afi == AFI_L2VPN)
5832 && (bgp_build_evpn_prefix(evpn_type,
5833 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5834 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5835 return CMD_WARNING_CONFIG_FAILED;
5836 }
5837 ret = str2prefix_rd(rd_str, &prd);
5838 if (!ret) {
5839 vty_out(vty, "%% Malformed rd\n");
5840 return CMD_WARNING_CONFIG_FAILED;
5841 }
718e3744 5842
d62a17ae 5843 if (label_str) {
5844 unsigned long label_val;
5845 label_val = strtoul(label_str, NULL, 10);
5846 encode_label(label_val, &label);
5847 }
718e3744 5848
d62a17ae 5849 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5850 if (!bgp_node_has_bgp_path_info_data(prn))
5851 bgp_node_set_bgp_table_info(prn,
5852 bgp_table_init(bgp, afi, safi));
d62a17ae 5853 else
5854 bgp_unlock_node(prn);
67009e22 5855 table = bgp_node_get_bgp_table_info(prn);
718e3744 5856
d62a17ae 5857 rn = bgp_node_lookup(table, &p);
6b0655a2 5858
d62a17ae 5859 if (rn) {
5860 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5861
5a8ba9fc 5862 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5863 bgp_static_free(bgp_static);
5a8ba9fc 5864 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5865 bgp_unlock_node(rn);
5866 bgp_unlock_node(rn);
5867 } else
5868 vty_out(vty, "%% Can't find the route\n");
5869
5870 return CMD_SUCCESS;
5871}
5872
5873static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5874 const char *rmap_name)
5875{
5876 VTY_DECLVAR_CONTEXT(bgp, bgp);
5877 struct bgp_rmap *rmap;
5878
5879 rmap = &bgp->table_map[afi][safi];
5880 if (rmap_name) {
0a22ddfb 5881 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5882 route_map_counter_decrement(rmap->map);
d62a17ae 5883 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5884 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5885 route_map_counter_increment(rmap->map);
d62a17ae 5886 } else {
0a22ddfb 5887 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5888 route_map_counter_decrement(rmap->map);
d62a17ae 5889 rmap->map = NULL;
5890 }
73ac8160 5891
d62a17ae 5892 if (bgp_fibupd_safi(safi))
5893 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5894
d62a17ae 5895 return CMD_SUCCESS;
73ac8160
DS
5896}
5897
d62a17ae 5898static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5899 const char *rmap_name)
73ac8160 5900{
d62a17ae 5901 VTY_DECLVAR_CONTEXT(bgp, bgp);
5902 struct bgp_rmap *rmap;
73ac8160 5903
d62a17ae 5904 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5905 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5906 route_map_counter_decrement(rmap->map);
d62a17ae 5907 rmap->map = NULL;
73ac8160 5908
d62a17ae 5909 if (bgp_fibupd_safi(safi))
5910 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5911
d62a17ae 5912 return CMD_SUCCESS;
73ac8160
DS
5913}
5914
2b791107 5915void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5916 safi_t safi)
73ac8160 5917{
d62a17ae 5918 if (bgp->table_map[afi][safi].name) {
d62a17ae 5919 vty_out(vty, " table-map %s\n",
5920 bgp->table_map[afi][safi].name);
5921 }
73ac8160
DS
5922}
5923
73ac8160
DS
5924DEFUN (bgp_table_map,
5925 bgp_table_map_cmd,
5926 "table-map WORD",
5927 "BGP table to RIB route download filter\n"
5928 "Name of the route map\n")
5929{
d62a17ae 5930 int idx_word = 1;
5931 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5932 argv[idx_word]->arg);
73ac8160
DS
5933}
5934DEFUN (no_bgp_table_map,
5935 no_bgp_table_map_cmd,
5936 "no table-map WORD",
3a2d747c 5937 NO_STR
73ac8160
DS
5938 "BGP table to RIB route download filter\n"
5939 "Name of the route map\n")
5940{
d62a17ae 5941 int idx_word = 2;
5942 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5943 argv[idx_word]->arg);
73ac8160
DS
5944}
5945
e2a86ad9
DS
5946DEFPY(bgp_network,
5947 bgp_network_cmd,
5948 "[no] network \
5949 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5950 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5951 backdoor$backdoor}]",
5952 NO_STR
5953 "Specify a network to announce via BGP\n"
5954 "IPv4 prefix\n"
5955 "Network number\n"
5956 "Network mask\n"
5957 "Network mask\n"
5958 "Route-map to modify the attributes\n"
5959 "Name of the route map\n"
5960 "Label index to associate with the prefix\n"
5961 "Label index value\n"
5962 "Specify a BGP backdoor route\n")
5963{
5964 char addr_prefix_str[BUFSIZ];
5965
5966 if (address_str) {
5967 int ret;
718e3744 5968
e2a86ad9
DS
5969 ret = netmask_str2prefix_str(address_str, netmask_str,
5970 addr_prefix_str);
5971 if (!ret) {
5972 vty_out(vty, "%% Inconsistent address and mask\n");
5973 return CMD_WARNING_CONFIG_FAILED;
5974 }
d62a17ae 5975 }
718e3744 5976
a4d82a8a
PZ
5977 return bgp_static_set(
5978 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5979 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5980 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5981}
5982
e2a86ad9
DS
5983DEFPY(ipv6_bgp_network,
5984 ipv6_bgp_network_cmd,
5985 "[no] network X:X::X:X/M$prefix \
5986 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5987 NO_STR
5988 "Specify a network to announce via BGP\n"
5989 "IPv6 prefix\n"
5990 "Route-map to modify the attributes\n"
5991 "Name of the route map\n"
5992 "Label index to associate with the prefix\n"
5993 "Label index value\n")
718e3744 5994{
a4d82a8a
PZ
5995 return bgp_static_set(
5996 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5997 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5998}
5999
d62a17ae 6000static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6001{
d62a17ae 6002 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6003}
6004
d62a17ae 6005static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6006{
20894f50
DA
6007 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6008 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6009 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6010}
718e3744 6011
40381db7 6012static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 6013 struct aspath *aspath,
3da2cc32 6014 struct community *comm,
dd18c5a9
DS
6015 struct ecommunity *ecomm,
6016 struct lcommunity *lcomm)
eaaf8adb
DS
6017{
6018 static struct aspath *ae = NULL;
6019
6020 if (!ae)
6021 ae = aspath_empty();
6022
40381db7 6023 if (!pi)
eaaf8adb
DS
6024 return 0;
6025
40381db7 6026 if (origin != pi->attr->origin)
eaaf8adb
DS
6027 return 0;
6028
40381db7 6029 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
6030 return 0;
6031
40381db7 6032 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
6033 return 0;
6034
3da2cc32 6035 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
6036 return 0;
6037
dd18c5a9
DS
6038 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6039 return 0;
6040
40381db7 6041 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
6042 return 0;
6043
eaaf8adb
DS
6044 return 1;
6045}
6046
c701010e
DS
6047static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
6048 struct prefix *p, uint8_t origin,
6049 struct aspath *aspath,
6050 struct community *community,
3da2cc32 6051 struct ecommunity *ecommunity,
dd18c5a9 6052 struct lcommunity *lcommunity,
c701010e
DS
6053 uint8_t atomic_aggregate,
6054 struct bgp_aggregate *aggregate)
6055{
6056 struct bgp_node *rn;
6057 struct bgp_table *table;
6f94b685 6058 struct bgp_path_info *pi, *orig, *new;
20894f50 6059 struct attr *attr;
c701010e
DS
6060
6061 table = bgp->rib[afi][safi];
6062
6063 rn = bgp_node_get(table, p);
eaaf8adb 6064
6f94b685 6065 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6066 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6067 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6068 break;
6069
c701010e 6070 if (aggregate->count > 0) {
eaaf8adb
DS
6071 /*
6072 * If the aggregate information has not changed
6073 * no need to re-install it again.
6074 */
6f94b685 6075 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6076 ecommunity, lcommunity)) {
eaaf8adb
DS
6077 bgp_unlock_node(rn);
6078
6079 if (aspath)
6080 aspath_free(aspath);
6081 if (community)
3c1f53de 6082 community_free(&community);
3da2cc32
DS
6083 if (ecommunity)
6084 ecommunity_free(&ecommunity);
dd18c5a9
DS
6085 if (lcommunity)
6086 lcommunity_free(&lcommunity);
eaaf8adb
DS
6087
6088 return;
6089 }
6090
6091 /*
6092 * Mark the old as unusable
6093 */
40381db7
DS
6094 if (pi)
6095 bgp_path_info_delete(rn, pi);
eaaf8adb 6096
20894f50
DA
6097 attr = bgp_attr_aggregate_intern(
6098 bgp, origin, aspath, community, ecommunity, lcommunity,
6099 aggregate, atomic_aggregate, p);
6100
6101 if (!attr) {
6102 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6103 return;
6104 }
6105
3da2cc32 6106 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
6107 bgp->peer_self, attr, rn);
6108
1defdda8 6109 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6110
18ee8310 6111 bgp_path_info_add(rn, new);
c701010e
DS
6112 bgp_process(bgp, rn, afi, safi);
6113 } else {
6f94b685 6114 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6115 if (pi->peer == bgp->peer_self
6116 && pi->type == ZEBRA_ROUTE_BGP
6117 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6118 break;
6119
6120 /* Withdraw static BGP route from routing table. */
40381db7
DS
6121 if (pi) {
6122 bgp_path_info_delete(rn, pi);
c701010e
DS
6123 bgp_process(bgp, rn, afi, safi);
6124 }
6125 }
6126
6127 bgp_unlock_node(rn);
6128}
6129
b5d58c32 6130/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 6131void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 6132 afi_t afi, safi_t safi,
d62a17ae 6133 struct bgp_aggregate *aggregate)
6134{
6135 struct bgp_table *table;
6136 struct bgp_node *top;
6137 struct bgp_node *rn;
d7c0a89a 6138 uint8_t origin;
d62a17ae 6139 struct aspath *aspath = NULL;
d62a17ae 6140 struct community *community = NULL;
3da2cc32 6141 struct ecommunity *ecommunity = NULL;
dd18c5a9 6142 struct lcommunity *lcommunity = NULL;
40381db7 6143 struct bgp_path_info *pi;
d62a17ae 6144 unsigned long match = 0;
d7c0a89a 6145 uint8_t atomic_aggregate = 0;
d62a17ae 6146
9f822fa2
S
6147 /* If the bgp instance is being deleted or self peer is deleted
6148 * then do not create aggregate route
6149 */
6150 if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
6151 (bgp->peer_self == NULL))
6152 return;
6153
d62a17ae 6154 /* ORIGIN attribute: If at least one route among routes that are
6155 aggregated has ORIGIN with the value INCOMPLETE, then the
6156 aggregated route must have the ORIGIN attribute with the value
6157 INCOMPLETE. Otherwise, if at least one route among routes that
6158 are aggregated has ORIGIN with the value EGP, then the aggregated
6159 route must have the origin attribute with the value EGP. In all
6160 other case the value of the ORIGIN attribute of the aggregated
6161 route is INTERNAL. */
6162 origin = BGP_ORIGIN_IGP;
718e3744 6163
d62a17ae 6164 table = bgp->rib[afi][safi];
718e3744 6165
d62a17ae 6166 top = bgp_node_get(table, p);
6167 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
6168 rn = bgp_route_next_until(rn, top)) {
6169 if (rn->p.prefixlen <= p->prefixlen)
6170 continue;
d62a17ae 6171
c2ff8b3e 6172 match = 0;
d62a17ae 6173
6f94b685 6174 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6175 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6176 continue;
718e3744 6177
40381db7 6178 if (pi->attr->flag
c2ff8b3e
DS
6179 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6180 atomic_aggregate = 1;
d62a17ae 6181
40381db7 6182 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6183 continue;
d62a17ae 6184
f273fef1
DS
6185 /*
6186 * summary-only aggregate route suppress
6187 * aggregated route announcements.
6188 */
c2ff8b3e 6189 if (aggregate->summary_only) {
40381db7
DS
6190 (bgp_path_info_extra_get(pi))->suppress++;
6191 bgp_path_info_set_flag(rn, pi,
18ee8310 6192 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6193 match++;
d62a17ae 6194 }
c2ff8b3e
DS
6195
6196 aggregate->count++;
6197
f273fef1
DS
6198 /*
6199 * If at least one route among routes that are
6200 * aggregated has ORIGIN with the value INCOMPLETE,
6201 * then the aggregated route MUST have the ORIGIN
6202 * attribute with the value INCOMPLETE. Otherwise, if
6203 * at least one route among routes that are aggregated
6204 * has ORIGIN with the value EGP, then the aggregated
6205 * route MUST have the ORIGIN attribute with the value
6206 * EGP.
6207 */
fc968841
NT
6208 switch (pi->attr->origin) {
6209 case BGP_ORIGIN_INCOMPLETE:
6210 aggregate->incomplete_origin_count++;
6211 break;
6212 case BGP_ORIGIN_EGP:
6213 aggregate->egp_origin_count++;
6214 break;
6215 default:
6216 /*Do nothing.
6217 */
6218 break;
6219 }
c2ff8b3e
DS
6220
6221 if (!aggregate->as_set)
6222 continue;
6223
f273fef1
DS
6224 /*
6225 * as-set aggregate route generate origin, as path,
6226 * and community aggregation.
6227 */
fc968841
NT
6228 /* Compute aggregate route's as-path.
6229 */
ef51a7d8 6230 bgp_compute_aggregate_aspath_hash(aggregate,
6231 pi->attr->aspath);
c2ff8b3e 6232
fc968841
NT
6233 /* Compute aggregate route's community.
6234 */
6235 if (pi->attr->community)
21fec674 6236 bgp_compute_aggregate_community_hash(
fc968841
NT
6237 aggregate,
6238 pi->attr->community);
dd18c5a9 6239
fc968841
NT
6240 /* Compute aggregate route's extended community.
6241 */
6242 if (pi->attr->ecommunity)
4edd83f9 6243 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6244 aggregate,
6245 pi->attr->ecommunity);
6246
6247 /* Compute aggregate route's large community.
6248 */
6249 if (pi->attr->lcommunity)
f1eb1f05 6250 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6251 aggregate,
6252 pi->attr->lcommunity);
d62a17ae 6253 }
c2ff8b3e
DS
6254 if (match)
6255 bgp_process(bgp, rn, afi, safi);
6256 }
21fec674 6257 if (aggregate->as_set) {
ef51a7d8 6258 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6259 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6260 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6261 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6262 }
6263
f1eb1f05 6264
d62a17ae 6265 bgp_unlock_node(top);
718e3744 6266
718e3744 6267
fc968841
NT
6268 if (aggregate->incomplete_origin_count > 0)
6269 origin = BGP_ORIGIN_INCOMPLETE;
6270 else if (aggregate->egp_origin_count > 0)
6271 origin = BGP_ORIGIN_EGP;
d62a17ae 6272
fc968841
NT
6273 if (aggregate->as_set) {
6274 if (aggregate->aspath)
6275 /* Retrieve aggregate route's as-path.
6276 */
6277 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6278
fc968841
NT
6279 if (aggregate->community)
6280 /* Retrieve aggregate route's community.
6281 */
6282 community = community_dup(aggregate->community);
3da2cc32 6283
fc968841
NT
6284 if (aggregate->ecommunity)
6285 /* Retrieve aggregate route's ecommunity.
6286 */
6287 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6288
fc968841
NT
6289 if (aggregate->lcommunity)
6290 /* Retrieve aggregate route's lcommunity.
6291 */
6292 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6293 }
718e3744 6294
c701010e 6295 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6296 ecommunity, lcommunity, atomic_aggregate,
6297 aggregate);
718e3744 6298}
6299
20894f50 6300void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6301 safi_t safi, struct bgp_aggregate *aggregate)
6302{
6303 struct bgp_table *table;
6304 struct bgp_node *top;
6305 struct bgp_node *rn;
40381db7 6306 struct bgp_path_info *pi;
3b7db173
DS
6307 unsigned long match;
6308
6309 table = bgp->rib[afi][safi];
6310
6311 /* If routes exists below this node, generate aggregate routes. */
6312 top = bgp_node_get(table, p);
6313 for (rn = bgp_node_get(table, p); rn;
6314 rn = bgp_route_next_until(rn, top)) {
6315 if (rn->p.prefixlen <= p->prefixlen)
6316 continue;
6317 match = 0;
6318
6f94b685 6319 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6320 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6321 continue;
6322
40381db7 6323 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6324 continue;
6325
40381db7
DS
6326 if (aggregate->summary_only && pi->extra) {
6327 pi->extra->suppress--;
3b7db173 6328
40381db7 6329 if (pi->extra->suppress == 0) {
18ee8310 6330 bgp_path_info_set_flag(
40381db7 6331 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6332 match++;
6333 }
6334 }
6335 aggregate->count--;
fc968841
NT
6336
6337 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6338 aggregate->incomplete_origin_count--;
6339 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6340 aggregate->egp_origin_count--;
6341
6342 if (aggregate->as_set) {
6343 /* Remove as-path from aggregate.
6344 */
ef51a7d8 6345 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6346 aggregate,
6347 pi->attr->aspath);
6348
6349 if (pi->attr->community)
6350 /* Remove community from aggregate.
6351 */
21fec674 6352 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6353 aggregate,
6354 pi->attr->community);
6355
6356 if (pi->attr->ecommunity)
6357 /* Remove ecommunity from aggregate.
6358 */
4edd83f9 6359 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6360 aggregate,
6361 pi->attr->ecommunity);
6362
6363 if (pi->attr->lcommunity)
6364 /* Remove lcommunity from aggregate.
6365 */
f1eb1f05 6366 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6367 aggregate,
6368 pi->attr->lcommunity);
6369 }
6370
3b7db173
DS
6371 }
6372
6373 /* If this node was suppressed, process the change. */
6374 if (match)
6375 bgp_process(bgp, rn, afi, safi);
6376 }
f1eb1f05 6377 if (aggregate->as_set) {
ef51a7d8 6378 aspath_free(aggregate->aspath);
6379 aggregate->aspath = NULL;
21fec674 6380 if (aggregate->community)
6381 community_free(&aggregate->community);
4edd83f9 6382 if (aggregate->ecommunity)
6383 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6384 if (aggregate->lcommunity)
6385 lcommunity_free(&aggregate->lcommunity);
6386 }
6387
3b7db173
DS
6388 bgp_unlock_node(top);
6389}
718e3744 6390
fc968841
NT
6391static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6392 struct bgp_path_info *pinew, afi_t afi,
6393 safi_t safi,
6394 struct bgp_aggregate *aggregate)
6395{
6396 uint8_t origin;
6397 struct aspath *aspath = NULL;
6398 uint8_t atomic_aggregate = 0;
6399 struct community *community = NULL;
6400 struct ecommunity *ecommunity = NULL;
6401 struct lcommunity *lcommunity = NULL;
6402
6403 /* ORIGIN attribute: If at least one route among routes that are
6404 * aggregated has ORIGIN with the value INCOMPLETE, then the
6405 * aggregated route must have the ORIGIN attribute with the value
6406 * INCOMPLETE. Otherwise, if at least one route among routes that
6407 * are aggregated has ORIGIN with the value EGP, then the aggregated
6408 * route must have the origin attribute with the value EGP. In all
6409 * other case the value of the ORIGIN attribute of the aggregated
6410 * route is INTERNAL.
6411 */
6412 origin = BGP_ORIGIN_IGP;
6413
6414 aggregate->count++;
6415
6416 if (aggregate->summary_only)
6417 (bgp_path_info_extra_get(pinew))->suppress++;
6418
6419 switch (pinew->attr->origin) {
6420 case BGP_ORIGIN_INCOMPLETE:
6421 aggregate->incomplete_origin_count++;
6422 break;
6423 case BGP_ORIGIN_EGP:
6424 aggregate->egp_origin_count++;
6425 break;
6426 default:
6427 /* Do nothing.
6428 */
6429 break;
6430 }
6431
6432 if (aggregate->incomplete_origin_count > 0)
6433 origin = BGP_ORIGIN_INCOMPLETE;
6434 else if (aggregate->egp_origin_count > 0)
6435 origin = BGP_ORIGIN_EGP;
6436
6437 if (aggregate->as_set) {
6438 /* Compute aggregate route's as-path.
6439 */
6440 bgp_compute_aggregate_aspath(aggregate,
6441 pinew->attr->aspath);
6442
6443 /* Compute aggregate route's community.
6444 */
6445 if (pinew->attr->community)
6446 bgp_compute_aggregate_community(
6447 aggregate,
6448 pinew->attr->community);
6449
6450 /* Compute aggregate route's extended community.
6451 */
6452 if (pinew->attr->ecommunity)
6453 bgp_compute_aggregate_ecommunity(
6454 aggregate,
6455 pinew->attr->ecommunity);
6456
6457 /* Compute aggregate route's large community.
6458 */
6459 if (pinew->attr->lcommunity)
6460 bgp_compute_aggregate_lcommunity(
6461 aggregate,
6462 pinew->attr->lcommunity);
6463
6464 /* Retrieve aggregate route's as-path.
6465 */
6466 if (aggregate->aspath)
6467 aspath = aspath_dup(aggregate->aspath);
6468
6469 /* Retrieve aggregate route's community.
6470 */
6471 if (aggregate->community)
6472 community = community_dup(aggregate->community);
6473
6474 /* Retrieve aggregate route's ecommunity.
6475 */
6476 if (aggregate->ecommunity)
6477 ecommunity = ecommunity_dup(aggregate->ecommunity);
6478
6479 /* Retrieve aggregate route's lcommunity.
6480 */
6481 if (aggregate->lcommunity)
6482 lcommunity = lcommunity_dup(aggregate->lcommunity);
6483 }
6484
6485 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6486 aspath, community, ecommunity,
6487 lcommunity, atomic_aggregate, aggregate);
6488}
6489
6490static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6491 safi_t safi,
6492 struct bgp_path_info *pi,
6493 struct bgp_aggregate *aggregate,
6494 struct prefix *aggr_p)
6495{
6496 uint8_t origin;
6497 struct aspath *aspath = NULL;
6498 uint8_t atomic_aggregate = 0;
6499 struct community *community = NULL;
6500 struct ecommunity *ecommunity = NULL;
6501 struct lcommunity *lcommunity = NULL;
6502 unsigned long match = 0;
6503
6504 if (BGP_PATH_HOLDDOWN(pi))
6505 return;
6506
6507 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6508 return;
6509
6510 if (aggregate->summary_only
6511 && pi->extra
6512 && pi->extra->suppress > 0) {
6513 pi->extra->suppress--;
6514
6515 if (pi->extra->suppress == 0) {
6516 bgp_path_info_set_flag(pi->net, pi,
6517 BGP_PATH_ATTR_CHANGED);
6518 match++;
6519 }
6520 }
6521
6522 if (aggregate->count > 0)
6523 aggregate->count--;
6524
6525 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6526 aggregate->incomplete_origin_count--;
6527 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6528 aggregate->egp_origin_count--;
6529
6530 if (aggregate->as_set) {
6531 /* Remove as-path from aggregate.
6532 */
6533 bgp_remove_aspath_from_aggregate(aggregate,
6534 pi->attr->aspath);
6535
6536 if (pi->attr->community)
6537 /* Remove community from aggregate.
6538 */
6539 bgp_remove_community_from_aggregate(
6540 aggregate,
6541 pi->attr->community);
6542
6543 if (pi->attr->ecommunity)
6544 /* Remove ecommunity from aggregate.
6545 */
6546 bgp_remove_ecommunity_from_aggregate(
6547 aggregate,
6548 pi->attr->ecommunity);
6549
6550 if (pi->attr->lcommunity)
6551 /* Remove lcommunity from aggregate.
6552 */
6553 bgp_remove_lcommunity_from_aggregate(
6554 aggregate,
6555 pi->attr->lcommunity);
6556 }
6557
6558 /* If this node was suppressed, process the change. */
6559 if (match)
6560 bgp_process(bgp, pi->net, afi, safi);
6561
6562 origin = BGP_ORIGIN_IGP;
6563 if (aggregate->incomplete_origin_count > 0)
6564 origin = BGP_ORIGIN_INCOMPLETE;
6565 else if (aggregate->egp_origin_count > 0)
6566 origin = BGP_ORIGIN_EGP;
6567
6568 if (aggregate->as_set) {
6569 /* Retrieve aggregate route's as-path.
6570 */
6571 if (aggregate->aspath)
6572 aspath = aspath_dup(aggregate->aspath);
6573
6574 /* Retrieve aggregate route's community.
6575 */
6576 if (aggregate->community)
6577 community = community_dup(aggregate->community);
6578
6579 /* Retrieve aggregate route's ecommunity.
6580 */
6581 if (aggregate->ecommunity)
6582 ecommunity = ecommunity_dup(aggregate->ecommunity);
6583
6584 /* Retrieve aggregate route's lcommunity.
6585 */
6586 if (aggregate->lcommunity)
6587 lcommunity = lcommunity_dup(aggregate->lcommunity);
6588 }
6589
6590 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6591 aspath, community, ecommunity,
6592 lcommunity, atomic_aggregate, aggregate);
6593}
6594
d62a17ae 6595void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6596 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6597{
d62a17ae 6598 struct bgp_node *child;
6599 struct bgp_node *rn;
6600 struct bgp_aggregate *aggregate;
6601 struct bgp_table *table;
718e3744 6602
d62a17ae 6603 table = bgp->aggregate[afi][safi];
f018db83 6604
d62a17ae 6605 /* No aggregates configured. */
6606 if (bgp_table_top_nolock(table) == NULL)
6607 return;
f018db83 6608
d62a17ae 6609 if (p->prefixlen == 0)
6610 return;
718e3744 6611
40381db7 6612 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6613 return;
718e3744 6614
d62a17ae 6615 child = bgp_node_get(table, p);
718e3744 6616
d62a17ae 6617 /* Aggregate address configuration check. */
b1e62edd 6618 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6619 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6620 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6621 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6622 safi, aggregate);
d62a17ae 6623 }
b1e62edd 6624 }
d62a17ae 6625 bgp_unlock_node(child);
718e3744 6626}
6627
d62a17ae 6628void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6629 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6630{
d62a17ae 6631 struct bgp_node *child;
6632 struct bgp_node *rn;
6633 struct bgp_aggregate *aggregate;
6634 struct bgp_table *table;
718e3744 6635
d62a17ae 6636 table = bgp->aggregate[afi][safi];
718e3744 6637
d62a17ae 6638 /* No aggregates configured. */
6639 if (bgp_table_top_nolock(table) == NULL)
6640 return;
718e3744 6641
d62a17ae 6642 if (p->prefixlen == 0)
6643 return;
718e3744 6644
d62a17ae 6645 child = bgp_node_get(table, p);
718e3744 6646
d62a17ae 6647 /* Aggregate address configuration check. */
b1e62edd 6648 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6649 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6650 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6651 bgp_remove_route_from_aggregate(bgp, afi, safi,
6652 del, aggregate, &rn->p);
d62a17ae 6653 }
b1e62edd 6654 }
d62a17ae 6655 bgp_unlock_node(child);
6656}
718e3744 6657
718e3744 6658/* Aggregate route attribute. */
6659#define AGGREGATE_SUMMARY_ONLY 1
6660#define AGGREGATE_AS_SET 1
fb29348a 6661#define AGGREGATE_AS_UNSET 0
718e3744 6662
d62a17ae 6663static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6664 afi_t afi, safi_t safi)
718e3744 6665{
d62a17ae 6666 VTY_DECLVAR_CONTEXT(bgp, bgp);
6667 int ret;
6668 struct prefix p;
6669 struct bgp_node *rn;
6670 struct bgp_aggregate *aggregate;
718e3744 6671
d62a17ae 6672 /* Convert string to prefix structure. */
6673 ret = str2prefix(prefix_str, &p);
6674 if (!ret) {
6675 vty_out(vty, "Malformed prefix\n");
6676 return CMD_WARNING_CONFIG_FAILED;
6677 }
6678 apply_mask(&p);
6679
6680 /* Old configuration check. */
6681 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6682 if (!rn) {
6683 vty_out(vty,
6684 "%% There is no aggregate-address configuration.\n");
6685 return CMD_WARNING_CONFIG_FAILED;
6686 }
f6269b4f 6687
b613a918 6688 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6689 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6690 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6691 NULL, NULL, 0, aggregate);
d62a17ae 6692
6693 /* Unlock aggregate address configuration. */
b613a918 6694 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6695
6696 if (aggregate->community)
6697 community_free(&aggregate->community);
6698
6699 if (aggregate->community_hash) {
6700 /* Delete all communities in the hash.
6701 */
6702 hash_clean(aggregate->community_hash,
6703 bgp_aggr_community_remove);
6704 /* Free up the community_hash.
6705 */
6706 hash_free(aggregate->community_hash);
6707 }
6708
6709 if (aggregate->ecommunity)
6710 ecommunity_free(&aggregate->ecommunity);
6711
6712 if (aggregate->ecommunity_hash) {
6713 /* Delete all ecommunities in the hash.
6714 */
6715 hash_clean(aggregate->ecommunity_hash,
6716 bgp_aggr_ecommunity_remove);
6717 /* Free up the ecommunity_hash.
6718 */
6719 hash_free(aggregate->ecommunity_hash);
6720 }
6721
6722 if (aggregate->lcommunity)
6723 lcommunity_free(&aggregate->lcommunity);
6724
6725 if (aggregate->lcommunity_hash) {
6726 /* Delete all lcommunities in the hash.
6727 */
6728 hash_clean(aggregate->lcommunity_hash,
6729 bgp_aggr_lcommunity_remove);
6730 /* Free up the lcommunity_hash.
6731 */
6732 hash_free(aggregate->lcommunity_hash);
6733 }
6734
6735 if (aggregate->aspath)
6736 aspath_free(aggregate->aspath);
6737
6738 if (aggregate->aspath_hash) {
6739 /* Delete all as-paths in the hash.
6740 */
6741 hash_clean(aggregate->aspath_hash,
6742 bgp_aggr_aspath_remove);
6743 /* Free up the aspath_hash.
6744 */
6745 hash_free(aggregate->aspath_hash);
6746 }
6747
d62a17ae 6748 bgp_aggregate_free(aggregate);
6749 bgp_unlock_node(rn);
6750 bgp_unlock_node(rn);
6751
6752 return CMD_SUCCESS;
6753}
6754
6755static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
20894f50
DA
6756 safi_t safi, const char *rmap, uint8_t summary_only,
6757 uint8_t as_set)
d62a17ae 6758{
6759 VTY_DECLVAR_CONTEXT(bgp, bgp);
6760 int ret;
6761 struct prefix p;
6762 struct bgp_node *rn;
6763 struct bgp_aggregate *aggregate;
fb29348a 6764 uint8_t as_set_new = as_set;
d62a17ae 6765
6766 /* Convert string to prefix structure. */
6767 ret = str2prefix(prefix_str, &p);
6768 if (!ret) {
6769 vty_out(vty, "Malformed prefix\n");
6770 return CMD_WARNING_CONFIG_FAILED;
6771 }
6772 apply_mask(&p);
6773
3624ac81
DS
6774 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6775 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6776 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6777 prefix_str);
6778 return CMD_WARNING_CONFIG_FAILED;
6779 }
6780
d62a17ae 6781 /* Old configuration check. */
6782 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6783 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6784
20894f50 6785 if (aggregate) {
d62a17ae 6786 vty_out(vty, "There is already same aggregate network.\n");
6787 /* try to remove the old entry */
6788 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6789 if (ret) {
6790 vty_out(vty, "Error deleting aggregate.\n");
6791 bgp_unlock_node(rn);
6792 return CMD_WARNING_CONFIG_FAILED;
6793 }
6794 }
718e3744 6795
d62a17ae 6796 /* Make aggregate address structure. */
6797 aggregate = bgp_aggregate_new();
6798 aggregate->summary_only = summary_only;
fb29348a
DA
6799
6800 /* Network operators MUST NOT locally generate any new
6801 * announcements containing AS_SET or AS_CONFED_SET. If they have
6802 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6803 * SHOULD withdraw those routes and re-announce routes for the
6804 * aggregate or component prefixes (i.e., the more-specific routes
6805 * subsumed by the previously aggregated route) without AS_SET
6806 * or AS_CONFED_SET in the updates.
6807 */
6808 if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
6809 if (as_set == AGGREGATE_AS_SET) {
6810 as_set_new = AGGREGATE_AS_UNSET;
6811 zlog_warn(
6812 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6813 __func__);
6814 vty_out(vty,
6815 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6816 }
6817 }
6818
6819 aggregate->as_set = as_set_new;
d62a17ae 6820 aggregate->safi = safi;
20894f50
DA
6821
6822 if (rmap) {
6823 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6824 route_map_counter_decrement(aggregate->rmap.map);
6825 aggregate->rmap.name =
6826 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6827 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6828 route_map_counter_increment(aggregate->rmap.map);
6829 }
b613a918 6830 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6831
d62a17ae 6832 /* Aggregate address insert into BGP routing table. */
fc968841 6833 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6834
d62a17ae 6835 return CMD_SUCCESS;
718e3744 6836}
6837
6838DEFUN (aggregate_address,
6839 aggregate_address_cmd,
20894f50 6840 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6841 "Configure BGP aggregate entries\n"
6842 "Aggregate prefix\n"
6843 "Generate AS set path information\n"
a636c635
DW
6844 "Filter more specific routes from updates\n"
6845 "Filter more specific routes from updates\n"
20894f50
DA
6846 "Generate AS set path information\n"
6847 "Apply route map to aggregate network\n"
6848 "Name of route map\n")
718e3744 6849{
d62a17ae 6850 int idx = 0;
6851 argv_find(argv, argc, "A.B.C.D/M", &idx);
6852 char *prefix = argv[idx]->arg;
20894f50 6853 char *rmap = NULL;
fb29348a
DA
6854 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6855 : AGGREGATE_AS_UNSET;
d62a17ae 6856 idx = 0;
6857 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6858 ? AGGREGATE_SUMMARY_ONLY
6859 : 0;
e3e6107d 6860
20894f50
DA
6861 idx = 0;
6862 argv_find(argv, argc, "WORD", &idx);
6863 if (idx)
6864 rmap = argv[idx]->arg;
6865
d62a17ae 6866 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
20894f50 6867 rmap, summary_only, as_set);
718e3744 6868}
6869
e3e6107d
QY
6870DEFUN (aggregate_address_mask,
6871 aggregate_address_mask_cmd,
20894f50 6872 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6873 "Configure BGP aggregate entries\n"
6874 "Aggregate address\n"
6875 "Aggregate mask\n"
6876 "Generate AS set path information\n"
a636c635
DW
6877 "Filter more specific routes from updates\n"
6878 "Filter more specific routes from updates\n"
20894f50
DA
6879 "Generate AS set path information\n"
6880 "Apply route map to aggregate network\n"
6881 "Name of route map\n")
718e3744 6882{
d62a17ae 6883 int idx = 0;
6884 argv_find(argv, argc, "A.B.C.D", &idx);
6885 char *prefix = argv[idx]->arg;
6886 char *mask = argv[idx + 1]->arg;
cf40d052 6887 bool rmap_found;
20894f50 6888 char *rmap = NULL;
fb29348a
DA
6889 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6890 : AGGREGATE_AS_UNSET;
d62a17ae 6891 idx = 0;
6892 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6893 ? AGGREGATE_SUMMARY_ONLY
6894 : 0;
6895
cf40d052
DS
6896 rmap_found = argv_find(argv, argc, "WORD", &idx);
6897 if (rmap_found)
20894f50
DA
6898 rmap = argv[idx]->arg;
6899
d62a17ae 6900 char prefix_str[BUFSIZ];
6901 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6902
6903 if (!ret) {
6904 vty_out(vty, "%% Inconsistent address and mask\n");
6905 return CMD_WARNING_CONFIG_FAILED;
6906 }
718e3744 6907
d62a17ae 6908 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
20894f50 6909 rmap, summary_only, as_set);
718e3744 6910}
6911
718e3744 6912DEFUN (no_aggregate_address,
6913 no_aggregate_address_cmd,
b84da0db 6914 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6915 NO_STR
6916 "Configure BGP aggregate entries\n"
a636c635
DW
6917 "Aggregate prefix\n"
6918 "Generate AS set path information\n"
e3e6107d
QY
6919 "Filter more specific routes from updates\n"
6920 "Filter more specific routes from updates\n"
b84da0db
DA
6921 "Generate AS set path information\n"
6922 "Apply route map to aggregate network\n"
6923 "Name of route map\n")
718e3744 6924{
d62a17ae 6925 int idx = 0;
6926 argv_find(argv, argc, "A.B.C.D/M", &idx);
6927 char *prefix = argv[idx]->arg;
6928 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6929}
6930
718e3744 6931DEFUN (no_aggregate_address_mask,
6932 no_aggregate_address_mask_cmd,
b84da0db 6933 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6934 NO_STR
6935 "Configure BGP aggregate entries\n"
6936 "Aggregate address\n"
a636c635
DW
6937 "Aggregate mask\n"
6938 "Generate AS set path information\n"
e3e6107d
QY
6939 "Filter more specific routes from updates\n"
6940 "Filter more specific routes from updates\n"
b84da0db
DA
6941 "Generate AS set path information\n"
6942 "Apply route map to aggregate network\n"
6943 "Name of route map\n")
718e3744 6944{
d62a17ae 6945 int idx = 0;
6946 argv_find(argv, argc, "A.B.C.D", &idx);
6947 char *prefix = argv[idx]->arg;
6948 char *mask = argv[idx + 1]->arg;
718e3744 6949
d62a17ae 6950 char prefix_str[BUFSIZ];
6951 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6952
d62a17ae 6953 if (!ret) {
6954 vty_out(vty, "%% Inconsistent address and mask\n");
6955 return CMD_WARNING_CONFIG_FAILED;
6956 }
718e3744 6957
d62a17ae 6958 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6959}
6960
718e3744 6961DEFUN (ipv6_aggregate_address,
6962 ipv6_aggregate_address_cmd,
20894f50 6963 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6964 "Configure BGP aggregate entries\n"
6965 "Aggregate prefix\n"
5101fece 6966 "Generate AS set path information\n"
6967 "Filter more specific routes from updates\n"
6968 "Filter more specific routes from updates\n"
20894f50
DA
6969 "Generate AS set path information\n"
6970 "Apply route map to aggregate network\n"
6971 "Name of route map\n")
718e3744 6972{
d62a17ae 6973 int idx = 0;
6974 argv_find(argv, argc, "X:X::X:X/M", &idx);
6975 char *prefix = argv[idx]->arg;
20894f50 6976 char *rmap = NULL;
273fae13 6977 bool rmap_found;
fb29348a
DA
6978 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6979 : AGGREGATE_AS_UNSET;
5101fece 6980
6981 idx = 0;
d62a17ae 6982 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6983 ? AGGREGATE_SUMMARY_ONLY
6984 : 0;
20894f50 6985
273fae13
DA
6986 rmap_found = argv_find(argv, argc, "WORD", &idx);
6987 if (rmap_found)
20894f50
DA
6988 rmap = argv[idx]->arg;
6989
6990 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
6991 sum_only, as_set);
718e3744 6992}
6993
6994DEFUN (no_ipv6_aggregate_address,
6995 no_ipv6_aggregate_address_cmd,
b84da0db 6996 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
718e3744 6997 NO_STR
6998 "Configure BGP aggregate entries\n"
16cedbb0 6999 "Aggregate prefix\n"
5101fece 7000 "Generate AS set path information\n"
7001 "Filter more specific routes from updates\n"
7002 "Filter more specific routes from updates\n"
b84da0db
DA
7003 "Generate AS set path information\n"
7004 "Apply route map to aggregate network\n"
7005 "Name of route map\n")
718e3744 7006{
d62a17ae 7007 int idx = 0;
7008 argv_find(argv, argc, "X:X::X:X/M", &idx);
7009 char *prefix = argv[idx]->arg;
7010 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7011}
7012
718e3744 7013/* Redistribute route treatment. */
d62a17ae 7014void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7015 const union g_addr *nexthop, ifindex_t ifindex,
7016 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7017 uint8_t type, unsigned short instance,
7018 route_tag_t tag)
d62a17ae 7019{
4b7e6066 7020 struct bgp_path_info *new;
40381db7
DS
7021 struct bgp_path_info *bpi;
7022 struct bgp_path_info rmap_path;
d62a17ae 7023 struct bgp_node *bn;
7024 struct attr attr;
7025 struct attr *new_attr;
7026 afi_t afi;
b68885f9 7027 route_map_result_t ret;
d62a17ae 7028 struct bgp_redist *red;
7029
7030 /* Make default attribute. */
7031 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7032 /*
7033 * This must not be NULL to satisfy Coverity SA
7034 */
7035 assert(attr.aspath);
9de1f7ff 7036
a4d82a8a 7037 switch (nhtype) {
9de1f7ff
DS
7038 case NEXTHOP_TYPE_IFINDEX:
7039 break;
7040 case NEXTHOP_TYPE_IPV4:
7041 case NEXTHOP_TYPE_IPV4_IFINDEX:
7042 attr.nexthop = nexthop->ipv4;
7043 break;
7044 case NEXTHOP_TYPE_IPV6:
7045 case NEXTHOP_TYPE_IPV6_IFINDEX:
7046 attr.mp_nexthop_global = nexthop->ipv6;
7047 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7048 break;
7049 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7050 switch (p->family) {
7051 case AF_INET:
9de1f7ff 7052 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7053 break;
7054 case AF_INET6:
9de1f7ff
DS
7055 memset(&attr.mp_nexthop_global, 0,
7056 sizeof(attr.mp_nexthop_global));
74489921 7057 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7058 break;
74489921 7059 }
9de1f7ff 7060 break;
d62a17ae 7061 }
74489921 7062 attr.nh_ifindex = ifindex;
f04a80a5 7063
d62a17ae 7064 attr.med = metric;
7065 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7066 attr.tag = tag;
718e3744 7067
d62a17ae 7068 afi = family2afi(p->family);
6aeb9e78 7069
d62a17ae 7070 red = bgp_redist_lookup(bgp, afi, type, instance);
7071 if (red) {
7072 struct attr attr_new;
718e3744 7073
d62a17ae 7074 /* Copy attribute for modification. */
6f4f49b2 7075 attr_new = attr;
718e3744 7076
d62a17ae 7077 if (red->redist_metric_flag)
7078 attr_new.med = red->redist_metric;
718e3744 7079
d62a17ae 7080 /* Apply route-map. */
7081 if (red->rmap.name) {
40381db7
DS
7082 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7083 rmap_path.peer = bgp->peer_self;
7084 rmap_path.attr = &attr_new;
718e3744 7085
d62a17ae 7086 SET_FLAG(bgp->peer_self->rmap_type,
7087 PEER_RMAP_TYPE_REDISTRIBUTE);
7088
7089 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7090 &rmap_path);
d62a17ae 7091
7092 bgp->peer_self->rmap_type = 0;
7093
7094 if (ret == RMAP_DENYMATCH) {
7095 /* Free uninterned attribute. */
7096 bgp_attr_flush(&attr_new);
7097
7098 /* Unintern original. */
7099 aspath_unintern(&attr.aspath);
7100 bgp_redistribute_delete(bgp, p, type, instance);
7101 return;
7102 }
7103 }
7104
7f323236
DW
7105 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
7106 bgp_attr_add_gshut_community(&attr_new);
7107
d62a17ae 7108 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7109 SAFI_UNICAST, p, NULL);
7110
7111 new_attr = bgp_attr_intern(&attr_new);
7112
6f94b685
DS
7113 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
7114 bpi = bpi->next)
40381db7
DS
7115 if (bpi->peer == bgp->peer_self
7116 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7117 break;
7118
40381db7 7119 if (bpi) {
d62a17ae 7120 /* Ensure the (source route) type is updated. */
40381db7
DS
7121 bpi->type = type;
7122 if (attrhash_cmp(bpi->attr, new_attr)
7123 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7124 bgp_attr_unintern(&new_attr);
7125 aspath_unintern(&attr.aspath);
7126 bgp_unlock_node(bn);
7127 return;
7128 } else {
7129 /* The attribute is changed. */
40381db7 7130 bgp_path_info_set_flag(bn, bpi,
18ee8310 7131 BGP_PATH_ATTR_CHANGED);
d62a17ae 7132
7133 /* Rewrite BGP route information. */
40381db7
DS
7134 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7135 bgp_path_info_restore(bn, bpi);
d62a17ae 7136 else
40381db7
DS
7137 bgp_aggregate_decrement(
7138 bgp, p, bpi, afi, SAFI_UNICAST);
7139 bgp_attr_unintern(&bpi->attr);
7140 bpi->attr = new_attr;
7141 bpi->uptime = bgp_clock();
d62a17ae 7142
7143 /* Process change. */
40381db7 7144 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7145 SAFI_UNICAST);
7146 bgp_process(bgp, bn, afi, SAFI_UNICAST);
7147 bgp_unlock_node(bn);
7148 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7149
7150 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7151 || (bgp->inst_type
7152 == BGP_INSTANCE_TYPE_DEFAULT)) {
7153
7154 vpn_leak_from_vrf_update(
40381db7 7155 bgp_get_default(), bgp, bpi);
ddb5b488 7156 }
d62a17ae 7157 return;
7158 }
7159 }
7160
7161 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7162 bgp->peer_self, new_attr, bn);
1defdda8 7163 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7164
7165 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7166 bgp_path_info_add(bn, new);
d62a17ae 7167 bgp_unlock_node(bn);
7168 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7169
7170 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7171 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7172
7173 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7174 }
d62a17ae 7175 }
7176
7177 /* Unintern original. */
7178 aspath_unintern(&attr.aspath);
718e3744 7179}
7180
d7c0a89a
QY
7181void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7182 unsigned short instance)
718e3744 7183{
d62a17ae 7184 afi_t afi;
7185 struct bgp_node *rn;
40381db7 7186 struct bgp_path_info *pi;
d62a17ae 7187 struct bgp_redist *red;
718e3744 7188
d62a17ae 7189 afi = family2afi(p->family);
718e3744 7190
d62a17ae 7191 red = bgp_redist_lookup(bgp, afi, type, instance);
7192 if (red) {
7193 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7194 SAFI_UNICAST, p, NULL);
7195
6f94b685 7196 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 7197 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7198 break;
7199
40381db7 7200 if (pi) {
ddb5b488
PZ
7201 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7202 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7203
7204 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7205 bgp, pi);
ddb5b488 7206 }
40381db7
DS
7207 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
7208 bgp_path_info_delete(rn, pi);
d62a17ae 7209 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7210 }
7211 bgp_unlock_node(rn);
7212 }
7213}
7214
7215/* Withdraw specified route type's route. */
7216void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7217 unsigned short instance)
d62a17ae 7218{
7219 struct bgp_node *rn;
40381db7 7220 struct bgp_path_info *pi;
d62a17ae 7221 struct bgp_table *table;
7222
7223 table = bgp->rib[afi][SAFI_UNICAST];
7224
7225 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 7226 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
7227 if (pi->peer == bgp->peer_self && pi->type == type
7228 && pi->instance == instance)
d62a17ae 7229 break;
7230
40381db7 7231 if (pi) {
ddb5b488
PZ
7232 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7233 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7234
7235 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7236 bgp, pi);
ddb5b488 7237 }
40381db7 7238 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 7239 SAFI_UNICAST);
40381db7 7240 bgp_path_info_delete(rn, pi);
d62a17ae 7241 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7242 }
718e3744 7243 }
718e3744 7244}
6b0655a2 7245
718e3744 7246/* Static function to display route. */
9c92b5f7
MK
7247static void route_vty_out_route(struct prefix *p, struct vty *vty,
7248 json_object *json)
718e3744 7249{
be054588 7250 int len = 0;
d62a17ae 7251 char buf[BUFSIZ];
50e05855 7252 char buf2[BUFSIZ];
718e3744 7253
d62a17ae 7254 if (p->family == AF_INET) {
c6462ff4 7255 if (!json) {
89e5e9f0
PM
7256 len = vty_out(
7257 vty, "%s/%d",
7258 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7259 p->prefixlen);
c6462ff4
MK
7260 } else {
7261 json_object_string_add(json, "prefix",
7262 inet_ntop(p->family,
7263 &p->u.prefix, buf,
7264 BUFSIZ));
7265 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7266 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7267 json_object_string_add(json, "network", buf2);
c6462ff4 7268 }
d62a17ae 7269 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7270 prefix2str(p, buf, PREFIX_STRLEN);
7271 len = vty_out(vty, "%s", buf);
7272 } else if (p->family == AF_EVPN) {
57f7feb6 7273 if (!json)
60466a63
QY
7274 len = vty_out(
7275 vty, "%s",
7276 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7277 BUFSIZ));
57f7feb6 7278 else
60466a63 7279 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7280 } else if (p->family == AF_FLOWSPEC) {
7281 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7282 json ?
7283 NLRI_STRING_FORMAT_JSON_SIMPLE :
7284 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7285 } else {
c6462ff4 7286 if (!json)
60466a63
QY
7287 len = vty_out(
7288 vty, "%s/%d",
7289 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7290 p->prefixlen);
50e05855
AD
7291 else {
7292 json_object_string_add(json, "prefix",
7293 inet_ntop(p->family,
7294 &p->u.prefix, buf,
7295 BUFSIZ));
7296 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7297 prefix2str(p, buf2, PREFIX_STRLEN);
7298 json_object_string_add(json, "network", buf2);
7299 }
9c92b5f7 7300 }
d62a17ae 7301
9c92b5f7
MK
7302 if (!json) {
7303 len = 17 - len;
7304 if (len < 1)
7305 vty_out(vty, "\n%*s", 20, " ");
7306 else
7307 vty_out(vty, "%*s", len, " ");
7308 }
718e3744 7309}
7310
d62a17ae 7311enum bgp_display_type {
7312 normal_list,
718e3744 7313};
7314
18ee8310 7315/* Print the short form route status for a bgp_path_info */
4b7e6066 7316static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7317 struct bgp_path_info *path,
d62a17ae 7318 json_object *json_path)
718e3744 7319{
d62a17ae 7320 if (json_path) {
b05a1c8b 7321
d62a17ae 7322 /* Route status display. */
9b6d8fcf 7323 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7324 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7325
9b6d8fcf 7326 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7327 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7328
9b6d8fcf 7329 if (path->extra && path->extra->suppress)
d62a17ae 7330 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7331
9b6d8fcf
DS
7332 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7333 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7334 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7335
d62a17ae 7336 /* Selected */
9b6d8fcf 7337 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7338 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7339
9b6d8fcf 7340 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7341 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7342
9b6d8fcf 7343 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7344 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7345
9b6d8fcf 7346 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7347 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7348
d62a17ae 7349 /* Internal route. */
9b6d8fcf
DS
7350 if ((path->peer->as)
7351 && (path->peer->as == path->peer->local_as))
d62a17ae 7352 json_object_string_add(json_path, "pathFrom",
7353 "internal");
7354 else
7355 json_object_string_add(json_path, "pathFrom",
7356 "external");
b05a1c8b 7357
d62a17ae 7358 return;
7359 }
b05a1c8b 7360
d62a17ae 7361 /* Route status display. */
9b6d8fcf 7362 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7363 vty_out(vty, "R");
9b6d8fcf 7364 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7365 vty_out(vty, "S");
9b6d8fcf 7366 else if (path->extra && path->extra->suppress)
d62a17ae 7367 vty_out(vty, "s");
9b6d8fcf
DS
7368 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7369 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7370 vty_out(vty, "*");
7371 else
7372 vty_out(vty, " ");
7373
7374 /* Selected */
9b6d8fcf 7375 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7376 vty_out(vty, "h");
9b6d8fcf 7377 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7378 vty_out(vty, "d");
9b6d8fcf 7379 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7380 vty_out(vty, ">");
9b6d8fcf 7381 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7382 vty_out(vty, "=");
7383 else
7384 vty_out(vty, " ");
718e3744 7385
d62a17ae 7386 /* Internal route. */
9b6d8fcf
DS
7387 if (path->peer && (path->peer->as)
7388 && (path->peer->as == path->peer->local_as))
d62a17ae 7389 vty_out(vty, "i");
7390 else
7391 vty_out(vty, " ");
b40d939b 7392}
7393
515c2602 7394static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
25b5da8d 7395{
515c2602
DA
7396 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)
7397 && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
25b5da8d
DA
7398 return peer->hostname;
7399 return NULL;
7400}
7401
b40d939b 7402/* called from terminal list command */
4b7e6066 7403void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7404 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7405 json_object *json_paths)
d62a17ae 7406{
515c2602 7407 struct attr *attr = path->attr;
d62a17ae 7408 json_object *json_path = NULL;
7409 json_object *json_nexthops = NULL;
7410 json_object *json_nexthop_global = NULL;
7411 json_object *json_nexthop_ll = NULL;
6f214dd3 7412 json_object *json_ext_community = NULL;
9df8b37c 7413 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7414 bool nexthop_self =
9b6d8fcf 7415 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7416 bool nexthop_othervrf = false;
43089216 7417 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7418 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
515c2602 7419 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 7420
7421 if (json_paths)
7422 json_path = json_object_new_object();
7423
7424 /* short status lead text */
9b6d8fcf 7425 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7426
7427 if (!json_paths) {
7428 /* print prefix and mask */
7429 if (!display)
9c92b5f7 7430 route_vty_out_route(p, vty, json_path);
d62a17ae 7431 else
7432 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7433 } else {
b682f6de 7434 route_vty_out_route(p, vty, json_path);
d62a17ae 7435 }
47fc97cc 7436
9df8b37c
PZ
7437 /*
7438 * If vrf id of nexthop is different from that of prefix,
7439 * set up printable string to append
7440 */
9b6d8fcf 7441 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7442 const char *self = "";
7443
7444 if (nexthop_self)
7445 self = "<";
7446
7447 nexthop_othervrf = true;
9b6d8fcf 7448 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7449
9b6d8fcf 7450 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7451 snprintf(vrf_id_str, sizeof(vrf_id_str),
7452 "@%s%s", VRFID_NONE_STR, self);
7453 else
7454 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7455 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7456
9b6d8fcf
DS
7457 if (path->extra->bgp_orig->inst_type
7458 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7459
9b6d8fcf 7460 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7461 } else {
7462 const char *self = "";
7463
7464 if (nexthop_self)
7465 self = "<";
7466
7467 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7468 }
7469
445c2480
DS
7470 /*
7471 * For ENCAP and EVPN routes, nexthop address family is not
7472 * neccessarily the same as the prefix address family.
7473 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7474 * EVPN routes are also exchanged with a MP nexthop. Currently,
7475 * this
7476 * is only IPv4, the value will be present in either
7477 * attr->nexthop or
7478 * attr->mp_nexthop_global_in
7479 */
7480 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7481 char buf[BUFSIZ];
7482 char nexthop[128];
7483 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7484
7485 switch (af) {
7486 case AF_INET:
7487 sprintf(nexthop, "%s",
a4d82a8a
PZ
7488 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7489 BUFSIZ));
445c2480
DS
7490 break;
7491 case AF_INET6:
7492 sprintf(nexthop, "%s",
a4d82a8a
PZ
7493 inet_ntop(af, &attr->mp_nexthop_global, buf,
7494 BUFSIZ));
445c2480
DS
7495 break;
7496 default:
7497 sprintf(nexthop, "?");
7498 break;
d62a17ae 7499 }
d62a17ae 7500
445c2480
DS
7501 if (json_paths) {
7502 json_nexthop_global = json_object_new_object();
7503
515c2602
DA
7504 json_object_string_add(json_nexthop_global, "ip",
7505 nexthop);
7506
7507 if (nexthop_hostname)
7508 json_object_string_add(json_nexthop_global,
7509 "hostname",
7510 nexthop_hostname);
7511
7512 json_object_string_add(json_nexthop_global, "afi",
7513 (af == AF_INET) ? "ipv4"
7514 : "ipv6");
445c2480
DS
7515 json_object_boolean_true_add(json_nexthop_global,
7516 "used");
7517 } else
25b5da8d 7518 vty_out(vty, "%s%s",
515c2602 7519 nexthop_hostname ? nexthop_hostname : nexthop,
25b5da8d 7520 vrf_id_str);
445c2480
DS
7521 } else if (safi == SAFI_EVPN) {
7522 if (json_paths) {
7523 json_nexthop_global = json_object_new_object();
7524
515c2602
DA
7525 json_object_string_add(json_nexthop_global, "ip",
7526 inet_ntoa(attr->nexthop));
7527
7528 if (nexthop_hostname)
7529 json_object_string_add(json_nexthop_global,
7530 "hostname",
7531 nexthop_hostname);
7532
a4d82a8a
PZ
7533 json_object_string_add(json_nexthop_global, "afi",
7534 "ipv4");
445c2480
DS
7535 json_object_boolean_true_add(json_nexthop_global,
7536 "used");
7537 } else
25b5da8d 7538 vty_out(vty, "%-16s%s",
515c2602
DA
7539 nexthop_hostname ? nexthop_hostname
7540 : inet_ntoa(attr->nexthop),
9df8b37c 7541 vrf_id_str);
d33fc23b 7542 } else if (safi == SAFI_FLOWSPEC) {
026b914a
PG
7543 if (attr->nexthop.s_addr != 0) {
7544 if (json_paths) {
7545 json_nexthop_global = json_object_new_object();
515c2602 7546
026b914a
PG
7547 json_object_string_add(json_nexthop_global,
7548 "afi", "ipv4");
515c2602
DA
7549 json_object_string_add(
7550 json_nexthop_global, "ip",
7551 inet_ntoa(attr->nexthop));
7552
7553 if (nexthop_hostname)
7554 json_object_string_add(
7555 json_nexthop_global, "hostname",
7556 nexthop_hostname);
7557
50e05855
AD
7558 json_object_boolean_true_add(
7559 json_nexthop_global,
026b914a
PG
7560 "used");
7561 } else {
25b5da8d 7562 vty_out(vty, "%-16s",
515c2602
DA
7563 nexthop_hostname
7564 ? nexthop_hostname
25b5da8d 7565 : inet_ntoa(attr->nexthop));
026b914a
PG
7566 }
7567 }
d33fc23b 7568 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7569 if (json_paths) {
7570 json_nexthop_global = json_object_new_object();
d62a17ae 7571
515c2602
DA
7572 json_object_string_add(json_nexthop_global, "ip",
7573 inet_ntoa(attr->nexthop));
7574
7575 if (nexthop_hostname)
7576 json_object_string_add(json_nexthop_global,
7577 "hostname",
7578 nexthop_hostname);
445c2480 7579
a4d82a8a
PZ
7580 json_object_string_add(json_nexthop_global, "afi",
7581 "ipv4");
445c2480
DS
7582 json_object_boolean_true_add(json_nexthop_global,
7583 "used");
7584 } else {
9df8b37c
PZ
7585 char buf[BUFSIZ];
7586
d87ff2dd 7587 snprintf(buf, sizeof(buf), "%s%s",
515c2602
DA
7588 nexthop_hostname ? nexthop_hostname
7589 : inet_ntoa(attr->nexthop),
25b5da8d 7590 vrf_id_str);
9df8b37c 7591 vty_out(vty, "%-16s", buf);
d62a17ae 7592 }
445c2480 7593 }
b05a1c8b 7594
445c2480 7595 /* IPv6 Next Hop */
a4d82a8a 7596 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7597 int len;
7598 char buf[BUFSIZ];
d62a17ae 7599
445c2480
DS
7600 if (json_paths) {
7601 json_nexthop_global = json_object_new_object();
a4d82a8a 7602 json_object_string_add(
515c2602
DA
7603 json_nexthop_global, "ip",
7604 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7605 buf, BUFSIZ));
7606
7607 if (nexthop_hostname)
7608 json_object_string_add(json_nexthop_global,
7609 "hostname",
7610 nexthop_hostname);
7611
a4d82a8a
PZ
7612 json_object_string_add(json_nexthop_global, "afi",
7613 "ipv6");
7614 json_object_string_add(json_nexthop_global, "scope",
7615 "global");
445c2480
DS
7616
7617 /* We display both LL & GL if both have been
7618 * received */
0606039c
DA
7619 if ((attr->mp_nexthop_len
7620 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7621 || (path->peer->conf_if)) {
a4d82a8a 7622 json_nexthop_ll = json_object_new_object();
d62a17ae 7623 json_object_string_add(
515c2602
DA
7624 json_nexthop_ll, "ip",
7625 inet_ntop(AF_INET6,
7626 &attr->mp_nexthop_local, buf,
7627 BUFSIZ));
7628
7629 if (nexthop_hostname)
7630 json_object_string_add(
7631 json_nexthop_ll, "hostname",
7632 nexthop_hostname);
7633
a4d82a8a
PZ
7634 json_object_string_add(json_nexthop_ll, "afi",
7635 "ipv6");
7636 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7637 "link-local");
d62a17ae 7638
a4d82a8a
PZ
7639 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7640 &attr->mp_nexthop_local)
445c2480
DS
7641 != 0)
7642 && !attr->mp_nexthop_prefer_global)
d62a17ae 7643 json_object_boolean_true_add(
a4d82a8a 7644 json_nexthop_ll, "used");
445c2480
DS
7645 else
7646 json_object_boolean_true_add(
a4d82a8a 7647 json_nexthop_global, "used");
445c2480
DS
7648 } else
7649 json_object_boolean_true_add(
7650 json_nexthop_global, "used");
7651 } else {
7652 /* Display LL if LL/Global both in table unless
7653 * prefer-global is set */
0606039c
DA
7654 if (((attr->mp_nexthop_len
7655 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7656 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7657 || (path->peer->conf_if)) {
7658 if (path->peer->conf_if) {
a4d82a8a 7659 len = vty_out(vty, "%s",
9b6d8fcf 7660 path->peer->conf_if);
445c2480
DS
7661 len = 16 - len; /* len of IPv6
7662 addr + max
7663 len of def
7664 ifname */
7665
7666 if (len < 1)
a4d82a8a 7667 vty_out(vty, "\n%*s", 36, " ");
445c2480 7668 else
a4d82a8a 7669 vty_out(vty, "%*s", len, " ");
d62a17ae 7670 } else {
7671 len = vty_out(
9df8b37c 7672 vty, "%s%s",
515c2602
DA
7673 nexthop_hostname
7674 ? nexthop_hostname
25b5da8d
DA
7675 : inet_ntop(
7676 AF_INET6,
7677 &attr->mp_nexthop_local,
7678 buf, BUFSIZ),
9df8b37c 7679 vrf_id_str);
d62a17ae 7680 len = 16 - len;
7681
7682 if (len < 1)
a4d82a8a 7683 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7684 else
a4d82a8a 7685 vty_out(vty, "%*s", len, " ");
d62a17ae 7686 }
445c2480 7687 } else {
a4d82a8a 7688 len = vty_out(
9df8b37c 7689 vty, "%s%s",
515c2602
DA
7690 nexthop_hostname
7691 ? nexthop_hostname
25b5da8d
DA
7692 : inet_ntop(
7693 AF_INET6,
7694 &attr->mp_nexthop_global,
7695 buf, BUFSIZ),
7696 vrf_id_str);
445c2480
DS
7697 len = 16 - len;
7698
7699 if (len < 1)
7700 vty_out(vty, "\n%*s", 36, " ");
7701 else
7702 vty_out(vty, "%*s", len, " ");
d62a17ae 7703 }
7704 }
445c2480 7705 }
718e3744 7706
445c2480
DS
7707 /* MED/Metric */
7708 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7709 if (json_paths) {
7710
7711 /*
7712 * Adding "metric" field to match with corresponding
7713 * CLI. "med" will be deprecated in future.
7714 */
a4d82a8a 7715 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7716 json_object_int_add(json_path, "metric", attr->med);
7717 } else
445c2480
DS
7718 vty_out(vty, "%10u", attr->med);
7719 else if (!json_paths)
7720 vty_out(vty, " ");
d62a17ae 7721
445c2480
DS
7722 /* Local Pref */
7723 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7724 if (json_paths) {
7725
7726 /*
7727 * Adding "locPrf" field to match with corresponding
7728 * CLI. "localPref" will be deprecated in future.
7729 */
445c2480
DS
7730 json_object_int_add(json_path, "localpref",
7731 attr->local_pref);
50e05855
AD
7732 json_object_int_add(json_path, "locPrf",
7733 attr->local_pref);
7734 } else
445c2480
DS
7735 vty_out(vty, "%7u", attr->local_pref);
7736 else if (!json_paths)
7737 vty_out(vty, " ");
d62a17ae 7738
445c2480
DS
7739 if (json_paths)
7740 json_object_int_add(json_path, "weight", attr->weight);
7741 else
7742 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7743
445c2480
DS
7744 if (json_paths) {
7745 char buf[BUFSIZ];
a4d82a8a
PZ
7746 json_object_string_add(
7747 json_path, "peerId",
9b6d8fcf 7748 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7749 }
b05a1c8b 7750
445c2480
DS
7751 /* Print aspath */
7752 if (attr->aspath) {
50e05855
AD
7753 if (json_paths) {
7754
7755 /*
7756 * Adding "path" field to match with corresponding
7757 * CLI. "aspath" will be deprecated in future.
7758 */
445c2480
DS
7759 json_object_string_add(json_path, "aspath",
7760 attr->aspath->str);
50e05855
AD
7761 json_object_string_add(json_path, "path",
7762 attr->aspath->str);
7763 } else
445c2480 7764 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7765 }
f1aa5d8a 7766
445c2480
DS
7767 /* Print origin */
7768 if (json_paths)
a4d82a8a
PZ
7769 json_object_string_add(json_path, "origin",
7770 bgp_origin_long_str[attr->origin]);
445c2480
DS
7771 else
7772 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7773
9df8b37c 7774 if (json_paths) {
6f214dd3
CS
7775 if (safi == SAFI_EVPN &&
7776 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7777 json_ext_community = json_object_new_object();
7778 json_object_string_add(json_ext_community,
7779 "string",
7780 attr->ecommunity->str);
7781 json_object_object_add(json_path,
7782 "extendedCommunity",
7783 json_ext_community);
7784 }
7785
9df8b37c
PZ
7786 if (nexthop_self)
7787 json_object_boolean_true_add(json_path,
7788 "announceNexthopSelf");
7789 if (nexthop_othervrf) {
7790 json_object_string_add(json_path, "nhVrfName",
7791 nexthop_vrfname);
7792
7793 json_object_int_add(json_path, "nhVrfId",
7794 ((nexthop_vrfid == VRF_UNKNOWN)
7795 ? -1
7796 : (int)nexthop_vrfid));
7797 }
7798 }
7799
d62a17ae 7800 if (json_paths) {
7801 if (json_nexthop_global || json_nexthop_ll) {
7802 json_nexthops = json_object_new_array();
f1aa5d8a 7803
d62a17ae 7804 if (json_nexthop_global)
7805 json_object_array_add(json_nexthops,
7806 json_nexthop_global);
f1aa5d8a 7807
d62a17ae 7808 if (json_nexthop_ll)
7809 json_object_array_add(json_nexthops,
7810 json_nexthop_ll);
f1aa5d8a 7811
d62a17ae 7812 json_object_object_add(json_path, "nexthops",
7813 json_nexthops);
7814 }
7815
7816 json_object_array_add(json_paths, json_path);
7817 } else {
7818 vty_out(vty, "\n");
6f214dd3
CS
7819
7820 if (safi == SAFI_EVPN &&
7821 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7822 vty_out(vty, "%*s", 20, " ");
7823 vty_out(vty, "%s\n", attr->ecommunity->str);
7824 }
7825
65efcfce 7826#if ENABLE_BGP_VNC
d62a17ae 7827 /* prints an additional line, indented, with VNC info, if
7828 * present */
7829 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7830 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7831#endif
d62a17ae 7832 }
7833}
718e3744 7834
7835/* called from terminal list command */
d62a17ae 7836void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7837 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7838{
7839 json_object *json_status = NULL;
7840 json_object *json_net = NULL;
7841 char buff[BUFSIZ];
dc387b0f 7842
d62a17ae 7843 /* Route status display. */
7844 if (use_json) {
7845 json_status = json_object_new_object();
7846 json_net = json_object_new_object();
7847 } else {
7848 vty_out(vty, "*");
7849 vty_out(vty, ">");
7850 vty_out(vty, " ");
7851 }
718e3744 7852
d62a17ae 7853 /* print prefix and mask */
50e05855 7854 if (use_json) {
dc387b0f
LK
7855 if (safi == SAFI_EVPN)
7856 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7857 else if (p->family == AF_INET || p->family == AF_INET6) {
7858 json_object_string_add(
7859 json_net, "addrPrefix",
7860 inet_ntop(p->family, &p->u.prefix, buff,
7861 BUFSIZ));
7862 json_object_int_add(json_net, "prefixLen",
7863 p->prefixlen);
7864 prefix2str(p, buff, PREFIX_STRLEN);
7865 json_object_string_add(json_net, "network", buff);
7866 }
50e05855 7867 } else
9c92b5f7 7868 route_vty_out_route(p, vty, NULL);
d62a17ae 7869
7870 /* Print attribute */
7871 if (attr) {
7872 if (use_json) {
7873 if (p->family == AF_INET
7874 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7875 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7876 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7877 json_object_string_add(
7878 json_net, "nextHop",
7879 inet_ntoa(
7880 attr->mp_nexthop_global_in));
7881 else
7882 json_object_string_add(
7883 json_net, "nextHop",
7884 inet_ntoa(attr->nexthop));
7885 } else if (p->family == AF_INET6
7886 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7887 char buf[BUFSIZ];
7888
7889 json_object_string_add(
aa0a10fc 7890 json_net, "nextHopGlobal",
d62a17ae 7891 inet_ntop(AF_INET6,
7892 &attr->mp_nexthop_global, buf,
7893 BUFSIZ));
dc387b0f
LK
7894 } else if (p->family == AF_EVPN &&
7895 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7896 json_object_string_add(json_net,
7897 "nextHop", inet_ntoa(
7898 attr->mp_nexthop_global_in));
d62a17ae 7899
7900 if (attr->flag
7901 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7902 json_object_int_add(json_net, "metric",
7903 attr->med);
7904
50e05855
AD
7905 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7906
7907 /*
7908 * Adding "locPrf" field to match with
7909 * corresponding CLI. "localPref" will be
7910 * deprecated in future.
7911 */
d62a17ae 7912 json_object_int_add(json_net, "localPref",
7913 attr->local_pref);
50e05855
AD
7914 json_object_int_add(json_net, "locPrf",
7915 attr->local_pref);
7916 }
d62a17ae 7917
7918 json_object_int_add(json_net, "weight", attr->weight);
7919
7920 /* Print aspath */
50e05855
AD
7921 if (attr->aspath) {
7922
7923 /*
7924 * Adding "path" field to match with
7925 * corresponding CLI. "localPref" will be
7926 * deprecated in future.
7927 */
d62a17ae 7928 json_object_string_add(json_net, "asPath",
7929 attr->aspath->str);
50e05855
AD
7930 json_object_string_add(json_net, "path",
7931 attr->aspath->str);
7932 }
d62a17ae 7933
7934 /* Print origin */
7935 json_object_string_add(json_net, "bgpOriginCode",
7936 bgp_origin_str[attr->origin]);
7937 } else {
7938 if (p->family == AF_INET
7939 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7940 || safi == SAFI_EVPN
7941 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7942 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7943 || safi == SAFI_EVPN)
7944 vty_out(vty, "%-16s",
7945 inet_ntoa(
7946 attr->mp_nexthop_global_in));
7947 else
7948 vty_out(vty, "%-16s",
7949 inet_ntoa(attr->nexthop));
7950 } else if (p->family == AF_INET6
7951 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7952 int len;
7953 char buf[BUFSIZ];
7954
7955 len = vty_out(
7956 vty, "%s",
7957 inet_ntop(AF_INET6,
7958 &attr->mp_nexthop_global, buf,
7959 BUFSIZ));
7960 len = 16 - len;
7961 if (len < 1)
7962 vty_out(vty, "\n%*s", 36, " ");
7963 else
7964 vty_out(vty, "%*s", len, " ");
7965 }
7966 if (attr->flag
7967 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7968 vty_out(vty, "%10u", attr->med);
7969 else
7970 vty_out(vty, " ");
718e3744 7971
d62a17ae 7972 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
7973 vty_out(vty, "%7u", attr->local_pref);
7974 else
7975 vty_out(vty, " ");
7976
7977 vty_out(vty, "%7u ", attr->weight);
7978
7979 /* Print aspath */
7980 if (attr->aspath)
7981 aspath_print_vty(vty, "%s", attr->aspath, " ");
7982
7983 /* Print origin */
7984 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7985 }
7986 }
7987 if (use_json) {
7988 json_object_boolean_true_add(json_status, "*");
7989 json_object_boolean_true_add(json_status, ">");
7990 json_object_object_add(json_net, "appliedStatusSymbols",
7991 json_status);
1608ff77 7992
dc387b0f
LK
7993 prefix2str(p, buff, PREFIX_STRLEN);
7994 json_object_object_add(json_ar, buff, json_net);
d62a17ae 7995 } else
7996 vty_out(vty, "\n");
7997}
7998
7999void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 8000 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8001 json_object *json)
8002{
8003 json_object *json_out = NULL;
8004 struct attr *attr;
8005 mpls_label_t label = MPLS_INVALID_LABEL;
8006
9b6d8fcf 8007 if (!path->extra)
d62a17ae 8008 return;
8009
8010 if (json)
8011 json_out = json_object_new_object();
8012
8013 /* short status lead text */
9b6d8fcf 8014 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8015
8016 /* print prefix and mask */
8017 if (json == NULL) {
8018 if (!display)
9c92b5f7 8019 route_vty_out_route(p, vty, NULL);
d62a17ae 8020 else
8021 vty_out(vty, "%*s", 17, " ");
8022 }
8023
8024 /* Print attribute */
9b6d8fcf 8025 attr = path->attr;
05864da7
DS
8026 if (((p->family == AF_INET)
8027 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8028 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8029 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8030 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8031 || safi == SAFI_EVPN) {
8032 if (json)
8033 json_object_string_add(
8034 json_out, "mpNexthopGlobalIn",
8035 inet_ntoa(attr->mp_nexthop_global_in));
8036 else
8037 vty_out(vty, "%-16s",
8038 inet_ntoa(attr->mp_nexthop_global_in));
8039 } else {
8040 if (json)
8041 json_object_string_add(
8042 json_out, "nexthop",
8043 inet_ntoa(attr->nexthop));
8044 else
8045 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8046 }
8047 } else if (((p->family == AF_INET6)
8048 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8049 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8050 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8051 char buf_a[512];
8052
8053 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8054 if (json)
8055 json_object_string_add(
8056 json_out, "mpNexthopGlobalIn",
8057 inet_ntop(AF_INET6,
8058 &attr->mp_nexthop_global,
8059 buf_a, sizeof(buf_a)));
8060 else
8061 vty_out(vty, "%s",
8062 inet_ntop(AF_INET6,
8063 &attr->mp_nexthop_global,
8064 buf_a, sizeof(buf_a)));
8065 } else if (attr->mp_nexthop_len
8066 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8067 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8068 &attr->mp_nexthop_global,
8069 &attr->mp_nexthop_local);
8070 if (json)
8071 json_object_string_add(json_out,
8072 "mpNexthopGlobalLocal",
8073 buf_a);
8074 else
8075 vty_out(vty, "%s", buf_a);
d62a17ae 8076 }
8077 }
8078
9b6d8fcf 8079 label = decode_label(&path->extra->label[0]);
d62a17ae 8080
8081 if (bgp_is_valid_label(&label)) {
8082 if (json) {
8083 json_object_int_add(json_out, "notag", label);
8084 json_object_array_add(json, json_out);
8085 } else {
8086 vty_out(vty, "notag/%d", label);
8087 vty_out(vty, "\n");
8088 }
8089 }
8090}
718e3744 8091
d62a17ae 8092void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 8093 struct bgp_path_info *path, int display,
d62a17ae 8094 json_object *json_paths)
718e3744 8095{
d62a17ae 8096 struct attr *attr;
14f51eba 8097 char buf[BUFSIZ] = {0};
d62a17ae 8098 json_object *json_path = NULL;
14f51eba
LK
8099 json_object *json_nexthop = NULL;
8100 json_object *json_overlay = NULL;
856ca177 8101
9b6d8fcf 8102 if (!path->extra)
d62a17ae 8103 return;
718e3744 8104
14f51eba
LK
8105 if (json_paths) {
8106 json_path = json_object_new_object();
8107 json_overlay = json_object_new_object();
8108 json_nexthop = json_object_new_object();
8109 }
8110
d62a17ae 8111 /* short status lead text */
9b6d8fcf 8112 route_vty_short_status_out(vty, path, json_path);
856ca177 8113
d62a17ae 8114 /* print prefix and mask */
8115 if (!display)
14f51eba 8116 route_vty_out_route(p, vty, json_path);
d62a17ae 8117 else
8118 vty_out(vty, "%*s", 17, " ");
8119
8120 /* Print attribute */
9b6d8fcf 8121 attr = path->attr;
05864da7
DS
8122 char buf1[BUFSIZ];
8123 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8124
05864da7
DS
8125 switch (af) {
8126 case AF_INET:
8127 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8128 if (!json_path) {
8129 vty_out(vty, "%-16s", buf);
8130 } else {
8131 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8132
05864da7 8133 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8134
05864da7
DS
8135 json_object_object_add(json_path, "nexthop",
8136 json_nexthop);
8137 }
8138 break;
8139 case AF_INET6:
8140 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8141 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8142 if (!json_path) {
8143 vty_out(vty, "%s(%s)", buf, buf1);
8144 } else {
8145 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8146
05864da7
DS
8147 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8148 buf1);
14f51eba 8149
05864da7 8150 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8151
05864da7
DS
8152 json_object_object_add(json_path, "nexthop",
8153 json_nexthop);
8154 }
8155 break;
8156 default:
8157 if (!json_path) {
8158 vty_out(vty, "?");
8159 } else {
8160 json_object_string_add(json_nexthop, "Error",
8161 "Unsupported address-family");
d62a17ae 8162 }
05864da7 8163 }
988258b4 8164
05864da7 8165 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8166
05864da7
DS
8167 if (!json_path)
8168 vty_out(vty, "%s", str);
8169 else
8170 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8171
05864da7 8172 XFREE(MTYPE_TMP, str);
988258b4 8173
05864da7
DS
8174 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8175 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8176 BUFSIZ);
8177 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8178 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8179 BUFSIZ);
8180 }
14f51eba 8181
05864da7
DS
8182 if (!json_path)
8183 vty_out(vty, "/%s", buf);
8184 else
8185 json_object_string_add(json_overlay, "gw", buf);
8186
8187 if (attr->ecommunity) {
8188 char *mac = NULL;
8189 struct ecommunity_val *routermac = ecommunity_lookup(
8190 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8191 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8192
8193 if (routermac)
8194 mac = ecom_mac2str((char *)routermac->val);
8195 if (mac) {
8196 if (!json_path) {
8197 vty_out(vty, "/%s", (char *)mac);
8198 } else {
8199 json_object_string_add(json_overlay, "rmac",
8200 mac);
988258b4 8201 }
05864da7 8202 XFREE(MTYPE_TMP, mac);
988258b4 8203 }
05864da7 8204 }
718e3744 8205
05864da7
DS
8206 if (!json_path) {
8207 vty_out(vty, "\n");
8208 } else {
8209 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8210
05864da7 8211 json_object_array_add(json_paths, json_path);
14f51eba 8212 }
d62a17ae 8213}
718e3744 8214
d62a17ae 8215/* dampening route */
8216static void damp_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8217 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8218 safi_t safi, bool use_json, json_object *json)
d62a17ae 8219{
8220 struct attr *attr;
8221 int len;
8222 char timebuf[BGP_UPTIME_LEN];
8223
8224 /* short status lead text */
9b6d8fcf 8225 route_vty_short_status_out(vty, path, json);
d62a17ae 8226
8227 /* print prefix and mask */
8228 if (!use_json) {
8229 if (!display)
9c92b5f7 8230 route_vty_out_route(p, vty, NULL);
d62a17ae 8231 else
8232 vty_out(vty, "%*s", 17, " ");
8233 }
8234
9b6d8fcf 8235 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8236 len = 17 - len;
8237 if (len < 1) {
8238 if (!use_json)
8239 vty_out(vty, "\n%*s", 34, " ");
8240 } else {
8241 if (use_json)
8242 json_object_int_add(json, "peerHost", len);
8243 else
8244 vty_out(vty, "%*s", len, " ");
8245 }
8246
8247 if (use_json)
a935f597
DA
8248 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8249 safi, use_json, json);
d62a17ae 8250 else
9b6d8fcf
DS
8251 vty_out(vty, "%s ",
8252 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8253 BGP_UPTIME_LEN, afi, safi,
8254 use_json, json));
d62a17ae 8255
8256 /* Print attribute */
9b6d8fcf 8257 attr = path->attr;
d62a17ae 8258
05864da7
DS
8259 /* Print aspath */
8260 if (attr->aspath) {
d62a17ae 8261 if (use_json)
05864da7
DS
8262 json_object_string_add(json, "asPath",
8263 attr->aspath->str);
d62a17ae 8264 else
05864da7 8265 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8266 }
05864da7
DS
8267
8268 /* Print origin */
8269 if (use_json)
8270 json_object_string_add(json, "origin",
8271 bgp_origin_str[attr->origin]);
8272 else
8273 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8274
d62a17ae 8275 if (!use_json)
8276 vty_out(vty, "\n");
8277}
718e3744 8278
d62a17ae 8279/* flap route */
8280static void flap_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8281 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8282 safi_t safi, bool use_json, json_object *json)
784d3a42 8283{
d62a17ae 8284 struct attr *attr;
8285 struct bgp_damp_info *bdi;
8286 char timebuf[BGP_UPTIME_LEN];
8287 int len;
784d3a42 8288
9b6d8fcf 8289 if (!path->extra)
d62a17ae 8290 return;
784d3a42 8291
9b6d8fcf 8292 bdi = path->extra->damp_info;
784d3a42 8293
d62a17ae 8294 /* short status lead text */
9b6d8fcf 8295 route_vty_short_status_out(vty, path, json);
784d3a42 8296
d62a17ae 8297 /* print prefix and mask */
8298 if (!use_json) {
8299 if (!display)
9c92b5f7 8300 route_vty_out_route(p, vty, NULL);
d62a17ae 8301 else
8302 vty_out(vty, "%*s", 17, " ");
8303 }
784d3a42 8304
9b6d8fcf 8305 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8306 len = 16 - len;
8307 if (len < 1) {
8308 if (!use_json)
8309 vty_out(vty, "\n%*s", 33, " ");
8310 } else {
8311 if (use_json)
8312 json_object_int_add(json, "peerHost", len);
8313 else
8314 vty_out(vty, "%*s", len, " ");
8315 }
784d3a42 8316
d62a17ae 8317 len = vty_out(vty, "%d", bdi->flap);
8318 len = 5 - len;
8319 if (len < 1) {
8320 if (!use_json)
8321 vty_out(vty, " ");
8322 } else {
8323 if (use_json)
8324 json_object_int_add(json, "bdiFlap", len);
8325 else
8326 vty_out(vty, "%*s", len, " ");
8327 }
8328
8329 if (use_json)
8330 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8331 json);
8332 else
996c9314
LB
8333 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8334 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8335
9b6d8fcf
DS
8336 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8337 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8338 if (use_json)
9b6d8fcf 8339 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8340 BGP_UPTIME_LEN, afi, safi,
8341 use_json, json);
d62a17ae 8342 else
8343 vty_out(vty, "%s ",
9b6d8fcf 8344 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8345 BGP_UPTIME_LEN, afi,
8346 safi, use_json, json));
d62a17ae 8347 } else {
8348 if (!use_json)
8349 vty_out(vty, "%*s ", 8, " ");
8350 }
8351
8352 /* Print attribute */
9b6d8fcf 8353 attr = path->attr;
d62a17ae 8354
05864da7
DS
8355 /* Print aspath */
8356 if (attr->aspath) {
d62a17ae 8357 if (use_json)
05864da7
DS
8358 json_object_string_add(json, "asPath",
8359 attr->aspath->str);
d62a17ae 8360 else
05864da7 8361 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8362 }
05864da7
DS
8363
8364 /* Print origin */
8365 if (use_json)
8366 json_object_string_add(json, "origin",
8367 bgp_origin_str[attr->origin]);
8368 else
8369 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8370
d62a17ae 8371 if (!use_json)
8372 vty_out(vty, "\n");
8373}
8374
8375static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8376 int *first, const char *header,
8377 json_object *json_adv_to)
8378{
8379 char buf1[INET6_ADDRSTRLEN];
8380 json_object *json_peer = NULL;
8381
8382 if (json_adv_to) {
8383 /* 'advertised-to' is a dictionary of peers we have advertised
8384 * this
8385 * prefix too. The key is the peer's IP or swpX, the value is
8386 * the
8387 * hostname if we know it and "" if not.
8388 */
8389 json_peer = json_object_new_object();
8390
8391 if (peer->hostname)
8392 json_object_string_add(json_peer, "hostname",
8393 peer->hostname);
8394
8395 if (peer->conf_if)
8396 json_object_object_add(json_adv_to, peer->conf_if,
8397 json_peer);
8398 else
8399 json_object_object_add(
8400 json_adv_to,
8401 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8402 json_peer);
8403 } else {
8404 if (*first) {
8405 vty_out(vty, "%s", header);
8406 *first = 0;
8407 }
8408
8409 if (peer->hostname
8410 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
8411 if (peer->conf_if)
8412 vty_out(vty, " %s(%s)", peer->hostname,
8413 peer->conf_if);
8414 else
8415 vty_out(vty, " %s(%s)", peer->hostname,
8416 sockunion2str(&peer->su, buf1,
8417 SU_ADDRSTRLEN));
8418 } else {
8419 if (peer->conf_if)
8420 vty_out(vty, " %s", peer->conf_if);
8421 else
8422 vty_out(vty, " %s",
8423 sockunion2str(&peer->su, buf1,
8424 SU_ADDRSTRLEN));
8425 }
8426 }
784d3a42
PG
8427}
8428
dcc68b5e
MS
8429static void route_vty_out_tx_ids(struct vty *vty,
8430 struct bgp_addpath_info_data *d)
8431{
8432 int i;
8433
8434 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8435 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8436 d->addpath_tx_id[i],
8437 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8438 }
8439}
8440
0dc8ee70
DS
8441static const char *bgp_path_selection_reason2str(
8442 enum bgp_path_selection_reason reason)
8443{
8444 switch (reason) {
8445 case bgp_path_selection_none:
8446 return "Nothing to Select";
8447 break;
8448 case bgp_path_selection_first:
8449 return "First path received";
8450 break;
8451 case bgp_path_selection_evpn_sticky_mac:
8452 return "EVPN Sticky Mac";
8453 break;
8454 case bgp_path_selection_evpn_seq:
8455 return "EVPN sequence number";
8456 break;
8457 case bgp_path_selection_evpn_lower_ip:
8458 return "EVPN lower IP";
8459 break;
8460 case bgp_path_selection_weight:
8461 return "Weight";
8462 break;
8463 case bgp_path_selection_local_pref:
8464 return "Local Pref";
8465 break;
8466 case bgp_path_selection_local_route:
8467 return "Local Route";
8468 break;
8469 case bgp_path_selection_confed_as_path:
8470 return "Confederation based AS Path";
8471 break;
8472 case bgp_path_selection_as_path:
8473 return "AS Path";
8474 break;
8475 case bgp_path_selection_origin:
8476 return "Origin";
8477 break;
8478 case bgp_path_selection_med:
8479 return "MED";
8480 break;
8481 case bgp_path_selection_peer:
8482 return "Peer Type";
8483 break;
8484 case bgp_path_selection_confed:
8485 return "Confed Peer Type";
8486 break;
8487 case bgp_path_selection_igp_metric:
8488 return "IGP Metric";
8489 break;
8490 case bgp_path_selection_older:
8491 return "Older Path";
8492 break;
8493 case bgp_path_selection_router_id:
8494 return "Router ID";
8495 break;
8496 case bgp_path_selection_cluster_length:
8497 return "Cluser length";
8498 break;
8499 case bgp_path_selection_stale:
8500 return "Path Staleness";
8501 break;
8502 case bgp_path_selection_local_configured:
8503 return "Locally configured route";
8504 break;
8505 case bgp_path_selection_neighbor_ip:
8506 return "Neighbor IP";
8507 break;
8508 case bgp_path_selection_default:
8509 return "Nothing left to compare";
8510 break;
8511 }
a74879b2 8512 return "Invalid (internal error)";
0dc8ee70
DS
8513}
8514
f08b5ca0
DS
8515void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8516 struct bgp_node *bn, struct bgp_path_info *path,
8517 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8518{
8519 char buf[INET6_ADDRSTRLEN];
8520 char buf1[BUFSIZ];
d62a17ae 8521 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8522 struct attr *attr = path->attr;
d62a17ae 8523 int sockunion_vty_out(struct vty *, union sockunion *);
8524 time_t tbuf;
8525 json_object *json_bestpath = NULL;
8526 json_object *json_cluster_list = NULL;
8527 json_object *json_cluster_list_list = NULL;
8528 json_object *json_ext_community = NULL;
8529 json_object *json_last_update = NULL;
7fd077aa 8530 json_object *json_pmsi = NULL;
d62a17ae 8531 json_object *json_nexthop_global = NULL;
8532 json_object *json_nexthop_ll = NULL;
8533 json_object *json_nexthops = NULL;
8534 json_object *json_path = NULL;
8535 json_object *json_peer = NULL;
8536 json_object *json_string = NULL;
8537 json_object *json_adv_to = NULL;
8538 int first = 0;
8539 struct listnode *node, *nnode;
8540 struct peer *peer;
8541 int addpath_capable;
8542 int has_adj;
8543 unsigned int first_as;
1defdda8 8544 bool nexthop_self =
9b6d8fcf 8545 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8546 int i;
515c2602 8547 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 8548
8549 if (json_paths) {
8550 json_path = json_object_new_object();
8551 json_peer = json_object_new_object();
8552 json_nexthop_global = json_object_new_object();
8553 }
8554
44c69747 8555 if (path->extra) {
b57ba6d2 8556 char tag_buf[30];
d62a17ae 8557
d7325ee7 8558 buf2[0] = '\0';
d62a17ae 8559 tag_buf[0] = '\0';
9b6d8fcf
DS
8560 if (path->extra && path->extra->num_labels) {
8561 bgp_evpn_label2str(path->extra->label,
8562 path->extra->num_labels, tag_buf,
a4d82a8a 8563 sizeof(tag_buf));
d62a17ae 8564 }
d7325ee7 8565 if (safi == SAFI_EVPN) {
44c69747
LK
8566 if (!json_paths) {
8567 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8568 buf2, sizeof(buf2));
8569 vty_out(vty, " Route %s", buf2);
8570 if (tag_buf[0] != '\0')
8571 vty_out(vty, " VNI %s", tag_buf);
8572 vty_out(vty, "\n");
8573 } else {
8574 if (tag_buf[0])
8575 json_object_string_add(json_path, "VNI",
8576 tag_buf);
8577 }
d7325ee7
DD
8578 }
8579
44c69747 8580 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8581 struct bgp_path_info *parent_ri;
d62a17ae 8582 struct bgp_node *rn, *prn;
8583
9b6d8fcf 8584 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8585 rn = parent_ri->net;
8586 if (rn && rn->prn) {
8587 prn = rn->prn;
d7325ee7
DD
8588 prefix_rd2str((struct prefix_rd *)&prn->p,
8589 buf1, sizeof(buf1));
8590 if (is_pi_family_evpn(parent_ri)) {
8591 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8592 buf2, sizeof(buf2));
8593 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8594 } else
8595 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8596 }
8597 }
8598 }
d62a17ae 8599
05864da7
DS
8600 /* Line1 display AS-path, Aggregator */
8601 if (attr->aspath) {
8602 if (json_paths) {
8603 if (!attr->aspath->json)
8604 aspath_str_update(attr->aspath, true);
8605 json_object_lock(attr->aspath->json);
8606 json_object_object_add(json_path, "aspath",
8607 attr->aspath->json);
8608 } else {
8609 if (attr->aspath->segments)
8610 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8611 else
05864da7 8612 vty_out(vty, " Local");
d62a17ae 8613 }
05864da7 8614 }
d62a17ae 8615
05864da7
DS
8616 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8617 if (json_paths)
8618 json_object_boolean_true_add(json_path, "removed");
8619 else
8620 vty_out(vty, ", (removed)");
8621 }
d62a17ae 8622
05864da7
DS
8623 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8624 if (json_paths)
8625 json_object_boolean_true_add(json_path, "stale");
8626 else
8627 vty_out(vty, ", (stale)");
8628 }
d62a17ae 8629
05864da7
DS
8630 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8631 if (json_paths) {
8632 json_object_int_add(json_path, "aggregatorAs",
8633 attr->aggregator_as);
8634 json_object_string_add(
8635 json_path, "aggregatorId",
8636 inet_ntoa(attr->aggregator_addr));
8637 } else {
8638 vty_out(vty, ", (aggregated by %u %s)",
8639 attr->aggregator_as,
8640 inet_ntoa(attr->aggregator_addr));
d62a17ae 8641 }
05864da7 8642 }
d62a17ae 8643
05864da7
DS
8644 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8645 PEER_FLAG_REFLECTOR_CLIENT)) {
8646 if (json_paths)
8647 json_object_boolean_true_add(json_path,
8648 "rxedFromRrClient");
8649 else
8650 vty_out(vty, ", (Received from a RR-client)");
8651 }
d62a17ae 8652
05864da7
DS
8653 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8654 PEER_FLAG_RSERVER_CLIENT)) {
8655 if (json_paths)
8656 json_object_boolean_true_add(json_path,
8657 "rxedFromRsClient");
8658 else
8659 vty_out(vty, ", (Received from a RS-client)");
8660 }
d62a17ae 8661
05864da7
DS
8662 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8663 if (json_paths)
8664 json_object_boolean_true_add(json_path,
8665 "dampeningHistoryEntry");
8666 else
8667 vty_out(vty, ", (history entry)");
8668 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8669 if (json_paths)
8670 json_object_boolean_true_add(json_path,
8671 "dampeningSuppressed");
8672 else
8673 vty_out(vty, ", (suppressed due to dampening)");
8674 }
d62a17ae 8675
05864da7
DS
8676 if (!json_paths)
8677 vty_out(vty, "\n");
d62a17ae 8678
05864da7
DS
8679 /* Line2 display Next-hop, Neighbor, Router-id */
8680 /* Display the nexthop */
8681 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8682 || bn->p.family == AF_EVPN)
8683 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8684 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8685 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8686 || safi == SAFI_EVPN) {
515c2602 8687 if (json_paths) {
d62a17ae 8688 json_object_string_add(
515c2602
DA
8689 json_nexthop_global, "ip",
8690 inet_ntoa(attr->mp_nexthop_global_in));
8691
8692 if (nexthop_hostname)
8693 json_object_string_add(
8694 json_nexthop_global, "hostname",
8695 nexthop_hostname);
8696 } else
d62a17ae 8697 vty_out(vty, " %s",
515c2602
DA
8698 nexthop_hostname
8699 ? nexthop_hostname
05864da7 8700 : inet_ntoa(
515c2602 8701 attr->mp_nexthop_global_in));
d62a17ae 8702 } else {
515c2602 8703 if (json_paths) {
05864da7 8704 json_object_string_add(
515c2602
DA
8705 json_nexthop_global, "ip",
8706 inet_ntoa(attr->nexthop));
8707
8708 if (nexthop_hostname)
8709 json_object_string_add(
8710 json_nexthop_global, "hostname",
8711 nexthop_hostname);
8712 } else
05864da7 8713 vty_out(vty, " %s",
515c2602
DA
8714 nexthop_hostname
8715 ? nexthop_hostname
05864da7 8716 : inet_ntoa(attr->nexthop));
d62a17ae 8717 }
8718
05864da7
DS
8719 if (json_paths)
8720 json_object_string_add(json_nexthop_global, "afi",
8721 "ipv4");
8722 } else {
8723 if (json_paths) {
8724 json_object_string_add(
515c2602
DA
8725 json_nexthop_global, "ip",
8726 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8727 buf, INET6_ADDRSTRLEN));
8728
8729 if (nexthop_hostname)
8730 json_object_string_add(json_nexthop_global,
8731 "hostname",
8732 nexthop_hostname);
8733
05864da7
DS
8734 json_object_string_add(json_nexthop_global, "afi",
8735 "ipv6");
8736 json_object_string_add(json_nexthop_global, "scope",
8737 "global");
8738 } else {
8739 vty_out(vty, " %s",
515c2602
DA
8740 nexthop_hostname
8741 ? nexthop_hostname
05864da7
DS
8742 : inet_ntop(AF_INET6,
8743 &attr->mp_nexthop_global,
8744 buf, INET6_ADDRSTRLEN));
d62a17ae 8745 }
05864da7 8746 }
d62a17ae 8747
05864da7
DS
8748 /* Display the IGP cost or 'inaccessible' */
8749 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8750 if (json_paths)
8751 json_object_boolean_false_add(json_nexthop_global,
8752 "accessible");
8753 else
8754 vty_out(vty, " (inaccessible)");
8755 } else {
8756 if (path->extra && path->extra->igpmetric) {
d62a17ae 8757 if (json_paths)
05864da7
DS
8758 json_object_int_add(json_nexthop_global,
8759 "metric",
8760 path->extra->igpmetric);
d62a17ae 8761 else
05864da7
DS
8762 vty_out(vty, " (metric %u)",
8763 path->extra->igpmetric);
d62a17ae 8764 }
8765
05864da7 8766 /* IGP cost is 0, display this only for json */
d62a17ae 8767 else {
d62a17ae 8768 if (json_paths)
05864da7
DS
8769 json_object_int_add(json_nexthop_global,
8770 "metric", 0);
d62a17ae 8771 }
d62a17ae 8772
05864da7
DS
8773 if (json_paths)
8774 json_object_boolean_true_add(json_nexthop_global,
8775 "accessible");
8776 }
d62a17ae 8777
05864da7
DS
8778 /* Display peer "from" output */
8779 /* This path was originated locally */
8780 if (path->peer == bgp->peer_self) {
d62a17ae 8781
05864da7
DS
8782 if (safi == SAFI_EVPN
8783 || (bn->p.family == AF_INET
8784 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8785 if (json_paths)
05864da7
DS
8786 json_object_string_add(json_peer, "peerId",
8787 "0.0.0.0");
d62a17ae 8788 else
05864da7
DS
8789 vty_out(vty, " from 0.0.0.0 ");
8790 } else {
d62a17ae 8791 if (json_paths)
05864da7
DS
8792 json_object_string_add(json_peer, "peerId",
8793 "::");
d62a17ae 8794 else
05864da7 8795 vty_out(vty, " from :: ");
d62a17ae 8796 }
d62a17ae 8797
05864da7
DS
8798 if (json_paths)
8799 json_object_string_add(json_peer, "routerId",
8800 inet_ntoa(bgp->router_id));
8801 else
8802 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8803 }
d62a17ae 8804
05864da7
DS
8805 /* We RXed this path from one of our peers */
8806 else {
8807
8808 if (json_paths) {
8809 json_object_string_add(json_peer, "peerId",
8810 sockunion2str(&path->peer->su,
8811 buf,
8812 SU_ADDRSTRLEN));
8813 json_object_string_add(json_peer, "routerId",
8814 inet_ntop(AF_INET,
8815 &path->peer->remote_id,
8816 buf1, sizeof(buf1)));
8817
8818 if (path->peer->hostname)
8819 json_object_string_add(json_peer, "hostname",
8820 path->peer->hostname);
8821
8822 if (path->peer->domainname)
8823 json_object_string_add(json_peer, "domainname",
8824 path->peer->domainname);
8825
8826 if (path->peer->conf_if)
8827 json_object_string_add(json_peer, "interface",
8828 path->peer->conf_if);
8829 } else {
8830 if (path->peer->conf_if) {
8831 if (path->peer->hostname
8832 && bgp_flag_check(path->peer->bgp,
8833 BGP_FLAG_SHOW_HOSTNAME))
8834 vty_out(vty, " from %s(%s)",
8835 path->peer->hostname,
8836 path->peer->conf_if);
d62a17ae 8837 else
05864da7 8838 vty_out(vty, " from %s",
9b6d8fcf 8839 path->peer->conf_if);
d62a17ae 8840 } else {
05864da7
DS
8841 if (path->peer->hostname
8842 && bgp_flag_check(path->peer->bgp,
8843 BGP_FLAG_SHOW_HOSTNAME))
8844 vty_out(vty, " from %s(%s)",
8845 path->peer->hostname,
8846 path->peer->host);
d62a17ae 8847 else
05864da7
DS
8848 vty_out(vty, " from %s",
8849 sockunion2str(&path->peer->su,
8850 buf,
8851 SU_ADDRSTRLEN));
d62a17ae 8852 }
d62a17ae 8853
05864da7
DS
8854 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8855 vty_out(vty, " (%s)",
8856 inet_ntoa(attr->originator_id));
8857 else
8858 vty_out(vty, " (%s)",
8859 inet_ntop(AF_INET,
8860 &path->peer->remote_id, buf1,
8861 sizeof(buf1)));
d62a17ae 8862 }
05864da7 8863 }
9df8b37c 8864
05864da7
DS
8865 /*
8866 * Note when vrfid of nexthop is different from that of prefix
8867 */
8868 if (path->extra && path->extra->bgp_orig) {
8869 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8870
05864da7
DS
8871 if (json_paths) {
8872 const char *vn;
9df8b37c 8873
05864da7
DS
8874 if (path->extra->bgp_orig->inst_type
8875 == BGP_INSTANCE_TYPE_DEFAULT)
8876 vn = VRF_DEFAULT_NAME;
8877 else
8878 vn = path->extra->bgp_orig->name;
9df8b37c 8879
05864da7 8880 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8881
05864da7
DS
8882 if (nexthop_vrfid == VRF_UNKNOWN) {
8883 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8884 } else {
05864da7
DS
8885 json_object_int_add(json_path, "nhVrfId",
8886 (int)nexthop_vrfid);
9df8b37c 8887 }
05864da7
DS
8888 } else {
8889 if (nexthop_vrfid == VRF_UNKNOWN)
8890 vty_out(vty, " vrf ?");
d62a17ae 8891 else
05864da7 8892 vty_out(vty, " vrf %u", nexthop_vrfid);
9df8b37c 8893 }
05864da7 8894 }
9df8b37c 8895
05864da7
DS
8896 if (nexthop_self) {
8897 if (json_paths) {
8898 json_object_boolean_true_add(json_path,
8899 "announceNexthopSelf");
8900 } else {
8901 vty_out(vty, " announce-nh-self");
9df8b37c 8902 }
05864da7 8903 }
9df8b37c 8904
05864da7
DS
8905 if (!json_paths)
8906 vty_out(vty, "\n");
d62a17ae 8907
05864da7
DS
8908 /* display the link-local nexthop */
8909 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8910 if (json_paths) {
8911 json_nexthop_ll = json_object_new_object();
8912 json_object_string_add(
515c2602
DA
8913 json_nexthop_ll, "ip",
8914 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8915 buf, INET6_ADDRSTRLEN));
8916
8917 if (nexthop_hostname)
8918 json_object_string_add(json_nexthop_ll,
8919 "hostname",
8920 nexthop_hostname);
8921
05864da7
DS
8922 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8923 json_object_string_add(json_nexthop_ll, "scope",
8924 "link-local");
d62a17ae 8925
05864da7
DS
8926 json_object_boolean_true_add(json_nexthop_ll,
8927 "accessible");
d62a17ae 8928
05864da7 8929 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8930 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8931 "used");
8932 else
8933 json_object_boolean_true_add(
8934 json_nexthop_global, "used");
8935 } else {
8936 vty_out(vty, " (%s) %s\n",
8937 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8938 buf, INET6_ADDRSTRLEN),
8939 attr->mp_nexthop_prefer_global
8940 ? "(prefer-global)"
8941 : "(used)");
d62a17ae 8942 }
05864da7
DS
8943 }
8944 /* If we do not have a link-local nexthop then we must flag the
8945 global as "used" */
8946 else {
8947 if (json_paths)
8948 json_object_boolean_true_add(json_nexthop_global,
8949 "used");
8950 }
d62a17ae 8951
05864da7
DS
8952 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8953 * Int/Ext/Local, Atomic, best */
8954 if (json_paths)
8955 json_object_string_add(json_path, "origin",
8956 bgp_origin_long_str[attr->origin]);
8957 else
8958 vty_out(vty, " Origin %s",
8959 bgp_origin_long_str[attr->origin]);
9df8b37c 8960
05864da7
DS
8961 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
8962 if (json_paths) {
8963 /*
8964 * Adding "metric" field to match with
8965 * corresponding CLI. "med" will be
8966 * deprecated in future.
8967 */
8968 json_object_int_add(json_path, "med", attr->med);
8969 json_object_int_add(json_path, "metric", attr->med);
8970 } else
8971 vty_out(vty, ", metric %u", attr->med);
8972 }
9df8b37c 8973
05864da7
DS
8974 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
8975 if (json_paths)
8976 json_object_int_add(json_path, "localpref",
8977 attr->local_pref);
8978 else
8979 vty_out(vty, ", localpref %u", attr->local_pref);
8980 }
9df8b37c 8981
05864da7
DS
8982 if (attr->weight != 0) {
8983 if (json_paths)
8984 json_object_int_add(json_path, "weight", attr->weight);
8985 else
8986 vty_out(vty, ", weight %u", attr->weight);
8987 }
9df8b37c 8988
05864da7
DS
8989 if (attr->tag != 0) {
8990 if (json_paths)
8991 json_object_int_add(json_path, "tag", attr->tag);
8992 else
8993 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
8994 }
9df8b37c 8995
05864da7
DS
8996 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8997 if (json_paths)
8998 json_object_boolean_false_add(json_path, "valid");
8999 else
9000 vty_out(vty, ", invalid");
9001 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9002 if (json_paths)
9003 json_object_boolean_true_add(json_path, "valid");
9004 else
9005 vty_out(vty, ", valid");
9006 }
9df8b37c 9007
05864da7
DS
9008 if (path->peer != bgp->peer_self) {
9009 if (path->peer->as == path->peer->local_as) {
9010 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9011 if (json_paths)
9012 json_object_string_add(
9013 json_peer, "type",
9014 "confed-internal");
d62a17ae 9015 else
05864da7 9016 vty_out(vty, ", confed-internal");
d62a17ae 9017 } else {
05864da7
DS
9018 if (json_paths)
9019 json_object_string_add(
9020 json_peer, "type", "internal");
9021 else
9022 vty_out(vty, ", internal");
9df8b37c 9023 }
05864da7
DS
9024 } else {
9025 if (bgp_confederation_peers_check(bgp,
9026 path->peer->as)) {
9027 if (json_paths)
9028 json_object_string_add(
9029 json_peer, "type",
9030 "confed-external");
d62a17ae 9031 else
05864da7 9032 vty_out(vty, ", confed-external");
d62a17ae 9033 } else {
05864da7
DS
9034 if (json_paths)
9035 json_object_string_add(
9036 json_peer, "type", "external");
9037 else
9038 vty_out(vty, ", external");
d62a17ae 9039 }
9040 }
05864da7
DS
9041 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9042 if (json_paths) {
9043 json_object_boolean_true_add(json_path, "aggregated");
9044 json_object_boolean_true_add(json_path, "local");
9045 } else {
9046 vty_out(vty, ", aggregated, local");
9047 }
9048 } else if (path->type != ZEBRA_ROUTE_BGP) {
9049 if (json_paths)
9050 json_object_boolean_true_add(json_path, "sourced");
9051 else
9052 vty_out(vty, ", sourced");
9053 } else {
9054 if (json_paths) {
9055 json_object_boolean_true_add(json_path, "sourced");
9056 json_object_boolean_true_add(json_path, "local");
9057 } else {
9058 vty_out(vty, ", sourced, local");
d62a17ae 9059 }
05864da7 9060 }
718e3744 9061
05864da7 9062 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9063 if (json_paths)
05864da7
DS
9064 json_object_boolean_true_add(json_path,
9065 "atomicAggregate");
d62a17ae 9066 else
05864da7
DS
9067 vty_out(vty, ", atomic-aggregate");
9068 }
d62a17ae 9069
05864da7
DS
9070 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9071 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9072 && bgp_path_info_mpath_count(path))) {
9073 if (json_paths)
9074 json_object_boolean_true_add(json_path, "multipath");
9075 else
9076 vty_out(vty, ", multipath");
9077 }
50e05855 9078
05864da7
DS
9079 // Mark the bestpath(s)
9080 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9081 first_as = aspath_get_first_as(attr->aspath);
718e3744 9082
05864da7
DS
9083 if (json_paths) {
9084 if (!json_bestpath)
9085 json_bestpath = json_object_new_object();
9086 json_object_int_add(json_bestpath, "bestpathFromAs",
9087 first_as);
9088 } else {
9089 if (first_as)
9090 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9091 else
05864da7 9092 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9093 }
05864da7 9094 }
718e3744 9095
05864da7
DS
9096 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9097 if (json_paths) {
9098 if (!json_bestpath)
9099 json_bestpath = json_object_new_object();
9100 json_object_boolean_true_add(json_bestpath, "overall");
9101 json_object_string_add(
9102 json_bestpath, "selectionReason",
9103 bgp_path_selection_reason2str(bn->reason));
9104 } else {
9105 vty_out(vty, ", best");
9106 vty_out(vty, " (%s)",
9107 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9108 }
05864da7 9109 }
718e3744 9110
05864da7
DS
9111 if (json_bestpath)
9112 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9113
05864da7
DS
9114 if (!json_paths)
9115 vty_out(vty, "\n");
9116
9117 /* Line 4 display Community */
9118 if (attr->community) {
9119 if (json_paths) {
9120 if (!attr->community->json)
9121 community_str(attr->community, true);
9122 json_object_lock(attr->community->json);
9123 json_object_object_add(json_path, "community",
9124 attr->community->json);
9125 } else {
9126 vty_out(vty, " Community: %s\n",
9127 attr->community->str);
d62a17ae 9128 }
05864da7 9129 }
718e3744 9130
05864da7
DS
9131 /* Line 5 display Extended-community */
9132 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9133 if (json_paths) {
9134 json_ext_community = json_object_new_object();
9135 json_object_string_add(json_ext_community, "string",
9136 attr->ecommunity->str);
9137 json_object_object_add(json_path, "extendedCommunity",
9138 json_ext_community);
d62a17ae 9139 } else {
05864da7
DS
9140 vty_out(vty, " Extended Community: %s\n",
9141 attr->ecommunity->str);
d62a17ae 9142 }
05864da7 9143 }
718e3744 9144
05864da7
DS
9145 /* Line 6 display Large community */
9146 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9147 if (json_paths) {
9148 if (!attr->lcommunity->json)
9149 lcommunity_str(attr->lcommunity, true);
9150 json_object_lock(attr->lcommunity->json);
9151 json_object_object_add(json_path, "largeCommunity",
9152 attr->lcommunity->json);
9153 } else {
9154 vty_out(vty, " Large Community: %s\n",
9155 attr->lcommunity->str);
d62a17ae 9156 }
05864da7 9157 }
718e3744 9158
05864da7
DS
9159 /* Line 7 display Originator, Cluster-id */
9160 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9161 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9162 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9163 if (json_paths)
05864da7
DS
9164 json_object_string_add(
9165 json_path, "originatorId",
9166 inet_ntoa(attr->originator_id));
d62a17ae 9167 else
05864da7
DS
9168 vty_out(vty, " Originator: %s",
9169 inet_ntoa(attr->originator_id));
d62a17ae 9170 }
856ca177 9171
05864da7
DS
9172 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9173 int i;
d62a17ae 9174
9175 if (json_paths) {
05864da7
DS
9176 json_cluster_list = json_object_new_object();
9177 json_cluster_list_list =
9178 json_object_new_array();
9179
9180 for (i = 0; i < attr->cluster->length / 4;
9181 i++) {
9182 json_string = json_object_new_string(
9183 inet_ntoa(attr->cluster
9184 ->list[i]));
9185 json_object_array_add(
9186 json_cluster_list_list,
9187 json_string);
9188 }
718e3744 9189
05864da7
DS
9190 /*
9191 * struct cluster_list does not have
9192 * "str" variable like aspath and community
9193 * do. Add this someday if someone asks
9194 * for it.
9195 * json_object_string_add(json_cluster_list,
9196 * "string", attr->cluster->str);
9197 */
9198 json_object_object_add(json_cluster_list,
9199 "list",
9200 json_cluster_list_list);
9201 json_object_object_add(json_path, "clusterList",
9202 json_cluster_list);
0dc8ee70 9203 } else {
05864da7
DS
9204 vty_out(vty, ", Cluster list: ");
9205
9206 for (i = 0; i < attr->cluster->length / 4;
9207 i++) {
9208 vty_out(vty, "%s ",
9209 inet_ntoa(attr->cluster
9210 ->list[i]));
9211 }
0dc8ee70 9212 }
d62a17ae 9213 }
718e3744 9214
d62a17ae 9215 if (!json_paths)
9216 vty_out(vty, "\n");
05864da7 9217 }
d62a17ae 9218
05864da7 9219 if (path->extra && path->extra->damp_info)
a935f597 9220 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9221
05864da7
DS
9222 /* Remote Label */
9223 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9224 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9225 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9226
05864da7
DS
9227 if (json_paths)
9228 json_object_int_add(json_path, "remoteLabel", label);
9229 else
9230 vty_out(vty, " Remote label: %d\n", label);
9231 }
d62a17ae 9232
e496b420
HS
9233 /* Remote SID */
9234 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9235 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9236 if (json_paths)
9237 json_object_string_add(json_path, "remoteSid", buf);
9238 else
9239 vty_out(vty, " Remote SID: %s\n", buf);
9240 }
9241
05864da7
DS
9242 /* Label Index */
9243 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9244 if (json_paths)
9245 json_object_int_add(json_path, "labelIndex",
9246 attr->label_index);
9247 else
9248 vty_out(vty, " Label Index: %d\n",
9249 attr->label_index);
9250 }
d62a17ae 9251
05864da7
DS
9252 /* Line 8 display Addpath IDs */
9253 if (path->addpath_rx_id
9254 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9255 if (json_paths) {
9256 json_object_int_add(json_path, "addpathRxId",
9257 path->addpath_rx_id);
d62a17ae 9258
05864da7
DS
9259 /* Keep backwards compatibility with the old API
9260 * by putting TX All's ID in the old field
9261 */
9262 json_object_int_add(
9263 json_path, "addpathTxId",
9264 path->tx_addpath
9265 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9266
05864da7
DS
9267 /* ... but create a specific field for each
9268 * strategy
9269 */
9270 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9271 json_object_int_add(
9272 json_path,
9273 bgp_addpath_names(i)->id_json_name,
9274 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9275 }
05864da7
DS
9276 } else {
9277 vty_out(vty, " AddPath ID: RX %u, ",
9278 path->addpath_rx_id);
d62a17ae 9279
05864da7 9280 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9281 }
05864da7 9282 }
520d5d76 9283
05864da7
DS
9284 /* If we used addpath to TX a non-bestpath we need to display
9285 * "Advertised to" on a path-by-path basis
9286 */
9287 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9288 first = 1;
dcc68b5e 9289
05864da7
DS
9290 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9291 addpath_capable =
9292 bgp_addpath_encode_tx(peer, afi, safi);
9293 has_adj = bgp_adj_out_lookup(
9294 peer, path->net,
9295 bgp_addpath_id_for_peer(peer, afi, safi,
9296 &path->tx_addpath));
9297
9298 if ((addpath_capable && has_adj)
9299 || (!addpath_capable && has_adj
9300 && CHECK_FLAG(path->flags,
9301 BGP_PATH_SELECTED))) {
9302 if (json_path && !json_adv_to)
9303 json_adv_to = json_object_new_object();
dcc68b5e 9304
05864da7
DS
9305 route_vty_out_advertised_to(
9306 vty, peer, &first,
9307 " Advertised to:", json_adv_to);
d62a17ae 9308 }
9309 }
718e3744 9310
05864da7
DS
9311 if (json_path) {
9312 if (json_adv_to) {
9313 json_object_object_add(
9314 json_path, "advertisedTo", json_adv_to);
d62a17ae 9315 }
05864da7
DS
9316 } else {
9317 if (!first) {
9318 vty_out(vty, "\n");
d62a17ae 9319 }
9320 }
05864da7 9321 }
b05a1c8b 9322
05864da7
DS
9323 /* Line 9 display Uptime */
9324 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9325 if (json_paths) {
9326 json_last_update = json_object_new_object();
9327 json_object_int_add(json_last_update, "epoch", tbuf);
9328 json_object_string_add(json_last_update, "string",
9329 ctime(&tbuf));
9330 json_object_object_add(json_path, "lastUpdate",
9331 json_last_update);
9332 } else
9333 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9334
05864da7
DS
9335 /* Line 10 display PMSI tunnel attribute, if present */
9336 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9337 const char *str =
9338 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9339 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9340
05864da7
DS
9341 if (json_paths) {
9342 json_pmsi = json_object_new_object();
9343 json_object_string_add(json_pmsi, "tunnelType", str);
9344 json_object_int_add(json_pmsi, "label",
9345 label2vni(&attr->label));
9346 json_object_object_add(json_path, "pmsi", json_pmsi);
9347 } else
9348 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9349 str, label2vni(&attr->label));
d62a17ae 9350 }
f1aa5d8a 9351
d62a17ae 9352 /* We've constructed the json object for this path, add it to the json
9353 * array of paths
9354 */
9355 if (json_paths) {
9356 if (json_nexthop_global || json_nexthop_ll) {
9357 json_nexthops = json_object_new_array();
f1aa5d8a 9358
d62a17ae 9359 if (json_nexthop_global)
9360 json_object_array_add(json_nexthops,
9361 json_nexthop_global);
f1aa5d8a 9362
d62a17ae 9363 if (json_nexthop_ll)
9364 json_object_array_add(json_nexthops,
9365 json_nexthop_ll);
f1aa5d8a 9366
d62a17ae 9367 json_object_object_add(json_path, "nexthops",
9368 json_nexthops);
9369 }
9370
9371 json_object_object_add(json_path, "peer", json_peer);
9372 json_object_array_add(json_paths, json_path);
05864da7 9373 }
b366b518
BB
9374}
9375
96ade3ed 9376#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9377#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9378#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9379
d62a17ae 9380static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9381 const char *prefix_list_str, afi_t afi,
9382 safi_t safi, enum bgp_show_type type);
9383static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9384 const char *filter, afi_t afi, safi_t safi,
9385 enum bgp_show_type type);
9386static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9387 const char *rmap_str, afi_t afi, safi_t safi,
9388 enum bgp_show_type type);
9389static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9390 const char *com, int exact, afi_t afi,
9391 safi_t safi);
9392static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9393 const char *prefix, afi_t afi, safi_t safi,
9394 enum bgp_show_type type);
a4d82a8a 9395static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9396 afi_t afi, safi_t safi, enum bgp_show_type type,
9397 bool use_json);
7f323236
DW
9398static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9399 const char *comstr, int exact, afi_t afi,
9f049418 9400 safi_t safi, bool use_json);
d62a17ae 9401
1ae44dfc
LB
9402
9403static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9404 struct bgp_table *table, enum bgp_show_type type,
9f049418 9405 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9406 int is_last, unsigned long *output_cum,
9407 unsigned long *total_cum,
9386b588 9408 unsigned long *json_header_depth)
d62a17ae 9409{
40381db7 9410 struct bgp_path_info *pi;
d62a17ae 9411 struct bgp_node *rn;
9412 int header = 1;
9413 int display;
1ae44dfc
LB
9414 unsigned long output_count = 0;
9415 unsigned long total_count = 0;
d62a17ae 9416 struct prefix *p;
d62a17ae 9417 char buf2[BUFSIZ];
9418 json_object *json_paths = NULL;
9419 int first = 1;
9420
1ae44dfc
LB
9421 if (output_cum && *output_cum != 0)
9422 header = 0;
9423
9386b588 9424 if (use_json && !*json_header_depth) {
d62a17ae 9425 vty_out(vty,
66f80d74 9426 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9427 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9428 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9429 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9430 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9431 ? VRF_DEFAULT_NAME
9432 : bgp->name,
01eced22
AD
9433 table->version, inet_ntoa(bgp->router_id),
9434 bgp->default_local_pref, bgp->as);
9386b588
PZ
9435 *json_header_depth = 2;
9436 if (rd) {
445c2480 9437 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9438 ++*json_header_depth;
9439 }
d62a17ae 9440 }
718e3744 9441
445c2480
DS
9442 if (use_json && rd) {
9443 vty_out(vty, " \"%s\" : { ", rd);
9444 }
9445
d62a17ae 9446 /* Start processing of routes. */
98ce9a06 9447 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9448 pi = bgp_node_get_bgp_path_info(rn);
9449 if (pi == NULL)
98ce9a06 9450 continue;
d62a17ae 9451
98ce9a06 9452 display = 0;
98ce9a06
DS
9453 if (use_json)
9454 json_paths = json_object_new_array();
9455 else
9456 json_paths = NULL;
d62a17ae 9457
6f94b685 9458 for (; pi; pi = pi->next) {
98ce9a06
DS
9459 total_count++;
9460 if (type == bgp_show_type_flap_statistics
9461 || type == bgp_show_type_flap_neighbor
9462 || type == bgp_show_type_dampend_paths
9463 || type == bgp_show_type_damp_neighbor) {
40381db7 9464 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9465 continue;
9466 }
9467 if (type == bgp_show_type_regexp) {
9468 regex_t *regex = output_arg;
d62a17ae 9469
40381db7 9470 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9471 == REG_NOMATCH)
9472 continue;
9473 }
9474 if (type == bgp_show_type_prefix_list) {
9475 struct prefix_list *plist = output_arg;
d62a17ae 9476
98ce9a06
DS
9477 if (prefix_list_apply(plist, &rn->p)
9478 != PREFIX_PERMIT)
9479 continue;
9480 }
9481 if (type == bgp_show_type_filter_list) {
9482 struct as_list *as_list = output_arg;
d62a17ae 9483
40381db7 9484 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9485 != AS_FILTER_PERMIT)
9486 continue;
9487 }
9488 if (type == bgp_show_type_route_map) {
9489 struct route_map *rmap = output_arg;
9b6d8fcf 9490 struct bgp_path_info path;
98ce9a06 9491 struct attr dummy_attr;
b68885f9 9492 route_map_result_t ret;
d62a17ae 9493
6f4f49b2 9494 dummy_attr = *pi->attr;
d62a17ae 9495
40381db7 9496 path.peer = pi->peer;
9b6d8fcf 9497 path.attr = &dummy_attr;
d62a17ae 9498
a4d82a8a 9499 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9500 &path);
98ce9a06
DS
9501 if (ret == RMAP_DENYMATCH)
9502 continue;
9503 }
9504 if (type == bgp_show_type_neighbor
9505 || type == bgp_show_type_flap_neighbor
9506 || type == bgp_show_type_damp_neighbor) {
9507 union sockunion *su = output_arg;
9508
40381db7
DS
9509 if (pi->peer == NULL
9510 || pi->peer->su_remote == NULL
9511 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9512 continue;
9513 }
9514 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9515 uint32_t destination;
d62a17ae 9516
98ce9a06
DS
9517 destination = ntohl(rn->p.u.prefix4.s_addr);
9518 if (IN_CLASSC(destination)
9519 && rn->p.prefixlen == 24)
9520 continue;
9521 if (IN_CLASSB(destination)
9522 && rn->p.prefixlen == 16)
9523 continue;
9524 if (IN_CLASSA(destination)
9525 && rn->p.prefixlen == 8)
9526 continue;
9527 }
9528 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9529 p = output_arg;
98ce9a06
DS
9530 if (!prefix_match(p, &rn->p))
9531 continue;
9532 }
9533 if (type == bgp_show_type_community_all) {
40381db7 9534 if (!pi->attr->community)
98ce9a06
DS
9535 continue;
9536 }
9537 if (type == bgp_show_type_community) {
9538 struct community *com = output_arg;
d62a17ae 9539
40381db7
DS
9540 if (!pi->attr->community
9541 || !community_match(pi->attr->community,
98ce9a06
DS
9542 com))
9543 continue;
9544 }
9545 if (type == bgp_show_type_community_exact) {
9546 struct community *com = output_arg;
d62a17ae 9547
40381db7
DS
9548 if (!pi->attr->community
9549 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9550 continue;
9551 }
9552 if (type == bgp_show_type_community_list) {
9553 struct community_list *list = output_arg;
d62a17ae 9554
40381db7 9555 if (!community_list_match(pi->attr->community,
a4d82a8a 9556 list))
98ce9a06
DS
9557 continue;
9558 }
a4d82a8a 9559 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9560 struct community_list *list = output_arg;
d62a17ae 9561
98ce9a06 9562 if (!community_list_exact_match(
40381db7 9563 pi->attr->community, list))
98ce9a06
DS
9564 continue;
9565 }
9566 if (type == bgp_show_type_lcommunity) {
9567 struct lcommunity *lcom = output_arg;
d62a17ae 9568
40381db7
DS
9569 if (!pi->attr->lcommunity
9570 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9571 lcom))
9572 continue;
9573 }
36a206db 9574
9575 if (type == bgp_show_type_lcommunity_exact) {
9576 struct lcommunity *lcom = output_arg;
9577
9578 if (!pi->attr->lcommunity
9579 || !lcommunity_cmp(pi->attr->lcommunity,
9580 lcom))
9581 continue;
9582 }
98ce9a06
DS
9583 if (type == bgp_show_type_lcommunity_list) {
9584 struct community_list *list = output_arg;
d62a17ae 9585
40381db7 9586 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9587 list))
98ce9a06
DS
9588 continue;
9589 }
36a206db 9590 if (type
9591 == bgp_show_type_lcommunity_list_exact) {
9592 struct community_list *list = output_arg;
9593
9594 if (!lcommunity_list_exact_match(
9595 pi->attr->lcommunity, list))
9596 continue;
9597 }
98ce9a06 9598 if (type == bgp_show_type_lcommunity_all) {
40381db7 9599 if (!pi->attr->lcommunity)
98ce9a06
DS
9600 continue;
9601 }
9602 if (type == bgp_show_type_dampend_paths
9603 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9604 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9605 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9606 continue;
9607 }
9608
9609 if (!use_json && header) {
996c9314 9610 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9611 ", local router ID is %s, vrf id ",
98ce9a06
DS
9612 table->version,
9613 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9614 if (bgp->vrf_id == VRF_UNKNOWN)
9615 vty_out(vty, "%s", VRFID_NONE_STR);
9616 else
9617 vty_out(vty, "%u", bgp->vrf_id);
9618 vty_out(vty, "\n");
01eced22
AD
9619 vty_out(vty, "Default local pref %u, ",
9620 bgp->default_local_pref);
9621 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9622 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9623 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9624 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9625 if (type == bgp_show_type_dampend_paths
9626 || type == bgp_show_type_damp_neighbor)
98ce9a06 9627 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9628 else if (type == bgp_show_type_flap_statistics
9629 || type == bgp_show_type_flap_neighbor)
98ce9a06 9630 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9631 else
98ce9a06
DS
9632 vty_out(vty, BGP_SHOW_HEADER);
9633 header = 0;
d62a17ae 9634 }
98ce9a06
DS
9635 if (rd != NULL && !display && !output_count) {
9636 if (!use_json)
9637 vty_out(vty,
9638 "Route Distinguisher: %s\n",
9639 rd);
d62a17ae 9640 }
98ce9a06
DS
9641 if (type == bgp_show_type_dampend_paths
9642 || type == bgp_show_type_damp_neighbor)
a935f597 9643 damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9644 safi, use_json, json_paths);
98ce9a06
DS
9645 else if (type == bgp_show_type_flap_statistics
9646 || type == bgp_show_type_flap_neighbor)
a935f597 9647 flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9648 safi, use_json, json_paths);
98ce9a06 9649 else
40381db7 9650 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9651 json_paths);
98ce9a06 9652 display++;
d62a17ae 9653 }
9654
98ce9a06
DS
9655 if (display) {
9656 output_count++;
9657 if (!use_json)
9658 continue;
9659
9660 p = &rn->p;
625d2931
PG
9661 /* encode prefix */
9662 if (p->family == AF_FLOWSPEC) {
9663 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9664
9665 bgp_fs_nlri_get_string((unsigned char *)
9666 p->u.prefix_flowspec.ptr,
9667 p->u.prefix_flowspec
9668 .prefixlen,
9669 retstr,
9670 NLRI_STRING_FORMAT_MIN,
9671 NULL);
9672 if (first)
9673 vty_out(vty, "\"%s/%d\": ",
9674 retstr,
9675 p->u.prefix_flowspec.prefixlen);
9676 else
9677 vty_out(vty, ",\"%s/%d\": ",
9678 retstr,
9679 p->u.prefix_flowspec.prefixlen);
9680 } else {
9681 prefix2str(p, buf2, sizeof(buf2));
9682 if (first)
9683 vty_out(vty, "\"%s\": ", buf2);
9684 else
9685 vty_out(vty, ",\"%s\": ", buf2);
9686 }
98ce9a06 9687 vty_out(vty, "%s",
f4ec52f7
DA
9688 json_object_to_json_string_ext(
9689 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9690 json_object_free(json_paths);
449feb8e 9691 json_paths = NULL;
98ce9a06 9692 first = 0;
1f83ed02
DS
9693 } else
9694 json_object_free(json_paths);
98ce9a06
DS
9695 }
9696
1ae44dfc
LB
9697 if (output_cum) {
9698 output_count += *output_cum;
9699 *output_cum = output_count;
9700 }
9701 if (total_cum) {
9702 total_count += *total_cum;
9703 *total_cum = total_count;
9704 }
d62a17ae 9705 if (use_json) {
9386b588 9706 if (rd) {
a4d82a8a 9707 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9708 }
9709 if (is_last) {
a4d82a8a
PZ
9710 unsigned long i;
9711 for (i = 0; i < *json_header_depth; ++i)
9712 vty_out(vty, " } ");
faf6559a 9713 vty_out(vty, "\n");
9386b588 9714 }
d62a17ae 9715 } else {
1ae44dfc
LB
9716 if (is_last) {
9717 /* No route is displayed */
9718 if (output_count == 0) {
9719 if (type == bgp_show_type_normal)
9720 vty_out(vty,
9721 "No BGP prefixes displayed, %ld exist\n",
9722 total_count);
9723 } else
d62a17ae 9724 vty_out(vty,
1ae44dfc
LB
9725 "\nDisplayed %ld routes and %ld total paths\n",
9726 output_count, total_count);
9727 }
d62a17ae 9728 }
718e3744 9729
d62a17ae 9730 return CMD_SUCCESS;
718e3744 9731}
9732
1ae44dfc
LB
9733int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9734 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9735 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9736{
9737 struct bgp_node *rn, *next;
9738 unsigned long output_cum = 0;
9739 unsigned long total_cum = 0;
9386b588 9740 unsigned long json_header_depth = 0;
67009e22 9741 struct bgp_table *itable;
0136788c
LB
9742 bool show_msg;
9743
9744 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9745
9746 for (rn = bgp_table_top(table); rn; rn = next) {
9747 next = bgp_route_next(rn);
9748 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9749 continue;
67009e22
DS
9750
9751 itable = bgp_node_get_bgp_table_info(rn);
9752 if (itable != NULL) {
1ae44dfc 9753 struct prefix_rd prd;
06b9f471 9754 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9755
9756 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9757 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9758 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9759 use_json, rd, next == NULL, &output_cum,
9760 &total_cum, &json_header_depth);
0136788c
LB
9761 if (next == NULL)
9762 show_msg = false;
1ae44dfc
LB
9763 }
9764 }
0136788c
LB
9765 if (show_msg) {
9766 if (output_cum == 0)
9767 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9768 total_cum);
9769 else
9770 vty_out(vty,
9771 "\nDisplayed %ld routes and %ld total paths\n",
9772 output_cum, total_cum);
9773 }
1ae44dfc
LB
9774 return CMD_SUCCESS;
9775}
d62a17ae 9776static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9777 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9778{
d62a17ae 9779 struct bgp_table *table;
9386b588 9780 unsigned long json_header_depth = 0;
fee0f4c6 9781
d62a17ae 9782 if (bgp == NULL) {
9783 bgp = bgp_get_default();
9784 }
fee0f4c6 9785
d62a17ae 9786 if (bgp == NULL) {
9787 if (!use_json)
9788 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9789 else
9790 vty_out(vty, "{}\n");
d62a17ae 9791 return CMD_WARNING;
9792 }
4dd6177e 9793
1ae44dfc 9794 table = bgp->rib[afi][safi];
d62a17ae 9795 /* use MPLS and ENCAP specific shows until they are merged */
9796 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9797 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9798 output_arg, use_json);
d62a17ae 9799 }
dba3c1d3
PG
9800
9801 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9802 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9803 output_arg, use_json,
9804 1, NULL, NULL);
9805 }
d62a17ae 9806 /* labeled-unicast routes live in the unicast table */
9807 else if (safi == SAFI_LABELED_UNICAST)
9808 safi = SAFI_UNICAST;
fee0f4c6 9809
1ae44dfc 9810 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9811 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9812}
9813
d62a17ae 9814static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9815 safi_t safi, bool use_json)
f186de26 9816{
d62a17ae 9817 struct listnode *node, *nnode;
9818 struct bgp *bgp;
9819 int is_first = 1;
9f049418 9820 bool route_output = false;
f186de26 9821
d62a17ae 9822 if (use_json)
9823 vty_out(vty, "{\n");
9f689658 9824
d62a17ae 9825 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9826 route_output = true;
d62a17ae 9827 if (use_json) {
9828 if (!is_first)
9829 vty_out(vty, ",\n");
9830 else
9831 is_first = 0;
9832
9833 vty_out(vty, "\"%s\":",
9834 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9835 ? VRF_DEFAULT_NAME
d62a17ae 9836 : bgp->name);
9837 } else {
9838 vty_out(vty, "\nInstance %s:\n",
9839 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9840 ? VRF_DEFAULT_NAME
d62a17ae 9841 : bgp->name);
9842 }
9843 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9844 use_json);
9845 }
9f689658 9846
d62a17ae 9847 if (use_json)
9848 vty_out(vty, "}\n");
9f049418
DS
9849 else if (!route_output)
9850 vty_out(vty, "%% BGP instance not found\n");
f186de26 9851}
9852
718e3744 9853/* Header of detailed BGP route information */
d62a17ae 9854void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9855 struct bgp_node *rn, struct prefix_rd *prd,
9856 afi_t afi, safi_t safi, json_object *json)
9857{
40381db7 9858 struct bgp_path_info *pi;
d62a17ae 9859 struct prefix *p;
9860 struct peer *peer;
9861 struct listnode *node, *nnode;
06b9f471 9862 char buf1[RD_ADDRSTRLEN];
d62a17ae 9863 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9864 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9865 char prefix_str[BUFSIZ];
d62a17ae 9866 int count = 0;
9867 int best = 0;
9868 int suppress = 0;
c5f1e1b2
C
9869 int accept_own = 0;
9870 int route_filter_translated_v4 = 0;
9871 int route_filter_v4 = 0;
9872 int route_filter_translated_v6 = 0;
9873 int route_filter_v6 = 0;
9874 int llgr_stale = 0;
9875 int no_llgr = 0;
9876 int accept_own_nexthop = 0;
9877 int blackhole = 0;
d62a17ae 9878 int no_export = 0;
9879 int no_advertise = 0;
9880 int local_as = 0;
c5f1e1b2 9881 int no_peer = 0;
d62a17ae 9882 int first = 1;
9883 int has_valid_label = 0;
9884 mpls_label_t label = 0;
9885 json_object *json_adv_to = NULL;
9bedbb1e 9886
d62a17ae 9887 p = &rn->p;
9888 has_valid_label = bgp_is_valid_label(&rn->local_label);
9889
9890 if (has_valid_label)
9891 label = label_pton(&rn->local_label);
9892
44c69747 9893 if (safi == SAFI_EVPN) {
d62a17ae 9894
44c69747 9895 if (!json) {
d62a17ae 9896 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9897 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9898 : "", prd ? ":" : "",
d62a17ae 9899 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9900 buf3, sizeof(buf3)));
9901 } else {
9902 json_object_string_add(json, "rd",
9903 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9904 "");
9905 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9906 }
9907 } else {
9908 if (!json) {
d62a17ae 9909 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9910 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9911 ? prefix_rd2str(prd, buf1,
9912 sizeof(buf1))
9913 : ""),
d62a17ae 9914 safi == SAFI_MPLS_VPN ? ":" : "",
9915 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9916 INET6_ADDRSTRLEN),
d62a17ae 9917 p->prefixlen);
cd1964ff 9918
44c69747
LK
9919 } else
9920 json_object_string_add(json, "prefix",
9921 prefix2str(p, prefix_str, sizeof(prefix_str)));
9922 }
9923
9924 if (has_valid_label) {
9925 if (json)
9926 json_object_int_add(json, "localLabel", label);
9927 else
d62a17ae 9928 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9929 }
9930
9931 if (!json)
d62a17ae 9932 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9933 vty_out(vty, "not allocated\n");
718e3744 9934
6f94b685 9935 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 9936 count++;
40381db7 9937 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 9938 best = count;
40381db7 9939 if (pi->extra && pi->extra->suppress)
d62a17ae 9940 suppress = 1;
cee9c031 9941
40381db7 9942 if (pi->attr->community == NULL)
cee9c031
QY
9943 continue;
9944
9945 no_advertise += community_include(
40381db7
DS
9946 pi->attr->community, COMMUNITY_NO_ADVERTISE);
9947 no_export += community_include(pi->attr->community,
cee9c031 9948 COMMUNITY_NO_EXPORT);
40381db7 9949 local_as += community_include(pi->attr->community,
cee9c031 9950 COMMUNITY_LOCAL_AS);
40381db7 9951 accept_own += community_include(pi->attr->community,
cee9c031
QY
9952 COMMUNITY_ACCEPT_OWN);
9953 route_filter_translated_v4 += community_include(
40381db7 9954 pi->attr->community,
cee9c031
QY
9955 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
9956 route_filter_translated_v6 += community_include(
40381db7 9957 pi->attr->community,
cee9c031
QY
9958 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
9959 route_filter_v4 += community_include(
40381db7 9960 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 9961 route_filter_v6 += community_include(
40381db7
DS
9962 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
9963 llgr_stale += community_include(pi->attr->community,
cee9c031 9964 COMMUNITY_LLGR_STALE);
40381db7 9965 no_llgr += community_include(pi->attr->community,
cee9c031
QY
9966 COMMUNITY_NO_LLGR);
9967 accept_own_nexthop +=
40381db7 9968 community_include(pi->attr->community,
cee9c031 9969 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 9970 blackhole += community_include(pi->attr->community,
cee9c031 9971 COMMUNITY_BLACKHOLE);
40381db7 9972 no_peer += community_include(pi->attr->community,
cee9c031 9973 COMMUNITY_NO_PEER);
d62a17ae 9974 }
718e3744 9975 }
718e3744 9976
d62a17ae 9977 if (!json) {
9978 vty_out(vty, "Paths: (%d available", count);
9979 if (best) {
9980 vty_out(vty, ", best #%d", best);
b84060bb
PG
9981 if (safi == SAFI_UNICAST) {
9982 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
9983 vty_out(vty, ", table %s",
9984 VRF_DEFAULT_NAME);
9985 else
9986 vty_out(vty, ", vrf %s",
9987 bgp->name);
9988 }
d62a17ae 9989 } else
9990 vty_out(vty, ", no best path");
9991
c5f1e1b2
C
9992 if (accept_own)
9993 vty_out(vty,
9994 ", accept own local route exported and imported in different VRF");
9995 else if (route_filter_translated_v4)
9996 vty_out(vty,
9997 ", mark translated RTs for VPNv4 route filtering");
9998 else if (route_filter_v4)
9999 vty_out(vty,
10000 ", attach RT as-is for VPNv4 route filtering");
10001 else if (route_filter_translated_v6)
10002 vty_out(vty,
10003 ", mark translated RTs for VPNv6 route filtering");
10004 else if (route_filter_v6)
10005 vty_out(vty,
10006 ", attach RT as-is for VPNv6 route filtering");
10007 else if (llgr_stale)
10008 vty_out(vty,
10009 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10010 else if (no_llgr)
10011 vty_out(vty,
10012 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10013 else if (accept_own_nexthop)
10014 vty_out(vty,
10015 ", accept local nexthop");
10016 else if (blackhole)
10017 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10018 else if (no_export)
10019 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10020 else if (no_advertise)
10021 vty_out(vty, ", not advertised to any peer");
d62a17ae 10022 else if (local_as)
10023 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10024 else if (no_peer)
10025 vty_out(vty,
10026 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10027
10028 if (suppress)
10029 vty_out(vty,
10030 ", Advertisements suppressed by an aggregate.");
10031 vty_out(vty, ")\n");
10032 }
718e3744 10033
d62a17ae 10034 /* If we are not using addpath then we can display Advertised to and
10035 * that will
10036 * show what peers we advertised the bestpath to. If we are using
10037 * addpath
10038 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10039 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10040 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10041 if (bgp_adj_out_lookup(peer, rn, 0)) {
10042 if (json && !json_adv_to)
10043 json_adv_to = json_object_new_object();
10044
10045 route_vty_out_advertised_to(
10046 vty, peer, &first,
10047 " Advertised to non peer-group peers:\n ",
10048 json_adv_to);
10049 }
10050 }
10051
10052 if (json) {
10053 if (json_adv_to) {
10054 json_object_object_add(json, "advertisedTo",
10055 json_adv_to);
10056 }
10057 } else {
10058 if (first)
10059 vty_out(vty, " Not advertised to any peer");
10060 vty_out(vty, "\n");
10061 }
10062 }
718e3744 10063}
10064
44c69747
LK
10065static void bgp_show_path_info(struct prefix_rd *pfx_rd,
10066 struct bgp_node *bgp_node, struct vty *vty,
10067 struct bgp *bgp, afi_t afi,
10068 safi_t safi, json_object *json,
10069 enum bgp_path_type pathtype, int *display)
10070{
10071 struct bgp_path_info *pi;
10072 int header = 1;
10073 char rdbuf[RD_ADDRSTRLEN];
10074 json_object *json_header = NULL;
10075 json_object *json_paths = NULL;
10076
10077 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
10078 pi = pi->next) {
10079
10080 if (json && !json_paths) {
10081 /* Instantiate json_paths only if path is valid */
10082 json_paths = json_object_new_array();
10083 if (pfx_rd) {
10084 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10085 json_header = json_object_new_object();
10086 } else
10087 json_header = json;
10088 }
10089
10090 if (header) {
10091 route_vty_out_detail_header(
10092 vty, bgp, bgp_node, pfx_rd,
10093 AFI_IP, safi, json_header);
10094 header = 0;
10095 }
10096 (*display)++;
10097
10098 if (pathtype == BGP_PATH_SHOW_ALL
10099 || (pathtype == BGP_PATH_SHOW_BESTPATH
10100 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10101 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10102 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10103 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10104 route_vty_out_detail(vty, bgp, bgp_node,
10105 pi, AFI_IP, safi,
10106 json_paths);
10107 }
10108
10109 if (json && json_paths) {
10110 json_object_object_add(json_header, "paths", json_paths);
10111
10112 if (pfx_rd)
10113 json_object_object_add(json, rdbuf, json_header);
10114 }
10115}
10116
718e3744 10117/* Display specified route of BGP table. */
d62a17ae 10118static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10119 struct bgp_table *rib, const char *ip_str,
10120 afi_t afi, safi_t safi,
10121 struct prefix_rd *prd, int prefix_check,
9f049418 10122 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10123{
10124 int ret;
d62a17ae 10125 int display = 0;
10126 struct prefix match;
10127 struct bgp_node *rn;
10128 struct bgp_node *rm;
d62a17ae 10129 struct bgp_table *table;
10130 json_object *json = NULL;
10131 json_object *json_paths = NULL;
10132
10133 /* Check IP address argument. */
10134 ret = str2prefix(ip_str, &match);
10135 if (!ret) {
10136 vty_out(vty, "address is malformed\n");
10137 return CMD_WARNING;
10138 }
718e3744 10139
d62a17ae 10140 match.family = afi2family(afi);
b05a1c8b 10141
44c69747 10142 if (use_json)
d62a17ae 10143 json = json_object_new_object();
718e3744 10144
44c69747 10145 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 10146 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
10147 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10148 continue;
67009e22
DS
10149 table = bgp_node_get_bgp_table_info(rn);
10150 if (!table)
ea47320b 10151 continue;
d62a17ae 10152
ea47320b
DL
10153 if ((rm = bgp_node_match(table, &match)) == NULL)
10154 continue;
d62a17ae 10155
ea47320b
DL
10156 if (prefix_check
10157 && rm->p.prefixlen != match.prefixlen) {
10158 bgp_unlock_node(rm);
10159 continue;
10160 }
d62a17ae 10161
44c69747
LK
10162 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10163 vty, bgp, afi, safi, json,
10164 pathtype, &display);
10165
10166 bgp_unlock_node(rm);
10167 }
10168 } else if (safi == SAFI_EVPN) {
10169 struct bgp_node *longest_pfx;
10170 bool is_exact_pfxlen_match = FALSE;
10171
10172 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
10173 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10174 continue;
10175 table = bgp_node_get_bgp_table_info(rn);
10176 if (!table)
10177 continue;
10178
10179 longest_pfx = NULL;
10180 is_exact_pfxlen_match = FALSE;
10181 /*
10182 * Search through all the prefixes for a match. The
10183 * pfx's are enumerated in ascending order of pfxlens.
10184 * So, the last pfx match is the longest match. Set
10185 * is_exact_pfxlen_match when we get exact pfxlen match
10186 */
10187 for (rm = bgp_table_top(table); rm;
10188 rm = bgp_route_next(rm)) {
10189 /*
10190 * Get prefixlen of the ip-prefix within type5
10191 * evpn route
10192 */
10193 if (evpn_type5_prefix_match(&rm->p,
10194 &match) && rm->info) {
10195 longest_pfx = rm;
10196 int type5_pfxlen =
10197 bgp_evpn_get_type5_prefixlen(&rm->p);
10198 if (type5_pfxlen == match.prefixlen) {
10199 is_exact_pfxlen_match = TRUE;
10200 bgp_unlock_node(rm);
10201 break;
10202 }
d62a17ae 10203 }
10204 }
ea47320b 10205
44c69747
LK
10206 if (!longest_pfx)
10207 continue;
10208
10209 if (prefix_check && !is_exact_pfxlen_match)
10210 continue;
10211
10212 rm = longest_pfx;
10213 bgp_lock_node(rm);
10214
10215 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10216 vty, bgp, afi, safi, json,
10217 pathtype, &display);
10218
ea47320b 10219 bgp_unlock_node(rm);
d62a17ae 10220 }
98a9dbc7 10221 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10222 if (use_json)
10223 json_paths = json_object_new_array();
10224
63a0b7a9
PG
10225 display = bgp_flowspec_display_match_per_ip(afi, rib,
10226 &match, prefix_check,
10227 vty,
10228 use_json,
10229 json_paths);
44c69747
LK
10230 if (use_json && display)
10231 json_object_object_add(json, "paths", json_paths);
d62a17ae 10232 } else {
d62a17ae 10233 if ((rn = bgp_node_match(rib, &match)) != NULL) {
10234 if (!prefix_check
10235 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
10236 bgp_show_path_info(NULL, rn, vty, bgp, afi,
10237 safi, json,
10238 pathtype, &display);
d62a17ae 10239 }
10240
10241 bgp_unlock_node(rn);
10242 }
10243 }
e5eee9af 10244
d62a17ae 10245 if (use_json) {
996c9314 10246 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10247 json, JSON_C_TO_STRING_PRETTY |
10248 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10249 json_object_free(json);
10250 } else {
10251 if (!display) {
10252 vty_out(vty, "%% Network not in table\n");
10253 return CMD_WARNING;
10254 }
10255 }
b05a1c8b 10256
d62a17ae 10257 return CMD_SUCCESS;
718e3744 10258}
10259
fee0f4c6 10260/* Display specified route of Main RIB */
d62a17ae 10261static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10262 afi_t afi, safi_t safi, struct prefix_rd *prd,
10263 int prefix_check, enum bgp_path_type pathtype,
9f049418 10264 bool use_json)
d62a17ae 10265{
9b86009a 10266 if (!bgp) {
d62a17ae 10267 bgp = bgp_get_default();
9b86009a
RW
10268 if (!bgp) {
10269 if (!use_json)
10270 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10271 else
10272 vty_out(vty, "{}\n");
9b86009a
RW
10273 return CMD_WARNING;
10274 }
10275 }
d62a17ae 10276
10277 /* labeled-unicast routes live in the unicast table */
10278 if (safi == SAFI_LABELED_UNICAST)
10279 safi = SAFI_UNICAST;
10280
10281 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10282 afi, safi, prd, prefix_check, pathtype,
10283 use_json);
10284}
10285
10286static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10287 struct cmd_token **argv, bool exact, afi_t afi,
10288 safi_t safi, bool uj)
d62a17ae 10289{
10290 struct lcommunity *lcom;
10291 struct buffer *b;
10292 int i;
10293 char *str;
10294 int first = 0;
10295
10296 b = buffer_new(1024);
10297 for (i = 0; i < argc; i++) {
10298 if (first)
10299 buffer_putc(b, ' ');
10300 else {
10301 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10302 first = 1;
10303 buffer_putstr(b, argv[i]->arg);
10304 }
10305 }
10306 }
10307 buffer_putc(b, '\0');
57d187bc 10308
d62a17ae 10309 str = buffer_getstr(b);
10310 buffer_free(b);
57d187bc 10311
d62a17ae 10312 lcom = lcommunity_str2com(str);
10313 XFREE(MTYPE_TMP, str);
10314 if (!lcom) {
10315 vty_out(vty, "%% Large-community malformed\n");
10316 return CMD_WARNING;
10317 }
57d187bc 10318
36a206db 10319 return bgp_show(vty, bgp, afi, safi,
10320 (exact ? bgp_show_type_lcommunity_exact
10321 : bgp_show_type_lcommunity),
10322 lcom, uj);
57d187bc
JS
10323}
10324
d62a17ae 10325static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10326 const char *lcom, bool exact, afi_t afi,
10327 safi_t safi, bool uj)
57d187bc 10328{
d62a17ae 10329 struct community_list *list;
57d187bc 10330
e237b0d2 10331 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10332 LARGE_COMMUNITY_LIST_MASTER);
10333 if (list == NULL) {
10334 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10335 lcom);
10336 return CMD_WARNING;
10337 }
57d187bc 10338
36a206db 10339 return bgp_show(vty, bgp, afi, safi,
10340 (exact ? bgp_show_type_lcommunity_list_exact
10341 : bgp_show_type_lcommunity_list),
d62a17ae 10342 list, uj);
fee0f4c6 10343}
10344
52951b63
DS
10345DEFUN (show_ip_bgp_large_community_list,
10346 show_ip_bgp_large_community_list_cmd,
36a206db 10347 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
10348 SHOW_STR
10349 IP_STR
10350 BGP_STR
10351 BGP_INSTANCE_HELP_STR
9bedbb1e 10352 BGP_AFI_HELP_STR
4dd6177e 10353 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10354 "Display routes matching the large-community-list\n"
10355 "large-community-list number\n"
10356 "large-community-list name\n"
36a206db 10357 "Exact match of the large-communities\n"
52951b63
DS
10358 JSON_STR)
10359{
d62a17ae 10360 char *vrf = NULL;
10361 afi_t afi = AFI_IP6;
10362 safi_t safi = SAFI_UNICAST;
10363 int idx = 0;
36a206db 10364 bool exact_match = 0;
d62a17ae 10365
10366 if (argv_find(argv, argc, "ip", &idx))
10367 afi = AFI_IP;
10368 if (argv_find(argv, argc, "view", &idx)
10369 || argv_find(argv, argc, "vrf", &idx))
10370 vrf = argv[++idx]->arg;
10371 if (argv_find(argv, argc, "ipv4", &idx)
10372 || argv_find(argv, argc, "ipv6", &idx)) {
10373 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10374 if (argv_find(argv, argc, "unicast", &idx)
10375 || argv_find(argv, argc, "multicast", &idx))
10376 safi = bgp_vty_safi_from_str(argv[idx]->text);
10377 }
10378
9f049418 10379 bool uj = use_json(argc, argv);
d62a17ae 10380
10381 struct bgp *bgp = bgp_lookup_by_name(vrf);
10382 if (bgp == NULL) {
10383 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10384 return CMD_WARNING;
10385 }
10386
10387 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10388
10389 const char *clist_number_or_name = argv[++idx]->arg;
10390
10391 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10392 exact_match = 1;
10393
10394 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10395 exact_match, afi, safi, uj);
52951b63
DS
10396}
10397DEFUN (show_ip_bgp_large_community,
10398 show_ip_bgp_large_community_cmd,
36a206db 10399 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
52951b63
DS
10400 SHOW_STR
10401 IP_STR
10402 BGP_STR
10403 BGP_INSTANCE_HELP_STR
9bedbb1e 10404 BGP_AFI_HELP_STR
4dd6177e 10405 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10406 "Display routes matching the large-communities\n"
10407 "List of large-community numbers\n"
36a206db 10408 "Exact match of the large-communities\n"
52951b63
DS
10409 JSON_STR)
10410{
d62a17ae 10411 char *vrf = NULL;
10412 afi_t afi = AFI_IP6;
10413 safi_t safi = SAFI_UNICAST;
10414 int idx = 0;
36a206db 10415 bool exact_match = 0;
d62a17ae 10416
10417 if (argv_find(argv, argc, "ip", &idx))
10418 afi = AFI_IP;
10419 if (argv_find(argv, argc, "view", &idx)
10420 || argv_find(argv, argc, "vrf", &idx))
10421 vrf = argv[++idx]->arg;
10422 if (argv_find(argv, argc, "ipv4", &idx)
10423 || argv_find(argv, argc, "ipv6", &idx)) {
10424 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
10425 if (argv_find(argv, argc, "unicast", &idx)
10426 || argv_find(argv, argc, "multicast", &idx))
10427 safi = bgp_vty_safi_from_str(argv[idx]->text);
10428 }
10429
9f049418 10430 bool uj = use_json(argc, argv);
d62a17ae 10431
10432 struct bgp *bgp = bgp_lookup_by_name(vrf);
10433 if (bgp == NULL) {
10434 vty_out(vty, "Can't find BGP instance %s\n", vrf);
10435 return CMD_WARNING;
10436 }
10437
36a206db 10438 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10439 if (argv_find(argv, argc, "exact-match", &idx))
10440 exact_match = 1;
10441 return bgp_show_lcommunity(vty, bgp, argc, argv,
10442 exact_match, afi, safi, uj);
10443 } else
d62a17ae 10444 return bgp_show(vty, bgp, afi, safi,
10445 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10446}
10447
d62a17ae 10448static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10449 safi_t safi);
e01ca200 10450
7b2ff250
DW
10451
10452/* BGP route print out function without JSON */
af462945
DS
10453DEFUN (show_ip_bgp,
10454 show_ip_bgp_cmd,
4dd6177e 10455 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10456 <dampening <parameters>\
10457 |route-map WORD\
10458 |prefix-list WORD\
10459 |filter-list WORD\
10460 |statistics\
7b2ff250
DW
10461 |community-list <(1-500)|WORD> [exact-match]\
10462 |A.B.C.D/M longer-prefixes\
10463 |X:X::X:X/M longer-prefixes\
10464 >",
718e3744 10465 SHOW_STR
10466 IP_STR
10467 BGP_STR
a636c635 10468 BGP_INSTANCE_HELP_STR
4f280b15 10469 BGP_AFI_HELP_STR
4dd6177e 10470 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10471 "Display detailed information about dampening\n"
af462945 10472 "Display detail of configured dampening parameters\n"
a636c635
DW
10473 "Display routes matching the route-map\n"
10474 "A route-map to match on\n"
10475 "Display routes conforming to the prefix-list\n"
8c3deaae 10476 "Prefix-list name\n"
a636c635
DW
10477 "Display routes conforming to the filter-list\n"
10478 "Regular expression access list name\n"
e01ca200 10479 "BGP RIB advertisement statistics\n"
a636c635
DW
10480 "Display routes matching the community-list\n"
10481 "community-list number\n"
10482 "community-list name\n"
10483 "Exact match of the communities\n"
0c7b1b01 10484 "IPv4 prefix\n"
8c3deaae 10485 "Display route and more specific routes\n"
0c7b1b01 10486 "IPv6 prefix\n"
7b2ff250 10487 "Display route and more specific routes\n")
718e3744 10488{
d62a17ae 10489 afi_t afi = AFI_IP6;
10490 safi_t safi = SAFI_UNICAST;
10491 int exact_match = 0;
d62a17ae 10492 struct bgp *bgp = NULL;
10493 int idx = 0;
10494
10495 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10496 &bgp, false);
d62a17ae 10497 if (!idx)
10498 return CMD_WARNING;
10499
d62a17ae 10500 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10501 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10502 return bgp_show_dampening_parameters(vty, afi, safi);
10503 }
c016b6c7 10504
d62a17ae 10505 if (argv_find(argv, argc, "prefix-list", &idx))
10506 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10507 safi, bgp_show_type_prefix_list);
10508
10509 if (argv_find(argv, argc, "filter-list", &idx))
10510 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10511 safi, bgp_show_type_filter_list);
10512
10513 if (argv_find(argv, argc, "statistics", &idx))
10514 return bgp_table_stats(vty, bgp, afi, safi);
10515
10516 if (argv_find(argv, argc, "route-map", &idx))
10517 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10518 safi, bgp_show_type_route_map);
10519
d62a17ae 10520 if (argv_find(argv, argc, "community-list", &idx)) {
10521 const char *clist_number_or_name = argv[++idx]->arg;
10522 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10523 exact_match = 1;
10524 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10525 exact_match, afi, safi);
10526 }
10527 /* prefix-longer */
10528 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10529 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10530 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10531 safi,
10532 bgp_show_type_prefix_longer);
10533
7b2ff250
DW
10534 return CMD_WARNING;
10535}
10536
10537/* BGP route print out function with JSON */
10538DEFUN (show_ip_bgp_json,
10539 show_ip_bgp_json_cmd,
10540 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10541 [cidr-only\
10542 |dampening <flap-statistics|dampened-paths>\
10543 |community [AA:NN|local-AS|no-advertise|no-export\
10544 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10545 |accept-own|accept-own-nexthop|route-filter-v6\
10546 |route-filter-v4|route-filter-translated-v6\
10547 |route-filter-translated-v4] [exact-match]\
10548 ] [json]",
7b2ff250
DW
10549 SHOW_STR
10550 IP_STR
10551 BGP_STR
10552 BGP_INSTANCE_HELP_STR
10553 BGP_AFI_HELP_STR
10554 BGP_SAFI_WITH_LABEL_HELP_STR
10555 "Display only routes with non-natural netmasks\n"
10556 "Display detailed information about dampening\n"
10557 "Display flap statistics of routes\n"
10558 "Display paths suppressed due to dampening\n"
10559 "Display routes matching the communities\n"
d0086e8e
AD
10560 COMMUNITY_AANN_STR
10561 "Do not send outside local AS (well-known community)\n"
10562 "Do not advertise to any peer (well-known community)\n"
10563 "Do not export to next AS (well-known community)\n"
10564 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10565 "Do not export to any peer (well-known community)\n"
10566 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10567 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10568 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10569 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10570 "Should accept VPN route with local nexthop (well-known community)\n"
10571 "RT VPNv6 route filtering (well-known community)\n"
10572 "RT VPNv4 route filtering (well-known community)\n"
10573 "RT translated VPNv6 route filtering (well-known community)\n"
10574 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10575 "Exact match of the communities\n"
7b2ff250
DW
10576 JSON_STR)
10577{
10578 afi_t afi = AFI_IP6;
10579 safi_t safi = SAFI_UNICAST;
10580 enum bgp_show_type sh_type = bgp_show_type_normal;
10581 struct bgp *bgp = NULL;
10582 int idx = 0;
d0086e8e 10583 int exact_match = 0;
9f049418
DS
10584 bool uj = use_json(argc, argv);
10585
10586 if (uj)
10587 argc--;
7b2ff250
DW
10588
10589 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10590 &bgp, uj);
7b2ff250
DW
10591 if (!idx)
10592 return CMD_WARNING;
10593
7b2ff250
DW
10594 if (argv_find(argv, argc, "cidr-only", &idx))
10595 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10596 NULL, uj);
10597
10598 if (argv_find(argv, argc, "dampening", &idx)) {
10599 if (argv_find(argv, argc, "dampened-paths", &idx))
10600 return bgp_show(vty, bgp, afi, safi,
10601 bgp_show_type_dampend_paths, NULL, uj);
10602 else if (argv_find(argv, argc, "flap-statistics", &idx))
10603 return bgp_show(vty, bgp, afi, safi,
10604 bgp_show_type_flap_statistics, NULL,
10605 uj);
10606 }
10607
10608 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10609 char *maybecomm = NULL;
cf4898bc 10610 char *community = NULL;
d0086e8e 10611
79bc257a
RW
10612 if (idx + 1 < argc) {
10613 if (argv[idx + 1]->type == VARIABLE_TKN)
10614 maybecomm = argv[idx + 1]->arg;
10615 else
10616 maybecomm = argv[idx + 1]->text;
10617 }
10618
cf4898bc
QY
10619 if (maybecomm && !strmatch(maybecomm, "json")
10620 && !strmatch(maybecomm, "exact-match"))
10621 community = maybecomm;
d0086e8e 10622
cf4898bc
QY
10623 if (argv_find(argv, argc, "exact-match", &idx))
10624 exact_match = 1;
d0086e8e 10625
cf4898bc
QY
10626 if (community)
10627 return bgp_show_community(vty, bgp, community,
10628 exact_match, afi, safi, uj);
10629 else
d0086e8e 10630 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10631 bgp_show_type_community_all, NULL,
10632 uj));
7b2ff250 10633 }
d0086e8e 10634
1ae44dfc 10635 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10636}
47fc97cc 10637
718e3744 10638DEFUN (show_ip_bgp_route,
10639 show_ip_bgp_route_cmd,
4dd6177e 10640 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10641 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10642 SHOW_STR
10643 IP_STR
10644 BGP_STR
a636c635 10645 BGP_INSTANCE_HELP_STR
4f280b15 10646 BGP_AFI_HELP_STR
4dd6177e 10647 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10648 "Network in the BGP routing table to display\n"
0c7b1b01 10649 "IPv4 prefix\n"
8c3deaae 10650 "Network in the BGP routing table to display\n"
0c7b1b01 10651 "IPv6 prefix\n"
4092b06c 10652 "Display only the bestpath\n"
b05a1c8b 10653 "Display only multipaths\n"
9973d184 10654 JSON_STR)
4092b06c 10655{
d62a17ae 10656 int prefix_check = 0;
ae19d7dd 10657
d62a17ae 10658 afi_t afi = AFI_IP6;
10659 safi_t safi = SAFI_UNICAST;
10660 char *prefix = NULL;
10661 struct bgp *bgp = NULL;
10662 enum bgp_path_type path_type;
9f049418 10663 bool uj = use_json(argc, argv);
b05a1c8b 10664
d62a17ae 10665 int idx = 0;
ae19d7dd 10666
d62a17ae 10667 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10668 &bgp, uj);
d62a17ae 10669 if (!idx)
10670 return CMD_WARNING;
c41247f5 10671
d62a17ae 10672 if (!bgp) {
10673 vty_out(vty,
10674 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10675 return CMD_WARNING;
10676 }
a636c635 10677
d62a17ae 10678 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10679 if (argv_find(argv, argc, "A.B.C.D", &idx)
10680 || argv_find(argv, argc, "X:X::X:X", &idx))
10681 prefix_check = 0;
10682 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10683 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10684 prefix_check = 1;
10685
10686 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10687 && afi != AFI_IP6) {
10688 vty_out(vty,
10689 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10690 return CMD_WARNING;
10691 }
10692 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10693 && afi != AFI_IP) {
10694 vty_out(vty,
10695 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10696 return CMD_WARNING;
10697 }
10698
10699 prefix = argv[idx]->arg;
10700
10701 /* [<bestpath|multipath>] */
10702 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10703 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10704 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10705 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10706 else
360660c6 10707 path_type = BGP_PATH_SHOW_ALL;
a636c635 10708
d62a17ae 10709 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10710 path_type, uj);
4092b06c
DS
10711}
10712
8c3deaae
QY
10713DEFUN (show_ip_bgp_regexp,
10714 show_ip_bgp_regexp_cmd,
3e5b31b3 10715 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
10716 SHOW_STR
10717 IP_STR
10718 BGP_STR
b00b230a 10719 BGP_INSTANCE_HELP_STR
4f280b15 10720 BGP_AFI_HELP_STR
4dd6177e 10721 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10722 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
10723 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10724 JSON_STR)
8c3deaae 10725{
d62a17ae 10726 afi_t afi = AFI_IP6;
10727 safi_t safi = SAFI_UNICAST;
10728 struct bgp *bgp = NULL;
3e5b31b3
DA
10729 bool uj = use_json(argc, argv);
10730 char *regstr = NULL;
8c3deaae 10731
d62a17ae 10732 int idx = 0;
10733 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10734 &bgp, false);
d62a17ae 10735 if (!idx)
10736 return CMD_WARNING;
8c3deaae 10737
d62a17ae 10738 // get index of regex
3e5b31b3
DA
10739 if (argv_find(argv, argc, "REGEX", &idx))
10740 regstr = argv[idx]->arg;
8c3deaae 10741
5f71d11c 10742 assert(regstr);
3e5b31b3
DA
10743 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
10744 bgp_show_type_regexp, uj);
8c3deaae
QY
10745}
10746
a636c635
DW
10747DEFUN (show_ip_bgp_instance_all,
10748 show_ip_bgp_instance_all_cmd,
4dd6177e 10749 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10750 SHOW_STR
a636c635 10751 IP_STR
4092b06c 10752 BGP_STR
a636c635 10753 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10754 BGP_AFI_HELP_STR
4dd6177e 10755 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10756 JSON_STR)
4092b06c 10757{
d62a17ae 10758 afi_t afi = AFI_IP;
10759 safi_t safi = SAFI_UNICAST;
10760 struct bgp *bgp = NULL;
d62a17ae 10761 int idx = 0;
9f049418 10762 bool uj = use_json(argc, argv);
ae19d7dd 10763
d62a17ae 10764 if (uj)
10765 argc--;
e3e29b32 10766
9f049418
DS
10767 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10768 &bgp, uj);
10769 if (!idx)
10770 return CMD_WARNING;
10771
d62a17ae 10772 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10773 return CMD_SUCCESS;
e3e29b32
LB
10774}
10775
a4d82a8a 10776static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10777 afi_t afi, safi_t safi, enum bgp_show_type type,
10778 bool use_json)
718e3744 10779{
d62a17ae 10780 regex_t *regex;
10781 int rc;
e3e29b32 10782
c3900853 10783 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 10784 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
10785 regstr);
10786 return CMD_WARNING_CONFIG_FAILED;
10787 }
10788
d62a17ae 10789 regex = bgp_regcomp(regstr);
10790 if (!regex) {
10791 vty_out(vty, "Can't compile regexp %s\n", regstr);
10792 return CMD_WARNING;
10793 }
a636c635 10794
3e5b31b3 10795 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 10796 bgp_regex_free(regex);
10797 return rc;
e3e29b32
LB
10798}
10799
d62a17ae 10800static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10801 const char *prefix_list_str, afi_t afi,
10802 safi_t safi, enum bgp_show_type type)
e3e29b32 10803{
d62a17ae 10804 struct prefix_list *plist;
718e3744 10805
d62a17ae 10806 plist = prefix_list_lookup(afi, prefix_list_str);
10807 if (plist == NULL) {
10808 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10809 prefix_list_str);
10810 return CMD_WARNING;
10811 }
718e3744 10812
d62a17ae 10813 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10814}
10815
d62a17ae 10816static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10817 const char *filter, afi_t afi, safi_t safi,
10818 enum bgp_show_type type)
4092b06c 10819{
d62a17ae 10820 struct as_list *as_list;
718e3744 10821
d62a17ae 10822 as_list = as_list_lookup(filter);
10823 if (as_list == NULL) {
10824 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10825 filter);
10826 return CMD_WARNING;
10827 }
a636c635 10828
d62a17ae 10829 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10830}
10831
d62a17ae 10832static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10833 const char *rmap_str, afi_t afi, safi_t safi,
10834 enum bgp_show_type type)
718e3744 10835{
d62a17ae 10836 struct route_map *rmap;
bb46e94f 10837
d62a17ae 10838 rmap = route_map_lookup_by_name(rmap_str);
10839 if (!rmap) {
10840 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10841 return CMD_WARNING;
10842 }
10843
10844 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10845}
10846
7f323236
DW
10847static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10848 const char *comstr, int exact, afi_t afi,
9f049418 10849 safi_t safi, bool use_json)
d62a17ae 10850{
10851 struct community *com;
d62a17ae 10852 int ret = 0;
10853
7f323236 10854 com = community_str2com(comstr);
d62a17ae 10855 if (!com) {
7f323236 10856 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10857 return CMD_WARNING;
10858 }
10859
10860 ret = bgp_show(vty, bgp, afi, safi,
10861 (exact ? bgp_show_type_community_exact
10862 : bgp_show_type_community),
d0086e8e 10863 com, use_json);
3c1f53de 10864 community_free(&com);
46c3ce83 10865
d62a17ae 10866 return ret;
718e3744 10867}
10868
d62a17ae 10869static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10870 const char *com, int exact, afi_t afi,
10871 safi_t safi)
50ef26d4 10872{
d62a17ae 10873 struct community_list *list;
50ef26d4 10874
e237b0d2 10875 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10876 if (list == NULL) {
10877 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10878 return CMD_WARNING;
10879 }
718e3744 10880
d62a17ae 10881 return bgp_show(vty, bgp, afi, safi,
10882 (exact ? bgp_show_type_community_list_exact
10883 : bgp_show_type_community_list),
10884 list, 0);
50ef26d4 10885}
10886
d62a17ae 10887static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10888 const char *prefix, afi_t afi, safi_t safi,
10889 enum bgp_show_type type)
718e3744 10890{
d62a17ae 10891 int ret;
10892 struct prefix *p;
47fc97cc 10893
d62a17ae 10894 p = prefix_new();
95cbbd2a 10895
d62a17ae 10896 ret = str2prefix(prefix, p);
10897 if (!ret) {
10898 vty_out(vty, "%% Malformed Prefix\n");
10899 return CMD_WARNING;
10900 }
47e9b292 10901
d62a17ae 10902 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 10903 prefix_free(&p);
d62a17ae 10904 return ret;
10905}
10906
d62a17ae 10907enum bgp_stats {
10908 BGP_STATS_MAXBITLEN = 0,
10909 BGP_STATS_RIB,
10910 BGP_STATS_PREFIXES,
10911 BGP_STATS_TOTPLEN,
10912 BGP_STATS_UNAGGREGATEABLE,
10913 BGP_STATS_MAX_AGGREGATEABLE,
10914 BGP_STATS_AGGREGATES,
10915 BGP_STATS_SPACE,
10916 BGP_STATS_ASPATH_COUNT,
10917 BGP_STATS_ASPATH_MAXHOPS,
10918 BGP_STATS_ASPATH_TOTHOPS,
10919 BGP_STATS_ASPATH_MAXSIZE,
10920 BGP_STATS_ASPATH_TOTSIZE,
10921 BGP_STATS_ASN_HIGHEST,
10922 BGP_STATS_MAX,
a636c635 10923};
2815e61f 10924
2b64873d 10925static const char *const table_stats_strs[] = {
9d303b37
DL
10926 [BGP_STATS_PREFIXES] = "Total Prefixes",
10927 [BGP_STATS_TOTPLEN] = "Average prefix length",
10928 [BGP_STATS_RIB] = "Total Advertisements",
10929 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10930 [BGP_STATS_MAX_AGGREGATEABLE] =
10931 "Maximum aggregateable prefixes",
10932 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10933 [BGP_STATS_SPACE] = "Address space advertised",
10934 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10935 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10936 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10937 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10938 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10939 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10940 [BGP_STATS_MAX] = NULL,
a636c635 10941};
2815e61f 10942
d62a17ae 10943struct bgp_table_stats {
10944 struct bgp_table *table;
10945 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10946 double total_space;
ff7924f6
PJ
10947};
10948
a636c635
DW
10949#if 0
10950#define TALLY_SIGFIG 100000
10951static unsigned long
10952ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10953{
a636c635
DW
10954 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10955 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10956 unsigned long ret = newtot / count;
07d0c4ed 10957
a636c635
DW
10958 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
10959 return ret + 1;
10960 else
10961 return ret;
10962}
10963#endif
ff7924f6 10964
9c14ec72
RW
10965static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
10966 struct bgp_table_stats *ts, unsigned int space)
2815e61f 10967{
9c14ec72
RW
10968 struct bgp_node *prn = bgp_node_parent_nolock(rn);
10969 struct bgp_path_info *pi;
d62a17ae 10970
9c14ec72
RW
10971 if (rn == top)
10972 return;
d62a17ae 10973
9c14ec72
RW
10974 if (!bgp_node_has_bgp_path_info_data(rn))
10975 return;
d62a17ae 10976
9c14ec72
RW
10977 ts->counts[BGP_STATS_PREFIXES]++;
10978 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 10979
a636c635
DW
10980#if 0
10981 ts->counts[BGP_STATS_AVGPLEN]
10982 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
10983 ts->counts[BGP_STATS_AVGPLEN],
10984 rn->p.prefixlen);
10985#endif
d62a17ae 10986
9c14ec72
RW
10987 /* check if the prefix is included by any other announcements */
10988 while (prn && !bgp_node_has_bgp_path_info_data(prn))
10989 prn = bgp_node_parent_nolock(prn);
d62a17ae 10990
9c14ec72
RW
10991 if (prn == NULL || prn == top) {
10992 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
10993 /* announced address space */
10994 if (space)
10995 ts->total_space += pow(2.0, space - rn->p.prefixlen);
10996 } else if (bgp_node_has_bgp_path_info_data(prn))
10997 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 10998
9c14ec72
RW
10999
11000 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
11001 ts->counts[BGP_STATS_RIB]++;
11002
05864da7
DS
11003 if (CHECK_FLAG(pi->attr->flag,
11004 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11005 ts->counts[BGP_STATS_AGGREGATES]++;
11006
11007 /* as-path stats */
05864da7 11008 if (pi->attr->aspath) {
9c14ec72
RW
11009 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11010 unsigned int size = aspath_size(pi->attr->aspath);
11011 as_t highest = aspath_highest(pi->attr->aspath);
11012
11013 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11014
11015 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11016 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11017
11018 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11019 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11020
11021 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11022 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11023#if 0
07d0c4ed 11024 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11025 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11026 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11027 hops);
11028 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11029 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11030 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11031 size);
11032#endif
9c14ec72
RW
11033 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11034 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11035 }
11036 }
11037}
11038
11039static int bgp_table_stats_walker(struct thread *t)
11040{
11041 struct bgp_node *rn, *nrn;
11042 struct bgp_node *top;
11043 struct bgp_table_stats *ts = THREAD_ARG(t);
11044 unsigned int space = 0;
11045
11046 if (!(top = bgp_table_top(ts->table)))
11047 return 0;
11048
11049 switch (ts->table->afi) {
11050 case AFI_IP:
11051 space = IPV4_MAX_BITLEN;
11052 break;
11053 case AFI_IP6:
11054 space = IPV6_MAX_BITLEN;
11055 break;
11056 default:
11057 return 0;
11058 }
11059
11060 ts->counts[BGP_STATS_MAXBITLEN] = space;
11061
11062 for (rn = top; rn; rn = bgp_route_next(rn)) {
11063 if (ts->table->safi == SAFI_MPLS_VPN) {
11064 struct bgp_table *table;
11065
11066 table = bgp_node_get_bgp_table_info(rn);
11067 if (!table)
11068 continue;
11069
11070 top = bgp_table_top(table);
11071 for (nrn = bgp_table_top(table); nrn;
11072 nrn = bgp_route_next(nrn))
11073 bgp_table_stats_rn(nrn, top, ts, space);
11074 } else {
11075 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 11076 }
11077 }
9c14ec72 11078
d62a17ae 11079 return 0;
2815e61f 11080}
ff7924f6 11081
d62a17ae 11082static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11083 safi_t safi)
2815e61f 11084{
d62a17ae 11085 struct bgp_table_stats ts;
11086 unsigned int i;
019386c2 11087
d62a17ae 11088 if (!bgp->rib[afi][safi]) {
11089 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11090 afi, safi);
11091 return CMD_WARNING;
11092 }
019386c2 11093
5cb5f4d0 11094 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 11095
d62a17ae 11096 /* labeled-unicast routes live in the unicast table */
11097 if (safi == SAFI_LABELED_UNICAST)
11098 safi = SAFI_UNICAST;
019386c2 11099
d62a17ae 11100 memset(&ts, 0, sizeof(ts));
11101 ts.table = bgp->rib[afi][safi];
11102 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11103
d62a17ae 11104 for (i = 0; i < BGP_STATS_MAX; i++) {
11105 if (!table_stats_strs[i])
11106 continue;
11107
11108 switch (i) {
a636c635
DW
11109#if 0
11110 case BGP_STATS_ASPATH_AVGHOPS:
11111 case BGP_STATS_ASPATH_AVGSIZE:
11112 case BGP_STATS_AVGPLEN:
11113 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11114 vty_out (vty, "%12.2f",
11115 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11116 break;
11117#endif
d62a17ae 11118 case BGP_STATS_ASPATH_TOTHOPS:
11119 case BGP_STATS_ASPATH_TOTSIZE:
11120 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11121 vty_out(vty, "%12.2f",
11122 ts.counts[i]
11123 ? (float)ts.counts[i]
11124 / (float)ts.counts
11125 [BGP_STATS_ASPATH_COUNT]
11126 : 0);
11127 break;
11128 case BGP_STATS_TOTPLEN:
11129 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11130 vty_out(vty, "%12.2f",
11131 ts.counts[i]
11132 ? (float)ts.counts[i]
11133 / (float)ts.counts
11134 [BGP_STATS_PREFIXES]
11135 : 0);
11136 break;
11137 case BGP_STATS_SPACE:
11138 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
11139 vty_out(vty, "%12g\n", ts.total_space);
11140
11141 if (afi == AFI_IP6) {
11142 vty_out(vty, "%30s: ", "/32 equivalent ");
11143 vty_out(vty, "%12g\n",
a4d82a8a 11144 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
11145 vty_out(vty, "%30s: ", "/48 equivalent ");
11146 vty_out(vty, "%12g\n",
a4d82a8a 11147 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
11148 } else {
11149 vty_out(vty, "%30s: ", "% announced ");
11150 vty_out(vty, "%12.2f\n",
11151 ts.total_space * 100. * pow(2.0, -32));
11152 vty_out(vty, "%30s: ", "/8 equivalent ");
11153 vty_out(vty, "%12.2f\n",
a4d82a8a 11154 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
11155 vty_out(vty, "%30s: ", "/24 equivalent ");
11156 vty_out(vty, "%12.2f\n",
a4d82a8a 11157 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 11158 }
d62a17ae 11159 break;
11160 default:
11161 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11162 vty_out(vty, "%12llu", ts.counts[i]);
11163 }
ff7924f6 11164
d62a17ae 11165 vty_out(vty, "\n");
11166 }
11167 return CMD_SUCCESS;
11168}
11169
11170enum bgp_pcounts {
11171 PCOUNT_ADJ_IN = 0,
11172 PCOUNT_DAMPED,
11173 PCOUNT_REMOVED,
11174 PCOUNT_HISTORY,
11175 PCOUNT_STALE,
11176 PCOUNT_VALID,
11177 PCOUNT_ALL,
11178 PCOUNT_COUNTED,
11179 PCOUNT_PFCNT, /* the figure we display to users */
11180 PCOUNT_MAX,
a636c635 11181};
718e3744 11182
2b64873d 11183static const char *const pcount_strs[] = {
9d303b37
DL
11184 [PCOUNT_ADJ_IN] = "Adj-in",
11185 [PCOUNT_DAMPED] = "Damped",
11186 [PCOUNT_REMOVED] = "Removed",
11187 [PCOUNT_HISTORY] = "History",
11188 [PCOUNT_STALE] = "Stale",
11189 [PCOUNT_VALID] = "Valid",
11190 [PCOUNT_ALL] = "All RIB",
11191 [PCOUNT_COUNTED] = "PfxCt counted",
11192 [PCOUNT_PFCNT] = "Useable",
11193 [PCOUNT_MAX] = NULL,
a636c635 11194};
718e3744 11195
d62a17ae 11196struct peer_pcounts {
11197 unsigned int count[PCOUNT_MAX];
11198 const struct peer *peer;
11199 const struct bgp_table *table;
54317cba 11200 safi_t safi;
a636c635 11201};
47fc97cc 11202
54317cba
JW
11203static void bgp_peer_count_proc(struct bgp_node *rn,
11204 struct peer_pcounts *pc)
d62a17ae 11205{
54317cba
JW
11206 const struct bgp_adj_in *ain;
11207 const struct bgp_path_info *pi;
d62a17ae 11208 const struct peer *peer = pc->peer;
11209
54317cba
JW
11210 for (ain = rn->adj_in; ain; ain = ain->next)
11211 if (ain->peer == peer)
11212 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11213
54317cba 11214 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11215
54317cba
JW
11216 if (pi->peer != peer)
11217 continue;
d62a17ae 11218
54317cba 11219 pc->count[PCOUNT_ALL]++;
d62a17ae 11220
54317cba
JW
11221 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11222 pc->count[PCOUNT_DAMPED]++;
11223 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11224 pc->count[PCOUNT_HISTORY]++;
11225 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11226 pc->count[PCOUNT_REMOVED]++;
11227 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11228 pc->count[PCOUNT_STALE]++;
11229 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11230 pc->count[PCOUNT_VALID]++;
11231 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11232 pc->count[PCOUNT_PFCNT]++;
11233
11234 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11235 pc->count[PCOUNT_COUNTED]++;
11236 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11237 flog_err(
11238 EC_LIB_DEVELOPMENT,
11239 "Attempting to count but flags say it is unusable");
11240 } else {
40381db7 11241 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11242 flog_err(
11243 EC_LIB_DEVELOPMENT,
11244 "Not counted but flags say we should");
d62a17ae 11245 }
11246 }
54317cba
JW
11247}
11248
11249static int bgp_peer_count_walker(struct thread *t)
11250{
11251 struct bgp_node *rn, *rm;
11252 const struct bgp_table *table;
11253 struct peer_pcounts *pc = THREAD_ARG(t);
11254
11255 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11256 || pc->safi == SAFI_EVPN) {
11257 /* Special handling for 2-level routing tables. */
11258 for (rn = bgp_table_top(pc->table); rn;
11259 rn = bgp_route_next(rn)) {
11260 table = bgp_node_get_bgp_table_info(rn);
11261 if (table != NULL)
11262 for (rm = bgp_table_top(table); rm;
11263 rm = bgp_route_next(rm))
11264 bgp_peer_count_proc(rm, pc);
11265 }
11266 } else
11267 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11268 bgp_peer_count_proc(rn, pc);
11269
d62a17ae 11270 return 0;
718e3744 11271}
11272
d62a17ae 11273static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11274 safi_t safi, bool use_json)
856ca177 11275{
d62a17ae 11276 struct peer_pcounts pcounts = {.peer = peer};
11277 unsigned int i;
11278 json_object *json = NULL;
11279 json_object *json_loop = NULL;
856ca177 11280
d62a17ae 11281 if (use_json) {
11282 json = json_object_new_object();
11283 json_loop = json_object_new_object();
11284 }
718e3744 11285
d62a17ae 11286 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11287 || !peer->bgp->rib[afi][safi]) {
11288 if (use_json) {
11289 json_object_string_add(
11290 json, "warning",
11291 "No such neighbor or address family");
11292 vty_out(vty, "%s\n", json_object_to_json_string(json));
11293 json_object_free(json);
11294 } else
11295 vty_out(vty, "%% No such neighbor or address family\n");
11296
11297 return CMD_WARNING;
11298 }
2a71e9ce 11299
d62a17ae 11300 memset(&pcounts, 0, sizeof(pcounts));
11301 pcounts.peer = peer;
11302 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11303 pcounts.safi = safi;
d62a17ae 11304
11305 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11306 * stats for the thread-walk (i.e. ensure this can't be blamed on
11307 * on just vty_read()).
11308 */
d62a17ae 11309 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11310
11311 if (use_json) {
11312 json_object_string_add(json, "prefixCountsFor", peer->host);
11313 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11314 get_afi_safi_str(afi, safi, true));
d62a17ae 11315 json_object_int_add(json, "pfxCounter",
11316 peer->pcount[afi][safi]);
11317
11318 for (i = 0; i < PCOUNT_MAX; i++)
11319 json_object_int_add(json_loop, pcount_strs[i],
11320 pcounts.count[i]);
11321
11322 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11323
11324 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11325 json_object_string_add(json, "pfxctDriftFor",
11326 peer->host);
11327 json_object_string_add(
11328 json, "recommended",
11329 "Please report this bug, with the above command output");
11330 }
996c9314
LB
11331 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11332 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11333 json_object_free(json);
11334 } else {
11335
11336 if (peer->hostname
11337 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
11338 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11339 peer->hostname, peer->host,
5cb5f4d0 11340 get_afi_safi_str(afi, safi, false));
d62a17ae 11341 } else {
11342 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11343 get_afi_safi_str(afi, safi, false));
d62a17ae 11344 }
11345
a0a87037 11346 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11347 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11348
11349 for (i = 0; i < PCOUNT_MAX; i++)
11350 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11351 pcounts.count[i]);
11352
11353 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11354 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11355 vty_out(vty,
11356 "Please report this bug, with the above command output\n");
11357 }
11358 }
11359
11360 return CMD_SUCCESS;
718e3744 11361}
11362
a636c635
DW
11363DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11364 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11365 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11366 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11367 SHOW_STR
11368 IP_STR
11369 BGP_STR
8386ac43 11370 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11371 BGP_AFI_HELP_STR
11372 BGP_SAFI_HELP_STR
0b16f239
DS
11373 "Detailed information on TCP and BGP neighbor connections\n"
11374 "Neighbor to display information about\n"
11375 "Neighbor to display information about\n"
91d37724 11376 "Neighbor on BGP configured interface\n"
a636c635 11377 "Display detailed prefix count information\n"
9973d184 11378 JSON_STR)
0b16f239 11379{
d62a17ae 11380 afi_t afi = AFI_IP6;
11381 safi_t safi = SAFI_UNICAST;
11382 struct peer *peer;
11383 int idx = 0;
11384 struct bgp *bgp = NULL;
9f049418
DS
11385 bool uj = use_json(argc, argv);
11386
11387 if (uj)
11388 argc--;
856ca177 11389
d62a17ae 11390 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11391 &bgp, uj);
d62a17ae 11392 if (!idx)
11393 return CMD_WARNING;
0b16f239 11394
d62a17ae 11395 argv_find(argv, argc, "neighbors", &idx);
11396 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11397 if (!peer)
11398 return CMD_WARNING;
bb46e94f 11399
29c8d9da 11400 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11401}
0b16f239 11402
d6902373
PG
11403#ifdef KEEP_OLD_VPN_COMMANDS
11404DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11405 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11406 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11407 SHOW_STR
11408 IP_STR
11409 BGP_STR
d6902373 11410 BGP_VPNVX_HELP_STR
91d37724 11411 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11412 "Detailed information on TCP and BGP neighbor connections\n"
11413 "Neighbor to display information about\n"
11414 "Neighbor to display information about\n"
91d37724 11415 "Neighbor on BGP configured interface\n"
a636c635 11416 "Display detailed prefix count information\n"
9973d184 11417 JSON_STR)
a636c635 11418{
d62a17ae 11419 int idx_peer = 6;
11420 struct peer *peer;
9f049418 11421 bool uj = use_json(argc, argv);
a636c635 11422
d62a17ae 11423 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11424 if (!peer)
11425 return CMD_WARNING;
11426
11427 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11428}
11429
d6902373
PG
11430DEFUN (show_ip_bgp_vpn_all_route_prefix,
11431 show_ip_bgp_vpn_all_route_prefix_cmd,
11432 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11433 SHOW_STR
11434 IP_STR
11435 BGP_STR
d6902373 11436 BGP_VPNVX_HELP_STR
91d37724
QY
11437 "Display information about all VPNv4 NLRIs\n"
11438 "Network in the BGP routing table to display\n"
3a2d747c 11439 "Network in the BGP routing table to display\n"
9973d184 11440 JSON_STR)
91d37724 11441{
d62a17ae 11442 int idx = 0;
11443 char *network = NULL;
11444 struct bgp *bgp = bgp_get_default();
11445 if (!bgp) {
11446 vty_out(vty, "Can't find default instance\n");
11447 return CMD_WARNING;
11448 }
87e34b58 11449
d62a17ae 11450 if (argv_find(argv, argc, "A.B.C.D", &idx))
11451 network = argv[idx]->arg;
11452 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11453 network = argv[idx]->arg;
11454 else {
11455 vty_out(vty, "Unable to figure out Network\n");
11456 return CMD_WARNING;
11457 }
87e34b58 11458
d62a17ae 11459 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11460 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11461}
d6902373 11462#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11463
44c69747
LK
11464DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11465 show_bgp_l2vpn_evpn_route_prefix_cmd,
11466 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11467 SHOW_STR
4c63a661
PG
11468 BGP_STR
11469 L2VPN_HELP_STR
11470 EVPN_HELP_STR
44c69747
LK
11471 "Network in the BGP routing table to display\n"
11472 "Network in the BGP routing table to display\n"
4c63a661
PG
11473 "Network in the BGP routing table to display\n"
11474 "Network in the BGP routing table to display\n"
11475 JSON_STR)
11476{
d62a17ae 11477 int idx = 0;
11478 char *network = NULL;
44c69747 11479 int prefix_check = 0;
a636c635 11480
44c69747
LK
11481 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11482 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11483 network = argv[idx]->arg;
44c69747 11484 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11485 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11486 network = argv[idx]->arg;
44c69747
LK
11487 prefix_check = 1;
11488 } else {
d62a17ae 11489 vty_out(vty, "Unable to figure out Network\n");
11490 return CMD_WARNING;
11491 }
44c69747
LK
11492 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11493 prefix_check, BGP_PATH_SHOW_ALL,
11494 use_json(argc, argv));
d62a17ae 11495}
11496
11497static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11498 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11499 const char *rmap_name, bool use_json,
6392aaa6 11500 json_object *json)
d62a17ae 11501{
11502 struct bgp_table *table;
11503 struct bgp_adj_in *ain;
11504 struct bgp_adj_out *adj;
11505 unsigned long output_count;
11506 unsigned long filtered_count;
11507 struct bgp_node *rn;
11508 int header1 = 1;
11509 struct bgp *bgp;
11510 int header2 = 1;
11511 struct attr attr;
11512 int ret;
11513 struct update_subgroup *subgrp;
11514 json_object *json_scode = NULL;
11515 json_object *json_ocode = NULL;
11516 json_object *json_ar = NULL;
11517 struct peer_af *paf;
f99def61 11518 bool route_filtered;
d62a17ae 11519
11520 if (use_json) {
11521 json_scode = json_object_new_object();
11522 json_ocode = json_object_new_object();
11523 json_ar = json_object_new_object();
11524
11525 json_object_string_add(json_scode, "suppressed", "s");
11526 json_object_string_add(json_scode, "damped", "d");
11527 json_object_string_add(json_scode, "history", "h");
11528 json_object_string_add(json_scode, "valid", "*");
11529 json_object_string_add(json_scode, "best", ">");
11530 json_object_string_add(json_scode, "multipath", "=");
11531 json_object_string_add(json_scode, "internal", "i");
11532 json_object_string_add(json_scode, "ribFailure", "r");
11533 json_object_string_add(json_scode, "stale", "S");
11534 json_object_string_add(json_scode, "removed", "R");
11535
11536 json_object_string_add(json_ocode, "igp", "i");
11537 json_object_string_add(json_ocode, "egp", "e");
11538 json_object_string_add(json_ocode, "incomplete", "?");
11539 }
a636c635 11540
d62a17ae 11541 bgp = peer->bgp;
a636c635 11542
d62a17ae 11543 if (!bgp) {
11544 if (use_json) {
11545 json_object_string_add(json, "alert", "no BGP");
11546 vty_out(vty, "%s\n", json_object_to_json_string(json));
11547 json_object_free(json);
11548 } else
11549 vty_out(vty, "%% No bgp\n");
11550 return;
11551 }
a636c635 11552
c512a642
EDP
11553 /* labeled-unicast routes live in the unicast table */
11554 if (safi == SAFI_LABELED_UNICAST)
11555 table = bgp->rib[afi][SAFI_UNICAST];
11556 else
11557 table = bgp->rib[afi][safi];
d62a17ae 11558
11559 output_count = filtered_count = 0;
11560 subgrp = peer_subgroup(peer, afi, safi);
11561
6392aaa6 11562 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11563 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11564 if (use_json) {
11565 json_object_int_add(json, "bgpTableVersion",
11566 table->version);
11567 json_object_string_add(json, "bgpLocalRouterId",
11568 inet_ntoa(bgp->router_id));
01eced22
AD
11569 json_object_int_add(json, "defaultLocPrf",
11570 bgp->default_local_pref);
11571 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11572 json_object_object_add(json, "bgpStatusCodes",
11573 json_scode);
11574 json_object_object_add(json, "bgpOriginCodes",
11575 json_ocode);
07d0c4ed
DA
11576 json_object_string_add(
11577 json, "bgpOriginatingDefaultNetwork",
11578 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11579 } else {
996c9314 11580 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11581 ", local router ID is %s, vrf id ",
d62a17ae 11582 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11583 if (bgp->vrf_id == VRF_UNKNOWN)
11584 vty_out(vty, "%s", VRFID_NONE_STR);
11585 else
11586 vty_out(vty, "%u", bgp->vrf_id);
11587 vty_out(vty, "\n");
01eced22
AD
11588 vty_out(vty, "Default local pref %u, ",
11589 bgp->default_local_pref);
11590 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11591 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11592 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11593 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11594
07d0c4ed
DA
11595 vty_out(vty, "Originating default network %s\n\n",
11596 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11597 }
11598 header1 = 0;
11599 }
a636c635 11600
d62a17ae 11601 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11602 if (type == bgp_show_adj_route_received
11603 || type == bgp_show_adj_route_filtered) {
d62a17ae 11604 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11605 if (ain->peer != peer)
ea47320b 11606 continue;
6392aaa6 11607
ea47320b
DL
11608 if (header1) {
11609 if (use_json) {
11610 json_object_int_add(
60466a63 11611 json, "bgpTableVersion",
ea47320b
DL
11612 0);
11613 json_object_string_add(
11614 json,
11615 "bgpLocalRouterId",
11616 inet_ntoa(
11617 bgp->router_id));
01eced22
AD
11618 json_object_int_add(json,
11619 "defaultLocPrf",
11620 bgp->default_local_pref);
11621 json_object_int_add(json,
11622 "localAS", bgp->as);
ea47320b 11623 json_object_object_add(
60466a63 11624 json, "bgpStatusCodes",
ea47320b
DL
11625 json_scode);
11626 json_object_object_add(
60466a63 11627 json, "bgpOriginCodes",
ea47320b
DL
11628 json_ocode);
11629 } else {
11630 vty_out(vty,
9df8b37c 11631 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11632 inet_ntoa(
9df8b37c
PZ
11633 bgp->router_id));
11634 if (bgp->vrf_id == VRF_UNKNOWN)
11635 vty_out(vty, "%s",
11636 VRFID_NONE_STR);
11637 else
11638 vty_out(vty, "%u",
11639 bgp->vrf_id);
11640 vty_out(vty, "\n");
01eced22
AD
11641 vty_out(vty,
11642 "Default local pref %u, ",
11643 bgp->default_local_pref);
11644 vty_out(vty, "local AS %u\n",
11645 bgp->as);
ea47320b
DL
11646 vty_out(vty,
11647 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11648 vty_out(vty,
11649 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11650 vty_out(vty,
11651 BGP_SHOW_OCODE_HEADER);
d62a17ae 11652 }
ea47320b
DL
11653 header1 = 0;
11654 }
11655 if (header2) {
11656 if (!use_json)
11657 vty_out(vty, BGP_SHOW_HEADER);
11658 header2 = 0;
11659 }
6392aaa6 11660
6f4f49b2 11661 attr = *ain->attr;
f99def61
AD
11662 route_filtered = false;
11663
11664 /* Filter prefix using distribute list,
11665 * filter list or prefix list
11666 */
11667 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11668 safi)) == FILTER_DENY)
11669 route_filtered = true;
11670
11671 /* Filter prefix using route-map */
6392aaa6 11672 ret = bgp_input_modifier(peer, &rn->p, &attr,
196c6b09
LK
11673 afi, safi, rmap_name, NULL, 0,
11674 NULL);
6392aaa6 11675
13c8e163
AD
11676 if (type == bgp_show_adj_route_filtered &&
11677 !route_filtered && ret != RMAP_DENY) {
b755861b 11678 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11679 continue;
d62a17ae 11680 }
6392aaa6 11681
13c8e163
AD
11682 if (type == bgp_show_adj_route_received &&
11683 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11684 filtered_count++;
11685
11686 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11687 use_json, json_ar);
b755861b 11688 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11689 output_count++;
d62a17ae 11690 }
6392aaa6 11691 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11692 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11693 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11694 if (paf->peer != peer || !adj->attr)
924c3f6a 11695 continue;
d62a17ae 11696
924c3f6a
DS
11697 if (header1) {
11698 if (use_json) {
11699 json_object_int_add(
11700 json,
11701 "bgpTableVersion",
11702 table->version);
11703 json_object_string_add(
11704 json,
11705 "bgpLocalRouterId",
11706 inet_ntoa(
11707 bgp->router_id));
01eced22
AD
11708 json_object_int_add(
11709 json, "defaultLocPrf",
11710 bgp->default_local_pref
11711 );
11712 json_object_int_add(
11713 json, "localAS",
11714 bgp->as);
924c3f6a
DS
11715 json_object_object_add(
11716 json,
11717 "bgpStatusCodes",
11718 json_scode);
11719 json_object_object_add(
11720 json,
11721 "bgpOriginCodes",
11722 json_ocode);
11723 } else {
11724 vty_out(vty,
11725 "BGP table version is %" PRIu64
9df8b37c 11726 ", local router ID is %s, vrf id ",
924c3f6a
DS
11727 table->version,
11728 inet_ntoa(
11729 bgp->router_id));
9df8b37c
PZ
11730 if (bgp->vrf_id ==
11731 VRF_UNKNOWN)
11732 vty_out(vty,
11733 "%s",
11734 VRFID_NONE_STR);
11735 else
11736 vty_out(vty,
11737 "%u",
11738 bgp->vrf_id);
11739 vty_out(vty, "\n");
01eced22
AD
11740 vty_out(vty,
11741 "Default local pref %u, ",
11742 bgp->default_local_pref
11743 );
11744 vty_out(vty,
11745 "local AS %u\n",
11746 bgp->as);
924c3f6a
DS
11747 vty_out(vty,
11748 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11749 vty_out(vty,
11750 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11751 vty_out(vty,
11752 BGP_SHOW_OCODE_HEADER);
a2addae8 11753 }
924c3f6a
DS
11754 header1 = 0;
11755 }
924c3f6a
DS
11756 if (header2) {
11757 if (!use_json)
11758 vty_out(vty,
11759 BGP_SHOW_HEADER);
11760 header2 = 0;
11761 }
d62a17ae 11762
6f4f49b2 11763 attr = *adj->attr;
b755861b
PM
11764 ret = bgp_output_modifier(
11765 peer, &rn->p, &attr, afi, safi,
11766 rmap_name);
f46d8e1e 11767
b755861b
PM
11768 if (ret != RMAP_DENY) {
11769 route_vty_out_tmp(vty, &rn->p,
11770 &attr, safi,
11771 use_json,
11772 json_ar);
11773 output_count++;
11774 } else {
11775 filtered_count++;
a2addae8 11776 }
b755861b
PM
11777
11778 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11779 }
d62a17ae 11780 }
11781 }
d62a17ae 11782
d62a17ae 11783 if (use_json) {
6392aaa6
PM
11784 json_object_object_add(json, "advertisedRoutes", json_ar);
11785 json_object_int_add(json, "totalPrefixCounter", output_count);
11786 json_object_int_add(json, "filteredPrefixCounter",
11787 filtered_count);
11788
996c9314
LB
11789 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11790 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11791 json_object_free(json);
6392aaa6
PM
11792 } else if (output_count > 0) {
11793 if (filtered_count > 0)
11794 vty_out(vty,
11795 "\nTotal number of prefixes %ld (%ld filtered)\n",
11796 output_count, filtered_count);
11797 else
11798 vty_out(vty, "\nTotal number of prefixes %ld\n",
11799 output_count);
d62a17ae 11800 }
a636c635 11801}
2a71e9ce 11802
d62a17ae 11803static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11804 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11805 const char *rmap_name, bool use_json)
0b16f239 11806{
d62a17ae 11807 json_object *json = NULL;
0b16f239 11808
d62a17ae 11809 if (use_json)
11810 json = json_object_new_object();
0b16f239 11811
d62a17ae 11812 if (!peer || !peer->afc[afi][safi]) {
11813 if (use_json) {
11814 json_object_string_add(
11815 json, "warning",
11816 "No such neighbor or address family");
11817 vty_out(vty, "%s\n", json_object_to_json_string(json));
11818 json_object_free(json);
11819 } else
11820 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11821
d62a17ae 11822 return CMD_WARNING;
11823 }
11824
6392aaa6
PM
11825 if ((type == bgp_show_adj_route_received
11826 || type == bgp_show_adj_route_filtered)
d62a17ae 11827 && !CHECK_FLAG(peer->af_flags[afi][safi],
11828 PEER_FLAG_SOFT_RECONFIG)) {
11829 if (use_json) {
11830 json_object_string_add(
11831 json, "warning",
11832 "Inbound soft reconfiguration not enabled");
11833 vty_out(vty, "%s\n", json_object_to_json_string(json));
11834 json_object_free(json);
11835 } else
11836 vty_out(vty,
11837 "%% Inbound soft reconfiguration not enabled\n");
11838
11839 return CMD_WARNING;
11840 }
0b16f239 11841
6392aaa6 11842 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11843
d62a17ae 11844 return CMD_SUCCESS;
a636c635 11845}
50ef26d4 11846
a636c635
DW
11847DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11848 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11849 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11850 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11851 SHOW_STR
11852 IP_STR
11853 BGP_STR
a636c635 11854 BGP_INSTANCE_HELP_STR
7395a2c9 11855 BGP_AFI_HELP_STR
4dd6177e 11856 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11857 "Detailed information on TCP and BGP neighbor connections\n"
11858 "Neighbor to display information about\n"
11859 "Neighbor to display information about\n"
91d37724 11860 "Neighbor on BGP configured interface\n"
a636c635 11861 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11862 "Display the received routes from neighbor\n"
11863 "Display the filtered routes received from neighbor\n"
a636c635
DW
11864 "Route-map to modify the attributes\n"
11865 "Name of the route map\n"
9973d184 11866 JSON_STR)
718e3744 11867{
d62a17ae 11868 afi_t afi = AFI_IP6;
11869 safi_t safi = SAFI_UNICAST;
11870 char *rmap_name = NULL;
11871 char *peerstr = NULL;
d62a17ae 11872 struct bgp *bgp = NULL;
11873 struct peer *peer;
6392aaa6 11874 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11875 int idx = 0;
9f049418 11876 bool uj = use_json(argc, argv);
6392aaa6 11877
d62a17ae 11878 if (uj)
11879 argc--;
30a6a167 11880
9f049418
DS
11881 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11882 &bgp, uj);
11883 if (!idx)
11884 return CMD_WARNING;
11885
d62a17ae 11886 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11887 argv_find(argv, argc, "neighbors", &idx);
11888 peerstr = argv[++idx]->arg;
8c3deaae 11889
d62a17ae 11890 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11891 if (!peer)
11892 return CMD_WARNING;
856ca177 11893
d62a17ae 11894 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11895 type = bgp_show_adj_route_advertised;
11896 else if (argv_find(argv, argc, "received-routes", &idx))
11897 type = bgp_show_adj_route_received;
11898 else if (argv_find(argv, argc, "filtered-routes", &idx))
11899 type = bgp_show_adj_route_filtered;
11900
d62a17ae 11901 if (argv_find(argv, argc, "route-map", &idx))
11902 rmap_name = argv[++idx]->arg;
95cbbd2a 11903
6392aaa6 11904 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11905}
11906
718e3744 11907DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11908 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11909 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11910 SHOW_STR
11911 IP_STR
11912 BGP_STR
8c3deaae
QY
11913 "Address Family\n"
11914 "Address Family\n"
718e3744 11915 "Address Family modifier\n"
11916 "Detailed information on TCP and BGP neighbor connections\n"
11917 "Neighbor to display information about\n"
11918 "Neighbor to display information about\n"
91d37724 11919 "Neighbor on BGP configured interface\n"
718e3744 11920 "Display information received from a BGP neighbor\n"
856ca177 11921 "Display the prefixlist filter\n"
9973d184 11922 JSON_STR)
718e3744 11923{
d62a17ae 11924 afi_t afi = AFI_IP6;
11925 safi_t safi = SAFI_UNICAST;
11926 char *peerstr = NULL;
11927
11928 char name[BUFSIZ];
11929 union sockunion su;
11930 struct peer *peer;
11931 int count, ret;
11932
11933 int idx = 0;
11934
11935 /* show [ip] bgp */
11936 if (argv_find(argv, argc, "ip", &idx))
11937 afi = AFI_IP;
11938 /* [<ipv4|ipv6> [unicast]] */
11939 if (argv_find(argv, argc, "ipv4", &idx))
11940 afi = AFI_IP;
11941 if (argv_find(argv, argc, "ipv6", &idx))
11942 afi = AFI_IP6;
11943 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11944 argv_find(argv, argc, "neighbors", &idx);
11945 peerstr = argv[++idx]->arg;
11946
9f049418 11947 bool uj = use_json(argc, argv);
d62a17ae 11948
11949 ret = str2sockunion(peerstr, &su);
11950 if (ret < 0) {
11951 peer = peer_lookup_by_conf_if(NULL, peerstr);
11952 if (!peer) {
11953 if (uj)
11954 vty_out(vty, "{}\n");
11955 else
11956 vty_out(vty,
11957 "%% Malformed address or name: %s\n",
11958 peerstr);
11959 return CMD_WARNING;
11960 }
11961 } else {
11962 peer = peer_lookup(NULL, &su);
11963 if (!peer) {
11964 if (uj)
11965 vty_out(vty, "{}\n");
11966 else
11967 vty_out(vty, "No peer\n");
11968 return CMD_WARNING;
11969 }
11970 }
718e3744 11971
d62a17ae 11972 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
11973 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
11974 if (count) {
11975 if (!uj)
11976 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 11977 get_afi_safi_str(afi, safi, false));
d62a17ae 11978 prefix_bgp_show_prefix_list(vty, afi, name, uj);
11979 } else {
11980 if (uj)
11981 vty_out(vty, "{}\n");
11982 else
11983 vty_out(vty, "No functional output\n");
11984 }
718e3744 11985
d62a17ae 11986 return CMD_SUCCESS;
11987}
11988
11989static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
11990 afi_t afi, safi_t safi,
9f049418 11991 enum bgp_show_type type, bool use_json)
d62a17ae 11992{
8a893163
DW
11993 /* labeled-unicast routes live in the unicast table */
11994 if (safi == SAFI_LABELED_UNICAST)
11995 safi = SAFI_UNICAST;
11996
d62a17ae 11997 if (!peer || !peer->afc[afi][safi]) {
11998 if (use_json) {
11999 json_object *json_no = NULL;
12000 json_no = json_object_new_object();
12001 json_object_string_add(
12002 json_no, "warning",
12003 "No such neighbor or address family");
12004 vty_out(vty, "%s\n",
12005 json_object_to_json_string(json_no));
12006 json_object_free(json_no);
12007 } else
12008 vty_out(vty, "%% No such neighbor or address family\n");
12009 return CMD_WARNING;
12010 }
47fc97cc 12011
d62a17ae 12012 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 12013}
12014
dba3c1d3
PG
12015DEFUN (show_ip_bgp_flowspec_routes_detailed,
12016 show_ip_bgp_flowspec_routes_detailed_cmd,
12017 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12018 SHOW_STR
12019 IP_STR
12020 BGP_STR
12021 BGP_INSTANCE_HELP_STR
12022 BGP_AFI_HELP_STR
12023 "SAFI Flowspec\n"
12024 "Detailed information on flowspec entries\n"
12025 JSON_STR)
12026{
12027 afi_t afi = AFI_IP;
12028 safi_t safi = SAFI_UNICAST;
12029 struct bgp *bgp = NULL;
12030 int idx = 0;
9f049418
DS
12031 bool uj = use_json(argc, argv);
12032
12033 if (uj)
12034 argc--;
dba3c1d3
PG
12035
12036 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12037 &bgp, uj);
dba3c1d3
PG
12038 if (!idx)
12039 return CMD_WARNING;
12040
9f049418 12041 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
12042}
12043
718e3744 12044DEFUN (show_ip_bgp_neighbor_routes,
12045 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 12046 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 12047 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 12048 SHOW_STR
12049 IP_STR
12050 BGP_STR
8386ac43 12051 BGP_INSTANCE_HELP_STR
4f280b15 12052 BGP_AFI_HELP_STR
4dd6177e 12053 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12054 "Detailed information on TCP and BGP neighbor connections\n"
12055 "Neighbor to display information about\n"
12056 "Neighbor to display information about\n"
91d37724 12057 "Neighbor on BGP configured interface\n"
2525cf39 12058 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12059 "Display the dampened routes received from neighbor\n"
12060 "Display routes learned from neighbor\n"
9973d184 12061 JSON_STR)
718e3744 12062{
d62a17ae 12063 char *peerstr = NULL;
12064 struct bgp *bgp = NULL;
12065 afi_t afi = AFI_IP6;
12066 safi_t safi = SAFI_UNICAST;
12067 struct peer *peer;
12068 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12069 int idx = 0;
9f049418
DS
12070 bool uj = use_json(argc, argv);
12071
12072 if (uj)
12073 argc--;
bb46e94f 12074
d62a17ae 12075 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12076 &bgp, uj);
d62a17ae 12077 if (!idx)
12078 return CMD_WARNING;
c493f2d8 12079
d62a17ae 12080 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12081 argv_find(argv, argc, "neighbors", &idx);
12082 peerstr = argv[++idx]->arg;
8c3deaae 12083
d62a17ae 12084 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12085 if (!peer)
d62a17ae 12086 return CMD_WARNING;
bb46e94f 12087
d62a17ae 12088 if (argv_find(argv, argc, "flap-statistics", &idx))
12089 sh_type = bgp_show_type_flap_neighbor;
12090 else if (argv_find(argv, argc, "dampened-routes", &idx))
12091 sh_type = bgp_show_type_damp_neighbor;
12092 else if (argv_find(argv, argc, "routes", &idx))
12093 sh_type = bgp_show_type_neighbor;
2525cf39 12094
d62a17ae 12095 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12096}
6b0655a2 12097
734b349e 12098struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12099
d62a17ae 12100struct bgp_distance {
12101 /* Distance value for the IP source prefix. */
d7c0a89a 12102 uint8_t distance;
718e3744 12103
d62a17ae 12104 /* Name of the access-list to be matched. */
12105 char *access_list;
718e3744 12106};
12107
4f280b15
LB
12108DEFUN (show_bgp_afi_vpn_rd_route,
12109 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12110 "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
12111 SHOW_STR
12112 BGP_STR
12113 BGP_AFI_HELP_STR
12114 "Address Family modifier\n"
12115 "Display information for a route distinguisher\n"
12116 "Route Distinguisher\n"
7395a2c9
DS
12117 "Network in the BGP routing table to display\n"
12118 "Network in the BGP routing table to display\n"
12119 JSON_STR)
4f280b15 12120{
d62a17ae 12121 int ret;
12122 struct prefix_rd prd;
12123 afi_t afi = AFI_MAX;
12124 int idx = 0;
4f280b15 12125
ff6566f3
DS
12126 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12127 vty_out(vty, "%% Malformed Address Family\n");
12128 return CMD_WARNING;
12129 }
12130
d62a17ae 12131 ret = str2prefix_rd(argv[5]->arg, &prd);
12132 if (!ret) {
12133 vty_out(vty, "%% Malformed Route Distinguisher\n");
12134 return CMD_WARNING;
12135 }
ff6566f3 12136
d62a17ae 12137 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12138 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12139}
12140
d62a17ae 12141static struct bgp_distance *bgp_distance_new(void)
718e3744 12142{
d62a17ae 12143 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12144}
12145
d62a17ae 12146static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12147{
d62a17ae 12148 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12149}
12150
d62a17ae 12151static int bgp_distance_set(struct vty *vty, const char *distance_str,
12152 const char *ip_str, const char *access_list_str)
718e3744 12153{
d62a17ae 12154 int ret;
12155 afi_t afi;
12156 safi_t safi;
12157 struct prefix p;
d7c0a89a 12158 uint8_t distance;
d62a17ae 12159 struct bgp_node *rn;
12160 struct bgp_distance *bdistance;
718e3744 12161
d62a17ae 12162 afi = bgp_node_afi(vty);
12163 safi = bgp_node_safi(vty);
734b349e 12164
d62a17ae 12165 ret = str2prefix(ip_str, &p);
12166 if (ret == 0) {
12167 vty_out(vty, "Malformed prefix\n");
12168 return CMD_WARNING_CONFIG_FAILED;
12169 }
718e3744 12170
d62a17ae 12171 distance = atoi(distance_str);
718e3744 12172
d62a17ae 12173 /* Get BGP distance node. */
12174 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 12175 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12176 if (bdistance)
d62a17ae 12177 bgp_unlock_node(rn);
ca2e160d 12178 else {
d62a17ae 12179 bdistance = bgp_distance_new();
5b00b40e 12180 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 12181 }
718e3744 12182
d62a17ae 12183 /* Set distance value. */
12184 bdistance->distance = distance;
718e3744 12185
d62a17ae 12186 /* Reset access-list configuration. */
e1b36e13 12187 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12188 if (access_list_str)
12189 bdistance->access_list =
12190 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12191
d62a17ae 12192 return CMD_SUCCESS;
718e3744 12193}
12194
d62a17ae 12195static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12196 const char *ip_str, const char *access_list_str)
718e3744 12197{
d62a17ae 12198 int ret;
12199 afi_t afi;
12200 safi_t safi;
12201 struct prefix p;
12202 int distance;
12203 struct bgp_node *rn;
12204 struct bgp_distance *bdistance;
718e3744 12205
d62a17ae 12206 afi = bgp_node_afi(vty);
12207 safi = bgp_node_safi(vty);
734b349e 12208
d62a17ae 12209 ret = str2prefix(ip_str, &p);
12210 if (ret == 0) {
12211 vty_out(vty, "Malformed prefix\n");
12212 return CMD_WARNING_CONFIG_FAILED;
12213 }
718e3744 12214
d62a17ae 12215 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
12216 (struct prefix *)&p);
12217 if (!rn) {
12218 vty_out(vty, "Can't find specified prefix\n");
12219 return CMD_WARNING_CONFIG_FAILED;
12220 }
718e3744 12221
5b00b40e 12222 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12223 distance = atoi(distance_str);
1f9a9fff 12224
d62a17ae 12225 if (bdistance->distance != distance) {
12226 vty_out(vty, "Distance does not match configured\n");
12227 return CMD_WARNING_CONFIG_FAILED;
12228 }
718e3744 12229
0a22ddfb 12230 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12231 bgp_distance_free(bdistance);
718e3744 12232
6f94b685 12233 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 12234 bgp_unlock_node(rn);
12235 bgp_unlock_node(rn);
718e3744 12236
d62a17ae 12237 return CMD_SUCCESS;
718e3744 12238}
12239
718e3744 12240/* Apply BGP information to distance method. */
40381db7 12241uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12242 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12243{
12244 struct bgp_node *rn;
12245 struct prefix q;
12246 struct peer *peer;
12247 struct bgp_distance *bdistance;
12248 struct access_list *alist;
12249 struct bgp_static *bgp_static;
12250
12251 if (!bgp)
12252 return 0;
12253
40381db7 12254 peer = pinfo->peer;
d62a17ae 12255
7b7d48e5
DS
12256 if (pinfo->attr->distance)
12257 return pinfo->attr->distance;
12258
d62a17ae 12259 /* Check source address. */
12260 sockunion2hostprefix(&peer->su, &q);
12261 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
12262 if (rn) {
5b00b40e 12263 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12264 bgp_unlock_node(rn);
12265
12266 if (bdistance->access_list) {
12267 alist = access_list_lookup(afi, bdistance->access_list);
12268 if (alist
12269 && access_list_apply(alist, p) == FILTER_PERMIT)
12270 return bdistance->distance;
12271 } else
12272 return bdistance->distance;
718e3744 12273 }
718e3744 12274
d62a17ae 12275 /* Backdoor check. */
12276 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12277 if (rn) {
5a8ba9fc 12278 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12279 bgp_unlock_node(rn);
718e3744 12280
d62a17ae 12281 if (bgp_static->backdoor) {
12282 if (bgp->distance_local[afi][safi])
12283 return bgp->distance_local[afi][safi];
12284 else
12285 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12286 }
718e3744 12287 }
718e3744 12288
d62a17ae 12289 if (peer->sort == BGP_PEER_EBGP) {
12290 if (bgp->distance_ebgp[afi][safi])
12291 return bgp->distance_ebgp[afi][safi];
12292 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12293 } else {
12294 if (bgp->distance_ibgp[afi][safi])
12295 return bgp->distance_ibgp[afi][safi];
12296 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12297 }
718e3744 12298}
12299
a612fb77
DA
12300/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12301 * we should tell ZEBRA update the routes for a specific
12302 * AFI/SAFI to reflect changes in RIB.
12303 */
8b54bc30
DA
12304static void bgp_announce_routes_distance_update(struct bgp *bgp,
12305 afi_t update_afi,
12306 safi_t update_safi)
a612fb77
DA
12307{
12308 afi_t afi;
12309 safi_t safi;
12310
12311 FOREACH_AFI_SAFI (afi, safi) {
12312 if (!bgp_fibupd_safi(safi))
12313 continue;
12314
8b54bc30
DA
12315 if (afi != update_afi && safi != update_safi)
12316 continue;
12317
12318 if (BGP_DEBUG(zebra, ZEBRA))
12319 zlog_debug(
12320 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12321 __func__, afi, safi);
12322 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12323 }
12324}
12325
718e3744 12326DEFUN (bgp_distance,
12327 bgp_distance_cmd,
6147e2c6 12328 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12329 "Define an administrative distance\n"
12330 "BGP distance\n"
12331 "Distance for routes external to the AS\n"
12332 "Distance for routes internal to the AS\n"
12333 "Distance for local routes\n")
12334{
d62a17ae 12335 VTY_DECLVAR_CONTEXT(bgp, bgp);
12336 int idx_number = 2;
12337 int idx_number_2 = 3;
12338 int idx_number_3 = 4;
8b54bc30
DA
12339 int distance_ebgp = atoi(argv[idx_number]->arg);
12340 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12341 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12342 afi_t afi;
12343 safi_t safi;
718e3744 12344
d62a17ae 12345 afi = bgp_node_afi(vty);
12346 safi = bgp_node_safi(vty);
718e3744 12347
8b54bc30
DA
12348 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12349 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12350 || bgp->distance_local[afi][safi] != distance_local) {
12351 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12352 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12353 bgp->distance_local[afi][safi] = distance_local;
12354 bgp_announce_routes_distance_update(bgp, afi, safi);
12355 }
d62a17ae 12356 return CMD_SUCCESS;
718e3744 12357}
12358
12359DEFUN (no_bgp_distance,
12360 no_bgp_distance_cmd,
a636c635 12361 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12362 NO_STR
12363 "Define an administrative distance\n"
12364 "BGP distance\n"
12365 "Distance for routes external to the AS\n"
12366 "Distance for routes internal to the AS\n"
12367 "Distance for local routes\n")
12368{
d62a17ae 12369 VTY_DECLVAR_CONTEXT(bgp, bgp);
12370 afi_t afi;
12371 safi_t safi;
718e3744 12372
d62a17ae 12373 afi = bgp_node_afi(vty);
12374 safi = bgp_node_safi(vty);
718e3744 12375
8b54bc30
DA
12376 if (bgp->distance_ebgp[afi][safi] != 0
12377 || bgp->distance_ibgp[afi][safi] != 0
12378 || bgp->distance_local[afi][safi] != 0) {
12379 bgp->distance_ebgp[afi][safi] = 0;
12380 bgp->distance_ibgp[afi][safi] = 0;
12381 bgp->distance_local[afi][safi] = 0;
12382 bgp_announce_routes_distance_update(bgp, afi, safi);
12383 }
d62a17ae 12384 return CMD_SUCCESS;
718e3744 12385}
12386
718e3744 12387
12388DEFUN (bgp_distance_source,
12389 bgp_distance_source_cmd,
6147e2c6 12390 "distance (1-255) A.B.C.D/M",
718e3744 12391 "Define an administrative distance\n"
12392 "Administrative distance\n"
12393 "IP source prefix\n")
12394{
d62a17ae 12395 int idx_number = 1;
12396 int idx_ipv4_prefixlen = 2;
12397 bgp_distance_set(vty, argv[idx_number]->arg,
12398 argv[idx_ipv4_prefixlen]->arg, NULL);
12399 return CMD_SUCCESS;
718e3744 12400}
12401
12402DEFUN (no_bgp_distance_source,
12403 no_bgp_distance_source_cmd,
6147e2c6 12404 "no distance (1-255) A.B.C.D/M",
718e3744 12405 NO_STR
12406 "Define an administrative distance\n"
12407 "Administrative distance\n"
12408 "IP source prefix\n")
12409{
d62a17ae 12410 int idx_number = 2;
12411 int idx_ipv4_prefixlen = 3;
12412 bgp_distance_unset(vty, argv[idx_number]->arg,
12413 argv[idx_ipv4_prefixlen]->arg, NULL);
12414 return CMD_SUCCESS;
718e3744 12415}
12416
12417DEFUN (bgp_distance_source_access_list,
12418 bgp_distance_source_access_list_cmd,
6147e2c6 12419 "distance (1-255) A.B.C.D/M WORD",
718e3744 12420 "Define an administrative distance\n"
12421 "Administrative distance\n"
12422 "IP source prefix\n"
12423 "Access list name\n")
12424{
d62a17ae 12425 int idx_number = 1;
12426 int idx_ipv4_prefixlen = 2;
12427 int idx_word = 3;
12428 bgp_distance_set(vty, argv[idx_number]->arg,
12429 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12430 return CMD_SUCCESS;
718e3744 12431}
12432
12433DEFUN (no_bgp_distance_source_access_list,
12434 no_bgp_distance_source_access_list_cmd,
6147e2c6 12435 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12436 NO_STR
12437 "Define an administrative distance\n"
12438 "Administrative distance\n"
12439 "IP source prefix\n"
12440 "Access list name\n")
12441{
d62a17ae 12442 int idx_number = 2;
12443 int idx_ipv4_prefixlen = 3;
12444 int idx_word = 4;
12445 bgp_distance_unset(vty, argv[idx_number]->arg,
12446 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12447 return CMD_SUCCESS;
718e3744 12448}
6b0655a2 12449
734b349e
MZ
12450DEFUN (ipv6_bgp_distance_source,
12451 ipv6_bgp_distance_source_cmd,
39e92c06 12452 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12453 "Define an administrative distance\n"
12454 "Administrative distance\n"
12455 "IP source prefix\n")
12456{
d62a17ae 12457 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12458 return CMD_SUCCESS;
734b349e
MZ
12459}
12460
12461DEFUN (no_ipv6_bgp_distance_source,
12462 no_ipv6_bgp_distance_source_cmd,
39e92c06 12463 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12464 NO_STR
12465 "Define an administrative distance\n"
12466 "Administrative distance\n"
12467 "IP source prefix\n")
12468{
d62a17ae 12469 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12470 return CMD_SUCCESS;
734b349e
MZ
12471}
12472
12473DEFUN (ipv6_bgp_distance_source_access_list,
12474 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12475 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12476 "Define an administrative distance\n"
12477 "Administrative distance\n"
12478 "IP source prefix\n"
12479 "Access list name\n")
12480{
d62a17ae 12481 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12482 return CMD_SUCCESS;
734b349e
MZ
12483}
12484
12485DEFUN (no_ipv6_bgp_distance_source_access_list,
12486 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12487 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12488 NO_STR
12489 "Define an administrative distance\n"
12490 "Administrative distance\n"
12491 "IP source prefix\n"
12492 "Access list name\n")
12493{
d62a17ae 12494 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12495 return CMD_SUCCESS;
734b349e
MZ
12496}
12497
718e3744 12498DEFUN (bgp_damp_set,
12499 bgp_damp_set_cmd,
31500417 12500 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12501 "BGP Specific commands\n"
12502 "Enable route-flap dampening\n"
12503 "Half-life time for the penalty\n"
12504 "Value to start reusing a route\n"
12505 "Value to start suppressing a route\n"
12506 "Maximum duration to suppress a stable route\n")
12507{
d62a17ae 12508 VTY_DECLVAR_CONTEXT(bgp, bgp);
12509 int idx_half_life = 2;
12510 int idx_reuse = 3;
12511 int idx_suppress = 4;
12512 int idx_max_suppress = 5;
12513 int half = DEFAULT_HALF_LIFE * 60;
12514 int reuse = DEFAULT_REUSE;
12515 int suppress = DEFAULT_SUPPRESS;
12516 int max = 4 * half;
12517
12518 if (argc == 6) {
12519 half = atoi(argv[idx_half_life]->arg) * 60;
12520 reuse = atoi(argv[idx_reuse]->arg);
12521 suppress = atoi(argv[idx_suppress]->arg);
12522 max = atoi(argv[idx_max_suppress]->arg) * 60;
12523 } else if (argc == 3) {
12524 half = atoi(argv[idx_half_life]->arg) * 60;
12525 max = 4 * half;
12526 }
718e3744 12527
6d24b7cc
DS
12528 /*
12529 * These can't be 0 but our SA doesn't understand the
12530 * way our cli is constructed
12531 */
12532 assert(reuse);
12533 assert(half);
d62a17ae 12534 if (suppress < reuse) {
12535 vty_out(vty,
12536 "Suppress value cannot be less than reuse value \n");
12537 return 0;
12538 }
7ebe9748 12539
d62a17ae 12540 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12541 reuse, suppress, max);
718e3744 12542}
12543
718e3744 12544DEFUN (bgp_damp_unset,
12545 bgp_damp_unset_cmd,
d04c479d 12546 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12547 NO_STR
12548 "BGP Specific commands\n"
16cedbb0
QY
12549 "Enable route-flap dampening\n"
12550 "Half-life time for the penalty\n"
12551 "Value to start reusing a route\n"
12552 "Value to start suppressing a route\n"
12553 "Maximum duration to suppress a stable route\n")
718e3744 12554{
d62a17ae 12555 VTY_DECLVAR_CONTEXT(bgp, bgp);
12556 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12557}
12558
718e3744 12559/* Display specified route of BGP table. */
d62a17ae 12560static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12561 const char *ip_str, afi_t afi, safi_t safi,
12562 struct prefix_rd *prd, int prefix_check)
12563{
12564 int ret;
12565 struct prefix match;
12566 struct bgp_node *rn;
12567 struct bgp_node *rm;
40381db7
DS
12568 struct bgp_path_info *pi;
12569 struct bgp_path_info *pi_temp;
d62a17ae 12570 struct bgp *bgp;
12571 struct bgp_table *table;
12572
12573 /* BGP structure lookup. */
12574 if (view_name) {
12575 bgp = bgp_lookup_by_name(view_name);
12576 if (bgp == NULL) {
12577 vty_out(vty, "%% Can't find BGP instance %s\n",
12578 view_name);
12579 return CMD_WARNING;
12580 }
12581 } else {
12582 bgp = bgp_get_default();
12583 if (bgp == NULL) {
12584 vty_out(vty, "%% No BGP process is configured\n");
12585 return CMD_WARNING;
12586 }
718e3744 12587 }
718e3744 12588
d62a17ae 12589 /* Check IP address argument. */
12590 ret = str2prefix(ip_str, &match);
12591 if (!ret) {
12592 vty_out(vty, "%% address is malformed\n");
12593 return CMD_WARNING;
12594 }
718e3744 12595
d62a17ae 12596 match.family = afi2family(afi);
12597
12598 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12599 || (safi == SAFI_EVPN)) {
12600 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12601 rn = bgp_route_next(rn)) {
12602 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12603 continue;
67009e22
DS
12604 table = bgp_node_get_bgp_table_info(rn);
12605 if (!table)
ea47320b
DL
12606 continue;
12607 if ((rm = bgp_node_match(table, &match)) == NULL)
12608 continue;
d62a17ae 12609
ea47320b
DL
12610 if (!prefix_check
12611 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12612 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12613 while (pi) {
12614 if (pi->extra && pi->extra->damp_info) {
12615 pi_temp = pi->next;
ea47320b 12616 bgp_damp_info_free(
40381db7 12617 pi->extra->damp_info,
a935f597 12618 1, afi, safi);
40381db7 12619 pi = pi_temp;
ea47320b 12620 } else
40381db7 12621 pi = pi->next;
d62a17ae 12622 }
ea47320b
DL
12623 }
12624
12625 bgp_unlock_node(rm);
d62a17ae 12626 }
12627 } else {
12628 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12629 != NULL) {
12630 if (!prefix_check
12631 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12632 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12633 while (pi) {
12634 if (pi->extra && pi->extra->damp_info) {
12635 pi_temp = pi->next;
d62a17ae 12636 bgp_damp_info_free(
40381db7 12637 pi->extra->damp_info,
a935f597 12638 1, afi, safi);
40381db7 12639 pi = pi_temp;
d62a17ae 12640 } else
40381db7 12641 pi = pi->next;
d62a17ae 12642 }
12643 }
12644
12645 bgp_unlock_node(rn);
12646 }
12647 }
718e3744 12648
d62a17ae 12649 return CMD_SUCCESS;
718e3744 12650}
12651
12652DEFUN (clear_ip_bgp_dampening,
12653 clear_ip_bgp_dampening_cmd,
12654 "clear ip bgp dampening",
12655 CLEAR_STR
12656 IP_STR
12657 BGP_STR
12658 "Clear route flap dampening information\n")
12659{
a935f597 12660 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12661 return CMD_SUCCESS;
718e3744 12662}
12663
12664DEFUN (clear_ip_bgp_dampening_prefix,
12665 clear_ip_bgp_dampening_prefix_cmd,
12666 "clear ip bgp dampening A.B.C.D/M",
12667 CLEAR_STR
12668 IP_STR
12669 BGP_STR
12670 "Clear route flap dampening information\n"
0c7b1b01 12671 "IPv4 prefix\n")
718e3744 12672{
d62a17ae 12673 int idx_ipv4_prefixlen = 4;
12674 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12675 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12676}
12677
12678DEFUN (clear_ip_bgp_dampening_address,
12679 clear_ip_bgp_dampening_address_cmd,
12680 "clear ip bgp dampening A.B.C.D",
12681 CLEAR_STR
12682 IP_STR
12683 BGP_STR
12684 "Clear route flap dampening information\n"
12685 "Network to clear damping information\n")
12686{
d62a17ae 12687 int idx_ipv4 = 4;
12688 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12689 SAFI_UNICAST, NULL, 0);
718e3744 12690}
12691
12692DEFUN (clear_ip_bgp_dampening_address_mask,
12693 clear_ip_bgp_dampening_address_mask_cmd,
12694 "clear ip bgp dampening A.B.C.D A.B.C.D",
12695 CLEAR_STR
12696 IP_STR
12697 BGP_STR
12698 "Clear route flap dampening information\n"
12699 "Network to clear damping information\n"
12700 "Network mask\n")
12701{
d62a17ae 12702 int idx_ipv4 = 4;
12703 int idx_ipv4_2 = 5;
12704 int ret;
12705 char prefix_str[BUFSIZ];
718e3744 12706
d62a17ae 12707 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12708 prefix_str);
12709 if (!ret) {
12710 vty_out(vty, "%% Inconsistent address and mask\n");
12711 return CMD_WARNING;
12712 }
718e3744 12713
d62a17ae 12714 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12715 NULL, 0);
718e3744 12716}
6b0655a2 12717
e3b78da8 12718static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12719{
12720 struct vty *vty = arg;
e3b78da8 12721 struct peer *peer = bucket->data;
825d9834
DS
12722 char buf[SU_ADDRSTRLEN];
12723
12724 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12725 sockunion2str(&peer->su, buf, sizeof(buf)));
12726}
12727
12728DEFUN (show_bgp_peerhash,
12729 show_bgp_peerhash_cmd,
12730 "show bgp peerhash",
12731 SHOW_STR
12732 BGP_STR
12733 "Display information about the BGP peerhash\n")
12734{
12735 struct list *instances = bm->bgp;
12736 struct listnode *node;
12737 struct bgp *bgp;
12738
12739 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12740 vty_out(vty, "BGP: %s\n", bgp->name);
12741 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12742 vty);
12743 }
12744
12745 return CMD_SUCCESS;
12746}
12747
587ff0fd 12748/* also used for encap safi */
2b791107
DL
12749static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12750 afi_t afi, safi_t safi)
d62a17ae 12751{
12752 struct bgp_node *prn;
12753 struct bgp_node *rn;
12754 struct bgp_table *table;
12755 struct prefix *p;
12756 struct prefix_rd *prd;
12757 struct bgp_static *bgp_static;
12758 mpls_label_t label;
12759 char buf[SU_ADDRSTRLEN];
12760 char rdbuf[RD_ADDRSTRLEN];
12761
12762 /* Network configuration. */
12763 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12764 prn = bgp_route_next(prn)) {
67009e22
DS
12765 table = bgp_node_get_bgp_table_info(prn);
12766 if (!table)
ea47320b 12767 continue;
d62a17ae 12768
60466a63 12769 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12770 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12771 if (bgp_static == NULL)
ea47320b 12772 continue;
d62a17ae 12773
ea47320b
DL
12774 p = &rn->p;
12775 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12776
ea47320b 12777 /* "network" configuration display. */
06b9f471 12778 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12779 label = decode_label(&bgp_static->label);
12780
12781 vty_out(vty, " network %s/%d rd %s",
12782 inet_ntop(p->family, &p->u.prefix, buf,
12783 SU_ADDRSTRLEN),
12784 p->prefixlen, rdbuf);
12785 if (safi == SAFI_MPLS_VPN)
12786 vty_out(vty, " label %u", label);
12787
12788 if (bgp_static->rmap.name)
12789 vty_out(vty, " route-map %s",
12790 bgp_static->rmap.name);
e2a86ad9
DS
12791
12792 if (bgp_static->backdoor)
12793 vty_out(vty, " backdoor");
12794
ea47320b
DL
12795 vty_out(vty, "\n");
12796 }
12797 }
d62a17ae 12798}
12799
2b791107
DL
12800static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12801 afi_t afi, safi_t safi)
d62a17ae 12802{
12803 struct bgp_node *prn;
12804 struct bgp_node *rn;
12805 struct bgp_table *table;
12806 struct prefix *p;
12807 struct prefix_rd *prd;
12808 struct bgp_static *bgp_static;
ff44f570 12809 char buf[PREFIX_STRLEN * 2];
d62a17ae 12810 char buf2[SU_ADDRSTRLEN];
12811 char rdbuf[RD_ADDRSTRLEN];
12812
12813 /* Network configuration. */
12814 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12815 prn = bgp_route_next(prn)) {
67009e22
DS
12816 table = bgp_node_get_bgp_table_info(prn);
12817 if (!table)
ea47320b 12818 continue;
d62a17ae 12819
60466a63 12820 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12821 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12822 if (bgp_static == NULL)
ea47320b 12823 continue;
d62a17ae 12824
ea47320b
DL
12825 char *macrouter = NULL;
12826 char *esi = NULL;
d62a17ae 12827
ea47320b
DL
12828 if (bgp_static->router_mac)
12829 macrouter = prefix_mac2str(
12830 bgp_static->router_mac, NULL, 0);
12831 if (bgp_static->eth_s_id)
12832 esi = esi2str(bgp_static->eth_s_id);
12833 p = &rn->p;
12834 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12835
ea47320b 12836 /* "network" configuration display. */
06b9f471 12837 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12838 if (p->u.prefix_evpn.route_type == 5) {
12839 char local_buf[PREFIX_STRLEN];
3714a385 12840 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12841 struct prefix_evpn *)p)
12842 ? AF_INET
12843 : AF_INET6;
3714a385 12844 inet_ntop(family,
12845 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12846 local_buf, PREFIX_STRLEN);
12847 sprintf(buf, "%s/%u", local_buf,
3714a385 12848 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12849 } else {
12850 prefix2str(p, buf, sizeof(buf));
12851 }
ea47320b 12852
a4d82a8a
PZ
12853 if (bgp_static->gatewayIp.family == AF_INET
12854 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12855 inet_ntop(bgp_static->gatewayIp.family,
12856 &bgp_static->gatewayIp.u.prefix, buf2,
12857 sizeof(buf2));
ea47320b 12858 vty_out(vty,
7bcc8dac 12859 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12860 buf, rdbuf,
12861 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12862 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12863 macrouter);
12864
0a22ddfb
QY
12865 XFREE(MTYPE_TMP, macrouter);
12866 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12867 }
12868 }
3da6fcd5
PG
12869}
12870
718e3744 12871/* Configuration of static route announcement and aggregate
12872 information. */
2b791107
DL
12873void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12874 safi_t safi)
d62a17ae 12875{
12876 struct bgp_node *rn;
12877 struct prefix *p;
12878 struct bgp_static *bgp_static;
12879 struct bgp_aggregate *bgp_aggregate;
12880 char buf[SU_ADDRSTRLEN];
12881
2b791107
DL
12882 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12883 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12884 return;
12885 }
d62a17ae 12886
2b791107
DL
12887 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12888 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12889 return;
12890 }
d62a17ae 12891
12892 /* Network configuration. */
12893 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12894 rn = bgp_route_next(rn)) {
5a8ba9fc 12895 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12896 if (bgp_static == NULL)
ea47320b 12897 continue;
d62a17ae 12898
ea47320b 12899 p = &rn->p;
d62a17ae 12900
d8a9922d
DS
12901 vty_out(vty, " network %s/%d",
12902 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12903 p->prefixlen);
d62a17ae 12904
ea47320b
DL
12905 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12906 vty_out(vty, " label-index %u",
12907 bgp_static->label_index);
d62a17ae 12908
ea47320b
DL
12909 if (bgp_static->rmap.name)
12910 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12911
12912 if (bgp_static->backdoor)
12913 vty_out(vty, " backdoor");
718e3744 12914
ea47320b
DL
12915 vty_out(vty, "\n");
12916 }
12917
d62a17ae 12918 /* Aggregate-address configuration. */
12919 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12920 rn = bgp_route_next(rn)) {
b613a918 12921 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12922 if (bgp_aggregate == NULL)
ea47320b 12923 continue;
d62a17ae 12924
ea47320b 12925 p = &rn->p;
d62a17ae 12926
d8a9922d
DS
12927 vty_out(vty, " aggregate-address %s/%d",
12928 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12929 p->prefixlen);
d62a17ae 12930
ea47320b
DL
12931 if (bgp_aggregate->as_set)
12932 vty_out(vty, " as-set");
d62a17ae 12933
ea47320b
DL
12934 if (bgp_aggregate->summary_only)
12935 vty_out(vty, " summary-only");
718e3744 12936
20894f50
DA
12937 if (bgp_aggregate->rmap.name)
12938 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12939
ea47320b
DL
12940 vty_out(vty, "\n");
12941 }
d62a17ae 12942}
734b349e 12943
2b791107 12944void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 12945 safi_t safi)
d62a17ae 12946{
12947 struct bgp_node *rn;
12948 struct bgp_distance *bdistance;
12949
12950 /* Distance configuration. */
12951 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
12952 && bgp->distance_local[afi][safi]
12953 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
12954 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
12955 || bgp->distance_local[afi][safi]
12956 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 12957 vty_out(vty, " distance bgp %d %d %d\n",
12958 bgp->distance_ebgp[afi][safi],
12959 bgp->distance_ibgp[afi][safi],
12960 bgp->distance_local[afi][safi]);
12961 }
734b349e 12962
d62a17ae 12963 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 12964 rn = bgp_route_next(rn)) {
5b00b40e 12965 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12966 if (bdistance != NULL) {
d62a17ae 12967 char buf[PREFIX_STRLEN];
12968
d62a17ae 12969 vty_out(vty, " distance %d %s %s\n",
12970 bdistance->distance,
12971 prefix2str(&rn->p, buf, sizeof(buf)),
12972 bdistance->access_list ? bdistance->access_list
12973 : "");
12974 }
ca2e160d 12975 }
718e3744 12976}
12977
12978/* Allocate routing table structure and install commands. */
d62a17ae 12979void bgp_route_init(void)
12980{
12981 afi_t afi;
12982 safi_t safi;
12983
12984 /* Init BGP distance table. */
05c7a1cc 12985 FOREACH_AFI_SAFI (afi, safi)
960035b2 12986 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 12987
12988 /* IPv4 BGP commands. */
12989 install_element(BGP_NODE, &bgp_table_map_cmd);
12990 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 12991 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 12992
12993 install_element(BGP_NODE, &aggregate_address_cmd);
12994 install_element(BGP_NODE, &aggregate_address_mask_cmd);
12995 install_element(BGP_NODE, &no_aggregate_address_cmd);
12996 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
12997
12998 /* IPv4 unicast configuration. */
12999 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13000 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13001 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13002
13003 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13004 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13005 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13006 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13007
13008 /* IPv4 multicast configuration. */
13009 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13010 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13011 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13012 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13013 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13014 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13015 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13016
13017 /* IPv4 labeled-unicast configuration. */
13018 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13019 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 13020 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13021 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13022 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
13023
13024 install_element(VIEW_NODE,
13025 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13026 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13027 install_element(VIEW_NODE,
13028 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13029#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13030 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13031#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13032 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13033 install_element(VIEW_NODE,
44c69747 13034 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13035
d62a17ae 13036 /* BGP dampening clear commands */
13037 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13038 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13039
d62a17ae 13040 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13041 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13042
13043 /* prefix count */
13044 install_element(ENABLE_NODE,
13045 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13046#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13047 install_element(ENABLE_NODE,
13048 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13049#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13050
d62a17ae 13051 /* New config IPv6 BGP commands. */
13052 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13053 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13054 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13055
13056 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13057 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13058
13059 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13060
d62a17ae 13061 install_element(BGP_NODE, &bgp_distance_cmd);
13062 install_element(BGP_NODE, &no_bgp_distance_cmd);
13063 install_element(BGP_NODE, &bgp_distance_source_cmd);
13064 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13065 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13066 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13067 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13068 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13069 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13070 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13071 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13072 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13073 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13074 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13075 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13076 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13077 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13078 install_element(BGP_IPV4M_NODE,
13079 &no_bgp_distance_source_access_list_cmd);
13080 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13081 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13082 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13083 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13084 install_element(BGP_IPV6_NODE,
13085 &ipv6_bgp_distance_source_access_list_cmd);
13086 install_element(BGP_IPV6_NODE,
13087 &no_ipv6_bgp_distance_source_access_list_cmd);
13088 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13089 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13090 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13091 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13092 install_element(BGP_IPV6M_NODE,
13093 &ipv6_bgp_distance_source_access_list_cmd);
13094 install_element(BGP_IPV6M_NODE,
13095 &no_ipv6_bgp_distance_source_access_list_cmd);
13096
13097 install_element(BGP_NODE, &bgp_damp_set_cmd);
13098 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13099 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13100 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
13101
13102 /* IPv4 Multicast Mode */
13103 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13104 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
13105
13106 /* Large Communities */
13107 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13108 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13109
13110 /* show bgp ipv4 flowspec detailed */
13111 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13112
825d9834 13113 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13114}
13115
13116void bgp_route_finish(void)
13117{
13118 afi_t afi;
13119 safi_t safi;
13120
05c7a1cc
QY
13121 FOREACH_AFI_SAFI (afi, safi) {
13122 bgp_table_unlock(bgp_distance_table[afi][safi]);
13123 bgp_distance_table[afi][safi] = NULL;
13124 }
228da428 13125}