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