]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #5927 from mjstapp/interval_string_api
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
718e3744 73
65efcfce 74#if ENABLE_BGP_VNC
f8b6f499
LB
75#include "bgpd/rfapi/rfapi_backend.h"
76#include "bgpd/rfapi/vnc_import_bgp.h"
77#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 78#endif
aee875b5
PG
79#include "bgpd/bgp_encap_types.h"
80#include "bgpd/bgp_encap_tlv.h"
684a7227 81#include "bgpd/bgp_evpn.h"
3da6fcd5 82#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 83#include "bgpd/bgp_flowspec.h"
98a9dbc7 84#include "bgpd/bgp_flowspec_util.h"
45918cfb 85#include "bgpd/bgp_pbr.h"
65efcfce 86
e2a86ad9
DS
87#ifndef VTYSH_EXTRACT_PL
88#include "bgpd/bgp_route_clippy.c"
89#endif
aee875b5 90
718e3744 91/* Extern from bgp_dump.c */
dde72586
SH
92extern const char *bgp_origin_str[];
93extern const char *bgp_origin_long_str[];
36235319 94const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 95/* PMSI strings. */
96#define PMSI_TNLTYPE_STR_NO_INFO "No info"
97#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
98static const struct message bgp_pmsi_tnltype_str[] = {
99 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
100 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
101 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
102 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
103 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
104 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
105 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
106 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 107 {0}
108};
b7d08f5a 109
9df8b37c
PZ
110#define VRFID_NONE_STR "-"
111
4a11bf2c
DL
112DEFINE_HOOK(bgp_process,
113 (struct bgp *bgp, afi_t afi, safi_t safi,
114 struct bgp_node *bn, struct peer *peer, bool withdraw),
115 (bgp, afi, safi, bn, peer, withdraw))
116
117
d62a17ae 118struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
119 safi_t safi, struct prefix *p,
120 struct prefix_rd *prd)
121{
122 struct bgp_node *rn;
123 struct bgp_node *prn = NULL;
124
125 assert(table);
d62a17ae 126
127 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
128 || (safi == SAFI_EVPN)) {
129 prn = bgp_node_get(table, (struct prefix *)prd);
130
67009e22
DS
131 if (!bgp_node_has_bgp_path_info_data(prn))
132 bgp_node_set_bgp_table_info(
133 prn, bgp_table_init(table->bgp, afi, safi));
d62a17ae 134 else
135 bgp_unlock_node(prn);
67009e22 136 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 137 }
718e3744 138
d62a17ae 139 rn = bgp_node_get(table, p);
718e3744 140
d62a17ae 141 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
142 || (safi == SAFI_EVPN))
143 rn->prn = prn;
718e3744 144
d62a17ae 145 return rn;
718e3744 146}
6b0655a2 147
d62a17ae 148struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
149 safi_t safi, struct prefix *p,
150 struct prefix_rd *prd)
128ea8ab 151{
d62a17ae 152 struct bgp_node *rn;
153 struct bgp_node *prn = NULL;
128ea8ab 154
d62a17ae 155 if (!table)
156 return NULL;
128ea8ab 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN)) {
160 prn = bgp_node_lookup(table, (struct prefix *)prd);
161 if (!prn)
162 return NULL;
128ea8ab 163
6f94b685 164 if (!bgp_node_has_bgp_path_info_data(prn)) {
d62a17ae 165 bgp_unlock_node(prn);
166 return NULL;
167 }
128ea8ab 168
67009e22 169 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 170 }
128ea8ab 171
d62a17ae 172 rn = bgp_node_lookup(table, p);
128ea8ab 173
d62a17ae 174 return rn;
128ea8ab 175}
176
18ee8310
DS
177/* Allocate bgp_path_info_extra */
178static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 179{
4b7e6066
DS
180 struct bgp_path_info_extra *new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
182 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
183 new->label[0] = MPLS_INVALID_LABEL;
184 new->num_labels = 0;
3e3708cb
PG
185 new->bgp_fs_pbr = NULL;
186 new->bgp_fs_iprule = NULL;
d62a17ae 187 return new;
fb982c25
PJ
188}
189
a2e219fe 190void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 191{
4b7e6066 192 struct bgp_path_info_extra *e;
d62a17ae 193
c93a3b77
DS
194 if (!extra || !*extra)
195 return;
d62a17ae 196
c93a3b77
DS
197 e = *extra;
198 if (e->damp_info)
a935f597
DA
199 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
200 e->damp_info->safi);
d62a17ae 201
c93a3b77
DS
202 e->damp_info = NULL;
203 if (e->parent) {
40381db7 204 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 205
40381db7 206 if (bpi->net) {
0e70e6c8
DL
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
210 *
40381db7
DS
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
0e70e6c8
DL
214 */
215 unsigned refcount;
216
40381db7
DS
217 bpi = bgp_path_info_lock(bpi);
218 refcount = bpi->net->lock - 1;
219 bgp_unlock_node((struct bgp_node *)bpi->net);
0e70e6c8 220 if (!refcount)
40381db7
DS
221 bpi->net = NULL;
222 bgp_path_info_unlock(bpi);
0e70e6c8 223 }
18ee8310 224 bgp_path_info_unlock(e->parent);
c93a3b77 225 e->parent = NULL;
d62a17ae 226 }
c93a3b77
DS
227
228 if (e->bgp_orig)
229 bgp_unlock(e->bgp_orig);
c26edcda 230
ce3c0614
PG
231 if ((*extra)->bgp_fs_iprule)
232 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 233 if ((*extra)->bgp_fs_pbr)
6a154c88 234 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 235 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
236}
237
18ee8310
DS
238/* Get bgp_path_info extra information for the given bgp_path_info, lazy
239 * allocated if required.
fb982c25 240 */
40381db7 241struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 242{
40381db7
DS
243 if (!pi->extra)
244 pi->extra = bgp_path_info_extra_new();
245 return pi->extra;
fb982c25
PJ
246}
247
718e3744 248/* Free bgp route information. */
9b6d8fcf 249static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 250{
05864da7 251 bgp_attr_unintern(&path->attr);
fb018d25 252
9b6d8fcf
DS
253 bgp_unlink_nexthop(path);
254 bgp_path_info_extra_free(&path->extra);
255 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
256 if (path->net)
257 bgp_addpath_free_info_data(&path->tx_addpath,
258 &path->net->tx_addpath);
718e3744 259
9b6d8fcf 260 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 261
9b6d8fcf 262 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 263}
264
9b6d8fcf 265struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 266{
9b6d8fcf
DS
267 path->lock++;
268 return path;
200df115 269}
270
9b6d8fcf 271struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 272{
9b6d8fcf
DS
273 assert(path && path->lock > 0);
274 path->lock--;
d62a17ae 275
9b6d8fcf 276 if (path->lock == 0) {
200df115 277#if 0
278 zlog_debug ("%s: unlocked and freeing", __func__);
279 zlog_backtrace (LOG_DEBUG);
280#endif
9b6d8fcf 281 bgp_path_info_free(path);
d62a17ae 282 return NULL;
283 }
200df115 284
285#if 0
9b6d8fcf 286 if (path->lock == 1)
200df115 287 {
288 zlog_debug ("%s: unlocked to 1", __func__);
289 zlog_backtrace (LOG_DEBUG);
290 }
291#endif
d62a17ae 292
9b6d8fcf 293 return path;
200df115 294}
295
f009ff26 296/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
297static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
298{
299 struct peer *peer;
300 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 301 bool set_flag = false;
f009ff26 302 struct bgp *bgp = NULL;
303 struct bgp_table *table = NULL;
304 afi_t afi = 0;
305 safi_t safi = 0;
306 char buf[PREFIX2STR_BUFFER];
307
308 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
309 * then the route selection is deferred
310 */
2ba1fe69 311 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 312 return 0;
313
5f9c1aa2 314 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
315 if (BGP_DEBUG(update, UPDATE_OUT)) {
316 prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
36235319
QY
317 zlog_debug(
318 "Route %s is in workqueue and being processed, not deferred.",
5f9c1aa2 319 buf);
320 }
321 return 0;
322 }
323
f009ff26 324 table = bgp_node_table(rn);
325 if (table) {
326 bgp = table->bgp;
327 afi = table->afi;
328 safi = table->safi;
329 }
330
331 for (old_pi = bgp_node_get_bgp_path_info(rn);
332 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
333 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
334 continue;
335
336 /* Route selection is deferred if there is a stale path which
337 * which indicates peer is in restart mode
338 */
36235319
QY
339 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
340 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 341 set_flag = true;
f009ff26 342 } else {
343 /* If the peer is graceful restart capable and peer is
344 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
345 */
346 peer = old_pi->peer;
36235319
QY
347 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
348 && BGP_PEER_RESTARTING_MODE(peer)
349 && (old_pi
350 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 351 set_flag = true;
f009ff26 352 }
353 }
354 if (set_flag)
355 break;
356 }
357
358 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
359 * is active
360 */
2ba1fe69 361 if (set_flag && table) {
f009ff26 362 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
363 SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
364 prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
365 if (rn->rt_node == NULL)
366 rn->rt_node = listnode_add(
367 bgp->gr_info[afi][safi].route_list, rn);
368 if (BGP_DEBUG(update, UPDATE_OUT))
369 zlog_debug("DEFER route %s, rn %p, node %p",
36235319 370 buf, rn, rn->rt_node);
f009ff26 371 return 0;
372 }
373 }
374 return -1;
375}
376
40381db7 377void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 378{
4b7e6066 379 struct bgp_path_info *top;
718e3744 380
6f94b685 381 top = bgp_node_get_bgp_path_info(rn);
d62a17ae 382
6f94b685 383 pi->next = top;
40381db7 384 pi->prev = NULL;
d62a17ae 385 if (top)
40381db7 386 top->prev = pi;
6f94b685 387 bgp_node_set_bgp_path_info(rn, pi);
d62a17ae 388
40381db7 389 bgp_path_info_lock(pi);
d62a17ae 390 bgp_lock_node(rn);
40381db7 391 peer_lock(pi->peer); /* bgp_path_info peer reference */
f009ff26 392 bgp_node_set_defer_flag(rn, false);
718e3744 393}
394
d62a17ae 395/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 396 completion callback *only* */
40381db7 397void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi)
718e3744 398{
40381db7
DS
399 if (pi->next)
400 pi->next->prev = pi->prev;
401 if (pi->prev)
402 pi->prev->next = pi->next;
d62a17ae 403 else
6f94b685 404 bgp_node_set_bgp_path_info(rn, pi->next);
d62a17ae 405
40381db7
DS
406 bgp_path_info_mpath_dequeue(pi);
407 bgp_path_info_unlock(pi);
d62a17ae 408 bgp_unlock_node(rn);
718e3744 409}
410
40381db7 411void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi)
b40d939b 412{
40381db7 413 bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 414 /* set of previous already took care of pcount */
40381db7 415 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 416}
417
18ee8310 418/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
419 called when a route is deleted and then quickly re-added before the
420 deletion has been processed */
40381db7 421void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi)
8d45210e 422{
40381db7 423 bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED);
d62a17ae 424 /* unset of previous already took care of pcount */
40381db7 425 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
426}
427
d62a17ae 428/* Adjust pcount as required */
40381db7 429static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi)
1a392d46 430{
d62a17ae 431 struct bgp_table *table;
67174041 432
d62a17ae 433 assert(rn && bgp_node_table(rn));
40381db7 434 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 435
d62a17ae 436 table = bgp_node_table(rn);
67174041 437
40381db7 438 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 439 return;
440
40381db7
DS
441 if (!BGP_PATH_COUNTABLE(pi)
442 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 443
40381db7 444 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 445
446 /* slight hack, but more robust against errors. */
40381db7
DS
447 if (pi->peer->pcount[table->afi][table->safi])
448 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 449 else
450971aa 450 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 451 "Asked to decrement 0 prefix count for peer");
40381db7
DS
452 } else if (BGP_PATH_COUNTABLE(pi)
453 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
454 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
455 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 456 }
1a392d46
PJ
457}
458
40381db7
DS
459static int bgp_label_index_differs(struct bgp_path_info *pi1,
460 struct bgp_path_info *pi2)
28d58fd7 461{
40381db7 462 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 463}
1a392d46 464
18ee8310 465/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
466 * This is here primarily to keep prefix-count in check.
467 */
40381db7 468void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 469 uint32_t flag)
1a392d46 470{
40381db7 471 SET_FLAG(pi->flags, flag);
d62a17ae 472
473 /* early bath if we know it's not a flag that changes countability state
474 */
475 if (!CHECK_FLAG(flag,
1defdda8 476 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 477 return;
478
40381db7 479 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
480}
481
40381db7 482void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi,
18ee8310 483 uint32_t flag)
1a392d46 484{
40381db7 485 UNSET_FLAG(pi->flags, flag);
d62a17ae 486
487 /* early bath if we know it's not a flag that changes countability state
488 */
489 if (!CHECK_FLAG(flag,
1defdda8 490 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 491 return;
492
40381db7 493 bgp_pcount_adjust(rn, pi);
1a392d46
PJ
494}
495
718e3744 496/* Get MED value. If MED value is missing and "bgp bestpath
497 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 498static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 499{
500 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
501 return attr->med;
502 else {
892fedb6 503 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 504 return BGP_MED_MAX;
505 else
506 return 0;
507 }
718e3744 508}
509
40381db7 510void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 511{
40381db7
DS
512 if (pi->addpath_rx_id)
513 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
514 pi->addpath_rx_id);
d62a17ae 515 else
40381db7 516 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 517}
9fbdd100 518
d62a17ae 519/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
520 */
18ee8310
DS
521static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
522 struct bgp_path_info *exist, int *paths_eq,
523 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
524 char *pfx_buf, afi_t afi, safi_t safi,
525 enum bgp_path_selection_reason *reason)
d62a17ae 526{
527 struct attr *newattr, *existattr;
528 bgp_peer_sort_t new_sort;
529 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
530 uint32_t new_pref;
531 uint32_t exist_pref;
532 uint32_t new_med;
533 uint32_t exist_med;
534 uint32_t new_weight;
535 uint32_t exist_weight;
d62a17ae 536 uint32_t newm, existm;
537 struct in_addr new_id;
538 struct in_addr exist_id;
539 int new_cluster;
540 int exist_cluster;
541 int internal_as_route;
542 int confed_as_route;
04d14c8b 543 int ret = 0;
d62a17ae 544 char new_buf[PATH_ADDPATH_STR_BUFFER];
545 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
546 uint32_t new_mm_seq;
547 uint32_t exist_mm_seq;
6d8c603a 548 int nh_cmp;
d62a17ae 549
550 *paths_eq = 0;
551
552 /* 0. Null check. */
553 if (new == NULL) {
fdf81fa0 554 *reason = bgp_path_selection_none;
d62a17ae 555 if (debug)
556 zlog_debug("%s: new is NULL", pfx_buf);
557 return 0;
558 }
2ec1e66f 559
d62a17ae 560 if (debug)
18ee8310 561 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 562
d62a17ae 563 if (exist == NULL) {
fdf81fa0 564 *reason = bgp_path_selection_first;
d62a17ae 565 if (debug)
566 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
567 new_buf);
568 return 1;
569 }
2ec1e66f 570
d62a17ae 571 if (debug) {
18ee8310 572 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 573 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
574 pfx_buf, new_buf, new->flags, exist_buf,
575 exist->flags);
576 }
8ff56318 577
d62a17ae 578 newattr = new->attr;
579 existattr = exist->attr;
580
581 /* For EVPN routes, we cannot just go by local vs remote, we have to
582 * look at the MAC mobility sequence number, if present.
583 */
584 if (safi == SAFI_EVPN) {
585 /* This is an error condition described in RFC 7432 Section
586 * 15.2. The RFC
587 * states that in this scenario "the PE MUST alert the operator"
588 * but it
589 * does not state what other action to take. In order to provide
590 * some
591 * consistency in this scenario we are going to prefer the path
592 * with the
593 * sticky flag.
594 */
595 if (newattr->sticky != existattr->sticky) {
596 if (!debug) {
597 prefix2str(&new->net->p, pfx_buf,
598 sizeof(*pfx_buf)
599 * PREFIX2STR_BUFFER);
18ee8310
DS
600 bgp_path_info_path_with_addpath_rx_str(new,
601 new_buf);
602 bgp_path_info_path_with_addpath_rx_str(
603 exist, exist_buf);
d62a17ae 604 }
605
606 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 607 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
608 if (debug)
609 zlog_debug(
610 "%s: %s wins over %s due to sticky MAC flag",
611 pfx_buf, new_buf, exist_buf);
d62a17ae 612 return 1;
613 }
614
615 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 616 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
617 if (debug)
618 zlog_debug(
619 "%s: %s loses to %s due to sticky MAC flag",
620 pfx_buf, new_buf, exist_buf);
d62a17ae 621 return 0;
622 }
623 }
128ea8ab 624
d62a17ae 625 new_mm_seq = mac_mobility_seqnum(newattr);
626 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 627
d62a17ae 628 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 629 *reason = bgp_path_selection_evpn_seq;
d62a17ae 630 if (debug)
631 zlog_debug(
632 "%s: %s wins over %s due to MM seq %u > %u",
633 pfx_buf, new_buf, exist_buf, new_mm_seq,
634 exist_mm_seq);
635 return 1;
636 }
8ff56318 637
d62a17ae 638 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 639 *reason = bgp_path_selection_evpn_seq;
d62a17ae 640 if (debug)
641 zlog_debug(
642 "%s: %s loses to %s due to MM seq %u < %u",
643 pfx_buf, new_buf, exist_buf, new_mm_seq,
644 exist_mm_seq);
645 return 0;
646 }
6d8c603a
AK
647
648 /*
649 * if sequence numbers are the same path with the lowest IP
650 * wins
651 */
652 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
653 if (nh_cmp < 0) {
fdf81fa0 654 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
655 if (debug)
656 zlog_debug(
657 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
658 pfx_buf, new_buf, exist_buf, new_mm_seq,
659 inet_ntoa(new->attr->nexthop));
660 return 1;
661 }
662 if (nh_cmp > 0) {
fdf81fa0 663 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
664 if (debug)
665 zlog_debug(
666 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
667 pfx_buf, new_buf, exist_buf, new_mm_seq,
668 inet_ntoa(new->attr->nexthop));
669 return 0;
670 }
d62a17ae 671 }
9fbdd100 672
d62a17ae 673 /* 1. Weight check. */
d62a17ae 674 new_weight = newattr->weight;
675 exist_weight = existattr->weight;
8ff56318 676
d62a17ae 677 if (new_weight > exist_weight) {
fdf81fa0 678 *reason = bgp_path_selection_weight;
d62a17ae 679 if (debug)
680 zlog_debug("%s: %s wins over %s due to weight %d > %d",
681 pfx_buf, new_buf, exist_buf, new_weight,
682 exist_weight);
683 return 1;
684 }
718e3744 685
d62a17ae 686 if (new_weight < exist_weight) {
fdf81fa0 687 *reason = bgp_path_selection_weight;
d62a17ae 688 if (debug)
689 zlog_debug("%s: %s loses to %s due to weight %d < %d",
690 pfx_buf, new_buf, exist_buf, new_weight,
691 exist_weight);
692 return 0;
693 }
9fbdd100 694
d62a17ae 695 /* 2. Local preference check. */
696 new_pref = exist_pref = bgp->default_local_pref;
697
698 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
699 new_pref = newattr->local_pref;
700 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
701 exist_pref = existattr->local_pref;
702
703 if (new_pref > exist_pref) {
fdf81fa0 704 *reason = bgp_path_selection_local_pref;
d62a17ae 705 if (debug)
706 zlog_debug(
707 "%s: %s wins over %s due to localpref %d > %d",
708 pfx_buf, new_buf, exist_buf, new_pref,
709 exist_pref);
710 return 1;
711 }
718e3744 712
d62a17ae 713 if (new_pref < exist_pref) {
fdf81fa0 714 *reason = bgp_path_selection_local_pref;
d62a17ae 715 if (debug)
716 zlog_debug(
717 "%s: %s loses to %s due to localpref %d < %d",
718 pfx_buf, new_buf, exist_buf, new_pref,
719 exist_pref);
720 return 0;
721 }
9fbdd100 722
d62a17ae 723 /* 3. Local route check. We prefer:
724 * - BGP_ROUTE_STATIC
725 * - BGP_ROUTE_AGGREGATE
726 * - BGP_ROUTE_REDISTRIBUTE
727 */
90f4f482 728 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
729 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 730 *reason = bgp_path_selection_local_route;
d62a17ae 731 if (debug)
732 zlog_debug(
733 "%s: %s wins over %s due to preferred BGP_ROUTE type",
734 pfx_buf, new_buf, exist_buf);
735 return 1;
736 }
718e3744 737
90f4f482 738 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 739 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 740 *reason = bgp_path_selection_local_route;
d62a17ae 741 if (debug)
742 zlog_debug(
743 "%s: %s loses to %s due to preferred BGP_ROUTE type",
744 pfx_buf, new_buf, exist_buf);
745 return 0;
6811845b 746 }
718e3744 747
d62a17ae 748 /* 4. AS path length check. */
892fedb6 749 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 750 int exist_hops = aspath_count_hops(existattr->aspath);
751 int exist_confeds = aspath_count_confeds(existattr->aspath);
752
892fedb6 753 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 754 int aspath_hops;
755
756 aspath_hops = aspath_count_hops(newattr->aspath);
757 aspath_hops += aspath_count_confeds(newattr->aspath);
758
759 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 760 *reason = bgp_path_selection_confed_as_path;
d62a17ae 761 if (debug)
762 zlog_debug(
763 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
764 pfx_buf, new_buf, exist_buf,
765 aspath_hops,
766 (exist_hops + exist_confeds));
767 return 1;
768 }
769
770 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 771 *reason = bgp_path_selection_confed_as_path;
d62a17ae 772 if (debug)
773 zlog_debug(
774 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
775 pfx_buf, new_buf, exist_buf,
776 aspath_hops,
777 (exist_hops + exist_confeds));
778 return 0;
779 }
780 } else {
781 int newhops = aspath_count_hops(newattr->aspath);
782
783 if (newhops < exist_hops) {
fdf81fa0 784 *reason = bgp_path_selection_as_path;
d62a17ae 785 if (debug)
786 zlog_debug(
787 "%s: %s wins over %s due to aspath hopcount %d < %d",
788 pfx_buf, new_buf, exist_buf,
789 newhops, exist_hops);
790 return 1;
791 }
792
793 if (newhops > exist_hops) {
fdf81fa0 794 *reason = bgp_path_selection_as_path;
d62a17ae 795 if (debug)
796 zlog_debug(
797 "%s: %s loses to %s due to aspath hopcount %d > %d",
798 pfx_buf, new_buf, exist_buf,
799 newhops, exist_hops);
800 return 0;
801 }
802 }
803 }
9fbdd100 804
d62a17ae 805 /* 5. Origin check. */
806 if (newattr->origin < existattr->origin) {
fdf81fa0 807 *reason = bgp_path_selection_origin;
d62a17ae 808 if (debug)
809 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
810 pfx_buf, new_buf, exist_buf,
811 bgp_origin_long_str[newattr->origin],
812 bgp_origin_long_str[existattr->origin]);
813 return 1;
814 }
718e3744 815
d62a17ae 816 if (newattr->origin > existattr->origin) {
fdf81fa0 817 *reason = bgp_path_selection_origin;
d62a17ae 818 if (debug)
819 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
820 pfx_buf, new_buf, exist_buf,
821 bgp_origin_long_str[newattr->origin],
822 bgp_origin_long_str[existattr->origin]);
823 return 0;
824 }
718e3744 825
d62a17ae 826 /* 6. MED check. */
827 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
828 && aspath_count_hops(existattr->aspath) == 0);
829 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
830 && aspath_count_confeds(existattr->aspath) > 0
831 && aspath_count_hops(newattr->aspath) == 0
832 && aspath_count_hops(existattr->aspath) == 0);
833
892fedb6
DA
834 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
835 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 836 || aspath_cmp_left(newattr->aspath, existattr->aspath)
837 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
838 || internal_as_route) {
839 new_med = bgp_med_value(new->attr, bgp);
840 exist_med = bgp_med_value(exist->attr, bgp);
841
842 if (new_med < exist_med) {
fdf81fa0 843 *reason = bgp_path_selection_med;
d62a17ae 844 if (debug)
845 zlog_debug(
846 "%s: %s wins over %s due to MED %d < %d",
847 pfx_buf, new_buf, exist_buf, new_med,
848 exist_med);
849 return 1;
850 }
8ff56318 851
d62a17ae 852 if (new_med > exist_med) {
fdf81fa0 853 *reason = bgp_path_selection_med;
d62a17ae 854 if (debug)
855 zlog_debug(
856 "%s: %s loses to %s due to MED %d > %d",
857 pfx_buf, new_buf, exist_buf, new_med,
858 exist_med);
859 return 0;
860 }
861 }
9fbdd100 862
d62a17ae 863 /* 7. Peer type check. */
864 new_sort = new->peer->sort;
865 exist_sort = exist->peer->sort;
866
867 if (new_sort == BGP_PEER_EBGP
868 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 869 *reason = bgp_path_selection_peer;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s wins over %s due to eBGP peer > iBGP peer",
873 pfx_buf, new_buf, exist_buf);
874 return 1;
875 }
718e3744 876
d62a17ae 877 if (exist_sort == BGP_PEER_EBGP
878 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 879 *reason = bgp_path_selection_peer;
d62a17ae 880 if (debug)
881 zlog_debug(
882 "%s: %s loses to %s due to iBGP peer < eBGP peer",
883 pfx_buf, new_buf, exist_buf);
884 return 0;
885 }
8ff56318 886
d62a17ae 887 /* 8. IGP metric check. */
888 newm = existm = 0;
8ff56318 889
d62a17ae 890 if (new->extra)
891 newm = new->extra->igpmetric;
892 if (exist->extra)
893 existm = exist->extra->igpmetric;
9fbdd100 894
d62a17ae 895 if (newm < existm) {
896 if (debug)
897 zlog_debug(
898 "%s: %s wins over %s due to IGP metric %d < %d",
899 pfx_buf, new_buf, exist_buf, newm, existm);
900 ret = 1;
901 }
718e3744 902
d62a17ae 903 if (newm > existm) {
904 if (debug)
905 zlog_debug(
906 "%s: %s loses to %s due to IGP metric %d > %d",
907 pfx_buf, new_buf, exist_buf, newm, existm);
908 ret = 0;
5e242b0d 909 }
5e242b0d 910
d62a17ae 911 /* 9. Same IGP metric. Compare the cluster list length as
912 representative of IGP hops metric. Rewrite the metric value
913 pair (newm, existm) with the cluster list length. Prefer the
914 path with smaller cluster list length. */
915 if (newm == existm) {
bf0d28dc
DS
916 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
917 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 918 && (mpath_cfg == NULL
919 || CHECK_FLAG(
920 mpath_cfg->ibgp_flags,
921 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
922 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
923 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
924
925 if (newm < existm) {
926 if (debug)
927 zlog_debug(
928 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
929 pfx_buf, new_buf, exist_buf,
930 newm, existm);
931 ret = 1;
932 }
933
934 if (newm > existm) {
935 if (debug)
936 zlog_debug(
937 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
938 pfx_buf, new_buf, exist_buf,
939 newm, existm);
940 ret = 0;
941 }
942 }
943 }
31a4638f 944
d62a17ae 945 /* 10. confed-external vs. confed-internal */
946 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
947 if (new_sort == BGP_PEER_CONFED
948 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 949 *reason = bgp_path_selection_confed;
d62a17ae 950 if (debug)
951 zlog_debug(
952 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
953 pfx_buf, new_buf, exist_buf);
954 return 1;
955 }
718e3744 956
d62a17ae 957 if (exist_sort == BGP_PEER_CONFED
958 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 959 *reason = bgp_path_selection_confed;
d62a17ae 960 if (debug)
961 zlog_debug(
962 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
963 pfx_buf, new_buf, exist_buf);
964 return 0;
965 }
966 }
718e3744 967
d62a17ae 968 /* 11. Maximum path check. */
969 if (newm == existm) {
970 /* If one path has a label but the other does not, do not treat
971 * them as equals for multipath
972 */
a4d82a8a 973 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 974 != (exist->extra
b57ba6d2 975 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 976 if (debug)
977 zlog_debug(
978 "%s: %s and %s cannot be multipath, one has a label while the other does not",
979 pfx_buf, new_buf, exist_buf);
892fedb6
DA
980 } else if (CHECK_FLAG(bgp->flags,
981 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 982
983 /*
984 * For the two paths, all comparison steps till IGP
985 * metric
986 * have succeeded - including AS_PATH hop count. Since
987 * 'bgp
988 * bestpath as-path multipath-relax' knob is on, we
989 * don't need
990 * an exact match of AS_PATH. Thus, mark the paths are
991 * equal.
992 * That will trigger both these paths to get into the
993 * multipath
994 * array.
995 */
996 *paths_eq = 1;
997
998 if (debug)
999 zlog_debug(
1000 "%s: %s and %s are equal via multipath-relax",
1001 pfx_buf, new_buf, exist_buf);
1002 } else if (new->peer->sort == BGP_PEER_IBGP) {
1003 if (aspath_cmp(new->attr->aspath,
1004 exist->attr->aspath)) {
1005 *paths_eq = 1;
1006
1007 if (debug)
1008 zlog_debug(
1009 "%s: %s and %s are equal via matching aspaths",
1010 pfx_buf, new_buf, exist_buf);
1011 }
1012 } else if (new->peer->as == exist->peer->as) {
1013 *paths_eq = 1;
1014
1015 if (debug)
1016 zlog_debug(
1017 "%s: %s and %s are equal via same remote-as",
1018 pfx_buf, new_buf, exist_buf);
1019 }
1020 } else {
1021 /*
1022 * TODO: If unequal cost ibgp multipath is enabled we can
1023 * mark the paths as equal here instead of returning
1024 */
1025 if (debug) {
1026 if (ret == 1)
1027 zlog_debug(
1028 "%s: %s wins over %s after IGP metric comparison",
1029 pfx_buf, new_buf, exist_buf);
1030 else
1031 zlog_debug(
1032 "%s: %s loses to %s after IGP metric comparison",
1033 pfx_buf, new_buf, exist_buf);
1034 }
fdf81fa0 1035 *reason = bgp_path_selection_igp_metric;
d62a17ae 1036 return ret;
1037 }
718e3744 1038
d62a17ae 1039 /* 12. If both paths are external, prefer the path that was received
1040 first (the oldest one). This step minimizes route-flap, since a
1041 newer path won't displace an older one, even if it was the
1042 preferred route based on the additional decision criteria below. */
892fedb6 1043 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1044 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1045 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1046 *reason = bgp_path_selection_older;
d62a17ae 1047 if (debug)
1048 zlog_debug(
1049 "%s: %s wins over %s due to oldest external",
1050 pfx_buf, new_buf, exist_buf);
1051 return 1;
1052 }
9fbdd100 1053
1defdda8 1054 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1055 *reason = bgp_path_selection_older;
d62a17ae 1056 if (debug)
1057 zlog_debug(
1058 "%s: %s loses to %s due to oldest external",
1059 pfx_buf, new_buf, exist_buf);
1060 return 0;
1061 }
1062 }
718e3744 1063
d62a17ae 1064 /* 13. Router-ID comparision. */
1065 /* If one of the paths is "stale", the corresponding peer router-id will
1066 * be 0 and would always win over the other path. If originator id is
1067 * used for the comparision, it will decide which path is better.
1068 */
1069 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1070 new_id.s_addr = newattr->originator_id.s_addr;
1071 else
1072 new_id.s_addr = new->peer->remote_id.s_addr;
1073 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1074 exist_id.s_addr = existattr->originator_id.s_addr;
1075 else
1076 exist_id.s_addr = exist->peer->remote_id.s_addr;
1077
1078 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1079 *reason = bgp_path_selection_router_id;
d62a17ae 1080 if (debug)
1081 zlog_debug(
1082 "%s: %s wins over %s due to Router-ID comparison",
1083 pfx_buf, new_buf, exist_buf);
1084 return 1;
1085 }
718e3744 1086
d62a17ae 1087 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1088 *reason = bgp_path_selection_router_id;
d62a17ae 1089 if (debug)
1090 zlog_debug(
1091 "%s: %s loses to %s due to Router-ID comparison",
1092 pfx_buf, new_buf, exist_buf);
1093 return 0;
1094 }
9fbdd100 1095
d62a17ae 1096 /* 14. Cluster length comparision. */
1097 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1098 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1099
1100 if (new_cluster < exist_cluster) {
fdf81fa0 1101 *reason = bgp_path_selection_cluster_length;
d62a17ae 1102 if (debug)
1103 zlog_debug(
1104 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1105 pfx_buf, new_buf, exist_buf, new_cluster,
1106 exist_cluster);
1107 return 1;
1108 }
718e3744 1109
d62a17ae 1110 if (new_cluster > exist_cluster) {
fdf81fa0 1111 *reason = bgp_path_selection_cluster_length;
d62a17ae 1112 if (debug)
1113 zlog_debug(
1114 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1115 pfx_buf, new_buf, exist_buf, new_cluster,
1116 exist_cluster);
1117 return 0;
1118 }
9fbdd100 1119
d62a17ae 1120 /* 15. Neighbor address comparision. */
1121 /* Do this only if neither path is "stale" as stale paths do not have
1122 * valid peer information (as the connection may or may not be up).
1123 */
1defdda8 1124 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1125 *reason = bgp_path_selection_stale;
d62a17ae 1126 if (debug)
1127 zlog_debug(
1128 "%s: %s wins over %s due to latter path being STALE",
1129 pfx_buf, new_buf, exist_buf);
1130 return 1;
1131 }
0de5153c 1132
1defdda8 1133 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1134 *reason = bgp_path_selection_stale;
d62a17ae 1135 if (debug)
1136 zlog_debug(
1137 "%s: %s loses to %s due to former path being STALE",
1138 pfx_buf, new_buf, exist_buf);
1139 return 0;
1140 }
718e3744 1141
d62a17ae 1142 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1143 if (new->peer->su_remote == NULL) {
1144 *reason = bgp_path_selection_local_configured;
d62a17ae 1145 return 0;
fdf81fa0
DS
1146 }
1147 if (exist->peer->su_remote == NULL) {
1148 *reason = bgp_path_selection_local_configured;
d62a17ae 1149 return 1;
fdf81fa0 1150 }
9fbdd100 1151
d62a17ae 1152 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1153
1154 if (ret == 1) {
fdf81fa0 1155 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1156 if (debug)
1157 zlog_debug(
1158 "%s: %s loses to %s due to Neighor IP comparison",
1159 pfx_buf, new_buf, exist_buf);
1160 return 0;
1161 }
1162
1163 if (ret == -1) {
fdf81fa0 1164 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1165 if (debug)
1166 zlog_debug(
1167 "%s: %s wins over %s due to Neighor IP comparison",
1168 pfx_buf, new_buf, exist_buf);
1169 return 1;
1170 }
9fbdd100 1171
fdf81fa0 1172 *reason = bgp_path_selection_default;
d62a17ae 1173 if (debug)
1174 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1175 pfx_buf, new_buf, exist_buf);
718e3744 1176
d62a17ae 1177 return 1;
718e3744 1178}
1179
65efcfce
LB
1180/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1181 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1182 * multipath is enabled
65efcfce 1183 * This version is compatible with */
18ee8310
DS
1184int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1185 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1186 afi_t afi, safi_t safi,
1187 enum bgp_path_selection_reason *reason)
d62a17ae 1188{
1189 int paths_eq;
1190 int ret;
18ee8310 1191 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1192 afi, safi, reason);
d62a17ae 1193
1194 if (paths_eq)
1195 ret = 0;
1196 else {
1197 if (ret == 1)
1198 ret = -1;
1199 else
1200 ret = 1;
1201 }
1202 return ret;
65efcfce
LB
1203}
1204
d62a17ae 1205static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
1206 struct attr *attr, afi_t afi,
1207 safi_t safi)
718e3744 1208{
d62a17ae 1209 struct bgp_filter *filter;
718e3744 1210
d62a17ae 1211 filter = &peer->filter[afi][safi];
718e3744 1212
d62a17ae 1213#define FILTER_EXIST_WARN(F, f, filter) \
1214 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1215 zlog_debug("%s: Could not find configured input %s-list %s!", \
1216 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1217
1218 if (DISTRIBUTE_IN_NAME(filter)) {
1219 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1220
1221 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1222 return FILTER_DENY;
1223 }
1224
1225 if (PREFIX_LIST_IN_NAME(filter)) {
1226 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1227
1228 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1229 return FILTER_DENY;
1230 }
1231
1232 if (FILTER_LIST_IN_NAME(filter)) {
1233 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1234
1235 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1236 == AS_FILTER_DENY)
1237 return FILTER_DENY;
1238 }
1239
1240 return FILTER_PERMIT;
650f76c2 1241#undef FILTER_EXIST_WARN
718e3744 1242}
1243
d62a17ae 1244static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1245 struct attr *attr, afi_t afi,
1246 safi_t safi)
718e3744 1247{
d62a17ae 1248 struct bgp_filter *filter;
1249
1250 filter = &peer->filter[afi][safi];
1251
1252#define FILTER_EXIST_WARN(F, f, filter) \
1253 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1254 zlog_debug("%s: Could not find configured output %s-list %s!", \
1255 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1256
d62a17ae 1257 if (DISTRIBUTE_OUT_NAME(filter)) {
1258 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1259
d62a17ae 1260 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1261 return FILTER_DENY;
1262 }
1263
1264 if (PREFIX_LIST_OUT_NAME(filter)) {
1265 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1266
d62a17ae 1267 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1268 == PREFIX_DENY)
1269 return FILTER_DENY;
1270 }
718e3744 1271
d62a17ae 1272 if (FILTER_LIST_OUT_NAME(filter)) {
1273 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1274
d62a17ae 1275 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1276 == AS_FILTER_DENY)
1277 return FILTER_DENY;
1278 }
718e3744 1279
d62a17ae 1280 return FILTER_PERMIT;
650f76c2 1281#undef FILTER_EXIST_WARN
718e3744 1282}
1283
1284/* If community attribute includes no_export then return 1. */
d62a17ae 1285static int bgp_community_filter(struct peer *peer, struct attr *attr)
1286{
1287 if (attr->community) {
1288 /* NO_ADVERTISE check. */
1289 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1290 return 1;
1291
1292 /* NO_EXPORT check. */
1293 if (peer->sort == BGP_PEER_EBGP
1294 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1295 return 1;
1296
1297 /* NO_EXPORT_SUBCONFED check. */
1298 if (peer->sort == BGP_PEER_EBGP
1299 || peer->sort == BGP_PEER_CONFED)
1300 if (community_include(attr->community,
1301 COMMUNITY_NO_EXPORT_SUBCONFED))
1302 return 1;
1303 }
1304 return 0;
718e3744 1305}
1306
1307/* Route reflection loop check. */
d62a17ae 1308static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1309{
d62a17ae 1310 struct in_addr cluster_id;
718e3744 1311
d62a17ae 1312 if (attr->cluster) {
1313 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1314 cluster_id = peer->bgp->cluster_id;
1315 else
1316 cluster_id = peer->bgp->router_id;
1317
1318 if (cluster_loop_check(attr->cluster, cluster_id))
1319 return 1;
1320 }
1321 return 0;
718e3744 1322}
6b0655a2 1323
d62a17ae 1324static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1325 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1326 const char *rmap_name, mpls_label_t *label,
196c6b09 1327 uint32_t num_labels, struct bgp_node *rn)
718e3744 1328{
d62a17ae 1329 struct bgp_filter *filter;
82b692c0
LK
1330 struct bgp_path_info rmap_path = { 0 };
1331 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1332 route_map_result_t ret;
1333 struct route_map *rmap = NULL;
718e3744 1334
d62a17ae 1335 filter = &peer->filter[afi][safi];
718e3744 1336
d62a17ae 1337 /* Apply default weight value. */
1338 if (peer->weight[afi][safi])
1339 attr->weight = peer->weight[afi][safi];
718e3744 1340
d62a17ae 1341 if (rmap_name) {
1342 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1343
d62a17ae 1344 if (rmap == NULL)
1345 return RMAP_DENY;
1346 } else {
1347 if (ROUTE_MAP_IN_NAME(filter)) {
1348 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1349
d62a17ae 1350 if (rmap == NULL)
1351 return RMAP_DENY;
1352 }
1353 }
0b16f239 1354
d62a17ae 1355 /* Route map apply. */
1356 if (rmap) {
40381db7 1357 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1358 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1359 rmap_path.peer = peer;
1360 rmap_path.attr = attr;
82b692c0 1361 rmap_path.extra = &extra;
196c6b09
LK
1362 rmap_path.net = rn;
1363
82b692c0
LK
1364 extra.num_labels = num_labels;
1365 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1366 memcpy(extra.label, label,
1367 num_labels * sizeof(mpls_label_t));
718e3744 1368
d62a17ae 1369 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1370
d62a17ae 1371 /* Apply BGP route map to the attribute. */
40381db7 1372 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1373
d62a17ae 1374 peer->rmap_type = 0;
0b16f239 1375
1f2263be 1376 if (ret == RMAP_DENYMATCH)
d62a17ae 1377 return RMAP_DENY;
0b16f239 1378 }
d62a17ae 1379 return RMAP_PERMIT;
0b16f239
DS
1380}
1381
d62a17ae 1382static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1383 struct attr *attr, afi_t afi, safi_t safi,
1384 const char *rmap_name)
0b16f239 1385{
40381db7 1386 struct bgp_path_info rmap_path;
d62a17ae 1387 route_map_result_t ret;
1388 struct route_map *rmap = NULL;
d7c0a89a 1389 uint8_t rmap_type;
0b16f239 1390
b787157a
DS
1391 /*
1392 * So if we get to this point and have no rmap_name
1393 * we want to just show the output as it currently
1394 * exists.
1395 */
1396 if (!rmap_name)
1397 return RMAP_PERMIT;
0b16f239 1398
d62a17ae 1399 /* Apply default weight value. */
1400 if (peer->weight[afi][safi])
1401 attr->weight = peer->weight[afi][safi];
0b16f239 1402
b787157a 1403 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1404
b787157a
DS
1405 /*
1406 * If we have a route map name and we do not find
1407 * the routemap that means we have an implicit
1408 * deny.
1409 */
1410 if (rmap == NULL)
1411 return RMAP_DENY;
0b16f239 1412
40381db7 1413 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1414 /* Route map apply. */
b787157a 1415 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1416 rmap_path.peer = peer;
1417 rmap_path.attr = attr;
0b16f239 1418
0f672529 1419 rmap_type = peer->rmap_type;
b787157a 1420 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1421
b787157a 1422 /* Apply BGP route map to the attribute. */
40381db7 1423 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1424
0f672529 1425 peer->rmap_type = rmap_type;
b787157a
DS
1426
1427 if (ret == RMAP_DENYMATCH)
1428 /*
1429 * caller has multiple error paths with bgp_attr_flush()
1430 */
1431 return RMAP_DENY;
ac41b2a2 1432
d62a17ae 1433 return RMAP_PERMIT;
718e3744 1434}
6b0655a2 1435
5000f21c 1436/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1437static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1438 struct peer *peer, struct attr *attr)
1439{
1440 if (peer->sort == BGP_PEER_EBGP
1441 && (peer_af_flag_check(peer, afi, safi,
1442 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1443 || peer_af_flag_check(peer, afi, safi,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1445 || peer_af_flag_check(peer, afi, safi,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1447 || peer_af_flag_check(peer, afi, safi,
1448 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1449 // Take action on the entire aspath
1450 if (peer_af_flag_check(peer, afi, safi,
1451 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1452 || peer_af_flag_check(peer, afi, safi,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1454 if (peer_af_flag_check(
1455 peer, afi, safi,
1456 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1457 attr->aspath = aspath_replace_private_asns(
bf26b80e 1458 attr->aspath, bgp->as, peer->as);
d62a17ae 1459
1460 // The entire aspath consists of private ASNs so create
1461 // an empty aspath
1462 else if (aspath_private_as_check(attr->aspath))
1463 attr->aspath = aspath_empty_get();
1464
1465 // There are some public and some private ASNs, remove
1466 // the private ASNs
1467 else
1468 attr->aspath = aspath_remove_private_asns(
bf26b80e 1469 attr->aspath, peer->as);
d62a17ae 1470 }
1471
1472 // 'all' was not specified so the entire aspath must be private
1473 // ASNs
1474 // for us to do anything
1475 else if (aspath_private_as_check(attr->aspath)) {
1476 if (peer_af_flag_check(
1477 peer, afi, safi,
1478 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1479 attr->aspath = aspath_replace_private_asns(
bf26b80e 1480 attr->aspath, bgp->as, peer->as);
d62a17ae 1481 else
1482 attr->aspath = aspath_empty_get();
1483 }
1484 }
5000f21c
DS
1485}
1486
c7122e14 1487/* If this is an EBGP peer with as-override */
d62a17ae 1488static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1489 struct peer *peer, struct attr *attr)
1490{
1491 if (peer->sort == BGP_PEER_EBGP
1492 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1493 if (aspath_single_asn_check(attr->aspath, peer->as))
1494 attr->aspath = aspath_replace_specific_asn(
1495 attr->aspath, peer->as, bgp->as);
1496 }
1497}
1498
7f323236
DW
1499void bgp_attr_add_gshut_community(struct attr *attr)
1500{
1501 struct community *old;
1502 struct community *new;
1503 struct community *merge;
1504 struct community *gshut;
1505
1506 old = attr->community;
1507 gshut = community_str2com("graceful-shutdown");
1508
990f4f91 1509 assert(gshut);
1510
7f323236
DW
1511 if (old) {
1512 merge = community_merge(community_dup(old), gshut);
1513
a4d82a8a 1514 if (old->refcnt == 0)
3c1f53de 1515 community_free(&old);
7f323236
DW
1516
1517 new = community_uniq_sort(merge);
3c1f53de 1518 community_free(&merge);
7f323236
DW
1519 } else {
1520 new = community_dup(gshut);
1521 }
1522
3c1f53de 1523 community_free(&gshut);
7f323236
DW
1524 attr->community = new;
1525 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1526
1527 /* When we add the graceful-shutdown community we must also
1528 * lower the local-preference */
1529 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1530 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1531}
1532
1533
d7c0a89a 1534static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1535{
960035b2 1536 if (family == AF_INET) {
975a328e
DA
1537 attr->nexthop.s_addr = INADDR_ANY;
1538 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1539 }
d62a17ae 1540 if (family == AF_INET6)
1541 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1542 if (family == AF_EVPN)
1543 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1544}
1545
40381db7 1546int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 1547 struct update_subgroup *subgrp, struct prefix *p,
1548 struct attr *attr)
1549{
1550 struct bgp_filter *filter;
1551 struct peer *from;
1552 struct peer *peer;
1553 struct peer *onlypeer;
1554 struct bgp *bgp;
40381db7 1555 struct attr *piattr;
d62a17ae 1556 char buf[PREFIX_STRLEN];
b68885f9 1557 route_map_result_t ret;
d62a17ae 1558 int transparent;
1559 int reflect;
1560 afi_t afi;
1561 safi_t safi;
1562 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1563
1564 if (DISABLE_BGP_ANNOUNCE)
1565 return 0;
1566
1567 afi = SUBGRP_AFI(subgrp);
1568 safi = SUBGRP_SAFI(subgrp);
1569 peer = SUBGRP_PEER(subgrp);
1570 onlypeer = NULL;
1571 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1572 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1573
40381db7 1574 from = pi->peer;
d62a17ae 1575 filter = &peer->filter[afi][safi];
1576 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1577 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1578 : pi->attr;
3f9c7369 1579
65efcfce 1580#if ENABLE_BGP_VNC
d62a17ae 1581 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1582 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1583 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1584
1585 /*
1586 * direct and direct_ext type routes originate internally even
1587 * though they can have peer pointers that reference other
1588 * systems
1589 */
1590 prefix2str(p, buf, PREFIX_STRLEN);
1591 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1592 __func__, buf);
1593 samepeer_safe = 1;
1594 }
65efcfce
LB
1595#endif
1596
ddb5b488
PZ
1597 if (((afi == AFI_IP) || (afi == AFI_IP6))
1598 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1599 && (pi->type == ZEBRA_ROUTE_BGP)
1600 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1601
1602 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1603
1604 samepeer_safe = 1;
1605 }
1606
d62a17ae 1607 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1608 * pi is valid */
1609 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1610 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1611 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 1612 return 0;
1613 }
adbac85e 1614
d62a17ae 1615 /* If this is not the bestpath then check to see if there is an enabled
1616 * addpath
1617 * feature that requires us to advertise it */
40381db7 1618 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1619 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
d62a17ae 1620 return 0;
1621 }
1622 }
06370dac 1623
d62a17ae 1624 /* Aggregate-address suppress check. */
40381db7 1625 if (pi->extra && pi->extra->suppress)
d62a17ae 1626 if (!UNSUPPRESS_MAP_NAME(filter)) {
1627 return 0;
1628 }
3f9c7369 1629
13b7e7f0
DS
1630 /*
1631 * If we are doing VRF 2 VRF leaking via the import
1632 * statement, we want to prevent the route going
1633 * off box as that the RT and RD created are localy
1634 * significant and globaly useless.
1635 */
40381db7
DS
1636 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1637 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
13b7e7f0
DS
1638 return 0;
1639
d62a17ae 1640 /* If it's labeled safi, make sure the route has a valid label. */
1641 if (safi == SAFI_LABELED_UNICAST) {
40381db7 1642 mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi);
d62a17ae 1643 if (!bgp_is_valid_label(&label)) {
1644 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1645 zlog_debug("u%" PRIu64 ":s%" PRIu64
1646 " %s/%d is filtered - no label (%p)",
1647 subgrp->update_group->id, subgrp->id,
1648 inet_ntop(p->family, &p->u.prefix,
1649 buf, SU_ADDRSTRLEN),
1650 p->prefixlen, &label);
1651 return 0;
1652 }
1653 }
cd1964ff 1654
d62a17ae 1655 /* Do not send back route to sender. */
1656 if (onlypeer && from == onlypeer) {
1657 return 0;
1658 }
3f9c7369 1659
d62a17ae 1660 /* Do not send the default route in the BGP table if the neighbor is
1661 * configured for default-originate */
1662 if (CHECK_FLAG(peer->af_flags[afi][safi],
1663 PEER_FLAG_DEFAULT_ORIGINATE)) {
1664 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1665 return 0;
1666 else if (p->family == AF_INET6 && p->prefixlen == 0)
1667 return 0;
1668 }
4125bb67 1669
d62a17ae 1670 /* Transparency check. */
1671 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1672 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1673 transparent = 1;
1674 else
1675 transparent = 0;
1676
1677 /* If community is not disabled check the no-export and local. */
40381db7 1678 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1679 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1680 zlog_debug(
1681 "subgrpannouncecheck: community filter check fail");
1682 return 0;
1683 }
3f9c7369 1684
d62a17ae 1685 /* If the attribute has originator-id and it is same as remote
1686 peer's id. */
40381db7
DS
1687 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1688 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1689 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1690 zlog_debug(
1691 "%s [Update:SEND] %s originator-id is same as "
1692 "remote router-id",
1693 onlypeer->host,
1694 prefix2str(p, buf, sizeof(buf)));
1695 return 0;
1696 }
3f9c7369 1697
d62a17ae 1698 /* ORF prefix-list filter check */
1699 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1700 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1701 || CHECK_FLAG(peer->af_cap[afi][safi],
1702 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1703 if (peer->orf_plist[afi][safi]) {
1704 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1705 == PREFIX_DENY) {
1706 if (bgp_debug_update(NULL, p,
1707 subgrp->update_group, 0))
1708 zlog_debug(
1709 "%s [Update:SEND] %s is filtered via ORF",
1710 peer->host,
1711 prefix2str(p, buf,
1712 sizeof(buf)));
1713 return 0;
1714 }
1715 }
1716
1717 /* Output filter check. */
40381db7 1718 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1719 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1720 zlog_debug("%s [Update:SEND] %s is filtered",
1721 peer->host, prefix2str(p, buf, sizeof(buf)));
1722 return 0;
1723 }
3f9c7369 1724
d62a17ae 1725 /* AS path loop check. */
2b31007c
RZ
1726 if (onlypeer && onlypeer->as_path_loop_detection
1727 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1728 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1729 zlog_debug(
1730 "%s [Update:SEND] suppress announcement to peer AS %u "
1731 "that is part of AS path.",
1732 onlypeer->host, onlypeer->as);
1733 return 0;
1734 }
3f9c7369 1735
d62a17ae 1736 /* If we're a CONFED we need to loop check the CONFED ID too */
1737 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1738 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1739 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1740 zlog_debug(
1741 "%s [Update:SEND] suppress announcement to peer AS %u"
1742 " is AS path.",
1743 peer->host, bgp->confed_id);
1744 return 0;
1745 }
3f9c7369 1746 }
3f9c7369 1747
d62a17ae 1748 /* Route-Reflect check. */
1749 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1750 reflect = 1;
1751 else
1752 reflect = 0;
1753
1754 /* IBGP reflection check. */
1755 if (reflect && !samepeer_safe) {
1756 /* A route from a Client peer. */
1757 if (CHECK_FLAG(from->af_flags[afi][safi],
1758 PEER_FLAG_REFLECTOR_CLIENT)) {
1759 /* Reflect to all the Non-Client peers and also to the
1760 Client peers other than the originator. Originator
1761 check
1762 is already done. So there is noting to do. */
1763 /* no bgp client-to-client reflection check. */
892fedb6
DA
1764 if (CHECK_FLAG(bgp->flags,
1765 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 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)
892fedb6
DA
1897 && !CHECK_FLAG(bgp->flags,
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
892fedb6 1948 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
a4d82a8a
PZ
1949 if (peer->sort == BGP_PEER_IBGP
1950 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
1951 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1952 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1953 } else {
1954 bgp_attr_add_gshut_community(attr);
1955 }
1956 }
1957
d62a17ae 1958 /* After route-map has been applied, we check to see if the nexthop to
1959 * be carried in the attribute (that is used for the announcement) can
1960 * be cleared off or not. We do this in all cases where we would be
1961 * setting the nexthop to "ourselves". For IPv6, we only need to
1962 * consider
1963 * the global nexthop here; the link-local nexthop would have been
1964 * cleared
1965 * already, and if not, it is required by the update formation code.
1966 * Also see earlier comments in this function.
1967 */
1968 /*
1969 * If route-map has performed some operation on the nexthop or the peer
1970 * configuration says to pass it unchanged, we cannot reset the nexthop
1971 * here, so only attempt to do it if these aren't true. Note that the
1972 * route-map handler itself might have cleared the nexthop, if for
1973 * example,
1974 * it is configured as 'peer-address'.
1975 */
1976 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 1977 piattr->rmap_change_flags)
d62a17ae 1978 && !transparent
1979 && !CHECK_FLAG(peer->af_flags[afi][safi],
1980 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1981 /* We can reset the nexthop, if setting (or forcing) it to
1982 * 'self' */
1983 if (CHECK_FLAG(peer->af_flags[afi][safi],
1984 PEER_FLAG_NEXTHOP_SELF)
1985 || CHECK_FLAG(peer->af_flags[afi][safi],
1986 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1987 if (!reflect
1988 || CHECK_FLAG(peer->af_flags[afi][safi],
1989 PEER_FLAG_FORCE_NEXTHOP_SELF))
1990 subgroup_announce_reset_nhop(
1991 (peer_cap_enhe(peer, afi, safi)
1992 ? AF_INET6
1993 : p->family),
1994 attr);
1995 } else if (peer->sort == BGP_PEER_EBGP) {
1996 /* Can also reset the nexthop if announcing to EBGP, but
1997 * only if
1998 * no peer in the subgroup is on a shared subnet.
1999 * Note: 3rd party nexthop currently implemented for
2000 * IPv4 only.
2001 */
737af885
BS
2002 if ((p->family == AF_INET) &&
2003 (!bgp_subgrp_multiaccess_check_v4(
2004 piattr->nexthop,
2005 subgrp)))
d62a17ae 2006 subgroup_announce_reset_nhop(
2007 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2008 ? AF_INET6
2009 : p->family),
737af885
BS
2010 attr);
2011
2012 if ((p->family == AF_INET6) &&
2013 (!bgp_subgrp_multiaccess_check_v6(
2014 piattr->mp_nexthop_global,
2015 subgrp)))
2016 subgroup_announce_reset_nhop(
2017 (peer_cap_enhe(peer, afi, safi)
2018 ? AF_INET6
2019 : p->family),
2020 attr);
2021
2022
2023
40381db7 2024 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2025 /*
2026 * This flag is used for leaked vpn-vrf routes
2027 */
2028 int family = p->family;
2029
2030 if (peer_cap_enhe(peer, afi, safi))
2031 family = AF_INET6;
2032
2033 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2034 zlog_debug(
1defdda8 2035 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2036 __func__, family2str(family));
2037 subgroup_announce_reset_nhop(family, attr);
d62a17ae 2038 }
63696f1d 2039 }
960035b2 2040
63696f1d 2041 /* If IPv6/MP and nexthop does not have any override and happens
2042 * to
2043 * be a link-local address, reset it so that we don't pass along
2044 * the
2045 * source's link-local IPv6 address to recipients who may not be
2046 * on
2047 * the same interface.
2048 */
2049 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
2050 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
2051 subgroup_announce_reset_nhop(AF_INET6, attr);
d62a17ae 2052 }
3f9c7369 2053
d62a17ae 2054 return 1;
3f9c7369
DS
2055}
2056
f009ff26 2057static int bgp_route_select_timer_expire(struct thread *thread)
2058{
2059 struct afi_safi_info *info;
2060 afi_t afi;
2061 safi_t safi;
2062 struct bgp *bgp;
2063
2064 info = THREAD_ARG(thread);
2065 afi = info->afi;
2066 safi = info->safi;
2067 bgp = info->bgp;
2068
2069 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2070 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2071 safi);
f009ff26 2072
2073 bgp->gr_info[afi][safi].t_route_select = NULL;
2074
2075 XFREE(MTYPE_TMP, info);
2076
2077 /* Best path selection */
2078 return bgp_best_path_select_defer(bgp, afi, safi);
2079}
2080
d62a17ae 2081void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
2082 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2083 struct bgp_path_info_pair *result, afi_t afi,
2084 safi_t safi)
2085{
2086 struct bgp_path_info *new_select;
2087 struct bgp_path_info *old_select;
40381db7
DS
2088 struct bgp_path_info *pi;
2089 struct bgp_path_info *pi1;
2090 struct bgp_path_info *pi2;
2091 struct bgp_path_info *nextpi = NULL;
d62a17ae 2092 int paths_eq, do_mpath, debug;
2093 struct list mp_list;
2094 char pfx_buf[PREFIX2STR_BUFFER];
2095 char path_buf[PATH_ADDPATH_STR_BUFFER];
2096
2097 bgp_mp_list_init(&mp_list);
2098 do_mpath =
2099 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2100
2101 debug = bgp_debug_bestpath(&rn->p);
2102
2103 if (debug)
2104 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2105
2106 /* bgp deterministic-med */
2107 new_select = NULL;
892fedb6 2108 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 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
892fedb6 2215 if (CHECK_FLAG(bgp->flags, 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
892fedb6 2448 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
f4c713ae
LB
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(
892fedb6
DA
2454 "%s: bgp delete in progress, ignoring event, p=%s",
2455 __func__, pfx_buf);
f4c713ae
LB
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))
2089dd80 2489 zlog_debug("SELECT_DEFER flag set for route %p", rn);
f009ff26 2490 return;
2491 }
2492
d62a17ae 2493 /* Best path selection. */
2494 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2495 afi, safi);
2496 old_select = old_and_new.old;
2497 new_select = old_and_new.new;
2498
2499 /* Do we need to allocate or free labels?
2500 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2501 * necessary to do this upon changes to best path. Exceptions:
2502 * - label index has changed -> recalculate resulting label
2503 * - path_info sub_type changed -> switch to/from implicit-null
2504 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2505 */
318cac96 2506 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2507 if (new_select) {
2508 if (!old_select
2509 || bgp_label_index_differs(new_select, old_select)
57592a53
AD
2510 || new_select->sub_type != old_select->sub_type
2511 || !bgp_is_valid_label(&rn->local_label)) {
2512 /* Enforced penultimate hop popping:
2513 * implicit-null for local routes, aggregate
2514 * and redistributed routes
2515 */
d62a17ae 2516 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2517 || new_select->sub_type
2518 == BGP_ROUTE_AGGREGATE
2519 || new_select->sub_type
2520 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2521 if (CHECK_FLAG(
2522 rn->flags,
2523 BGP_NODE_REGISTERED_FOR_LABEL))
2524 bgp_unregister_for_label(rn);
70e98a7f 2525 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
d62a17ae 2526 &rn->local_label);
2527 bgp_set_valid_label(&rn->local_label);
2528 } else
2529 bgp_register_for_label(rn, new_select);
2530 }
a4d82a8a
PZ
2531 } else if (CHECK_FLAG(rn->flags,
2532 BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2533 bgp_unregister_for_label(rn);
318cac96
DW
2534 }
2535 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2536 bgp_unregister_for_label(rn);
d62a17ae 2537 }
cd1964ff 2538
ddb5b488
PZ
2539 if (debug) {
2540 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
2541 zlog_debug(
2542 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2543 __func__, pfx_buf, afi2str(afi), safi2str(safi),
2544 old_select, new_select);
2545 }
2546
d62a17ae 2547 /* If best route remains the same and this is not due to user-initiated
2548 * clear, see exactly what needs to be done.
2549 */
d62a17ae 2550 if (old_select && old_select == new_select
2551 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
1defdda8 2552 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2553 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 2554 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2555#if ENABLE_BGP_VNC
d62a17ae 2556 vnc_import_bgp_add_route(bgp, p, old_select);
2557 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2558#endif
bb744275 2559 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2560 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2561
2562 if (new_select->type == ZEBRA_ROUTE_BGP
2563 && (new_select->sub_type == BGP_ROUTE_NORMAL
2564 || new_select->sub_type
2565 == BGP_ROUTE_IMPORTED))
2566
2567 bgp_zebra_announce(rn, p, old_select,
2568 bgp, afi, safi);
2569 }
d62a17ae 2570 }
1defdda8 2571 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2572 bgp_zebra_clear_route_change_flags(rn);
2573
2574 /* If there is a change of interest to peers, reannounce the
2575 * route. */
1defdda8 2576 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
d62a17ae 2577 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2578 group_announce_route(bgp, afi, safi, rn, new_select);
2579
2580 /* unicast routes must also be annouced to
2581 * labeled-unicast update-groups */
2582 if (safi == SAFI_UNICAST)
2583 group_announce_route(bgp, afi,
2584 SAFI_LABELED_UNICAST, rn,
2585 new_select);
2586
1defdda8 2587 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2588 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2589 }
fee0f4c6 2590
d62a17ae 2591 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2592 return;
d62a17ae 2593 }
8ad7271d 2594
d62a17ae 2595 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2596 */
2597 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2598
2599 /* bestpath has changed; bump version */
2600 if (old_select || new_select) {
2601 bgp_bump_version(rn);
2602
2603 if (!bgp->t_rmap_def_originate_eval) {
2604 bgp_lock(bgp);
2605 thread_add_timer(
2606 bm->master,
2607 update_group_refresh_default_originate_route_map,
2608 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2609 &bgp->t_rmap_def_originate_eval);
2610 }
2611 }
3f9c7369 2612
d62a17ae 2613 if (old_select)
18ee8310 2614 bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED);
d62a17ae 2615 if (new_select) {
ddb5b488
PZ
2616 if (debug)
2617 zlog_debug("%s: setting SELECTED flag", __func__);
18ee8310
DS
2618 bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
2619 bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
1defdda8 2620 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
d62a17ae 2621 }
338b3424 2622
65efcfce 2623#if ENABLE_BGP_VNC
d62a17ae 2624 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2625 if (old_select != new_select) {
2626 if (old_select) {
2627 vnc_import_bgp_exterior_del_route(bgp, p,
2628 old_select);
2629 vnc_import_bgp_del_route(bgp, p, old_select);
2630 }
2631 if (new_select) {
2632 vnc_import_bgp_exterior_add_route(bgp, p,
2633 new_select);
2634 vnc_import_bgp_add_route(bgp, p, new_select);
2635 }
2636 }
2637 }
65efcfce
LB
2638#endif
2639
d62a17ae 2640 group_announce_route(bgp, afi, safi, rn, new_select);
2641
2642 /* unicast routes must also be annouced to labeled-unicast update-groups
2643 */
2644 if (safi == SAFI_UNICAST)
2645 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2646 new_select);
2647
2648 /* FIB update. */
2649 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2650 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2651 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2652 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2653 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2654 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2655
2656 /* if this is an evpn imported type-5 prefix,
2657 * we need to withdraw the route first to clear
2658 * the nh neigh and the RMAC entry.
2659 */
2660 if (old_select &&
2661 is_route_parent_evpn(old_select))
2662 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2663
d62a17ae 2664 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2b659f33 2665 } else {
d62a17ae 2666 /* Withdraw the route from the kernel. */
2667 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2668 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2669 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2670 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2671
568e10ca 2672 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2673 }
718e3744 2674 }
3064bf43 2675
5424b7ba
MK
2676 /* advertise/withdraw type-5 routes */
2677 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
f106e3a7 2678 if (advertise_type5_routes(bgp, afi) &&
2679 new_select &&
2680 is_route_injectable_into_evpn(new_select)) {
7e4ed18e
MK
2681
2682 /* apply the route-map */
2683 if (bgp->adv_cmd_rmap[afi][safi].map) {
b68885f9 2684 route_map_result_t ret;
7e4ed18e 2685
3518f352
DS
2686 ret = route_map_apply(
2687 bgp->adv_cmd_rmap[afi][safi].map,
2688 &rn->p, RMAP_BGP, new_select);
b68885f9 2689 if (ret == RMAP_PERMITMATCH)
3518f352
DS
2690 bgp_evpn_advertise_type5_route(
2691 bgp, &rn->p, new_select->attr,
2692 afi, safi);
c27ee4c4 2693 else
2694 bgp_evpn_withdraw_type5_route(
2695 bgp, &rn->p, afi, safi);
7e4ed18e
MK
2696 } else {
2697 bgp_evpn_advertise_type5_route(bgp,
2698 &rn->p,
2699 new_select->attr,
2700 afi, safi);
2701
2702 }
f106e3a7 2703 } else if (advertise_type5_routes(bgp, afi) &&
2704 old_select &&
2705 is_route_injectable_into_evpn(old_select))
31310b25 2706 bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
5424b7ba
MK
2707 }
2708
d62a17ae 2709 /* Clear any route change flags. */
2710 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2711
18ee8310 2712 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2713 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
18ee8310 2714 bgp_path_info_reap(rn, old_select);
d62a17ae 2715
2716 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2717 return;
718e3744 2718}
2719
f009ff26 2720/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2721int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2722{
2723 struct bgp_node *rn;
2724 int cnt = 0;
2725 struct afi_safi_info *thread_info;
2726 struct listnode *node = NULL, *nnode = NULL;
2727
2728 if (bgp->gr_info[afi][safi].t_route_select)
2729 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2730
2731 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2732 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2733 get_afi_safi_str(afi, safi, false),
2734 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2735 }
2736
2737 /* Process the route list */
2738 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2739 while (node) {
2740 rn = listgetdata(node);
2741 nnode = node->next;
2742 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
2743 rn->rt_node = NULL;
2744
2745 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2746 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
2747 bgp_process_main_one(bgp, rn, afi, safi);
2748 cnt++;
2749 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2750 break;
2751 }
2752 node = nnode;
2753 }
2754
9e3b51a7 2755 /* Send EOR message when all routes are processed */
2756 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2757 bgp_send_delayed_eor(bgp);
8c48b3b6 2758 /* Send route processing complete message to RIB */
2759 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2760 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2761 return 0;
9e3b51a7 2762 }
f009ff26 2763
2764 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2765
2766 thread_info->afi = afi;
2767 thread_info->safi = safi;
2768 thread_info->bgp = bgp;
2769
2770 /* If there are more routes to be processed, start the
2771 * selection timer
2772 */
2773 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2774 BGP_ROUTE_SELECT_DELAY,
2775 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2776 return 0;
2777}
2778
aac24838 2779static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2780{
aac24838
JB
2781 struct bgp_process_queue *pqnode = data;
2782 struct bgp *bgp = pqnode->bgp;
d62a17ae 2783 struct bgp_table *table;
ac021f40 2784 struct bgp_node *rn;
aac24838
JB
2785
2786 /* eoiu marker */
2787 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2788 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2789 /* should always have dedicated wq call */
2790 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2791 return WQ_SUCCESS;
2792 }
2793
ac021f40
LB
2794 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2795 rn = STAILQ_FIRST(&pqnode->pqueue);
2796 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2797 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2798 table = bgp_node_table(rn);
ac021f40 2799 /* note, new RNs may be added as part of processing */
aac24838 2800 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2801
aac24838 2802 bgp_unlock_node(rn);
d62a17ae 2803 bgp_table_unlock(table);
2804 }
aac24838
JB
2805
2806 return WQ_SUCCESS;
2807}
2808
2809static void bgp_processq_del(struct work_queue *wq, void *data)
2810{
2811 struct bgp_process_queue *pqnode = data;
2812
2813 bgp_unlock(pqnode->bgp);
2814
2815 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2816}
2817
d62a17ae 2818void bgp_process_queue_init(void)
200df115 2819{
0ce1ca80 2820 if (!bm->process_main_queue)
d62a17ae 2821 bm->process_main_queue =
2822 work_queue_new(bm->master, "process_main_queue");
2823
aac24838 2824 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2825 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2826 bm->process_main_queue->spec.max_retries = 0;
2827 bm->process_main_queue->spec.hold = 50;
2828 /* Use a higher yield value of 50ms for main queue processing */
2829 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2830}
2831
cfe8d15a 2832static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2833{
2834 struct bgp_process_queue *pqnode;
2835
a4d82a8a
PZ
2836 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2837 sizeof(struct bgp_process_queue));
aac24838
JB
2838
2839 /* unlocked in bgp_processq_del */
2840 pqnode->bgp = bgp_lock(bgp);
2841 STAILQ_INIT(&pqnode->pqueue);
2842
aac24838
JB
2843 return pqnode;
2844}
2845
d62a17ae 2846void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2847{
aac24838
JB
2848#define ARBITRARY_PROCESS_QLEN 10000
2849 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2850 struct bgp_process_queue *pqnode;
cfe8d15a 2851 int pqnode_reuse = 0;
495f0b13 2852
d62a17ae 2853 /* already scheduled for processing? */
2854 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2855 return;
2e02b9b2 2856
f009ff26 2857 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2858 * the workqueue
2859 */
2860 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
2861 if (BGP_DEBUG(update, UPDATE_OUT))
2862 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
36235319 2863 rn);
f009ff26 2864 return;
2865 }
2866
aac24838 2867 if (wq == NULL)
d62a17ae 2868 return;
2869
aac24838 2870 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2871 limit only if is from the same BGP view and it's not an EOIU marker
2872 */
aac24838
JB
2873 if (work_queue_item_count(wq)) {
2874 struct work_queue_item *item = work_queue_last_item(wq);
2875 pqnode = item->data;
228da428 2876
a4d82a8a
PZ
2877 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
2878 || pqnode->bgp != bgp
2879 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2880 pqnode = bgp_processq_alloc(bgp);
2881 else
2882 pqnode_reuse = 1;
aac24838 2883 } else
cfe8d15a 2884 pqnode = bgp_processq_alloc(bgp);
aac24838 2885 /* all unlocked in bgp_process_wq */
d62a17ae 2886 bgp_table_lock(bgp_node_table(rn));
aac24838 2887
d62a17ae 2888 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2889 bgp_lock_node(rn);
2890
60466a63
QY
2891 /* can't be enqueued twice */
2892 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2893 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2894 pqnode->queued++;
2895
cfe8d15a
LB
2896 if (!pqnode_reuse)
2897 work_queue_add(wq, pqnode);
2898
d62a17ae 2899 return;
fee0f4c6 2900}
0a486e5f 2901
d62a17ae 2902void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2903{
d62a17ae 2904 struct bgp_process_queue *pqnode;
cb1faec9 2905
d62a17ae 2906 if (bm->process_main_queue == NULL)
2907 return;
2e02b9b2 2908
cfe8d15a 2909 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2910
aac24838 2911 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2912 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2913}
2914
d62a17ae 2915static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2916{
d62a17ae 2917 struct peer *peer;
0a486e5f 2918
d62a17ae 2919 peer = THREAD_ARG(thread);
2920 peer->t_pmax_restart = NULL;
0a486e5f 2921
d62a17ae 2922 if (bgp_debug_neighbor_events(peer))
2923 zlog_debug(
2924 "%s Maximum-prefix restart timer expired, restore peering",
2925 peer->host);
0a486e5f 2926
a9bafa95 2927 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 2928 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 2929
d62a17ae 2930 return 0;
0a486e5f 2931}
2932
d62a17ae 2933int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2934 int always)
718e3744 2935{
d62a17ae 2936 iana_afi_t pkt_afi;
5c525538 2937 iana_safi_t pkt_safi;
9cabb64b 2938
d62a17ae 2939 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2940 return 0;
e0701b79 2941
d62a17ae 2942 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2943 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2944 PEER_STATUS_PREFIX_LIMIT)
2945 && !always)
2946 return 0;
e0701b79 2947
d62a17ae 2948 zlog_info(
a0a87037
DA
2949 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2950 " exceed, limit %" PRIu32,
5cb5f4d0 2951 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 2952 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2953 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2954
2955 if (CHECK_FLAG(peer->af_flags[afi][safi],
2956 PEER_FLAG_MAX_PREFIX_WARNING))
2957 return 0;
2958
2959 /* Convert AFI, SAFI to values for packet. */
2960 pkt_afi = afi_int2iana(afi);
2961 pkt_safi = safi_int2iana(safi);
2962 {
d7c0a89a 2963 uint8_t ndata[7];
d62a17ae 2964
2965 ndata[0] = (pkt_afi >> 8);
2966 ndata[1] = pkt_afi;
2967 ndata[2] = pkt_safi;
2968 ndata[3] = (peer->pmax[afi][safi] >> 24);
2969 ndata[4] = (peer->pmax[afi][safi] >> 16);
2970 ndata[5] = (peer->pmax[afi][safi] >> 8);
2971 ndata[6] = (peer->pmax[afi][safi]);
2972
2973 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2974 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2975 BGP_NOTIFY_CEASE_MAX_PREFIX,
2976 ndata, 7);
2977 }
2978
2979 /* Dynamic peers will just close their connection. */
2980 if (peer_dynamic_neighbor(peer))
2981 return 1;
2982
2983 /* restart timer start */
2984 if (peer->pmax_restart[afi][safi]) {
2985 peer->v_pmax_restart =
2986 peer->pmax_restart[afi][safi] * 60;
2987
2988 if (bgp_debug_neighbor_events(peer))
2989 zlog_debug(
2990 "%s Maximum-prefix restart timer started for %d secs",
2991 peer->host, peer->v_pmax_restart);
2992
2993 BGP_TIMER_ON(peer->t_pmax_restart,
2994 bgp_maximum_prefix_restart_timer,
2995 peer->v_pmax_restart);
2996 }
2997
2998 return 1;
2999 } else
3000 UNSET_FLAG(peer->af_sflags[afi][safi],
3001 PEER_STATUS_PREFIX_LIMIT);
3002
3003 if (peer->pcount[afi][safi]
3004 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
3005 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3006 PEER_STATUS_PREFIX_THRESHOLD)
3007 && !always)
3008 return 0;
3009
3010 zlog_info(
a0a87037
DA
3011 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3012 ", max %" PRIu32,
5cb5f4d0 3013 get_afi_safi_str(afi, safi, false), peer->host,
d62a17ae 3014 peer->pcount[afi][safi], peer->pmax[afi][safi]);
3015 SET_FLAG(peer->af_sflags[afi][safi],
3016 PEER_STATUS_PREFIX_THRESHOLD);
3017 } else
3018 UNSET_FLAG(peer->af_sflags[afi][safi],
3019 PEER_STATUS_PREFIX_THRESHOLD);
3020 return 0;
718e3744 3021}
3022
b40d939b 3023/* Unconditionally remove the route from the RIB, without taking
3024 * damping into consideration (eg, because the session went down)
3025 */
40381db7 3026void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 3027 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3028{
f009ff26 3029
3030 struct bgp *bgp = NULL;
3031 bool delete_route = false;
3032
40381db7 3033 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
d62a17ae 3034
f009ff26 3035 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
40381db7 3036 bgp_path_info_delete(rn, pi); /* keep historical info */
d62a17ae 3037
f009ff26 3038 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3039 * flag
3040 */
3041 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3042 delete_route = true;
36235319
QY
3043 else if (bgp_node_set_defer_flag(rn, true) < 0)
3044 delete_route = true;
f009ff26 3045 if (delete_route) {
3046 if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
3047 UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3048 bgp = pi->peer->bgp;
36235319
QY
3049 if ((rn->rt_node)
3050 && (bgp->gr_info[afi][safi].route_list)) {
3051 list_delete_node(bgp->gr_info[afi][safi]
3052 .route_list,
3053 rn->rt_node);
f009ff26 3054 rn->rt_node = NULL;
3055 }
3056 }
3057 }
3058 }
4a11bf2c 3059
f009ff26 3060 hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
d62a17ae 3061 bgp_process(peer->bgp, rn, afi, safi);
3062}
3063
40381db7 3064static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 3065 struct peer *peer, afi_t afi, safi_t safi,
3066 struct prefix_rd *prd)
3067{
d62a17ae 3068 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3069 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3070 */
3071 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3072 && peer->sort == BGP_PEER_EBGP)
40381db7 3073 if ((bgp_damp_withdraw(pi, rn, afi, safi, 0))
d62a17ae 3074 == BGP_DAMP_SUPPRESSED) {
40381db7 3075 bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi,
d62a17ae 3076 safi);
3077 return;
3078 }
3079
65efcfce 3080#if ENABLE_BGP_VNC
d62a17ae 3081 if (safi == SAFI_MPLS_VPN) {
3082 struct bgp_node *prn = NULL;
3083 struct bgp_table *table = NULL;
3084
3085 prn = bgp_node_get(peer->bgp->rib[afi][safi],
3086 (struct prefix *)prd);
67009e22
DS
3087 if (bgp_node_has_bgp_path_info_data(prn)) {
3088 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3089
3090 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3091 peer->bgp, prd, table, &rn->p, pi);
d62a17ae 3092 }
3093 bgp_unlock_node(prn);
3094 }
3095 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3096 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3097
40381db7 3098 vnc_import_bgp_del_route(peer->bgp, &rn->p, pi);
d62a17ae 3099 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
40381db7 3100 pi);
d62a17ae 3101 }
65efcfce 3102 }
d62a17ae 3103#endif
128ea8ab 3104
d62a17ae 3105 /* If this is an EVPN route, process for un-import. */
3106 if (safi == SAFI_EVPN)
40381db7 3107 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi);
128ea8ab 3108
40381db7 3109 bgp_rib_remove(rn, pi, peer, afi, safi);
718e3744 3110}
3111
4b7e6066
DS
3112struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3113 struct peer *peer, struct attr *attr,
3114 struct bgp_node *rn)
fb018d25 3115{
4b7e6066 3116 struct bgp_path_info *new;
fb018d25 3117
d62a17ae 3118 /* Make new BGP info. */
4b7e6066 3119 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3120 new->type = type;
3121 new->instance = instance;
3122 new->sub_type = sub_type;
3123 new->peer = peer;
3124 new->attr = attr;
3125 new->uptime = bgp_clock();
3126 new->net = rn;
d62a17ae 3127 return new;
fb018d25
DS
3128}
3129
d62a17ae 3130static void overlay_index_update(struct attr *attr,
3131 struct eth_segment_id *eth_s_id,
3132 union gw_addr *gw_ip)
684a7227 3133{
d62a17ae 3134 if (!attr)
3135 return;
684a7227 3136
d62a17ae 3137 if (eth_s_id == NULL) {
3138 memset(&(attr->evpn_overlay.eth_s_id), 0,
3139 sizeof(struct eth_segment_id));
3140 } else {
3141 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
3142 sizeof(struct eth_segment_id));
3143 }
3144 if (gw_ip == NULL) {
3145 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3146 } else {
3147 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3148 sizeof(union gw_addr));
3149 }
684a7227
PG
3150}
3151
40381db7 3152static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3153 struct eth_segment_id *eth_s_id,
3154 union gw_addr *gw_ip)
3155{
40381db7
DS
3156 struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote;
3157 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed
DS
3158 union {
3159 struct eth_segment_id esi;
3160 union gw_addr ip;
3161 } temp;
d62a17ae 3162
3163 if (afi != AFI_L2VPN)
3164 return true;
11ebf4ed 3165
05864da7
DS
3166 path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id);
3167 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3168
3169 if (gw_ip == NULL) {
3170 memset(&temp, 0, sizeof(temp));
40381db7 3171 path_gw_ip_remote = &temp.ip;
11ebf4ed 3172 } else
40381db7 3173 path_gw_ip_remote = gw_ip;
11ebf4ed
DS
3174
3175 if (eth_s_id == NULL) {
3176 memset(&temp, 0, sizeof(temp));
40381db7 3177 path_eth_s_id_remote = &temp.esi;
11ebf4ed 3178 } else
40381db7 3179 path_eth_s_id_remote = eth_s_id;
11ebf4ed 3180
40381db7 3181 if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)))
d62a17ae 3182 return false;
11ebf4ed 3183
40381db7 3184 return !memcmp(path_eth_s_id, path_eth_s_id_remote,
d62a17ae 3185 sizeof(struct eth_segment_id));
684a7227
PG
3186}
3187
c265ee22 3188/* Check if received nexthop is valid or not. */
d62a17ae 3189static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
949b0f24 3190 uint8_t type, uint8_t stype,
3191 struct attr *attr, struct bgp_node *rn)
d62a17ae 3192{
3193 int ret = 0;
3194
3195 /* Only validated for unicast and multicast currently. */
3196 /* Also valid for EVPN where the nexthop is an IP address. */
3197 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
3198 return 0;
3199
3200 /* If NEXT_HOP is present, validate it. */
3201 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
975a328e 3202 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3203 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
975a328e 3204 || bgp_nexthop_self(bgp, afi, type, stype, attr, rn))
d62a17ae 3205 return 1;
3206 }
c265ee22 3207
d62a17ae 3208 /* If MP_NEXTHOP is present, validate it. */
3209 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3210 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3211 * it is not an IPv6 link-local address.
3212 */
3213 if (attr->mp_nexthop_len) {
3214 switch (attr->mp_nexthop_len) {
3215 case BGP_ATTR_NHLEN_IPV4:
3216 case BGP_ATTR_NHLEN_VPNV4:
975a328e
DA
3217 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
3218 || IPV4_CLASS_DE(
3219 ntohl(attr->mp_nexthop_global_in.s_addr))
3220 || bgp_nexthop_self(bgp, afi, type, stype, attr,
3221 rn));
d62a17ae 3222 break;
3223
3224 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
3225 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3226 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
3227 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
3228 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3229 || IN6_IS_ADDR_MULTICAST(
949b0f24 3230 &attr->mp_nexthop_global)
3231 || bgp_nexthop_self(bgp, afi, type, stype,
3232 attr, rn));
d62a17ae 3233 break;
3234
3235 default:
3236 ret = 1;
3237 break;
3238 }
3239 }
c265ee22 3240
d62a17ae 3241 return ret;
3242}
3243
d7c0a89a 3244int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 3245 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3246 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3247 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3248 struct bgp_route_evpn *evpn)
d62a17ae 3249{
3250 int ret;
3251 int aspath_loop_count = 0;
3252 struct bgp_node *rn;
3253 struct bgp *bgp;
3254 struct attr new_attr;
3255 struct attr *attr_new;
40381db7 3256 struct bgp_path_info *pi;
4b7e6066
DS
3257 struct bgp_path_info *new;
3258 struct bgp_path_info_extra *extra;
d62a17ae 3259 const char *reason;
3260 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3261 int connected = 0;
3262 int do_loop_check = 1;
3263 int has_valid_label = 0;
7c312383 3264 afi_t nh_afi;
949b0f24 3265 uint8_t pi_type = 0;
3266 uint8_t pi_sub_type = 0;
3267
65efcfce 3268#if ENABLE_BGP_VNC
d62a17ae 3269 int vnc_implicit_withdraw = 0;
65efcfce 3270#endif
d62a17ae 3271 int same_attr = 0;
718e3744 3272
d62a17ae 3273 memset(&new_attr, 0, sizeof(struct attr));
3274 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3275 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3276
d62a17ae 3277 bgp = peer->bgp;
3278 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3279 /* TODO: Check to see if we can get rid of "is_valid_label" */
3280 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3281 has_valid_label = (num_labels > 0) ? 1 : 0;
3282 else
3283 has_valid_label = bgp_is_valid_label(label);
718e3744 3284
d62a17ae 3285 /* When peer's soft reconfiguration enabled. Record input packet in
3286 Adj-RIBs-In. */
3287 if (!soft_reconfig
3288 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3289 && peer != bgp->peer_self)
3290 bgp_adj_in_set(rn, peer, attr, addpath_id);
3291
3292 /* Check previously received route. */
6f94b685 3293 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
3294 if (pi->peer == peer && pi->type == type
3295 && pi->sub_type == sub_type
3296 && pi->addpath_rx_id == addpath_id)
d62a17ae 3297 break;
3298
3299 /* AS path local-as loop check. */
3300 if (peer->change_local_as) {
c4368918
DW
3301 if (peer->allowas_in[afi][safi])
3302 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3303 else if (!CHECK_FLAG(peer->flags,
3304 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3305 aspath_loop_count = 1;
3306
3307 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3308 > aspath_loop_count) {
b4d46cc9 3309 peer->stat_pfx_aspath_loop++;
d62a17ae 3310 reason = "as-path contains our own AS;";
3311 goto filtered;
3312 }
718e3744 3313 }
718e3744 3314
d62a17ae 3315 /* If the peer is configured for "allowas-in origin" and the last ASN in
3316 * the
3317 * as-path is our ASN then we do not need to call aspath_loop_check
3318 */
3319 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3320 if (aspath_get_last_as(attr->aspath) == bgp->as)
3321 do_loop_check = 0;
3322
3323 /* AS path loop check. */
3324 if (do_loop_check) {
3325 if (aspath_loop_check(attr->aspath, bgp->as)
3326 > peer->allowas_in[afi][safi]
3327 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3328 && aspath_loop_check(attr->aspath, bgp->confed_id)
3329 > peer->allowas_in[afi][safi])) {
b4d46cc9 3330 peer->stat_pfx_aspath_loop++;
d62a17ae 3331 reason = "as-path contains our own AS;";
3332 goto filtered;
3333 }
3334 }
aac9ef6c 3335
d62a17ae 3336 /* Route reflector originator ID check. */
3337 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3338 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3339 peer->stat_pfx_originator_loop++;
d62a17ae 3340 reason = "originator is us;";
3341 goto filtered;
3342 }
718e3744 3343
d62a17ae 3344 /* Route reflector cluster ID check. */
3345 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3346 peer->stat_pfx_cluster_loop++;
d62a17ae 3347 reason = "reflected from the same cluster;";
3348 goto filtered;
3349 }
718e3744 3350
d62a17ae 3351 /* Apply incoming filter. */
3352 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3353 peer->stat_pfx_filter++;
d62a17ae 3354 reason = "filter;";
3355 goto filtered;
3356 }
718e3744 3357
a8b72dc6
DA
3358 /* RFC 8212 to prevent route leaks.
3359 * This specification intends to improve this situation by requiring the
3360 * explicit configuration of both BGP Import and Export Policies for any
3361 * External BGP (EBGP) session such as customers, peers, or
3362 * confederation boundaries for all enabled address families. Through
3363 * codification of the aforementioned requirement, operators will
3364 * benefit from consistent behavior across different BGP
3365 * implementations.
3366 */
3367 if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
3368 if (!bgp_inbound_policy_exists(peer,
3369 &peer->filter[afi][safi])) {
3370 reason = "inbound policy missing";
3371 goto filtered;
3372 }
3373
fb29348a
DA
3374 /* draft-ietf-idr-deprecate-as-set-confed-set
3375 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3376 * Eventually, This document (if approved) updates RFC 4271
3377 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3378 * and obsoletes RFC 6472.
3379 */
3380 if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
3381 if (aspath_check_as_sets(attr->aspath)) {
3382 reason =
3383 "as-path contains AS_SET or AS_CONFED_SET type;";
3384 goto filtered;
3385 }
3386
6f4f49b2 3387 new_attr = *attr;
d62a17ae 3388
3389 /* Apply incoming route-map.
3390 * NB: new_attr may now contain newly allocated values from route-map
3391 * "set"
3392 * commands, so we need bgp_attr_flush in the error paths, until we
3393 * intern
3394 * the attr (which takes over the memory references) */
82b692c0 3395 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
196c6b09 3396 label, num_labels, rn) == RMAP_DENY) {
b4d46cc9 3397 peer->stat_pfx_filter++;
d62a17ae 3398 reason = "route-map;";
3399 bgp_attr_flush(&new_attr);
3400 goto filtered;
3401 }
718e3744 3402
05864da7 3403 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3404 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3405 /* remove from RIB previous entry */
3406 bgp_zebra_withdraw(p, pi, bgp, safi);
3407 }
3408
7f323236
DW
3409 if (peer->sort == BGP_PEER_EBGP) {
3410
a4d82a8a
PZ
3411 /* If we receive the graceful-shutdown community from an eBGP
3412 * peer we must lower local-preference */
3413 if (new_attr.community
3414 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3415 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3416 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3417
a4d82a8a
PZ
3418 /* If graceful-shutdown is configured then add the GSHUT
3419 * community to all paths received from eBGP peers */
892fedb6
DA
3420 } else if (CHECK_FLAG(peer->bgp->flags,
3421 BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236 3422 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3423 }
3424
949b0f24 3425 if (pi) {
3426 pi_type = pi->type;
3427 pi_sub_type = pi->sub_type;
3428 }
3429
d62a17ae 3430 /* next hop check. */
a4d82a8a 3431 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
949b0f24 3432 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type,
3433 pi_sub_type, &new_attr, rn)) {
b4d46cc9 3434 peer->stat_pfx_nh_invalid++;
d62a17ae 3435 reason = "martian or self next-hop;";
3436 bgp_attr_flush(&new_attr);
3437 goto filtered;
3438 }
718e3744 3439
5c14a191 3440 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3441 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3442 reason = "self mac;";
3443 goto filtered;
3444 }
3445
d62a17ae 3446 attr_new = bgp_attr_intern(&new_attr);
3447
3448 /* If the update is implicit withdraw. */
40381db7
DS
3449 if (pi) {
3450 pi->uptime = bgp_clock();
3451 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3452
4a11bf2c
DL
3453 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3454
d62a17ae 3455 /* Same attribute comes in. */
40381db7
DS
3456 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3457 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3458 && (!has_valid_label
40381db7 3459 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3460 num_labels * sizeof(mpls_label_t))
d62a17ae 3461 == 0)
3462 && (overlay_index_equal(
40381db7 3463 afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3464 evpn == NULL ? NULL : &evpn->gw_ip))) {
3465 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3466 BGP_CONFIG_DAMPENING)
3467 && peer->sort == BGP_PEER_EBGP
40381db7 3468 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3469 if (bgp_debug_update(peer, p, NULL, 1)) {
3470 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3471 afi, safi, prd, p, label,
3472 num_labels, addpath_id ? 1 : 0,
3473 addpath_id, pfx_buf,
3474 sizeof(pfx_buf));
d62a17ae 3475 zlog_debug("%s rcvd %s", peer->host,
3476 pfx_buf);
3477 }
3478
40381db7 3479 if (bgp_damp_update(pi, rn, afi, safi)
d62a17ae 3480 != BGP_DAMP_SUPPRESSED) {
40381db7 3481 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3482 safi);
3483 bgp_process(bgp, rn, afi, safi);
3484 }
3485 } else /* Duplicate - odd */
3486 {
3487 if (bgp_debug_update(peer, p, NULL, 1)) {
3488 if (!peer->rcvd_attr_printed) {
3489 zlog_debug(
3490 "%s rcvd UPDATE w/ attr: %s",
3491 peer->host,
3492 peer->rcvd_attr_str);
3493 peer->rcvd_attr_printed = 1;
3494 }
3495
3496 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3497 afi, safi, prd, p, label,
3498 num_labels, addpath_id ? 1 : 0,
3499 addpath_id, pfx_buf,
3500 sizeof(pfx_buf));
d62a17ae 3501 zlog_debug(
3502 "%s rcvd %s...duplicate ignored",
3503 peer->host, pfx_buf);
3504 }
3505
3506 /* graceful restart STALE flag unset. */
40381db7 3507 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3508 bgp_path_info_unset_flag(
40381db7 3509 rn, pi, BGP_PATH_STALE);
f009ff26 3510 bgp_node_set_defer_flag(rn, false);
d62a17ae 3511 bgp_process(bgp, rn, afi, safi);
3512 }
3513 }
3514
3515 bgp_unlock_node(rn);
3516 bgp_attr_unintern(&attr_new);
3517
3518 return 0;
3519 }
718e3744 3520
d62a17ae 3521 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3522 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3523 if (bgp_debug_update(peer, p, NULL, 1)) {
3524 bgp_debug_rdpfxpath2str(
a4d82a8a 3525 afi, safi, prd, p, label, num_labels,
d62a17ae 3526 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3527 sizeof(pfx_buf));
3528 zlog_debug(
3529 "%s rcvd %s, flapped quicker than processing",
3530 peer->host, pfx_buf);
3531 }
3532
40381db7 3533 bgp_path_info_restore(rn, pi);
d62a17ae 3534 }
718e3744 3535
d62a17ae 3536 /* Received Logging. */
3537 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3538 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3539 num_labels, addpath_id ? 1 : 0,
3540 addpath_id, pfx_buf,
3541 sizeof(pfx_buf));
d62a17ae 3542 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3543 }
718e3744 3544
d62a17ae 3545 /* graceful restart STALE flag unset. */
f009ff26 3546 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
40381db7 3547 bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
f009ff26 3548 bgp_node_set_defer_flag(rn, false);
3549 }
d62a17ae 3550
3551 /* The attribute is changed. */
40381db7 3552 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3553
3554 /* implicit withdraw, decrement aggregate and pcount here.
3555 * only if update is accepted, they'll increment below.
3556 */
40381db7 3557 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3558
3559 /* Update bgp route dampening information. */
3560 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3561 && peer->sort == BGP_PEER_EBGP) {
3562 /* This is implicit withdraw so we should update
3563 dampening
3564 information. */
40381db7
DS
3565 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
3566 bgp_damp_withdraw(pi, rn, afi, safi, 1);
d62a17ae 3567 }
65efcfce 3568#if ENABLE_BGP_VNC
d62a17ae 3569 if (safi == SAFI_MPLS_VPN) {
3570 struct bgp_node *prn = NULL;
3571 struct bgp_table *table = NULL;
3572
3573 prn = bgp_node_get(bgp->rib[afi][safi],
3574 (struct prefix *)prd);
67009e22
DS
3575 if (bgp_node_has_bgp_path_info_data(prn)) {
3576 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3577
3578 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3579 bgp, prd, table, p, pi);
d62a17ae 3580 }
3581 bgp_unlock_node(prn);
3582 }
3583 if ((afi == AFI_IP || afi == AFI_IP6)
3584 && (safi == SAFI_UNICAST)) {
40381db7 3585 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3586 /*
3587 * Implicit withdraw case.
3588 */
3589 ++vnc_implicit_withdraw;
40381db7
DS
3590 vnc_import_bgp_del_route(bgp, p, pi);
3591 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3592 }
3593 }
65efcfce 3594#endif
128ea8ab 3595
d62a17ae 3596 /* Special handling for EVPN update of an existing route. If the
3597 * extended community attribute has changed, we need to
3598 * un-import
3599 * the route using its existing extended community. It will be
3600 * subsequently processed for import with the new extended
3601 * community.
3602 */
3603 if (safi == SAFI_EVPN && !same_attr) {
40381db7 3604 if ((pi->attr->flag
d62a17ae 3605 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3606 && (attr_new->flag
3607 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3608 int cmp;
3609
40381db7 3610 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3611 attr_new->ecommunity);
3612 if (!cmp) {
3613 if (bgp_debug_update(peer, p, NULL, 1))
3614 zlog_debug(
3615 "Change in EXT-COMM, existing %s new %s",
3616 ecommunity_str(
40381db7 3617 pi->attr->ecommunity),
d62a17ae 3618 ecommunity_str(
3619 attr_new->ecommunity));
3620 bgp_evpn_unimport_route(bgp, afi, safi,
40381db7 3621 p, pi);
d62a17ae 3622 }
3623 }
3624 }
718e3744 3625
d62a17ae 3626 /* Update to new attribute. */
40381db7
DS
3627 bgp_attr_unintern(&pi->attr);
3628 pi->attr = attr_new;
d62a17ae 3629
3630 /* Update MPLS label */
3631 if (has_valid_label) {
40381db7 3632 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3633 if (extra->label != label) {
3634 memcpy(&extra->label, label,
dbd587da 3635 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3636 extra->num_labels = num_labels;
3637 }
b57ba6d2
MK
3638 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3639 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3640 }
718e3744 3641
e496b420
HS
3642 /* Update SRv6 SID */
3643 if (attr->srv6_l3vpn) {
3644 extra = bgp_path_info_extra_get(pi);
3645 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3646 sid_copy(&extra->sid[0],
3647 &attr->srv6_l3vpn->sid);
3648 extra->num_sids = 1;
3649 }
3650 } else if (attr->srv6_vpn) {
3651 extra = bgp_path_info_extra_get(pi);
3652 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3653 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3654 extra->num_sids = 1;
3655 }
3656 }
3657
65efcfce 3658#if ENABLE_BGP_VNC
d62a17ae 3659 if ((afi == AFI_IP || afi == AFI_IP6)
3660 && (safi == SAFI_UNICAST)) {
3661 if (vnc_implicit_withdraw) {
3662 /*
3663 * Add back the route with its new attributes
3664 * (e.g., nexthop).
3665 * The route is still selected, until the route
3666 * selection
3667 * queued by bgp_process actually runs. We have
3668 * to make this
3669 * update to the VNC side immediately to avoid
3670 * racing against
3671 * configuration changes (e.g., route-map
3672 * changes) which
3673 * trigger re-importation of the entire RIB.
3674 */
40381db7
DS
3675 vnc_import_bgp_add_route(bgp, p, pi);
3676 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3677 }
3678 }
65efcfce 3679#endif
d62a17ae 3680 /* Update Overlay Index */
3681 if (afi == AFI_L2VPN) {
3682 overlay_index_update(
40381db7 3683 pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
d62a17ae 3684 evpn == NULL ? NULL : &evpn->gw_ip);
3685 }
65efcfce 3686
d62a17ae 3687 /* Update bgp route dampening information. */
3688 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3689 && peer->sort == BGP_PEER_EBGP) {
3690 /* Now we do normal update dampening. */
40381db7 3691 ret = bgp_damp_update(pi, rn, afi, safi);
d62a17ae 3692 if (ret == BGP_DAMP_SUPPRESSED) {
3693 bgp_unlock_node(rn);
3694 return 0;
3695 }
3696 }
128ea8ab 3697
d62a17ae 3698 /* Nexthop reachability check - for unicast and
3699 * labeled-unicast.. */
7c312383
AD
3700 if (((afi == AFI_IP || afi == AFI_IP6)
3701 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3702 || (safi == SAFI_EVPN &&
3703 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3704 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3705 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3706 && !CHECK_FLAG(peer->flags,
3707 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3708 && !CHECK_FLAG(bgp->flags,
3709 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3710 connected = 1;
3711 else
3712 connected = 0;
3713
960035b2
PZ
3714 struct bgp *bgp_nexthop = bgp;
3715
40381db7
DS
3716 if (pi->extra && pi->extra->bgp_orig)
3717 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3718
7c312383
AD
3719 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3720
3721 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3722 pi, NULL, connected)
a4d82a8a 3723 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
40381db7 3724 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3725 else {
3726 if (BGP_DEBUG(nht, NHT)) {
3727 char buf1[INET6_ADDRSTRLEN];
3728 inet_ntop(AF_INET,
3729 (const void *)&attr_new
3730 ->nexthop,
3731 buf1, INET6_ADDRSTRLEN);
3732 zlog_debug("%s(%s): NH unresolved",
15569c58 3733 __func__, buf1);
d62a17ae 3734 }
40381db7 3735 bgp_path_info_unset_flag(rn, pi,
18ee8310 3736 BGP_PATH_VALID);
d62a17ae 3737 }
3738 } else
40381db7 3739 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 3740
3741#if ENABLE_BGP_VNC
3742 if (safi == SAFI_MPLS_VPN) {
3743 struct bgp_node *prn = NULL;
3744 struct bgp_table *table = NULL;
3745
3746 prn = bgp_node_get(bgp->rib[afi][safi],
3747 (struct prefix *)prd);
67009e22
DS
3748 if (bgp_node_has_bgp_path_info_data(prn)) {
3749 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3750
3751 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3752 bgp, prd, table, p, pi);
d62a17ae 3753 }
3754 bgp_unlock_node(prn);
3755 }
3756#endif
718e3744 3757
d62a17ae 3758 /* If this is an EVPN route and some attribute has changed,
3759 * process
3760 * route for import. If the extended community has changed, we
3761 * would
3762 * have done the un-import earlier and the import would result
3763 * in the
3764 * route getting injected into appropriate L2 VNIs. If it is
3765 * just
3766 * some other attribute change, the import will result in
3767 * updating
3768 * the attributes for the route in the VNI(s).
3769 */
7c312383
AD
3770 if (safi == SAFI_EVPN && !same_attr &&
3771 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3772 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3773
3774 /* Process change. */
40381db7 3775 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3776
3777 bgp_process(bgp, rn, afi, safi);
3778 bgp_unlock_node(rn);
558d1fec 3779
ddb5b488
PZ
3780 if (SAFI_UNICAST == safi
3781 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3782 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3783
40381db7 3784 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3785 }
3786 if ((SAFI_MPLS_VPN == safi)
3787 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3788
40381db7 3789 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3790 }
3791
28070ee3 3792#if ENABLE_BGP_VNC
d62a17ae 3793 if (SAFI_MPLS_VPN == safi) {
3794 mpls_label_t label_decoded = decode_label(label);
28070ee3 3795
d62a17ae 3796 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3797 type, sub_type, &label_decoded);
3798 }
3799 if (SAFI_ENCAP == safi) {
3800 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3801 type, sub_type, NULL);
3802 }
28070ee3
PZ
3803#endif
3804
d62a17ae 3805 return 0;
3806 } // End of implicit withdraw
718e3744 3807
d62a17ae 3808 /* Received Logging. */
3809 if (bgp_debug_update(peer, p, NULL, 1)) {
3810 if (!peer->rcvd_attr_printed) {
3811 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3812 peer->rcvd_attr_str);
3813 peer->rcvd_attr_printed = 1;
3814 }
718e3744 3815
a4d82a8a 3816 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3817 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3818 sizeof(pfx_buf));
3819 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3820 }
718e3744 3821
d62a17ae 3822 /* Make new BGP info. */
3823 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3824
d62a17ae 3825 /* Update MPLS label */
3826 if (has_valid_label) {
18ee8310 3827 extra = bgp_path_info_extra_get(new);
8ba71050 3828 if (extra->label != label) {
dbd587da
QY
3829 memcpy(&extra->label, label,
3830 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3831 extra->num_labels = num_labels;
3832 }
b57ba6d2
MK
3833 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3834 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3835 }
718e3744 3836
e496b420
HS
3837 /* Update SRv6 SID */
3838 if (safi == SAFI_MPLS_VPN) {
3839 extra = bgp_path_info_extra_get(new);
3840 if (attr->srv6_l3vpn) {
3841 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
3842 extra->num_sids = 1;
3843 } else if (attr->srv6_vpn) {
3844 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3845 extra->num_sids = 1;
3846 }
3847 }
3848
d62a17ae 3849 /* Update Overlay Index */
3850 if (afi == AFI_L2VPN) {
3851 overlay_index_update(new->attr,
3852 evpn == NULL ? NULL : &evpn->eth_s_id,
3853 evpn == NULL ? NULL : &evpn->gw_ip);
3854 }
3855 /* Nexthop reachability check. */
7c312383
AD
3856 if (((afi == AFI_IP || afi == AFI_IP6)
3857 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3858 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3859 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3860 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3861 && !CHECK_FLAG(peer->flags,
3862 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3863 && !CHECK_FLAG(bgp->flags,
3864 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3865 connected = 1;
3866 else
3867 connected = 0;
3868
7c312383
AD
3869 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
3870
3871 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
3872 connected)
a4d82a8a 3873 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
18ee8310 3874 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3875 else {
3876 if (BGP_DEBUG(nht, NHT)) {
3877 char buf1[INET6_ADDRSTRLEN];
3878 inet_ntop(AF_INET,
3879 (const void *)&attr_new->nexthop,
3880 buf1, INET6_ADDRSTRLEN);
15569c58
DA
3881 zlog_debug("%s(%s): NH unresolved", __func__,
3882 buf1);
d62a17ae 3883 }
18ee8310 3884 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 3885 }
3886 } else
18ee8310 3887 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
a82478b9 3888
d62a17ae 3889 /* Addpath ID */
3890 new->addpath_rx_id = addpath_id;
3891
3892 /* Increment prefix */
3893 bgp_aggregate_increment(bgp, p, new, afi, safi);
3894
3895 /* Register new BGP information. */
18ee8310 3896 bgp_path_info_add(rn, new);
d62a17ae 3897
3898 /* route_node_get lock */
3899 bgp_unlock_node(rn);
558d1fec 3900
65efcfce 3901#if ENABLE_BGP_VNC
d62a17ae 3902 if (safi == SAFI_MPLS_VPN) {
3903 struct bgp_node *prn = NULL;
3904 struct bgp_table *table = NULL;
3905
3906 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
67009e22
DS
3907 if (bgp_node_has_bgp_path_info_data(prn)) {
3908 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 3909
3910 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3911 bgp, prd, table, p, new);
3912 }
3913 bgp_unlock_node(prn);
3914 }
65efcfce
LB
3915#endif
3916
d62a17ae 3917 /* If maximum prefix count is configured and current prefix
3918 count exeed it. */
3919 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3920 return -1;
718e3744 3921
d62a17ae 3922 /* If this is an EVPN route, process for import. */
7c312383 3923 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 3924 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3925
4a11bf2c
DL
3926 hook_call(bgp_process, bgp, afi, safi, rn, peer, false);
3927
d62a17ae 3928 /* Process change. */
3929 bgp_process(bgp, rn, afi, safi);
718e3744 3930
ddb5b488
PZ
3931 if (SAFI_UNICAST == safi
3932 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3933 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3934 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
3935 }
3936 if ((SAFI_MPLS_VPN == safi)
3937 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3938
3939 vpn_leak_to_vrf_update(bgp, new);
3940 }
28070ee3 3941#if ENABLE_BGP_VNC
d62a17ae 3942 if (SAFI_MPLS_VPN == safi) {
3943 mpls_label_t label_decoded = decode_label(label);
28070ee3 3944
d62a17ae 3945 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3946 sub_type, &label_decoded);
3947 }
3948 if (SAFI_ENCAP == safi) {
3949 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3950 sub_type, NULL);
3951 }
28070ee3
PZ
3952#endif
3953
d62a17ae 3954 return 0;
718e3744 3955
d62a17ae 3956/* This BGP update is filtered. Log the reason then update BGP
3957 entry. */
3958filtered:
4a11bf2c
DL
3959 hook_call(bgp_process, bgp, afi, safi, rn, peer, true);
3960
d62a17ae 3961 if (bgp_debug_update(peer, p, NULL, 1)) {
3962 if (!peer->rcvd_attr_printed) {
3963 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3964 peer->rcvd_attr_str);
3965 peer->rcvd_attr_printed = 1;
3966 }
718e3744 3967
a4d82a8a 3968 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3969 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3970 sizeof(pfx_buf));
3971 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3972 peer->host, pfx_buf, reason);
3973 }
128ea8ab 3974
40381db7 3975 if (pi) {
d62a17ae 3976 /* If this is an EVPN route, un-import it as it is now filtered.
3977 */
3978 if (safi == SAFI_EVPN)
40381db7 3979 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 3980
ddb5b488
PZ
3981 if (SAFI_UNICAST == safi
3982 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3983 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3984
40381db7 3985 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3986 }
3987 if ((SAFI_MPLS_VPN == safi)
3988 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3989
40381db7 3990 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
3991 }
3992
40381db7 3993 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 3994 }
3995
3996 bgp_unlock_node(rn);
558d1fec 3997
97736e32 3998#if ENABLE_BGP_VNC
d62a17ae 3999 /*
4000 * Filtered update is treated as an implicit withdrawal (see
4001 * bgp_rib_remove()
4002 * a few lines above)
4003 */
4004 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4005 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4006 0);
4007 }
97736e32
PZ
4008#endif
4009
d62a17ae 4010 return 0;
718e3744 4011}
4012
d7c0a89a 4013int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id,
d62a17ae 4014 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4015 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4016 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4017{
d62a17ae 4018 struct bgp *bgp;
4019 char pfx_buf[BGP_PRD_PATH_STRLEN];
4020 struct bgp_node *rn;
40381db7 4021 struct bgp_path_info *pi;
718e3744 4022
28070ee3 4023#if ENABLE_BGP_VNC
d62a17ae 4024 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4025 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4026 0);
4027 }
28070ee3
PZ
4028#endif
4029
d62a17ae 4030 bgp = peer->bgp;
4031
4032 /* Lookup node. */
4033 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
4034
4035 /* If peer is soft reconfiguration enabled. Record input packet for
4036 * further calculation.
4037 *
4038 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4039 * routes that are filtered. This tanks out Quagga RS pretty badly due
4040 * to
4041 * the iteration over all RS clients.
4042 * Since we need to remove the entry from adj_in anyway, do that first
4043 * and
4044 * if there was no entry, we don't need to do anything more.
4045 */
4046 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4047 && peer != bgp->peer_self)
4048 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
b4d46cc9
DL
4049 peer->stat_pfx_dup_withdraw++;
4050
d62a17ae 4051 if (bgp_debug_update(peer, p, NULL, 1)) {
4052 bgp_debug_rdpfxpath2str(
a4d82a8a 4053 afi, safi, prd, p, label, num_labels,
d62a17ae 4054 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4055 sizeof(pfx_buf));
4056 zlog_debug(
4057 "%s withdrawing route %s not in adj-in",
4058 peer->host, pfx_buf);
4059 }
4060 bgp_unlock_node(rn);
4061 return 0;
4062 }
cd808e74 4063
d62a17ae 4064 /* Lookup withdrawn route. */
6f94b685 4065 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4066 if (pi->peer == peer && pi->type == type
4067 && pi->sub_type == sub_type
4068 && pi->addpath_rx_id == addpath_id)
d62a17ae 4069 break;
4070
4071 /* Logging. */
4072 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4073 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4074 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4075 sizeof(pfx_buf));
4076 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4077 pfx_buf);
4078 }
718e3744 4079
d62a17ae 4080 /* Withdraw specified route from routing table. */
40381db7
DS
4081 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
4082 bgp_rib_withdraw(rn, pi, peer, afi, safi, prd);
ddb5b488
PZ
4083 if (SAFI_UNICAST == safi
4084 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4085 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4086 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4087 }
4088 if ((SAFI_MPLS_VPN == safi)
4089 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4090
40381db7 4091 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4092 }
4093 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4094 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4095 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4096 sizeof(pfx_buf));
4097 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4098 }
718e3744 4099
d62a17ae 4100 /* Unlock bgp_node_get() lock. */
4101 bgp_unlock_node(rn);
4102
4103 return 0;
718e3744 4104}
6b0655a2 4105
d62a17ae 4106void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4107 int withdraw)
718e3744 4108{
d62a17ae 4109 struct update_subgroup *subgrp;
4110 subgrp = peer_subgroup(peer, afi, safi);
4111 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4112}
6182d65b 4113
718e3744 4114
3f9c7369
DS
4115/*
4116 * bgp_stop_announce_route_timer
4117 */
d62a17ae 4118void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4119{
d62a17ae 4120 if (!paf->t_announce_route)
4121 return;
4122
4123 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4124}
6b0655a2 4125
3f9c7369
DS
4126/*
4127 * bgp_announce_route_timer_expired
4128 *
4129 * Callback that is invoked when the route announcement timer for a
4130 * peer_af expires.
4131 */
d62a17ae 4132static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4133{
d62a17ae 4134 struct peer_af *paf;
4135 struct peer *peer;
558d1fec 4136
d62a17ae 4137 paf = THREAD_ARG(t);
4138 peer = paf->peer;
718e3744 4139
d62a17ae 4140 if (peer->status != Established)
4141 return 0;
3f9c7369 4142
d62a17ae 4143 if (!peer->afc_nego[paf->afi][paf->safi])
4144 return 0;
3f9c7369 4145
d62a17ae 4146 peer_af_announce_route(paf, 1);
4147 return 0;
718e3744 4148}
4149
3f9c7369
DS
4150/*
4151 * bgp_announce_route
4152 *
4153 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4154 */
d62a17ae 4155void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4156{
4157 struct peer_af *paf;
4158 struct update_subgroup *subgrp;
4159
4160 paf = peer_af_find(peer, afi, safi);
4161 if (!paf)
4162 return;
4163 subgrp = PAF_SUBGRP(paf);
4164
4165 /*
4166 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4167 * or a refresh has already been triggered.
4168 */
4169 if (!subgrp || paf->t_announce_route)
4170 return;
4171
4172 /*
4173 * Start a timer to stagger/delay the announce. This serves
4174 * two purposes - announcement can potentially be combined for
4175 * multiple peers and the announcement doesn't happen in the
4176 * vty context.
4177 */
4178 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4179 (subgrp->peer_count == 1)
4180 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4181 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4182 &paf->t_announce_route);
3f9c7369
DS
4183}
4184
4185/*
4186 * Announce routes from all AF tables to a peer.
4187 *
4188 * This should ONLY be called when there is a need to refresh the
4189 * routes to the peer based on a policy change for this peer alone
4190 * or a route refresh request received from the peer.
4191 * The operation will result in splitting the peer from its existing
4192 * subgroups and putting it in new subgroups.
4193 */
d62a17ae 4194void bgp_announce_route_all(struct peer *peer)
718e3744 4195{
d62a17ae 4196 afi_t afi;
4197 safi_t safi;
4198
05c7a1cc
QY
4199 FOREACH_AFI_SAFI (afi, safi)
4200 bgp_announce_route(peer, afi, safi);
718e3744 4201}
6b0655a2 4202
d62a17ae 4203static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4204 struct bgp_table *table,
4205 struct prefix_rd *prd)
718e3744 4206{
d62a17ae 4207 int ret;
4208 struct bgp_node *rn;
4209 struct bgp_adj_in *ain;
718e3744 4210
d62a17ae 4211 if (!table)
4212 table = peer->bgp->rib[afi][safi];
718e3744 4213
d62a17ae 4214 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
4215 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
4216 if (ain->peer != peer)
4217 continue;
8692c506 4218
d7d15889 4219 struct bgp_path_info *pi;
d7c0a89a 4220 uint32_t num_labels = 0;
b57ba6d2 4221 mpls_label_t *label_pnt = NULL;
8cb687c2 4222 struct bgp_route_evpn evpn;
b57ba6d2 4223
d7d15889
DS
4224 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4225 pi = pi->next)
4226 if (pi->peer == peer)
4227 break;
4228
40381db7
DS
4229 if (pi && pi->extra)
4230 num_labels = pi->extra->num_labels;
b57ba6d2 4231 if (num_labels)
40381db7 4232 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4233 if (pi)
4234 memcpy(&evpn, &pi->attr->evpn_overlay,
4235 sizeof(evpn));
4236 else
4237 memset(&evpn, 0, sizeof(evpn));
8692c506 4238
ea47320b
DL
4239 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
4240 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4241 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4242 num_labels, 1, &evpn);
ea47320b
DL
4243
4244 if (ret < 0) {
4245 bgp_unlock_node(rn);
4246 return;
d62a17ae 4247 }
4248 }
718e3744 4249}
4250
d62a17ae 4251void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4252{
d62a17ae 4253 struct bgp_node *rn;
4254 struct bgp_table *table;
718e3744 4255
d62a17ae 4256 if (peer->status != Established)
4257 return;
718e3744 4258
d62a17ae 4259 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4260 && (safi != SAFI_EVPN))
4261 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4262 else
4263 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4264 rn = bgp_route_next(rn)) {
4265 table = bgp_node_get_bgp_table_info(rn);
4266 if (table != NULL) {
d62a17ae 4267 struct prefix_rd prd;
67009e22 4268
d62a17ae 4269 prd.family = AF_UNSPEC;
4270 prd.prefixlen = 64;
4271 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 4272
d62a17ae 4273 bgp_soft_reconfig_table(peer, afi, safi, table,
4274 &prd);
4275 }
67009e22 4276 }
718e3744 4277}
6b0655a2 4278
228da428 4279
d62a17ae 4280struct bgp_clear_node_queue {
4281 struct bgp_node *rn;
228da428
CC
4282};
4283
d62a17ae 4284static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4285{
d62a17ae 4286 struct bgp_clear_node_queue *cnq = data;
4287 struct bgp_node *rn = cnq->rn;
4288 struct peer *peer = wq->spec.data;
40381db7 4289 struct bgp_path_info *pi;
3103e8d2 4290 struct bgp *bgp;
d62a17ae 4291 afi_t afi = bgp_node_table(rn)->afi;
4292 safi_t safi = bgp_node_table(rn)->safi;
4293
4294 assert(rn && peer);
3103e8d2 4295 bgp = peer->bgp;
d62a17ae 4296
4297 /* It is possible that we have multiple paths for a prefix from a peer
4298 * if that peer is using AddPath.
4299 */
6f94b685 4300 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 4301 if (pi->peer != peer)
ea47320b
DL
4302 continue;
4303
4304 /* graceful restart STALE flag set. */
4305 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4306 && peer->nsf[afi][safi]
40381db7
DS
4307 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4308 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
4309 bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE);
ea47320b
DL
4310 else {
4311 /* If this is an EVPN route, process for
4312 * un-import. */
4313 if (safi == SAFI_EVPN)
40381db7
DS
4314 bgp_evpn_unimport_route(bgp, afi, safi, &rn->p,
4315 pi);
3103e8d2
DS
4316 /* Handle withdraw for VRF route-leaking and L3VPN */
4317 if (SAFI_UNICAST == safi
4318 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4319 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4320 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4321 bgp, pi);
960035b2 4322 }
3103e8d2 4323 if (SAFI_MPLS_VPN == safi &&
960035b2 4324 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4325 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4326 }
3103e8d2 4327
40381db7 4328 bgp_rib_remove(rn, pi, peer, afi, safi);
d62a17ae 4329 }
ea47320b 4330 }
d62a17ae 4331 return WQ_SUCCESS;
200df115 4332}
4333
d62a17ae 4334static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4335{
d62a17ae 4336 struct bgp_clear_node_queue *cnq = data;
4337 struct bgp_node *rn = cnq->rn;
4338 struct bgp_table *table = bgp_node_table(rn);
228da428 4339
d62a17ae 4340 bgp_unlock_node(rn);
4341 bgp_table_unlock(table);
4342 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4343}
4344
d62a17ae 4345static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4346{
d62a17ae 4347 struct peer *peer = wq->spec.data;
64e580a7 4348
d62a17ae 4349 /* Tickle FSM to start moving again */
4350 BGP_EVENT_ADD(peer, Clearing_Completed);
4351
4352 peer_unlock(peer); /* bgp_clear_route */
200df115 4353}
718e3744 4354
d62a17ae 4355static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4356{
d62a17ae 4357 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4358
4359 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4360#undef CLEAR_QUEUE_NAME_LEN
4361
0ce1ca80 4362 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4363 peer->clear_node_queue->spec.hold = 10;
4364 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4365 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4366 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4367 peer->clear_node_queue->spec.max_retries = 0;
4368
4369 /* we only 'lock' this peer reference when the queue is actually active
4370 */
4371 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4372}
4373
d62a17ae 4374static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4375 struct bgp_table *table)
65ca75e0 4376{
d62a17ae 4377 struct bgp_node *rn;
4378 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4379
d62a17ae 4380 if (!table)
4381 table = peer->bgp->rib[afi][safi];
dc83d712 4382
d62a17ae 4383 /* If still no table => afi/safi isn't configured at all or smth. */
4384 if (!table)
4385 return;
dc83d712 4386
d62a17ae 4387 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
40381db7 4388 struct bgp_path_info *pi, *next;
d62a17ae 4389 struct bgp_adj_in *ain;
4390 struct bgp_adj_in *ain_next;
4391
4392 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4393 * queued for every clearing peer, regardless of whether it is
4394 * relevant to the peer at hand.
4395 *
4396 * Overview: There are 3 different indices which need to be
4397 * scrubbed, potentially, when a peer is removed:
4398 *
4399 * 1 peer's routes visible via the RIB (ie accepted routes)
4400 * 2 peer's routes visible by the (optional) peer's adj-in index
4401 * 3 other routes visible by the peer's adj-out index
4402 *
4403 * 3 there is no hurry in scrubbing, once the struct peer is
4404 * removed from bgp->peer, we could just GC such deleted peer's
4405 * adj-outs at our leisure.
4406 *
4407 * 1 and 2 must be 'scrubbed' in some way, at least made
4408 * invisible via RIB index before peer session is allowed to be
4409 * brought back up. So one needs to know when such a 'search' is
4410 * complete.
4411 *
4412 * Ideally:
4413 *
4414 * - there'd be a single global queue or a single RIB walker
4415 * - rather than tracking which route_nodes still need to be
4416 * examined on a peer basis, we'd track which peers still
4417 * aren't cleared
4418 *
4419 * Given that our per-peer prefix-counts now should be reliable,
4420 * this may actually be achievable. It doesn't seem to be a huge
4421 * problem at this time,
4422 *
4423 * It is possible that we have multiple paths for a prefix from
4424 * a peer
4425 * if that peer is using AddPath.
4426 */
4427 ain = rn->adj_in;
4428 while (ain) {
4429 ain_next = ain->next;
4430
4431 if (ain->peer == peer) {
4432 bgp_adj_in_remove(rn, ain);
4433 bgp_unlock_node(rn);
4434 }
4435
4436 ain = ain_next;
4437 }
4438
6f94b685 4439 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7
DS
4440 next = pi->next;
4441 if (pi->peer != peer)
d62a17ae 4442 continue;
4443
4444 if (force)
40381db7 4445 bgp_path_info_reap(rn, pi);
d62a17ae 4446 else {
4447 struct bgp_clear_node_queue *cnq;
4448
4449 /* both unlocked in bgp_clear_node_queue_del */
4450 bgp_table_lock(bgp_node_table(rn));
4451 bgp_lock_node(rn);
4452 cnq = XCALLOC(
4453 MTYPE_BGP_CLEAR_NODE_QUEUE,
4454 sizeof(struct bgp_clear_node_queue));
4455 cnq->rn = rn;
4456 work_queue_add(peer->clear_node_queue, cnq);
4457 break;
4458 }
4459 }
4460 }
4461 return;
4462}
4463
4464void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4465{
4466 struct bgp_node *rn;
4467 struct bgp_table *table;
4468
4469 if (peer->clear_node_queue == NULL)
4470 bgp_clear_node_queue_init(peer);
4471
4472 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4473 * Idle until it receives a Clearing_Completed event. This protects
4474 * against peers which flap faster than we can we clear, which could
4475 * lead to:
4476 *
4477 * a) race with routes from the new session being installed before
4478 * clear_route_node visits the node (to delete the route of that
4479 * peer)
4480 * b) resource exhaustion, clear_route_node likely leads to an entry
4481 * on the process_main queue. Fast-flapping could cause that queue
4482 * to grow and grow.
4483 */
4484
4485 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4486 * the unlock will happen upon work-queue completion; other wise, the
4487 * unlock happens at the end of this function.
4488 */
4489 if (!peer->clear_node_queue->thread)
4490 peer_lock(peer);
4491
4492 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4493 bgp_clear_route_table(peer, afi, safi, NULL);
4494 else
4495 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
67009e22
DS
4496 rn = bgp_route_next(rn)) {
4497 table = bgp_node_get_bgp_table_info(rn);
4498 if (!table)
4499 continue;
4500
4501 bgp_clear_route_table(peer, afi, safi, table);
4502 }
d62a17ae 4503
4504 /* unlock if no nodes got added to the clear-node-queue. */
4505 if (!peer->clear_node_queue->thread)
4506 peer_unlock(peer);
718e3744 4507}
d62a17ae 4508
4509void bgp_clear_route_all(struct peer *peer)
718e3744 4510{
d62a17ae 4511 afi_t afi;
4512 safi_t safi;
718e3744 4513
05c7a1cc
QY
4514 FOREACH_AFI_SAFI (afi, safi)
4515 bgp_clear_route(peer, afi, safi);
65efcfce
LB
4516
4517#if ENABLE_BGP_VNC
d62a17ae 4518 rfapiProcessPeerDown(peer);
65efcfce 4519#endif
718e3744 4520}
4521
d62a17ae 4522void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4523{
d62a17ae 4524 struct bgp_table *table;
4525 struct bgp_node *rn;
4526 struct bgp_adj_in *ain;
4527 struct bgp_adj_in *ain_next;
718e3744 4528
d62a17ae 4529 table = peer->bgp->rib[afi][safi];
718e3744 4530
d62a17ae 4531 /* It is possible that we have multiple paths for a prefix from a peer
4532 * if that peer is using AddPath.
4533 */
4534 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4535 ain = rn->adj_in;
43143c8f 4536
d62a17ae 4537 while (ain) {
4538 ain_next = ain->next;
43143c8f 4539
d62a17ae 4540 if (ain->peer == peer) {
4541 bgp_adj_in_remove(rn, ain);
4542 bgp_unlock_node(rn);
4543 }
43143c8f 4544
d62a17ae 4545 ain = ain_next;
4546 }
4547 }
718e3744 4548}
93406d87 4549
d62a17ae 4550void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4551{
4552 struct bgp_node *rn;
40381db7 4553 struct bgp_path_info *pi;
d62a17ae 4554 struct bgp_table *table;
4555
4556 if (safi == SAFI_MPLS_VPN) {
4557 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4558 rn = bgp_route_next(rn)) {
4559 struct bgp_node *rm;
d62a17ae 4560
4561 /* look for neighbor in tables */
67009e22
DS
4562 table = bgp_node_get_bgp_table_info(rn);
4563 if (!table)
ea47320b
DL
4564 continue;
4565
4566 for (rm = bgp_table_top(table); rm;
4567 rm = bgp_route_next(rm))
6f94b685
DS
4568 for (pi = bgp_node_get_bgp_path_info(rm); pi;
4569 pi = pi->next) {
40381db7 4570 if (pi->peer != peer)
ea47320b 4571 continue;
40381db7 4572 if (!CHECK_FLAG(pi->flags,
1defdda8 4573 BGP_PATH_STALE))
ea47320b
DL
4574 break;
4575
40381db7 4576 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4577 break;
4578 }
d62a17ae 4579 }
4580 } else {
4581 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
4582 rn = bgp_route_next(rn))
6f94b685
DS
4583 for (pi = bgp_node_get_bgp_path_info(rn); pi;
4584 pi = pi->next) {
40381db7 4585 if (pi->peer != peer)
ea47320b 4586 continue;
40381db7 4587 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4588 break;
40381db7 4589 bgp_rib_remove(rn, pi, peer, afi, safi);
ea47320b
DL
4590 break;
4591 }
d62a17ae 4592 }
93406d87 4593}
6b0655a2 4594
9dac9fc8
DA
4595int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4596{
e0df4c04
DA
4597 if (peer->sort == BGP_PEER_IBGP)
4598 return 1;
4599
9dac9fc8
DA
4600 if (peer->sort == BGP_PEER_EBGP
4601 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4602 || FILTER_LIST_OUT_NAME(filter)
4603 || DISTRIBUTE_OUT_NAME(filter)))
4604 return 1;
4605 return 0;
4606}
4607
4608int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
4609{
e0df4c04
DA
4610 if (peer->sort == BGP_PEER_IBGP)
4611 return 1;
4612
9dac9fc8
DA
4613 if (peer->sort == BGP_PEER_EBGP
4614 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4615 || FILTER_LIST_IN_NAME(filter)
4616 || DISTRIBUTE_IN_NAME(filter)))
4617 return 1;
4618 return 0;
4619}
4620
568e10ca 4621static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4622 safi_t safi)
bb86c601 4623{
d62a17ae 4624 struct bgp_node *rn;
40381db7 4625 struct bgp_path_info *pi;
4b7e6066 4626 struct bgp_path_info *next;
bb86c601 4627
d62a17ae 4628 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
6f94b685 4629 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = next) {
40381db7 4630 next = pi->next;
1b7bb747
CS
4631
4632 /* Unimport EVPN routes from VRFs */
4633 if (safi == SAFI_EVPN)
4634 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
4635 SAFI_EVPN,
4636 &rn->p, pi);
4637
40381db7
DS
4638 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4639 && pi->type == ZEBRA_ROUTE_BGP
4640 && (pi->sub_type == BGP_ROUTE_NORMAL
4641 || pi->sub_type == BGP_ROUTE_AGGREGATE
4642 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4643
d62a17ae 4644 if (bgp_fibupd_safi(safi))
40381db7
DS
4645 bgp_zebra_withdraw(&rn->p, pi, bgp,
4646 safi);
4647 bgp_path_info_reap(rn, pi);
d62a17ae 4648 }
4649 }
bb86c601
LB
4650}
4651
718e3744 4652/* Delete all kernel routes. */
d62a17ae 4653void bgp_cleanup_routes(struct bgp *bgp)
4654{
4655 afi_t afi;
4656 struct bgp_node *rn;
67009e22 4657 struct bgp_table *table;
d62a17ae 4658
4659 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4660 if (afi == AFI_L2VPN)
4661 continue;
568e10ca 4662 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4663 SAFI_UNICAST);
d62a17ae 4664 /*
4665 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4666 */
4667 if (afi != AFI_L2VPN) {
4668 safi_t safi;
4669 safi = SAFI_MPLS_VPN;
4670 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4671 rn = bgp_route_next(rn)) {
67009e22
DS
4672 table = bgp_node_get_bgp_table_info(rn);
4673 if (table != NULL) {
4674 bgp_cleanup_table(bgp, table, safi);
4675 bgp_table_finish(&table);
4676 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4677 bgp_unlock_node(rn);
4678 }
4679 }
4680 safi = SAFI_ENCAP;
4681 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
4682 rn = bgp_route_next(rn)) {
67009e22
DS
4683 table = bgp_node_get_bgp_table_info(rn);
4684 if (table != NULL) {
4685 bgp_cleanup_table(bgp, table, safi);
4686 bgp_table_finish(&table);
4687 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4688 bgp_unlock_node(rn);
4689 }
4690 }
4691 }
4692 }
4693 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
4694 rn = bgp_route_next(rn)) {
67009e22
DS
4695 table = bgp_node_get_bgp_table_info(rn);
4696 if (table != NULL) {
4697 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4698 bgp_table_finish(&table);
4699 bgp_node_set_bgp_table_info(rn, NULL);
d62a17ae 4700 bgp_unlock_node(rn);
4701 }
bb86c601 4702 }
718e3744 4703}
4704
d62a17ae 4705void bgp_reset(void)
718e3744 4706{
d62a17ae 4707 vty_reset();
4708 bgp_zclient_reset();
4709 access_list_reset();
4710 prefix_list_reset();
718e3744 4711}
6b0655a2 4712
d62a17ae 4713static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4714{
d62a17ae 4715 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4716 && CHECK_FLAG(peer->af_cap[afi][safi],
4717 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4718}
4719
718e3744 4720/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4721 value. */
d62a17ae 4722int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4723 struct bgp_nlri *packet)
4724{
d7c0a89a
QY
4725 uint8_t *pnt;
4726 uint8_t *lim;
d62a17ae 4727 struct prefix p;
4728 int psize;
4729 int ret;
4730 afi_t afi;
4731 safi_t safi;
4732 int addpath_encoded;
d7c0a89a 4733 uint32_t addpath_id;
d62a17ae 4734
d62a17ae 4735 pnt = packet->nlri;
4736 lim = pnt + packet->length;
4737 afi = packet->afi;
4738 safi = packet->safi;
4739 addpath_id = 0;
4740 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4741
4742 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4743 syntactic validity. If the field is syntactically incorrect,
4744 then the Error Subcode is set to Invalid Network Field. */
4745 for (; pnt < lim; pnt += psize) {
4746 /* Clear prefix structure. */
4747 memset(&p, 0, sizeof(struct prefix));
4748
4749 if (addpath_encoded) {
4750
4751 /* When packet overflow occurs return immediately. */
761ed665 4752 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4753 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4754
a3a850a1 4755 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4756 addpath_id = ntohl(addpath_id);
d62a17ae 4757 pnt += BGP_ADDPATH_ID_LEN;
4758 }
718e3744 4759
d62a17ae 4760 /* Fetch prefix length. */
4761 p.prefixlen = *pnt++;
4762 /* afi/safi validity already verified by caller,
4763 * bgp_update_receive */
4764 p.family = afi2family(afi);
4765
4766 /* Prefix length check. */
4767 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4768 flog_err(
e50f7cfd 4769 EC_BGP_UPDATE_RCV,
14454c9f 4770 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4771 peer->host, p.prefixlen, packet->afi);
513386b5 4772 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4773 }
6b0655a2 4774
d62a17ae 4775 /* Packet size overflow check. */
4776 psize = PSIZE(p.prefixlen);
4777
4778 /* When packet overflow occur return immediately. */
4779 if (pnt + psize > lim) {
af4c2728 4780 flog_err(
e50f7cfd 4781 EC_BGP_UPDATE_RCV,
d62a17ae 4782 "%s [Error] Update packet error (prefix length %d overflows packet)",
4783 peer->host, p.prefixlen);
513386b5 4784 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4785 }
4786
4787 /* Defensive coding, double-check the psize fits in a struct
4788 * prefix */
4789 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4790 flog_err(
e50f7cfd 4791 EC_BGP_UPDATE_RCV,
d62a17ae 4792 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4793 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4794 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4795 }
4796
4797 /* Fetch prefix from NLRI packet. */
a85297a7 4798 memcpy(p.u.val, pnt, psize);
d62a17ae 4799
4800 /* Check address. */
4801 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4802 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4803 /* From RFC4271 Section 6.3:
4804 *
4805 * If a prefix in the NLRI field is semantically
4806 * incorrect
4807 * (e.g., an unexpected multicast IP address),
4808 * an error SHOULD
4809 * be logged locally, and the prefix SHOULD be
4810 * ignored.
a4d82a8a 4811 */
af4c2728 4812 flog_err(
e50f7cfd 4813 EC_BGP_UPDATE_RCV,
d62a17ae 4814 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4815 peer->host, inet_ntoa(p.u.prefix4));
4816 continue;
4817 }
4818 }
4819
4820 /* Check address. */
4821 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4822 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4823 char buf[BUFSIZ];
4824
af4c2728 4825 flog_err(
e50f7cfd 4826 EC_BGP_UPDATE_RCV,
d62a17ae 4827 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4828 peer->host,
4829 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4830 BUFSIZ));
4831
4832 continue;
4833 }
4834 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4835 char buf[BUFSIZ];
4836
af4c2728 4837 flog_err(
e50f7cfd 4838 EC_BGP_UPDATE_RCV,
d62a17ae 4839 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4840 peer->host,
4841 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4842 BUFSIZ));
4843
4844 continue;
4845 }
4846 }
4847
4848 /* Normal process. */
4849 if (attr)
4850 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4851 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 4852 NULL, NULL, 0, 0, NULL);
d62a17ae 4853 else
4854 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4855 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
4856 BGP_ROUTE_NORMAL, NULL, NULL, 0,
4857 NULL);
d62a17ae 4858
513386b5
DA
4859 /* Do not send BGP notification twice when maximum-prefix count
4860 * overflow. */
4861 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4862 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
4863
4864 /* Address family configuration mismatch. */
d62a17ae 4865 if (ret < 0)
513386b5 4866 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 4867 }
4868
4869 /* Packet length consistency check. */
4870 if (pnt != lim) {
af4c2728 4871 flog_err(
e50f7cfd 4872 EC_BGP_UPDATE_RCV,
d62a17ae 4873 "%s [Error] Update packet error (prefix length mismatch with total length)",
4874 peer->host);
513386b5 4875 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4876 }
6b0655a2 4877
513386b5 4878 return BGP_NLRI_PARSE_OK;
718e3744 4879}
4880
d62a17ae 4881static struct bgp_static *bgp_static_new(void)
718e3744 4882{
d62a17ae 4883 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4884}
4885
d62a17ae 4886static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4887{
0a22ddfb 4888 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 4889 route_map_counter_decrement(bgp_static->rmap.map);
4890
0a22ddfb 4891 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 4892 XFREE(MTYPE_BGP_STATIC, bgp_static);
4893}
4894
4895void bgp_static_update(struct bgp *bgp, struct prefix *p,
4896 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4897{
4898 struct bgp_node *rn;
40381db7 4899 struct bgp_path_info *pi;
4b7e6066 4900 struct bgp_path_info *new;
40381db7 4901 struct bgp_path_info rmap_path;
d62a17ae 4902 struct attr attr;
4903 struct attr *attr_new;
b68885f9 4904 route_map_result_t ret;
65efcfce 4905#if ENABLE_BGP_VNC
d62a17ae 4906 int vnc_implicit_withdraw = 0;
65efcfce 4907#endif
fee0f4c6 4908
d62a17ae 4909 assert(bgp_static);
dd8103a9 4910
d62a17ae 4911 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4912
d62a17ae 4913 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4914
d62a17ae 4915 attr.nexthop = bgp_static->igpnexthop;
4916 attr.med = bgp_static->igpmetric;
4917 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4918
d62a17ae 4919 if (bgp_static->atomic)
4920 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4921
d62a17ae 4922 /* Store label index, if required. */
4923 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4924 attr.label_index = bgp_static->label_index;
4925 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4926 }
718e3744 4927
d62a17ae 4928 /* Apply route-map. */
4929 if (bgp_static->rmap.name) {
4930 struct attr attr_tmp = attr;
80ced710 4931
40381db7
DS
4932 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
4933 rmap_path.peer = bgp->peer_self;
4934 rmap_path.attr = &attr_tmp;
fee0f4c6 4935
d62a17ae 4936 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4937
40381db7
DS
4938 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
4939 &rmap_path);
fee0f4c6 4940
d62a17ae 4941 bgp->peer_self->rmap_type = 0;
718e3744 4942
d62a17ae 4943 if (ret == RMAP_DENYMATCH) {
4944 /* Free uninterned attribute. */
4945 bgp_attr_flush(&attr_tmp);
718e3744 4946
d62a17ae 4947 /* Unintern original. */
4948 aspath_unintern(&attr.aspath);
4949 bgp_static_withdraw(bgp, p, afi, safi);
4950 return;
4951 }
7f323236 4952
892fedb6 4953 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
4954 bgp_attr_add_gshut_community(&attr_tmp);
4955
d62a17ae 4956 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4957 } else {
4958
892fedb6 4959 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
4960 bgp_attr_add_gshut_community(&attr);
4961
d62a17ae 4962 attr_new = bgp_attr_intern(&attr);
7f323236 4963 }
718e3744 4964
6f94b685 4965 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
4966 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
4967 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 4968 break;
4969
40381db7
DS
4970 if (pi) {
4971 if (attrhash_cmp(pi->attr, attr_new)
4972 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 4973 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
d62a17ae 4974 bgp_unlock_node(rn);
4975 bgp_attr_unintern(&attr_new);
4976 aspath_unintern(&attr.aspath);
4977 return;
4978 } else {
4979 /* The attribute is changed. */
40381db7 4980 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4981
4982 /* Rewrite BGP route information. */
40381db7
DS
4983 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
4984 bgp_path_info_restore(rn, pi);
d62a17ae 4985 else
40381db7 4986 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
65efcfce 4987#if ENABLE_BGP_VNC
d62a17ae 4988 if ((afi == AFI_IP || afi == AFI_IP6)
4989 && (safi == SAFI_UNICAST)) {
40381db7 4990 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4991 /*
4992 * Implicit withdraw case.
40381db7 4993 * We have to do this before pi is
d62a17ae 4994 * changed
4995 */
4996 ++vnc_implicit_withdraw;
40381db7 4997 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 4998 vnc_import_bgp_exterior_del_route(
40381db7 4999 bgp, p, pi);
d62a17ae 5000 }
5001 }
65efcfce 5002#endif
40381db7
DS
5003 bgp_attr_unintern(&pi->attr);
5004 pi->attr = attr_new;
5005 pi->uptime = bgp_clock();
65efcfce 5006#if ENABLE_BGP_VNC
d62a17ae 5007 if ((afi == AFI_IP || afi == AFI_IP6)
5008 && (safi == SAFI_UNICAST)) {
5009 if (vnc_implicit_withdraw) {
40381db7 5010 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5011 vnc_import_bgp_exterior_add_route(
40381db7 5012 bgp, p, pi);
d62a17ae 5013 }
5014 }
65efcfce 5015#endif
718e3744 5016
d62a17ae 5017 /* Nexthop reachability check. */
892fedb6 5018 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5019 && (safi == SAFI_UNICAST
5020 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5021
5022 struct bgp *bgp_nexthop = bgp;
5023
40381db7
DS
5024 if (pi->extra && pi->extra->bgp_orig)
5025 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5026
5027 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7
DS
5028 afi, pi, NULL, 0))
5029 bgp_path_info_set_flag(rn, pi,
18ee8310 5030 BGP_PATH_VALID);
d62a17ae 5031 else {
5032 if (BGP_DEBUG(nht, NHT)) {
5033 char buf1[INET6_ADDRSTRLEN];
5034 inet_ntop(p->family,
5035 &p->u.prefix, buf1,
5036 INET6_ADDRSTRLEN);
5037 zlog_debug(
5038 "%s(%s): Route not in table, not advertising",
15569c58 5039 __func__, buf1);
d62a17ae 5040 }
18ee8310 5041 bgp_path_info_unset_flag(
40381db7 5042 rn, pi, BGP_PATH_VALID);
d62a17ae 5043 }
5044 } else {
5045 /* Delete the NHT structure if any, if we're
5046 * toggling between
5047 * enabling/disabling import check. We
5048 * deregister the route
5049 * from NHT to avoid overloading NHT and the
5050 * process interaction
5051 */
40381db7
DS
5052 bgp_unlink_nexthop(pi);
5053 bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
d62a17ae 5054 }
5055 /* Process change. */
40381db7 5056 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5057 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5058
5059 if (SAFI_UNICAST == safi
5060 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5061 || bgp->inst_type
5062 == BGP_INSTANCE_TYPE_DEFAULT)) {
5063 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5064 pi);
ddb5b488
PZ
5065 }
5066
d62a17ae 5067 bgp_unlock_node(rn);
5068 aspath_unintern(&attr.aspath);
5069 return;
5070 }
718e3744 5071 }
718e3744 5072
d62a17ae 5073 /* Make new BGP info. */
5074 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5075 attr_new, rn);
5076 /* Nexthop reachability check. */
892fedb6 5077 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5078 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5079 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
18ee8310 5080 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5081 else {
5082 if (BGP_DEBUG(nht, NHT)) {
5083 char buf1[INET6_ADDRSTRLEN];
5084 inet_ntop(p->family, &p->u.prefix, buf1,
5085 INET6_ADDRSTRLEN);
5086 zlog_debug(
5087 "%s(%s): Route not in table, not advertising",
15569c58 5088 __func__, buf1);
d62a17ae 5089 }
18ee8310 5090 bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID);
d62a17ae 5091 }
5092 } else {
5093 /* Delete the NHT structure if any, if we're toggling between
5094 * enabling/disabling import check. We deregister the route
5095 * from NHT to avoid overloading NHT and the process interaction
5096 */
5097 bgp_unlink_nexthop(new);
5098
18ee8310 5099 bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
fc9a856f 5100 }
078430f6 5101
d62a17ae 5102 /* Aggregate address increment. */
5103 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5104
d62a17ae 5105 /* Register new BGP information. */
18ee8310 5106 bgp_path_info_add(rn, new);
718e3744 5107
d62a17ae 5108 /* route_node_get lock */
5109 bgp_unlock_node(rn);
5110
5111 /* Process change. */
5112 bgp_process(bgp, rn, afi, safi);
5113
ddb5b488
PZ
5114 if (SAFI_UNICAST == safi
5115 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5116 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5117 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5118 }
5119
d62a17ae 5120 /* Unintern original. */
5121 aspath_unintern(&attr.aspath);
718e3744 5122}
5123
d62a17ae 5124void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
5125 safi_t safi)
718e3744 5126{
d62a17ae 5127 struct bgp_node *rn;
40381db7 5128 struct bgp_path_info *pi;
718e3744 5129
d62a17ae 5130 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5131
d62a17ae 5132 /* Check selected route and self inserted route. */
6f94b685 5133 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5134 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5135 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5136 break;
5137
5138 /* Withdraw static BGP route from routing table. */
40381db7 5139 if (pi) {
ddb5b488
PZ
5140 if (SAFI_UNICAST == safi
5141 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5142 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5143 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5144 }
40381db7
DS
5145 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5146 bgp_unlink_nexthop(pi);
5147 bgp_path_info_delete(rn, pi);
d62a17ae 5148 bgp_process(bgp, rn, afi, safi);
5149 }
718e3744 5150
d62a17ae 5151 /* Unlock bgp_node_lookup. */
5152 bgp_unlock_node(rn);
718e3744 5153}
5154
137446f9
LB
5155/*
5156 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5157 */
d62a17ae 5158static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
5159 afi_t afi, safi_t safi,
5160 struct prefix_rd *prd)
718e3744 5161{
d62a17ae 5162 struct bgp_node *rn;
40381db7 5163 struct bgp_path_info *pi;
718e3744 5164
d62a17ae 5165 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5166
d62a17ae 5167 /* Check selected route and self inserted route. */
6f94b685 5168 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5169 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5170 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5171 break;
718e3744 5172
d62a17ae 5173 /* Withdraw static BGP route from routing table. */
40381db7 5174 if (pi) {
65efcfce 5175#if ENABLE_BGP_VNC
d62a17ae 5176 rfapiProcessWithdraw(
40381db7 5177 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5178 1); /* Kill, since it is an administrative change */
65efcfce 5179#endif
ddb5b488
PZ
5180 if (SAFI_MPLS_VPN == safi
5181 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5182 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5183 }
40381db7
DS
5184 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5185 bgp_path_info_delete(rn, pi);
d62a17ae 5186 bgp_process(bgp, rn, afi, safi);
5187 }
718e3744 5188
d62a17ae 5189 /* Unlock bgp_node_lookup. */
5190 bgp_unlock_node(rn);
718e3744 5191}
5192
d62a17ae 5193static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
5194 struct bgp_static *bgp_static, afi_t afi,
5195 safi_t safi)
137446f9 5196{
d62a17ae 5197 struct bgp_node *rn;
4b7e6066 5198 struct bgp_path_info *new;
d62a17ae 5199 struct attr *attr_new;
5200 struct attr attr = {0};
40381db7 5201 struct bgp_path_info *pi;
65efcfce 5202#if ENABLE_BGP_VNC
d62a17ae 5203 mpls_label_t label = 0;
65efcfce 5204#endif
d7c0a89a 5205 uint32_t num_labels = 0;
d62a17ae 5206 union gw_addr add;
137446f9 5207
d62a17ae 5208 assert(bgp_static);
137446f9 5209
b57ba6d2
MK
5210 if (bgp_static->label != MPLS_INVALID_LABEL)
5211 num_labels = 1;
d62a17ae 5212 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5213 &bgp_static->prd);
137446f9 5214
d62a17ae 5215 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5216
d62a17ae 5217 attr.nexthop = bgp_static->igpnexthop;
5218 attr.med = bgp_static->igpmetric;
5219 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5220
d62a17ae 5221 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5222 || (safi == SAFI_ENCAP)) {
5223 if (afi == AFI_IP) {
5224 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5225 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5226 }
5227 }
5228 if (afi == AFI_L2VPN) {
5229 if (bgp_static->gatewayIp.family == AF_INET)
5230 add.ipv4.s_addr =
5231 bgp_static->gatewayIp.u.prefix4.s_addr;
5232 else if (bgp_static->gatewayIp.family == AF_INET6)
5233 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5234 sizeof(struct in6_addr));
5235 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
5236 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5237 struct bgp_encap_type_vxlan bet;
5238 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5239 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5240 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5241 }
5242 if (bgp_static->router_mac) {
5243 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5244 }
5245 }
5246 /* Apply route-map. */
5247 if (bgp_static->rmap.name) {
5248 struct attr attr_tmp = attr;
40381db7 5249 struct bgp_path_info rmap_path;
b68885f9 5250 route_map_result_t ret;
137446f9 5251
40381db7
DS
5252 rmap_path.peer = bgp->peer_self;
5253 rmap_path.attr = &attr_tmp;
137446f9 5254
d62a17ae 5255 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5256
40381db7
DS
5257 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5258 &rmap_path);
137446f9 5259
d62a17ae 5260 bgp->peer_self->rmap_type = 0;
137446f9 5261
d62a17ae 5262 if (ret == RMAP_DENYMATCH) {
5263 /* Free uninterned attribute. */
5264 bgp_attr_flush(&attr_tmp);
137446f9 5265
d62a17ae 5266 /* Unintern original. */
5267 aspath_unintern(&attr.aspath);
5268 bgp_static_withdraw_safi(bgp, p, afi, safi,
5269 &bgp_static->prd);
5270 return;
5271 }
137446f9 5272
d62a17ae 5273 attr_new = bgp_attr_intern(&attr_tmp);
5274 } else {
5275 attr_new = bgp_attr_intern(&attr);
5276 }
137446f9 5277
6f94b685 5278 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
5279 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5280 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5281 break;
5282
40381db7 5283 if (pi) {
d62a17ae 5284 memset(&add, 0, sizeof(union gw_addr));
40381db7
DS
5285 if (attrhash_cmp(pi->attr, attr_new)
5286 && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add)
5287 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 5288 bgp_unlock_node(rn);
5289 bgp_attr_unintern(&attr_new);
5290 aspath_unintern(&attr.aspath);
5291 return;
5292 } else {
5293 /* The attribute is changed. */
40381db7 5294 bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5295
5296 /* Rewrite BGP route information. */
40381db7
DS
5297 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
5298 bgp_path_info_restore(rn, pi);
d62a17ae 5299 else
40381db7
DS
5300 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5301 bgp_attr_unintern(&pi->attr);
5302 pi->attr = attr_new;
5303 pi->uptime = bgp_clock();
65efcfce 5304#if ENABLE_BGP_VNC
40381db7
DS
5305 if (pi->extra)
5306 label = decode_label(&pi->extra->label[0]);
65efcfce 5307#endif
137446f9 5308
d62a17ae 5309 /* Process change. */
40381db7 5310 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 5311 bgp_process(bgp, rn, afi, safi);
ddb5b488
PZ
5312
5313 if (SAFI_MPLS_VPN == safi
5314 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5315 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5316 }
65efcfce 5317#if ENABLE_BGP_VNC
40381db7
DS
5318 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5319 pi->attr, afi, safi, pi->type,
5320 pi->sub_type, &label);
65efcfce 5321#endif
d62a17ae 5322 bgp_unlock_node(rn);
5323 aspath_unintern(&attr.aspath);
5324 return;
5325 }
5326 }
137446f9
LB
5327
5328
d62a17ae 5329 /* Make new BGP info. */
5330 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
5331 attr_new, rn);
1defdda8 5332 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5333 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5334 if (num_labels) {
5335 new->extra->label[0] = bgp_static->label;
5336 new->extra->num_labels = num_labels;
5337 }
65efcfce 5338#if ENABLE_BGP_VNC
d62a17ae 5339 label = decode_label(&bgp_static->label);
65efcfce 5340#endif
137446f9 5341
d62a17ae 5342 /* Aggregate address increment. */
5343 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5344
d62a17ae 5345 /* Register new BGP information. */
18ee8310 5346 bgp_path_info_add(rn, new);
d62a17ae 5347 /* route_node_get lock */
5348 bgp_unlock_node(rn);
137446f9 5349
d62a17ae 5350 /* Process change. */
5351 bgp_process(bgp, rn, afi, safi);
137446f9 5352
ddb5b488
PZ
5353 if (SAFI_MPLS_VPN == safi
5354 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5355 vpn_leak_to_vrf_update(bgp, new);
5356 }
65efcfce 5357#if ENABLE_BGP_VNC
d62a17ae 5358 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5359 safi, new->type, new->sub_type, &label);
65efcfce
LB
5360#endif
5361
d62a17ae 5362 /* Unintern original. */
5363 aspath_unintern(&attr.aspath);
137446f9
LB
5364}
5365
718e3744 5366/* Configure static BGP network. When user don't run zebra, static
5367 route should be installed as valid. */
e2a86ad9
DS
5368static int bgp_static_set(struct vty *vty, const char *negate,
5369 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5370 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5371{
5372 VTY_DECLVAR_CONTEXT(bgp, bgp);
5373 int ret;
5374 struct prefix p;
5375 struct bgp_static *bgp_static;
5376 struct bgp_node *rn;
d7c0a89a 5377 uint8_t need_update = 0;
d62a17ae 5378
5379 /* Convert IP prefix string to struct prefix. */
5380 ret = str2prefix(ip_str, &p);
5381 if (!ret) {
5382 vty_out(vty, "%% Malformed prefix\n");
5383 return CMD_WARNING_CONFIG_FAILED;
5384 }
5385 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5386 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5387 return CMD_WARNING_CONFIG_FAILED;
5388 }
718e3744 5389
d62a17ae 5390 apply_mask(&p);
718e3744 5391
e2a86ad9 5392 if (negate) {
718e3744 5393
e2a86ad9
DS
5394 /* Set BGP static route configuration. */
5395 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5396
e2a86ad9 5397 if (!rn) {
a4d82a8a 5398 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5399 return CMD_WARNING_CONFIG_FAILED;
5400 }
5401
5a8ba9fc 5402 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5403
e2a86ad9
DS
5404 if ((label_index != BGP_INVALID_LABEL_INDEX)
5405 && (label_index != bgp_static->label_index)) {
5406 vty_out(vty,
5407 "%% label-index doesn't match static route\n");
5408 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5409 }
d62a17ae 5410
e2a86ad9
DS
5411 if ((rmap && bgp_static->rmap.name)
5412 && strcmp(rmap, bgp_static->rmap.name)) {
5413 vty_out(vty,
5414 "%% route-map name doesn't match static route\n");
5415 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5416 }
718e3744 5417
e2a86ad9
DS
5418 /* Update BGP RIB. */
5419 if (!bgp_static->backdoor)
5420 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5421
e2a86ad9
DS
5422 /* Clear configuration. */
5423 bgp_static_free(bgp_static);
5a8ba9fc 5424 bgp_node_set_bgp_static_info(rn, NULL);
e2a86ad9
DS
5425 bgp_unlock_node(rn);
5426 bgp_unlock_node(rn);
5427 } else {
718e3744 5428
e2a86ad9
DS
5429 /* Set BGP static route configuration. */
5430 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 5431
5a8ba9fc 5432 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 5433 if (bgp_static) {
e2a86ad9 5434 /* Configuration change. */
e2a86ad9
DS
5435 /* Label index cannot be changed. */
5436 if (bgp_static->label_index != label_index) {
5437 vty_out(vty, "%% cannot change label-index\n");
5438 return CMD_WARNING_CONFIG_FAILED;
5439 }
d62a17ae 5440
e2a86ad9 5441 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5442 if (bgp_static->valid
5443 && bgp_static->backdoor != backdoor)
e2a86ad9 5444 need_update = 1;
718e3744 5445
e2a86ad9 5446 bgp_static->backdoor = backdoor;
718e3744 5447
e2a86ad9 5448 if (rmap) {
0a22ddfb
QY
5449 XFREE(MTYPE_ROUTE_MAP_NAME,
5450 bgp_static->rmap.name);
b4897fa5 5451 route_map_counter_decrement(
5452 bgp_static->rmap.map);
e2a86ad9
DS
5453 bgp_static->rmap.name =
5454 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5455 bgp_static->rmap.map =
5456 route_map_lookup_by_name(rmap);
b4897fa5 5457 route_map_counter_increment(
5458 bgp_static->rmap.map);
e2a86ad9 5459 } else {
0a22ddfb
QY
5460 XFREE(MTYPE_ROUTE_MAP_NAME,
5461 bgp_static->rmap.name);
b4897fa5 5462 route_map_counter_decrement(
5463 bgp_static->rmap.map);
e2a86ad9
DS
5464 bgp_static->rmap.map = NULL;
5465 bgp_static->valid = 0;
5466 }
5467 bgp_unlock_node(rn);
5468 } else {
5469 /* New configuration. */
5470 bgp_static = bgp_static_new();
5471 bgp_static->backdoor = backdoor;
5472 bgp_static->valid = 0;
5473 bgp_static->igpmetric = 0;
975a328e 5474 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5475 bgp_static->label_index = label_index;
718e3744 5476
e2a86ad9 5477 if (rmap) {
0a22ddfb
QY
5478 XFREE(MTYPE_ROUTE_MAP_NAME,
5479 bgp_static->rmap.name);
b4897fa5 5480 route_map_counter_decrement(
5481 bgp_static->rmap.map);
e2a86ad9
DS
5482 bgp_static->rmap.name =
5483 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5484 bgp_static->rmap.map =
5485 route_map_lookup_by_name(rmap);
b4897fa5 5486 route_map_counter_increment(
5487 bgp_static->rmap.map);
e2a86ad9 5488 }
5a8ba9fc 5489 bgp_node_set_bgp_static_info(rn, bgp_static);
e2a86ad9 5490 }
d62a17ae 5491
e2a86ad9
DS
5492 bgp_static->valid = 1;
5493 if (need_update)
5494 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5495
e2a86ad9
DS
5496 if (!bgp_static->backdoor)
5497 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5498 }
d62a17ae 5499
5500 return CMD_SUCCESS;
5501}
5502
5503void bgp_static_add(struct bgp *bgp)
5504{
5505 afi_t afi;
5506 safi_t safi;
5507 struct bgp_node *rn;
5508 struct bgp_node *rm;
5509 struct bgp_table *table;
5510 struct bgp_static *bgp_static;
5511
05c7a1cc
QY
5512 FOREACH_AFI_SAFI (afi, safi)
5513 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5514 rn = bgp_route_next(rn)) {
67009e22 5515 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5516 continue;
ea47320b 5517
05c7a1cc
QY
5518 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5519 || (safi == SAFI_EVPN)) {
67009e22 5520 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5521
5522 for (rm = bgp_table_top(table); rm;
5523 rm = bgp_route_next(rm)) {
a78beeb5 5524 bgp_static =
5a8ba9fc
DS
5525 bgp_node_get_bgp_static_info(
5526 rm);
05c7a1cc
QY
5527 bgp_static_update_safi(bgp, &rm->p,
5528 bgp_static, afi,
5529 safi);
d62a17ae 5530 }
05c7a1cc 5531 } else {
5a8ba9fc
DS
5532 bgp_static_update(
5533 bgp, &rn->p,
5534 bgp_node_get_bgp_static_info(rn), afi,
5535 safi);
ea47320b 5536 }
05c7a1cc 5537 }
6aeb9e78
DS
5538}
5539
718e3744 5540/* Called from bgp_delete(). Delete all static routes from the BGP
5541 instance. */
d62a17ae 5542void bgp_static_delete(struct bgp *bgp)
5543{
5544 afi_t afi;
5545 safi_t safi;
5546 struct bgp_node *rn;
5547 struct bgp_node *rm;
5548 struct bgp_table *table;
5549 struct bgp_static *bgp_static;
5550
05c7a1cc
QY
5551 FOREACH_AFI_SAFI (afi, safi)
5552 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5553 rn = bgp_route_next(rn)) {
67009e22 5554 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5555 continue;
ea47320b 5556
05c7a1cc
QY
5557 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5558 || (safi == SAFI_EVPN)) {
67009e22 5559 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5560
5561 for (rm = bgp_table_top(table); rm;
5562 rm = bgp_route_next(rm)) {
a78beeb5 5563 bgp_static =
5a8ba9fc
DS
5564 bgp_node_get_bgp_static_info(
5565 rm);
c7d14ba6
PG
5566 if (!bgp_static)
5567 continue;
5568
05c7a1cc
QY
5569 bgp_static_withdraw_safi(
5570 bgp, &rm->p, AFI_IP, safi,
5571 (struct prefix_rd *)&rn->p);
ea47320b 5572 bgp_static_free(bgp_static);
5a8ba9fc 5573 bgp_node_set_bgp_static_info(rn, NULL);
ea47320b 5574 bgp_unlock_node(rn);
d62a17ae 5575 }
05c7a1cc 5576 } else {
5a8ba9fc 5577 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5578 bgp_static_withdraw(bgp, &rn->p, afi, safi);
5579 bgp_static_free(bgp_static);
5a8ba9fc 5580 bgp_node_set_bgp_static_info(rn, NULL);
05c7a1cc 5581 bgp_unlock_node(rn);
ea47320b 5582 }
05c7a1cc 5583 }
d62a17ae 5584}
5585
5586void bgp_static_redo_import_check(struct bgp *bgp)
5587{
5588 afi_t afi;
5589 safi_t safi;
5590 struct bgp_node *rn;
5591 struct bgp_node *rm;
5592 struct bgp_table *table;
5593 struct bgp_static *bgp_static;
5594
5595 /* Use this flag to force reprocessing of the route */
892fedb6 5596 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
5597 FOREACH_AFI_SAFI (afi, safi) {
5598 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
5599 rn = bgp_route_next(rn)) {
67009e22 5600 if (!bgp_node_has_bgp_path_info_data(rn))
05c7a1cc 5601 continue;
ea47320b 5602
05c7a1cc
QY
5603 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5604 || (safi == SAFI_EVPN)) {
67009e22 5605 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc
QY
5606
5607 for (rm = bgp_table_top(table); rm;
5608 rm = bgp_route_next(rm)) {
a78beeb5 5609 bgp_static =
5a8ba9fc
DS
5610 bgp_node_get_bgp_static_info(
5611 rm);
05c7a1cc
QY
5612 bgp_static_update_safi(bgp, &rm->p,
5613 bgp_static, afi,
5614 safi);
d62a17ae 5615 }
05c7a1cc 5616 } else {
5a8ba9fc 5617 bgp_static = bgp_node_get_bgp_static_info(rn);
05c7a1cc
QY
5618 bgp_static_update(bgp, &rn->p, bgp_static, afi,
5619 safi);
ea47320b 5620 }
05c7a1cc
QY
5621 }
5622 }
892fedb6 5623 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5624}
5625
5626static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5627 safi_t safi)
5628{
5629 struct bgp_table *table;
5630 struct bgp_node *rn;
40381db7 5631 struct bgp_path_info *pi;
d62a17ae 5632
dfb6fd1d
NT
5633 /* Do not install the aggregate route if BGP is in the
5634 * process of termination.
5635 */
892fedb6
DA
5636 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5637 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5638 return;
5639
d62a17ae 5640 table = bgp->rib[afi][safi];
5641 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 5642 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7
DS
5643 if (pi->peer == bgp->peer_self
5644 && ((pi->type == ZEBRA_ROUTE_BGP
5645 && pi->sub_type == BGP_ROUTE_STATIC)
5646 || (pi->type != ZEBRA_ROUTE_BGP
5647 && pi->sub_type
d62a17ae 5648 == BGP_ROUTE_REDISTRIBUTE))) {
40381db7 5649 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 5650 safi);
40381db7
DS
5651 bgp_unlink_nexthop(pi);
5652 bgp_path_info_delete(rn, pi);
d62a17ae 5653 bgp_process(bgp, rn, afi, safi);
5654 }
5655 }
5656 }
ad4cbda1 5657}
5658
5659/*
5660 * Purge all networks and redistributed routes from routing table.
5661 * Invoked upon the instance going down.
5662 */
d62a17ae 5663void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5664{
d62a17ae 5665 afi_t afi;
5666 safi_t safi;
ad4cbda1 5667
05c7a1cc
QY
5668 FOREACH_AFI_SAFI (afi, safi)
5669 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5670}
5671
137446f9
LB
5672/*
5673 * gpz 110624
5674 * Currently this is used to set static routes for VPN and ENCAP.
5675 * I think it can probably be factored with bgp_static_set.
5676 */
d62a17ae 5677int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5678 const char *ip_str, const char *rd_str,
5679 const char *label_str, const char *rmap_str,
5680 int evpn_type, const char *esi, const char *gwip,
5681 const char *ethtag, const char *routermac)
5682{
5683 VTY_DECLVAR_CONTEXT(bgp, bgp);
5684 int ret;
5685 struct prefix p;
5686 struct prefix_rd prd;
5687 struct bgp_node *prn;
5688 struct bgp_node *rn;
5689 struct bgp_table *table;
5690 struct bgp_static *bgp_static;
5691 mpls_label_t label = MPLS_INVALID_LABEL;
5692 struct prefix gw_ip;
5693
5694 /* validate ip prefix */
5695 ret = str2prefix(ip_str, &p);
5696 if (!ret) {
5697 vty_out(vty, "%% Malformed prefix\n");
5698 return CMD_WARNING_CONFIG_FAILED;
5699 }
5700 apply_mask(&p);
5701 if ((afi == AFI_L2VPN)
5702 && (bgp_build_evpn_prefix(evpn_type,
5703 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5704 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5705 return CMD_WARNING_CONFIG_FAILED;
5706 }
718e3744 5707
d62a17ae 5708 ret = str2prefix_rd(rd_str, &prd);
5709 if (!ret) {
5710 vty_out(vty, "%% Malformed rd\n");
5711 return CMD_WARNING_CONFIG_FAILED;
5712 }
718e3744 5713
d62a17ae 5714 if (label_str) {
5715 unsigned long label_val;
5716 label_val = strtoul(label_str, NULL, 10);
5717 encode_label(label_val, &label);
5718 }
9bedbb1e 5719
d62a17ae 5720 if (safi == SAFI_EVPN) {
5721 if (esi && str2esi(esi, NULL) == 0) {
5722 vty_out(vty, "%% Malformed ESI\n");
5723 return CMD_WARNING_CONFIG_FAILED;
5724 }
5725 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5726 vty_out(vty, "%% Malformed Router MAC\n");
5727 return CMD_WARNING_CONFIG_FAILED;
5728 }
5729 if (gwip) {
5730 memset(&gw_ip, 0, sizeof(struct prefix));
5731 ret = str2prefix(gwip, &gw_ip);
5732 if (!ret) {
5733 vty_out(vty, "%% Malformed GatewayIp\n");
5734 return CMD_WARNING_CONFIG_FAILED;
5735 }
5736 if ((gw_ip.family == AF_INET
3714a385 5737 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5738 (struct prefix_evpn *)&p))
5739 || (gw_ip.family == AF_INET6
3714a385 5740 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5741 (struct prefix_evpn *)&p))) {
5742 vty_out(vty,
5743 "%% GatewayIp family differs with IP prefix\n");
5744 return CMD_WARNING_CONFIG_FAILED;
5745 }
5746 }
5747 }
5748 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5749 if (!bgp_node_has_bgp_path_info_data(prn))
5750 bgp_node_set_bgp_table_info(prn,
5751 bgp_table_init(bgp, afi, safi));
67009e22 5752 table = bgp_node_get_bgp_table_info(prn);
d62a17ae 5753
5754 rn = bgp_node_get(table, &p);
5755
67009e22 5756 if (bgp_node_has_bgp_path_info_data(rn)) {
d62a17ae 5757 vty_out(vty, "%% Same network configuration exists\n");
5758 bgp_unlock_node(rn);
5759 } else {
5760 /* New configuration. */
5761 bgp_static = bgp_static_new();
5762 bgp_static->backdoor = 0;
5763 bgp_static->valid = 0;
5764 bgp_static->igpmetric = 0;
975a328e 5765 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5766 bgp_static->label = label;
5767 bgp_static->prd = prd;
5768
5769 if (rmap_str) {
0a22ddfb 5770 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5771 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5772 bgp_static->rmap.name =
5773 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5774 bgp_static->rmap.map =
5775 route_map_lookup_by_name(rmap_str);
b4897fa5 5776 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5777 }
718e3744 5778
d62a17ae 5779 if (safi == SAFI_EVPN) {
5780 if (esi) {
5781 bgp_static->eth_s_id =
5782 XCALLOC(MTYPE_ATTR,
5783 sizeof(struct eth_segment_id));
5784 str2esi(esi, bgp_static->eth_s_id);
5785 }
5786 if (routermac) {
5787 bgp_static->router_mac =
28328ea9 5788 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5789 (void)prefix_str2mac(routermac,
5790 bgp_static->router_mac);
d62a17ae 5791 }
5792 if (gwip)
5793 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5794 }
5a8ba9fc 5795 bgp_node_set_bgp_static_info(rn, bgp_static);
718e3744 5796
d62a17ae 5797 bgp_static->valid = 1;
5798 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5799 }
718e3744 5800
d62a17ae 5801 return CMD_SUCCESS;
718e3744 5802}
5803
5804/* Configure static BGP network. */
d62a17ae 5805int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5806 const char *ip_str, const char *rd_str,
5807 const char *label_str, int evpn_type, const char *esi,
5808 const char *gwip, const char *ethtag)
5809{
5810 VTY_DECLVAR_CONTEXT(bgp, bgp);
5811 int ret;
5812 struct prefix p;
5813 struct prefix_rd prd;
5814 struct bgp_node *prn;
5815 struct bgp_node *rn;
5816 struct bgp_table *table;
5817 struct bgp_static *bgp_static;
5818 mpls_label_t label = MPLS_INVALID_LABEL;
5819
5820 /* Convert IP prefix string to struct prefix. */
5821 ret = str2prefix(ip_str, &p);
5822 if (!ret) {
5823 vty_out(vty, "%% Malformed prefix\n");
5824 return CMD_WARNING_CONFIG_FAILED;
5825 }
5826 apply_mask(&p);
5827 if ((afi == AFI_L2VPN)
5828 && (bgp_build_evpn_prefix(evpn_type,
5829 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5830 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5831 return CMD_WARNING_CONFIG_FAILED;
5832 }
5833 ret = str2prefix_rd(rd_str, &prd);
5834 if (!ret) {
5835 vty_out(vty, "%% Malformed rd\n");
5836 return CMD_WARNING_CONFIG_FAILED;
5837 }
718e3744 5838
d62a17ae 5839 if (label_str) {
5840 unsigned long label_val;
5841 label_val = strtoul(label_str, NULL, 10);
5842 encode_label(label_val, &label);
5843 }
718e3744 5844
d62a17ae 5845 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
67009e22
DS
5846 if (!bgp_node_has_bgp_path_info_data(prn))
5847 bgp_node_set_bgp_table_info(prn,
5848 bgp_table_init(bgp, afi, safi));
d62a17ae 5849 else
5850 bgp_unlock_node(prn);
67009e22 5851 table = bgp_node_get_bgp_table_info(prn);
718e3744 5852
d62a17ae 5853 rn = bgp_node_lookup(table, &p);
6b0655a2 5854
d62a17ae 5855 if (rn) {
5856 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 5857
5a8ba9fc 5858 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 5859 bgp_static_free(bgp_static);
5a8ba9fc 5860 bgp_node_set_bgp_static_info(rn, NULL);
d62a17ae 5861 bgp_unlock_node(rn);
5862 bgp_unlock_node(rn);
5863 } else
5864 vty_out(vty, "%% Can't find the route\n");
5865
5866 return CMD_SUCCESS;
5867}
5868
5869static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
5870 const char *rmap_name)
5871{
5872 VTY_DECLVAR_CONTEXT(bgp, bgp);
5873 struct bgp_rmap *rmap;
5874
5875 rmap = &bgp->table_map[afi][safi];
5876 if (rmap_name) {
0a22ddfb 5877 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5878 route_map_counter_decrement(rmap->map);
d62a17ae 5879 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
5880 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 5881 route_map_counter_increment(rmap->map);
d62a17ae 5882 } else {
0a22ddfb 5883 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5884 route_map_counter_decrement(rmap->map);
d62a17ae 5885 rmap->map = NULL;
5886 }
73ac8160 5887
d62a17ae 5888 if (bgp_fibupd_safi(safi))
5889 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5890
d62a17ae 5891 return CMD_SUCCESS;
73ac8160
DS
5892}
5893
d62a17ae 5894static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
5895 const char *rmap_name)
73ac8160 5896{
d62a17ae 5897 VTY_DECLVAR_CONTEXT(bgp, bgp);
5898 struct bgp_rmap *rmap;
73ac8160 5899
d62a17ae 5900 rmap = &bgp->table_map[afi][safi];
0a22ddfb 5901 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 5902 route_map_counter_decrement(rmap->map);
d62a17ae 5903 rmap->map = NULL;
73ac8160 5904
d62a17ae 5905 if (bgp_fibupd_safi(safi))
5906 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5907
d62a17ae 5908 return CMD_SUCCESS;
73ac8160
DS
5909}
5910
2b791107 5911void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5912 safi_t safi)
73ac8160 5913{
d62a17ae 5914 if (bgp->table_map[afi][safi].name) {
d62a17ae 5915 vty_out(vty, " table-map %s\n",
5916 bgp->table_map[afi][safi].name);
5917 }
73ac8160
DS
5918}
5919
73ac8160
DS
5920DEFUN (bgp_table_map,
5921 bgp_table_map_cmd,
5922 "table-map WORD",
5923 "BGP table to RIB route download filter\n"
5924 "Name of the route map\n")
5925{
d62a17ae 5926 int idx_word = 1;
5927 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5928 argv[idx_word]->arg);
73ac8160
DS
5929}
5930DEFUN (no_bgp_table_map,
5931 no_bgp_table_map_cmd,
5932 "no table-map WORD",
3a2d747c 5933 NO_STR
73ac8160
DS
5934 "BGP table to RIB route download filter\n"
5935 "Name of the route map\n")
5936{
d62a17ae 5937 int idx_word = 2;
5938 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5939 argv[idx_word]->arg);
73ac8160
DS
5940}
5941
e2a86ad9
DS
5942DEFPY(bgp_network,
5943 bgp_network_cmd,
5944 "[no] network \
5945 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5946 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5947 backdoor$backdoor}]",
5948 NO_STR
5949 "Specify a network to announce via BGP\n"
5950 "IPv4 prefix\n"
5951 "Network number\n"
5952 "Network mask\n"
5953 "Network mask\n"
5954 "Route-map to modify the attributes\n"
5955 "Name of the route map\n"
5956 "Label index to associate with the prefix\n"
5957 "Label index value\n"
5958 "Specify a BGP backdoor route\n")
5959{
5960 char addr_prefix_str[BUFSIZ];
5961
5962 if (address_str) {
5963 int ret;
718e3744 5964
e2a86ad9
DS
5965 ret = netmask_str2prefix_str(address_str, netmask_str,
5966 addr_prefix_str);
5967 if (!ret) {
5968 vty_out(vty, "%% Inconsistent address and mask\n");
5969 return CMD_WARNING_CONFIG_FAILED;
5970 }
d62a17ae 5971 }
718e3744 5972
a4d82a8a
PZ
5973 return bgp_static_set(
5974 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
5975 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
5976 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 5977}
5978
e2a86ad9
DS
5979DEFPY(ipv6_bgp_network,
5980 ipv6_bgp_network_cmd,
5981 "[no] network X:X::X:X/M$prefix \
5982 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5983 NO_STR
5984 "Specify a network to announce via BGP\n"
5985 "IPv6 prefix\n"
5986 "Route-map to modify the attributes\n"
5987 "Name of the route map\n"
5988 "Label index to associate with the prefix\n"
5989 "Label index value\n")
718e3744 5990{
a4d82a8a
PZ
5991 return bgp_static_set(
5992 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
5993 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5994}
5995
d62a17ae 5996static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5997{
d62a17ae 5998 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5999}
6000
d62a17ae 6001static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6002{
20894f50
DA
6003 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6004 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6005 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6006}
718e3744 6007
40381db7 6008static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
29f7d023 6009 struct aspath *aspath,
3da2cc32 6010 struct community *comm,
dd18c5a9
DS
6011 struct ecommunity *ecomm,
6012 struct lcommunity *lcomm)
eaaf8adb
DS
6013{
6014 static struct aspath *ae = NULL;
6015
6016 if (!ae)
6017 ae = aspath_empty();
6018
40381db7 6019 if (!pi)
eaaf8adb
DS
6020 return 0;
6021
40381db7 6022 if (origin != pi->attr->origin)
eaaf8adb
DS
6023 return 0;
6024
40381db7 6025 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
29f7d023
DS
6026 return 0;
6027
40381db7 6028 if (!community_cmp(pi->attr->community, comm))
eaaf8adb
DS
6029 return 0;
6030
3da2cc32 6031 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
eaaf8adb
DS
6032 return 0;
6033
dd18c5a9
DS
6034 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
6035 return 0;
6036
40381db7 6037 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
7ce8a8e0
DS
6038 return 0;
6039
eaaf8adb
DS
6040 return 1;
6041}
6042
c701010e
DS
6043static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
6044 struct prefix *p, uint8_t origin,
6045 struct aspath *aspath,
6046 struct community *community,
3da2cc32 6047 struct ecommunity *ecommunity,
dd18c5a9 6048 struct lcommunity *lcommunity,
c701010e
DS
6049 uint8_t atomic_aggregate,
6050 struct bgp_aggregate *aggregate)
6051{
6052 struct bgp_node *rn;
6053 struct bgp_table *table;
6f94b685 6054 struct bgp_path_info *pi, *orig, *new;
20894f50 6055 struct attr *attr;
c701010e
DS
6056
6057 table = bgp->rib[afi][safi];
6058
6059 rn = bgp_node_get(table, p);
eaaf8adb 6060
6f94b685 6061 for (orig = pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
6062 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6063 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6064 break;
6065
c701010e 6066 if (aggregate->count > 0) {
eaaf8adb
DS
6067 /*
6068 * If the aggregate information has not changed
6069 * no need to re-install it again.
6070 */
6f94b685 6071 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6072 ecommunity, lcommunity)) {
eaaf8adb
DS
6073 bgp_unlock_node(rn);
6074
6075 if (aspath)
6076 aspath_free(aspath);
6077 if (community)
3c1f53de 6078 community_free(&community);
3da2cc32
DS
6079 if (ecommunity)
6080 ecommunity_free(&ecommunity);
dd18c5a9
DS
6081 if (lcommunity)
6082 lcommunity_free(&lcommunity);
eaaf8adb
DS
6083
6084 return;
6085 }
6086
6087 /*
6088 * Mark the old as unusable
6089 */
40381db7
DS
6090 if (pi)
6091 bgp_path_info_delete(rn, pi);
eaaf8adb 6092
20894f50
DA
6093 attr = bgp_attr_aggregate_intern(
6094 bgp, origin, aspath, community, ecommunity, lcommunity,
6095 aggregate, atomic_aggregate, p);
6096
6097 if (!attr) {
6098 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6099 return;
6100 }
6101
3da2cc32 6102 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
20894f50
DA
6103 bgp->peer_self, attr, rn);
6104
1defdda8 6105 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6106
18ee8310 6107 bgp_path_info_add(rn, new);
c701010e
DS
6108 bgp_process(bgp, rn, afi, safi);
6109 } else {
6f94b685 6110 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6111 if (pi->peer == bgp->peer_self
6112 && pi->type == ZEBRA_ROUTE_BGP
6113 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6114 break;
6115
6116 /* Withdraw static BGP route from routing table. */
40381db7
DS
6117 if (pi) {
6118 bgp_path_info_delete(rn, pi);
c701010e
DS
6119 bgp_process(bgp, rn, afi, safi);
6120 }
6121 }
6122
6123 bgp_unlock_node(rn);
6124}
6125
b5d58c32 6126/* Update an aggregate as routes are added/removed from the BGP table */
20894f50 6127void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
fc968841 6128 afi_t afi, safi_t safi,
d62a17ae 6129 struct bgp_aggregate *aggregate)
6130{
6131 struct bgp_table *table;
6132 struct bgp_node *top;
6133 struct bgp_node *rn;
d7c0a89a 6134 uint8_t origin;
d62a17ae 6135 struct aspath *aspath = NULL;
d62a17ae 6136 struct community *community = NULL;
3da2cc32 6137 struct ecommunity *ecommunity = NULL;
dd18c5a9 6138 struct lcommunity *lcommunity = NULL;
40381db7 6139 struct bgp_path_info *pi;
d62a17ae 6140 unsigned long match = 0;
d7c0a89a 6141 uint8_t atomic_aggregate = 0;
d62a17ae 6142
9f822fa2
S
6143 /* If the bgp instance is being deleted or self peer is deleted
6144 * then do not create aggregate route
6145 */
892fedb6
DA
6146 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6147 || (bgp->peer_self == NULL))
9f822fa2
S
6148 return;
6149
d62a17ae 6150 /* ORIGIN attribute: If at least one route among routes that are
6151 aggregated has ORIGIN with the value INCOMPLETE, then the
6152 aggregated route must have the ORIGIN attribute with the value
6153 INCOMPLETE. Otherwise, if at least one route among routes that
6154 are aggregated has ORIGIN with the value EGP, then the aggregated
6155 route must have the origin attribute with the value EGP. In all
6156 other case the value of the ORIGIN attribute of the aggregated
6157 route is INTERNAL. */
6158 origin = BGP_ORIGIN_IGP;
718e3744 6159
d62a17ae 6160 table = bgp->rib[afi][safi];
718e3744 6161
d62a17ae 6162 top = bgp_node_get(table, p);
6163 for (rn = bgp_node_get(table, p); rn;
c2ff8b3e
DS
6164 rn = bgp_route_next_until(rn, top)) {
6165 if (rn->p.prefixlen <= p->prefixlen)
6166 continue;
d62a17ae 6167
c2ff8b3e 6168 match = 0;
d62a17ae 6169
6f94b685 6170 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6171 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6172 continue;
718e3744 6173
40381db7 6174 if (pi->attr->flag
c2ff8b3e
DS
6175 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6176 atomic_aggregate = 1;
d62a17ae 6177
40381db7 6178 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6179 continue;
d62a17ae 6180
f273fef1
DS
6181 /*
6182 * summary-only aggregate route suppress
6183 * aggregated route announcements.
6184 */
c2ff8b3e 6185 if (aggregate->summary_only) {
40381db7
DS
6186 (bgp_path_info_extra_get(pi))->suppress++;
6187 bgp_path_info_set_flag(rn, pi,
18ee8310 6188 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6189 match++;
d62a17ae 6190 }
c2ff8b3e
DS
6191
6192 aggregate->count++;
6193
f273fef1
DS
6194 /*
6195 * If at least one route among routes that are
6196 * aggregated has ORIGIN with the value INCOMPLETE,
6197 * then the aggregated route MUST have the ORIGIN
6198 * attribute with the value INCOMPLETE. Otherwise, if
6199 * at least one route among routes that are aggregated
6200 * has ORIGIN with the value EGP, then the aggregated
6201 * route MUST have the ORIGIN attribute with the value
6202 * EGP.
6203 */
fc968841
NT
6204 switch (pi->attr->origin) {
6205 case BGP_ORIGIN_INCOMPLETE:
6206 aggregate->incomplete_origin_count++;
6207 break;
6208 case BGP_ORIGIN_EGP:
6209 aggregate->egp_origin_count++;
6210 break;
6211 default:
6212 /*Do nothing.
6213 */
6214 break;
6215 }
c2ff8b3e
DS
6216
6217 if (!aggregate->as_set)
6218 continue;
6219
f273fef1
DS
6220 /*
6221 * as-set aggregate route generate origin, as path,
6222 * and community aggregation.
6223 */
fc968841
NT
6224 /* Compute aggregate route's as-path.
6225 */
ef51a7d8 6226 bgp_compute_aggregate_aspath_hash(aggregate,
6227 pi->attr->aspath);
c2ff8b3e 6228
fc968841
NT
6229 /* Compute aggregate route's community.
6230 */
6231 if (pi->attr->community)
21fec674 6232 bgp_compute_aggregate_community_hash(
fc968841
NT
6233 aggregate,
6234 pi->attr->community);
dd18c5a9 6235
fc968841
NT
6236 /* Compute aggregate route's extended community.
6237 */
6238 if (pi->attr->ecommunity)
4edd83f9 6239 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6240 aggregate,
6241 pi->attr->ecommunity);
6242
6243 /* Compute aggregate route's large community.
6244 */
6245 if (pi->attr->lcommunity)
f1eb1f05 6246 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6247 aggregate,
6248 pi->attr->lcommunity);
d62a17ae 6249 }
c2ff8b3e
DS
6250 if (match)
6251 bgp_process(bgp, rn, afi, safi);
6252 }
21fec674 6253 if (aggregate->as_set) {
ef51a7d8 6254 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6255 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6256 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6257 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6258 }
6259
f1eb1f05 6260
d62a17ae 6261 bgp_unlock_node(top);
718e3744 6262
718e3744 6263
fc968841
NT
6264 if (aggregate->incomplete_origin_count > 0)
6265 origin = BGP_ORIGIN_INCOMPLETE;
6266 else if (aggregate->egp_origin_count > 0)
6267 origin = BGP_ORIGIN_EGP;
d62a17ae 6268
229757f1
DA
6269 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6270 origin = aggregate->origin;
6271
fc968841
NT
6272 if (aggregate->as_set) {
6273 if (aggregate->aspath)
6274 /* Retrieve aggregate route's as-path.
6275 */
6276 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6277
fc968841
NT
6278 if (aggregate->community)
6279 /* Retrieve aggregate route's community.
6280 */
6281 community = community_dup(aggregate->community);
3da2cc32 6282
fc968841
NT
6283 if (aggregate->ecommunity)
6284 /* Retrieve aggregate route's ecommunity.
6285 */
6286 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6287
fc968841
NT
6288 if (aggregate->lcommunity)
6289 /* Retrieve aggregate route's lcommunity.
6290 */
6291 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6292 }
718e3744 6293
c701010e 6294 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6295 ecommunity, lcommunity, atomic_aggregate,
6296 aggregate);
718e3744 6297}
6298
20894f50 6299void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
3b7db173
DS
6300 safi_t safi, struct bgp_aggregate *aggregate)
6301{
6302 struct bgp_table *table;
6303 struct bgp_node *top;
6304 struct bgp_node *rn;
40381db7 6305 struct bgp_path_info *pi;
3b7db173
DS
6306 unsigned long match;
6307
6308 table = bgp->rib[afi][safi];
6309
6310 /* If routes exists below this node, generate aggregate routes. */
6311 top = bgp_node_get(table, p);
6312 for (rn = bgp_node_get(table, p); rn;
6313 rn = bgp_route_next_until(rn, top)) {
6314 if (rn->p.prefixlen <= p->prefixlen)
6315 continue;
6316 match = 0;
6317
6f94b685 6318 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
40381db7 6319 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6320 continue;
6321
40381db7 6322 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6323 continue;
6324
40381db7
DS
6325 if (aggregate->summary_only && pi->extra) {
6326 pi->extra->suppress--;
3b7db173 6327
40381db7 6328 if (pi->extra->suppress == 0) {
18ee8310 6329 bgp_path_info_set_flag(
40381db7 6330 rn, pi, BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6331 match++;
6332 }
6333 }
6334 aggregate->count--;
fc968841
NT
6335
6336 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6337 aggregate->incomplete_origin_count--;
6338 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6339 aggregate->egp_origin_count--;
6340
6341 if (aggregate->as_set) {
6342 /* Remove as-path from aggregate.
6343 */
ef51a7d8 6344 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6345 aggregate,
6346 pi->attr->aspath);
6347
6348 if (pi->attr->community)
6349 /* Remove community from aggregate.
6350 */
21fec674 6351 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6352 aggregate,
6353 pi->attr->community);
6354
6355 if (pi->attr->ecommunity)
6356 /* Remove ecommunity from aggregate.
6357 */
4edd83f9 6358 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6359 aggregate,
6360 pi->attr->ecommunity);
6361
6362 if (pi->attr->lcommunity)
6363 /* Remove lcommunity from aggregate.
6364 */
f1eb1f05 6365 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6366 aggregate,
6367 pi->attr->lcommunity);
6368 }
6369
3b7db173
DS
6370 }
6371
6372 /* If this node was suppressed, process the change. */
6373 if (match)
6374 bgp_process(bgp, rn, afi, safi);
6375 }
f1eb1f05 6376 if (aggregate->as_set) {
ef51a7d8 6377 aspath_free(aggregate->aspath);
6378 aggregate->aspath = NULL;
21fec674 6379 if (aggregate->community)
6380 community_free(&aggregate->community);
4edd83f9 6381 if (aggregate->ecommunity)
6382 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6383 if (aggregate->lcommunity)
6384 lcommunity_free(&aggregate->lcommunity);
6385 }
6386
3b7db173
DS
6387 bgp_unlock_node(top);
6388}
718e3744 6389
fc968841
NT
6390static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
6391 struct bgp_path_info *pinew, afi_t afi,
6392 safi_t safi,
6393 struct bgp_aggregate *aggregate)
6394{
6395 uint8_t origin;
6396 struct aspath *aspath = NULL;
6397 uint8_t atomic_aggregate = 0;
6398 struct community *community = NULL;
6399 struct ecommunity *ecommunity = NULL;
6400 struct lcommunity *lcommunity = NULL;
6401
6402 /* ORIGIN attribute: If at least one route among routes that are
6403 * aggregated has ORIGIN with the value INCOMPLETE, then the
6404 * aggregated route must have the ORIGIN attribute with the value
6405 * INCOMPLETE. Otherwise, if at least one route among routes that
6406 * are aggregated has ORIGIN with the value EGP, then the aggregated
6407 * route must have the origin attribute with the value EGP. In all
6408 * other case the value of the ORIGIN attribute of the aggregated
6409 * route is INTERNAL.
6410 */
6411 origin = BGP_ORIGIN_IGP;
6412
6413 aggregate->count++;
6414
6415 if (aggregate->summary_only)
6416 (bgp_path_info_extra_get(pinew))->suppress++;
6417
6418 switch (pinew->attr->origin) {
6419 case BGP_ORIGIN_INCOMPLETE:
6420 aggregate->incomplete_origin_count++;
6421 break;
6422 case BGP_ORIGIN_EGP:
6423 aggregate->egp_origin_count++;
6424 break;
6425 default:
6426 /* Do nothing.
6427 */
6428 break;
6429 }
6430
6431 if (aggregate->incomplete_origin_count > 0)
6432 origin = BGP_ORIGIN_INCOMPLETE;
6433 else if (aggregate->egp_origin_count > 0)
6434 origin = BGP_ORIGIN_EGP;
6435
229757f1
DA
6436 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6437 origin = aggregate->origin;
6438
fc968841
NT
6439 if (aggregate->as_set) {
6440 /* Compute aggregate route's as-path.
6441 */
6442 bgp_compute_aggregate_aspath(aggregate,
6443 pinew->attr->aspath);
6444
6445 /* Compute aggregate route's community.
6446 */
6447 if (pinew->attr->community)
6448 bgp_compute_aggregate_community(
6449 aggregate,
6450 pinew->attr->community);
6451
6452 /* Compute aggregate route's extended community.
6453 */
6454 if (pinew->attr->ecommunity)
6455 bgp_compute_aggregate_ecommunity(
6456 aggregate,
6457 pinew->attr->ecommunity);
6458
6459 /* Compute aggregate route's large community.
6460 */
6461 if (pinew->attr->lcommunity)
6462 bgp_compute_aggregate_lcommunity(
6463 aggregate,
6464 pinew->attr->lcommunity);
6465
6466 /* Retrieve aggregate route's as-path.
6467 */
6468 if (aggregate->aspath)
6469 aspath = aspath_dup(aggregate->aspath);
6470
6471 /* Retrieve aggregate route's community.
6472 */
6473 if (aggregate->community)
6474 community = community_dup(aggregate->community);
6475
6476 /* Retrieve aggregate route's ecommunity.
6477 */
6478 if (aggregate->ecommunity)
6479 ecommunity = ecommunity_dup(aggregate->ecommunity);
6480
6481 /* Retrieve aggregate route's lcommunity.
6482 */
6483 if (aggregate->lcommunity)
6484 lcommunity = lcommunity_dup(aggregate->lcommunity);
6485 }
6486
6487 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6488 aspath, community, ecommunity,
6489 lcommunity, atomic_aggregate, aggregate);
6490}
6491
6492static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6493 safi_t safi,
6494 struct bgp_path_info *pi,
6495 struct bgp_aggregate *aggregate,
6496 struct prefix *aggr_p)
6497{
6498 uint8_t origin;
6499 struct aspath *aspath = NULL;
6500 uint8_t atomic_aggregate = 0;
6501 struct community *community = NULL;
6502 struct ecommunity *ecommunity = NULL;
6503 struct lcommunity *lcommunity = NULL;
6504 unsigned long match = 0;
6505
6506 if (BGP_PATH_HOLDDOWN(pi))
6507 return;
6508
6509 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6510 return;
6511
6512 if (aggregate->summary_only
6513 && pi->extra
6514 && pi->extra->suppress > 0) {
6515 pi->extra->suppress--;
6516
6517 if (pi->extra->suppress == 0) {
6518 bgp_path_info_set_flag(pi->net, pi,
6519 BGP_PATH_ATTR_CHANGED);
6520 match++;
6521 }
6522 }
6523
6524 if (aggregate->count > 0)
6525 aggregate->count--;
6526
6527 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6528 aggregate->incomplete_origin_count--;
6529 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6530 aggregate->egp_origin_count--;
6531
6532 if (aggregate->as_set) {
6533 /* Remove as-path from aggregate.
6534 */
6535 bgp_remove_aspath_from_aggregate(aggregate,
6536 pi->attr->aspath);
6537
6538 if (pi->attr->community)
6539 /* Remove community from aggregate.
6540 */
6541 bgp_remove_community_from_aggregate(
6542 aggregate,
6543 pi->attr->community);
6544
6545 if (pi->attr->ecommunity)
6546 /* Remove ecommunity from aggregate.
6547 */
6548 bgp_remove_ecommunity_from_aggregate(
6549 aggregate,
6550 pi->attr->ecommunity);
6551
6552 if (pi->attr->lcommunity)
6553 /* Remove lcommunity from aggregate.
6554 */
6555 bgp_remove_lcommunity_from_aggregate(
6556 aggregate,
6557 pi->attr->lcommunity);
6558 }
6559
6560 /* If this node was suppressed, process the change. */
6561 if (match)
6562 bgp_process(bgp, pi->net, afi, safi);
6563
6564 origin = BGP_ORIGIN_IGP;
6565 if (aggregate->incomplete_origin_count > 0)
6566 origin = BGP_ORIGIN_INCOMPLETE;
6567 else if (aggregate->egp_origin_count > 0)
6568 origin = BGP_ORIGIN_EGP;
6569
229757f1
DA
6570 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6571 origin = aggregate->origin;
6572
fc968841
NT
6573 if (aggregate->as_set) {
6574 /* Retrieve aggregate route's as-path.
6575 */
6576 if (aggregate->aspath)
6577 aspath = aspath_dup(aggregate->aspath);
6578
6579 /* Retrieve aggregate route's community.
6580 */
6581 if (aggregate->community)
6582 community = community_dup(aggregate->community);
6583
6584 /* Retrieve aggregate route's ecommunity.
6585 */
6586 if (aggregate->ecommunity)
6587 ecommunity = ecommunity_dup(aggregate->ecommunity);
6588
6589 /* Retrieve aggregate route's lcommunity.
6590 */
6591 if (aggregate->lcommunity)
6592 lcommunity = lcommunity_dup(aggregate->lcommunity);
6593 }
6594
6595 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6596 aspath, community, ecommunity,
6597 lcommunity, atomic_aggregate, aggregate);
6598}
6599
d62a17ae 6600void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
40381db7 6601 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 6602{
d62a17ae 6603 struct bgp_node *child;
6604 struct bgp_node *rn;
6605 struct bgp_aggregate *aggregate;
6606 struct bgp_table *table;
718e3744 6607
d62a17ae 6608 table = bgp->aggregate[afi][safi];
f018db83 6609
d62a17ae 6610 /* No aggregates configured. */
6611 if (bgp_table_top_nolock(table) == NULL)
6612 return;
f018db83 6613
d62a17ae 6614 if (p->prefixlen == 0)
6615 return;
718e3744 6616
40381db7 6617 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 6618 return;
718e3744 6619
d62a17ae 6620 child = bgp_node_get(table, p);
718e3744 6621
d62a17ae 6622 /* Aggregate address configuration check. */
b1e62edd 6623 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6624 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6625 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6626 bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
6627 safi, aggregate);
d62a17ae 6628 }
b1e62edd 6629 }
d62a17ae 6630 bgp_unlock_node(child);
718e3744 6631}
6632
d62a17ae 6633void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
4b7e6066 6634 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 6635{
d62a17ae 6636 struct bgp_node *child;
6637 struct bgp_node *rn;
6638 struct bgp_aggregate *aggregate;
6639 struct bgp_table *table;
718e3744 6640
d62a17ae 6641 table = bgp->aggregate[afi][safi];
718e3744 6642
d62a17ae 6643 /* No aggregates configured. */
6644 if (bgp_table_top_nolock(table) == NULL)
6645 return;
718e3744 6646
d62a17ae 6647 if (p->prefixlen == 0)
6648 return;
718e3744 6649
d62a17ae 6650 child = bgp_node_get(table, p);
718e3744 6651
d62a17ae 6652 /* Aggregate address configuration check. */
b1e62edd 6653 for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
b613a918 6654 aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 6655 if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
fc968841
NT
6656 bgp_remove_route_from_aggregate(bgp, afi, safi,
6657 del, aggregate, &rn->p);
d62a17ae 6658 }
b1e62edd 6659 }
d62a17ae 6660 bgp_unlock_node(child);
6661}
718e3744 6662
718e3744 6663/* Aggregate route attribute. */
6664#define AGGREGATE_SUMMARY_ONLY 1
6665#define AGGREGATE_AS_SET 1
fb29348a 6666#define AGGREGATE_AS_UNSET 0
718e3744 6667
229757f1
DA
6668static const char *bgp_origin2str(uint8_t origin)
6669{
6670 switch (origin) {
6671 case BGP_ORIGIN_IGP:
6672 return "igp";
6673 case BGP_ORIGIN_EGP:
6674 return "egp";
6675 case BGP_ORIGIN_INCOMPLETE:
6676 return "incomplete";
6677 }
6678 return "n/a";
6679}
6680
d62a17ae 6681static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
6682 afi_t afi, safi_t safi)
718e3744 6683{
d62a17ae 6684 VTY_DECLVAR_CONTEXT(bgp, bgp);
6685 int ret;
6686 struct prefix p;
6687 struct bgp_node *rn;
6688 struct bgp_aggregate *aggregate;
718e3744 6689
d62a17ae 6690 /* Convert string to prefix structure. */
6691 ret = str2prefix(prefix_str, &p);
6692 if (!ret) {
6693 vty_out(vty, "Malformed prefix\n");
6694 return CMD_WARNING_CONFIG_FAILED;
6695 }
6696 apply_mask(&p);
6697
6698 /* Old configuration check. */
6699 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
6700 if (!rn) {
6701 vty_out(vty,
6702 "%% There is no aggregate-address configuration.\n");
6703 return CMD_WARNING_CONFIG_FAILED;
6704 }
f6269b4f 6705
b613a918 6706 aggregate = bgp_node_get_bgp_aggregate_info(rn);
09990cdd 6707 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
6708 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
6709 NULL, NULL, 0, aggregate);
d62a17ae 6710
6711 /* Unlock aggregate address configuration. */
b613a918 6712 bgp_node_set_bgp_aggregate_info(rn, NULL);
fc968841
NT
6713
6714 if (aggregate->community)
6715 community_free(&aggregate->community);
6716
6717 if (aggregate->community_hash) {
6718 /* Delete all communities in the hash.
6719 */
6720 hash_clean(aggregate->community_hash,
6721 bgp_aggr_community_remove);
6722 /* Free up the community_hash.
6723 */
6724 hash_free(aggregate->community_hash);
6725 }
6726
6727 if (aggregate->ecommunity)
6728 ecommunity_free(&aggregate->ecommunity);
6729
6730 if (aggregate->ecommunity_hash) {
6731 /* Delete all ecommunities in the hash.
6732 */
6733 hash_clean(aggregate->ecommunity_hash,
6734 bgp_aggr_ecommunity_remove);
6735 /* Free up the ecommunity_hash.
6736 */
6737 hash_free(aggregate->ecommunity_hash);
6738 }
6739
6740 if (aggregate->lcommunity)
6741 lcommunity_free(&aggregate->lcommunity);
6742
6743 if (aggregate->lcommunity_hash) {
6744 /* Delete all lcommunities in the hash.
6745 */
6746 hash_clean(aggregate->lcommunity_hash,
6747 bgp_aggr_lcommunity_remove);
6748 /* Free up the lcommunity_hash.
6749 */
6750 hash_free(aggregate->lcommunity_hash);
6751 }
6752
6753 if (aggregate->aspath)
6754 aspath_free(aggregate->aspath);
6755
6756 if (aggregate->aspath_hash) {
6757 /* Delete all as-paths in the hash.
6758 */
6759 hash_clean(aggregate->aspath_hash,
6760 bgp_aggr_aspath_remove);
6761 /* Free up the aspath_hash.
6762 */
6763 hash_free(aggregate->aspath_hash);
6764 }
6765
d62a17ae 6766 bgp_aggregate_free(aggregate);
6767 bgp_unlock_node(rn);
6768 bgp_unlock_node(rn);
6769
6770 return CMD_SUCCESS;
6771}
6772
6773static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
6774 safi_t safi, const char *rmap,
6775 uint8_t summary_only, uint8_t as_set,
6776 uint8_t origin)
d62a17ae 6777{
6778 VTY_DECLVAR_CONTEXT(bgp, bgp);
6779 int ret;
6780 struct prefix p;
6781 struct bgp_node *rn;
6782 struct bgp_aggregate *aggregate;
fb29348a 6783 uint8_t as_set_new = as_set;
d62a17ae 6784
6785 /* Convert string to prefix structure. */
6786 ret = str2prefix(prefix_str, &p);
6787 if (!ret) {
6788 vty_out(vty, "Malformed prefix\n");
6789 return CMD_WARNING_CONFIG_FAILED;
6790 }
6791 apply_mask(&p);
6792
3624ac81
DS
6793 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
6794 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
6795 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6796 prefix_str);
6797 return CMD_WARNING_CONFIG_FAILED;
6798 }
6799
d62a17ae 6800 /* Old configuration check. */
6801 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
20894f50 6802 aggregate = bgp_node_get_bgp_aggregate_info(rn);
d62a17ae 6803
20894f50 6804 if (aggregate) {
d62a17ae 6805 vty_out(vty, "There is already same aggregate network.\n");
6806 /* try to remove the old entry */
6807 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
6808 if (ret) {
6809 vty_out(vty, "Error deleting aggregate.\n");
6810 bgp_unlock_node(rn);
6811 return CMD_WARNING_CONFIG_FAILED;
6812 }
6813 }
718e3744 6814
d62a17ae 6815 /* Make aggregate address structure. */
6816 aggregate = bgp_aggregate_new();
6817 aggregate->summary_only = summary_only;
fb29348a
DA
6818
6819 /* Network operators MUST NOT locally generate any new
6820 * announcements containing AS_SET or AS_CONFED_SET. If they have
6821 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6822 * SHOULD withdraw those routes and re-announce routes for the
6823 * aggregate or component prefixes (i.e., the more-specific routes
6824 * subsumed by the previously aggregated route) without AS_SET
6825 * or AS_CONFED_SET in the updates.
6826 */
6827 if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
6828 if (as_set == AGGREGATE_AS_SET) {
6829 as_set_new = AGGREGATE_AS_UNSET;
6830 zlog_warn(
6831 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6832 __func__);
6833 vty_out(vty,
6834 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6835 }
6836 }
6837
6838 aggregate->as_set = as_set_new;
d62a17ae 6839 aggregate->safi = safi;
229757f1
DA
6840 /* Override ORIGIN attribute if defined.
6841 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6842 * to IGP which is not what rfc4271 says.
6843 * This enables the same behavior, optionally.
6844 */
6845 aggregate->origin = origin;
20894f50
DA
6846
6847 if (rmap) {
6848 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6849 route_map_counter_decrement(aggregate->rmap.map);
6850 aggregate->rmap.name =
6851 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6852 aggregate->rmap.map = route_map_lookup_by_name(rmap);
6853 route_map_counter_increment(aggregate->rmap.map);
6854 }
b613a918 6855 bgp_node_set_bgp_aggregate_info(rn, aggregate);
718e3744 6856
d62a17ae 6857 /* Aggregate address insert into BGP routing table. */
fc968841 6858 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 6859
d62a17ae 6860 return CMD_SUCCESS;
718e3744 6861}
6862
6863DEFUN (aggregate_address,
6864 aggregate_address_cmd,
229757f1 6865 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6866 "Configure BGP aggregate entries\n"
6867 "Aggregate prefix\n"
6868 "Generate AS set path information\n"
a636c635
DW
6869 "Filter more specific routes from updates\n"
6870 "Filter more specific routes from updates\n"
20894f50
DA
6871 "Generate AS set path information\n"
6872 "Apply route map to aggregate network\n"
229757f1
DA
6873 "Name of route map\n"
6874 "BGP origin code\n"
6875 "Remote EGP\n"
6876 "Local IGP\n"
6877 "Unknown heritage\n")
718e3744 6878{
d62a17ae 6879 int idx = 0;
6880 argv_find(argv, argc, "A.B.C.D/M", &idx);
6881 char *prefix = argv[idx]->arg;
20894f50 6882 char *rmap = NULL;
229757f1 6883 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6884 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6885 : AGGREGATE_AS_UNSET;
d62a17ae 6886 idx = 0;
6887 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6888 ? AGGREGATE_SUMMARY_ONLY
6889 : 0;
e3e6107d 6890
20894f50
DA
6891 idx = 0;
6892 argv_find(argv, argc, "WORD", &idx);
6893 if (idx)
6894 rmap = argv[idx]->arg;
6895
229757f1
DA
6896 idx = 0;
6897 if (argv_find(argv, argc, "origin", &idx)) {
6898 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6899 origin = BGP_ORIGIN_IGP;
6900 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6901 origin = BGP_ORIGIN_EGP;
6902 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6903 origin = BGP_ORIGIN_INCOMPLETE;
6904 }
6905
6906 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
6907 summary_only, as_set, origin);
718e3744 6908}
6909
e3e6107d
QY
6910DEFUN (aggregate_address_mask,
6911 aggregate_address_mask_cmd,
229757f1 6912 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6913 "Configure BGP aggregate entries\n"
6914 "Aggregate address\n"
6915 "Aggregate mask\n"
6916 "Generate AS set path information\n"
a636c635
DW
6917 "Filter more specific routes from updates\n"
6918 "Filter more specific routes from updates\n"
20894f50
DA
6919 "Generate AS set path information\n"
6920 "Apply route map to aggregate network\n"
229757f1
DA
6921 "Name of route map\n"
6922 "BGP origin code\n"
6923 "Remote EGP\n"
6924 "Local IGP\n"
6925 "Unknown heritage\n")
718e3744 6926{
d62a17ae 6927 int idx = 0;
6928 argv_find(argv, argc, "A.B.C.D", &idx);
6929 char *prefix = argv[idx]->arg;
6930 char *mask = argv[idx + 1]->arg;
cf40d052 6931 bool rmap_found;
20894f50 6932 char *rmap = NULL;
229757f1 6933 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
6934 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
6935 : AGGREGATE_AS_UNSET;
d62a17ae 6936 idx = 0;
6937 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6938 ? AGGREGATE_SUMMARY_ONLY
6939 : 0;
6940
cf40d052
DS
6941 rmap_found = argv_find(argv, argc, "WORD", &idx);
6942 if (rmap_found)
20894f50
DA
6943 rmap = argv[idx]->arg;
6944
d62a17ae 6945 char prefix_str[BUFSIZ];
6946 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6947
6948 if (!ret) {
6949 vty_out(vty, "%% Inconsistent address and mask\n");
6950 return CMD_WARNING_CONFIG_FAILED;
6951 }
718e3744 6952
229757f1
DA
6953 idx = 0;
6954 if (argv_find(argv, argc, "origin", &idx)) {
6955 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
6956 origin = BGP_ORIGIN_IGP;
6957 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
6958 origin = BGP_ORIGIN_EGP;
6959 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
6960 origin = BGP_ORIGIN_INCOMPLETE;
6961 }
6962
d62a17ae 6963 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
229757f1 6964 rmap, summary_only, as_set, origin);
718e3744 6965}
6966
718e3744 6967DEFUN (no_aggregate_address,
6968 no_aggregate_address_cmd,
229757f1 6969 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6970 NO_STR
6971 "Configure BGP aggregate entries\n"
a636c635
DW
6972 "Aggregate prefix\n"
6973 "Generate AS set path information\n"
e3e6107d
QY
6974 "Filter more specific routes from updates\n"
6975 "Filter more specific routes from updates\n"
b84da0db
DA
6976 "Generate AS set path information\n"
6977 "Apply route map to aggregate network\n"
229757f1
DA
6978 "Name of route map\n"
6979 "BGP origin code\n"
6980 "Remote EGP\n"
6981 "Local IGP\n"
6982 "Unknown heritage\n")
718e3744 6983{
d62a17ae 6984 int idx = 0;
6985 argv_find(argv, argc, "A.B.C.D/M", &idx);
6986 char *prefix = argv[idx]->arg;
6987 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6988}
6989
718e3744 6990DEFUN (no_aggregate_address_mask,
6991 no_aggregate_address_mask_cmd,
229757f1 6992 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 6993 NO_STR
6994 "Configure BGP aggregate entries\n"
6995 "Aggregate address\n"
a636c635
DW
6996 "Aggregate mask\n"
6997 "Generate AS set path information\n"
e3e6107d
QY
6998 "Filter more specific routes from updates\n"
6999 "Filter more specific routes from updates\n"
b84da0db
DA
7000 "Generate AS set path information\n"
7001 "Apply route map to aggregate network\n"
229757f1
DA
7002 "Name of route map\n"
7003 "BGP origin code\n"
7004 "Remote EGP\n"
7005 "Local IGP\n"
7006 "Unknown heritage\n")
718e3744 7007{
d62a17ae 7008 int idx = 0;
7009 argv_find(argv, argc, "A.B.C.D", &idx);
7010 char *prefix = argv[idx]->arg;
7011 char *mask = argv[idx + 1]->arg;
718e3744 7012
d62a17ae 7013 char prefix_str[BUFSIZ];
7014 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 7015
d62a17ae 7016 if (!ret) {
7017 vty_out(vty, "%% Inconsistent address and mask\n");
7018 return CMD_WARNING_CONFIG_FAILED;
7019 }
718e3744 7020
d62a17ae 7021 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 7022}
7023
718e3744 7024DEFUN (ipv6_aggregate_address,
7025 ipv6_aggregate_address_cmd,
229757f1 7026 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7027 "Configure BGP aggregate entries\n"
7028 "Aggregate prefix\n"
5101fece 7029 "Generate AS set path information\n"
7030 "Filter more specific routes from updates\n"
7031 "Filter more specific routes from updates\n"
20894f50
DA
7032 "Generate AS set path information\n"
7033 "Apply route map to aggregate network\n"
229757f1
DA
7034 "Name of route map\n"
7035 "BGP origin code\n"
7036 "Remote EGP\n"
7037 "Local IGP\n"
7038 "Unknown heritage\n")
718e3744 7039{
d62a17ae 7040 int idx = 0;
7041 argv_find(argv, argc, "X:X::X:X/M", &idx);
7042 char *prefix = argv[idx]->arg;
20894f50 7043 char *rmap = NULL;
273fae13 7044 bool rmap_found;
229757f1 7045 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
fb29348a
DA
7046 int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
7047 : AGGREGATE_AS_UNSET;
5101fece 7048
7049 idx = 0;
d62a17ae 7050 int sum_only = argv_find(argv, argc, "summary-only", &idx)
7051 ? AGGREGATE_SUMMARY_ONLY
7052 : 0;
20894f50 7053
273fae13
DA
7054 rmap_found = argv_find(argv, argc, "WORD", &idx);
7055 if (rmap_found)
20894f50
DA
7056 rmap = argv[idx]->arg;
7057
229757f1
DA
7058 idx = 0;
7059 if (argv_find(argv, argc, "origin", &idx)) {
7060 if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
7061 origin = BGP_ORIGIN_IGP;
7062 if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
7063 origin = BGP_ORIGIN_EGP;
7064 if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
7065 origin = BGP_ORIGIN_INCOMPLETE;
7066 }
7067
20894f50 7068 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
229757f1 7069 sum_only, as_set, origin);
718e3744 7070}
7071
7072DEFUN (no_ipv6_aggregate_address,
7073 no_ipv6_aggregate_address_cmd,
229757f1 7074 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
718e3744 7075 NO_STR
7076 "Configure BGP aggregate entries\n"
16cedbb0 7077 "Aggregate prefix\n"
5101fece 7078 "Generate AS set path information\n"
7079 "Filter more specific routes from updates\n"
7080 "Filter more specific routes from updates\n"
b84da0db
DA
7081 "Generate AS set path information\n"
7082 "Apply route map to aggregate network\n"
229757f1
DA
7083 "Name of route map\n"
7084 "BGP origin code\n"
7085 "Remote EGP\n"
7086 "Local IGP\n"
7087 "Unknown heritage\n")
718e3744 7088{
d62a17ae 7089 int idx = 0;
7090 argv_find(argv, argc, "X:X::X:X/M", &idx);
7091 char *prefix = argv[idx]->arg;
7092 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 7093}
7094
718e3744 7095/* Redistribute route treatment. */
d62a17ae 7096void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7097 const union g_addr *nexthop, ifindex_t ifindex,
7098 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7099 uint8_t type, unsigned short instance,
7100 route_tag_t tag)
d62a17ae 7101{
4b7e6066 7102 struct bgp_path_info *new;
40381db7
DS
7103 struct bgp_path_info *bpi;
7104 struct bgp_path_info rmap_path;
d62a17ae 7105 struct bgp_node *bn;
7106 struct attr attr;
7107 struct attr *new_attr;
7108 afi_t afi;
b68885f9 7109 route_map_result_t ret;
d62a17ae 7110 struct bgp_redist *red;
7111
7112 /* Make default attribute. */
7113 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7114 /*
7115 * This must not be NULL to satisfy Coverity SA
7116 */
7117 assert(attr.aspath);
9de1f7ff 7118
a4d82a8a 7119 switch (nhtype) {
9de1f7ff
DS
7120 case NEXTHOP_TYPE_IFINDEX:
7121 break;
7122 case NEXTHOP_TYPE_IPV4:
7123 case NEXTHOP_TYPE_IPV4_IFINDEX:
7124 attr.nexthop = nexthop->ipv4;
7125 break;
7126 case NEXTHOP_TYPE_IPV6:
7127 case NEXTHOP_TYPE_IPV6_IFINDEX:
7128 attr.mp_nexthop_global = nexthop->ipv6;
7129 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7130 break;
7131 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7132 switch (p->family) {
7133 case AF_INET:
9de1f7ff 7134 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7135 break;
7136 case AF_INET6:
9de1f7ff
DS
7137 memset(&attr.mp_nexthop_global, 0,
7138 sizeof(attr.mp_nexthop_global));
74489921 7139 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7140 break;
74489921 7141 }
9de1f7ff 7142 break;
d62a17ae 7143 }
74489921 7144 attr.nh_ifindex = ifindex;
f04a80a5 7145
d62a17ae 7146 attr.med = metric;
7147 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7148 attr.tag = tag;
718e3744 7149
d62a17ae 7150 afi = family2afi(p->family);
6aeb9e78 7151
d62a17ae 7152 red = bgp_redist_lookup(bgp, afi, type, instance);
7153 if (red) {
7154 struct attr attr_new;
718e3744 7155
d62a17ae 7156 /* Copy attribute for modification. */
6f4f49b2 7157 attr_new = attr;
718e3744 7158
d62a17ae 7159 if (red->redist_metric_flag)
7160 attr_new.med = red->redist_metric;
718e3744 7161
d62a17ae 7162 /* Apply route-map. */
7163 if (red->rmap.name) {
40381db7
DS
7164 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7165 rmap_path.peer = bgp->peer_self;
7166 rmap_path.attr = &attr_new;
718e3744 7167
d62a17ae 7168 SET_FLAG(bgp->peer_self->rmap_type,
7169 PEER_RMAP_TYPE_REDISTRIBUTE);
7170
7171 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7172 &rmap_path);
d62a17ae 7173
7174 bgp->peer_self->rmap_type = 0;
7175
7176 if (ret == RMAP_DENYMATCH) {
7177 /* Free uninterned attribute. */
7178 bgp_attr_flush(&attr_new);
7179
7180 /* Unintern original. */
7181 aspath_unintern(&attr.aspath);
7182 bgp_redistribute_delete(bgp, p, type, instance);
7183 return;
7184 }
7185 }
7186
892fedb6 7187 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
7f323236
DW
7188 bgp_attr_add_gshut_community(&attr_new);
7189
d62a17ae 7190 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7191 SAFI_UNICAST, p, NULL);
7192
7193 new_attr = bgp_attr_intern(&attr_new);
7194
6f94b685
DS
7195 for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
7196 bpi = bpi->next)
40381db7
DS
7197 if (bpi->peer == bgp->peer_self
7198 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7199 break;
7200
40381db7 7201 if (bpi) {
d62a17ae 7202 /* Ensure the (source route) type is updated. */
40381db7
DS
7203 bpi->type = type;
7204 if (attrhash_cmp(bpi->attr, new_attr)
7205 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7206 bgp_attr_unintern(&new_attr);
7207 aspath_unintern(&attr.aspath);
7208 bgp_unlock_node(bn);
7209 return;
7210 } else {
7211 /* The attribute is changed. */
40381db7 7212 bgp_path_info_set_flag(bn, bpi,
18ee8310 7213 BGP_PATH_ATTR_CHANGED);
d62a17ae 7214
7215 /* Rewrite BGP route information. */
40381db7
DS
7216 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7217 bgp_path_info_restore(bn, bpi);
d62a17ae 7218 else
40381db7
DS
7219 bgp_aggregate_decrement(
7220 bgp, p, bpi, afi, SAFI_UNICAST);
7221 bgp_attr_unintern(&bpi->attr);
7222 bpi->attr = new_attr;
7223 bpi->uptime = bgp_clock();
d62a17ae 7224
7225 /* Process change. */
40381db7 7226 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7227 SAFI_UNICAST);
7228 bgp_process(bgp, bn, afi, SAFI_UNICAST);
7229 bgp_unlock_node(bn);
7230 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7231
7232 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7233 || (bgp->inst_type
7234 == BGP_INSTANCE_TYPE_DEFAULT)) {
7235
7236 vpn_leak_from_vrf_update(
40381db7 7237 bgp_get_default(), bgp, bpi);
ddb5b488 7238 }
d62a17ae 7239 return;
7240 }
7241 }
7242
7243 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7244 bgp->peer_self, new_attr, bn);
1defdda8 7245 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7246
7247 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7248 bgp_path_info_add(bn, new);
d62a17ae 7249 bgp_unlock_node(bn);
7250 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7251
7252 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7253 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7254
7255 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7256 }
d62a17ae 7257 }
7258
7259 /* Unintern original. */
7260 aspath_unintern(&attr.aspath);
718e3744 7261}
7262
d7c0a89a
QY
7263void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7264 unsigned short instance)
718e3744 7265{
d62a17ae 7266 afi_t afi;
7267 struct bgp_node *rn;
40381db7 7268 struct bgp_path_info *pi;
d62a17ae 7269 struct bgp_redist *red;
718e3744 7270
d62a17ae 7271 afi = family2afi(p->family);
718e3744 7272
d62a17ae 7273 red = bgp_redist_lookup(bgp, afi, type, instance);
7274 if (red) {
7275 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7276 SAFI_UNICAST, p, NULL);
7277
6f94b685 7278 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7 7279 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7280 break;
7281
40381db7 7282 if (pi) {
ddb5b488
PZ
7283 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7284 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7285
7286 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7287 bgp, pi);
ddb5b488 7288 }
40381db7
DS
7289 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
7290 bgp_path_info_delete(rn, pi);
d62a17ae 7291 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7292 }
7293 bgp_unlock_node(rn);
7294 }
7295}
7296
7297/* Withdraw specified route type's route. */
7298void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7299 unsigned short instance)
d62a17ae 7300{
7301 struct bgp_node *rn;
40381db7 7302 struct bgp_path_info *pi;
d62a17ae 7303 struct bgp_table *table;
7304
7305 table = bgp->rib[afi][SAFI_UNICAST];
7306
7307 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685 7308 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next)
40381db7
DS
7309 if (pi->peer == bgp->peer_self && pi->type == type
7310 && pi->instance == instance)
d62a17ae 7311 break;
7312
40381db7 7313 if (pi) {
ddb5b488
PZ
7314 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7315 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7316
7317 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7318 bgp, pi);
ddb5b488 7319 }
40381db7 7320 bgp_aggregate_decrement(bgp, &rn->p, pi, afi,
d62a17ae 7321 SAFI_UNICAST);
40381db7 7322 bgp_path_info_delete(rn, pi);
d62a17ae 7323 bgp_process(bgp, rn, afi, SAFI_UNICAST);
7324 }
718e3744 7325 }
718e3744 7326}
6b0655a2 7327
718e3744 7328/* Static function to display route. */
9c92b5f7
MK
7329static void route_vty_out_route(struct prefix *p, struct vty *vty,
7330 json_object *json)
718e3744 7331{
be054588 7332 int len = 0;
d62a17ae 7333 char buf[BUFSIZ];
50e05855 7334 char buf2[BUFSIZ];
718e3744 7335
d62a17ae 7336 if (p->family == AF_INET) {
c6462ff4 7337 if (!json) {
89e5e9f0
PM
7338 len = vty_out(
7339 vty, "%s/%d",
7340 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7341 p->prefixlen);
c6462ff4
MK
7342 } else {
7343 json_object_string_add(json, "prefix",
7344 inet_ntop(p->family,
7345 &p->u.prefix, buf,
7346 BUFSIZ));
7347 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7348 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7349 json_object_string_add(json, "network", buf2);
c6462ff4 7350 }
d62a17ae 7351 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7352 prefix2str(p, buf, PREFIX_STRLEN);
7353 len = vty_out(vty, "%s", buf);
7354 } else if (p->family == AF_EVPN) {
57f7feb6 7355 if (!json)
60466a63
QY
7356 len = vty_out(
7357 vty, "%s",
7358 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7359 BUFSIZ));
57f7feb6 7360 else
60466a63 7361 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7362 } else if (p->family == AF_FLOWSPEC) {
7363 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7364 json ?
7365 NLRI_STRING_FORMAT_JSON_SIMPLE :
7366 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7367 } else {
c6462ff4 7368 if (!json)
60466a63
QY
7369 len = vty_out(
7370 vty, "%s/%d",
7371 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7372 p->prefixlen);
50e05855
AD
7373 else {
7374 json_object_string_add(json, "prefix",
7375 inet_ntop(p->family,
7376 &p->u.prefix, buf,
7377 BUFSIZ));
7378 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7379 prefix2str(p, buf2, PREFIX_STRLEN);
7380 json_object_string_add(json, "network", buf2);
7381 }
9c92b5f7 7382 }
d62a17ae 7383
9c92b5f7
MK
7384 if (!json) {
7385 len = 17 - len;
7386 if (len < 1)
7387 vty_out(vty, "\n%*s", 20, " ");
7388 else
7389 vty_out(vty, "%*s", len, " ");
7390 }
718e3744 7391}
7392
d62a17ae 7393enum bgp_display_type {
7394 normal_list,
718e3744 7395};
7396
18ee8310 7397/* Print the short form route status for a bgp_path_info */
4b7e6066 7398static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7399 struct bgp_path_info *path,
d62a17ae 7400 json_object *json_path)
718e3744 7401{
d62a17ae 7402 if (json_path) {
b05a1c8b 7403
d62a17ae 7404 /* Route status display. */
9b6d8fcf 7405 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7406 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7407
9b6d8fcf 7408 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7409 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7410
9b6d8fcf 7411 if (path->extra && path->extra->suppress)
d62a17ae 7412 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7413
9b6d8fcf
DS
7414 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7415 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7416 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7417
d62a17ae 7418 /* Selected */
9b6d8fcf 7419 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7420 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7421
9b6d8fcf 7422 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7423 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7424
9b6d8fcf 7425 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7426 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7427
9b6d8fcf 7428 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7429 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7430
d62a17ae 7431 /* Internal route. */
9b6d8fcf
DS
7432 if ((path->peer->as)
7433 && (path->peer->as == path->peer->local_as))
d62a17ae 7434 json_object_string_add(json_path, "pathFrom",
7435 "internal");
7436 else
7437 json_object_string_add(json_path, "pathFrom",
7438 "external");
b05a1c8b 7439
d62a17ae 7440 return;
7441 }
b05a1c8b 7442
d62a17ae 7443 /* Route status display. */
9b6d8fcf 7444 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7445 vty_out(vty, "R");
9b6d8fcf 7446 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7447 vty_out(vty, "S");
9b6d8fcf 7448 else if (path->extra && path->extra->suppress)
d62a17ae 7449 vty_out(vty, "s");
9b6d8fcf
DS
7450 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7451 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7452 vty_out(vty, "*");
7453 else
7454 vty_out(vty, " ");
7455
7456 /* Selected */
9b6d8fcf 7457 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7458 vty_out(vty, "h");
9b6d8fcf 7459 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7460 vty_out(vty, "d");
9b6d8fcf 7461 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7462 vty_out(vty, ">");
9b6d8fcf 7463 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7464 vty_out(vty, "=");
7465 else
7466 vty_out(vty, " ");
718e3744 7467
d62a17ae 7468 /* Internal route. */
9b6d8fcf
DS
7469 if (path->peer && (path->peer->as)
7470 && (path->peer->as == path->peer->local_as))
d62a17ae 7471 vty_out(vty, "i");
7472 else
7473 vty_out(vty, " ");
b40d939b 7474}
7475
515c2602 7476static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
25b5da8d 7477{
892fedb6
DA
7478 if (peer->hostname
7479 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)
515c2602 7480 && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
25b5da8d
DA
7481 return peer->hostname;
7482 return NULL;
7483}
7484
b40d939b 7485/* called from terminal list command */
4b7e6066 7486void route_vty_out(struct vty *vty, struct prefix *p,
9b6d8fcf 7487 struct bgp_path_info *path, int display, safi_t safi,
4b7e6066 7488 json_object *json_paths)
d62a17ae 7489{
515c2602 7490 struct attr *attr = path->attr;
d62a17ae 7491 json_object *json_path = NULL;
7492 json_object *json_nexthops = NULL;
7493 json_object *json_nexthop_global = NULL;
7494 json_object *json_nexthop_ll = NULL;
6f214dd3 7495 json_object *json_ext_community = NULL;
9df8b37c 7496 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7497 bool nexthop_self =
9b6d8fcf 7498 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7499 bool nexthop_othervrf = false;
43089216 7500 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7501 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
515c2602 7502 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 7503
7504 if (json_paths)
7505 json_path = json_object_new_object();
7506
7507 /* short status lead text */
9b6d8fcf 7508 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7509
7510 if (!json_paths) {
7511 /* print prefix and mask */
7512 if (!display)
9c92b5f7 7513 route_vty_out_route(p, vty, json_path);
d62a17ae 7514 else
7515 vty_out(vty, "%*s", 17, " ");
9c92b5f7 7516 } else {
b682f6de 7517 route_vty_out_route(p, vty, json_path);
d62a17ae 7518 }
47fc97cc 7519
9df8b37c
PZ
7520 /*
7521 * If vrf id of nexthop is different from that of prefix,
7522 * set up printable string to append
7523 */
9b6d8fcf 7524 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7525 const char *self = "";
7526
7527 if (nexthop_self)
7528 self = "<";
7529
7530 nexthop_othervrf = true;
9b6d8fcf 7531 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7532
9b6d8fcf 7533 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7534 snprintf(vrf_id_str, sizeof(vrf_id_str),
7535 "@%s%s", VRFID_NONE_STR, self);
7536 else
7537 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7538 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7539
9b6d8fcf
DS
7540 if (path->extra->bgp_orig->inst_type
7541 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7542
9b6d8fcf 7543 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7544 } else {
7545 const char *self = "";
7546
7547 if (nexthop_self)
7548 self = "<";
7549
7550 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7551 }
7552
445c2480
DS
7553 /*
7554 * For ENCAP and EVPN routes, nexthop address family is not
7555 * neccessarily the same as the prefix address family.
7556 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7557 * EVPN routes are also exchanged with a MP nexthop. Currently,
7558 * this
7559 * is only IPv4, the value will be present in either
7560 * attr->nexthop or
7561 * attr->mp_nexthop_global_in
7562 */
7563 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7564 char buf[BUFSIZ];
7565 char nexthop[128];
7566 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7567
7568 switch (af) {
7569 case AF_INET:
7570 sprintf(nexthop, "%s",
a4d82a8a
PZ
7571 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7572 BUFSIZ));
445c2480
DS
7573 break;
7574 case AF_INET6:
7575 sprintf(nexthop, "%s",
a4d82a8a
PZ
7576 inet_ntop(af, &attr->mp_nexthop_global, buf,
7577 BUFSIZ));
445c2480
DS
7578 break;
7579 default:
7580 sprintf(nexthop, "?");
7581 break;
d62a17ae 7582 }
d62a17ae 7583
445c2480
DS
7584 if (json_paths) {
7585 json_nexthop_global = json_object_new_object();
7586
515c2602
DA
7587 json_object_string_add(json_nexthop_global, "ip",
7588 nexthop);
7589
7590 if (nexthop_hostname)
7591 json_object_string_add(json_nexthop_global,
7592 "hostname",
7593 nexthop_hostname);
7594
7595 json_object_string_add(json_nexthop_global, "afi",
7596 (af == AF_INET) ? "ipv4"
7597 : "ipv6");
445c2480
DS
7598 json_object_boolean_true_add(json_nexthop_global,
7599 "used");
7600 } else
25b5da8d 7601 vty_out(vty, "%s%s",
515c2602 7602 nexthop_hostname ? nexthop_hostname : nexthop,
25b5da8d 7603 vrf_id_str);
445c2480
DS
7604 } else if (safi == SAFI_EVPN) {
7605 if (json_paths) {
7606 json_nexthop_global = json_object_new_object();
7607
515c2602
DA
7608 json_object_string_add(json_nexthop_global, "ip",
7609 inet_ntoa(attr->nexthop));
7610
7611 if (nexthop_hostname)
7612 json_object_string_add(json_nexthop_global,
7613 "hostname",
7614 nexthop_hostname);
7615
a4d82a8a
PZ
7616 json_object_string_add(json_nexthop_global, "afi",
7617 "ipv4");
445c2480
DS
7618 json_object_boolean_true_add(json_nexthop_global,
7619 "used");
7620 } else
25b5da8d 7621 vty_out(vty, "%-16s%s",
515c2602
DA
7622 nexthop_hostname ? nexthop_hostname
7623 : inet_ntoa(attr->nexthop),
9df8b37c 7624 vrf_id_str);
d33fc23b 7625 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7626 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7627 if (json_paths) {
7628 json_nexthop_global = json_object_new_object();
515c2602 7629
026b914a
PG
7630 json_object_string_add(json_nexthop_global,
7631 "afi", "ipv4");
515c2602
DA
7632 json_object_string_add(
7633 json_nexthop_global, "ip",
7634 inet_ntoa(attr->nexthop));
7635
7636 if (nexthop_hostname)
7637 json_object_string_add(
7638 json_nexthop_global, "hostname",
7639 nexthop_hostname);
7640
50e05855
AD
7641 json_object_boolean_true_add(
7642 json_nexthop_global,
026b914a
PG
7643 "used");
7644 } else {
25b5da8d 7645 vty_out(vty, "%-16s",
515c2602
DA
7646 nexthop_hostname
7647 ? nexthop_hostname
25b5da8d 7648 : inet_ntoa(attr->nexthop));
026b914a
PG
7649 }
7650 }
d33fc23b 7651 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7652 if (json_paths) {
7653 json_nexthop_global = json_object_new_object();
d62a17ae 7654
515c2602
DA
7655 json_object_string_add(json_nexthop_global, "ip",
7656 inet_ntoa(attr->nexthop));
7657
7658 if (nexthop_hostname)
7659 json_object_string_add(json_nexthop_global,
7660 "hostname",
7661 nexthop_hostname);
445c2480 7662
a4d82a8a
PZ
7663 json_object_string_add(json_nexthop_global, "afi",
7664 "ipv4");
445c2480
DS
7665 json_object_boolean_true_add(json_nexthop_global,
7666 "used");
7667 } else {
9df8b37c
PZ
7668 char buf[BUFSIZ];
7669
d87ff2dd 7670 snprintf(buf, sizeof(buf), "%s%s",
515c2602
DA
7671 nexthop_hostname ? nexthop_hostname
7672 : inet_ntoa(attr->nexthop),
25b5da8d 7673 vrf_id_str);
9df8b37c 7674 vty_out(vty, "%-16s", buf);
d62a17ae 7675 }
445c2480 7676 }
b05a1c8b 7677
445c2480 7678 /* IPv6 Next Hop */
a4d82a8a 7679 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7680 int len;
7681 char buf[BUFSIZ];
d62a17ae 7682
445c2480
DS
7683 if (json_paths) {
7684 json_nexthop_global = json_object_new_object();
a4d82a8a 7685 json_object_string_add(
515c2602
DA
7686 json_nexthop_global, "ip",
7687 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7688 buf, BUFSIZ));
7689
7690 if (nexthop_hostname)
7691 json_object_string_add(json_nexthop_global,
7692 "hostname",
7693 nexthop_hostname);
7694
a4d82a8a
PZ
7695 json_object_string_add(json_nexthop_global, "afi",
7696 "ipv6");
7697 json_object_string_add(json_nexthop_global, "scope",
7698 "global");
445c2480
DS
7699
7700 /* We display both LL & GL if both have been
7701 * received */
0606039c
DA
7702 if ((attr->mp_nexthop_len
7703 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 7704 || (path->peer->conf_if)) {
a4d82a8a 7705 json_nexthop_ll = json_object_new_object();
d62a17ae 7706 json_object_string_add(
515c2602
DA
7707 json_nexthop_ll, "ip",
7708 inet_ntop(AF_INET6,
7709 &attr->mp_nexthop_local, buf,
7710 BUFSIZ));
7711
7712 if (nexthop_hostname)
7713 json_object_string_add(
7714 json_nexthop_ll, "hostname",
7715 nexthop_hostname);
7716
a4d82a8a
PZ
7717 json_object_string_add(json_nexthop_ll, "afi",
7718 "ipv6");
7719 json_object_string_add(json_nexthop_ll, "scope",
445c2480 7720 "link-local");
d62a17ae 7721
a4d82a8a
PZ
7722 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
7723 &attr->mp_nexthop_local)
445c2480
DS
7724 != 0)
7725 && !attr->mp_nexthop_prefer_global)
d62a17ae 7726 json_object_boolean_true_add(
a4d82a8a 7727 json_nexthop_ll, "used");
445c2480
DS
7728 else
7729 json_object_boolean_true_add(
a4d82a8a 7730 json_nexthop_global, "used");
445c2480
DS
7731 } else
7732 json_object_boolean_true_add(
7733 json_nexthop_global, "used");
7734 } else {
7735 /* Display LL if LL/Global both in table unless
7736 * prefer-global is set */
0606039c
DA
7737 if (((attr->mp_nexthop_len
7738 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 7739 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
7740 || (path->peer->conf_if)) {
7741 if (path->peer->conf_if) {
a4d82a8a 7742 len = vty_out(vty, "%s",
9b6d8fcf 7743 path->peer->conf_if);
445c2480
DS
7744 len = 16 - len; /* len of IPv6
7745 addr + max
7746 len of def
7747 ifname */
7748
7749 if (len < 1)
a4d82a8a 7750 vty_out(vty, "\n%*s", 36, " ");
445c2480 7751 else
a4d82a8a 7752 vty_out(vty, "%*s", len, " ");
d62a17ae 7753 } else {
7754 len = vty_out(
9df8b37c 7755 vty, "%s%s",
515c2602
DA
7756 nexthop_hostname
7757 ? nexthop_hostname
25b5da8d
DA
7758 : inet_ntop(
7759 AF_INET6,
7760 &attr->mp_nexthop_local,
7761 buf, BUFSIZ),
9df8b37c 7762 vrf_id_str);
d62a17ae 7763 len = 16 - len;
7764
7765 if (len < 1)
a4d82a8a 7766 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 7767 else
a4d82a8a 7768 vty_out(vty, "%*s", len, " ");
d62a17ae 7769 }
445c2480 7770 } else {
a4d82a8a 7771 len = vty_out(
9df8b37c 7772 vty, "%s%s",
515c2602
DA
7773 nexthop_hostname
7774 ? nexthop_hostname
25b5da8d
DA
7775 : inet_ntop(
7776 AF_INET6,
7777 &attr->mp_nexthop_global,
7778 buf, BUFSIZ),
7779 vrf_id_str);
445c2480
DS
7780 len = 16 - len;
7781
7782 if (len < 1)
7783 vty_out(vty, "\n%*s", 36, " ");
7784 else
7785 vty_out(vty, "%*s", len, " ");
d62a17ae 7786 }
7787 }
445c2480 7788 }
718e3744 7789
445c2480
DS
7790 /* MED/Metric */
7791 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
50e05855
AD
7792 if (json_paths) {
7793
7794 /*
7795 * Adding "metric" field to match with corresponding
7796 * CLI. "med" will be deprecated in future.
7797 */
a4d82a8a 7798 json_object_int_add(json_path, "med", attr->med);
50e05855
AD
7799 json_object_int_add(json_path, "metric", attr->med);
7800 } else
445c2480
DS
7801 vty_out(vty, "%10u", attr->med);
7802 else if (!json_paths)
7803 vty_out(vty, " ");
d62a17ae 7804
445c2480
DS
7805 /* Local Pref */
7806 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855
AD
7807 if (json_paths) {
7808
7809 /*
7810 * Adding "locPrf" field to match with corresponding
7811 * CLI. "localPref" will be deprecated in future.
7812 */
445c2480
DS
7813 json_object_int_add(json_path, "localpref",
7814 attr->local_pref);
50e05855
AD
7815 json_object_int_add(json_path, "locPrf",
7816 attr->local_pref);
7817 } else
445c2480
DS
7818 vty_out(vty, "%7u", attr->local_pref);
7819 else if (!json_paths)
7820 vty_out(vty, " ");
d62a17ae 7821
445c2480
DS
7822 if (json_paths)
7823 json_object_int_add(json_path, "weight", attr->weight);
7824 else
7825 vty_out(vty, "%7u ", attr->weight);
47fc97cc 7826
445c2480
DS
7827 if (json_paths) {
7828 char buf[BUFSIZ];
a4d82a8a
PZ
7829 json_object_string_add(
7830 json_path, "peerId",
9b6d8fcf 7831 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 7832 }
b05a1c8b 7833
445c2480
DS
7834 /* Print aspath */
7835 if (attr->aspath) {
50e05855
AD
7836 if (json_paths) {
7837
7838 /*
7839 * Adding "path" field to match with corresponding
7840 * CLI. "aspath" will be deprecated in future.
7841 */
445c2480
DS
7842 json_object_string_add(json_path, "aspath",
7843 attr->aspath->str);
50e05855
AD
7844 json_object_string_add(json_path, "path",
7845 attr->aspath->str);
7846 } else
445c2480 7847 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 7848 }
f1aa5d8a 7849
445c2480
DS
7850 /* Print origin */
7851 if (json_paths)
a4d82a8a
PZ
7852 json_object_string_add(json_path, "origin",
7853 bgp_origin_long_str[attr->origin]);
445c2480
DS
7854 else
7855 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7856
9df8b37c 7857 if (json_paths) {
6f214dd3
CS
7858 if (safi == SAFI_EVPN &&
7859 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7860 json_ext_community = json_object_new_object();
7861 json_object_string_add(json_ext_community,
7862 "string",
7863 attr->ecommunity->str);
7864 json_object_object_add(json_path,
7865 "extendedCommunity",
7866 json_ext_community);
7867 }
7868
9df8b37c
PZ
7869 if (nexthop_self)
7870 json_object_boolean_true_add(json_path,
7871 "announceNexthopSelf");
7872 if (nexthop_othervrf) {
7873 json_object_string_add(json_path, "nhVrfName",
7874 nexthop_vrfname);
7875
7876 json_object_int_add(json_path, "nhVrfId",
7877 ((nexthop_vrfid == VRF_UNKNOWN)
7878 ? -1
7879 : (int)nexthop_vrfid));
7880 }
7881 }
7882
d62a17ae 7883 if (json_paths) {
7884 if (json_nexthop_global || json_nexthop_ll) {
7885 json_nexthops = json_object_new_array();
f1aa5d8a 7886
d62a17ae 7887 if (json_nexthop_global)
7888 json_object_array_add(json_nexthops,
7889 json_nexthop_global);
f1aa5d8a 7890
d62a17ae 7891 if (json_nexthop_ll)
7892 json_object_array_add(json_nexthops,
7893 json_nexthop_ll);
f1aa5d8a 7894
d62a17ae 7895 json_object_object_add(json_path, "nexthops",
7896 json_nexthops);
7897 }
7898
7899 json_object_array_add(json_paths, json_path);
7900 } else {
7901 vty_out(vty, "\n");
6f214dd3
CS
7902
7903 if (safi == SAFI_EVPN &&
7904 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7905 vty_out(vty, "%*s", 20, " ");
7906 vty_out(vty, "%s\n", attr->ecommunity->str);
7907 }
7908
65efcfce 7909#if ENABLE_BGP_VNC
d62a17ae 7910 /* prints an additional line, indented, with VNC info, if
7911 * present */
7912 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 7913 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 7914#endif
d62a17ae 7915 }
7916}
718e3744 7917
7918/* called from terminal list command */
d62a17ae 7919void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
9f049418 7920 safi_t safi, bool use_json, json_object *json_ar)
d62a17ae 7921{
7922 json_object *json_status = NULL;
7923 json_object *json_net = NULL;
7924 char buff[BUFSIZ];
dc387b0f 7925
d62a17ae 7926 /* Route status display. */
7927 if (use_json) {
7928 json_status = json_object_new_object();
7929 json_net = json_object_new_object();
7930 } else {
7931 vty_out(vty, "*");
7932 vty_out(vty, ">");
7933 vty_out(vty, " ");
7934 }
718e3744 7935
d62a17ae 7936 /* print prefix and mask */
50e05855 7937 if (use_json) {
dc387b0f
LK
7938 if (safi == SAFI_EVPN)
7939 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
7940 else if (p->family == AF_INET || p->family == AF_INET6) {
7941 json_object_string_add(
7942 json_net, "addrPrefix",
7943 inet_ntop(p->family, &p->u.prefix, buff,
7944 BUFSIZ));
7945 json_object_int_add(json_net, "prefixLen",
7946 p->prefixlen);
7947 prefix2str(p, buff, PREFIX_STRLEN);
7948 json_object_string_add(json_net, "network", buff);
7949 }
50e05855 7950 } else
9c92b5f7 7951 route_vty_out_route(p, vty, NULL);
d62a17ae 7952
7953 /* Print attribute */
7954 if (attr) {
7955 if (use_json) {
7956 if (p->family == AF_INET
7957 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 7958 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 7959 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 7960 json_object_string_add(
7961 json_net, "nextHop",
7962 inet_ntoa(
7963 attr->mp_nexthop_global_in));
7964 else
7965 json_object_string_add(
7966 json_net, "nextHop",
7967 inet_ntoa(attr->nexthop));
7968 } else if (p->family == AF_INET6
7969 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
7970 char buf[BUFSIZ];
7971
7972 json_object_string_add(
aa0a10fc 7973 json_net, "nextHopGlobal",
d62a17ae 7974 inet_ntop(AF_INET6,
7975 &attr->mp_nexthop_global, buf,
7976 BUFSIZ));
dc387b0f
LK
7977 } else if (p->family == AF_EVPN &&
7978 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
7979 json_object_string_add(json_net,
7980 "nextHop", inet_ntoa(
7981 attr->mp_nexthop_global_in));
d62a17ae 7982
7983 if (attr->flag
7984 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
7985 json_object_int_add(json_net, "metric",
7986 attr->med);
7987
50e05855
AD
7988 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7989
7990 /*
7991 * Adding "locPrf" field to match with
7992 * corresponding CLI. "localPref" will be
7993 * deprecated in future.
7994 */
d62a17ae 7995 json_object_int_add(json_net, "localPref",
7996 attr->local_pref);
50e05855
AD
7997 json_object_int_add(json_net, "locPrf",
7998 attr->local_pref);
7999 }
d62a17ae 8000
8001 json_object_int_add(json_net, "weight", attr->weight);
8002
8003 /* Print aspath */
50e05855
AD
8004 if (attr->aspath) {
8005
8006 /*
8007 * Adding "path" field to match with
8008 * corresponding CLI. "localPref" will be
8009 * deprecated in future.
8010 */
d62a17ae 8011 json_object_string_add(json_net, "asPath",
8012 attr->aspath->str);
50e05855
AD
8013 json_object_string_add(json_net, "path",
8014 attr->aspath->str);
8015 }
d62a17ae 8016
8017 /* Print origin */
8018 json_object_string_add(json_net, "bgpOriginCode",
8019 bgp_origin_str[attr->origin]);
8020 } else {
8021 if (p->family == AF_INET
8022 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8023 || safi == SAFI_EVPN
8024 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8025 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8026 || safi == SAFI_EVPN)
8027 vty_out(vty, "%-16s",
8028 inet_ntoa(
8029 attr->mp_nexthop_global_in));
8030 else
8031 vty_out(vty, "%-16s",
8032 inet_ntoa(attr->nexthop));
8033 } else if (p->family == AF_INET6
8034 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8035 int len;
8036 char buf[BUFSIZ];
8037
8038 len = vty_out(
8039 vty, "%s",
8040 inet_ntop(AF_INET6,
8041 &attr->mp_nexthop_global, buf,
8042 BUFSIZ));
8043 len = 16 - len;
8044 if (len < 1)
8045 vty_out(vty, "\n%*s", 36, " ");
8046 else
8047 vty_out(vty, "%*s", len, " ");
8048 }
8049 if (attr->flag
8050 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8051 vty_out(vty, "%10u", attr->med);
8052 else
8053 vty_out(vty, " ");
718e3744 8054
d62a17ae 8055 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8056 vty_out(vty, "%7u", attr->local_pref);
8057 else
8058 vty_out(vty, " ");
8059
8060 vty_out(vty, "%7u ", attr->weight);
8061
8062 /* Print aspath */
8063 if (attr->aspath)
8064 aspath_print_vty(vty, "%s", attr->aspath, " ");
8065
8066 /* Print origin */
8067 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8068 }
8069 }
8070 if (use_json) {
8071 json_object_boolean_true_add(json_status, "*");
8072 json_object_boolean_true_add(json_status, ">");
8073 json_object_object_add(json_net, "appliedStatusSymbols",
8074 json_status);
1608ff77 8075
dc387b0f
LK
8076 prefix2str(p, buff, PREFIX_STRLEN);
8077 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8078 } else
8079 vty_out(vty, "\n");
8080}
8081
8082void route_vty_out_tag(struct vty *vty, struct prefix *p,
9b6d8fcf 8083 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8084 json_object *json)
8085{
8086 json_object *json_out = NULL;
8087 struct attr *attr;
8088 mpls_label_t label = MPLS_INVALID_LABEL;
8089
9b6d8fcf 8090 if (!path->extra)
d62a17ae 8091 return;
8092
8093 if (json)
8094 json_out = json_object_new_object();
8095
8096 /* short status lead text */
9b6d8fcf 8097 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8098
8099 /* print prefix and mask */
8100 if (json == NULL) {
8101 if (!display)
9c92b5f7 8102 route_vty_out_route(p, vty, NULL);
d62a17ae 8103 else
8104 vty_out(vty, "%*s", 17, " ");
8105 }
8106
8107 /* Print attribute */
9b6d8fcf 8108 attr = path->attr;
05864da7
DS
8109 if (((p->family == AF_INET)
8110 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8111 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8112 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8113 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8114 || safi == SAFI_EVPN) {
8115 if (json)
8116 json_object_string_add(
8117 json_out, "mpNexthopGlobalIn",
8118 inet_ntoa(attr->mp_nexthop_global_in));
8119 else
8120 vty_out(vty, "%-16s",
8121 inet_ntoa(attr->mp_nexthop_global_in));
8122 } else {
8123 if (json)
8124 json_object_string_add(
8125 json_out, "nexthop",
8126 inet_ntoa(attr->nexthop));
8127 else
8128 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8129 }
8130 } else if (((p->family == AF_INET6)
8131 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8132 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8133 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8134 char buf_a[512];
8135
8136 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8137 if (json)
8138 json_object_string_add(
8139 json_out, "mpNexthopGlobalIn",
8140 inet_ntop(AF_INET6,
8141 &attr->mp_nexthop_global,
8142 buf_a, sizeof(buf_a)));
8143 else
8144 vty_out(vty, "%s",
8145 inet_ntop(AF_INET6,
8146 &attr->mp_nexthop_global,
8147 buf_a, sizeof(buf_a)));
8148 } else if (attr->mp_nexthop_len
8149 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8150 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8151 &attr->mp_nexthop_global,
8152 &attr->mp_nexthop_local);
8153 if (json)
8154 json_object_string_add(json_out,
8155 "mpNexthopGlobalLocal",
8156 buf_a);
8157 else
8158 vty_out(vty, "%s", buf_a);
d62a17ae 8159 }
8160 }
8161
9b6d8fcf 8162 label = decode_label(&path->extra->label[0]);
d62a17ae 8163
8164 if (bgp_is_valid_label(&label)) {
8165 if (json) {
8166 json_object_int_add(json_out, "notag", label);
8167 json_object_array_add(json, json_out);
8168 } else {
8169 vty_out(vty, "notag/%d", label);
8170 vty_out(vty, "\n");
8171 }
8172 }
8173}
718e3744 8174
d62a17ae 8175void route_vty_out_overlay(struct vty *vty, struct prefix *p,
9b6d8fcf 8176 struct bgp_path_info *path, int display,
d62a17ae 8177 json_object *json_paths)
718e3744 8178{
d62a17ae 8179 struct attr *attr;
14f51eba 8180 char buf[BUFSIZ] = {0};
d62a17ae 8181 json_object *json_path = NULL;
14f51eba
LK
8182 json_object *json_nexthop = NULL;
8183 json_object *json_overlay = NULL;
856ca177 8184
9b6d8fcf 8185 if (!path->extra)
d62a17ae 8186 return;
718e3744 8187
14f51eba
LK
8188 if (json_paths) {
8189 json_path = json_object_new_object();
8190 json_overlay = json_object_new_object();
8191 json_nexthop = json_object_new_object();
8192 }
8193
d62a17ae 8194 /* short status lead text */
9b6d8fcf 8195 route_vty_short_status_out(vty, path, json_path);
856ca177 8196
d62a17ae 8197 /* print prefix and mask */
8198 if (!display)
14f51eba 8199 route_vty_out_route(p, vty, json_path);
d62a17ae 8200 else
8201 vty_out(vty, "%*s", 17, " ");
8202
8203 /* Print attribute */
9b6d8fcf 8204 attr = path->attr;
05864da7
DS
8205 char buf1[BUFSIZ];
8206 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8207
05864da7
DS
8208 switch (af) {
8209 case AF_INET:
8210 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8211 if (!json_path) {
8212 vty_out(vty, "%-16s", buf);
8213 } else {
8214 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8215
05864da7 8216 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8217
05864da7
DS
8218 json_object_object_add(json_path, "nexthop",
8219 json_nexthop);
8220 }
8221 break;
8222 case AF_INET6:
8223 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8224 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8225 if (!json_path) {
8226 vty_out(vty, "%s(%s)", buf, buf1);
8227 } else {
8228 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8229
05864da7
DS
8230 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8231 buf1);
14f51eba 8232
05864da7 8233 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8234
05864da7
DS
8235 json_object_object_add(json_path, "nexthop",
8236 json_nexthop);
8237 }
8238 break;
8239 default:
8240 if (!json_path) {
8241 vty_out(vty, "?");
8242 } else {
8243 json_object_string_add(json_nexthop, "Error",
8244 "Unsupported address-family");
d62a17ae 8245 }
05864da7 8246 }
988258b4 8247
05864da7 8248 char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
988258b4 8249
05864da7
DS
8250 if (!json_path)
8251 vty_out(vty, "%s", str);
8252 else
8253 json_object_string_add(json_overlay, "esi", str);
25b5da8d 8254
05864da7 8255 XFREE(MTYPE_TMP, str);
988258b4 8256
05864da7
DS
8257 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8258 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8259 BUFSIZ);
8260 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8261 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8262 BUFSIZ);
8263 }
14f51eba 8264
05864da7
DS
8265 if (!json_path)
8266 vty_out(vty, "/%s", buf);
8267 else
8268 json_object_string_add(json_overlay, "gw", buf);
8269
8270 if (attr->ecommunity) {
8271 char *mac = NULL;
8272 struct ecommunity_val *routermac = ecommunity_lookup(
8273 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8274 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8275
8276 if (routermac)
8277 mac = ecom_mac2str((char *)routermac->val);
8278 if (mac) {
8279 if (!json_path) {
8280 vty_out(vty, "/%s", (char *)mac);
8281 } else {
8282 json_object_string_add(json_overlay, "rmac",
8283 mac);
988258b4 8284 }
05864da7 8285 XFREE(MTYPE_TMP, mac);
988258b4 8286 }
05864da7 8287 }
718e3744 8288
05864da7
DS
8289 if (!json_path) {
8290 vty_out(vty, "\n");
8291 } else {
8292 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8293
05864da7 8294 json_object_array_add(json_paths, json_path);
14f51eba 8295 }
d62a17ae 8296}
718e3744 8297
d62a17ae 8298/* dampening route */
8299static void damp_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8300 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8301 safi_t safi, bool use_json, json_object *json)
d62a17ae 8302{
8303 struct attr *attr;
8304 int len;
8305 char timebuf[BGP_UPTIME_LEN];
8306
8307 /* short status lead text */
9b6d8fcf 8308 route_vty_short_status_out(vty, path, json);
d62a17ae 8309
8310 /* print prefix and mask */
8311 if (!use_json) {
8312 if (!display)
9c92b5f7 8313 route_vty_out_route(p, vty, NULL);
d62a17ae 8314 else
8315 vty_out(vty, "%*s", 17, " ");
8316 }
8317
9b6d8fcf 8318 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8319 len = 17 - len;
8320 if (len < 1) {
8321 if (!use_json)
8322 vty_out(vty, "\n%*s", 34, " ");
8323 } else {
8324 if (use_json)
8325 json_object_int_add(json, "peerHost", len);
8326 else
8327 vty_out(vty, "%*s", len, " ");
8328 }
8329
8330 if (use_json)
a935f597
DA
8331 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8332 safi, use_json, json);
d62a17ae 8333 else
9b6d8fcf
DS
8334 vty_out(vty, "%s ",
8335 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8336 BGP_UPTIME_LEN, afi, safi,
8337 use_json, json));
d62a17ae 8338
8339 /* Print attribute */
9b6d8fcf 8340 attr = path->attr;
d62a17ae 8341
05864da7
DS
8342 /* Print aspath */
8343 if (attr->aspath) {
d62a17ae 8344 if (use_json)
05864da7
DS
8345 json_object_string_add(json, "asPath",
8346 attr->aspath->str);
d62a17ae 8347 else
05864da7 8348 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8349 }
05864da7
DS
8350
8351 /* Print origin */
8352 if (use_json)
8353 json_object_string_add(json, "origin",
8354 bgp_origin_str[attr->origin]);
8355 else
8356 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8357
d62a17ae 8358 if (!use_json)
8359 vty_out(vty, "\n");
8360}
718e3744 8361
d62a17ae 8362/* flap route */
8363static void flap_route_vty_out(struct vty *vty, struct prefix *p,
a935f597 8364 struct bgp_path_info *path, int display, afi_t afi,
4b7e6066 8365 safi_t safi, bool use_json, json_object *json)
784d3a42 8366{
d62a17ae 8367 struct attr *attr;
8368 struct bgp_damp_info *bdi;
8369 char timebuf[BGP_UPTIME_LEN];
8370 int len;
784d3a42 8371
9b6d8fcf 8372 if (!path->extra)
d62a17ae 8373 return;
784d3a42 8374
9b6d8fcf 8375 bdi = path->extra->damp_info;
784d3a42 8376
d62a17ae 8377 /* short status lead text */
9b6d8fcf 8378 route_vty_short_status_out(vty, path, json);
784d3a42 8379
d62a17ae 8380 /* print prefix and mask */
8381 if (!use_json) {
8382 if (!display)
9c92b5f7 8383 route_vty_out_route(p, vty, NULL);
d62a17ae 8384 else
8385 vty_out(vty, "%*s", 17, " ");
8386 }
784d3a42 8387
9b6d8fcf 8388 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8389 len = 16 - len;
8390 if (len < 1) {
8391 if (!use_json)
8392 vty_out(vty, "\n%*s", 33, " ");
8393 } else {
8394 if (use_json)
8395 json_object_int_add(json, "peerHost", len);
8396 else
8397 vty_out(vty, "%*s", len, " ");
8398 }
784d3a42 8399
d62a17ae 8400 len = vty_out(vty, "%d", bdi->flap);
8401 len = 5 - len;
8402 if (len < 1) {
8403 if (!use_json)
8404 vty_out(vty, " ");
8405 } else {
8406 if (use_json)
8407 json_object_int_add(json, "bdiFlap", len);
8408 else
8409 vty_out(vty, "%*s", len, " ");
8410 }
8411
8412 if (use_json)
8413 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8414 json);
8415 else
996c9314
LB
8416 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8417 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8418
9b6d8fcf
DS
8419 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8420 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8421 if (use_json)
9b6d8fcf 8422 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8423 BGP_UPTIME_LEN, afi, safi,
8424 use_json, json);
d62a17ae 8425 else
8426 vty_out(vty, "%s ",
9b6d8fcf 8427 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8428 BGP_UPTIME_LEN, afi,
8429 safi, use_json, json));
d62a17ae 8430 } else {
8431 if (!use_json)
8432 vty_out(vty, "%*s ", 8, " ");
8433 }
8434
8435 /* Print attribute */
9b6d8fcf 8436 attr = path->attr;
d62a17ae 8437
05864da7
DS
8438 /* Print aspath */
8439 if (attr->aspath) {
d62a17ae 8440 if (use_json)
05864da7
DS
8441 json_object_string_add(json, "asPath",
8442 attr->aspath->str);
d62a17ae 8443 else
05864da7 8444 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8445 }
05864da7
DS
8446
8447 /* Print origin */
8448 if (use_json)
8449 json_object_string_add(json, "origin",
8450 bgp_origin_str[attr->origin]);
8451 else
8452 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8453
d62a17ae 8454 if (!use_json)
8455 vty_out(vty, "\n");
8456}
8457
8458static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8459 int *first, const char *header,
8460 json_object *json_adv_to)
8461{
8462 char buf1[INET6_ADDRSTRLEN];
8463 json_object *json_peer = NULL;
8464
8465 if (json_adv_to) {
8466 /* 'advertised-to' is a dictionary of peers we have advertised
8467 * this
8468 * prefix too. The key is the peer's IP or swpX, the value is
8469 * the
8470 * hostname if we know it and "" if not.
8471 */
8472 json_peer = json_object_new_object();
8473
8474 if (peer->hostname)
8475 json_object_string_add(json_peer, "hostname",
8476 peer->hostname);
8477
8478 if (peer->conf_if)
8479 json_object_object_add(json_adv_to, peer->conf_if,
8480 json_peer);
8481 else
8482 json_object_object_add(
8483 json_adv_to,
8484 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8485 json_peer);
8486 } else {
8487 if (*first) {
8488 vty_out(vty, "%s", header);
8489 *first = 0;
8490 }
8491
8492 if (peer->hostname
892fedb6 8493 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8494 if (peer->conf_if)
8495 vty_out(vty, " %s(%s)", peer->hostname,
8496 peer->conf_if);
8497 else
8498 vty_out(vty, " %s(%s)", peer->hostname,
8499 sockunion2str(&peer->su, buf1,
8500 SU_ADDRSTRLEN));
8501 } else {
8502 if (peer->conf_if)
8503 vty_out(vty, " %s", peer->conf_if);
8504 else
8505 vty_out(vty, " %s",
8506 sockunion2str(&peer->su, buf1,
8507 SU_ADDRSTRLEN));
8508 }
8509 }
784d3a42
PG
8510}
8511
dcc68b5e
MS
8512static void route_vty_out_tx_ids(struct vty *vty,
8513 struct bgp_addpath_info_data *d)
8514{
8515 int i;
8516
8517 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8518 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8519 d->addpath_tx_id[i],
8520 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8521 }
8522}
8523
0dc8ee70
DS
8524static const char *bgp_path_selection_reason2str(
8525 enum bgp_path_selection_reason reason)
8526{
8527 switch (reason) {
8528 case bgp_path_selection_none:
8529 return "Nothing to Select";
0dc8ee70
DS
8530 case bgp_path_selection_first:
8531 return "First path received";
0dc8ee70
DS
8532 case bgp_path_selection_evpn_sticky_mac:
8533 return "EVPN Sticky Mac";
0dc8ee70
DS
8534 case bgp_path_selection_evpn_seq:
8535 return "EVPN sequence number";
0dc8ee70
DS
8536 case bgp_path_selection_evpn_lower_ip:
8537 return "EVPN lower IP";
0dc8ee70
DS
8538 case bgp_path_selection_weight:
8539 return "Weight";
0dc8ee70
DS
8540 case bgp_path_selection_local_pref:
8541 return "Local Pref";
0dc8ee70
DS
8542 case bgp_path_selection_local_route:
8543 return "Local Route";
0dc8ee70
DS
8544 case bgp_path_selection_confed_as_path:
8545 return "Confederation based AS Path";
0dc8ee70
DS
8546 case bgp_path_selection_as_path:
8547 return "AS Path";
0dc8ee70
DS
8548 case bgp_path_selection_origin:
8549 return "Origin";
0dc8ee70
DS
8550 case bgp_path_selection_med:
8551 return "MED";
0dc8ee70
DS
8552 case bgp_path_selection_peer:
8553 return "Peer Type";
0dc8ee70
DS
8554 case bgp_path_selection_confed:
8555 return "Confed Peer Type";
0dc8ee70
DS
8556 case bgp_path_selection_igp_metric:
8557 return "IGP Metric";
0dc8ee70
DS
8558 case bgp_path_selection_older:
8559 return "Older Path";
0dc8ee70
DS
8560 case bgp_path_selection_router_id:
8561 return "Router ID";
0dc8ee70
DS
8562 case bgp_path_selection_cluster_length:
8563 return "Cluser length";
0dc8ee70
DS
8564 case bgp_path_selection_stale:
8565 return "Path Staleness";
0dc8ee70
DS
8566 case bgp_path_selection_local_configured:
8567 return "Locally configured route";
0dc8ee70
DS
8568 case bgp_path_selection_neighbor_ip:
8569 return "Neighbor IP";
0dc8ee70
DS
8570 case bgp_path_selection_default:
8571 return "Nothing left to compare";
0dc8ee70 8572 }
a74879b2 8573 return "Invalid (internal error)";
0dc8ee70
DS
8574}
8575
f08b5ca0
DS
8576void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8577 struct bgp_node *bn, struct bgp_path_info *path,
8578 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8579{
8580 char buf[INET6_ADDRSTRLEN];
8581 char buf1[BUFSIZ];
d62a17ae 8582 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8583 struct attr *attr = path->attr;
d62a17ae 8584 int sockunion_vty_out(struct vty *, union sockunion *);
8585 time_t tbuf;
8586 json_object *json_bestpath = NULL;
8587 json_object *json_cluster_list = NULL;
8588 json_object *json_cluster_list_list = NULL;
8589 json_object *json_ext_community = NULL;
8590 json_object *json_last_update = NULL;
7fd077aa 8591 json_object *json_pmsi = NULL;
d62a17ae 8592 json_object *json_nexthop_global = NULL;
8593 json_object *json_nexthop_ll = NULL;
8594 json_object *json_nexthops = NULL;
8595 json_object *json_path = NULL;
8596 json_object *json_peer = NULL;
8597 json_object *json_string = NULL;
8598 json_object *json_adv_to = NULL;
8599 int first = 0;
8600 struct listnode *node, *nnode;
8601 struct peer *peer;
8602 int addpath_capable;
8603 int has_adj;
8604 unsigned int first_as;
1defdda8 8605 bool nexthop_self =
9b6d8fcf 8606 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8607 int i;
515c2602 8608 char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
d62a17ae 8609
8610 if (json_paths) {
8611 json_path = json_object_new_object();
8612 json_peer = json_object_new_object();
8613 json_nexthop_global = json_object_new_object();
8614 }
8615
44c69747 8616 if (path->extra) {
b57ba6d2 8617 char tag_buf[30];
d62a17ae 8618
d7325ee7 8619 buf2[0] = '\0';
d62a17ae 8620 tag_buf[0] = '\0';
9b6d8fcf
DS
8621 if (path->extra && path->extra->num_labels) {
8622 bgp_evpn_label2str(path->extra->label,
8623 path->extra->num_labels, tag_buf,
a4d82a8a 8624 sizeof(tag_buf));
d62a17ae 8625 }
d7325ee7 8626 if (safi == SAFI_EVPN) {
44c69747
LK
8627 if (!json_paths) {
8628 bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
8629 buf2, sizeof(buf2));
8630 vty_out(vty, " Route %s", buf2);
8631 if (tag_buf[0] != '\0')
8632 vty_out(vty, " VNI %s", tag_buf);
8633 vty_out(vty, "\n");
8634 } else {
8635 if (tag_buf[0])
8636 json_object_string_add(json_path, "VNI",
8637 tag_buf);
8638 }
d7325ee7
DD
8639 }
8640
44c69747 8641 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 8642 struct bgp_path_info *parent_ri;
d62a17ae 8643 struct bgp_node *rn, *prn;
8644
9b6d8fcf 8645 parent_ri = (struct bgp_path_info *)path->extra->parent;
d62a17ae 8646 rn = parent_ri->net;
8647 if (rn && rn->prn) {
8648 prn = rn->prn;
d7325ee7
DD
8649 prefix_rd2str((struct prefix_rd *)&prn->p,
8650 buf1, sizeof(buf1));
8651 if (is_pi_family_evpn(parent_ri)) {
8652 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
8653 buf2, sizeof(buf2));
8654 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
8655 } else
8656 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 8657 }
8658 }
8659 }
d62a17ae 8660
05864da7
DS
8661 /* Line1 display AS-path, Aggregator */
8662 if (attr->aspath) {
8663 if (json_paths) {
8664 if (!attr->aspath->json)
8665 aspath_str_update(attr->aspath, true);
8666 json_object_lock(attr->aspath->json);
8667 json_object_object_add(json_path, "aspath",
8668 attr->aspath->json);
8669 } else {
8670 if (attr->aspath->segments)
8671 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 8672 else
05864da7 8673 vty_out(vty, " Local");
d62a17ae 8674 }
05864da7 8675 }
d62a17ae 8676
05864da7
DS
8677 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
8678 if (json_paths)
8679 json_object_boolean_true_add(json_path, "removed");
8680 else
8681 vty_out(vty, ", (removed)");
8682 }
d62a17ae 8683
05864da7
DS
8684 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
8685 if (json_paths)
8686 json_object_boolean_true_add(json_path, "stale");
8687 else
8688 vty_out(vty, ", (stale)");
8689 }
d62a17ae 8690
05864da7
DS
8691 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
8692 if (json_paths) {
8693 json_object_int_add(json_path, "aggregatorAs",
8694 attr->aggregator_as);
8695 json_object_string_add(
8696 json_path, "aggregatorId",
8697 inet_ntoa(attr->aggregator_addr));
8698 } else {
8699 vty_out(vty, ", (aggregated by %u %s)",
8700 attr->aggregator_as,
8701 inet_ntoa(attr->aggregator_addr));
d62a17ae 8702 }
05864da7 8703 }
d62a17ae 8704
05864da7
DS
8705 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8706 PEER_FLAG_REFLECTOR_CLIENT)) {
8707 if (json_paths)
8708 json_object_boolean_true_add(json_path,
8709 "rxedFromRrClient");
8710 else
8711 vty_out(vty, ", (Received from a RR-client)");
8712 }
d62a17ae 8713
05864da7
DS
8714 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
8715 PEER_FLAG_RSERVER_CLIENT)) {
8716 if (json_paths)
8717 json_object_boolean_true_add(json_path,
8718 "rxedFromRsClient");
8719 else
8720 vty_out(vty, ", (Received from a RS-client)");
8721 }
d62a17ae 8722
05864da7
DS
8723 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
8724 if (json_paths)
8725 json_object_boolean_true_add(json_path,
8726 "dampeningHistoryEntry");
8727 else
8728 vty_out(vty, ", (history entry)");
8729 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
8730 if (json_paths)
8731 json_object_boolean_true_add(json_path,
8732 "dampeningSuppressed");
8733 else
8734 vty_out(vty, ", (suppressed due to dampening)");
8735 }
d62a17ae 8736
05864da7
DS
8737 if (!json_paths)
8738 vty_out(vty, "\n");
d62a17ae 8739
05864da7
DS
8740 /* Line2 display Next-hop, Neighbor, Router-id */
8741 /* Display the nexthop */
8742 if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET
8743 || bn->p.family == AF_EVPN)
8744 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
8745 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8746 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8747 || safi == SAFI_EVPN) {
515c2602 8748 if (json_paths) {
d62a17ae 8749 json_object_string_add(
515c2602
DA
8750 json_nexthop_global, "ip",
8751 inet_ntoa(attr->mp_nexthop_global_in));
8752
8753 if (nexthop_hostname)
8754 json_object_string_add(
8755 json_nexthop_global, "hostname",
8756 nexthop_hostname);
8757 } else
d62a17ae 8758 vty_out(vty, " %s",
515c2602
DA
8759 nexthop_hostname
8760 ? nexthop_hostname
05864da7 8761 : inet_ntoa(
515c2602 8762 attr->mp_nexthop_global_in));
d62a17ae 8763 } else {
515c2602 8764 if (json_paths) {
05864da7 8765 json_object_string_add(
515c2602
DA
8766 json_nexthop_global, "ip",
8767 inet_ntoa(attr->nexthop));
8768
8769 if (nexthop_hostname)
8770 json_object_string_add(
8771 json_nexthop_global, "hostname",
8772 nexthop_hostname);
8773 } else
05864da7 8774 vty_out(vty, " %s",
515c2602
DA
8775 nexthop_hostname
8776 ? nexthop_hostname
05864da7 8777 : inet_ntoa(attr->nexthop));
d62a17ae 8778 }
8779
05864da7
DS
8780 if (json_paths)
8781 json_object_string_add(json_nexthop_global, "afi",
8782 "ipv4");
8783 } else {
8784 if (json_paths) {
8785 json_object_string_add(
515c2602
DA
8786 json_nexthop_global, "ip",
8787 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8788 buf, INET6_ADDRSTRLEN));
8789
8790 if (nexthop_hostname)
8791 json_object_string_add(json_nexthop_global,
8792 "hostname",
8793 nexthop_hostname);
8794
05864da7
DS
8795 json_object_string_add(json_nexthop_global, "afi",
8796 "ipv6");
8797 json_object_string_add(json_nexthop_global, "scope",
8798 "global");
8799 } else {
8800 vty_out(vty, " %s",
515c2602
DA
8801 nexthop_hostname
8802 ? nexthop_hostname
05864da7
DS
8803 : inet_ntop(AF_INET6,
8804 &attr->mp_nexthop_global,
8805 buf, INET6_ADDRSTRLEN));
d62a17ae 8806 }
05864da7 8807 }
d62a17ae 8808
05864da7
DS
8809 /* Display the IGP cost or 'inaccessible' */
8810 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
8811 if (json_paths)
8812 json_object_boolean_false_add(json_nexthop_global,
8813 "accessible");
8814 else
8815 vty_out(vty, " (inaccessible)");
8816 } else {
8817 if (path->extra && path->extra->igpmetric) {
d62a17ae 8818 if (json_paths)
05864da7
DS
8819 json_object_int_add(json_nexthop_global,
8820 "metric",
8821 path->extra->igpmetric);
d62a17ae 8822 else
05864da7
DS
8823 vty_out(vty, " (metric %u)",
8824 path->extra->igpmetric);
d62a17ae 8825 }
8826
05864da7 8827 /* IGP cost is 0, display this only for json */
d62a17ae 8828 else {
d62a17ae 8829 if (json_paths)
05864da7
DS
8830 json_object_int_add(json_nexthop_global,
8831 "metric", 0);
d62a17ae 8832 }
d62a17ae 8833
05864da7
DS
8834 if (json_paths)
8835 json_object_boolean_true_add(json_nexthop_global,
8836 "accessible");
8837 }
d62a17ae 8838
05864da7
DS
8839 /* Display peer "from" output */
8840 /* This path was originated locally */
8841 if (path->peer == bgp->peer_self) {
d62a17ae 8842
05864da7
DS
8843 if (safi == SAFI_EVPN
8844 || (bn->p.family == AF_INET
8845 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 8846 if (json_paths)
05864da7
DS
8847 json_object_string_add(json_peer, "peerId",
8848 "0.0.0.0");
d62a17ae 8849 else
05864da7
DS
8850 vty_out(vty, " from 0.0.0.0 ");
8851 } else {
d62a17ae 8852 if (json_paths)
05864da7
DS
8853 json_object_string_add(json_peer, "peerId",
8854 "::");
d62a17ae 8855 else
05864da7 8856 vty_out(vty, " from :: ");
d62a17ae 8857 }
d62a17ae 8858
05864da7
DS
8859 if (json_paths)
8860 json_object_string_add(json_peer, "routerId",
8861 inet_ntoa(bgp->router_id));
8862 else
8863 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
8864 }
d62a17ae 8865
05864da7
DS
8866 /* We RXed this path from one of our peers */
8867 else {
8868
8869 if (json_paths) {
8870 json_object_string_add(json_peer, "peerId",
8871 sockunion2str(&path->peer->su,
8872 buf,
8873 SU_ADDRSTRLEN));
8874 json_object_string_add(json_peer, "routerId",
8875 inet_ntop(AF_INET,
8876 &path->peer->remote_id,
8877 buf1, sizeof(buf1)));
8878
8879 if (path->peer->hostname)
8880 json_object_string_add(json_peer, "hostname",
8881 path->peer->hostname);
8882
8883 if (path->peer->domainname)
8884 json_object_string_add(json_peer, "domainname",
8885 path->peer->domainname);
8886
8887 if (path->peer->conf_if)
8888 json_object_string_add(json_peer, "interface",
8889 path->peer->conf_if);
8890 } else {
8891 if (path->peer->conf_if) {
8892 if (path->peer->hostname
892fedb6
DA
8893 && CHECK_FLAG(path->peer->bgp->flags,
8894 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
8895 vty_out(vty, " from %s(%s)",
8896 path->peer->hostname,
8897 path->peer->conf_if);
d62a17ae 8898 else
05864da7 8899 vty_out(vty, " from %s",
9b6d8fcf 8900 path->peer->conf_if);
d62a17ae 8901 } else {
05864da7 8902 if (path->peer->hostname
892fedb6
DA
8903 && CHECK_FLAG(path->peer->bgp->flags,
8904 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
8905 vty_out(vty, " from %s(%s)",
8906 path->peer->hostname,
8907 path->peer->host);
d62a17ae 8908 else
05864da7
DS
8909 vty_out(vty, " from %s",
8910 sockunion2str(&path->peer->su,
8911 buf,
8912 SU_ADDRSTRLEN));
d62a17ae 8913 }
d62a17ae 8914
05864da7
DS
8915 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
8916 vty_out(vty, " (%s)",
8917 inet_ntoa(attr->originator_id));
8918 else
8919 vty_out(vty, " (%s)",
8920 inet_ntop(AF_INET,
8921 &path->peer->remote_id, buf1,
8922 sizeof(buf1)));
d62a17ae 8923 }
05864da7 8924 }
9df8b37c 8925
05864da7
DS
8926 /*
8927 * Note when vrfid of nexthop is different from that of prefix
8928 */
8929 if (path->extra && path->extra->bgp_orig) {
8930 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8931
05864da7
DS
8932 if (json_paths) {
8933 const char *vn;
9df8b37c 8934
05864da7
DS
8935 if (path->extra->bgp_orig->inst_type
8936 == BGP_INSTANCE_TYPE_DEFAULT)
8937 vn = VRF_DEFAULT_NAME;
8938 else
8939 vn = path->extra->bgp_orig->name;
9df8b37c 8940
05864da7 8941 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 8942
05864da7
DS
8943 if (nexthop_vrfid == VRF_UNKNOWN) {
8944 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 8945 } else {
05864da7
DS
8946 json_object_int_add(json_path, "nhVrfId",
8947 (int)nexthop_vrfid);
9df8b37c 8948 }
05864da7
DS
8949 } else {
8950 if (nexthop_vrfid == VRF_UNKNOWN)
8951 vty_out(vty, " vrf ?");
137147c6
DS
8952 else {
8953 struct vrf *vrf;
8954
8955 vrf = vrf_lookup_by_id(nexthop_vrfid);
8956 vty_out(vty, " vrf %s(%u)",
8957 VRF_LOGNAME(vrf), nexthop_vrfid);
8958 }
9df8b37c 8959 }
05864da7 8960 }
9df8b37c 8961
05864da7
DS
8962 if (nexthop_self) {
8963 if (json_paths) {
8964 json_object_boolean_true_add(json_path,
8965 "announceNexthopSelf");
8966 } else {
8967 vty_out(vty, " announce-nh-self");
9df8b37c 8968 }
05864da7 8969 }
9df8b37c 8970
05864da7
DS
8971 if (!json_paths)
8972 vty_out(vty, "\n");
d62a17ae 8973
05864da7
DS
8974 /* display the link-local nexthop */
8975 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8976 if (json_paths) {
8977 json_nexthop_ll = json_object_new_object();
8978 json_object_string_add(
515c2602
DA
8979 json_nexthop_ll, "ip",
8980 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
8981 buf, INET6_ADDRSTRLEN));
8982
8983 if (nexthop_hostname)
8984 json_object_string_add(json_nexthop_ll,
8985 "hostname",
8986 nexthop_hostname);
8987
05864da7
DS
8988 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
8989 json_object_string_add(json_nexthop_ll, "scope",
8990 "link-local");
d62a17ae 8991
05864da7
DS
8992 json_object_boolean_true_add(json_nexthop_ll,
8993 "accessible");
d62a17ae 8994
05864da7 8995 if (!attr->mp_nexthop_prefer_global)
d62a17ae 8996 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
8997 "used");
8998 else
8999 json_object_boolean_true_add(
9000 json_nexthop_global, "used");
9001 } else {
9002 vty_out(vty, " (%s) %s\n",
9003 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9004 buf, INET6_ADDRSTRLEN),
9005 attr->mp_nexthop_prefer_global
9006 ? "(prefer-global)"
9007 : "(used)");
d62a17ae 9008 }
05864da7
DS
9009 }
9010 /* If we do not have a link-local nexthop then we must flag the
9011 global as "used" */
9012 else {
9013 if (json_paths)
9014 json_object_boolean_true_add(json_nexthop_global,
9015 "used");
9016 }
d62a17ae 9017
05864da7
DS
9018 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9019 * Int/Ext/Local, Atomic, best */
9020 if (json_paths)
9021 json_object_string_add(json_path, "origin",
9022 bgp_origin_long_str[attr->origin]);
9023 else
9024 vty_out(vty, " Origin %s",
9025 bgp_origin_long_str[attr->origin]);
9df8b37c 9026
05864da7
DS
9027 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
9028 if (json_paths) {
9029 /*
9030 * Adding "metric" field to match with
9031 * corresponding CLI. "med" will be
9032 * deprecated in future.
9033 */
9034 json_object_int_add(json_path, "med", attr->med);
9035 json_object_int_add(json_path, "metric", attr->med);
9036 } else
9037 vty_out(vty, ", metric %u", attr->med);
9038 }
9df8b37c 9039
05864da7
DS
9040 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9041 if (json_paths)
9042 json_object_int_add(json_path, "localpref",
9043 attr->local_pref);
9044 else
9045 vty_out(vty, ", localpref %u", attr->local_pref);
9046 }
9df8b37c 9047
05864da7
DS
9048 if (attr->weight != 0) {
9049 if (json_paths)
9050 json_object_int_add(json_path, "weight", attr->weight);
9051 else
9052 vty_out(vty, ", weight %u", attr->weight);
9053 }
9df8b37c 9054
05864da7
DS
9055 if (attr->tag != 0) {
9056 if (json_paths)
9057 json_object_int_add(json_path, "tag", attr->tag);
9058 else
9059 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9060 }
9df8b37c 9061
05864da7
DS
9062 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9063 if (json_paths)
9064 json_object_boolean_false_add(json_path, "valid");
9065 else
9066 vty_out(vty, ", invalid");
9067 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9068 if (json_paths)
9069 json_object_boolean_true_add(json_path, "valid");
9070 else
9071 vty_out(vty, ", valid");
9072 }
9df8b37c 9073
05864da7
DS
9074 if (path->peer != bgp->peer_self) {
9075 if (path->peer->as == path->peer->local_as) {
9076 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9077 if (json_paths)
9078 json_object_string_add(
9079 json_peer, "type",
9080 "confed-internal");
d62a17ae 9081 else
05864da7 9082 vty_out(vty, ", confed-internal");
d62a17ae 9083 } else {
05864da7
DS
9084 if (json_paths)
9085 json_object_string_add(
9086 json_peer, "type", "internal");
9087 else
9088 vty_out(vty, ", internal");
9df8b37c 9089 }
05864da7
DS
9090 } else {
9091 if (bgp_confederation_peers_check(bgp,
9092 path->peer->as)) {
9093 if (json_paths)
9094 json_object_string_add(
9095 json_peer, "type",
9096 "confed-external");
d62a17ae 9097 else
05864da7 9098 vty_out(vty, ", confed-external");
d62a17ae 9099 } else {
05864da7
DS
9100 if (json_paths)
9101 json_object_string_add(
9102 json_peer, "type", "external");
9103 else
9104 vty_out(vty, ", external");
d62a17ae 9105 }
9106 }
05864da7
DS
9107 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9108 if (json_paths) {
9109 json_object_boolean_true_add(json_path, "aggregated");
9110 json_object_boolean_true_add(json_path, "local");
9111 } else {
9112 vty_out(vty, ", aggregated, local");
9113 }
9114 } else if (path->type != ZEBRA_ROUTE_BGP) {
9115 if (json_paths)
9116 json_object_boolean_true_add(json_path, "sourced");
9117 else
9118 vty_out(vty, ", sourced");
9119 } else {
9120 if (json_paths) {
9121 json_object_boolean_true_add(json_path, "sourced");
9122 json_object_boolean_true_add(json_path, "local");
9123 } else {
9124 vty_out(vty, ", sourced, local");
d62a17ae 9125 }
05864da7 9126 }
718e3744 9127
05864da7 9128 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9129 if (json_paths)
05864da7
DS
9130 json_object_boolean_true_add(json_path,
9131 "atomicAggregate");
d62a17ae 9132 else
05864da7
DS
9133 vty_out(vty, ", atomic-aggregate");
9134 }
d62a17ae 9135
05864da7
DS
9136 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9137 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9138 && bgp_path_info_mpath_count(path))) {
9139 if (json_paths)
9140 json_object_boolean_true_add(json_path, "multipath");
9141 else
9142 vty_out(vty, ", multipath");
9143 }
50e05855 9144
05864da7
DS
9145 // Mark the bestpath(s)
9146 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9147 first_as = aspath_get_first_as(attr->aspath);
718e3744 9148
05864da7
DS
9149 if (json_paths) {
9150 if (!json_bestpath)
9151 json_bestpath = json_object_new_object();
9152 json_object_int_add(json_bestpath, "bestpathFromAs",
9153 first_as);
9154 } else {
9155 if (first_as)
9156 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9157 else
05864da7 9158 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9159 }
05864da7 9160 }
718e3744 9161
05864da7
DS
9162 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9163 if (json_paths) {
9164 if (!json_bestpath)
9165 json_bestpath = json_object_new_object();
9166 json_object_boolean_true_add(json_bestpath, "overall");
9167 json_object_string_add(
9168 json_bestpath, "selectionReason",
9169 bgp_path_selection_reason2str(bn->reason));
9170 } else {
9171 vty_out(vty, ", best");
9172 vty_out(vty, " (%s)",
9173 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9174 }
05864da7 9175 }
718e3744 9176
05864da7
DS
9177 if (json_bestpath)
9178 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9179
05864da7
DS
9180 if (!json_paths)
9181 vty_out(vty, "\n");
9182
9183 /* Line 4 display Community */
9184 if (attr->community) {
9185 if (json_paths) {
9186 if (!attr->community->json)
9187 community_str(attr->community, true);
9188 json_object_lock(attr->community->json);
9189 json_object_object_add(json_path, "community",
9190 attr->community->json);
9191 } else {
9192 vty_out(vty, " Community: %s\n",
9193 attr->community->str);
d62a17ae 9194 }
05864da7 9195 }
718e3744 9196
05864da7
DS
9197 /* Line 5 display Extended-community */
9198 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9199 if (json_paths) {
9200 json_ext_community = json_object_new_object();
9201 json_object_string_add(json_ext_community, "string",
9202 attr->ecommunity->str);
9203 json_object_object_add(json_path, "extendedCommunity",
9204 json_ext_community);
d62a17ae 9205 } else {
05864da7
DS
9206 vty_out(vty, " Extended Community: %s\n",
9207 attr->ecommunity->str);
d62a17ae 9208 }
05864da7 9209 }
718e3744 9210
05864da7
DS
9211 /* Line 6 display Large community */
9212 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9213 if (json_paths) {
9214 if (!attr->lcommunity->json)
9215 lcommunity_str(attr->lcommunity, true);
9216 json_object_lock(attr->lcommunity->json);
9217 json_object_object_add(json_path, "largeCommunity",
9218 attr->lcommunity->json);
9219 } else {
9220 vty_out(vty, " Large Community: %s\n",
9221 attr->lcommunity->str);
d62a17ae 9222 }
05864da7 9223 }
718e3744 9224
05864da7
DS
9225 /* Line 7 display Originator, Cluster-id */
9226 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9227 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9228 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9229 if (json_paths)
05864da7
DS
9230 json_object_string_add(
9231 json_path, "originatorId",
9232 inet_ntoa(attr->originator_id));
d62a17ae 9233 else
05864da7
DS
9234 vty_out(vty, " Originator: %s",
9235 inet_ntoa(attr->originator_id));
d62a17ae 9236 }
856ca177 9237
05864da7
DS
9238 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9239 int i;
d62a17ae 9240
9241 if (json_paths) {
05864da7
DS
9242 json_cluster_list = json_object_new_object();
9243 json_cluster_list_list =
9244 json_object_new_array();
9245
9246 for (i = 0; i < attr->cluster->length / 4;
9247 i++) {
9248 json_string = json_object_new_string(
9249 inet_ntoa(attr->cluster
9250 ->list[i]));
9251 json_object_array_add(
9252 json_cluster_list_list,
9253 json_string);
9254 }
718e3744 9255
05864da7
DS
9256 /*
9257 * struct cluster_list does not have
9258 * "str" variable like aspath and community
9259 * do. Add this someday if someone asks
9260 * for it.
9261 * json_object_string_add(json_cluster_list,
9262 * "string", attr->cluster->str);
9263 */
9264 json_object_object_add(json_cluster_list,
9265 "list",
9266 json_cluster_list_list);
9267 json_object_object_add(json_path, "clusterList",
9268 json_cluster_list);
0dc8ee70 9269 } else {
05864da7
DS
9270 vty_out(vty, ", Cluster list: ");
9271
9272 for (i = 0; i < attr->cluster->length / 4;
9273 i++) {
9274 vty_out(vty, "%s ",
9275 inet_ntoa(attr->cluster
9276 ->list[i]));
9277 }
0dc8ee70 9278 }
d62a17ae 9279 }
718e3744 9280
d62a17ae 9281 if (!json_paths)
9282 vty_out(vty, "\n");
05864da7 9283 }
d62a17ae 9284
05864da7 9285 if (path->extra && path->extra->damp_info)
a935f597 9286 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9287
05864da7
DS
9288 /* Remote Label */
9289 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9290 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9291 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9292
05864da7
DS
9293 if (json_paths)
9294 json_object_int_add(json_path, "remoteLabel", label);
9295 else
9296 vty_out(vty, " Remote label: %d\n", label);
9297 }
d62a17ae 9298
e496b420
HS
9299 /* Remote SID */
9300 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9301 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9302 if (json_paths)
9303 json_object_string_add(json_path, "remoteSid", buf);
9304 else
9305 vty_out(vty, " Remote SID: %s\n", buf);
9306 }
9307
05864da7
DS
9308 /* Label Index */
9309 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9310 if (json_paths)
9311 json_object_int_add(json_path, "labelIndex",
9312 attr->label_index);
9313 else
9314 vty_out(vty, " Label Index: %d\n",
9315 attr->label_index);
9316 }
d62a17ae 9317
05864da7
DS
9318 /* Line 8 display Addpath IDs */
9319 if (path->addpath_rx_id
9320 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9321 if (json_paths) {
9322 json_object_int_add(json_path, "addpathRxId",
9323 path->addpath_rx_id);
d62a17ae 9324
05864da7
DS
9325 /* Keep backwards compatibility with the old API
9326 * by putting TX All's ID in the old field
9327 */
9328 json_object_int_add(
9329 json_path, "addpathTxId",
9330 path->tx_addpath
9331 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9332
05864da7
DS
9333 /* ... but create a specific field for each
9334 * strategy
9335 */
9336 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9337 json_object_int_add(
9338 json_path,
9339 bgp_addpath_names(i)->id_json_name,
9340 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9341 }
05864da7
DS
9342 } else {
9343 vty_out(vty, " AddPath ID: RX %u, ",
9344 path->addpath_rx_id);
d62a17ae 9345
05864da7 9346 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9347 }
05864da7 9348 }
520d5d76 9349
05864da7
DS
9350 /* If we used addpath to TX a non-bestpath we need to display
9351 * "Advertised to" on a path-by-path basis
9352 */
9353 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9354 first = 1;
dcc68b5e 9355
05864da7
DS
9356 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9357 addpath_capable =
9358 bgp_addpath_encode_tx(peer, afi, safi);
9359 has_adj = bgp_adj_out_lookup(
9360 peer, path->net,
9361 bgp_addpath_id_for_peer(peer, afi, safi,
9362 &path->tx_addpath));
9363
9364 if ((addpath_capable && has_adj)
9365 || (!addpath_capable && has_adj
9366 && CHECK_FLAG(path->flags,
9367 BGP_PATH_SELECTED))) {
9368 if (json_path && !json_adv_to)
9369 json_adv_to = json_object_new_object();
dcc68b5e 9370
05864da7
DS
9371 route_vty_out_advertised_to(
9372 vty, peer, &first,
9373 " Advertised to:", json_adv_to);
d62a17ae 9374 }
9375 }
718e3744 9376
05864da7
DS
9377 if (json_path) {
9378 if (json_adv_to) {
9379 json_object_object_add(
9380 json_path, "advertisedTo", json_adv_to);
d62a17ae 9381 }
05864da7
DS
9382 } else {
9383 if (!first) {
9384 vty_out(vty, "\n");
d62a17ae 9385 }
9386 }
05864da7 9387 }
b05a1c8b 9388
05864da7
DS
9389 /* Line 9 display Uptime */
9390 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9391 if (json_paths) {
9392 json_last_update = json_object_new_object();
9393 json_object_int_add(json_last_update, "epoch", tbuf);
9394 json_object_string_add(json_last_update, "string",
9395 ctime(&tbuf));
9396 json_object_object_add(json_path, "lastUpdate",
9397 json_last_update);
9398 } else
9399 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9400
05864da7
DS
9401 /* Line 10 display PMSI tunnel attribute, if present */
9402 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9403 const char *str =
9404 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9405 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9406
05864da7
DS
9407 if (json_paths) {
9408 json_pmsi = json_object_new_object();
9409 json_object_string_add(json_pmsi, "tunnelType", str);
9410 json_object_int_add(json_pmsi, "label",
9411 label2vni(&attr->label));
9412 json_object_object_add(json_path, "pmsi", json_pmsi);
9413 } else
9414 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9415 str, label2vni(&attr->label));
d62a17ae 9416 }
f1aa5d8a 9417
d62a17ae 9418 /* We've constructed the json object for this path, add it to the json
9419 * array of paths
9420 */
9421 if (json_paths) {
9422 if (json_nexthop_global || json_nexthop_ll) {
9423 json_nexthops = json_object_new_array();
f1aa5d8a 9424
d62a17ae 9425 if (json_nexthop_global)
9426 json_object_array_add(json_nexthops,
9427 json_nexthop_global);
f1aa5d8a 9428
d62a17ae 9429 if (json_nexthop_ll)
9430 json_object_array_add(json_nexthops,
9431 json_nexthop_ll);
f1aa5d8a 9432
d62a17ae 9433 json_object_object_add(json_path, "nexthops",
9434 json_nexthops);
9435 }
9436
9437 json_object_object_add(json_path, "peer", json_peer);
9438 json_object_array_add(json_paths, json_path);
05864da7 9439 }
b366b518
BB
9440}
9441
96ade3ed 9442#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9443#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9444#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9445
d62a17ae 9446static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9447 const char *prefix_list_str, afi_t afi,
9448 safi_t safi, enum bgp_show_type type);
9449static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9450 const char *filter, afi_t afi, safi_t safi,
9451 enum bgp_show_type type);
9452static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9453 const char *rmap_str, afi_t afi, safi_t safi,
9454 enum bgp_show_type type);
9455static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9456 const char *com, int exact, afi_t afi,
9457 safi_t safi);
9458static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9459 const char *prefix, afi_t afi, safi_t safi,
9460 enum bgp_show_type type);
a4d82a8a 9461static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9462 afi_t afi, safi_t safi, enum bgp_show_type type,
9463 bool use_json);
7f323236
DW
9464static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9465 const char *comstr, int exact, afi_t afi,
9f049418 9466 safi_t safi, bool use_json);
d62a17ae 9467
1ae44dfc
LB
9468
9469static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9470 struct bgp_table *table, enum bgp_show_type type,
9f049418 9471 void *output_arg, bool use_json, char *rd,
a4d82a8a
PZ
9472 int is_last, unsigned long *output_cum,
9473 unsigned long *total_cum,
9386b588 9474 unsigned long *json_header_depth)
d62a17ae 9475{
40381db7 9476 struct bgp_path_info *pi;
d62a17ae 9477 struct bgp_node *rn;
9478 int header = 1;
9479 int display;
1ae44dfc
LB
9480 unsigned long output_count = 0;
9481 unsigned long total_count = 0;
d62a17ae 9482 struct prefix *p;
d62a17ae 9483 char buf2[BUFSIZ];
9484 json_object *json_paths = NULL;
9485 int first = 1;
9486
1ae44dfc
LB
9487 if (output_cum && *output_cum != 0)
9488 header = 0;
9489
9386b588 9490 if (use_json && !*json_header_depth) {
d62a17ae 9491 vty_out(vty,
66f80d74 9492 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
01eced22
AD
9493 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9494 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9495 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9496 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9497 ? VRF_DEFAULT_NAME
9498 : bgp->name,
01eced22
AD
9499 table->version, inet_ntoa(bgp->router_id),
9500 bgp->default_local_pref, bgp->as);
9386b588
PZ
9501 *json_header_depth = 2;
9502 if (rd) {
445c2480 9503 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9504 ++*json_header_depth;
9505 }
d62a17ae 9506 }
718e3744 9507
445c2480
DS
9508 if (use_json && rd) {
9509 vty_out(vty, " \"%s\" : { ", rd);
9510 }
9511
d62a17ae 9512 /* Start processing of routes. */
98ce9a06 9513 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6f94b685
DS
9514 pi = bgp_node_get_bgp_path_info(rn);
9515 if (pi == NULL)
98ce9a06 9516 continue;
d62a17ae 9517
98ce9a06 9518 display = 0;
98ce9a06
DS
9519 if (use_json)
9520 json_paths = json_object_new_array();
9521 else
9522 json_paths = NULL;
d62a17ae 9523
6f94b685 9524 for (; pi; pi = pi->next) {
98ce9a06
DS
9525 total_count++;
9526 if (type == bgp_show_type_flap_statistics
9527 || type == bgp_show_type_flap_neighbor
9528 || type == bgp_show_type_dampend_paths
9529 || type == bgp_show_type_damp_neighbor) {
40381db7 9530 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9531 continue;
9532 }
9533 if (type == bgp_show_type_regexp) {
9534 regex_t *regex = output_arg;
d62a17ae 9535
40381db7 9536 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9537 == REG_NOMATCH)
9538 continue;
9539 }
9540 if (type == bgp_show_type_prefix_list) {
9541 struct prefix_list *plist = output_arg;
d62a17ae 9542
98ce9a06
DS
9543 if (prefix_list_apply(plist, &rn->p)
9544 != PREFIX_PERMIT)
9545 continue;
9546 }
9547 if (type == bgp_show_type_filter_list) {
9548 struct as_list *as_list = output_arg;
d62a17ae 9549
40381db7 9550 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9551 != AS_FILTER_PERMIT)
9552 continue;
9553 }
9554 if (type == bgp_show_type_route_map) {
9555 struct route_map *rmap = output_arg;
9b6d8fcf 9556 struct bgp_path_info path;
98ce9a06 9557 struct attr dummy_attr;
b68885f9 9558 route_map_result_t ret;
d62a17ae 9559
6f4f49b2 9560 dummy_attr = *pi->attr;
d62a17ae 9561
40381db7 9562 path.peer = pi->peer;
9b6d8fcf 9563 path.attr = &dummy_attr;
d62a17ae 9564
a4d82a8a 9565 ret = route_map_apply(rmap, &rn->p, RMAP_BGP,
9b6d8fcf 9566 &path);
98ce9a06
DS
9567 if (ret == RMAP_DENYMATCH)
9568 continue;
9569 }
9570 if (type == bgp_show_type_neighbor
9571 || type == bgp_show_type_flap_neighbor
9572 || type == bgp_show_type_damp_neighbor) {
9573 union sockunion *su = output_arg;
9574
40381db7
DS
9575 if (pi->peer == NULL
9576 || pi->peer->su_remote == NULL
9577 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9578 continue;
9579 }
9580 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9581 uint32_t destination;
d62a17ae 9582
98ce9a06
DS
9583 destination = ntohl(rn->p.u.prefix4.s_addr);
9584 if (IN_CLASSC(destination)
9585 && rn->p.prefixlen == 24)
9586 continue;
9587 if (IN_CLASSB(destination)
9588 && rn->p.prefixlen == 16)
9589 continue;
9590 if (IN_CLASSA(destination)
9591 && rn->p.prefixlen == 8)
9592 continue;
9593 }
9594 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9595 p = output_arg;
98ce9a06
DS
9596 if (!prefix_match(p, &rn->p))
9597 continue;
9598 }
9599 if (type == bgp_show_type_community_all) {
40381db7 9600 if (!pi->attr->community)
98ce9a06
DS
9601 continue;
9602 }
9603 if (type == bgp_show_type_community) {
9604 struct community *com = output_arg;
d62a17ae 9605
40381db7
DS
9606 if (!pi->attr->community
9607 || !community_match(pi->attr->community,
98ce9a06
DS
9608 com))
9609 continue;
9610 }
9611 if (type == bgp_show_type_community_exact) {
9612 struct community *com = output_arg;
d62a17ae 9613
40381db7
DS
9614 if (!pi->attr->community
9615 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9616 continue;
9617 }
9618 if (type == bgp_show_type_community_list) {
9619 struct community_list *list = output_arg;
d62a17ae 9620
40381db7 9621 if (!community_list_match(pi->attr->community,
a4d82a8a 9622 list))
98ce9a06
DS
9623 continue;
9624 }
a4d82a8a 9625 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9626 struct community_list *list = output_arg;
d62a17ae 9627
98ce9a06 9628 if (!community_list_exact_match(
40381db7 9629 pi->attr->community, list))
98ce9a06
DS
9630 continue;
9631 }
9632 if (type == bgp_show_type_lcommunity) {
9633 struct lcommunity *lcom = output_arg;
d62a17ae 9634
40381db7
DS
9635 if (!pi->attr->lcommunity
9636 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9637 lcom))
9638 continue;
9639 }
36a206db 9640
9641 if (type == bgp_show_type_lcommunity_exact) {
9642 struct lcommunity *lcom = output_arg;
9643
9644 if (!pi->attr->lcommunity
9645 || !lcommunity_cmp(pi->attr->lcommunity,
9646 lcom))
9647 continue;
9648 }
98ce9a06
DS
9649 if (type == bgp_show_type_lcommunity_list) {
9650 struct community_list *list = output_arg;
d62a17ae 9651
40381db7 9652 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9653 list))
98ce9a06
DS
9654 continue;
9655 }
36a206db 9656 if (type
9657 == bgp_show_type_lcommunity_list_exact) {
9658 struct community_list *list = output_arg;
9659
9660 if (!lcommunity_list_exact_match(
9661 pi->attr->lcommunity, list))
9662 continue;
9663 }
98ce9a06 9664 if (type == bgp_show_type_lcommunity_all) {
40381db7 9665 if (!pi->attr->lcommunity)
98ce9a06
DS
9666 continue;
9667 }
9668 if (type == bgp_show_type_dampend_paths
9669 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9670 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9671 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9672 continue;
9673 }
9674
9675 if (!use_json && header) {
996c9314 9676 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 9677 ", local router ID is %s, vrf id ",
98ce9a06
DS
9678 table->version,
9679 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9680 if (bgp->vrf_id == VRF_UNKNOWN)
9681 vty_out(vty, "%s", VRFID_NONE_STR);
9682 else
9683 vty_out(vty, "%u", bgp->vrf_id);
9684 vty_out(vty, "\n");
01eced22
AD
9685 vty_out(vty, "Default local pref %u, ",
9686 bgp->default_local_pref);
9687 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9688 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9689 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9690 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9691 if (type == bgp_show_type_dampend_paths
9692 || type == bgp_show_type_damp_neighbor)
98ce9a06 9693 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9694 else if (type == bgp_show_type_flap_statistics
9695 || type == bgp_show_type_flap_neighbor)
98ce9a06 9696 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9697 else
98ce9a06
DS
9698 vty_out(vty, BGP_SHOW_HEADER);
9699 header = 0;
d62a17ae 9700 }
98ce9a06
DS
9701 if (rd != NULL && !display && !output_count) {
9702 if (!use_json)
9703 vty_out(vty,
9704 "Route Distinguisher: %s\n",
9705 rd);
d62a17ae 9706 }
98ce9a06
DS
9707 if (type == bgp_show_type_dampend_paths
9708 || type == bgp_show_type_damp_neighbor)
a935f597 9709 damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9710 safi, use_json, json_paths);
98ce9a06
DS
9711 else if (type == bgp_show_type_flap_statistics
9712 || type == bgp_show_type_flap_neighbor)
a935f597 9713 flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
a4d82a8a 9714 safi, use_json, json_paths);
98ce9a06 9715 else
40381db7 9716 route_vty_out(vty, &rn->p, pi, display, safi,
a4d82a8a 9717 json_paths);
98ce9a06 9718 display++;
d62a17ae 9719 }
9720
98ce9a06
DS
9721 if (display) {
9722 output_count++;
9723 if (!use_json)
9724 continue;
9725
9726 p = &rn->p;
625d2931
PG
9727 /* encode prefix */
9728 if (p->family == AF_FLOWSPEC) {
9729 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
9730
9731 bgp_fs_nlri_get_string((unsigned char *)
9732 p->u.prefix_flowspec.ptr,
9733 p->u.prefix_flowspec
9734 .prefixlen,
9735 retstr,
9736 NLRI_STRING_FORMAT_MIN,
9737 NULL);
9738 if (first)
9739 vty_out(vty, "\"%s/%d\": ",
9740 retstr,
9741 p->u.prefix_flowspec.prefixlen);
9742 else
9743 vty_out(vty, ",\"%s/%d\": ",
9744 retstr,
9745 p->u.prefix_flowspec.prefixlen);
9746 } else {
9747 prefix2str(p, buf2, sizeof(buf2));
9748 if (first)
9749 vty_out(vty, "\"%s\": ", buf2);
9750 else
9751 vty_out(vty, ",\"%s\": ", buf2);
9752 }
98ce9a06 9753 vty_out(vty, "%s",
f4ec52f7
DA
9754 json_object_to_json_string_ext(
9755 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 9756 json_object_free(json_paths);
449feb8e 9757 json_paths = NULL;
98ce9a06 9758 first = 0;
1f83ed02
DS
9759 } else
9760 json_object_free(json_paths);
98ce9a06
DS
9761 }
9762
1ae44dfc
LB
9763 if (output_cum) {
9764 output_count += *output_cum;
9765 *output_cum = output_count;
9766 }
9767 if (total_cum) {
9768 total_count += *total_cum;
9769 *total_cum = total_count;
9770 }
d62a17ae 9771 if (use_json) {
9386b588 9772 if (rd) {
a4d82a8a 9773 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
9774 }
9775 if (is_last) {
a4d82a8a
PZ
9776 unsigned long i;
9777 for (i = 0; i < *json_header_depth; ++i)
9778 vty_out(vty, " } ");
faf6559a 9779 vty_out(vty, "\n");
9386b588 9780 }
d62a17ae 9781 } else {
1ae44dfc
LB
9782 if (is_last) {
9783 /* No route is displayed */
9784 if (output_count == 0) {
9785 if (type == bgp_show_type_normal)
9786 vty_out(vty,
9787 "No BGP prefixes displayed, %ld exist\n",
9788 total_count);
9789 } else
d62a17ae 9790 vty_out(vty,
1ae44dfc
LB
9791 "\nDisplayed %ld routes and %ld total paths\n",
9792 output_count, total_count);
9793 }
d62a17ae 9794 }
718e3744 9795
d62a17ae 9796 return CMD_SUCCESS;
718e3744 9797}
9798
1ae44dfc
LB
9799int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
9800 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 9801 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc
LB
9802{
9803 struct bgp_node *rn, *next;
9804 unsigned long output_cum = 0;
9805 unsigned long total_cum = 0;
9386b588 9806 unsigned long json_header_depth = 0;
67009e22 9807 struct bgp_table *itable;
0136788c
LB
9808 bool show_msg;
9809
9810 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc
LB
9811
9812 for (rn = bgp_table_top(table); rn; rn = next) {
9813 next = bgp_route_next(rn);
9814 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
9815 continue;
67009e22
DS
9816
9817 itable = bgp_node_get_bgp_table_info(rn);
9818 if (itable != NULL) {
1ae44dfc 9819 struct prefix_rd prd;
06b9f471 9820 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
9821
9822 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 9823 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22
DS
9824 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
9825 use_json, rd, next == NULL, &output_cum,
9826 &total_cum, &json_header_depth);
0136788c
LB
9827 if (next == NULL)
9828 show_msg = false;
1ae44dfc
LB
9829 }
9830 }
0136788c
LB
9831 if (show_msg) {
9832 if (output_cum == 0)
9833 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
9834 total_cum);
9835 else
9836 vty_out(vty,
9837 "\nDisplayed %ld routes and %ld total paths\n",
9838 output_cum, total_cum);
9839 }
1ae44dfc
LB
9840 return CMD_SUCCESS;
9841}
d62a17ae 9842static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
9f049418 9843 enum bgp_show_type type, void *output_arg, bool use_json)
fee0f4c6 9844{
d62a17ae 9845 struct bgp_table *table;
9386b588 9846 unsigned long json_header_depth = 0;
fee0f4c6 9847
d62a17ae 9848 if (bgp == NULL) {
9849 bgp = bgp_get_default();
9850 }
fee0f4c6 9851
d62a17ae 9852 if (bgp == NULL) {
9853 if (!use_json)
9854 vty_out(vty, "No BGP process is configured\n");
16307668
RW
9855 else
9856 vty_out(vty, "{}\n");
d62a17ae 9857 return CMD_WARNING;
9858 }
4dd6177e 9859
1ae44dfc 9860 table = bgp->rib[afi][safi];
d62a17ae 9861 /* use MPLS and ENCAP specific shows until they are merged */
9862 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
9863 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
9864 output_arg, use_json);
d62a17ae 9865 }
dba3c1d3
PG
9866
9867 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
9868 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
9869 output_arg, use_json,
9870 1, NULL, NULL);
9871 }
d62a17ae 9872 /* labeled-unicast routes live in the unicast table */
9873 else if (safi == SAFI_LABELED_UNICAST)
9874 safi = SAFI_UNICAST;
fee0f4c6 9875
1ae44dfc 9876 return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
9386b588 9877 NULL, 1, NULL, NULL, &json_header_depth);
fee0f4c6 9878}
9879
d62a17ae 9880static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
9f049418 9881 safi_t safi, bool use_json)
f186de26 9882{
d62a17ae 9883 struct listnode *node, *nnode;
9884 struct bgp *bgp;
9885 int is_first = 1;
9f049418 9886 bool route_output = false;
f186de26 9887
d62a17ae 9888 if (use_json)
9889 vty_out(vty, "{\n");
9f689658 9890
d62a17ae 9891 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 9892 route_output = true;
d62a17ae 9893 if (use_json) {
9894 if (!is_first)
9895 vty_out(vty, ",\n");
9896 else
9897 is_first = 0;
9898
9899 vty_out(vty, "\"%s\":",
9900 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9901 ? VRF_DEFAULT_NAME
d62a17ae 9902 : bgp->name);
9903 } else {
9904 vty_out(vty, "\nInstance %s:\n",
9905 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 9906 ? VRF_DEFAULT_NAME
d62a17ae 9907 : bgp->name);
9908 }
9909 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
9910 use_json);
9911 }
9f689658 9912
d62a17ae 9913 if (use_json)
9914 vty_out(vty, "}\n");
9f049418
DS
9915 else if (!route_output)
9916 vty_out(vty, "%% BGP instance not found\n");
f186de26 9917}
9918
718e3744 9919/* Header of detailed BGP route information */
d62a17ae 9920void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9921 struct bgp_node *rn, struct prefix_rd *prd,
9922 afi_t afi, safi_t safi, json_object *json)
9923{
40381db7 9924 struct bgp_path_info *pi;
d62a17ae 9925 struct prefix *p;
9926 struct peer *peer;
9927 struct listnode *node, *nnode;
06b9f471 9928 char buf1[RD_ADDRSTRLEN];
d62a17ae 9929 char buf2[INET6_ADDRSTRLEN];
d62a17ae 9930 char buf3[EVPN_ROUTE_STRLEN];
0291c246 9931 char prefix_str[BUFSIZ];
d62a17ae 9932 int count = 0;
9933 int best = 0;
9934 int suppress = 0;
c5f1e1b2
C
9935 int accept_own = 0;
9936 int route_filter_translated_v4 = 0;
9937 int route_filter_v4 = 0;
9938 int route_filter_translated_v6 = 0;
9939 int route_filter_v6 = 0;
9940 int llgr_stale = 0;
9941 int no_llgr = 0;
9942 int accept_own_nexthop = 0;
9943 int blackhole = 0;
d62a17ae 9944 int no_export = 0;
9945 int no_advertise = 0;
9946 int local_as = 0;
c5f1e1b2 9947 int no_peer = 0;
d62a17ae 9948 int first = 1;
9949 int has_valid_label = 0;
9950 mpls_label_t label = 0;
9951 json_object *json_adv_to = NULL;
9bedbb1e 9952
d62a17ae 9953 p = &rn->p;
9954 has_valid_label = bgp_is_valid_label(&rn->local_label);
9955
9956 if (has_valid_label)
9957 label = label_pton(&rn->local_label);
9958
44c69747 9959 if (safi == SAFI_EVPN) {
d62a17ae 9960
44c69747 9961 if (!json) {
d62a17ae 9962 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 9963 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 9964 : "", prd ? ":" : "",
d62a17ae 9965 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
9966 buf3, sizeof(buf3)));
9967 } else {
9968 json_object_string_add(json, "rd",
9969 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
9970 "");
9971 bgp_evpn_route2json((struct prefix_evpn *)p, json);
9972 }
9973 } else {
9974 if (!json) {
d62a17ae 9975 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
9976 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
9977 ? prefix_rd2str(prd, buf1,
9978 sizeof(buf1))
9979 : ""),
d62a17ae 9980 safi == SAFI_MPLS_VPN ? ":" : "",
9981 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 9982 INET6_ADDRSTRLEN),
d62a17ae 9983 p->prefixlen);
cd1964ff 9984
44c69747
LK
9985 } else
9986 json_object_string_add(json, "prefix",
9987 prefix2str(p, prefix_str, sizeof(prefix_str)));
9988 }
9989
9990 if (has_valid_label) {
9991 if (json)
9992 json_object_int_add(json, "localLabel", label);
9993 else
d62a17ae 9994 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
9995 }
9996
9997 if (!json)
d62a17ae 9998 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 9999 vty_out(vty, "not allocated\n");
718e3744 10000
6f94b685 10001 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
d62a17ae 10002 count++;
40381db7 10003 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10004 best = count;
40381db7 10005 if (pi->extra && pi->extra->suppress)
d62a17ae 10006 suppress = 1;
cee9c031 10007
40381db7 10008 if (pi->attr->community == NULL)
cee9c031
QY
10009 continue;
10010
10011 no_advertise += community_include(
40381db7
DS
10012 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10013 no_export += community_include(pi->attr->community,
cee9c031 10014 COMMUNITY_NO_EXPORT);
40381db7 10015 local_as += community_include(pi->attr->community,
cee9c031 10016 COMMUNITY_LOCAL_AS);
40381db7 10017 accept_own += community_include(pi->attr->community,
cee9c031
QY
10018 COMMUNITY_ACCEPT_OWN);
10019 route_filter_translated_v4 += community_include(
40381db7 10020 pi->attr->community,
cee9c031
QY
10021 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10022 route_filter_translated_v6 += community_include(
40381db7 10023 pi->attr->community,
cee9c031
QY
10024 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10025 route_filter_v4 += community_include(
40381db7 10026 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10027 route_filter_v6 += community_include(
40381db7
DS
10028 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10029 llgr_stale += community_include(pi->attr->community,
cee9c031 10030 COMMUNITY_LLGR_STALE);
40381db7 10031 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10032 COMMUNITY_NO_LLGR);
10033 accept_own_nexthop +=
40381db7 10034 community_include(pi->attr->community,
cee9c031 10035 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10036 blackhole += community_include(pi->attr->community,
cee9c031 10037 COMMUNITY_BLACKHOLE);
40381db7 10038 no_peer += community_include(pi->attr->community,
cee9c031 10039 COMMUNITY_NO_PEER);
d62a17ae 10040 }
718e3744 10041 }
718e3744 10042
d62a17ae 10043 if (!json) {
10044 vty_out(vty, "Paths: (%d available", count);
10045 if (best) {
10046 vty_out(vty, ", best #%d", best);
b84060bb
PG
10047 if (safi == SAFI_UNICAST) {
10048 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10049 vty_out(vty, ", table %s",
10050 VRF_DEFAULT_NAME);
10051 else
10052 vty_out(vty, ", vrf %s",
10053 bgp->name);
10054 }
d62a17ae 10055 } else
10056 vty_out(vty, ", no best path");
10057
c5f1e1b2
C
10058 if (accept_own)
10059 vty_out(vty,
10060 ", accept own local route exported and imported in different VRF");
10061 else if (route_filter_translated_v4)
10062 vty_out(vty,
10063 ", mark translated RTs for VPNv4 route filtering");
10064 else if (route_filter_v4)
10065 vty_out(vty,
10066 ", attach RT as-is for VPNv4 route filtering");
10067 else if (route_filter_translated_v6)
10068 vty_out(vty,
10069 ", mark translated RTs for VPNv6 route filtering");
10070 else if (route_filter_v6)
10071 vty_out(vty,
10072 ", attach RT as-is for VPNv6 route filtering");
10073 else if (llgr_stale)
10074 vty_out(vty,
10075 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10076 else if (no_llgr)
10077 vty_out(vty,
10078 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10079 else if (accept_own_nexthop)
10080 vty_out(vty,
10081 ", accept local nexthop");
10082 else if (blackhole)
10083 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10084 else if (no_export)
10085 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10086 else if (no_advertise)
10087 vty_out(vty, ", not advertised to any peer");
d62a17ae 10088 else if (local_as)
10089 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10090 else if (no_peer)
10091 vty_out(vty,
10092 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10093
10094 if (suppress)
10095 vty_out(vty,
10096 ", Advertisements suppressed by an aggregate.");
10097 vty_out(vty, ")\n");
10098 }
718e3744 10099
d62a17ae 10100 /* If we are not using addpath then we can display Advertised to and
10101 * that will
10102 * show what peers we advertised the bestpath to. If we are using
10103 * addpath
10104 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10105 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10106 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10107 if (bgp_adj_out_lookup(peer, rn, 0)) {
10108 if (json && !json_adv_to)
10109 json_adv_to = json_object_new_object();
10110
10111 route_vty_out_advertised_to(
10112 vty, peer, &first,
10113 " Advertised to non peer-group peers:\n ",
10114 json_adv_to);
10115 }
10116 }
10117
10118 if (json) {
10119 if (json_adv_to) {
10120 json_object_object_add(json, "advertisedTo",
10121 json_adv_to);
10122 }
10123 } else {
10124 if (first)
10125 vty_out(vty, " Not advertised to any peer");
10126 vty_out(vty, "\n");
10127 }
10128 }
718e3744 10129}
10130
44c69747
LK
10131static void bgp_show_path_info(struct prefix_rd *pfx_rd,
10132 struct bgp_node *bgp_node, struct vty *vty,
10133 struct bgp *bgp, afi_t afi,
10134 safi_t safi, json_object *json,
10135 enum bgp_path_type pathtype, int *display)
10136{
10137 struct bgp_path_info *pi;
10138 int header = 1;
10139 char rdbuf[RD_ADDRSTRLEN];
10140 json_object *json_header = NULL;
10141 json_object *json_paths = NULL;
10142
10143 for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
10144 pi = pi->next) {
10145
10146 if (json && !json_paths) {
10147 /* Instantiate json_paths only if path is valid */
10148 json_paths = json_object_new_array();
10149 if (pfx_rd) {
10150 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10151 json_header = json_object_new_object();
10152 } else
10153 json_header = json;
10154 }
10155
10156 if (header) {
10157 route_vty_out_detail_header(
10158 vty, bgp, bgp_node, pfx_rd,
10159 AFI_IP, safi, json_header);
10160 header = 0;
10161 }
10162 (*display)++;
10163
10164 if (pathtype == BGP_PATH_SHOW_ALL
10165 || (pathtype == BGP_PATH_SHOW_BESTPATH
10166 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10167 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10168 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10169 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10170 route_vty_out_detail(vty, bgp, bgp_node,
10171 pi, AFI_IP, safi,
10172 json_paths);
10173 }
10174
10175 if (json && json_paths) {
10176 json_object_object_add(json_header, "paths", json_paths);
10177
10178 if (pfx_rd)
10179 json_object_object_add(json, rdbuf, json_header);
10180 }
10181}
10182
718e3744 10183/* Display specified route of BGP table. */
d62a17ae 10184static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10185 struct bgp_table *rib, const char *ip_str,
10186 afi_t afi, safi_t safi,
10187 struct prefix_rd *prd, int prefix_check,
9f049418 10188 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10189{
10190 int ret;
d62a17ae 10191 int display = 0;
10192 struct prefix match;
10193 struct bgp_node *rn;
10194 struct bgp_node *rm;
d62a17ae 10195 struct bgp_table *table;
10196 json_object *json = NULL;
10197 json_object *json_paths = NULL;
10198
10199 /* Check IP address argument. */
10200 ret = str2prefix(ip_str, &match);
10201 if (!ret) {
10202 vty_out(vty, "address is malformed\n");
10203 return CMD_WARNING;
10204 }
718e3744 10205
d62a17ae 10206 match.family = afi2family(afi);
b05a1c8b 10207
44c69747 10208 if (use_json)
d62a17ae 10209 json = json_object_new_object();
718e3744 10210
44c69747 10211 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
d62a17ae 10212 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
10213 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10214 continue;
67009e22
DS
10215 table = bgp_node_get_bgp_table_info(rn);
10216 if (!table)
ea47320b 10217 continue;
d62a17ae 10218
ea47320b
DL
10219 if ((rm = bgp_node_match(table, &match)) == NULL)
10220 continue;
d62a17ae 10221
ea47320b
DL
10222 if (prefix_check
10223 && rm->p.prefixlen != match.prefixlen) {
10224 bgp_unlock_node(rm);
10225 continue;
10226 }
d62a17ae 10227
44c69747
LK
10228 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10229 vty, bgp, afi, safi, json,
10230 pathtype, &display);
10231
10232 bgp_unlock_node(rm);
10233 }
10234 } else if (safi == SAFI_EVPN) {
10235 struct bgp_node *longest_pfx;
10236 bool is_exact_pfxlen_match = FALSE;
10237
10238 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
10239 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10240 continue;
10241 table = bgp_node_get_bgp_table_info(rn);
10242 if (!table)
10243 continue;
10244
10245 longest_pfx = NULL;
10246 is_exact_pfxlen_match = FALSE;
10247 /*
10248 * Search through all the prefixes for a match. The
10249 * pfx's are enumerated in ascending order of pfxlens.
10250 * So, the last pfx match is the longest match. Set
10251 * is_exact_pfxlen_match when we get exact pfxlen match
10252 */
10253 for (rm = bgp_table_top(table); rm;
10254 rm = bgp_route_next(rm)) {
10255 /*
10256 * Get prefixlen of the ip-prefix within type5
10257 * evpn route
10258 */
10259 if (evpn_type5_prefix_match(&rm->p,
10260 &match) && rm->info) {
10261 longest_pfx = rm;
10262 int type5_pfxlen =
10263 bgp_evpn_get_type5_prefixlen(&rm->p);
10264 if (type5_pfxlen == match.prefixlen) {
10265 is_exact_pfxlen_match = TRUE;
10266 bgp_unlock_node(rm);
10267 break;
10268 }
d62a17ae 10269 }
10270 }
ea47320b 10271
44c69747
LK
10272 if (!longest_pfx)
10273 continue;
10274
10275 if (prefix_check && !is_exact_pfxlen_match)
10276 continue;
10277
10278 rm = longest_pfx;
10279 bgp_lock_node(rm);
10280
10281 bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
10282 vty, bgp, afi, safi, json,
10283 pathtype, &display);
10284
ea47320b 10285 bgp_unlock_node(rm);
d62a17ae 10286 }
98a9dbc7 10287 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10288 if (use_json)
10289 json_paths = json_object_new_array();
10290
63a0b7a9
PG
10291 display = bgp_flowspec_display_match_per_ip(afi, rib,
10292 &match, prefix_check,
10293 vty,
10294 use_json,
10295 json_paths);
44c69747
LK
10296 if (use_json && display)
10297 json_object_object_add(json, "paths", json_paths);
d62a17ae 10298 } else {
d62a17ae 10299 if ((rn = bgp_node_match(rib, &match)) != NULL) {
10300 if (!prefix_check
10301 || rn->p.prefixlen == match.prefixlen) {
44c69747
LK
10302 bgp_show_path_info(NULL, rn, vty, bgp, afi,
10303 safi, json,
10304 pathtype, &display);
d62a17ae 10305 }
10306
10307 bgp_unlock_node(rn);
10308 }
10309 }
e5eee9af 10310
d62a17ae 10311 if (use_json) {
996c9314 10312 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10313 json, JSON_C_TO_STRING_PRETTY |
10314 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10315 json_object_free(json);
10316 } else {
10317 if (!display) {
10318 vty_out(vty, "%% Network not in table\n");
10319 return CMD_WARNING;
10320 }
10321 }
b05a1c8b 10322
d62a17ae 10323 return CMD_SUCCESS;
718e3744 10324}
10325
fee0f4c6 10326/* Display specified route of Main RIB */
d62a17ae 10327static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10328 afi_t afi, safi_t safi, struct prefix_rd *prd,
10329 int prefix_check, enum bgp_path_type pathtype,
9f049418 10330 bool use_json)
d62a17ae 10331{
9b86009a 10332 if (!bgp) {
d62a17ae 10333 bgp = bgp_get_default();
9b86009a
RW
10334 if (!bgp) {
10335 if (!use_json)
10336 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10337 else
10338 vty_out(vty, "{}\n");
9b86009a
RW
10339 return CMD_WARNING;
10340 }
10341 }
d62a17ae 10342
10343 /* labeled-unicast routes live in the unicast table */
10344 if (safi == SAFI_LABELED_UNICAST)
10345 safi = SAFI_UNICAST;
10346
10347 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10348 afi, safi, prd, prefix_check, pathtype,
10349 use_json);
10350}
10351
10352static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10353 struct cmd_token **argv, bool exact, afi_t afi,
10354 safi_t safi, bool uj)
d62a17ae 10355{
10356 struct lcommunity *lcom;
10357 struct buffer *b;
10358 int i;
10359 char *str;
10360 int first = 0;
10361
10362 b = buffer_new(1024);
10363 for (i = 0; i < argc; i++) {
10364 if (first)
10365 buffer_putc(b, ' ');
10366 else {
10367 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10368 first = 1;
10369 buffer_putstr(b, argv[i]->arg);
10370 }
10371 }
10372 }
10373 buffer_putc(b, '\0');
57d187bc 10374
d62a17ae 10375 str = buffer_getstr(b);
10376 buffer_free(b);
57d187bc 10377
d62a17ae 10378 lcom = lcommunity_str2com(str);
10379 XFREE(MTYPE_TMP, str);
10380 if (!lcom) {
10381 vty_out(vty, "%% Large-community malformed\n");
10382 return CMD_WARNING;
10383 }
57d187bc 10384
36a206db 10385 return bgp_show(vty, bgp, afi, safi,
10386 (exact ? bgp_show_type_lcommunity_exact
10387 : bgp_show_type_lcommunity),
10388 lcom, uj);
57d187bc
JS
10389}
10390
d62a17ae 10391static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10392 const char *lcom, bool exact, afi_t afi,
10393 safi_t safi, bool uj)
57d187bc 10394{
d62a17ae 10395 struct community_list *list;
57d187bc 10396
e237b0d2 10397 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10398 LARGE_COMMUNITY_LIST_MASTER);
10399 if (list == NULL) {
10400 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10401 lcom);
10402 return CMD_WARNING;
10403 }
57d187bc 10404
36a206db 10405 return bgp_show(vty, bgp, afi, safi,
10406 (exact ? bgp_show_type_lcommunity_list_exact
10407 : bgp_show_type_lcommunity_list),
d62a17ae 10408 list, uj);
fee0f4c6 10409}
10410
52951b63
DS
10411DEFUN (show_ip_bgp_large_community_list,
10412 show_ip_bgp_large_community_list_cmd,
36a206db 10413 "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
10414 SHOW_STR
10415 IP_STR
10416 BGP_STR
10417 BGP_INSTANCE_HELP_STR
9bedbb1e 10418 BGP_AFI_HELP_STR
4dd6177e 10419 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10420 "Display routes matching the large-community-list\n"
10421 "large-community-list number\n"
10422 "large-community-list name\n"
36a206db 10423 "Exact match of the large-communities\n"
52951b63
DS
10424 JSON_STR)
10425{
d62a17ae 10426 afi_t afi = AFI_IP6;
10427 safi_t safi = SAFI_UNICAST;
10428 int idx = 0;
36a206db 10429 bool exact_match = 0;
4d678463 10430 struct bgp *bgp = NULL;
9f049418 10431 bool uj = use_json(argc, argv);
d62a17ae 10432
4d678463
KA
10433 if (uj)
10434 argc--;
10435
10436 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10437 &bgp, uj);
10438 if (!idx)
10439 return CMD_WARNING;
d62a17ae 10440
10441 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10442
10443 const char *clist_number_or_name = argv[++idx]->arg;
10444
10445 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10446 exact_match = 1;
10447
10448 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10449 exact_match, afi, safi, uj);
52951b63
DS
10450}
10451DEFUN (show_ip_bgp_large_community,
10452 show_ip_bgp_large_community_cmd,
36a206db 10453 "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
10454 SHOW_STR
10455 IP_STR
10456 BGP_STR
10457 BGP_INSTANCE_HELP_STR
9bedbb1e 10458 BGP_AFI_HELP_STR
4dd6177e 10459 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10460 "Display routes matching the large-communities\n"
10461 "List of large-community numbers\n"
36a206db 10462 "Exact match of the large-communities\n"
52951b63
DS
10463 JSON_STR)
10464{
d62a17ae 10465 afi_t afi = AFI_IP6;
10466 safi_t safi = SAFI_UNICAST;
10467 int idx = 0;
36a206db 10468 bool exact_match = 0;
4d678463 10469 struct bgp *bgp = NULL;
9f049418 10470 bool uj = use_json(argc, argv);
d62a17ae 10471
4d678463
KA
10472 if (uj)
10473 argc--;
10474
10475 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10476 &bgp, uj);
10477 if (!idx)
10478 return CMD_WARNING;
d62a17ae 10479
36a206db 10480 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10481 if (argv_find(argv, argc, "exact-match", &idx))
10482 exact_match = 1;
10483 return bgp_show_lcommunity(vty, bgp, argc, argv,
10484 exact_match, afi, safi, uj);
10485 } else
d62a17ae 10486 return bgp_show(vty, bgp, afi, safi,
10487 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
10488}
10489
d62a17ae 10490static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
10491 safi_t safi);
e01ca200 10492
7b2ff250
DW
10493
10494/* BGP route print out function without JSON */
af462945
DS
10495DEFUN (show_ip_bgp,
10496 show_ip_bgp_cmd,
4dd6177e 10497 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
7b2ff250
DW
10498 <dampening <parameters>\
10499 |route-map WORD\
10500 |prefix-list WORD\
10501 |filter-list WORD\
10502 |statistics\
7b2ff250
DW
10503 |community-list <(1-500)|WORD> [exact-match]\
10504 |A.B.C.D/M longer-prefixes\
10505 |X:X::X:X/M longer-prefixes\
10506 >",
718e3744 10507 SHOW_STR
10508 IP_STR
10509 BGP_STR
a636c635 10510 BGP_INSTANCE_HELP_STR
4f280b15 10511 BGP_AFI_HELP_STR
4dd6177e 10512 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 10513 "Display detailed information about dampening\n"
af462945 10514 "Display detail of configured dampening parameters\n"
a636c635
DW
10515 "Display routes matching the route-map\n"
10516 "A route-map to match on\n"
10517 "Display routes conforming to the prefix-list\n"
8c3deaae 10518 "Prefix-list name\n"
a636c635
DW
10519 "Display routes conforming to the filter-list\n"
10520 "Regular expression access list name\n"
e01ca200 10521 "BGP RIB advertisement statistics\n"
a636c635
DW
10522 "Display routes matching the community-list\n"
10523 "community-list number\n"
10524 "community-list name\n"
10525 "Exact match of the communities\n"
0c7b1b01 10526 "IPv4 prefix\n"
8c3deaae 10527 "Display route and more specific routes\n"
0c7b1b01 10528 "IPv6 prefix\n"
7b2ff250 10529 "Display route and more specific routes\n")
718e3744 10530{
d62a17ae 10531 afi_t afi = AFI_IP6;
10532 safi_t safi = SAFI_UNICAST;
10533 int exact_match = 0;
d62a17ae 10534 struct bgp *bgp = NULL;
10535 int idx = 0;
10536
10537 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10538 &bgp, false);
d62a17ae 10539 if (!idx)
10540 return CMD_WARNING;
10541
d62a17ae 10542 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 10543 if (argv_find(argv, argc, "parameters", &idx))
d62a17ae 10544 return bgp_show_dampening_parameters(vty, afi, safi);
10545 }
c016b6c7 10546
d62a17ae 10547 if (argv_find(argv, argc, "prefix-list", &idx))
10548 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
10549 safi, bgp_show_type_prefix_list);
10550
10551 if (argv_find(argv, argc, "filter-list", &idx))
10552 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
10553 safi, bgp_show_type_filter_list);
10554
10555 if (argv_find(argv, argc, "statistics", &idx))
10556 return bgp_table_stats(vty, bgp, afi, safi);
10557
10558 if (argv_find(argv, argc, "route-map", &idx))
10559 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
10560 safi, bgp_show_type_route_map);
10561
d62a17ae 10562 if (argv_find(argv, argc, "community-list", &idx)) {
10563 const char *clist_number_or_name = argv[++idx]->arg;
10564 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10565 exact_match = 1;
10566 return bgp_show_community_list(vty, bgp, clist_number_or_name,
10567 exact_match, afi, safi);
10568 }
10569 /* prefix-longer */
10570 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10571 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10572 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
10573 safi,
10574 bgp_show_type_prefix_longer);
10575
7b2ff250
DW
10576 return CMD_WARNING;
10577}
10578
10579/* BGP route print out function with JSON */
10580DEFUN (show_ip_bgp_json,
10581 show_ip_bgp_json_cmd,
10582 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
cf4898bc
QY
10583 [cidr-only\
10584 |dampening <flap-statistics|dampened-paths>\
10585 |community [AA:NN|local-AS|no-advertise|no-export\
10586 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10587 |accept-own|accept-own-nexthop|route-filter-v6\
10588 |route-filter-v4|route-filter-translated-v6\
10589 |route-filter-translated-v4] [exact-match]\
10590 ] [json]",
7b2ff250
DW
10591 SHOW_STR
10592 IP_STR
10593 BGP_STR
10594 BGP_INSTANCE_HELP_STR
10595 BGP_AFI_HELP_STR
10596 BGP_SAFI_WITH_LABEL_HELP_STR
10597 "Display only routes with non-natural netmasks\n"
10598 "Display detailed information about dampening\n"
10599 "Display flap statistics of routes\n"
10600 "Display paths suppressed due to dampening\n"
10601 "Display routes matching the communities\n"
d0086e8e
AD
10602 COMMUNITY_AANN_STR
10603 "Do not send outside local AS (well-known community)\n"
10604 "Do not advertise to any peer (well-known community)\n"
10605 "Do not export to next AS (well-known community)\n"
10606 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
10607 "Do not export to any peer (well-known community)\n"
10608 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10609 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10610 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10611 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10612 "Should accept VPN route with local nexthop (well-known community)\n"
10613 "RT VPNv6 route filtering (well-known community)\n"
10614 "RT VPNv4 route filtering (well-known community)\n"
10615 "RT translated VPNv6 route filtering (well-known community)\n"
10616 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 10617 "Exact match of the communities\n"
7b2ff250
DW
10618 JSON_STR)
10619{
10620 afi_t afi = AFI_IP6;
10621 safi_t safi = SAFI_UNICAST;
10622 enum bgp_show_type sh_type = bgp_show_type_normal;
10623 struct bgp *bgp = NULL;
10624 int idx = 0;
d0086e8e 10625 int exact_match = 0;
9f049418
DS
10626 bool uj = use_json(argc, argv);
10627
10628 if (uj)
10629 argc--;
7b2ff250
DW
10630
10631 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10632 &bgp, uj);
7b2ff250
DW
10633 if (!idx)
10634 return CMD_WARNING;
10635
7b2ff250
DW
10636 if (argv_find(argv, argc, "cidr-only", &idx))
10637 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
10638 NULL, uj);
10639
10640 if (argv_find(argv, argc, "dampening", &idx)) {
10641 if (argv_find(argv, argc, "dampened-paths", &idx))
10642 return bgp_show(vty, bgp, afi, safi,
10643 bgp_show_type_dampend_paths, NULL, uj);
10644 else if (argv_find(argv, argc, "flap-statistics", &idx))
10645 return bgp_show(vty, bgp, afi, safi,
10646 bgp_show_type_flap_statistics, NULL,
10647 uj);
10648 }
10649
10650 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 10651 char *maybecomm = NULL;
cf4898bc 10652 char *community = NULL;
d0086e8e 10653
79bc257a
RW
10654 if (idx + 1 < argc) {
10655 if (argv[idx + 1]->type == VARIABLE_TKN)
10656 maybecomm = argv[idx + 1]->arg;
10657 else
10658 maybecomm = argv[idx + 1]->text;
10659 }
10660
cf4898bc
QY
10661 if (maybecomm && !strmatch(maybecomm, "json")
10662 && !strmatch(maybecomm, "exact-match"))
10663 community = maybecomm;
d0086e8e 10664
cf4898bc
QY
10665 if (argv_find(argv, argc, "exact-match", &idx))
10666 exact_match = 1;
d0086e8e 10667
cf4898bc
QY
10668 if (community)
10669 return bgp_show_community(vty, bgp, community,
10670 exact_match, afi, safi, uj);
10671 else
d0086e8e 10672 return (bgp_show(vty, bgp, afi, safi,
cf4898bc
QY
10673 bgp_show_type_community_all, NULL,
10674 uj));
7b2ff250 10675 }
d0086e8e 10676
1ae44dfc 10677 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 10678}
47fc97cc 10679
718e3744 10680DEFUN (show_ip_bgp_route,
10681 show_ip_bgp_route_cmd,
4dd6177e 10682 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 10683 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 10684 SHOW_STR
10685 IP_STR
10686 BGP_STR
a636c635 10687 BGP_INSTANCE_HELP_STR
4f280b15 10688 BGP_AFI_HELP_STR
4dd6177e 10689 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 10690 "Network in the BGP routing table to display\n"
0c7b1b01 10691 "IPv4 prefix\n"
8c3deaae 10692 "Network in the BGP routing table to display\n"
0c7b1b01 10693 "IPv6 prefix\n"
4092b06c 10694 "Display only the bestpath\n"
b05a1c8b 10695 "Display only multipaths\n"
9973d184 10696 JSON_STR)
4092b06c 10697{
d62a17ae 10698 int prefix_check = 0;
ae19d7dd 10699
d62a17ae 10700 afi_t afi = AFI_IP6;
10701 safi_t safi = SAFI_UNICAST;
10702 char *prefix = NULL;
10703 struct bgp *bgp = NULL;
10704 enum bgp_path_type path_type;
9f049418 10705 bool uj = use_json(argc, argv);
b05a1c8b 10706
d62a17ae 10707 int idx = 0;
ae19d7dd 10708
d62a17ae 10709 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10710 &bgp, uj);
d62a17ae 10711 if (!idx)
10712 return CMD_WARNING;
c41247f5 10713
d62a17ae 10714 if (!bgp) {
10715 vty_out(vty,
10716 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10717 return CMD_WARNING;
10718 }
a636c635 10719
d62a17ae 10720 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10721 if (argv_find(argv, argc, "A.B.C.D", &idx)
10722 || argv_find(argv, argc, "X:X::X:X", &idx))
10723 prefix_check = 0;
10724 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
10725 || argv_find(argv, argc, "X:X::X:X/M", &idx))
10726 prefix_check = 1;
10727
10728 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
10729 && afi != AFI_IP6) {
10730 vty_out(vty,
10731 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10732 return CMD_WARNING;
10733 }
10734 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
10735 && afi != AFI_IP) {
10736 vty_out(vty,
10737 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10738 return CMD_WARNING;
10739 }
10740
10741 prefix = argv[idx]->arg;
10742
10743 /* [<bestpath|multipath>] */
10744 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 10745 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 10746 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 10747 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 10748 else
360660c6 10749 path_type = BGP_PATH_SHOW_ALL;
a636c635 10750
d62a17ae 10751 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
10752 path_type, uj);
4092b06c
DS
10753}
10754
8c3deaae
QY
10755DEFUN (show_ip_bgp_regexp,
10756 show_ip_bgp_regexp_cmd,
3e5b31b3 10757 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
10758 SHOW_STR
10759 IP_STR
10760 BGP_STR
b00b230a 10761 BGP_INSTANCE_HELP_STR
4f280b15 10762 BGP_AFI_HELP_STR
4dd6177e 10763 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 10764 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
10765 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10766 JSON_STR)
8c3deaae 10767{
d62a17ae 10768 afi_t afi = AFI_IP6;
10769 safi_t safi = SAFI_UNICAST;
10770 struct bgp *bgp = NULL;
3e5b31b3
DA
10771 bool uj = use_json(argc, argv);
10772 char *regstr = NULL;
8c3deaae 10773
d62a17ae 10774 int idx = 0;
10775 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 10776 &bgp, false);
d62a17ae 10777 if (!idx)
10778 return CMD_WARNING;
8c3deaae 10779
d62a17ae 10780 // get index of regex
3e5b31b3
DA
10781 if (argv_find(argv, argc, "REGEX", &idx))
10782 regstr = argv[idx]->arg;
8c3deaae 10783
5f71d11c 10784 assert(regstr);
3e5b31b3
DA
10785 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
10786 bgp_show_type_regexp, uj);
8c3deaae
QY
10787}
10788
a636c635
DW
10789DEFUN (show_ip_bgp_instance_all,
10790 show_ip_bgp_instance_all_cmd,
4dd6177e 10791 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 10792 SHOW_STR
a636c635 10793 IP_STR
4092b06c 10794 BGP_STR
a636c635 10795 BGP_INSTANCE_ALL_HELP_STR
4f280b15 10796 BGP_AFI_HELP_STR
4dd6177e 10797 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 10798 JSON_STR)
4092b06c 10799{
d62a17ae 10800 afi_t afi = AFI_IP;
10801 safi_t safi = SAFI_UNICAST;
10802 struct bgp *bgp = NULL;
d62a17ae 10803 int idx = 0;
9f049418 10804 bool uj = use_json(argc, argv);
ae19d7dd 10805
d62a17ae 10806 if (uj)
10807 argc--;
e3e29b32 10808
9f049418
DS
10809 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10810 &bgp, uj);
10811 if (!idx)
10812 return CMD_WARNING;
10813
d62a17ae 10814 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
10815 return CMD_SUCCESS;
e3e29b32
LB
10816}
10817
a4d82a8a 10818static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10819 afi_t afi, safi_t safi, enum bgp_show_type type,
10820 bool use_json)
718e3744 10821{
d62a17ae 10822 regex_t *regex;
10823 int rc;
e3e29b32 10824
c3900853 10825 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 10826 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
10827 regstr);
10828 return CMD_WARNING_CONFIG_FAILED;
10829 }
10830
d62a17ae 10831 regex = bgp_regcomp(regstr);
10832 if (!regex) {
10833 vty_out(vty, "Can't compile regexp %s\n", regstr);
10834 return CMD_WARNING;
10835 }
a636c635 10836
3e5b31b3 10837 rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
d62a17ae 10838 bgp_regex_free(regex);
10839 return rc;
e3e29b32
LB
10840}
10841
d62a17ae 10842static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10843 const char *prefix_list_str, afi_t afi,
10844 safi_t safi, enum bgp_show_type type)
e3e29b32 10845{
d62a17ae 10846 struct prefix_list *plist;
718e3744 10847
d62a17ae 10848 plist = prefix_list_lookup(afi, prefix_list_str);
10849 if (plist == NULL) {
10850 vty_out(vty, "%% %s is not a valid prefix-list name\n",
10851 prefix_list_str);
10852 return CMD_WARNING;
10853 }
718e3744 10854
d62a17ae 10855 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
10856}
10857
d62a17ae 10858static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10859 const char *filter, afi_t afi, safi_t safi,
10860 enum bgp_show_type type)
4092b06c 10861{
d62a17ae 10862 struct as_list *as_list;
718e3744 10863
d62a17ae 10864 as_list = as_list_lookup(filter);
10865 if (as_list == NULL) {
10866 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
10867 filter);
10868 return CMD_WARNING;
10869 }
a636c635 10870
d62a17ae 10871 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 10872}
10873
d62a17ae 10874static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10875 const char *rmap_str, afi_t afi, safi_t safi,
10876 enum bgp_show_type type)
718e3744 10877{
d62a17ae 10878 struct route_map *rmap;
bb46e94f 10879
d62a17ae 10880 rmap = route_map_lookup_by_name(rmap_str);
10881 if (!rmap) {
10882 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
10883 return CMD_WARNING;
10884 }
10885
10886 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
10887}
10888
7f323236
DW
10889static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10890 const char *comstr, int exact, afi_t afi,
9f049418 10891 safi_t safi, bool use_json)
d62a17ae 10892{
10893 struct community *com;
d62a17ae 10894 int ret = 0;
10895
7f323236 10896 com = community_str2com(comstr);
d62a17ae 10897 if (!com) {
7f323236 10898 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 10899 return CMD_WARNING;
10900 }
10901
10902 ret = bgp_show(vty, bgp, afi, safi,
10903 (exact ? bgp_show_type_community_exact
10904 : bgp_show_type_community),
d0086e8e 10905 com, use_json);
3c1f53de 10906 community_free(&com);
46c3ce83 10907
d62a17ae 10908 return ret;
718e3744 10909}
10910
d62a17ae 10911static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10912 const char *com, int exact, afi_t afi,
10913 safi_t safi)
50ef26d4 10914{
d62a17ae 10915 struct community_list *list;
50ef26d4 10916
e237b0d2 10917 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 10918 if (list == NULL) {
10919 vty_out(vty, "%% %s is not a valid community-list name\n", com);
10920 return CMD_WARNING;
10921 }
718e3744 10922
d62a17ae 10923 return bgp_show(vty, bgp, afi, safi,
10924 (exact ? bgp_show_type_community_list_exact
10925 : bgp_show_type_community_list),
10926 list, 0);
50ef26d4 10927}
10928
d62a17ae 10929static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10930 const char *prefix, afi_t afi, safi_t safi,
10931 enum bgp_show_type type)
718e3744 10932{
d62a17ae 10933 int ret;
10934 struct prefix *p;
47fc97cc 10935
d62a17ae 10936 p = prefix_new();
95cbbd2a 10937
d62a17ae 10938 ret = str2prefix(prefix, p);
10939 if (!ret) {
10940 vty_out(vty, "%% Malformed Prefix\n");
10941 return CMD_WARNING;
10942 }
47e9b292 10943
d62a17ae 10944 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
63265b5c 10945 prefix_free(&p);
d62a17ae 10946 return ret;
10947}
10948
d62a17ae 10949enum bgp_stats {
10950 BGP_STATS_MAXBITLEN = 0,
10951 BGP_STATS_RIB,
10952 BGP_STATS_PREFIXES,
10953 BGP_STATS_TOTPLEN,
10954 BGP_STATS_UNAGGREGATEABLE,
10955 BGP_STATS_MAX_AGGREGATEABLE,
10956 BGP_STATS_AGGREGATES,
10957 BGP_STATS_SPACE,
10958 BGP_STATS_ASPATH_COUNT,
10959 BGP_STATS_ASPATH_MAXHOPS,
10960 BGP_STATS_ASPATH_TOTHOPS,
10961 BGP_STATS_ASPATH_MAXSIZE,
10962 BGP_STATS_ASPATH_TOTSIZE,
10963 BGP_STATS_ASN_HIGHEST,
10964 BGP_STATS_MAX,
a636c635 10965};
2815e61f 10966
2b64873d 10967static const char *const table_stats_strs[] = {
9d303b37
DL
10968 [BGP_STATS_PREFIXES] = "Total Prefixes",
10969 [BGP_STATS_TOTPLEN] = "Average prefix length",
10970 [BGP_STATS_RIB] = "Total Advertisements",
10971 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
10972 [BGP_STATS_MAX_AGGREGATEABLE] =
10973 "Maximum aggregateable prefixes",
10974 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
10975 [BGP_STATS_SPACE] = "Address space advertised",
10976 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
10977 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
10978 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
10979 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
10980 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
10981 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
10982 [BGP_STATS_MAX] = NULL,
a636c635 10983};
2815e61f 10984
d62a17ae 10985struct bgp_table_stats {
10986 struct bgp_table *table;
10987 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 10988 double total_space;
ff7924f6
PJ
10989};
10990
a636c635
DW
10991#if 0
10992#define TALLY_SIGFIG 100000
10993static unsigned long
10994ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 10995{
a636c635
DW
10996 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
10997 unsigned long res = (newtot * TALLY_SIGFIG) / count;
10998 unsigned long ret = newtot / count;
07d0c4ed 10999
a636c635
DW
11000 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11001 return ret + 1;
11002 else
11003 return ret;
11004}
11005#endif
ff7924f6 11006
9c14ec72
RW
11007static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
11008 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11009{
9c14ec72
RW
11010 struct bgp_node *prn = bgp_node_parent_nolock(rn);
11011 struct bgp_path_info *pi;
d62a17ae 11012
9c14ec72
RW
11013 if (rn == top)
11014 return;
d62a17ae 11015
9c14ec72
RW
11016 if (!bgp_node_has_bgp_path_info_data(rn))
11017 return;
d62a17ae 11018
9c14ec72
RW
11019 ts->counts[BGP_STATS_PREFIXES]++;
11020 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 11021
a636c635
DW
11022#if 0
11023 ts->counts[BGP_STATS_AVGPLEN]
11024 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11025 ts->counts[BGP_STATS_AVGPLEN],
11026 rn->p.prefixlen);
11027#endif
d62a17ae 11028
9c14ec72
RW
11029 /* check if the prefix is included by any other announcements */
11030 while (prn && !bgp_node_has_bgp_path_info_data(prn))
11031 prn = bgp_node_parent_nolock(prn);
d62a17ae 11032
9c14ec72
RW
11033 if (prn == NULL || prn == top) {
11034 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11035 /* announced address space */
11036 if (space)
11037 ts->total_space += pow(2.0, space - rn->p.prefixlen);
11038 } else if (bgp_node_has_bgp_path_info_data(prn))
11039 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11040
9c14ec72
RW
11041
11042 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
11043 ts->counts[BGP_STATS_RIB]++;
11044
05864da7
DS
11045 if (CHECK_FLAG(pi->attr->flag,
11046 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11047 ts->counts[BGP_STATS_AGGREGATES]++;
11048
11049 /* as-path stats */
05864da7 11050 if (pi->attr->aspath) {
9c14ec72
RW
11051 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11052 unsigned int size = aspath_size(pi->attr->aspath);
11053 as_t highest = aspath_highest(pi->attr->aspath);
11054
11055 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11056
11057 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11058 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11059
11060 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11061 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11062
11063 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11064 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11065#if 0
07d0c4ed 11066 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11067 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11068 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11069 hops);
11070 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11071 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11072 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11073 size);
11074#endif
9c14ec72
RW
11075 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11076 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11077 }
11078 }
11079}
11080
11081static int bgp_table_stats_walker(struct thread *t)
11082{
11083 struct bgp_node *rn, *nrn;
11084 struct bgp_node *top;
11085 struct bgp_table_stats *ts = THREAD_ARG(t);
11086 unsigned int space = 0;
11087
11088 if (!(top = bgp_table_top(ts->table)))
11089 return 0;
11090
11091 switch (ts->table->afi) {
11092 case AFI_IP:
11093 space = IPV4_MAX_BITLEN;
11094 break;
11095 case AFI_IP6:
11096 space = IPV6_MAX_BITLEN;
11097 break;
11098 default:
11099 return 0;
11100 }
11101
11102 ts->counts[BGP_STATS_MAXBITLEN] = space;
11103
11104 for (rn = top; rn; rn = bgp_route_next(rn)) {
11105 if (ts->table->safi == SAFI_MPLS_VPN) {
11106 struct bgp_table *table;
11107
11108 table = bgp_node_get_bgp_table_info(rn);
11109 if (!table)
11110 continue;
11111
11112 top = bgp_table_top(table);
11113 for (nrn = bgp_table_top(table); nrn;
11114 nrn = bgp_route_next(nrn))
11115 bgp_table_stats_rn(nrn, top, ts, space);
11116 } else {
11117 bgp_table_stats_rn(rn, top, ts, space);
d62a17ae 11118 }
11119 }
9c14ec72 11120
d62a17ae 11121 return 0;
2815e61f 11122}
ff7924f6 11123
d62a17ae 11124static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11125 safi_t safi)
2815e61f 11126{
d62a17ae 11127 struct bgp_table_stats ts;
11128 unsigned int i;
019386c2 11129
d62a17ae 11130 if (!bgp->rib[afi][safi]) {
11131 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11132 afi, safi);
11133 return CMD_WARNING;
11134 }
019386c2 11135
5cb5f4d0 11136 vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
019386c2 11137
d62a17ae 11138 /* labeled-unicast routes live in the unicast table */
11139 if (safi == SAFI_LABELED_UNICAST)
11140 safi = SAFI_UNICAST;
019386c2 11141
d62a17ae 11142 memset(&ts, 0, sizeof(ts));
11143 ts.table = bgp->rib[afi][safi];
11144 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11145
d62a17ae 11146 for (i = 0; i < BGP_STATS_MAX; i++) {
11147 if (!table_stats_strs[i])
11148 continue;
11149
11150 switch (i) {
a636c635
DW
11151#if 0
11152 case BGP_STATS_ASPATH_AVGHOPS:
11153 case BGP_STATS_ASPATH_AVGSIZE:
11154 case BGP_STATS_AVGPLEN:
11155 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11156 vty_out (vty, "%12.2f",
11157 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11158 break;
11159#endif
d62a17ae 11160 case BGP_STATS_ASPATH_TOTHOPS:
11161 case BGP_STATS_ASPATH_TOTSIZE:
11162 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11163 vty_out(vty, "%12.2f",
11164 ts.counts[i]
11165 ? (float)ts.counts[i]
11166 / (float)ts.counts
11167 [BGP_STATS_ASPATH_COUNT]
11168 : 0);
11169 break;
11170 case BGP_STATS_TOTPLEN:
11171 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11172 vty_out(vty, "%12.2f",
11173 ts.counts[i]
11174 ? (float)ts.counts[i]
11175 / (float)ts.counts
11176 [BGP_STATS_PREFIXES]
11177 : 0);
11178 break;
11179 case BGP_STATS_SPACE:
11180 vty_out(vty, "%-30s: ", table_stats_strs[i]);
8d0ab76d
DL
11181 vty_out(vty, "%12g\n", ts.total_space);
11182
11183 if (afi == AFI_IP6) {
11184 vty_out(vty, "%30s: ", "/32 equivalent ");
11185 vty_out(vty, "%12g\n",
a4d82a8a 11186 ts.total_space * pow(2.0, -128 + 32));
8d0ab76d
DL
11187 vty_out(vty, "%30s: ", "/48 equivalent ");
11188 vty_out(vty, "%12g\n",
a4d82a8a 11189 ts.total_space * pow(2.0, -128 + 48));
8d0ab76d
DL
11190 } else {
11191 vty_out(vty, "%30s: ", "% announced ");
11192 vty_out(vty, "%12.2f\n",
11193 ts.total_space * 100. * pow(2.0, -32));
11194 vty_out(vty, "%30s: ", "/8 equivalent ");
11195 vty_out(vty, "%12.2f\n",
a4d82a8a 11196 ts.total_space * pow(2.0, -32 + 8));
8d0ab76d
DL
11197 vty_out(vty, "%30s: ", "/24 equivalent ");
11198 vty_out(vty, "%12.2f\n",
a4d82a8a 11199 ts.total_space * pow(2.0, -32 + 24));
8d0ab76d 11200 }
d62a17ae 11201 break;
11202 default:
11203 vty_out(vty, "%-30s: ", table_stats_strs[i]);
11204 vty_out(vty, "%12llu", ts.counts[i]);
11205 }
ff7924f6 11206
d62a17ae 11207 vty_out(vty, "\n");
11208 }
11209 return CMD_SUCCESS;
11210}
11211
11212enum bgp_pcounts {
11213 PCOUNT_ADJ_IN = 0,
11214 PCOUNT_DAMPED,
11215 PCOUNT_REMOVED,
11216 PCOUNT_HISTORY,
11217 PCOUNT_STALE,
11218 PCOUNT_VALID,
11219 PCOUNT_ALL,
11220 PCOUNT_COUNTED,
11221 PCOUNT_PFCNT, /* the figure we display to users */
11222 PCOUNT_MAX,
a636c635 11223};
718e3744 11224
2b64873d 11225static const char *const pcount_strs[] = {
9d303b37
DL
11226 [PCOUNT_ADJ_IN] = "Adj-in",
11227 [PCOUNT_DAMPED] = "Damped",
11228 [PCOUNT_REMOVED] = "Removed",
11229 [PCOUNT_HISTORY] = "History",
11230 [PCOUNT_STALE] = "Stale",
11231 [PCOUNT_VALID] = "Valid",
11232 [PCOUNT_ALL] = "All RIB",
11233 [PCOUNT_COUNTED] = "PfxCt counted",
11234 [PCOUNT_PFCNT] = "Useable",
11235 [PCOUNT_MAX] = NULL,
a636c635 11236};
718e3744 11237
d62a17ae 11238struct peer_pcounts {
11239 unsigned int count[PCOUNT_MAX];
11240 const struct peer *peer;
11241 const struct bgp_table *table;
54317cba 11242 safi_t safi;
a636c635 11243};
47fc97cc 11244
54317cba
JW
11245static void bgp_peer_count_proc(struct bgp_node *rn,
11246 struct peer_pcounts *pc)
d62a17ae 11247{
54317cba
JW
11248 const struct bgp_adj_in *ain;
11249 const struct bgp_path_info *pi;
d62a17ae 11250 const struct peer *peer = pc->peer;
11251
54317cba
JW
11252 for (ain = rn->adj_in; ain; ain = ain->next)
11253 if (ain->peer == peer)
11254 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 11255
54317cba 11256 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 11257
54317cba
JW
11258 if (pi->peer != peer)
11259 continue;
d62a17ae 11260
54317cba 11261 pc->count[PCOUNT_ALL]++;
d62a17ae 11262
54317cba
JW
11263 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
11264 pc->count[PCOUNT_DAMPED]++;
11265 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
11266 pc->count[PCOUNT_HISTORY]++;
11267 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
11268 pc->count[PCOUNT_REMOVED]++;
11269 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
11270 pc->count[PCOUNT_STALE]++;
11271 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
11272 pc->count[PCOUNT_VALID]++;
11273 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11274 pc->count[PCOUNT_PFCNT]++;
11275
11276 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
11277 pc->count[PCOUNT_COUNTED]++;
11278 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
11279 flog_err(
11280 EC_LIB_DEVELOPMENT,
11281 "Attempting to count but flags say it is unusable");
11282 } else {
40381db7 11283 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
11284 flog_err(
11285 EC_LIB_DEVELOPMENT,
11286 "Not counted but flags say we should");
d62a17ae 11287 }
11288 }
54317cba
JW
11289}
11290
11291static int bgp_peer_count_walker(struct thread *t)
11292{
11293 struct bgp_node *rn, *rm;
11294 const struct bgp_table *table;
11295 struct peer_pcounts *pc = THREAD_ARG(t);
11296
11297 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
11298 || pc->safi == SAFI_EVPN) {
11299 /* Special handling for 2-level routing tables. */
11300 for (rn = bgp_table_top(pc->table); rn;
11301 rn = bgp_route_next(rn)) {
11302 table = bgp_node_get_bgp_table_info(rn);
11303 if (table != NULL)
11304 for (rm = bgp_table_top(table); rm;
11305 rm = bgp_route_next(rm))
11306 bgp_peer_count_proc(rm, pc);
11307 }
11308 } else
11309 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
11310 bgp_peer_count_proc(rn, pc);
11311
d62a17ae 11312 return 0;
718e3744 11313}
11314
d62a17ae 11315static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 11316 safi_t safi, bool use_json)
856ca177 11317{
d62a17ae 11318 struct peer_pcounts pcounts = {.peer = peer};
11319 unsigned int i;
11320 json_object *json = NULL;
11321 json_object *json_loop = NULL;
856ca177 11322
d62a17ae 11323 if (use_json) {
11324 json = json_object_new_object();
11325 json_loop = json_object_new_object();
11326 }
718e3744 11327
d62a17ae 11328 if (!peer || !peer->bgp || !peer->afc[afi][safi]
11329 || !peer->bgp->rib[afi][safi]) {
11330 if (use_json) {
11331 json_object_string_add(
11332 json, "warning",
11333 "No such neighbor or address family");
11334 vty_out(vty, "%s\n", json_object_to_json_string(json));
11335 json_object_free(json);
11336 } else
11337 vty_out(vty, "%% No such neighbor or address family\n");
11338
11339 return CMD_WARNING;
11340 }
2a71e9ce 11341
d62a17ae 11342 memset(&pcounts, 0, sizeof(pcounts));
11343 pcounts.peer = peer;
11344 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 11345 pcounts.safi = safi;
d62a17ae 11346
11347 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
11348 * stats for the thread-walk (i.e. ensure this can't be blamed on
11349 * on just vty_read()).
11350 */
d62a17ae 11351 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
11352
11353 if (use_json) {
11354 json_object_string_add(json, "prefixCountsFor", peer->host);
11355 json_object_string_add(json, "multiProtocol",
5cb5f4d0 11356 get_afi_safi_str(afi, safi, true));
d62a17ae 11357 json_object_int_add(json, "pfxCounter",
11358 peer->pcount[afi][safi]);
11359
11360 for (i = 0; i < PCOUNT_MAX; i++)
11361 json_object_int_add(json_loop, pcount_strs[i],
11362 pcounts.count[i]);
11363
11364 json_object_object_add(json, "ribTableWalkCounters", json_loop);
11365
11366 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11367 json_object_string_add(json, "pfxctDriftFor",
11368 peer->host);
11369 json_object_string_add(
11370 json, "recommended",
11371 "Please report this bug, with the above command output");
11372 }
996c9314
LB
11373 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11374 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11375 json_object_free(json);
11376 } else {
11377
11378 if (peer->hostname
892fedb6 11379 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 11380 vty_out(vty, "Prefix counts for %s/%s, %s\n",
11381 peer->hostname, peer->host,
5cb5f4d0 11382 get_afi_safi_str(afi, safi, false));
d62a17ae 11383 } else {
11384 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 11385 get_afi_safi_str(afi, safi, false));
d62a17ae 11386 }
11387
a0a87037 11388 vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]);
d62a17ae 11389 vty_out(vty, "\nCounts from RIB table walk:\n\n");
11390
11391 for (i = 0; i < PCOUNT_MAX; i++)
11392 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
11393 pcounts.count[i]);
11394
11395 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
11396 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
11397 vty_out(vty,
11398 "Please report this bug, with the above command output\n");
11399 }
11400 }
11401
11402 return CMD_SUCCESS;
718e3744 11403}
11404
a636c635
DW
11405DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
11406 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 11407 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 11408 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 11409 SHOW_STR
11410 IP_STR
11411 BGP_STR
8386ac43 11412 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
11413 BGP_AFI_HELP_STR
11414 BGP_SAFI_HELP_STR
0b16f239
DS
11415 "Detailed information on TCP and BGP neighbor connections\n"
11416 "Neighbor to display information about\n"
11417 "Neighbor to display information about\n"
91d37724 11418 "Neighbor on BGP configured interface\n"
a636c635 11419 "Display detailed prefix count information\n"
9973d184 11420 JSON_STR)
0b16f239 11421{
d62a17ae 11422 afi_t afi = AFI_IP6;
11423 safi_t safi = SAFI_UNICAST;
11424 struct peer *peer;
11425 int idx = 0;
11426 struct bgp *bgp = NULL;
9f049418
DS
11427 bool uj = use_json(argc, argv);
11428
11429 if (uj)
11430 argc--;
856ca177 11431
d62a17ae 11432 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11433 &bgp, uj);
d62a17ae 11434 if (!idx)
11435 return CMD_WARNING;
0b16f239 11436
d62a17ae 11437 argv_find(argv, argc, "neighbors", &idx);
11438 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
11439 if (!peer)
11440 return CMD_WARNING;
bb46e94f 11441
29c8d9da 11442 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 11443}
0b16f239 11444
d6902373
PG
11445#ifdef KEEP_OLD_VPN_COMMANDS
11446DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
11447 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
11448 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
11449 SHOW_STR
11450 IP_STR
11451 BGP_STR
d6902373 11452 BGP_VPNVX_HELP_STR
91d37724 11453 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
11454 "Detailed information on TCP and BGP neighbor connections\n"
11455 "Neighbor to display information about\n"
11456 "Neighbor to display information about\n"
91d37724 11457 "Neighbor on BGP configured interface\n"
a636c635 11458 "Display detailed prefix count information\n"
9973d184 11459 JSON_STR)
a636c635 11460{
d62a17ae 11461 int idx_peer = 6;
11462 struct peer *peer;
9f049418 11463 bool uj = use_json(argc, argv);
a636c635 11464
d62a17ae 11465 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
11466 if (!peer)
11467 return CMD_WARNING;
11468
11469 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
11470}
11471
d6902373
PG
11472DEFUN (show_ip_bgp_vpn_all_route_prefix,
11473 show_ip_bgp_vpn_all_route_prefix_cmd,
11474 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
11475 SHOW_STR
11476 IP_STR
11477 BGP_STR
d6902373 11478 BGP_VPNVX_HELP_STR
91d37724
QY
11479 "Display information about all VPNv4 NLRIs\n"
11480 "Network in the BGP routing table to display\n"
3a2d747c 11481 "Network in the BGP routing table to display\n"
9973d184 11482 JSON_STR)
91d37724 11483{
d62a17ae 11484 int idx = 0;
11485 char *network = NULL;
11486 struct bgp *bgp = bgp_get_default();
11487 if (!bgp) {
11488 vty_out(vty, "Can't find default instance\n");
11489 return CMD_WARNING;
11490 }
87e34b58 11491
d62a17ae 11492 if (argv_find(argv, argc, "A.B.C.D", &idx))
11493 network = argv[idx]->arg;
11494 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
11495 network = argv[idx]->arg;
11496 else {
11497 vty_out(vty, "Unable to figure out Network\n");
11498 return CMD_WARNING;
11499 }
87e34b58 11500
d62a17ae 11501 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 11502 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 11503}
d6902373 11504#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 11505
44c69747
LK
11506DEFUN (show_bgp_l2vpn_evpn_route_prefix,
11507 show_bgp_l2vpn_evpn_route_prefix_cmd,
11508 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 11509 SHOW_STR
4c63a661
PG
11510 BGP_STR
11511 L2VPN_HELP_STR
11512 EVPN_HELP_STR
44c69747
LK
11513 "Network in the BGP routing table to display\n"
11514 "Network in the BGP routing table to display\n"
4c63a661
PG
11515 "Network in the BGP routing table to display\n"
11516 "Network in the BGP routing table to display\n"
11517 JSON_STR)
11518{
d62a17ae 11519 int idx = 0;
11520 char *network = NULL;
44c69747 11521 int prefix_check = 0;
a636c635 11522
44c69747
LK
11523 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
11524 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 11525 network = argv[idx]->arg;
44c69747 11526 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 11527 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 11528 network = argv[idx]->arg;
44c69747
LK
11529 prefix_check = 1;
11530 } else {
d62a17ae 11531 vty_out(vty, "Unable to figure out Network\n");
11532 return CMD_WARNING;
11533 }
44c69747
LK
11534 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
11535 prefix_check, BGP_PATH_SHOW_ALL,
11536 use_json(argc, argv));
d62a17ae 11537}
11538
11539static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11540 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11541 const char *rmap_name, bool use_json,
6392aaa6 11542 json_object *json)
d62a17ae 11543{
11544 struct bgp_table *table;
11545 struct bgp_adj_in *ain;
11546 struct bgp_adj_out *adj;
11547 unsigned long output_count;
11548 unsigned long filtered_count;
11549 struct bgp_node *rn;
11550 int header1 = 1;
11551 struct bgp *bgp;
11552 int header2 = 1;
11553 struct attr attr;
11554 int ret;
11555 struct update_subgroup *subgrp;
11556 json_object *json_scode = NULL;
11557 json_object *json_ocode = NULL;
11558 json_object *json_ar = NULL;
11559 struct peer_af *paf;
f99def61 11560 bool route_filtered;
d62a17ae 11561
11562 if (use_json) {
11563 json_scode = json_object_new_object();
11564 json_ocode = json_object_new_object();
11565 json_ar = json_object_new_object();
11566
11567 json_object_string_add(json_scode, "suppressed", "s");
11568 json_object_string_add(json_scode, "damped", "d");
11569 json_object_string_add(json_scode, "history", "h");
11570 json_object_string_add(json_scode, "valid", "*");
11571 json_object_string_add(json_scode, "best", ">");
11572 json_object_string_add(json_scode, "multipath", "=");
11573 json_object_string_add(json_scode, "internal", "i");
11574 json_object_string_add(json_scode, "ribFailure", "r");
11575 json_object_string_add(json_scode, "stale", "S");
11576 json_object_string_add(json_scode, "removed", "R");
11577
11578 json_object_string_add(json_ocode, "igp", "i");
11579 json_object_string_add(json_ocode, "egp", "e");
11580 json_object_string_add(json_ocode, "incomplete", "?");
11581 }
a636c635 11582
d62a17ae 11583 bgp = peer->bgp;
a636c635 11584
d62a17ae 11585 if (!bgp) {
11586 if (use_json) {
11587 json_object_string_add(json, "alert", "no BGP");
11588 vty_out(vty, "%s\n", json_object_to_json_string(json));
11589 json_object_free(json);
11590 } else
11591 vty_out(vty, "%% No bgp\n");
11592 return;
11593 }
a636c635 11594
c512a642
EDP
11595 /* labeled-unicast routes live in the unicast table */
11596 if (safi == SAFI_LABELED_UNICAST)
11597 table = bgp->rib[afi][SAFI_UNICAST];
11598 else
11599 table = bgp->rib[afi][safi];
d62a17ae 11600
11601 output_count = filtered_count = 0;
11602 subgrp = peer_subgroup(peer, afi, safi);
11603
6392aaa6 11604 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 11605 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
11606 if (use_json) {
11607 json_object_int_add(json, "bgpTableVersion",
11608 table->version);
11609 json_object_string_add(json, "bgpLocalRouterId",
11610 inet_ntoa(bgp->router_id));
01eced22
AD
11611 json_object_int_add(json, "defaultLocPrf",
11612 bgp->default_local_pref);
11613 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 11614 json_object_object_add(json, "bgpStatusCodes",
11615 json_scode);
11616 json_object_object_add(json, "bgpOriginCodes",
11617 json_ocode);
07d0c4ed
DA
11618 json_object_string_add(
11619 json, "bgpOriginatingDefaultNetwork",
11620 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11621 } else {
996c9314 11622 vty_out(vty, "BGP table version is %" PRIu64
9df8b37c 11623 ", local router ID is %s, vrf id ",
d62a17ae 11624 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
11625 if (bgp->vrf_id == VRF_UNKNOWN)
11626 vty_out(vty, "%s", VRFID_NONE_STR);
11627 else
11628 vty_out(vty, "%u", bgp->vrf_id);
11629 vty_out(vty, "\n");
01eced22
AD
11630 vty_out(vty, "Default local pref %u, ",
11631 bgp->default_local_pref);
11632 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 11633 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11634 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 11635 vty_out(vty, BGP_SHOW_OCODE_HEADER);
11636
07d0c4ed
DA
11637 vty_out(vty, "Originating default network %s\n\n",
11638 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 11639 }
11640 header1 = 0;
11641 }
a636c635 11642
d62a17ae 11643 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6392aaa6
PM
11644 if (type == bgp_show_adj_route_received
11645 || type == bgp_show_adj_route_filtered) {
d62a17ae 11646 for (ain = rn->adj_in; ain; ain = ain->next) {
05864da7 11647 if (ain->peer != peer)
ea47320b 11648 continue;
6392aaa6 11649
ea47320b
DL
11650 if (header1) {
11651 if (use_json) {
11652 json_object_int_add(
60466a63 11653 json, "bgpTableVersion",
ea47320b
DL
11654 0);
11655 json_object_string_add(
11656 json,
11657 "bgpLocalRouterId",
11658 inet_ntoa(
11659 bgp->router_id));
01eced22
AD
11660 json_object_int_add(json,
11661 "defaultLocPrf",
11662 bgp->default_local_pref);
11663 json_object_int_add(json,
11664 "localAS", bgp->as);
ea47320b 11665 json_object_object_add(
60466a63 11666 json, "bgpStatusCodes",
ea47320b
DL
11667 json_scode);
11668 json_object_object_add(
60466a63 11669 json, "bgpOriginCodes",
ea47320b
DL
11670 json_ocode);
11671 } else {
11672 vty_out(vty,
9df8b37c 11673 "BGP table version is 0, local router ID is %s, vrf id ",
ea47320b 11674 inet_ntoa(
9df8b37c
PZ
11675 bgp->router_id));
11676 if (bgp->vrf_id == VRF_UNKNOWN)
11677 vty_out(vty, "%s",
11678 VRFID_NONE_STR);
11679 else
11680 vty_out(vty, "%u",
11681 bgp->vrf_id);
11682 vty_out(vty, "\n");
01eced22
AD
11683 vty_out(vty,
11684 "Default local pref %u, ",
11685 bgp->default_local_pref);
11686 vty_out(vty, "local AS %u\n",
11687 bgp->as);
ea47320b
DL
11688 vty_out(vty,
11689 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11690 vty_out(vty,
11691 BGP_SHOW_NCODE_HEADER);
ea47320b
DL
11692 vty_out(vty,
11693 BGP_SHOW_OCODE_HEADER);
d62a17ae 11694 }
ea47320b
DL
11695 header1 = 0;
11696 }
11697 if (header2) {
11698 if (!use_json)
11699 vty_out(vty, BGP_SHOW_HEADER);
11700 header2 = 0;
11701 }
6392aaa6 11702
6f4f49b2 11703 attr = *ain->attr;
f99def61
AD
11704 route_filtered = false;
11705
11706 /* Filter prefix using distribute list,
11707 * filter list or prefix list
11708 */
11709 if ((bgp_input_filter(peer, &rn->p, &attr, afi,
11710 safi)) == FILTER_DENY)
11711 route_filtered = true;
11712
11713 /* Filter prefix using route-map */
6392aaa6 11714 ret = bgp_input_modifier(peer, &rn->p, &attr,
196c6b09
LK
11715 afi, safi, rmap_name, NULL, 0,
11716 NULL);
6392aaa6 11717
13c8e163
AD
11718 if (type == bgp_show_adj_route_filtered &&
11719 !route_filtered && ret != RMAP_DENY) {
b755861b 11720 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11721 continue;
d62a17ae 11722 }
6392aaa6 11723
13c8e163
AD
11724 if (type == bgp_show_adj_route_received &&
11725 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
11726 filtered_count++;
11727
11728 route_vty_out_tmp(vty, &rn->p, &attr, safi,
11729 use_json, json_ar);
b755861b 11730 bgp_attr_undup(&attr, ain->attr);
6392aaa6 11731 output_count++;
d62a17ae 11732 }
6392aaa6 11733 } else if (type == bgp_show_adj_route_advertised) {
a79c04e7 11734 RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
924c3f6a 11735 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 11736 if (paf->peer != peer || !adj->attr)
924c3f6a 11737 continue;
d62a17ae 11738
924c3f6a
DS
11739 if (header1) {
11740 if (use_json) {
11741 json_object_int_add(
11742 json,
11743 "bgpTableVersion",
11744 table->version);
11745 json_object_string_add(
11746 json,
11747 "bgpLocalRouterId",
11748 inet_ntoa(
11749 bgp->router_id));
01eced22
AD
11750 json_object_int_add(
11751 json, "defaultLocPrf",
11752 bgp->default_local_pref
11753 );
11754 json_object_int_add(
11755 json, "localAS",
11756 bgp->as);
924c3f6a
DS
11757 json_object_object_add(
11758 json,
11759 "bgpStatusCodes",
11760 json_scode);
11761 json_object_object_add(
11762 json,
11763 "bgpOriginCodes",
11764 json_ocode);
11765 } else {
11766 vty_out(vty,
11767 "BGP table version is %" PRIu64
9df8b37c 11768 ", local router ID is %s, vrf id ",
924c3f6a
DS
11769 table->version,
11770 inet_ntoa(
11771 bgp->router_id));
9df8b37c
PZ
11772 if (bgp->vrf_id ==
11773 VRF_UNKNOWN)
11774 vty_out(vty,
11775 "%s",
11776 VRFID_NONE_STR);
11777 else
11778 vty_out(vty,
11779 "%u",
11780 bgp->vrf_id);
11781 vty_out(vty, "\n");
01eced22
AD
11782 vty_out(vty,
11783 "Default local pref %u, ",
11784 bgp->default_local_pref
11785 );
11786 vty_out(vty,
11787 "local AS %u\n",
11788 bgp->as);
924c3f6a
DS
11789 vty_out(vty,
11790 BGP_SHOW_SCODE_HEADER);
9df8b37c
PZ
11791 vty_out(vty,
11792 BGP_SHOW_NCODE_HEADER);
924c3f6a
DS
11793 vty_out(vty,
11794 BGP_SHOW_OCODE_HEADER);
a2addae8 11795 }
924c3f6a
DS
11796 header1 = 0;
11797 }
924c3f6a
DS
11798 if (header2) {
11799 if (!use_json)
11800 vty_out(vty,
11801 BGP_SHOW_HEADER);
11802 header2 = 0;
11803 }
d62a17ae 11804
6f4f49b2 11805 attr = *adj->attr;
b755861b
PM
11806 ret = bgp_output_modifier(
11807 peer, &rn->p, &attr, afi, safi,
11808 rmap_name);
f46d8e1e 11809
b755861b
PM
11810 if (ret != RMAP_DENY) {
11811 route_vty_out_tmp(vty, &rn->p,
11812 &attr, safi,
11813 use_json,
11814 json_ar);
11815 output_count++;
11816 } else {
11817 filtered_count++;
a2addae8 11818 }
b755861b
PM
11819
11820 bgp_attr_undup(&attr, adj->attr);
924c3f6a 11821 }
d62a17ae 11822 }
11823 }
d62a17ae 11824
d62a17ae 11825 if (use_json) {
6392aaa6
PM
11826 json_object_object_add(json, "advertisedRoutes", json_ar);
11827 json_object_int_add(json, "totalPrefixCounter", output_count);
11828 json_object_int_add(json, "filteredPrefixCounter",
11829 filtered_count);
11830
996c9314
LB
11831 vty_out(vty, "%s\n", json_object_to_json_string_ext(
11832 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 11833 json_object_free(json);
6392aaa6
PM
11834 } else if (output_count > 0) {
11835 if (filtered_count > 0)
11836 vty_out(vty,
11837 "\nTotal number of prefixes %ld (%ld filtered)\n",
11838 output_count, filtered_count);
11839 else
11840 vty_out(vty, "\nTotal number of prefixes %ld\n",
11841 output_count);
d62a17ae 11842 }
a636c635 11843}
2a71e9ce 11844
d62a17ae 11845static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 11846 safi_t safi, enum bgp_show_adj_route_type type,
9f049418 11847 const char *rmap_name, bool use_json)
0b16f239 11848{
d62a17ae 11849 json_object *json = NULL;
0b16f239 11850
d62a17ae 11851 if (use_json)
11852 json = json_object_new_object();
0b16f239 11853
d62a17ae 11854 if (!peer || !peer->afc[afi][safi]) {
11855 if (use_json) {
11856 json_object_string_add(
11857 json, "warning",
11858 "No such neighbor or address family");
11859 vty_out(vty, "%s\n", json_object_to_json_string(json));
11860 json_object_free(json);
11861 } else
11862 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 11863
d62a17ae 11864 return CMD_WARNING;
11865 }
11866
6392aaa6
PM
11867 if ((type == bgp_show_adj_route_received
11868 || type == bgp_show_adj_route_filtered)
d62a17ae 11869 && !CHECK_FLAG(peer->af_flags[afi][safi],
11870 PEER_FLAG_SOFT_RECONFIG)) {
11871 if (use_json) {
11872 json_object_string_add(
11873 json, "warning",
11874 "Inbound soft reconfiguration not enabled");
11875 vty_out(vty, "%s\n", json_object_to_json_string(json));
11876 json_object_free(json);
11877 } else
11878 vty_out(vty,
11879 "%% Inbound soft reconfiguration not enabled\n");
11880
11881 return CMD_WARNING;
11882 }
0b16f239 11883
6392aaa6 11884 show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json);
0b16f239 11885
d62a17ae 11886 return CMD_SUCCESS;
a636c635 11887}
50ef26d4 11888
a636c635
DW
11889DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
11890 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 11891 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
6392aaa6 11892 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
718e3744 11893 SHOW_STR
11894 IP_STR
11895 BGP_STR
a636c635 11896 BGP_INSTANCE_HELP_STR
7395a2c9 11897 BGP_AFI_HELP_STR
4dd6177e 11898 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 11899 "Detailed information on TCP and BGP neighbor connections\n"
11900 "Neighbor to display information about\n"
11901 "Neighbor to display information about\n"
91d37724 11902 "Neighbor on BGP configured interface\n"
a636c635 11903 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
11904 "Display the received routes from neighbor\n"
11905 "Display the filtered routes received from neighbor\n"
a636c635
DW
11906 "Route-map to modify the attributes\n"
11907 "Name of the route map\n"
9973d184 11908 JSON_STR)
718e3744 11909{
d62a17ae 11910 afi_t afi = AFI_IP6;
11911 safi_t safi = SAFI_UNICAST;
11912 char *rmap_name = NULL;
11913 char *peerstr = NULL;
d62a17ae 11914 struct bgp *bgp = NULL;
11915 struct peer *peer;
6392aaa6 11916 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 11917 int idx = 0;
9f049418 11918 bool uj = use_json(argc, argv);
6392aaa6 11919
d62a17ae 11920 if (uj)
11921 argc--;
30a6a167 11922
9f049418
DS
11923 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11924 &bgp, uj);
11925 if (!idx)
11926 return CMD_WARNING;
11927
d62a17ae 11928 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11929 argv_find(argv, argc, "neighbors", &idx);
11930 peerstr = argv[++idx]->arg;
8c3deaae 11931
d62a17ae 11932 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
11933 if (!peer)
11934 return CMD_WARNING;
856ca177 11935
d62a17ae 11936 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
11937 type = bgp_show_adj_route_advertised;
11938 else if (argv_find(argv, argc, "received-routes", &idx))
11939 type = bgp_show_adj_route_received;
11940 else if (argv_find(argv, argc, "filtered-routes", &idx))
11941 type = bgp_show_adj_route_filtered;
11942
d62a17ae 11943 if (argv_find(argv, argc, "route-map", &idx))
11944 rmap_name = argv[++idx]->arg;
95cbbd2a 11945
6392aaa6 11946 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj);
95cbbd2a
ML
11947}
11948
718e3744 11949DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
11950 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 11951 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 11952 SHOW_STR
11953 IP_STR
11954 BGP_STR
8c3deaae
QY
11955 "Address Family\n"
11956 "Address Family\n"
718e3744 11957 "Address Family modifier\n"
11958 "Detailed information on TCP and BGP neighbor connections\n"
11959 "Neighbor to display information about\n"
11960 "Neighbor to display information about\n"
91d37724 11961 "Neighbor on BGP configured interface\n"
718e3744 11962 "Display information received from a BGP neighbor\n"
856ca177 11963 "Display the prefixlist filter\n"
9973d184 11964 JSON_STR)
718e3744 11965{
d62a17ae 11966 afi_t afi = AFI_IP6;
11967 safi_t safi = SAFI_UNICAST;
11968 char *peerstr = NULL;
11969
11970 char name[BUFSIZ];
11971 union sockunion su;
11972 struct peer *peer;
11973 int count, ret;
11974
11975 int idx = 0;
11976
11977 /* show [ip] bgp */
11978 if (argv_find(argv, argc, "ip", &idx))
11979 afi = AFI_IP;
11980 /* [<ipv4|ipv6> [unicast]] */
11981 if (argv_find(argv, argc, "ipv4", &idx))
11982 afi = AFI_IP;
11983 if (argv_find(argv, argc, "ipv6", &idx))
11984 afi = AFI_IP6;
11985 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11986 argv_find(argv, argc, "neighbors", &idx);
11987 peerstr = argv[++idx]->arg;
11988
9f049418 11989 bool uj = use_json(argc, argv);
d62a17ae 11990
11991 ret = str2sockunion(peerstr, &su);
11992 if (ret < 0) {
11993 peer = peer_lookup_by_conf_if(NULL, peerstr);
11994 if (!peer) {
11995 if (uj)
11996 vty_out(vty, "{}\n");
11997 else
11998 vty_out(vty,
11999 "%% Malformed address or name: %s\n",
12000 peerstr);
12001 return CMD_WARNING;
12002 }
12003 } else {
12004 peer = peer_lookup(NULL, &su);
12005 if (!peer) {
12006 if (uj)
12007 vty_out(vty, "{}\n");
12008 else
12009 vty_out(vty, "No peer\n");
12010 return CMD_WARNING;
12011 }
12012 }
718e3744 12013
d62a17ae 12014 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
12015 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12016 if (count) {
12017 if (!uj)
12018 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12019 get_afi_safi_str(afi, safi, false));
d62a17ae 12020 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12021 } else {
12022 if (uj)
12023 vty_out(vty, "{}\n");
12024 else
12025 vty_out(vty, "No functional output\n");
12026 }
718e3744 12027
d62a17ae 12028 return CMD_SUCCESS;
12029}
12030
12031static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12032 afi_t afi, safi_t safi,
9f049418 12033 enum bgp_show_type type, bool use_json)
d62a17ae 12034{
8a893163
DW
12035 /* labeled-unicast routes live in the unicast table */
12036 if (safi == SAFI_LABELED_UNICAST)
12037 safi = SAFI_UNICAST;
12038
d62a17ae 12039 if (!peer || !peer->afc[afi][safi]) {
12040 if (use_json) {
12041 json_object *json_no = NULL;
12042 json_no = json_object_new_object();
12043 json_object_string_add(
12044 json_no, "warning",
12045 "No such neighbor or address family");
12046 vty_out(vty, "%s\n",
12047 json_object_to_json_string(json_no));
12048 json_object_free(json_no);
12049 } else
12050 vty_out(vty, "%% No such neighbor or address family\n");
12051 return CMD_WARNING;
12052 }
47fc97cc 12053
d62a17ae 12054 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 12055}
12056
dba3c1d3
PG
12057DEFUN (show_ip_bgp_flowspec_routes_detailed,
12058 show_ip_bgp_flowspec_routes_detailed_cmd,
12059 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12060 SHOW_STR
12061 IP_STR
12062 BGP_STR
12063 BGP_INSTANCE_HELP_STR
12064 BGP_AFI_HELP_STR
12065 "SAFI Flowspec\n"
12066 "Detailed information on flowspec entries\n"
12067 JSON_STR)
12068{
12069 afi_t afi = AFI_IP;
12070 safi_t safi = SAFI_UNICAST;
12071 struct bgp *bgp = NULL;
12072 int idx = 0;
9f049418
DS
12073 bool uj = use_json(argc, argv);
12074
12075 if (uj)
12076 argc--;
dba3c1d3
PG
12077
12078 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12079 &bgp, uj);
dba3c1d3
PG
12080 if (!idx)
12081 return CMD_WARNING;
12082
9f049418 12083 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj);
dba3c1d3
PG
12084}
12085
718e3744 12086DEFUN (show_ip_bgp_neighbor_routes,
12087 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 12088 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 12089 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 12090 SHOW_STR
12091 IP_STR
12092 BGP_STR
8386ac43 12093 BGP_INSTANCE_HELP_STR
4f280b15 12094 BGP_AFI_HELP_STR
4dd6177e 12095 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12096 "Detailed information on TCP and BGP neighbor connections\n"
12097 "Neighbor to display information about\n"
12098 "Neighbor to display information about\n"
91d37724 12099 "Neighbor on BGP configured interface\n"
2525cf39 12100 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12101 "Display the dampened routes received from neighbor\n"
12102 "Display routes learned from neighbor\n"
9973d184 12103 JSON_STR)
718e3744 12104{
d62a17ae 12105 char *peerstr = NULL;
12106 struct bgp *bgp = NULL;
12107 afi_t afi = AFI_IP6;
12108 safi_t safi = SAFI_UNICAST;
12109 struct peer *peer;
12110 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12111 int idx = 0;
9f049418
DS
12112 bool uj = use_json(argc, argv);
12113
12114 if (uj)
12115 argc--;
bb46e94f 12116
d62a17ae 12117 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12118 &bgp, uj);
d62a17ae 12119 if (!idx)
12120 return CMD_WARNING;
c493f2d8 12121
d62a17ae 12122 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12123 argv_find(argv, argc, "neighbors", &idx);
12124 peerstr = argv[++idx]->arg;
8c3deaae 12125
d62a17ae 12126 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 12127 if (!peer)
d62a17ae 12128 return CMD_WARNING;
bb46e94f 12129
d62a17ae 12130 if (argv_find(argv, argc, "flap-statistics", &idx))
12131 sh_type = bgp_show_type_flap_neighbor;
12132 else if (argv_find(argv, argc, "dampened-routes", &idx))
12133 sh_type = bgp_show_type_damp_neighbor;
12134 else if (argv_find(argv, argc, "routes", &idx))
12135 sh_type = bgp_show_type_neighbor;
2525cf39 12136
d62a17ae 12137 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 12138}
6b0655a2 12139
734b349e 12140struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 12141
d62a17ae 12142struct bgp_distance {
12143 /* Distance value for the IP source prefix. */
d7c0a89a 12144 uint8_t distance;
718e3744 12145
d62a17ae 12146 /* Name of the access-list to be matched. */
12147 char *access_list;
718e3744 12148};
12149
4f280b15
LB
12150DEFUN (show_bgp_afi_vpn_rd_route,
12151 show_bgp_afi_vpn_rd_route_cmd,
d114b977 12152 "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
12153 SHOW_STR
12154 BGP_STR
12155 BGP_AFI_HELP_STR
12156 "Address Family modifier\n"
12157 "Display information for a route distinguisher\n"
12158 "Route Distinguisher\n"
7395a2c9
DS
12159 "Network in the BGP routing table to display\n"
12160 "Network in the BGP routing table to display\n"
12161 JSON_STR)
4f280b15 12162{
d62a17ae 12163 int ret;
12164 struct prefix_rd prd;
12165 afi_t afi = AFI_MAX;
12166 int idx = 0;
4f280b15 12167
ff6566f3
DS
12168 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
12169 vty_out(vty, "%% Malformed Address Family\n");
12170 return CMD_WARNING;
12171 }
12172
d62a17ae 12173 ret = str2prefix_rd(argv[5]->arg, &prd);
12174 if (!ret) {
12175 vty_out(vty, "%% Malformed Route Distinguisher\n");
12176 return CMD_WARNING;
12177 }
ff6566f3 12178
d62a17ae 12179 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 12180 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
12181}
12182
d62a17ae 12183static struct bgp_distance *bgp_distance_new(void)
718e3744 12184{
d62a17ae 12185 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 12186}
12187
d62a17ae 12188static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 12189{
d62a17ae 12190 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 12191}
12192
d62a17ae 12193static int bgp_distance_set(struct vty *vty, const char *distance_str,
12194 const char *ip_str, const char *access_list_str)
718e3744 12195{
d62a17ae 12196 int ret;
12197 afi_t afi;
12198 safi_t safi;
12199 struct prefix p;
d7c0a89a 12200 uint8_t distance;
d62a17ae 12201 struct bgp_node *rn;
12202 struct bgp_distance *bdistance;
718e3744 12203
d62a17ae 12204 afi = bgp_node_afi(vty);
12205 safi = bgp_node_safi(vty);
734b349e 12206
d62a17ae 12207 ret = str2prefix(ip_str, &p);
12208 if (ret == 0) {
12209 vty_out(vty, "Malformed prefix\n");
12210 return CMD_WARNING_CONFIG_FAILED;
12211 }
718e3744 12212
d62a17ae 12213 distance = atoi(distance_str);
718e3744 12214
d62a17ae 12215 /* Get BGP distance node. */
12216 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
5b00b40e 12217 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 12218 if (bdistance)
d62a17ae 12219 bgp_unlock_node(rn);
ca2e160d 12220 else {
d62a17ae 12221 bdistance = bgp_distance_new();
5b00b40e 12222 bgp_node_set_bgp_distance_info(rn, bdistance);
d62a17ae 12223 }
718e3744 12224
d62a17ae 12225 /* Set distance value. */
12226 bdistance->distance = distance;
718e3744 12227
d62a17ae 12228 /* Reset access-list configuration. */
e1b36e13 12229 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12230 if (access_list_str)
12231 bdistance->access_list =
12232 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 12233
d62a17ae 12234 return CMD_SUCCESS;
718e3744 12235}
12236
d62a17ae 12237static int bgp_distance_unset(struct vty *vty, const char *distance_str,
12238 const char *ip_str, const char *access_list_str)
718e3744 12239{
d62a17ae 12240 int ret;
12241 afi_t afi;
12242 safi_t safi;
12243 struct prefix p;
12244 int distance;
12245 struct bgp_node *rn;
12246 struct bgp_distance *bdistance;
718e3744 12247
d62a17ae 12248 afi = bgp_node_afi(vty);
12249 safi = bgp_node_safi(vty);
734b349e 12250
d62a17ae 12251 ret = str2prefix(ip_str, &p);
12252 if (ret == 0) {
12253 vty_out(vty, "Malformed prefix\n");
12254 return CMD_WARNING_CONFIG_FAILED;
12255 }
718e3744 12256
d62a17ae 12257 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
12258 (struct prefix *)&p);
12259 if (!rn) {
12260 vty_out(vty, "Can't find specified prefix\n");
12261 return CMD_WARNING_CONFIG_FAILED;
12262 }
718e3744 12263
5b00b40e 12264 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12265 distance = atoi(distance_str);
1f9a9fff 12266
d62a17ae 12267 if (bdistance->distance != distance) {
12268 vty_out(vty, "Distance does not match configured\n");
12269 return CMD_WARNING_CONFIG_FAILED;
12270 }
718e3744 12271
0a22ddfb 12272 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 12273 bgp_distance_free(bdistance);
718e3744 12274
6f94b685 12275 bgp_node_set_bgp_path_info(rn, NULL);
d62a17ae 12276 bgp_unlock_node(rn);
12277 bgp_unlock_node(rn);
718e3744 12278
d62a17ae 12279 return CMD_SUCCESS;
718e3744 12280}
12281
718e3744 12282/* Apply BGP information to distance method. */
40381db7 12283uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 12284 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 12285{
12286 struct bgp_node *rn;
12287 struct prefix q;
12288 struct peer *peer;
12289 struct bgp_distance *bdistance;
12290 struct access_list *alist;
12291 struct bgp_static *bgp_static;
12292
12293 if (!bgp)
12294 return 0;
12295
40381db7 12296 peer = pinfo->peer;
d62a17ae 12297
7b7d48e5
DS
12298 if (pinfo->attr->distance)
12299 return pinfo->attr->distance;
12300
d62a17ae 12301 /* Check source address. */
12302 sockunion2hostprefix(&peer->su, &q);
12303 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
12304 if (rn) {
5b00b40e 12305 bdistance = bgp_node_get_bgp_distance_info(rn);
d62a17ae 12306 bgp_unlock_node(rn);
12307
12308 if (bdistance->access_list) {
12309 alist = access_list_lookup(afi, bdistance->access_list);
12310 if (alist
12311 && access_list_apply(alist, p) == FILTER_PERMIT)
12312 return bdistance->distance;
12313 } else
12314 return bdistance->distance;
718e3744 12315 }
718e3744 12316
d62a17ae 12317 /* Backdoor check. */
12318 rn = bgp_node_lookup(bgp->route[afi][safi], p);
12319 if (rn) {
5a8ba9fc 12320 bgp_static = bgp_node_get_bgp_static_info(rn);
d62a17ae 12321 bgp_unlock_node(rn);
718e3744 12322
d62a17ae 12323 if (bgp_static->backdoor) {
12324 if (bgp->distance_local[afi][safi])
12325 return bgp->distance_local[afi][safi];
12326 else
12327 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12328 }
718e3744 12329 }
718e3744 12330
d62a17ae 12331 if (peer->sort == BGP_PEER_EBGP) {
12332 if (bgp->distance_ebgp[afi][safi])
12333 return bgp->distance_ebgp[afi][safi];
12334 return ZEBRA_EBGP_DISTANCE_DEFAULT;
12335 } else {
12336 if (bgp->distance_ibgp[afi][safi])
12337 return bgp->distance_ibgp[afi][safi];
12338 return ZEBRA_IBGP_DISTANCE_DEFAULT;
12339 }
718e3744 12340}
12341
a612fb77
DA
12342/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12343 * we should tell ZEBRA update the routes for a specific
12344 * AFI/SAFI to reflect changes in RIB.
12345 */
8b54bc30
DA
12346static void bgp_announce_routes_distance_update(struct bgp *bgp,
12347 afi_t update_afi,
12348 safi_t update_safi)
a612fb77
DA
12349{
12350 afi_t afi;
12351 safi_t safi;
12352
12353 FOREACH_AFI_SAFI (afi, safi) {
12354 if (!bgp_fibupd_safi(safi))
12355 continue;
12356
8b54bc30
DA
12357 if (afi != update_afi && safi != update_safi)
12358 continue;
12359
12360 if (BGP_DEBUG(zebra, ZEBRA))
12361 zlog_debug(
12362 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12363 __func__, afi, safi);
12364 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
12365 }
12366}
12367
718e3744 12368DEFUN (bgp_distance,
12369 bgp_distance_cmd,
6147e2c6 12370 "distance bgp (1-255) (1-255) (1-255)",
718e3744 12371 "Define an administrative distance\n"
12372 "BGP distance\n"
12373 "Distance for routes external to the AS\n"
12374 "Distance for routes internal to the AS\n"
12375 "Distance for local routes\n")
12376{
d62a17ae 12377 VTY_DECLVAR_CONTEXT(bgp, bgp);
12378 int idx_number = 2;
12379 int idx_number_2 = 3;
12380 int idx_number_3 = 4;
8b54bc30
DA
12381 int distance_ebgp = atoi(argv[idx_number]->arg);
12382 int distance_ibgp = atoi(argv[idx_number_2]->arg);
12383 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 12384 afi_t afi;
12385 safi_t safi;
718e3744 12386
d62a17ae 12387 afi = bgp_node_afi(vty);
12388 safi = bgp_node_safi(vty);
718e3744 12389
8b54bc30
DA
12390 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
12391 || bgp->distance_ibgp[afi][safi] != distance_ibgp
12392 || bgp->distance_local[afi][safi] != distance_local) {
12393 bgp->distance_ebgp[afi][safi] = distance_ebgp;
12394 bgp->distance_ibgp[afi][safi] = distance_ibgp;
12395 bgp->distance_local[afi][safi] = distance_local;
12396 bgp_announce_routes_distance_update(bgp, afi, safi);
12397 }
d62a17ae 12398 return CMD_SUCCESS;
718e3744 12399}
12400
12401DEFUN (no_bgp_distance,
12402 no_bgp_distance_cmd,
a636c635 12403 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 12404 NO_STR
12405 "Define an administrative distance\n"
12406 "BGP distance\n"
12407 "Distance for routes external to the AS\n"
12408 "Distance for routes internal to the AS\n"
12409 "Distance for local routes\n")
12410{
d62a17ae 12411 VTY_DECLVAR_CONTEXT(bgp, bgp);
12412 afi_t afi;
12413 safi_t safi;
718e3744 12414
d62a17ae 12415 afi = bgp_node_afi(vty);
12416 safi = bgp_node_safi(vty);
718e3744 12417
8b54bc30
DA
12418 if (bgp->distance_ebgp[afi][safi] != 0
12419 || bgp->distance_ibgp[afi][safi] != 0
12420 || bgp->distance_local[afi][safi] != 0) {
12421 bgp->distance_ebgp[afi][safi] = 0;
12422 bgp->distance_ibgp[afi][safi] = 0;
12423 bgp->distance_local[afi][safi] = 0;
12424 bgp_announce_routes_distance_update(bgp, afi, safi);
12425 }
d62a17ae 12426 return CMD_SUCCESS;
718e3744 12427}
12428
718e3744 12429
12430DEFUN (bgp_distance_source,
12431 bgp_distance_source_cmd,
6147e2c6 12432 "distance (1-255) A.B.C.D/M",
718e3744 12433 "Define an administrative distance\n"
12434 "Administrative distance\n"
12435 "IP source prefix\n")
12436{
d62a17ae 12437 int idx_number = 1;
12438 int idx_ipv4_prefixlen = 2;
12439 bgp_distance_set(vty, argv[idx_number]->arg,
12440 argv[idx_ipv4_prefixlen]->arg, NULL);
12441 return CMD_SUCCESS;
718e3744 12442}
12443
12444DEFUN (no_bgp_distance_source,
12445 no_bgp_distance_source_cmd,
6147e2c6 12446 "no distance (1-255) A.B.C.D/M",
718e3744 12447 NO_STR
12448 "Define an administrative distance\n"
12449 "Administrative distance\n"
12450 "IP source prefix\n")
12451{
d62a17ae 12452 int idx_number = 2;
12453 int idx_ipv4_prefixlen = 3;
12454 bgp_distance_unset(vty, argv[idx_number]->arg,
12455 argv[idx_ipv4_prefixlen]->arg, NULL);
12456 return CMD_SUCCESS;
718e3744 12457}
12458
12459DEFUN (bgp_distance_source_access_list,
12460 bgp_distance_source_access_list_cmd,
6147e2c6 12461 "distance (1-255) A.B.C.D/M WORD",
718e3744 12462 "Define an administrative distance\n"
12463 "Administrative distance\n"
12464 "IP source prefix\n"
12465 "Access list name\n")
12466{
d62a17ae 12467 int idx_number = 1;
12468 int idx_ipv4_prefixlen = 2;
12469 int idx_word = 3;
12470 bgp_distance_set(vty, argv[idx_number]->arg,
12471 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12472 return CMD_SUCCESS;
718e3744 12473}
12474
12475DEFUN (no_bgp_distance_source_access_list,
12476 no_bgp_distance_source_access_list_cmd,
6147e2c6 12477 "no distance (1-255) A.B.C.D/M WORD",
718e3744 12478 NO_STR
12479 "Define an administrative distance\n"
12480 "Administrative distance\n"
12481 "IP source prefix\n"
12482 "Access list name\n")
12483{
d62a17ae 12484 int idx_number = 2;
12485 int idx_ipv4_prefixlen = 3;
12486 int idx_word = 4;
12487 bgp_distance_unset(vty, argv[idx_number]->arg,
12488 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
12489 return CMD_SUCCESS;
718e3744 12490}
6b0655a2 12491
734b349e
MZ
12492DEFUN (ipv6_bgp_distance_source,
12493 ipv6_bgp_distance_source_cmd,
39e92c06 12494 "distance (1-255) X:X::X:X/M",
734b349e
MZ
12495 "Define an administrative distance\n"
12496 "Administrative distance\n"
12497 "IP source prefix\n")
12498{
d62a17ae 12499 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
12500 return CMD_SUCCESS;
734b349e
MZ
12501}
12502
12503DEFUN (no_ipv6_bgp_distance_source,
12504 no_ipv6_bgp_distance_source_cmd,
39e92c06 12505 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
12506 NO_STR
12507 "Define an administrative distance\n"
12508 "Administrative distance\n"
12509 "IP source prefix\n")
12510{
d62a17ae 12511 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
12512 return CMD_SUCCESS;
734b349e
MZ
12513}
12514
12515DEFUN (ipv6_bgp_distance_source_access_list,
12516 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12517 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12518 "Define an administrative distance\n"
12519 "Administrative distance\n"
12520 "IP source prefix\n"
12521 "Access list name\n")
12522{
d62a17ae 12523 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
12524 return CMD_SUCCESS;
734b349e
MZ
12525}
12526
12527DEFUN (no_ipv6_bgp_distance_source_access_list,
12528 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 12529 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
12530 NO_STR
12531 "Define an administrative distance\n"
12532 "Administrative distance\n"
12533 "IP source prefix\n"
12534 "Access list name\n")
12535{
d62a17ae 12536 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
12537 return CMD_SUCCESS;
734b349e
MZ
12538}
12539
718e3744 12540DEFUN (bgp_damp_set,
12541 bgp_damp_set_cmd,
31500417 12542 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12543 "BGP Specific commands\n"
12544 "Enable route-flap dampening\n"
12545 "Half-life time for the penalty\n"
12546 "Value to start reusing a route\n"
12547 "Value to start suppressing a route\n"
12548 "Maximum duration to suppress a stable route\n")
12549{
d62a17ae 12550 VTY_DECLVAR_CONTEXT(bgp, bgp);
12551 int idx_half_life = 2;
12552 int idx_reuse = 3;
12553 int idx_suppress = 4;
12554 int idx_max_suppress = 5;
12555 int half = DEFAULT_HALF_LIFE * 60;
12556 int reuse = DEFAULT_REUSE;
12557 int suppress = DEFAULT_SUPPRESS;
12558 int max = 4 * half;
12559
12560 if (argc == 6) {
12561 half = atoi(argv[idx_half_life]->arg) * 60;
12562 reuse = atoi(argv[idx_reuse]->arg);
12563 suppress = atoi(argv[idx_suppress]->arg);
12564 max = atoi(argv[idx_max_suppress]->arg) * 60;
12565 } else if (argc == 3) {
12566 half = atoi(argv[idx_half_life]->arg) * 60;
12567 max = 4 * half;
12568 }
718e3744 12569
6d24b7cc
DS
12570 /*
12571 * These can't be 0 but our SA doesn't understand the
12572 * way our cli is constructed
12573 */
12574 assert(reuse);
12575 assert(half);
d62a17ae 12576 if (suppress < reuse) {
12577 vty_out(vty,
12578 "Suppress value cannot be less than reuse value \n");
12579 return 0;
12580 }
7ebe9748 12581
d62a17ae 12582 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
12583 reuse, suppress, max);
718e3744 12584}
12585
718e3744 12586DEFUN (bgp_damp_unset,
12587 bgp_damp_unset_cmd,
d04c479d 12588 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 12589 NO_STR
12590 "BGP Specific commands\n"
16cedbb0
QY
12591 "Enable route-flap dampening\n"
12592 "Half-life time for the penalty\n"
12593 "Value to start reusing a route\n"
12594 "Value to start suppressing a route\n"
12595 "Maximum duration to suppress a stable route\n")
718e3744 12596{
d62a17ae 12597 VTY_DECLVAR_CONTEXT(bgp, bgp);
12598 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 12599}
12600
718e3744 12601/* Display specified route of BGP table. */
d62a17ae 12602static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
12603 const char *ip_str, afi_t afi, safi_t safi,
12604 struct prefix_rd *prd, int prefix_check)
12605{
12606 int ret;
12607 struct prefix match;
12608 struct bgp_node *rn;
12609 struct bgp_node *rm;
40381db7
DS
12610 struct bgp_path_info *pi;
12611 struct bgp_path_info *pi_temp;
d62a17ae 12612 struct bgp *bgp;
12613 struct bgp_table *table;
12614
12615 /* BGP structure lookup. */
12616 if (view_name) {
12617 bgp = bgp_lookup_by_name(view_name);
12618 if (bgp == NULL) {
12619 vty_out(vty, "%% Can't find BGP instance %s\n",
12620 view_name);
12621 return CMD_WARNING;
12622 }
12623 } else {
12624 bgp = bgp_get_default();
12625 if (bgp == NULL) {
12626 vty_out(vty, "%% No BGP process is configured\n");
12627 return CMD_WARNING;
12628 }
718e3744 12629 }
718e3744 12630
d62a17ae 12631 /* Check IP address argument. */
12632 ret = str2prefix(ip_str, &match);
12633 if (!ret) {
12634 vty_out(vty, "%% address is malformed\n");
12635 return CMD_WARNING;
12636 }
718e3744 12637
d62a17ae 12638 match.family = afi2family(afi);
12639
12640 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
12641 || (safi == SAFI_EVPN)) {
12642 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
12643 rn = bgp_route_next(rn)) {
12644 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
12645 continue;
67009e22
DS
12646 table = bgp_node_get_bgp_table_info(rn);
12647 if (!table)
ea47320b
DL
12648 continue;
12649 if ((rm = bgp_node_match(table, &match)) == NULL)
12650 continue;
d62a17ae 12651
ea47320b
DL
12652 if (!prefix_check
12653 || rm->p.prefixlen == match.prefixlen) {
6f94b685 12654 pi = bgp_node_get_bgp_path_info(rm);
40381db7
DS
12655 while (pi) {
12656 if (pi->extra && pi->extra->damp_info) {
12657 pi_temp = pi->next;
ea47320b 12658 bgp_damp_info_free(
40381db7 12659 pi->extra->damp_info,
a935f597 12660 1, afi, safi);
40381db7 12661 pi = pi_temp;
ea47320b 12662 } else
40381db7 12663 pi = pi->next;
d62a17ae 12664 }
ea47320b
DL
12665 }
12666
12667 bgp_unlock_node(rm);
d62a17ae 12668 }
12669 } else {
12670 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
12671 != NULL) {
12672 if (!prefix_check
12673 || rn->p.prefixlen == match.prefixlen) {
6f94b685 12674 pi = bgp_node_get_bgp_path_info(rn);
40381db7
DS
12675 while (pi) {
12676 if (pi->extra && pi->extra->damp_info) {
12677 pi_temp = pi->next;
d62a17ae 12678 bgp_damp_info_free(
40381db7 12679 pi->extra->damp_info,
a935f597 12680 1, afi, safi);
40381db7 12681 pi = pi_temp;
d62a17ae 12682 } else
40381db7 12683 pi = pi->next;
d62a17ae 12684 }
12685 }
12686
12687 bgp_unlock_node(rn);
12688 }
12689 }
718e3744 12690
d62a17ae 12691 return CMD_SUCCESS;
718e3744 12692}
12693
12694DEFUN (clear_ip_bgp_dampening,
12695 clear_ip_bgp_dampening_cmd,
12696 "clear ip bgp dampening",
12697 CLEAR_STR
12698 IP_STR
12699 BGP_STR
12700 "Clear route flap dampening information\n")
12701{
a935f597 12702 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 12703 return CMD_SUCCESS;
718e3744 12704}
12705
12706DEFUN (clear_ip_bgp_dampening_prefix,
12707 clear_ip_bgp_dampening_prefix_cmd,
12708 "clear ip bgp dampening A.B.C.D/M",
12709 CLEAR_STR
12710 IP_STR
12711 BGP_STR
12712 "Clear route flap dampening information\n"
0c7b1b01 12713 "IPv4 prefix\n")
718e3744 12714{
d62a17ae 12715 int idx_ipv4_prefixlen = 4;
12716 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
12717 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 12718}
12719
12720DEFUN (clear_ip_bgp_dampening_address,
12721 clear_ip_bgp_dampening_address_cmd,
12722 "clear ip bgp dampening A.B.C.D",
12723 CLEAR_STR
12724 IP_STR
12725 BGP_STR
12726 "Clear route flap dampening information\n"
12727 "Network to clear damping information\n")
12728{
d62a17ae 12729 int idx_ipv4 = 4;
12730 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
12731 SAFI_UNICAST, NULL, 0);
718e3744 12732}
12733
12734DEFUN (clear_ip_bgp_dampening_address_mask,
12735 clear_ip_bgp_dampening_address_mask_cmd,
12736 "clear ip bgp dampening A.B.C.D A.B.C.D",
12737 CLEAR_STR
12738 IP_STR
12739 BGP_STR
12740 "Clear route flap dampening information\n"
12741 "Network to clear damping information\n"
12742 "Network mask\n")
12743{
d62a17ae 12744 int idx_ipv4 = 4;
12745 int idx_ipv4_2 = 5;
12746 int ret;
12747 char prefix_str[BUFSIZ];
718e3744 12748
d62a17ae 12749 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
12750 prefix_str);
12751 if (!ret) {
12752 vty_out(vty, "%% Inconsistent address and mask\n");
12753 return CMD_WARNING;
12754 }
718e3744 12755
d62a17ae 12756 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
12757 NULL, 0);
718e3744 12758}
6b0655a2 12759
e3b78da8 12760static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
12761{
12762 struct vty *vty = arg;
e3b78da8 12763 struct peer *peer = bucket->data;
825d9834
DS
12764 char buf[SU_ADDRSTRLEN];
12765
12766 vty_out(vty, "\tPeer: %s %s\n", peer->host,
12767 sockunion2str(&peer->su, buf, sizeof(buf)));
12768}
12769
2a0e69ae
DS
12770DEFUN (show_bgp_listeners,
12771 show_bgp_listeners_cmd,
12772 "show bgp listeners",
12773 SHOW_STR
12774 BGP_STR
12775 "Display Listen Sockets and who created them\n")
12776{
12777 bgp_dump_listener_info(vty);
12778
12779 return CMD_SUCCESS;
12780}
12781
825d9834
DS
12782DEFUN (show_bgp_peerhash,
12783 show_bgp_peerhash_cmd,
12784 "show bgp peerhash",
12785 SHOW_STR
12786 BGP_STR
12787 "Display information about the BGP peerhash\n")
12788{
12789 struct list *instances = bm->bgp;
12790 struct listnode *node;
12791 struct bgp *bgp;
12792
12793 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
12794 vty_out(vty, "BGP: %s\n", bgp->name);
12795 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
12796 vty);
12797 }
12798
12799 return CMD_SUCCESS;
12800}
12801
587ff0fd 12802/* also used for encap safi */
2b791107
DL
12803static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
12804 afi_t afi, safi_t safi)
d62a17ae 12805{
12806 struct bgp_node *prn;
12807 struct bgp_node *rn;
12808 struct bgp_table *table;
12809 struct prefix *p;
12810 struct prefix_rd *prd;
12811 struct bgp_static *bgp_static;
12812 mpls_label_t label;
12813 char buf[SU_ADDRSTRLEN];
12814 char rdbuf[RD_ADDRSTRLEN];
12815
12816 /* Network configuration. */
12817 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12818 prn = bgp_route_next(prn)) {
67009e22
DS
12819 table = bgp_node_get_bgp_table_info(prn);
12820 if (!table)
ea47320b 12821 continue;
d62a17ae 12822
60466a63 12823 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12824 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12825 if (bgp_static == NULL)
ea47320b 12826 continue;
d62a17ae 12827
ea47320b
DL
12828 p = &rn->p;
12829 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12830
ea47320b 12831 /* "network" configuration display. */
06b9f471 12832 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
12833 label = decode_label(&bgp_static->label);
12834
12835 vty_out(vty, " network %s/%d rd %s",
12836 inet_ntop(p->family, &p->u.prefix, buf,
12837 SU_ADDRSTRLEN),
12838 p->prefixlen, rdbuf);
12839 if (safi == SAFI_MPLS_VPN)
12840 vty_out(vty, " label %u", label);
12841
12842 if (bgp_static->rmap.name)
12843 vty_out(vty, " route-map %s",
12844 bgp_static->rmap.name);
e2a86ad9
DS
12845
12846 if (bgp_static->backdoor)
12847 vty_out(vty, " backdoor");
12848
ea47320b
DL
12849 vty_out(vty, "\n");
12850 }
12851 }
d62a17ae 12852}
12853
2b791107
DL
12854static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
12855 afi_t afi, safi_t safi)
d62a17ae 12856{
12857 struct bgp_node *prn;
12858 struct bgp_node *rn;
12859 struct bgp_table *table;
12860 struct prefix *p;
12861 struct prefix_rd *prd;
12862 struct bgp_static *bgp_static;
ff44f570 12863 char buf[PREFIX_STRLEN * 2];
d62a17ae 12864 char buf2[SU_ADDRSTRLEN];
12865 char rdbuf[RD_ADDRSTRLEN];
12866
12867 /* Network configuration. */
12868 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b 12869 prn = bgp_route_next(prn)) {
67009e22
DS
12870 table = bgp_node_get_bgp_table_info(prn);
12871 if (!table)
ea47320b 12872 continue;
d62a17ae 12873
60466a63 12874 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
5a8ba9fc 12875 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12876 if (bgp_static == NULL)
ea47320b 12877 continue;
d62a17ae 12878
ea47320b
DL
12879 char *macrouter = NULL;
12880 char *esi = NULL;
d62a17ae 12881
ea47320b
DL
12882 if (bgp_static->router_mac)
12883 macrouter = prefix_mac2str(
12884 bgp_static->router_mac, NULL, 0);
12885 if (bgp_static->eth_s_id)
12886 esi = esi2str(bgp_static->eth_s_id);
12887 p = &rn->p;
12888 prd = (struct prefix_rd *)&prn->p;
d62a17ae 12889
ea47320b 12890 /* "network" configuration display. */
06b9f471 12891 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
12892 if (p->u.prefix_evpn.route_type == 5) {
12893 char local_buf[PREFIX_STRLEN];
3714a385 12894 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
12895 struct prefix_evpn *)p)
12896 ? AF_INET
12897 : AF_INET6;
3714a385 12898 inet_ntop(family,
12899 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a
PZ
12900 local_buf, PREFIX_STRLEN);
12901 sprintf(buf, "%s/%u", local_buf,
3714a385 12902 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
197cb530
PG
12903 } else {
12904 prefix2str(p, buf, sizeof(buf));
12905 }
ea47320b 12906
a4d82a8a
PZ
12907 if (bgp_static->gatewayIp.family == AF_INET
12908 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
12909 inet_ntop(bgp_static->gatewayIp.family,
12910 &bgp_static->gatewayIp.u.prefix, buf2,
12911 sizeof(buf2));
ea47320b 12912 vty_out(vty,
7bcc8dac 12913 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 12914 buf, rdbuf,
12915 p->u.prefix_evpn.prefix_addr.eth_tag,
60466a63 12916 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
12917 macrouter);
12918
0a22ddfb
QY
12919 XFREE(MTYPE_TMP, macrouter);
12920 XFREE(MTYPE_TMP, esi);
ea47320b
DL
12921 }
12922 }
3da6fcd5
PG
12923}
12924
718e3744 12925/* Configuration of static route announcement and aggregate
12926 information. */
2b791107
DL
12927void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
12928 safi_t safi)
d62a17ae 12929{
12930 struct bgp_node *rn;
12931 struct prefix *p;
12932 struct bgp_static *bgp_static;
12933 struct bgp_aggregate *bgp_aggregate;
12934 char buf[SU_ADDRSTRLEN];
12935
2b791107
DL
12936 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
12937 bgp_config_write_network_vpn(vty, bgp, afi, safi);
12938 return;
12939 }
d62a17ae 12940
2b791107
DL
12941 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
12942 bgp_config_write_network_evpn(vty, bgp, afi, safi);
12943 return;
12944 }
d62a17ae 12945
12946 /* Network configuration. */
12947 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b 12948 rn = bgp_route_next(rn)) {
5a8ba9fc 12949 bgp_static = bgp_node_get_bgp_static_info(rn);
a78beeb5 12950 if (bgp_static == NULL)
ea47320b 12951 continue;
d62a17ae 12952
ea47320b 12953 p = &rn->p;
d62a17ae 12954
d8a9922d
DS
12955 vty_out(vty, " network %s/%d",
12956 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12957 p->prefixlen);
d62a17ae 12958
ea47320b
DL
12959 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
12960 vty_out(vty, " label-index %u",
12961 bgp_static->label_index);
d62a17ae 12962
ea47320b
DL
12963 if (bgp_static->rmap.name)
12964 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
12965
12966 if (bgp_static->backdoor)
12967 vty_out(vty, " backdoor");
718e3744 12968
ea47320b
DL
12969 vty_out(vty, "\n");
12970 }
12971
d62a17ae 12972 /* Aggregate-address configuration. */
12973 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b 12974 rn = bgp_route_next(rn)) {
b613a918 12975 bgp_aggregate = bgp_node_get_bgp_aggregate_info(rn);
b1e62edd 12976 if (bgp_aggregate == NULL)
ea47320b 12977 continue;
d62a17ae 12978
ea47320b 12979 p = &rn->p;
d62a17ae 12980
d8a9922d
DS
12981 vty_out(vty, " aggregate-address %s/%d",
12982 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
12983 p->prefixlen);
d62a17ae 12984
ea47320b
DL
12985 if (bgp_aggregate->as_set)
12986 vty_out(vty, " as-set");
d62a17ae 12987
ea47320b
DL
12988 if (bgp_aggregate->summary_only)
12989 vty_out(vty, " summary-only");
718e3744 12990
20894f50
DA
12991 if (bgp_aggregate->rmap.name)
12992 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
12993
229757f1
DA
12994 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
12995 vty_out(vty, " origin %s",
12996 bgp_origin2str(bgp_aggregate->origin));
12997
ea47320b
DL
12998 vty_out(vty, "\n");
12999 }
d62a17ae 13000}
734b349e 13001
2b791107 13002void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13003 safi_t safi)
d62a17ae 13004{
13005 struct bgp_node *rn;
13006 struct bgp_distance *bdistance;
13007
13008 /* Distance configuration. */
13009 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13010 && bgp->distance_local[afi][safi]
13011 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13012 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13013 || bgp->distance_local[afi][safi]
13014 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13015 vty_out(vty, " distance bgp %d %d %d\n",
13016 bgp->distance_ebgp[afi][safi],
13017 bgp->distance_ibgp[afi][safi],
13018 bgp->distance_local[afi][safi]);
13019 }
734b349e 13020
d62a17ae 13021 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
ca2e160d 13022 rn = bgp_route_next(rn)) {
5b00b40e 13023 bdistance = bgp_node_get_bgp_distance_info(rn);
ca2e160d 13024 if (bdistance != NULL) {
d62a17ae 13025 char buf[PREFIX_STRLEN];
13026
d62a17ae 13027 vty_out(vty, " distance %d %s %s\n",
13028 bdistance->distance,
13029 prefix2str(&rn->p, buf, sizeof(buf)),
13030 bdistance->access_list ? bdistance->access_list
13031 : "");
13032 }
ca2e160d 13033 }
718e3744 13034}
13035
13036/* Allocate routing table structure and install commands. */
d62a17ae 13037void bgp_route_init(void)
13038{
13039 afi_t afi;
13040 safi_t safi;
13041
13042 /* Init BGP distance table. */
05c7a1cc 13043 FOREACH_AFI_SAFI (afi, safi)
960035b2 13044 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13045
13046 /* IPv4 BGP commands. */
13047 install_element(BGP_NODE, &bgp_table_map_cmd);
13048 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13049 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13050
13051 install_element(BGP_NODE, &aggregate_address_cmd);
13052 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13053 install_element(BGP_NODE, &no_aggregate_address_cmd);
13054 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13055
13056 /* IPv4 unicast configuration. */
13057 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13058 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13059 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13060
13061 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13062 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13063 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13064 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13065
13066 /* IPv4 multicast configuration. */
13067 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13068 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13069 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13070 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13071 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13072 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13073 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13074
13075 /* IPv4 labeled-unicast configuration. */
13076 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13077 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 13078 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13079 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13080 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
13081
13082 install_element(VIEW_NODE,
13083 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
13084 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13085 install_element(VIEW_NODE,
13086 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13087#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13088 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13089#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13090 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13091 install_element(VIEW_NODE,
44c69747 13092 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13093
d62a17ae 13094 /* BGP dampening clear commands */
13095 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13096 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13097
d62a17ae 13098 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13099 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13100
13101 /* prefix count */
13102 install_element(ENABLE_NODE,
13103 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13104#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13105 install_element(ENABLE_NODE,
13106 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13107#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13108
d62a17ae 13109 /* New config IPv6 BGP commands. */
13110 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
13111 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13112 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 13113
13114 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
13115 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
13116
13117 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 13118
d62a17ae 13119 install_element(BGP_NODE, &bgp_distance_cmd);
13120 install_element(BGP_NODE, &no_bgp_distance_cmd);
13121 install_element(BGP_NODE, &bgp_distance_source_cmd);
13122 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
13123 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
13124 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
13125 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
13126 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
13127 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
13128 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
13129 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
13130 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
13131 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
13132 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
13133 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
13134 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
13135 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
13136 install_element(BGP_IPV4M_NODE,
13137 &no_bgp_distance_source_access_list_cmd);
13138 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
13139 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
13140 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
13141 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
13142 install_element(BGP_IPV6_NODE,
13143 &ipv6_bgp_distance_source_access_list_cmd);
13144 install_element(BGP_IPV6_NODE,
13145 &no_ipv6_bgp_distance_source_access_list_cmd);
13146 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
13147 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
13148 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
13149 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
13150 install_element(BGP_IPV6M_NODE,
13151 &ipv6_bgp_distance_source_access_list_cmd);
13152 install_element(BGP_IPV6M_NODE,
13153 &no_ipv6_bgp_distance_source_access_list_cmd);
13154
13155 install_element(BGP_NODE, &bgp_damp_set_cmd);
13156 install_element(BGP_NODE, &bgp_damp_unset_cmd);
13157 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
13158 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
13159
13160 /* IPv4 Multicast Mode */
13161 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
13162 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
13163
13164 /* Large Communities */
13165 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
13166 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
13167
13168 /* show bgp ipv4 flowspec detailed */
13169 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
13170
2a0e69ae 13171 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 13172 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 13173}
13174
13175void bgp_route_finish(void)
13176{
13177 afi_t afi;
13178 safi_t safi;
13179
05c7a1cc
QY
13180 FOREACH_AFI_SAFI (afi, safi) {
13181 bgp_table_unlock(bgp_distance_table[afi][safi]);
13182 bgp_distance_table[afi][safi] = NULL;
13183 }
228da428 13184}