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