]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: use macro HAVE_STRUCT_UTSNAME_DOMAINNAME to avoid compilation failures
[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>
23
24#include "prefix.h"
25#include "linklist.h"
26#include "memory.h"
27#include "command.h"
28#include "stream.h"
29#include "filter.h"
718e3744 30#include "log.h"
31#include "routemap.h"
32#include "buffer.h"
33#include "sockunion.h"
34#include "plist.h"
35#include "thread.h"
200df115 36#include "workqueue.h"
3f9c7369 37#include "queue.h"
6e919709 38#include "memory.h"
4dcadbef 39#include "lib/json.h"
718e3744 40
41#include "bgpd/bgpd.h"
42#include "bgpd/bgp_table.h"
43#include "bgpd/bgp_route.h"
44#include "bgpd/bgp_attr.h"
45#include "bgpd/bgp_debug.h"
46#include "bgpd/bgp_aspath.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_community.h"
49#include "bgpd/bgp_ecommunity.h"
57d187bc 50#include "bgpd/bgp_lcommunity.h"
718e3744 51#include "bgpd/bgp_clist.h"
52#include "bgpd/bgp_packet.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_fsm.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_nexthop.h"
57#include "bgpd/bgp_damp.h"
58#include "bgpd/bgp_advertise.h"
59#include "bgpd/bgp_zebra.h"
0a486e5f 60#include "bgpd/bgp_vty.h"
96450faf 61#include "bgpd/bgp_mpath.h"
fc9a856f 62#include "bgpd/bgp_nht.h"
3f9c7369 63#include "bgpd/bgp_updgrp.h"
cd1964ff 64#include "bgpd/bgp_label.h"
718e3744 65
65efcfce 66#if ENABLE_BGP_VNC
f8b6f499
LB
67#include "bgpd/rfapi/rfapi_backend.h"
68#include "bgpd/rfapi/vnc_import_bgp.h"
69#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 70#endif
aee875b5
PG
71#include "bgpd/bgp_encap_types.h"
72#include "bgpd/bgp_encap_tlv.h"
684a7227 73#include "bgpd/bgp_evpn.h"
3da6fcd5 74#include "bgpd/bgp_evpn_vty.h"
65efcfce 75
aee875b5 76
718e3744 77/* Extern from bgp_dump.c */
dde72586
SH
78extern const char *bgp_origin_str[];
79extern const char *bgp_origin_long_str[];
6b0655a2 80
d62a17ae 81struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
82 safi_t safi, struct prefix *p,
83 struct prefix_rd *prd)
84{
85 struct bgp_node *rn;
86 struct bgp_node *prn = NULL;
87
88 assert(table);
89 if (!table)
90 return NULL;
91
92 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
93 || (safi == SAFI_EVPN)) {
94 prn = bgp_node_get(table, (struct prefix *)prd);
95
96 if (prn->info == NULL)
97 prn->info = bgp_table_init(afi, safi);
98 else
99 bgp_unlock_node(prn);
100 table = prn->info;
101 }
718e3744 102
d62a17ae 103 rn = bgp_node_get(table, p);
718e3744 104
d62a17ae 105 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
106 || (safi == SAFI_EVPN))
107 rn->prn = prn;
718e3744 108
d62a17ae 109 return rn;
718e3744 110}
6b0655a2 111
d62a17ae 112struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
113 safi_t safi, struct prefix *p,
114 struct prefix_rd *prd)
128ea8ab 115{
d62a17ae 116 struct bgp_node *rn;
117 struct bgp_node *prn = NULL;
128ea8ab 118
d62a17ae 119 if (!table)
120 return NULL;
128ea8ab 121
d62a17ae 122 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
123 || (safi == SAFI_EVPN)) {
124 prn = bgp_node_lookup(table, (struct prefix *)prd);
125 if (!prn)
126 return NULL;
128ea8ab 127
d62a17ae 128 if (prn->info == NULL) {
129 bgp_unlock_node(prn);
130 return NULL;
131 }
128ea8ab 132
d62a17ae 133 table = prn->info;
134 }
128ea8ab 135
d62a17ae 136 rn = bgp_node_lookup(table, p);
128ea8ab 137
d62a17ae 138 return rn;
128ea8ab 139}
140
fb982c25 141/* Allocate bgp_info_extra */
d62a17ae 142static struct bgp_info_extra *bgp_info_extra_new(void)
fb982c25 143{
d62a17ae 144 struct bgp_info_extra *new;
145 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA, sizeof(struct bgp_info_extra));
146 new->label = MPLS_INVALID_LABEL;
147 return new;
fb982c25
PJ
148}
149
d62a17ae 150static void bgp_info_extra_free(struct bgp_info_extra **extra)
fb982c25 151{
d62a17ae 152 if (extra && *extra) {
153 if ((*extra)->damp_info)
154 bgp_damp_info_free((*extra)->damp_info, 0);
155
156 (*extra)->damp_info = NULL;
157
158 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
159
160 *extra = NULL;
161 }
fb982c25
PJ
162}
163
164/* Get bgp_info extra information for the given bgp_info, lazy allocated
165 * if required.
166 */
d62a17ae 167struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *ri)
fb982c25 168{
d62a17ae 169 if (!ri->extra)
170 ri->extra = bgp_info_extra_new();
171 return ri->extra;
fb982c25
PJ
172}
173
65efcfce 174/* Allocate new bgp info structure. */
d62a17ae 175struct bgp_info *bgp_info_new(void)
65efcfce 176{
d62a17ae 177 return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info));
65efcfce
LB
178}
179
718e3744 180/* Free bgp route information. */
d62a17ae 181static void bgp_info_free(struct bgp_info *binfo)
718e3744 182{
d62a17ae 183 if (binfo->attr)
184 bgp_attr_unintern(&binfo->attr);
fb018d25 185
d62a17ae 186 bgp_unlink_nexthop(binfo);
187 bgp_info_extra_free(&binfo->extra);
188 bgp_info_mpath_free(&binfo->mpath);
718e3744 189
d62a17ae 190 peer_unlock(binfo->peer); /* bgp_info peer reference */
200df115 191
d62a17ae 192 XFREE(MTYPE_BGP_ROUTE, binfo);
718e3744 193}
194
d62a17ae 195struct bgp_info *bgp_info_lock(struct bgp_info *binfo)
200df115 196{
d62a17ae 197 binfo->lock++;
198 return binfo;
200df115 199}
200
d62a17ae 201struct bgp_info *bgp_info_unlock(struct bgp_info *binfo)
200df115 202{
d62a17ae 203 assert(binfo && binfo->lock > 0);
204 binfo->lock--;
205
206 if (binfo->lock == 0) {
200df115 207#if 0
208 zlog_debug ("%s: unlocked and freeing", __func__);
209 zlog_backtrace (LOG_DEBUG);
210#endif
d62a17ae 211 bgp_info_free(binfo);
212 return NULL;
213 }
200df115 214
215#if 0
216 if (binfo->lock == 1)
217 {
218 zlog_debug ("%s: unlocked to 1", __func__);
219 zlog_backtrace (LOG_DEBUG);
220 }
221#endif
d62a17ae 222
223 return binfo;
200df115 224}
225
d62a17ae 226void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri)
718e3744 227{
d62a17ae 228 struct bgp_info *top;
718e3744 229
d62a17ae 230 top = rn->info;
231
232 ri->next = rn->info;
233 ri->prev = NULL;
234 if (top)
235 top->prev = ri;
236 rn->info = ri;
237
238 bgp_info_lock(ri);
239 bgp_lock_node(rn);
240 peer_lock(ri->peer); /* bgp_info peer reference */
718e3744 241}
242
d62a17ae 243/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 244 completion callback *only* */
d62a17ae 245void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri)
718e3744 246{
d62a17ae 247 if (ri->next)
248 ri->next->prev = ri->prev;
249 if (ri->prev)
250 ri->prev->next = ri->next;
251 else
252 rn->info = ri->next;
253
254 bgp_info_mpath_dequeue(ri);
255 bgp_info_unlock(ri);
256 bgp_unlock_node(rn);
718e3744 257}
258
d62a17ae 259void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri)
b40d939b 260{
d62a17ae 261 bgp_info_set_flag(rn, ri, BGP_INFO_REMOVED);
262 /* set of previous already took care of pcount */
263 UNSET_FLAG(ri->flags, BGP_INFO_VALID);
b40d939b 264}
265
8d45210e
AS
266/* undo the effects of a previous call to bgp_info_delete; typically
267 called when a route is deleted and then quickly re-added before the
268 deletion has been processed */
d62a17ae 269void bgp_info_restore(struct bgp_node *rn, struct bgp_info *ri)
8d45210e 270{
d62a17ae 271 bgp_info_unset_flag(rn, ri, BGP_INFO_REMOVED);
272 /* unset of previous already took care of pcount */
273 SET_FLAG(ri->flags, BGP_INFO_VALID);
8d45210e
AS
274}
275
d62a17ae 276/* Adjust pcount as required */
277static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)
1a392d46 278{
d62a17ae 279 struct bgp_table *table;
67174041 280
d62a17ae 281 assert(rn && bgp_node_table(rn));
282 assert(ri && ri->peer && ri->peer->bgp);
6f58544d 283
d62a17ae 284 table = bgp_node_table(rn);
67174041 285
d62a17ae 286 if (ri->peer == ri->peer->bgp->peer_self)
287 return;
288
289 if (!BGP_INFO_COUNTABLE(ri)
290 && CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
291
292 UNSET_FLAG(ri->flags, BGP_INFO_COUNTED);
293
294 /* slight hack, but more robust against errors. */
295 if (ri->peer->pcount[table->afi][table->safi])
296 ri->peer->pcount[table->afi][table->safi]--;
297 else {
298 zlog_warn(
299 "%s: Asked to decrement 0 prefix count for peer %s",
300 __func__, ri->peer->host);
301 zlog_backtrace(LOG_WARNING);
302 zlog_warn("%s: Please report to Quagga bugzilla",
303 __func__);
304 }
305 } else if (BGP_INFO_COUNTABLE(ri)
306 && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
307 SET_FLAG(ri->flags, BGP_INFO_COUNTED);
308 ri->peer->pcount[table->afi][table->safi]++;
309 }
1a392d46
PJ
310}
311
d62a17ae 312static int bgp_label_index_differs(struct bgp_info *ri1, struct bgp_info *ri2)
28d58fd7 313{
d62a17ae 314 return (!(ri1->attr->label_index == ri2->attr->label_index));
28d58fd7 315}
1a392d46
PJ
316
317/* Set/unset bgp_info flags, adjusting any other state as needed.
318 * This is here primarily to keep prefix-count in check.
319 */
d62a17ae 320void bgp_info_set_flag(struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
1a392d46 321{
d62a17ae 322 SET_FLAG(ri->flags, flag);
323
324 /* early bath if we know it's not a flag that changes countability state
325 */
326 if (!CHECK_FLAG(flag,
327 BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED))
328 return;
329
330 bgp_pcount_adjust(rn, ri);
1a392d46
PJ
331}
332
d62a17ae 333void bgp_info_unset_flag(struct bgp_node *rn, struct bgp_info *ri,
334 u_int32_t flag)
1a392d46 335{
d62a17ae 336 UNSET_FLAG(ri->flags, flag);
337
338 /* early bath if we know it's not a flag that changes countability state
339 */
340 if (!CHECK_FLAG(flag,
341 BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED))
342 return;
343
344 bgp_pcount_adjust(rn, ri);
1a392d46
PJ
345}
346
718e3744 347/* Get MED value. If MED value is missing and "bgp bestpath
348 missing-as-worst" is specified, treat it as the worst value. */
d62a17ae 349static u_int32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
350{
351 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
352 return attr->med;
353 else {
354 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
355 return BGP_MED_MAX;
356 else
357 return 0;
358 }
718e3744 359}
360
d62a17ae 361void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf)
2ec1e66f 362{
d62a17ae 363 if (ri->addpath_rx_id)
364 sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host,
365 ri->addpath_rx_id);
366 else
367 sprintf(buf, "path %s", ri->peer->host);
368}
9fbdd100 369
d62a17ae 370/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
371 */
372static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new,
373 struct bgp_info *exist, int *paths_eq,
374 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
375 char *pfx_buf, afi_t afi, safi_t safi)
376{
377 struct attr *newattr, *existattr;
378 bgp_peer_sort_t new_sort;
379 bgp_peer_sort_t exist_sort;
380 u_int32_t new_pref;
381 u_int32_t exist_pref;
382 u_int32_t new_med;
383 u_int32_t exist_med;
384 u_int32_t new_weight;
385 u_int32_t exist_weight;
386 uint32_t newm, existm;
387 struct in_addr new_id;
388 struct in_addr exist_id;
389 int new_cluster;
390 int exist_cluster;
391 int internal_as_route;
392 int confed_as_route;
393 int ret;
394 char new_buf[PATH_ADDPATH_STR_BUFFER];
395 char exist_buf[PATH_ADDPATH_STR_BUFFER];
396 u_int32_t new_mm_seq;
397 u_int32_t exist_mm_seq;
398
399 *paths_eq = 0;
400
401 /* 0. Null check. */
402 if (new == NULL) {
403 if (debug)
404 zlog_debug("%s: new is NULL", pfx_buf);
405 return 0;
406 }
2ec1e66f 407
d62a17ae 408 if (debug)
409 bgp_info_path_with_addpath_rx_str(new, new_buf);
718e3744 410
d62a17ae 411 if (exist == NULL) {
412 if (debug)
413 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
414 new_buf);
415 return 1;
416 }
2ec1e66f 417
d62a17ae 418 if (debug) {
419 bgp_info_path_with_addpath_rx_str(exist, exist_buf);
420 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
421 pfx_buf, new_buf, new->flags, exist_buf,
422 exist->flags);
423 }
8ff56318 424
d62a17ae 425 newattr = new->attr;
426 existattr = exist->attr;
427
428 /* For EVPN routes, we cannot just go by local vs remote, we have to
429 * look at the MAC mobility sequence number, if present.
430 */
431 if (safi == SAFI_EVPN) {
432 /* This is an error condition described in RFC 7432 Section
433 * 15.2. The RFC
434 * states that in this scenario "the PE MUST alert the operator"
435 * but it
436 * does not state what other action to take. In order to provide
437 * some
438 * consistency in this scenario we are going to prefer the path
439 * with the
440 * sticky flag.
441 */
442 if (newattr->sticky != existattr->sticky) {
443 if (!debug) {
444 prefix2str(&new->net->p, pfx_buf,
445 sizeof(*pfx_buf)
446 * PREFIX2STR_BUFFER);
447 bgp_info_path_with_addpath_rx_str(new, new_buf);
448 bgp_info_path_with_addpath_rx_str(exist,
449 exist_buf);
450 }
451
452 if (newattr->sticky && !existattr->sticky) {
453 zlog_warn(
454 "%s: %s wins over %s due to sticky MAC flag",
455 pfx_buf, new_buf, exist_buf);
456 return 1;
457 }
458
459 if (!newattr->sticky && existattr->sticky) {
460 zlog_warn(
461 "%s: %s loses to %s due to sticky MAC flag",
462 pfx_buf, new_buf, exist_buf);
463 return 0;
464 }
465 }
128ea8ab 466
d62a17ae 467 new_mm_seq = mac_mobility_seqnum(newattr);
468 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 469
d62a17ae 470 if (new_mm_seq > exist_mm_seq) {
471 if (debug)
472 zlog_debug(
473 "%s: %s wins over %s due to MM seq %u > %u",
474 pfx_buf, new_buf, exist_buf, new_mm_seq,
475 exist_mm_seq);
476 return 1;
477 }
8ff56318 478
d62a17ae 479 if (new_mm_seq < exist_mm_seq) {
480 if (debug)
481 zlog_debug(
482 "%s: %s loses to %s due to MM seq %u < %u",
483 pfx_buf, new_buf, exist_buf, new_mm_seq,
484 exist_mm_seq);
485 return 0;
486 }
487 }
9fbdd100 488
d62a17ae 489 /* 1. Weight check. */
490 new_weight = exist_weight = 0;
718e3744 491
d62a17ae 492 new_weight = newattr->weight;
493 exist_weight = existattr->weight;
8ff56318 494
d62a17ae 495 if (new_weight > exist_weight) {
496 if (debug)
497 zlog_debug("%s: %s wins over %s due to weight %d > %d",
498 pfx_buf, new_buf, exist_buf, new_weight,
499 exist_weight);
500 return 1;
501 }
718e3744 502
d62a17ae 503 if (new_weight < exist_weight) {
504 if (debug)
505 zlog_debug("%s: %s loses to %s due to weight %d < %d",
506 pfx_buf, new_buf, exist_buf, new_weight,
507 exist_weight);
508 return 0;
509 }
9fbdd100 510
d62a17ae 511 /* 2. Local preference check. */
512 new_pref = exist_pref = bgp->default_local_pref;
513
514 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
515 new_pref = newattr->local_pref;
516 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
517 exist_pref = existattr->local_pref;
518
519 if (new_pref > exist_pref) {
520 if (debug)
521 zlog_debug(
522 "%s: %s wins over %s due to localpref %d > %d",
523 pfx_buf, new_buf, exist_buf, new_pref,
524 exist_pref);
525 return 1;
526 }
718e3744 527
d62a17ae 528 if (new_pref < exist_pref) {
529 if (debug)
530 zlog_debug(
531 "%s: %s loses to %s due to localpref %d < %d",
532 pfx_buf, new_buf, exist_buf, new_pref,
533 exist_pref);
534 return 0;
535 }
9fbdd100 536
d62a17ae 537 /* 3. Local route check. We prefer:
538 * - BGP_ROUTE_STATIC
539 * - BGP_ROUTE_AGGREGATE
540 * - BGP_ROUTE_REDISTRIBUTE
541 */
542 if (!(new->sub_type == BGP_ROUTE_NORMAL)) {
543 if (debug)
544 zlog_debug(
545 "%s: %s wins over %s due to preferred BGP_ROUTE type",
546 pfx_buf, new_buf, exist_buf);
547 return 1;
548 }
718e3744 549
d62a17ae 550 if (!(exist->sub_type == BGP_ROUTE_NORMAL)) {
551 if (debug)
552 zlog_debug(
553 "%s: %s loses to %s due to preferred BGP_ROUTE type",
554 pfx_buf, new_buf, exist_buf);
555 return 0;
6811845b 556 }
718e3744 557
d62a17ae 558 /* 4. AS path length check. */
559 if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
560 int exist_hops = aspath_count_hops(existattr->aspath);
561 int exist_confeds = aspath_count_confeds(existattr->aspath);
562
563 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
564 int aspath_hops;
565
566 aspath_hops = aspath_count_hops(newattr->aspath);
567 aspath_hops += aspath_count_confeds(newattr->aspath);
568
569 if (aspath_hops < (exist_hops + exist_confeds)) {
570 if (debug)
571 zlog_debug(
572 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
573 pfx_buf, new_buf, exist_buf,
574 aspath_hops,
575 (exist_hops + exist_confeds));
576 return 1;
577 }
578
579 if (aspath_hops > (exist_hops + exist_confeds)) {
580 if (debug)
581 zlog_debug(
582 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
583 pfx_buf, new_buf, exist_buf,
584 aspath_hops,
585 (exist_hops + exist_confeds));
586 return 0;
587 }
588 } else {
589 int newhops = aspath_count_hops(newattr->aspath);
590
591 if (newhops < exist_hops) {
592 if (debug)
593 zlog_debug(
594 "%s: %s wins over %s due to aspath hopcount %d < %d",
595 pfx_buf, new_buf, exist_buf,
596 newhops, exist_hops);
597 return 1;
598 }
599
600 if (newhops > exist_hops) {
601 if (debug)
602 zlog_debug(
603 "%s: %s loses to %s due to aspath hopcount %d > %d",
604 pfx_buf, new_buf, exist_buf,
605 newhops, exist_hops);
606 return 0;
607 }
608 }
609 }
9fbdd100 610
d62a17ae 611 /* 5. Origin check. */
612 if (newattr->origin < existattr->origin) {
613 if (debug)
614 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
615 pfx_buf, new_buf, exist_buf,
616 bgp_origin_long_str[newattr->origin],
617 bgp_origin_long_str[existattr->origin]);
618 return 1;
619 }
718e3744 620
d62a17ae 621 if (newattr->origin > existattr->origin) {
622 if (debug)
623 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
624 pfx_buf, new_buf, exist_buf,
625 bgp_origin_long_str[newattr->origin],
626 bgp_origin_long_str[existattr->origin]);
627 return 0;
628 }
718e3744 629
d62a17ae 630 /* 6. MED check. */
631 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
632 && aspath_count_hops(existattr->aspath) == 0);
633 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
634 && aspath_count_confeds(existattr->aspath) > 0
635 && aspath_count_hops(newattr->aspath) == 0
636 && aspath_count_hops(existattr->aspath) == 0);
637
638 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
639 || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
640 || aspath_cmp_left(newattr->aspath, existattr->aspath)
641 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
642 || internal_as_route) {
643 new_med = bgp_med_value(new->attr, bgp);
644 exist_med = bgp_med_value(exist->attr, bgp);
645
646 if (new_med < exist_med) {
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to MED %d < %d",
650 pfx_buf, new_buf, exist_buf, new_med,
651 exist_med);
652 return 1;
653 }
8ff56318 654
d62a17ae 655 if (new_med > exist_med) {
656 if (debug)
657 zlog_debug(
658 "%s: %s loses to %s due to MED %d > %d",
659 pfx_buf, new_buf, exist_buf, new_med,
660 exist_med);
661 return 0;
662 }
663 }
9fbdd100 664
d62a17ae 665 /* 7. Peer type check. */
666 new_sort = new->peer->sort;
667 exist_sort = exist->peer->sort;
668
669 if (new_sort == BGP_PEER_EBGP
670 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
671 if (debug)
672 zlog_debug(
673 "%s: %s wins over %s due to eBGP peer > iBGP peer",
674 pfx_buf, new_buf, exist_buf);
675 return 1;
676 }
718e3744 677
d62a17ae 678 if (exist_sort == BGP_PEER_EBGP
679 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
680 if (debug)
681 zlog_debug(
682 "%s: %s loses to %s due to iBGP peer < eBGP peer",
683 pfx_buf, new_buf, exist_buf);
684 return 0;
685 }
8ff56318 686
d62a17ae 687 /* 8. IGP metric check. */
688 newm = existm = 0;
8ff56318 689
d62a17ae 690 if (new->extra)
691 newm = new->extra->igpmetric;
692 if (exist->extra)
693 existm = exist->extra->igpmetric;
9fbdd100 694
d62a17ae 695 if (newm < existm) {
696 if (debug)
697 zlog_debug(
698 "%s: %s wins over %s due to IGP metric %d < %d",
699 pfx_buf, new_buf, exist_buf, newm, existm);
700 ret = 1;
701 }
718e3744 702
d62a17ae 703 if (newm > existm) {
704 if (debug)
705 zlog_debug(
706 "%s: %s loses to %s due to IGP metric %d > %d",
707 pfx_buf, new_buf, exist_buf, newm, existm);
708 ret = 0;
5e242b0d 709 }
5e242b0d 710
d62a17ae 711 /* 9. Same IGP metric. Compare the cluster list length as
712 representative of IGP hops metric. Rewrite the metric value
713 pair (newm, existm) with the cluster list length. Prefer the
714 path with smaller cluster list length. */
715 if (newm == existm) {
716 if (peer_sort(new->peer) == BGP_PEER_IBGP
717 && peer_sort(exist->peer) == BGP_PEER_IBGP
718 && (mpath_cfg == NULL
719 || CHECK_FLAG(
720 mpath_cfg->ibgp_flags,
721 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
722 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
723 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
724
725 if (newm < existm) {
726 if (debug)
727 zlog_debug(
728 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
729 pfx_buf, new_buf, exist_buf,
730 newm, existm);
731 ret = 1;
732 }
733
734 if (newm > existm) {
735 if (debug)
736 zlog_debug(
737 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
738 pfx_buf, new_buf, exist_buf,
739 newm, existm);
740 ret = 0;
741 }
742 }
743 }
31a4638f 744
d62a17ae 745 /* 10. confed-external vs. confed-internal */
746 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
747 if (new_sort == BGP_PEER_CONFED
748 && exist_sort == BGP_PEER_IBGP) {
749 if (debug)
750 zlog_debug(
751 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
752 pfx_buf, new_buf, exist_buf);
753 return 1;
754 }
718e3744 755
d62a17ae 756 if (exist_sort == BGP_PEER_CONFED
757 && new_sort == BGP_PEER_IBGP) {
758 if (debug)
759 zlog_debug(
760 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
761 pfx_buf, new_buf, exist_buf);
762 return 0;
763 }
764 }
718e3744 765
d62a17ae 766 /* 11. Maximum path check. */
767 if (newm == existm) {
768 /* If one path has a label but the other does not, do not treat
769 * them as equals for multipath
770 */
771 if ((new->extra &&bgp_is_valid_label(&new->extra->label))
772 != (exist->extra
773 && bgp_is_valid_label(&exist->extra->label))) {
774 if (debug)
775 zlog_debug(
776 "%s: %s and %s cannot be multipath, one has a label while the other does not",
777 pfx_buf, new_buf, exist_buf);
778 } else if (bgp_flag_check(bgp,
779 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
780
781 /*
782 * For the two paths, all comparison steps till IGP
783 * metric
784 * have succeeded - including AS_PATH hop count. Since
785 * 'bgp
786 * bestpath as-path multipath-relax' knob is on, we
787 * don't need
788 * an exact match of AS_PATH. Thus, mark the paths are
789 * equal.
790 * That will trigger both these paths to get into the
791 * multipath
792 * array.
793 */
794 *paths_eq = 1;
795
796 if (debug)
797 zlog_debug(
798 "%s: %s and %s are equal via multipath-relax",
799 pfx_buf, new_buf, exist_buf);
800 } else if (new->peer->sort == BGP_PEER_IBGP) {
801 if (aspath_cmp(new->attr->aspath,
802 exist->attr->aspath)) {
803 *paths_eq = 1;
804
805 if (debug)
806 zlog_debug(
807 "%s: %s and %s are equal via matching aspaths",
808 pfx_buf, new_buf, exist_buf);
809 }
810 } else if (new->peer->as == exist->peer->as) {
811 *paths_eq = 1;
812
813 if (debug)
814 zlog_debug(
815 "%s: %s and %s are equal via same remote-as",
816 pfx_buf, new_buf, exist_buf);
817 }
818 } else {
819 /*
820 * TODO: If unequal cost ibgp multipath is enabled we can
821 * mark the paths as equal here instead of returning
822 */
823 if (debug) {
824 if (ret == 1)
825 zlog_debug(
826 "%s: %s wins over %s after IGP metric comparison",
827 pfx_buf, new_buf, exist_buf);
828 else
829 zlog_debug(
830 "%s: %s loses to %s after IGP metric comparison",
831 pfx_buf, new_buf, exist_buf);
832 }
833 return ret;
834 }
718e3744 835
d62a17ae 836 /* 12. If both paths are external, prefer the path that was received
837 first (the oldest one). This step minimizes route-flap, since a
838 newer path won't displace an older one, even if it was the
839 preferred route based on the additional decision criteria below. */
840 if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
841 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
842 if (CHECK_FLAG(new->flags, BGP_INFO_SELECTED)) {
843 if (debug)
844 zlog_debug(
845 "%s: %s wins over %s due to oldest external",
846 pfx_buf, new_buf, exist_buf);
847 return 1;
848 }
9fbdd100 849
d62a17ae 850 if (CHECK_FLAG(exist->flags, BGP_INFO_SELECTED)) {
851 if (debug)
852 zlog_debug(
853 "%s: %s loses to %s due to oldest external",
854 pfx_buf, new_buf, exist_buf);
855 return 0;
856 }
857 }
718e3744 858
d62a17ae 859 /* 13. Router-ID comparision. */
860 /* If one of the paths is "stale", the corresponding peer router-id will
861 * be 0 and would always win over the other path. If originator id is
862 * used for the comparision, it will decide which path is better.
863 */
864 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
865 new_id.s_addr = newattr->originator_id.s_addr;
866 else
867 new_id.s_addr = new->peer->remote_id.s_addr;
868 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
869 exist_id.s_addr = existattr->originator_id.s_addr;
870 else
871 exist_id.s_addr = exist->peer->remote_id.s_addr;
872
873 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
874 if (debug)
875 zlog_debug(
876 "%s: %s wins over %s due to Router-ID comparison",
877 pfx_buf, new_buf, exist_buf);
878 return 1;
879 }
718e3744 880
d62a17ae 881 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
882 if (debug)
883 zlog_debug(
884 "%s: %s loses to %s due to Router-ID comparison",
885 pfx_buf, new_buf, exist_buf);
886 return 0;
887 }
9fbdd100 888
d62a17ae 889 /* 14. Cluster length comparision. */
890 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
891 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
892
893 if (new_cluster < exist_cluster) {
894 if (debug)
895 zlog_debug(
896 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
897 pfx_buf, new_buf, exist_buf, new_cluster,
898 exist_cluster);
899 return 1;
900 }
718e3744 901
d62a17ae 902 if (new_cluster > exist_cluster) {
903 if (debug)
904 zlog_debug(
905 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
906 pfx_buf, new_buf, exist_buf, new_cluster,
907 exist_cluster);
908 return 0;
909 }
9fbdd100 910
d62a17ae 911 /* 15. Neighbor address comparision. */
912 /* Do this only if neither path is "stale" as stale paths do not have
913 * valid peer information (as the connection may or may not be up).
914 */
915 if (CHECK_FLAG(exist->flags, BGP_INFO_STALE)) {
916 if (debug)
917 zlog_debug(
918 "%s: %s wins over %s due to latter path being STALE",
919 pfx_buf, new_buf, exist_buf);
920 return 1;
921 }
0de5153c 922
d62a17ae 923 if (CHECK_FLAG(new->flags, BGP_INFO_STALE)) {
924 if (debug)
925 zlog_debug(
926 "%s: %s loses to %s due to former path being STALE",
927 pfx_buf, new_buf, exist_buf);
928 return 0;
929 }
718e3744 930
d62a17ae 931 /* locally configured routes to advertise do not have su_remote */
932 if (new->peer->su_remote == NULL)
933 return 0;
934 if (exist->peer->su_remote == NULL)
935 return 1;
9fbdd100 936
d62a17ae 937 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
938
939 if (ret == 1) {
940 if (debug)
941 zlog_debug(
942 "%s: %s loses to %s due to Neighor IP comparison",
943 pfx_buf, new_buf, exist_buf);
944 return 0;
945 }
946
947 if (ret == -1) {
948 if (debug)
949 zlog_debug(
950 "%s: %s wins over %s due to Neighor IP comparison",
951 pfx_buf, new_buf, exist_buf);
952 return 1;
953 }
9fbdd100 954
d62a17ae 955 if (debug)
956 zlog_debug("%s: %s wins over %s due to nothing left to compare",
957 pfx_buf, new_buf, exist_buf);
718e3744 958
d62a17ae 959 return 1;
718e3744 960}
961
65efcfce
LB
962/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
963 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 964 * multipath is enabled
65efcfce 965 * This version is compatible with */
d62a17ae 966int bgp_info_cmp_compatible(struct bgp *bgp, struct bgp_info *new,
967 struct bgp_info *exist, char *pfx_buf, afi_t afi,
968 safi_t safi)
969{
970 int paths_eq;
971 int ret;
972 ret = bgp_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf, afi,
973 safi);
974
975 if (paths_eq)
976 ret = 0;
977 else {
978 if (ret == 1)
979 ret = -1;
980 else
981 ret = 1;
982 }
983 return ret;
65efcfce
LB
984}
985
d62a17ae 986static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
987 struct attr *attr, afi_t afi,
988 safi_t safi)
718e3744 989{
d62a17ae 990 struct bgp_filter *filter;
718e3744 991
d62a17ae 992 filter = &peer->filter[afi][safi];
718e3744 993
d62a17ae 994#define FILTER_EXIST_WARN(F, f, filter) \
995 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
996 zlog_warn("%s: Could not find configured input %s-list %s!", \
997 peer->host, #f, F##_IN_NAME(filter));
998
999 if (DISTRIBUTE_IN_NAME(filter)) {
1000 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1001
1002 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1003 return FILTER_DENY;
1004 }
1005
1006 if (PREFIX_LIST_IN_NAME(filter)) {
1007 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1008
1009 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1010 return FILTER_DENY;
1011 }
1012
1013 if (FILTER_LIST_IN_NAME(filter)) {
1014 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1015
1016 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1017 == AS_FILTER_DENY)
1018 return FILTER_DENY;
1019 }
1020
1021 return FILTER_PERMIT;
650f76c2 1022#undef FILTER_EXIST_WARN
718e3744 1023}
1024
d62a17ae 1025static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
1026 struct attr *attr, afi_t afi,
1027 safi_t safi)
718e3744 1028{
d62a17ae 1029 struct bgp_filter *filter;
1030
1031 filter = &peer->filter[afi][safi];
1032
1033#define FILTER_EXIST_WARN(F, f, filter) \
1034 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1035 zlog_warn("%s: Could not find configured output %s-list %s!", \
1036 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1037
d62a17ae 1038 if (DISTRIBUTE_OUT_NAME(filter)) {
1039 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1040
d62a17ae 1041 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1042 return FILTER_DENY;
1043 }
1044
1045 if (PREFIX_LIST_OUT_NAME(filter)) {
1046 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1047
d62a17ae 1048 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1049 == PREFIX_DENY)
1050 return FILTER_DENY;
1051 }
718e3744 1052
d62a17ae 1053 if (FILTER_LIST_OUT_NAME(filter)) {
1054 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1055
d62a17ae 1056 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1057 == AS_FILTER_DENY)
1058 return FILTER_DENY;
1059 }
718e3744 1060
d62a17ae 1061 return FILTER_PERMIT;
650f76c2 1062#undef FILTER_EXIST_WARN
718e3744 1063}
1064
1065/* If community attribute includes no_export then return 1. */
d62a17ae 1066static int bgp_community_filter(struct peer *peer, struct attr *attr)
1067{
1068 if (attr->community) {
1069 /* NO_ADVERTISE check. */
1070 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
1071 return 1;
1072
1073 /* NO_EXPORT check. */
1074 if (peer->sort == BGP_PEER_EBGP
1075 && community_include(attr->community, COMMUNITY_NO_EXPORT))
1076 return 1;
1077
1078 /* NO_EXPORT_SUBCONFED check. */
1079 if (peer->sort == BGP_PEER_EBGP
1080 || peer->sort == BGP_PEER_CONFED)
1081 if (community_include(attr->community,
1082 COMMUNITY_NO_EXPORT_SUBCONFED))
1083 return 1;
1084 }
1085 return 0;
718e3744 1086}
1087
1088/* Route reflection loop check. */
d62a17ae 1089static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1090{
d62a17ae 1091 struct in_addr cluster_id;
718e3744 1092
d62a17ae 1093 if (attr->cluster) {
1094 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1095 cluster_id = peer->bgp->cluster_id;
1096 else
1097 cluster_id = peer->bgp->router_id;
1098
1099 if (cluster_loop_check(attr->cluster, cluster_id))
1100 return 1;
1101 }
1102 return 0;
718e3744 1103}
6b0655a2 1104
d62a17ae 1105static int bgp_input_modifier(struct peer *peer, struct prefix *p,
1106 struct attr *attr, afi_t afi, safi_t safi,
1107 const char *rmap_name)
718e3744 1108{
d62a17ae 1109 struct bgp_filter *filter;
1110 struct bgp_info info;
1111 route_map_result_t ret;
1112 struct route_map *rmap = NULL;
718e3744 1113
d62a17ae 1114 filter = &peer->filter[afi][safi];
718e3744 1115
d62a17ae 1116 /* Apply default weight value. */
1117 if (peer->weight[afi][safi])
1118 attr->weight = peer->weight[afi][safi];
718e3744 1119
d62a17ae 1120 if (rmap_name) {
1121 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1122
d62a17ae 1123 if (rmap == NULL)
1124 return RMAP_DENY;
1125 } else {
1126 if (ROUTE_MAP_IN_NAME(filter)) {
1127 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1128
d62a17ae 1129 if (rmap == NULL)
1130 return RMAP_DENY;
1131 }
1132 }
0b16f239 1133
d62a17ae 1134 /* Route map apply. */
1135 if (rmap) {
1136 /* Duplicate current value to new strucutre for modification. */
1137 info.peer = peer;
1138 info.attr = attr;
718e3744 1139
d62a17ae 1140 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1141
d62a17ae 1142 /* Apply BGP route map to the attribute. */
1143 ret = route_map_apply(rmap, p, RMAP_BGP, &info);
0b16f239 1144
d62a17ae 1145 peer->rmap_type = 0;
0b16f239 1146
d62a17ae 1147 if (ret == RMAP_DENYMATCH) {
1148 /* Free newly generated AS path and community by
1149 * route-map. */
1150 bgp_attr_flush(attr);
1151 return RMAP_DENY;
1152 }
0b16f239 1153 }
d62a17ae 1154 return RMAP_PERMIT;
0b16f239
DS
1155}
1156
d62a17ae 1157static int bgp_output_modifier(struct peer *peer, struct prefix *p,
1158 struct attr *attr, afi_t afi, safi_t safi,
1159 const char *rmap_name)
0b16f239 1160{
d62a17ae 1161 struct bgp_filter *filter;
1162 struct bgp_info info;
1163 route_map_result_t ret;
1164 struct route_map *rmap = NULL;
0b16f239 1165
d62a17ae 1166 filter = &peer->filter[afi][safi];
0b16f239 1167
d62a17ae 1168 /* Apply default weight value. */
1169 if (peer->weight[afi][safi])
1170 attr->weight = peer->weight[afi][safi];
0b16f239 1171
d62a17ae 1172 if (rmap_name) {
1173 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1174
d62a17ae 1175 if (rmap == NULL)
1176 return RMAP_DENY;
1177 } else {
1178 if (ROUTE_MAP_OUT_NAME(filter)) {
1179 rmap = ROUTE_MAP_OUT(filter);
98a4a44e 1180
d62a17ae 1181 if (rmap == NULL)
1182 return RMAP_DENY;
1183 }
1184 }
0b16f239 1185
d62a17ae 1186 /* Route map apply. */
1187 if (rmap) {
1188 /* Duplicate current value to new strucutre for modification. */
1189 info.peer = peer;
1190 info.attr = attr;
0b16f239 1191
d62a17ae 1192 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1193
d62a17ae 1194 /* Apply BGP route map to the attribute. */
1195 ret = route_map_apply(rmap, p, RMAP_BGP, &info);
ac41b2a2 1196
d62a17ae 1197 peer->rmap_type = 0;
ac41b2a2 1198
d62a17ae 1199 if (ret == RMAP_DENYMATCH)
1200 /* caller has multiple error paths with bgp_attr_flush()
1201 */
1202 return RMAP_DENY;
1203 }
1204 return RMAP_PERMIT;
718e3744 1205}
6b0655a2 1206
5000f21c 1207/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1208static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1209 struct peer *peer, struct attr *attr)
1210{
1211 if (peer->sort == BGP_PEER_EBGP
1212 && (peer_af_flag_check(peer, afi, safi,
1213 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1214 || peer_af_flag_check(peer, afi, safi,
1215 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1216 || peer_af_flag_check(peer, afi, safi,
1217 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1218 || peer_af_flag_check(peer, afi, safi,
1219 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1220 // Take action on the entire aspath
1221 if (peer_af_flag_check(peer, afi, safi,
1222 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1223 || peer_af_flag_check(peer, afi, safi,
1224 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1225 if (peer_af_flag_check(
1226 peer, afi, safi,
1227 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1228 attr->aspath = aspath_replace_private_asns(
1229 attr->aspath, bgp->as);
1230
1231 // The entire aspath consists of private ASNs so create
1232 // an empty aspath
1233 else if (aspath_private_as_check(attr->aspath))
1234 attr->aspath = aspath_empty_get();
1235
1236 // There are some public and some private ASNs, remove
1237 // the private ASNs
1238 else
1239 attr->aspath = aspath_remove_private_asns(
1240 attr->aspath);
1241 }
1242
1243 // 'all' was not specified so the entire aspath must be private
1244 // ASNs
1245 // for us to do anything
1246 else if (aspath_private_as_check(attr->aspath)) {
1247 if (peer_af_flag_check(
1248 peer, afi, safi,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1250 attr->aspath = aspath_replace_private_asns(
1251 attr->aspath, bgp->as);
1252 else
1253 attr->aspath = aspath_empty_get();
1254 }
1255 }
5000f21c
DS
1256}
1257
c7122e14 1258/* If this is an EBGP peer with as-override */
d62a17ae 1259static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1260 struct peer *peer, struct attr *attr)
1261{
1262 if (peer->sort == BGP_PEER_EBGP
1263 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1264 if (aspath_single_asn_check(attr->aspath, peer->as))
1265 attr->aspath = aspath_replace_specific_asn(
1266 attr->aspath, peer->as, bgp->as);
1267 }
1268}
1269
1270static void subgroup_announce_reset_nhop(u_char family, struct attr *attr)
c7122e14 1271{
d62a17ae 1272 if (family == AF_INET)
1273 attr->nexthop.s_addr = 0;
1274 if (family == AF_INET6)
1275 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
c7122e14
DS
1276}
1277
d62a17ae 1278int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
1279 struct update_subgroup *subgrp, struct prefix *p,
1280 struct attr *attr)
1281{
1282 struct bgp_filter *filter;
1283 struct peer *from;
1284 struct peer *peer;
1285 struct peer *onlypeer;
1286 struct bgp *bgp;
1287 struct attr *riattr;
1288 struct peer_af *paf;
1289 char buf[PREFIX_STRLEN];
1290 int ret;
1291 int transparent;
1292 int reflect;
1293 afi_t afi;
1294 safi_t safi;
1295 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1296
1297 if (DISABLE_BGP_ANNOUNCE)
1298 return 0;
1299
1300 afi = SUBGRP_AFI(subgrp);
1301 safi = SUBGRP_SAFI(subgrp);
1302 peer = SUBGRP_PEER(subgrp);
1303 onlypeer = NULL;
1304 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1305 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1306
1307 from = ri->peer;
1308 filter = &peer->filter[afi][safi];
1309 bgp = SUBGRP_INST(subgrp);
1310 riattr = bgp_info_mpath_count(ri) ? bgp_info_mpath_attr(ri) : ri->attr;
3f9c7369 1311
65efcfce 1312#if ENABLE_BGP_VNC
d62a17ae 1313 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1314 && ((ri->type == ZEBRA_ROUTE_BGP_DIRECT)
1315 || (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1316
1317 /*
1318 * direct and direct_ext type routes originate internally even
1319 * though they can have peer pointers that reference other
1320 * systems
1321 */
1322 prefix2str(p, buf, PREFIX_STRLEN);
1323 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1324 __func__, buf);
1325 samepeer_safe = 1;
1326 }
65efcfce
LB
1327#endif
1328
d62a17ae 1329 /* With addpath we may be asked to TX all kinds of paths so make sure
1330 * ri is valid */
1331 if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID)
1332 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)
1333 || CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
1334 return 0;
1335 }
adbac85e 1336
d62a17ae 1337 /* If this is not the bestpath then check to see if there is an enabled
1338 * addpath
1339 * feature that requires us to advertise it */
1340 if (!CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
1341 if (!bgp_addpath_tx_path(peer, afi, safi, ri)) {
1342 return 0;
1343 }
1344 }
06370dac 1345
d62a17ae 1346 /* Aggregate-address suppress check. */
1347 if (ri->extra && ri->extra->suppress)
1348 if (!UNSUPPRESS_MAP_NAME(filter)) {
1349 return 0;
1350 }
3f9c7369 1351
d62a17ae 1352 /* If it's labeled safi, make sure the route has a valid label. */
1353 if (safi == SAFI_LABELED_UNICAST) {
1354 mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi);
1355 if (!bgp_is_valid_label(&label)) {
1356 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1357 zlog_debug("u%" PRIu64 ":s%" PRIu64
1358 " %s/%d is filtered - no label (%p)",
1359 subgrp->update_group->id, subgrp->id,
1360 inet_ntop(p->family, &p->u.prefix,
1361 buf, SU_ADDRSTRLEN),
1362 p->prefixlen, &label);
1363 return 0;
1364 }
1365 }
cd1964ff 1366
d62a17ae 1367 /* Do not send back route to sender. */
1368 if (onlypeer && from == onlypeer) {
1369 return 0;
1370 }
3f9c7369 1371
d62a17ae 1372 /* Do not send the default route in the BGP table if the neighbor is
1373 * configured for default-originate */
1374 if (CHECK_FLAG(peer->af_flags[afi][safi],
1375 PEER_FLAG_DEFAULT_ORIGINATE)) {
1376 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1377 return 0;
1378 else if (p->family == AF_INET6 && p->prefixlen == 0)
1379 return 0;
1380 }
4125bb67 1381
d62a17ae 1382 /* Transparency check. */
1383 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1384 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1385 transparent = 1;
1386 else
1387 transparent = 0;
1388
1389 /* If community is not disabled check the no-export and local. */
1390 if (!transparent && bgp_community_filter(peer, riattr)) {
1391 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1392 zlog_debug(
1393 "subgrpannouncecheck: community filter check fail");
1394 return 0;
1395 }
3f9c7369 1396
d62a17ae 1397 /* If the attribute has originator-id and it is same as remote
1398 peer's id. */
1399 if (onlypeer && riattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1400 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &riattr->originator_id))) {
1401 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1402 zlog_debug(
1403 "%s [Update:SEND] %s originator-id is same as "
1404 "remote router-id",
1405 onlypeer->host,
1406 prefix2str(p, buf, sizeof(buf)));
1407 return 0;
1408 }
3f9c7369 1409
d62a17ae 1410 /* ORF prefix-list filter check */
1411 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1412 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1413 || CHECK_FLAG(peer->af_cap[afi][safi],
1414 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1415 if (peer->orf_plist[afi][safi]) {
1416 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1417 == PREFIX_DENY) {
1418 if (bgp_debug_update(NULL, p,
1419 subgrp->update_group, 0))
1420 zlog_debug(
1421 "%s [Update:SEND] %s is filtered via ORF",
1422 peer->host,
1423 prefix2str(p, buf,
1424 sizeof(buf)));
1425 return 0;
1426 }
1427 }
1428
1429 /* Output filter check. */
1430 if (bgp_output_filter(peer, p, riattr, afi, safi) == FILTER_DENY) {
1431 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1432 zlog_debug("%s [Update:SEND] %s is filtered",
1433 peer->host, prefix2str(p, buf, sizeof(buf)));
1434 return 0;
1435 }
3f9c7369
DS
1436
1437#ifdef BGP_SEND_ASPATH_CHECK
d62a17ae 1438 /* AS path loop check. */
1439 if (onlypeer && aspath_loop_check(riattr->aspath, onlypeer->as)) {
1440 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1441 zlog_debug(
1442 "%s [Update:SEND] suppress announcement to peer AS %u "
1443 "that is part of AS path.",
1444 onlypeer->host, onlypeer->as);
1445 return 0;
1446 }
3f9c7369
DS
1447#endif /* BGP_SEND_ASPATH_CHECK */
1448
d62a17ae 1449 /* If we're a CONFED we need to loop check the CONFED ID too */
1450 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1451 if (aspath_loop_check(riattr->aspath, bgp->confed_id)) {
1452 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1453 zlog_debug(
1454 "%s [Update:SEND] suppress announcement to peer AS %u"
1455 " is AS path.",
1456 peer->host, bgp->confed_id);
1457 return 0;
1458 }
3f9c7369 1459 }
3f9c7369 1460
d62a17ae 1461 /* Route-Reflect check. */
1462 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1463 reflect = 1;
1464 else
1465 reflect = 0;
1466
1467 /* IBGP reflection check. */
1468 if (reflect && !samepeer_safe) {
1469 /* A route from a Client peer. */
1470 if (CHECK_FLAG(from->af_flags[afi][safi],
1471 PEER_FLAG_REFLECTOR_CLIENT)) {
1472 /* Reflect to all the Non-Client peers and also to the
1473 Client peers other than the originator. Originator
1474 check
1475 is already done. So there is noting to do. */
1476 /* no bgp client-to-client reflection check. */
1477 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1478 if (CHECK_FLAG(peer->af_flags[afi][safi],
1479 PEER_FLAG_REFLECTOR_CLIENT))
1480 return 0;
1481 } else {
1482 /* A route from a Non-client peer. Reflect to all other
1483 clients. */
1484 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1485 PEER_FLAG_REFLECTOR_CLIENT))
1486 return 0;
1487 }
1488 }
3f9c7369 1489
d62a17ae 1490 /* For modify attribute, copy it to temporary structure. */
1491 bgp_attr_dup(attr, riattr);
1492
1493 /* If local-preference is not set. */
1494 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1495 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1496 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1497 attr->local_pref = bgp->default_local_pref;
3f9c7369 1498 }
3f9c7369 1499
d62a17ae 1500 /* If originator-id is not set and the route is to be reflected,
1501 set the originator id */
1502 if (reflect
1503 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1504 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1505 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1506 }
3f9c7369 1507
d62a17ae 1508 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1509 */
1510 if (peer->sort == BGP_PEER_EBGP
1511 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1512 if (from != bgp->peer_self && !transparent
1513 && !CHECK_FLAG(peer->af_flags[afi][safi],
1514 PEER_FLAG_MED_UNCHANGED))
1515 attr->flag &=
1516 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1517 }
3f9c7369 1518
d62a17ae 1519 /* Since the nexthop attribute can vary per peer, it is not explicitly
1520 * set
1521 * in announce check, only certain flags and length (or number of
1522 * nexthops
1523 * -- for IPv6/MP_REACH) are set here in order to guide the update
1524 * formation
1525 * code in setting the nexthop(s) on a per peer basis in
1526 * reformat_peer().
1527 * Typically, the source nexthop in the attribute is preserved but in
1528 * the
1529 * scenarios where we know it will always be overwritten, we reset the
1530 * nexthop to "0" in an attempt to achieve better Update packing. An
1531 * example of this is when a prefix from each of 2 IBGP peers needs to
1532 * be
1533 * announced to an EBGP peer (and they have the same attributes barring
1534 * their nexthop).
1535 */
1536 if (reflect)
1537 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1538
1539#define NEXTHOP_IS_V6 \
1540 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1541 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1542 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1543 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1544
1545 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1546 * if
1547 * the peer (group) is configured to receive link-local nexthop
1548 * unchanged
1549 * and it is available in the prefix OR we're not reflecting the route
1550 * and
1551 * the peer (group) to whom we're going to announce is on a shared
1552 * network
1553 * and this is either a self-originated route or the peer is EBGP.
1554 */
1555 if (NEXTHOP_IS_V6) {
1556 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1557 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1558 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1559 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
1560 || (!reflect && peer->shared_network
1561 && (from == bgp->peer_self
1562 || peer->sort == BGP_PEER_EBGP))) {
1563 attr->mp_nexthop_len =
1564 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1565 }
3f9c7369 1566
d62a17ae 1567 /* Clear off link-local nexthop in source, whenever it is not
1568 * needed to
1569 * ensure more prefixes share the same attribute for
1570 * announcement.
1571 */
1572 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1573 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1574 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1575 }
3f9c7369 1576
d62a17ae 1577 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1578 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1579
1580 /* Route map & unsuppress-map apply. */
1581 if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) {
1582 struct bgp_info info;
16f7ce2b 1583 struct bgp_info_extra dummy_info_extra;
d62a17ae 1584 struct attr dummy_attr;
1585
1586 info.peer = peer;
1587 info.attr = attr;
d37ba549 1588
16f7ce2b
MK
1589 if (ri->extra) {
1590 memcpy(&dummy_info_extra, ri->extra,
1591 sizeof(struct bgp_info_extra));
1592 info.extra = &dummy_info_extra;
1593 }
1594
d62a17ae 1595 /* don't confuse inbound and outbound setting */
1596 RESET_FLAG(attr->rmap_change_flags);
1597
1598 /*
1599 * The route reflector is not allowed to modify the attributes
1600 * of the reflected IBGP routes unless explicitly allowed.
1601 */
1602 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1603 && !bgp_flag_check(bgp,
1604 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1605 bgp_attr_dup(&dummy_attr, attr);
1606 info.attr = &dummy_attr;
1607 }
3f9c7369 1608
d62a17ae 1609 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1610
d62a17ae 1611 if (ri->extra && ri->extra->suppress)
1612 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1613 RMAP_BGP, &info);
1614 else
1615 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1616 RMAP_BGP, &info);
1617
1618 peer->rmap_type = 0;
1619
1620 if (ret == RMAP_DENYMATCH) {
1621 bgp_attr_flush(attr);
1622 return 0;
1623 }
3f9c7369 1624 }
3f9c7369 1625
d62a17ae 1626 /* After route-map has been applied, we check to see if the nexthop to
1627 * be carried in the attribute (that is used for the announcement) can
1628 * be cleared off or not. We do this in all cases where we would be
1629 * setting the nexthop to "ourselves". For IPv6, we only need to
1630 * consider
1631 * the global nexthop here; the link-local nexthop would have been
1632 * cleared
1633 * already, and if not, it is required by the update formation code.
1634 * Also see earlier comments in this function.
1635 */
1636 /*
1637 * If route-map has performed some operation on the nexthop or the peer
1638 * configuration says to pass it unchanged, we cannot reset the nexthop
1639 * here, so only attempt to do it if these aren't true. Note that the
1640 * route-map handler itself might have cleared the nexthop, if for
1641 * example,
1642 * it is configured as 'peer-address'.
1643 */
1644 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
1645 riattr->rmap_change_flags)
1646 && !transparent
1647 && !CHECK_FLAG(peer->af_flags[afi][safi],
1648 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1649 /* We can reset the nexthop, if setting (or forcing) it to
1650 * 'self' */
1651 if (CHECK_FLAG(peer->af_flags[afi][safi],
1652 PEER_FLAG_NEXTHOP_SELF)
1653 || CHECK_FLAG(peer->af_flags[afi][safi],
1654 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1655 if (!reflect
1656 || CHECK_FLAG(peer->af_flags[afi][safi],
1657 PEER_FLAG_FORCE_NEXTHOP_SELF))
1658 subgroup_announce_reset_nhop(
1659 (peer_cap_enhe(peer, afi, safi)
1660 ? AF_INET6
1661 : p->family),
1662 attr);
1663 } else if (peer->sort == BGP_PEER_EBGP) {
1664 /* Can also reset the nexthop if announcing to EBGP, but
1665 * only if
1666 * no peer in the subgroup is on a shared subnet.
1667 * Note: 3rd party nexthop currently implemented for
1668 * IPv4 only.
1669 */
1670 SUBGRP_FOREACH_PEER(subgrp, paf)
1671 {
1672 if (bgp_multiaccess_check_v4(riattr->nexthop,
1673 paf->peer))
1674 break;
1675 }
1676 if (!paf)
1677 subgroup_announce_reset_nhop(
1678 (peer_cap_enhe(peer, afi, safi)
1679 ? AF_INET6
1680 : p->family),
1681 attr);
1682 }
1683 /* If IPv6/MP and nexthop does not have any override and happens
1684 * to
1685 * be a link-local address, reset it so that we don't pass along
1686 * the
1687 * source's link-local IPv6 address to recipients who may not be
1688 * on
1689 * the same interface.
1690 */
1691 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1692 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1693 subgroup_announce_reset_nhop(AF_INET6, attr);
1694 }
1695 }
3f9c7369 1696
d62a17ae 1697 return 1;
3f9c7369
DS
1698}
1699
d62a17ae 1700void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1701 struct bgp_maxpaths_cfg *mpath_cfg,
1702 struct bgp_info_pair *result, afi_t afi, safi_t safi)
1703{
1704 struct bgp_info *new_select;
1705 struct bgp_info *old_select;
1706 struct bgp_info *ri;
1707 struct bgp_info *ri1;
1708 struct bgp_info *ri2;
1709 struct bgp_info *nextri = NULL;
1710 int paths_eq, do_mpath, debug;
1711 struct list mp_list;
1712 char pfx_buf[PREFIX2STR_BUFFER];
1713 char path_buf[PATH_ADDPATH_STR_BUFFER];
1714
1715 bgp_mp_list_init(&mp_list);
1716 do_mpath =
1717 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1718
1719 debug = bgp_debug_bestpath(&rn->p);
1720
1721 if (debug)
1722 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1723
1724 /* bgp deterministic-med */
1725 new_select = NULL;
1726 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1727
1728 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1729 for (ri1 = rn->info; ri1; ri1 = ri1->next)
1730 bgp_info_unset_flag(rn, ri1, BGP_INFO_DMED_SELECTED);
1731
1732 for (ri1 = rn->info; ri1; ri1 = ri1->next) {
1733 if (CHECK_FLAG(ri1->flags, BGP_INFO_DMED_CHECK))
1734 continue;
1735 if (BGP_INFO_HOLDDOWN(ri1))
1736 continue;
1737 if (ri1->peer && ri1->peer != bgp->peer_self)
1738 if (ri1->peer->status != Established)
1739 continue;
1740
1741 new_select = ri1;
1742 if (ri1->next) {
1743 for (ri2 = ri1->next; ri2; ri2 = ri2->next) {
1744 if (CHECK_FLAG(ri2->flags,
1745 BGP_INFO_DMED_CHECK))
1746 continue;
1747 if (BGP_INFO_HOLDDOWN(ri2))
1748 continue;
1749 if (ri2->peer
1750 && ri2->peer != bgp->peer_self
1751 && !CHECK_FLAG(
1752 ri2->peer->sflags,
1753 PEER_STATUS_NSF_WAIT))
1754 if (ri2->peer->status
1755 != Established)
1756 continue;
1757
1758 if (aspath_cmp_left(ri1->attr->aspath,
1759 ri2->attr->aspath)
1760 || aspath_cmp_left_confed(
1761 ri1->attr->aspath,
1762 ri2->attr->aspath)) {
1763 if (bgp_info_cmp(bgp, ri2,
1764 new_select,
1765 &paths_eq,
1766 mpath_cfg,
1767 debug, pfx_buf,
1768 afi, safi)) {
1769 bgp_info_unset_flag(
1770 rn, new_select,
1771 BGP_INFO_DMED_SELECTED);
1772 new_select = ri2;
1773 }
1774
1775 bgp_info_set_flag(
1776 rn, ri2,
1777 BGP_INFO_DMED_CHECK);
1778 }
1779 }
1780 }
1781 bgp_info_set_flag(rn, new_select, BGP_INFO_DMED_CHECK);
1782 bgp_info_set_flag(rn, new_select,
1783 BGP_INFO_DMED_SELECTED);
1784
1785 if (debug) {
1786 bgp_info_path_with_addpath_rx_str(new_select,
1787 path_buf);
1788 zlog_debug("%s: %s is the bestpath from AS %d",
1789 pfx_buf, path_buf,
1790 aspath_get_first_as(
1791 new_select->attr->aspath));
1792 }
1793 }
1794 }
96450faf 1795
d62a17ae 1796 /* Check old selected route and new selected route. */
1797 old_select = NULL;
1798 new_select = NULL;
1799 for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1);
1800 ri = nextri) {
1801 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED))
1802 old_select = ri;
1803
1804 if (BGP_INFO_HOLDDOWN(ri)) {
1805 /* reap REMOVED routes, if needs be
1806 * selected route must stay for a while longer though
1807 */
1808 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
1809 && (ri != old_select))
1810 bgp_info_reap(rn, ri);
1811
1812 continue;
1813 }
96450faf 1814
d62a17ae 1815 if (ri->peer && ri->peer != bgp->peer_self
1816 && !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT))
1817 if (ri->peer->status != Established)
1818 continue;
9fbdd100 1819
d62a17ae 1820 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
1821 && (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) {
1822 bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
1823 continue;
1824 }
9fbdd100 1825
d62a17ae 1826 bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
06370dac 1827
d62a17ae 1828 if (bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg,
1829 debug, pfx_buf, afi, safi)) {
1830 new_select = ri;
1831 }
1832 }
718e3744 1833
d62a17ae 1834 /* Now that we know which path is the bestpath see if any of the other
1835 * paths
1836 * qualify as multipaths
1837 */
1838 if (debug) {
1839 if (new_select)
1840 bgp_info_path_with_addpath_rx_str(new_select, path_buf);
1841 else
1842 sprintf(path_buf, "NONE");
1843 zlog_debug(
1844 "%s: After path selection, newbest is %s oldbest was %s",
1845 pfx_buf, path_buf,
1846 old_select ? old_select->peer->host : "NONE");
96450faf 1847 }
9fbdd100 1848
d62a17ae 1849 if (do_mpath && new_select) {
1850 for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1);
1851 ri = nextri) {
1852
1853 if (debug)
1854 bgp_info_path_with_addpath_rx_str(ri, path_buf);
1855
1856 if (ri == new_select) {
1857 if (debug)
1858 zlog_debug(
1859 "%s: %s is the bestpath, add to the multipath list",
1860 pfx_buf, path_buf);
1861 bgp_mp_list_add(&mp_list, ri);
1862 continue;
1863 }
1864
1865 if (BGP_INFO_HOLDDOWN(ri))
1866 continue;
1867
1868 if (ri->peer && ri->peer != bgp->peer_self
1869 && !CHECK_FLAG(ri->peer->sflags,
1870 PEER_STATUS_NSF_WAIT))
1871 if (ri->peer->status != Established)
1872 continue;
1873
1874 if (!bgp_info_nexthop_cmp(ri, new_select)) {
1875 if (debug)
1876 zlog_debug(
1877 "%s: %s has the same nexthop as the bestpath, skip it",
1878 pfx_buf, path_buf);
1879 continue;
1880 }
1881
1882 bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg,
1883 debug, pfx_buf, afi, safi);
1884
1885 if (paths_eq) {
1886 if (debug)
1887 zlog_debug(
1888 "%s: %s is equivalent to the bestpath, add to the multipath list",
1889 pfx_buf, path_buf);
1890 bgp_mp_list_add(&mp_list, ri);
1891 }
1892 }
1893 }
fee0f4c6 1894
d62a17ae 1895 bgp_info_mpath_update(rn, new_select, old_select, &mp_list, mpath_cfg);
1896 bgp_info_mpath_aggregate_update(new_select, old_select);
1897 bgp_mp_list_clear(&mp_list);
96450faf 1898
d62a17ae 1899 result->old = old_select;
1900 result->new = new_select;
96450faf 1901
d62a17ae 1902 return;
fee0f4c6 1903}
1904
3f9c7369
DS
1905/*
1906 * A new route/change in bestpath of an existing route. Evaluate the path
1907 * for advertisement to the subgroup.
1908 */
d62a17ae 1909int subgroup_process_announce_selected(struct update_subgroup *subgrp,
1910 struct bgp_info *selected,
1911 struct bgp_node *rn,
1912 u_int32_t addpath_tx_id)
1913{
1914 struct prefix *p;
1915 struct peer *onlypeer;
1916 struct attr attr;
1917 afi_t afi;
1918 safi_t safi;
adbac85e 1919
d62a17ae 1920 p = &rn->p;
1921 afi = SUBGRP_AFI(subgrp);
1922 safi = SUBGRP_SAFI(subgrp);
1923 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
1924 : NULL);
1925
1926 /* First update is deferred until ORF or ROUTE-REFRESH is received */
9d303b37
DL
1927 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
1928 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 1929 return 0;
1930
1931 memset(&attr, 0, sizeof(struct attr));
1932 /* It's initialized in bgp_announce_check() */
1933
1934 /* Announcement to the subgroup. If the route is filtered withdraw it.
1935 */
1936 if (selected) {
1937 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
1938 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
1939 else
1940 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
1941 selected->addpath_tx_id);
1942 }
1943
1944 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1945 else {
1946 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
1947 }
558d1fec 1948
d62a17ae 1949 return 0;
200df115 1950}
fee0f4c6 1951
3064bf43 1952/*
e1072051 1953 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1954 * This is called at the end of route processing.
3064bf43 1955 */
d62a17ae 1956void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 1957{
d62a17ae 1958 struct bgp_info *ri;
3064bf43 1959
d62a17ae 1960 for (ri = rn->info; ri; ri = ri->next) {
1961 if (BGP_INFO_HOLDDOWN(ri))
1962 continue;
1963 UNSET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
1964 UNSET_FLAG(ri->flags, BGP_INFO_ATTR_CHANGED);
1965 }
3064bf43 1966}
1967
1968/*
1969 * Has the route changed from the RIB's perspective? This is invoked only
1970 * if the route selection returns the same best route as earlier - to
1971 * determine if we need to update zebra or not.
1972 */
d62a17ae 1973int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected)
1974{
1975 struct bgp_info *mpinfo;
1976
1977 /* If this is multipath, check all selected paths for any nexthop change
1978 * or
1979 * attribute change. Some attribute changes (e.g., community) aren't of
1980 * relevance to the RIB, but we'll update zebra to ensure we handle the
1981 * case of BGP nexthop change. This is the behavior when the best path
1982 * has
1983 * an attribute change anyway.
1984 */
1985 if (CHECK_FLAG(selected->flags, BGP_INFO_IGP_CHANGED)
1986 || CHECK_FLAG(selected->flags, BGP_INFO_MULTIPATH_CHG))
1987 return 1;
1988
1989 /* If this is multipath, check all selected paths for any nexthop change
1990 */
1991 for (mpinfo = bgp_info_mpath_first(selected); mpinfo;
1992 mpinfo = bgp_info_mpath_next(mpinfo)) {
1993 if (CHECK_FLAG(mpinfo->flags, BGP_INFO_IGP_CHANGED)
1994 || CHECK_FLAG(mpinfo->flags, BGP_INFO_ATTR_CHANGED))
1995 return 1;
1996 }
3064bf43 1997
d62a17ae 1998 /* Nothing has changed from the RIB's perspective. */
1999 return 0;
3064bf43 2000}
2001
d62a17ae 2002struct bgp_process_queue {
2003 struct bgp *bgp;
2004 struct bgp_node *rn;
2005 afi_t afi;
2006 safi_t safi;
200df115 2007};
2008
d62a17ae 2009static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
2010{
2011 struct bgp_process_queue *pq = data;
2012 struct bgp *bgp = pq->bgp;
2013 struct bgp_node *rn = pq->rn;
2014 afi_t afi = pq->afi;
2015 safi_t safi = pq->safi;
2016 struct prefix *p = &rn->p;
2017 struct bgp_info *new_select;
2018 struct bgp_info *old_select;
2019 struct bgp_info_pair old_and_new;
2020
2021 /* Is it end of initial update? (after startup) */
2022 if (!rn) {
2023 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2024 sizeof(bgp->update_delay_zebra_resume_time));
2025
2026 bgp->main_zebra_update_hold = 0;
2027 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2028 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
2029 if (bgp_fibupd_safi(safi))
2030 bgp_zebra_announce_table(bgp, afi,
2031 safi);
2032 }
2033 bgp->main_peers_update_hold = 0;
2034
2035 bgp_start_routeadv(bgp);
2036 return WQ_SUCCESS;
2037 }
cb1faec9 2038
d62a17ae 2039 /* Best path selection. */
2040 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2041 afi, safi);
2042 old_select = old_and_new.old;
2043 new_select = old_and_new.new;
2044
2045 /* Do we need to allocate or free labels?
2046 * Right now, since we only deal with per-prefix labels, it is not
cb499ebb 2047 * necessary to do this upon changes to best path except if the label
2048 * index changes.
2049 * NOTE: This is only relevant for the default instance.
d62a17ae 2050 */
cb499ebb 2051 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
2052 && safi == SAFI_UNICAST) {
d62a17ae 2053 if (new_select) {
2054 if (!old_select
2055 || bgp_label_index_differs(new_select, old_select)
2056 || new_select->sub_type != old_select->sub_type) {
2057 if (new_select->sub_type == BGP_ROUTE_STATIC
2058 && new_select->attr->flag
2059 & ATTR_FLAG_BIT(
2060 BGP_ATTR_PREFIX_SID)
2061 && new_select->attr->label_index
2062 != BGP_INVALID_LABEL_INDEX) {
2063 if (CHECK_FLAG(
2064 rn->flags,
2065 BGP_NODE_REGISTERED_FOR_LABEL))
2066 bgp_unregister_for_label(rn);
2067 label_ntop(MPLS_IMP_NULL_LABEL, 1,
2068 &rn->local_label);
2069 bgp_set_valid_label(&rn->local_label);
2070 } else
2071 bgp_register_for_label(rn, new_select);
2072 }
2073 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
2074 bgp_unregister_for_label(rn);
2075 }
cd1964ff 2076
d62a17ae 2077 /* If best route remains the same and this is not due to user-initiated
2078 * clear, see exactly what needs to be done.
2079 */
cd1964ff 2080
d62a17ae 2081 if (old_select && old_select == new_select
2082 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
2083 && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
2084 && !bgp->addpath_tx_used[afi][safi]) {
2085 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2086#if ENABLE_BGP_VNC
d62a17ae 2087 vnc_import_bgp_add_route(bgp, p, old_select);
2088 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2089#endif
bb744275 2090 if (bgp_fibupd_safi(safi)
d62a17ae 2091 && !bgp_option_check(BGP_OPT_NO_FIB)
2092 && new_select->type == ZEBRA_ROUTE_BGP
2093 && new_select->sub_type == BGP_ROUTE_NORMAL)
2094 bgp_zebra_announce(rn, p, old_select, bgp, afi,
2095 safi);
2096 }
2097 UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
2098 bgp_zebra_clear_route_change_flags(rn);
2099
2100 /* If there is a change of interest to peers, reannounce the
2101 * route. */
2102 if (CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
2103 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2104 group_announce_route(bgp, afi, safi, rn, new_select);
2105
2106 /* unicast routes must also be annouced to
2107 * labeled-unicast update-groups */
2108 if (safi == SAFI_UNICAST)
2109 group_announce_route(bgp, afi,
2110 SAFI_LABELED_UNICAST, rn,
2111 new_select);
2112
2113 UNSET_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED);
2114 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2115 }
fee0f4c6 2116
d62a17ae 2117 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
2118 return WQ_SUCCESS;
2119 }
8ad7271d 2120
d62a17ae 2121 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2122 */
2123 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2124
2125 /* bestpath has changed; bump version */
2126 if (old_select || new_select) {
2127 bgp_bump_version(rn);
2128
2129 if (!bgp->t_rmap_def_originate_eval) {
2130 bgp_lock(bgp);
2131 thread_add_timer(
2132 bm->master,
2133 update_group_refresh_default_originate_route_map,
2134 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2135 &bgp->t_rmap_def_originate_eval);
2136 }
2137 }
3f9c7369 2138
d62a17ae 2139 if (old_select)
2140 bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
2141 if (new_select) {
2142 bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
2143 bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
2144 UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
2145 }
338b3424 2146
65efcfce 2147#if ENABLE_BGP_VNC
d62a17ae 2148 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2149 if (old_select != new_select) {
2150 if (old_select) {
2151 vnc_import_bgp_exterior_del_route(bgp, p,
2152 old_select);
2153 vnc_import_bgp_del_route(bgp, p, old_select);
2154 }
2155 if (new_select) {
2156 vnc_import_bgp_exterior_add_route(bgp, p,
2157 new_select);
2158 vnc_import_bgp_add_route(bgp, p, new_select);
2159 }
2160 }
2161 }
65efcfce
LB
2162#endif
2163
d62a17ae 2164 group_announce_route(bgp, afi, safi, rn, new_select);
2165
2166 /* unicast routes must also be annouced to labeled-unicast update-groups
2167 */
2168 if (safi == SAFI_UNICAST)
2169 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2170 new_select);
2171
2172 /* FIB update. */
2173 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2174 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2175 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2176 && (new_select->sub_type == BGP_ROUTE_NORMAL
2177 || new_select->sub_type == BGP_ROUTE_AGGREGATE))
2178 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2179 else {
2180 /* Withdraw the route from the kernel. */
2181 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2182 && (old_select->sub_type == BGP_ROUTE_NORMAL
2183 || old_select->sub_type == BGP_ROUTE_AGGREGATE))
2184 bgp_zebra_withdraw(p, old_select, safi);
2185 }
718e3744 2186 }
3064bf43 2187
d62a17ae 2188 /* Clear any route change flags. */
2189 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2190
d62a17ae 2191 /* Reap old select bgp_info, if it has been removed */
2192 if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED))
2193 bgp_info_reap(rn, old_select);
2194
2195 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
2196 return WQ_SUCCESS;
718e3744 2197}
2198
d62a17ae 2199static void bgp_processq_del(struct work_queue *wq, void *data)
200df115 2200{
d62a17ae 2201 struct bgp_process_queue *pq = data;
2202 struct bgp_table *table;
cb1faec9 2203
d62a17ae 2204 bgp_unlock(pq->bgp);
2205 if (pq->rn) {
2206 table = bgp_node_table(pq->rn);
2207 bgp_unlock_node(pq->rn);
2208 bgp_table_unlock(table);
2209 }
2210 XFREE(MTYPE_BGP_PROCESS_QUEUE, pq);
200df115 2211}
2212
d62a17ae 2213void bgp_process_queue_init(void)
200df115 2214{
d62a17ae 2215 if (!bm->process_main_queue) {
2216 bm->process_main_queue =
2217 work_queue_new(bm->master, "process_main_queue");
2218
2219 if (!bm->process_main_queue) {
2220 zlog_err("%s: Failed to allocate work queue", __func__);
2221 exit(1);
2222 }
2223 }
2224
2225 bm->process_main_queue->spec.workfunc = &bgp_process_main;
2226 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2227 bm->process_main_queue->spec.max_retries = 0;
2228 bm->process_main_queue->spec.hold = 50;
2229 /* Use a higher yield value of 50ms for main queue processing */
2230 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2231}
2232
d62a17ae 2233void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2234{
d62a17ae 2235 struct bgp_process_queue *pqnode;
495f0b13 2236
d62a17ae 2237 /* already scheduled for processing? */
2238 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2239 return;
2e02b9b2 2240
d62a17ae 2241 if (bm->process_main_queue == NULL)
2242 return;
2243
2244 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2245 sizeof(struct bgp_process_queue));
2246 if (!pqnode)
2247 return;
228da428 2248
d62a17ae 2249 /* all unlocked in bgp_processq_del */
2250 bgp_table_lock(bgp_node_table(rn));
2251 pqnode->rn = bgp_lock_node(rn);
2252 pqnode->bgp = bgp;
2253 bgp_lock(bgp);
2254 pqnode->afi = afi;
2255 pqnode->safi = safi;
2256 work_queue_add(bm->process_main_queue, pqnode);
2257 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
2258 return;
fee0f4c6 2259}
0a486e5f 2260
d62a17ae 2261void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2262{
d62a17ae 2263 struct bgp_process_queue *pqnode;
cb1faec9 2264
d62a17ae 2265 if (bm->process_main_queue == NULL)
2266 return;
2e02b9b2 2267
d62a17ae 2268 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2269 sizeof(struct bgp_process_queue));
2270 if (!pqnode)
2271 return;
cb1faec9 2272
d62a17ae 2273 pqnode->rn = NULL;
2274 pqnode->bgp = bgp;
2275 bgp_lock(bgp);
2276 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2277}
2278
d62a17ae 2279static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2280{
d62a17ae 2281 struct peer *peer;
0a486e5f 2282
d62a17ae 2283 peer = THREAD_ARG(thread);
2284 peer->t_pmax_restart = NULL;
0a486e5f 2285
d62a17ae 2286 if (bgp_debug_neighbor_events(peer))
2287 zlog_debug(
2288 "%s Maximum-prefix restart timer expired, restore peering",
2289 peer->host);
0a486e5f 2290
d62a17ae 2291 peer_clear(peer, NULL);
0a486e5f 2292
d62a17ae 2293 return 0;
0a486e5f 2294}
2295
d62a17ae 2296int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2297 int always)
718e3744 2298{
d62a17ae 2299 iana_afi_t pkt_afi;
5c525538 2300 iana_safi_t pkt_safi;
9cabb64b 2301
d62a17ae 2302 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2303 return 0;
e0701b79 2304
d62a17ae 2305 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2306 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2307 PEER_STATUS_PREFIX_LIMIT)
2308 && !always)
2309 return 0;
e0701b79 2310
d62a17ae 2311 zlog_info(
2312 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2313 "limit %ld",
2314 afi_safi_print(afi, safi), peer->host,
2315 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2316 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2317
2318 if (CHECK_FLAG(peer->af_flags[afi][safi],
2319 PEER_FLAG_MAX_PREFIX_WARNING))
2320 return 0;
2321
2322 /* Convert AFI, SAFI to values for packet. */
2323 pkt_afi = afi_int2iana(afi);
2324 pkt_safi = safi_int2iana(safi);
2325 {
2326 u_int8_t ndata[7];
2327
2328 ndata[0] = (pkt_afi >> 8);
2329 ndata[1] = pkt_afi;
2330 ndata[2] = pkt_safi;
2331 ndata[3] = (peer->pmax[afi][safi] >> 24);
2332 ndata[4] = (peer->pmax[afi][safi] >> 16);
2333 ndata[5] = (peer->pmax[afi][safi] >> 8);
2334 ndata[6] = (peer->pmax[afi][safi]);
2335
2336 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2337 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2338 BGP_NOTIFY_CEASE_MAX_PREFIX,
2339 ndata, 7);
2340 }
2341
2342 /* Dynamic peers will just close their connection. */
2343 if (peer_dynamic_neighbor(peer))
2344 return 1;
2345
2346 /* restart timer start */
2347 if (peer->pmax_restart[afi][safi]) {
2348 peer->v_pmax_restart =
2349 peer->pmax_restart[afi][safi] * 60;
2350
2351 if (bgp_debug_neighbor_events(peer))
2352 zlog_debug(
2353 "%s Maximum-prefix restart timer started for %d secs",
2354 peer->host, peer->v_pmax_restart);
2355
2356 BGP_TIMER_ON(peer->t_pmax_restart,
2357 bgp_maximum_prefix_restart_timer,
2358 peer->v_pmax_restart);
2359 }
2360
2361 return 1;
2362 } else
2363 UNSET_FLAG(peer->af_sflags[afi][safi],
2364 PEER_STATUS_PREFIX_LIMIT);
2365
2366 if (peer->pcount[afi][safi]
2367 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2368 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2369 PEER_STATUS_PREFIX_THRESHOLD)
2370 && !always)
2371 return 0;
2372
2373 zlog_info(
2374 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2375 afi_safi_print(afi, safi), peer->host,
2376 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2377 SET_FLAG(peer->af_sflags[afi][safi],
2378 PEER_STATUS_PREFIX_THRESHOLD);
2379 } else
2380 UNSET_FLAG(peer->af_sflags[afi][safi],
2381 PEER_STATUS_PREFIX_THRESHOLD);
2382 return 0;
718e3744 2383}
2384
b40d939b 2385/* Unconditionally remove the route from the RIB, without taking
2386 * damping into consideration (eg, because the session went down)
2387 */
db0e1937 2388void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
d62a17ae 2389 struct peer *peer, afi_t afi, safi_t safi)
718e3744 2390{
d62a17ae 2391 bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
2392
2393 if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
2394 bgp_info_delete(rn, ri); /* keep historical info */
2395
2396 bgp_process(peer->bgp, rn, afi, safi);
2397}
2398
2399static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri,
2400 struct peer *peer, afi_t afi, safi_t safi,
2401 struct prefix_rd *prd)
2402{
2403 int status = BGP_DAMP_NONE;
2404
2405 /* apply dampening, if result is suppressed, we'll be retaining
2406 * the bgp_info in the RIB for historical reference.
2407 */
2408 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2409 && peer->sort == BGP_PEER_EBGP)
2410 if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0))
2411 == BGP_DAMP_SUPPRESSED) {
2412 bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi,
2413 safi);
2414 return;
2415 }
2416
65efcfce 2417#if ENABLE_BGP_VNC
d62a17ae 2418 if (safi == SAFI_MPLS_VPN) {
2419 struct bgp_node *prn = NULL;
2420 struct bgp_table *table = NULL;
2421
2422 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2423 (struct prefix *)prd);
2424 if (prn->info) {
2425 table = (struct bgp_table *)(prn->info);
2426
2427 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2428 peer->bgp, prd, table, &rn->p, ri);
2429 }
2430 bgp_unlock_node(prn);
2431 }
2432 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2433 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
65efcfce 2434
d62a17ae 2435 vnc_import_bgp_del_route(peer->bgp, &rn->p, ri);
2436 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
2437 ri);
2438 }
65efcfce 2439 }
d62a17ae 2440#endif
128ea8ab 2441
d62a17ae 2442 /* If this is an EVPN route, process for un-import. */
2443 if (safi == SAFI_EVPN)
2444 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, ri);
128ea8ab 2445
d62a17ae 2446 bgp_rib_remove(rn, ri, peer, afi, safi);
718e3744 2447}
2448
d62a17ae 2449struct bgp_info *info_make(int type, int sub_type, u_short instance,
2450 struct peer *peer, struct attr *attr,
2451 struct bgp_node *rn)
fb018d25 2452{
d62a17ae 2453 struct bgp_info *new;
fb018d25 2454
d62a17ae 2455 /* Make new BGP info. */
2456 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info));
2457 new->type = type;
2458 new->instance = instance;
2459 new->sub_type = sub_type;
2460 new->peer = peer;
2461 new->attr = attr;
2462 new->uptime = bgp_clock();
2463 new->net = rn;
2464 new->addpath_tx_id = ++peer->bgp->addpath_tx_id;
2465 return new;
fb018d25
DS
2466}
2467
d62a17ae 2468static void overlay_index_update(struct attr *attr,
2469 struct eth_segment_id *eth_s_id,
2470 union gw_addr *gw_ip)
684a7227 2471{
d62a17ae 2472 if (!attr)
2473 return;
684a7227 2474
d62a17ae 2475 if (eth_s_id == NULL) {
2476 memset(&(attr->evpn_overlay.eth_s_id), 0,
2477 sizeof(struct eth_segment_id));
2478 } else {
2479 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2480 sizeof(struct eth_segment_id));
2481 }
2482 if (gw_ip == NULL) {
2483 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2484 } else {
2485 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2486 sizeof(union gw_addr));
2487 }
684a7227
PG
2488}
2489
d62a17ae 2490static bool overlay_index_equal(afi_t afi, struct bgp_info *info,
2491 struct eth_segment_id *eth_s_id,
2492 union gw_addr *gw_ip)
2493{
2494 struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote;
2495 union gw_addr *info_gw_ip, *info_gw_ip_remote;
2496 char temp[16];
2497
2498 if (afi != AFI_L2VPN)
2499 return true;
2500 if (!info->attr) {
2501 memset(&temp, 0, 16);
2502 info_eth_s_id = (struct eth_segment_id *)&temp;
2503 info_gw_ip = (union gw_addr *)&temp;
2504 if (eth_s_id == NULL && gw_ip == NULL)
2505 return true;
2506 } else {
2507 info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id);
2508 info_gw_ip = &(info->attr->evpn_overlay.gw_ip);
2509 }
2510 if (gw_ip == NULL)
2511 info_gw_ip_remote = (union gw_addr *)&temp;
2512 else
2513 info_gw_ip_remote = gw_ip;
2514 if (eth_s_id == NULL)
2515 info_eth_s_id_remote = (struct eth_segment_id *)&temp;
2516 else
2517 info_eth_s_id_remote = eth_s_id;
2518 if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr)))
2519 return false;
2520 return !memcmp(info_eth_s_id, info_eth_s_id_remote,
2521 sizeof(struct eth_segment_id));
684a7227
PG
2522}
2523
c265ee22 2524/* Check if received nexthop is valid or not. */
d62a17ae 2525static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2526 struct attr *attr)
2527{
2528 int ret = 0;
2529
2530 /* Only validated for unicast and multicast currently. */
2531 /* Also valid for EVPN where the nexthop is an IP address. */
2532 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2533 return 0;
2534
2535 /* If NEXT_HOP is present, validate it. */
2536 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2537 if (attr->nexthop.s_addr == 0
2538 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2539 || bgp_nexthop_self(bgp, attr->nexthop))
2540 return 1;
2541 }
c265ee22 2542
d62a17ae 2543 /* If MP_NEXTHOP is present, validate it. */
2544 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2545 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2546 * it is not an IPv6 link-local address.
2547 */
2548 if (attr->mp_nexthop_len) {
2549 switch (attr->mp_nexthop_len) {
2550 case BGP_ATTR_NHLEN_IPV4:
2551 case BGP_ATTR_NHLEN_VPNV4:
2552 ret = (attr->mp_nexthop_global_in.s_addr == 0
2553 || IPV4_CLASS_DE(ntohl(
2554 attr->mp_nexthop_global_in.s_addr))
2555 || bgp_nexthop_self(bgp,
2556 attr->mp_nexthop_global_in));
2557 break;
2558
2559 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2560 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2561 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2562 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
2563 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
2564 || IN6_IS_ADDR_MULTICAST(
2565 &attr->mp_nexthop_global));
2566 break;
2567
2568 default:
2569 ret = 1;
2570 break;
2571 }
2572 }
c265ee22 2573
d62a17ae 2574 return ret;
2575}
2576
2577int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
2578 struct attr *attr, afi_t afi, safi_t safi, int type,
2579 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
2580 int soft_reconfig, struct bgp_route_evpn *evpn)
2581{
2582 int ret;
2583 int aspath_loop_count = 0;
2584 struct bgp_node *rn;
2585 struct bgp *bgp;
2586 struct attr new_attr;
2587 struct attr *attr_new;
2588 struct bgp_info *ri;
2589 struct bgp_info *new;
2590 const char *reason;
2591 char pfx_buf[BGP_PRD_PATH_STRLEN];
2592 char label_buf[20];
2593 int connected = 0;
2594 int do_loop_check = 1;
2595 int has_valid_label = 0;
65efcfce 2596#if ENABLE_BGP_VNC
d62a17ae 2597 int vnc_implicit_withdraw = 0;
65efcfce 2598#endif
d62a17ae 2599 int same_attr = 0;
718e3744 2600
d62a17ae 2601 memset(&new_attr, 0, sizeof(struct attr));
2602 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
2603 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 2604
d62a17ae 2605 bgp = peer->bgp;
2606 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
2607 has_valid_label = bgp_is_valid_label(label);
9bedbb1e 2608
d62a17ae 2609 if (has_valid_label)
2610 sprintf(label_buf, "label %u", label_pton(label));
718e3744 2611
d62a17ae 2612 /* When peer's soft reconfiguration enabled. Record input packet in
2613 Adj-RIBs-In. */
2614 if (!soft_reconfig
2615 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
2616 && peer != bgp->peer_self)
2617 bgp_adj_in_set(rn, peer, attr, addpath_id);
2618
2619 /* Check previously received route. */
2620 for (ri = rn->info; ri; ri = ri->next)
2621 if (ri->peer == peer && ri->type == type
2622 && ri->sub_type == sub_type
2623 && ri->addpath_rx_id == addpath_id)
2624 break;
2625
2626 /* AS path local-as loop check. */
2627 if (peer->change_local_as) {
2628 if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
2629 aspath_loop_count = 1;
2630
2631 if (aspath_loop_check(attr->aspath, peer->change_local_as)
2632 > aspath_loop_count) {
2633 reason = "as-path contains our own AS;";
2634 goto filtered;
2635 }
718e3744 2636 }
718e3744 2637
d62a17ae 2638 /* If the peer is configured for "allowas-in origin" and the last ASN in
2639 * the
2640 * as-path is our ASN then we do not need to call aspath_loop_check
2641 */
2642 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
2643 if (aspath_get_last_as(attr->aspath) == bgp->as)
2644 do_loop_check = 0;
2645
2646 /* AS path loop check. */
2647 if (do_loop_check) {
2648 if (aspath_loop_check(attr->aspath, bgp->as)
2649 > peer->allowas_in[afi][safi]
2650 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
2651 && aspath_loop_check(attr->aspath, bgp->confed_id)
2652 > peer->allowas_in[afi][safi])) {
2653 reason = "as-path contains our own AS;";
2654 goto filtered;
2655 }
2656 }
aac9ef6c 2657
d62a17ae 2658 /* Route reflector originator ID check. */
2659 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2660 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
2661 reason = "originator is us;";
2662 goto filtered;
2663 }
718e3744 2664
d62a17ae 2665 /* Route reflector cluster ID check. */
2666 if (bgp_cluster_filter(peer, attr)) {
2667 reason = "reflected from the same cluster;";
2668 goto filtered;
2669 }
718e3744 2670
d62a17ae 2671 /* Apply incoming filter. */
2672 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
2673 reason = "filter;";
2674 goto filtered;
2675 }
718e3744 2676
d62a17ae 2677 bgp_attr_dup(&new_attr, attr);
2678
2679 /* Apply incoming route-map.
2680 * NB: new_attr may now contain newly allocated values from route-map
2681 * "set"
2682 * commands, so we need bgp_attr_flush in the error paths, until we
2683 * intern
2684 * the attr (which takes over the memory references) */
2685 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
2686 == RMAP_DENY) {
2687 reason = "route-map;";
2688 bgp_attr_flush(&new_attr);
2689 goto filtered;
2690 }
718e3744 2691
d62a17ae 2692 /* next hop check. */
2693 if (bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
2694 reason = "martian or self next-hop;";
2695 bgp_attr_flush(&new_attr);
2696 goto filtered;
2697 }
718e3744 2698
d62a17ae 2699 attr_new = bgp_attr_intern(&new_attr);
2700
2701 /* If the update is implicit withdraw. */
2702 if (ri) {
2703 ri->uptime = bgp_clock();
2704 same_attr = attrhash_cmp(ri->attr, attr_new);
2705
2706 /* Same attribute comes in. */
2707 if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
2708 && attrhash_cmp(ri->attr, attr_new)
2709 && (!has_valid_label
2710 || memcmp(&(bgp_info_extra_get(ri))->label, label,
2711 BGP_LABEL_BYTES)
2712 == 0)
2713 && (overlay_index_equal(
2714 afi, ri, evpn == NULL ? NULL : &evpn->eth_s_id,
2715 evpn == NULL ? NULL : &evpn->gw_ip))) {
2716 if (CHECK_FLAG(bgp->af_flags[afi][safi],
2717 BGP_CONFIG_DAMPENING)
2718 && peer->sort == BGP_PEER_EBGP
2719 && CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) {
2720 if (bgp_debug_update(peer, p, NULL, 1)) {
2721 bgp_debug_rdpfxpath2str(
2722 afi, safi, prd, p, label,
2723 addpath_id ? 1 : 0, addpath_id,
2724 pfx_buf, sizeof(pfx_buf));
2725 zlog_debug("%s rcvd %s", peer->host,
2726 pfx_buf);
2727 }
2728
2729 if (bgp_damp_update(ri, rn, afi, safi)
2730 != BGP_DAMP_SUPPRESSED) {
2731 bgp_aggregate_increment(bgp, p, ri, afi,
2732 safi);
2733 bgp_process(bgp, rn, afi, safi);
2734 }
2735 } else /* Duplicate - odd */
2736 {
2737 if (bgp_debug_update(peer, p, NULL, 1)) {
2738 if (!peer->rcvd_attr_printed) {
2739 zlog_debug(
2740 "%s rcvd UPDATE w/ attr: %s",
2741 peer->host,
2742 peer->rcvd_attr_str);
2743 peer->rcvd_attr_printed = 1;
2744 }
2745
2746 bgp_debug_rdpfxpath2str(
2747 afi, safi, prd, p, label,
2748 addpath_id ? 1 : 0, addpath_id,
2749 pfx_buf, sizeof(pfx_buf));
2750 zlog_debug(
2751 "%s rcvd %s...duplicate ignored",
2752 peer->host, pfx_buf);
2753 }
2754
2755 /* graceful restart STALE flag unset. */
2756 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) {
2757 bgp_info_unset_flag(rn, ri,
2758 BGP_INFO_STALE);
2759 bgp_process(bgp, rn, afi, safi);
2760 }
2761 }
2762
2763 bgp_unlock_node(rn);
2764 bgp_attr_unintern(&attr_new);
2765
2766 return 0;
2767 }
718e3744 2768
d62a17ae 2769 /* Withdraw/Announce before we fully processed the withdraw */
2770 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
2771 if (bgp_debug_update(peer, p, NULL, 1)) {
2772 bgp_debug_rdpfxpath2str(
2773 afi, safi, prd, p, label,
2774 addpath_id ? 1 : 0, addpath_id, pfx_buf,
2775 sizeof(pfx_buf));
2776 zlog_debug(
2777 "%s rcvd %s, flapped quicker than processing",
2778 peer->host, pfx_buf);
2779 }
2780
2781 bgp_info_restore(rn, ri);
2782 }
718e3744 2783
d62a17ae 2784 /* Received Logging. */
2785 if (bgp_debug_update(peer, p, NULL, 1)) {
2786 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
2787 addpath_id ? 1 : 0, addpath_id,
2788 pfx_buf, sizeof(pfx_buf));
2789 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
2790 }
718e3744 2791
d62a17ae 2792 /* graceful restart STALE flag unset. */
2793 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
2794 bgp_info_unset_flag(rn, ri, BGP_INFO_STALE);
2795
2796 /* The attribute is changed. */
2797 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
2798
2799 /* implicit withdraw, decrement aggregate and pcount here.
2800 * only if update is accepted, they'll increment below.
2801 */
2802 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
2803
2804 /* Update bgp route dampening information. */
2805 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2806 && peer->sort == BGP_PEER_EBGP) {
2807 /* This is implicit withdraw so we should update
2808 dampening
2809 information. */
2810 if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
2811 bgp_damp_withdraw(ri, rn, afi, safi, 1);
2812 }
65efcfce 2813#if ENABLE_BGP_VNC
d62a17ae 2814 if (safi == SAFI_MPLS_VPN) {
2815 struct bgp_node *prn = NULL;
2816 struct bgp_table *table = NULL;
2817
2818 prn = bgp_node_get(bgp->rib[afi][safi],
2819 (struct prefix *)prd);
2820 if (prn->info) {
2821 table = (struct bgp_table *)(prn->info);
2822
2823 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2824 bgp, prd, table, p, ri);
2825 }
2826 bgp_unlock_node(prn);
2827 }
2828 if ((afi == AFI_IP || afi == AFI_IP6)
2829 && (safi == SAFI_UNICAST)) {
2830 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
2831 /*
2832 * Implicit withdraw case.
2833 */
2834 ++vnc_implicit_withdraw;
2835 vnc_import_bgp_del_route(bgp, p, ri);
2836 vnc_import_bgp_exterior_del_route(bgp, p, ri);
2837 }
2838 }
65efcfce 2839#endif
128ea8ab 2840
d62a17ae 2841 /* Special handling for EVPN update of an existing route. If the
2842 * extended community attribute has changed, we need to
2843 * un-import
2844 * the route using its existing extended community. It will be
2845 * subsequently processed for import with the new extended
2846 * community.
2847 */
2848 if (safi == SAFI_EVPN && !same_attr) {
2849 if ((ri->attr->flag
2850 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
2851 && (attr_new->flag
2852 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
2853 int cmp;
2854
2855 cmp = ecommunity_cmp(ri->attr->ecommunity,
2856 attr_new->ecommunity);
2857 if (!cmp) {
2858 if (bgp_debug_update(peer, p, NULL, 1))
2859 zlog_debug(
2860 "Change in EXT-COMM, existing %s new %s",
2861 ecommunity_str(
2862 ri->attr->ecommunity),
2863 ecommunity_str(
2864 attr_new->ecommunity));
2865 bgp_evpn_unimport_route(bgp, afi, safi,
2866 p, ri);
2867 }
2868 }
2869 }
718e3744 2870
d62a17ae 2871 /* Update to new attribute. */
2872 bgp_attr_unintern(&ri->attr);
2873 ri->attr = attr_new;
2874
2875 /* Update MPLS label */
2876 if (has_valid_label) {
2877 memcpy(&(bgp_info_extra_get(ri))->label, label,
2878 BGP_LABEL_BYTES);
2879 bgp_set_valid_label(&(bgp_info_extra_get(ri))->label);
fc9a856f 2880 }
718e3744 2881
65efcfce 2882#if ENABLE_BGP_VNC
d62a17ae 2883 if ((afi == AFI_IP || afi == AFI_IP6)
2884 && (safi == SAFI_UNICAST)) {
2885 if (vnc_implicit_withdraw) {
2886 /*
2887 * Add back the route with its new attributes
2888 * (e.g., nexthop).
2889 * The route is still selected, until the route
2890 * selection
2891 * queued by bgp_process actually runs. We have
2892 * to make this
2893 * update to the VNC side immediately to avoid
2894 * racing against
2895 * configuration changes (e.g., route-map
2896 * changes) which
2897 * trigger re-importation of the entire RIB.
2898 */
2899 vnc_import_bgp_add_route(bgp, p, ri);
2900 vnc_import_bgp_exterior_add_route(bgp, p, ri);
2901 }
2902 }
65efcfce 2903#endif
d62a17ae 2904 /* Update Overlay Index */
2905 if (afi == AFI_L2VPN) {
2906 overlay_index_update(
2907 ri->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
2908 evpn == NULL ? NULL : &evpn->gw_ip);
2909 }
65efcfce 2910
d62a17ae 2911 /* Update bgp route dampening information. */
2912 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2913 && peer->sort == BGP_PEER_EBGP) {
2914 /* Now we do normal update dampening. */
2915 ret = bgp_damp_update(ri, rn, afi, safi);
2916 if (ret == BGP_DAMP_SUPPRESSED) {
2917 bgp_unlock_node(rn);
2918 return 0;
2919 }
2920 }
128ea8ab 2921
d62a17ae 2922 /* Nexthop reachability check - for unicast and
2923 * labeled-unicast.. */
2924 if ((afi == AFI_IP || afi == AFI_IP6)
2925 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
2926 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
2927 && !CHECK_FLAG(peer->flags,
2928 PEER_FLAG_DISABLE_CONNECTED_CHECK)
2929 && !bgp_flag_check(
2930 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
2931 connected = 1;
2932 else
2933 connected = 0;
2934
2935 if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL,
2936 connected))
2937 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
2938 else {
2939 if (BGP_DEBUG(nht, NHT)) {
2940 char buf1[INET6_ADDRSTRLEN];
2941 inet_ntop(AF_INET,
2942 (const void *)&attr_new
2943 ->nexthop,
2944 buf1, INET6_ADDRSTRLEN);
2945 zlog_debug("%s(%s): NH unresolved",
2946 __FUNCTION__, buf1);
2947 }
2948 bgp_info_unset_flag(rn, ri, BGP_INFO_VALID);
2949 }
2950 } else
2951 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
2952
2953#if ENABLE_BGP_VNC
2954 if (safi == SAFI_MPLS_VPN) {
2955 struct bgp_node *prn = NULL;
2956 struct bgp_table *table = NULL;
2957
2958 prn = bgp_node_get(bgp->rib[afi][safi],
2959 (struct prefix *)prd);
2960 if (prn->info) {
2961 table = (struct bgp_table *)(prn->info);
2962
2963 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
2964 bgp, prd, table, p, ri);
2965 }
2966 bgp_unlock_node(prn);
2967 }
2968#endif
718e3744 2969
d62a17ae 2970 /* If this is an EVPN route and some attribute has changed,
2971 * process
2972 * route for import. If the extended community has changed, we
2973 * would
2974 * have done the un-import earlier and the import would result
2975 * in the
2976 * route getting injected into appropriate L2 VNIs. If it is
2977 * just
2978 * some other attribute change, the import will result in
2979 * updating
2980 * the attributes for the route in the VNI(s).
2981 */
2982 if (safi == SAFI_EVPN && !same_attr)
2983 bgp_evpn_import_route(bgp, afi, safi, p, ri);
2984
2985 /* Process change. */
2986 bgp_aggregate_increment(bgp, p, ri, afi, safi);
2987
2988 bgp_process(bgp, rn, afi, safi);
2989 bgp_unlock_node(rn);
558d1fec 2990
28070ee3 2991#if ENABLE_BGP_VNC
d62a17ae 2992 if (SAFI_MPLS_VPN == safi) {
2993 mpls_label_t label_decoded = decode_label(label);
28070ee3 2994
d62a17ae 2995 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
2996 type, sub_type, &label_decoded);
2997 }
2998 if (SAFI_ENCAP == safi) {
2999 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3000 type, sub_type, NULL);
3001 }
28070ee3
PZ
3002#endif
3003
d62a17ae 3004 return 0;
3005 } // End of implicit withdraw
718e3744 3006
d62a17ae 3007 /* Received Logging. */
3008 if (bgp_debug_update(peer, p, NULL, 1)) {
3009 if (!peer->rcvd_attr_printed) {
3010 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3011 peer->rcvd_attr_str);
3012 peer->rcvd_attr_printed = 1;
3013 }
718e3744 3014
d62a17ae 3015 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3016 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3017 sizeof(pfx_buf));
3018 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3019 }
718e3744 3020
d62a17ae 3021 /* Make new BGP info. */
3022 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3023
d62a17ae 3024 /* Update MPLS label */
3025 if (has_valid_label) {
3026 memcpy(&(bgp_info_extra_get(new))->label, label,
3027 BGP_LABEL_BYTES);
3028 bgp_set_valid_label(&(bgp_info_extra_get(new))->label);
fc9a856f 3029 }
718e3744 3030
d62a17ae 3031 /* Update Overlay Index */
3032 if (afi == AFI_L2VPN) {
3033 overlay_index_update(new->attr,
3034 evpn == NULL ? NULL : &evpn->eth_s_id,
3035 evpn == NULL ? NULL : &evpn->gw_ip);
3036 }
3037 /* Nexthop reachability check. */
3038 if ((afi == AFI_IP || afi == AFI_IP6)
3039 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3040 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3041 && !CHECK_FLAG(peer->flags,
3042 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3043 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3044 connected = 1;
3045 else
3046 connected = 0;
3047
3048 if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, connected))
3049 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
3050 else {
3051 if (BGP_DEBUG(nht, NHT)) {
3052 char buf1[INET6_ADDRSTRLEN];
3053 inet_ntop(AF_INET,
3054 (const void *)&attr_new->nexthop,
3055 buf1, INET6_ADDRSTRLEN);
3056 zlog_debug("%s(%s): NH unresolved",
3057 __FUNCTION__, buf1);
3058 }
3059 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
3060 }
3061 } else
3062 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
a82478b9 3063
d62a17ae 3064 /* Addpath ID */
3065 new->addpath_rx_id = addpath_id;
3066
3067 /* Increment prefix */
3068 bgp_aggregate_increment(bgp, p, new, afi, safi);
3069
3070 /* Register new BGP information. */
3071 bgp_info_add(rn, new);
3072
3073 /* route_node_get lock */
3074 bgp_unlock_node(rn);
558d1fec 3075
65efcfce 3076#if ENABLE_BGP_VNC
d62a17ae 3077 if (safi == SAFI_MPLS_VPN) {
3078 struct bgp_node *prn = NULL;
3079 struct bgp_table *table = NULL;
3080
3081 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
3082 if (prn->info) {
3083 table = (struct bgp_table *)(prn->info);
3084
3085 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3086 bgp, prd, table, p, new);
3087 }
3088 bgp_unlock_node(prn);
3089 }
65efcfce
LB
3090#endif
3091
d62a17ae 3092 /* If maximum prefix count is configured and current prefix
3093 count exeed it. */
3094 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3095 return -1;
718e3744 3096
d62a17ae 3097 /* If this is an EVPN route, process for import. */
3098 if (safi == SAFI_EVPN)
3099 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3100
d62a17ae 3101 /* Process change. */
3102 bgp_process(bgp, rn, afi, safi);
718e3744 3103
28070ee3 3104#if ENABLE_BGP_VNC
d62a17ae 3105 if (SAFI_MPLS_VPN == safi) {
3106 mpls_label_t label_decoded = decode_label(label);
28070ee3 3107
d62a17ae 3108 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3109 sub_type, &label_decoded);
3110 }
3111 if (SAFI_ENCAP == safi) {
3112 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3113 sub_type, NULL);
3114 }
28070ee3
PZ
3115#endif
3116
d62a17ae 3117 return 0;
718e3744 3118
d62a17ae 3119/* This BGP update is filtered. Log the reason then update BGP
3120 entry. */
3121filtered:
3122 if (bgp_debug_update(peer, p, NULL, 1)) {
3123 if (!peer->rcvd_attr_printed) {
3124 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3125 peer->rcvd_attr_str);
3126 peer->rcvd_attr_printed = 1;
3127 }
718e3744 3128
d62a17ae 3129 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3130 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3131 sizeof(pfx_buf));
3132 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3133 peer->host, pfx_buf, reason);
3134 }
128ea8ab 3135
d62a17ae 3136 if (ri) {
3137 /* If this is an EVPN route, un-import it as it is now filtered.
3138 */
3139 if (safi == SAFI_EVPN)
3140 bgp_evpn_unimport_route(bgp, afi, safi, p, ri);
718e3744 3141
d62a17ae 3142 bgp_rib_remove(rn, ri, peer, afi, safi);
3143 }
3144
3145 bgp_unlock_node(rn);
558d1fec 3146
97736e32 3147#if ENABLE_BGP_VNC
d62a17ae 3148 /*
3149 * Filtered update is treated as an implicit withdrawal (see
3150 * bgp_rib_remove()
3151 * a few lines above)
3152 */
3153 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3154 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3155 0);
3156 }
97736e32
PZ
3157#endif
3158
d62a17ae 3159 return 0;
718e3744 3160}
3161
d62a17ae 3162int bgp_withdraw(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
3163 struct attr *attr, afi_t afi, safi_t safi, int type,
3164 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3165 struct bgp_route_evpn *evpn)
718e3744 3166{
d62a17ae 3167 struct bgp *bgp;
3168 char pfx_buf[BGP_PRD_PATH_STRLEN];
3169 struct bgp_node *rn;
3170 struct bgp_info *ri;
718e3744 3171
28070ee3 3172#if ENABLE_BGP_VNC
d62a17ae 3173 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3174 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3175 0);
3176 }
28070ee3
PZ
3177#endif
3178
d62a17ae 3179 bgp = peer->bgp;
3180
3181 /* Lookup node. */
3182 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3183
3184 /* If peer is soft reconfiguration enabled. Record input packet for
3185 * further calculation.
3186 *
3187 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3188 * routes that are filtered. This tanks out Quagga RS pretty badly due
3189 * to
3190 * the iteration over all RS clients.
3191 * Since we need to remove the entry from adj_in anyway, do that first
3192 * and
3193 * if there was no entry, we don't need to do anything more.
3194 */
3195 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3196 && peer != bgp->peer_self)
3197 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
3198 if (bgp_debug_update(peer, p, NULL, 1)) {
3199 bgp_debug_rdpfxpath2str(
3200 afi, safi, prd, p, label,
3201 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3202 sizeof(pfx_buf));
3203 zlog_debug(
3204 "%s withdrawing route %s not in adj-in",
3205 peer->host, pfx_buf);
3206 }
3207 bgp_unlock_node(rn);
3208 return 0;
3209 }
cd808e74 3210
d62a17ae 3211 /* Lookup withdrawn route. */
3212 for (ri = rn->info; ri; ri = ri->next)
3213 if (ri->peer == peer && ri->type == type
3214 && ri->sub_type == sub_type
3215 && ri->addpath_rx_id == addpath_id)
3216 break;
3217
3218 /* Logging. */
3219 if (bgp_debug_update(peer, p, NULL, 1)) {
3220 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3221 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3222 sizeof(pfx_buf));
3223 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3224 pfx_buf);
3225 }
718e3744 3226
d62a17ae 3227 /* Withdraw specified route from routing table. */
3228 if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
3229 bgp_rib_withdraw(rn, ri, peer, afi, safi, prd);
3230 else if (bgp_debug_update(peer, p, NULL, 1)) {
3231 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3232 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3233 sizeof(pfx_buf));
3234 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3235 }
718e3744 3236
d62a17ae 3237 /* Unlock bgp_node_get() lock. */
3238 bgp_unlock_node(rn);
3239
3240 return 0;
718e3744 3241}
6b0655a2 3242
d62a17ae 3243void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3244 int withdraw)
718e3744 3245{
d62a17ae 3246 struct update_subgroup *subgrp;
3247 subgrp = peer_subgroup(peer, afi, safi);
3248 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3249}
6182d65b 3250
718e3744 3251
3f9c7369
DS
3252/*
3253 * bgp_stop_announce_route_timer
3254 */
d62a17ae 3255void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3256{
d62a17ae 3257 if (!paf->t_announce_route)
3258 return;
3259
3260 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3261}
6b0655a2 3262
3f9c7369
DS
3263/*
3264 * bgp_announce_route_timer_expired
3265 *
3266 * Callback that is invoked when the route announcement timer for a
3267 * peer_af expires.
3268 */
d62a17ae 3269static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3270{
d62a17ae 3271 struct peer_af *paf;
3272 struct peer *peer;
558d1fec 3273
d62a17ae 3274 paf = THREAD_ARG(t);
3275 peer = paf->peer;
718e3744 3276
d62a17ae 3277 if (peer->status != Established)
3278 return 0;
3f9c7369 3279
d62a17ae 3280 if (!peer->afc_nego[paf->afi][paf->safi])
3281 return 0;
3f9c7369 3282
d62a17ae 3283 peer_af_announce_route(paf, 1);
3284 return 0;
718e3744 3285}
3286
3f9c7369
DS
3287/*
3288 * bgp_announce_route
3289 *
3290 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3291 */
d62a17ae 3292void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3293{
3294 struct peer_af *paf;
3295 struct update_subgroup *subgrp;
3296
3297 paf = peer_af_find(peer, afi, safi);
3298 if (!paf)
3299 return;
3300 subgrp = PAF_SUBGRP(paf);
3301
3302 /*
3303 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3304 * or a refresh has already been triggered.
3305 */
3306 if (!subgrp || paf->t_announce_route)
3307 return;
3308
3309 /*
3310 * Start a timer to stagger/delay the announce. This serves
3311 * two purposes - announcement can potentially be combined for
3312 * multiple peers and the announcement doesn't happen in the
3313 * vty context.
3314 */
3315 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3316 (subgrp->peer_count == 1)
3317 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3318 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3319 &paf->t_announce_route);
3f9c7369
DS
3320}
3321
3322/*
3323 * Announce routes from all AF tables to a peer.
3324 *
3325 * This should ONLY be called when there is a need to refresh the
3326 * routes to the peer based on a policy change for this peer alone
3327 * or a route refresh request received from the peer.
3328 * The operation will result in splitting the peer from its existing
3329 * subgroups and putting it in new subgroups.
3330 */
d62a17ae 3331void bgp_announce_route_all(struct peer *peer)
718e3744 3332{
d62a17ae 3333 afi_t afi;
3334 safi_t safi;
3335
3336 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3337 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3338 bgp_announce_route(peer, afi, safi);
718e3744 3339}
6b0655a2 3340
d62a17ae 3341static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3342 struct bgp_table *table,
3343 struct prefix_rd *prd)
718e3744 3344{
d62a17ae 3345 int ret;
3346 struct bgp_node *rn;
3347 struct bgp_adj_in *ain;
718e3744 3348
d62a17ae 3349 if (!table)
3350 table = peer->bgp->rib[afi][safi];
718e3744 3351
d62a17ae 3352 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3353 for (ain = rn->adj_in; ain; ain = ain->next) {
3354 if (ain->peer == peer) {
3355 struct bgp_info *ri = rn->info;
3356 mpls_label_t label =
3357 (ri && ri->extra) ? ri->extra->label
3358 : MPLS_INVALID_LABEL;
8692c506 3359
d62a17ae 3360 ret = bgp_update(
3361 peer, &rn->p, ain->addpath_rx_id,
3362 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
3363 BGP_ROUTE_NORMAL, prd, &label, 1, NULL);
8692c506 3364
d62a17ae 3365 if (ret < 0) {
3366 bgp_unlock_node(rn);
3367 return;
3368 }
3369 }
3370 }
718e3744 3371}
3372
d62a17ae 3373void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3374{
d62a17ae 3375 struct bgp_node *rn;
3376 struct bgp_table *table;
718e3744 3377
d62a17ae 3378 if (peer->status != Established)
3379 return;
718e3744 3380
d62a17ae 3381 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3382 && (safi != SAFI_EVPN))
3383 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3384 else
3385 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3386 rn = bgp_route_next(rn))
3387 if ((table = rn->info) != NULL) {
3388 struct prefix_rd prd;
3389 prd.family = AF_UNSPEC;
3390 prd.prefixlen = 64;
3391 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3392
d62a17ae 3393 bgp_soft_reconfig_table(peer, afi, safi, table,
3394 &prd);
3395 }
718e3744 3396}
6b0655a2 3397
228da428 3398
d62a17ae 3399struct bgp_clear_node_queue {
3400 struct bgp_node *rn;
228da428
CC
3401};
3402
d62a17ae 3403static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3404{
d62a17ae 3405 struct bgp_clear_node_queue *cnq = data;
3406 struct bgp_node *rn = cnq->rn;
3407 struct peer *peer = wq->spec.data;
3408 struct bgp_info *ri;
3409 afi_t afi = bgp_node_table(rn)->afi;
3410 safi_t safi = bgp_node_table(rn)->safi;
3411
3412 assert(rn && peer);
3413
3414 /* It is possible that we have multiple paths for a prefix from a peer
3415 * if that peer is using AddPath.
3416 */
3417 for (ri = rn->info; ri; ri = ri->next)
3418 if (ri->peer == peer) {
3419 /* graceful restart STALE flag set. */
3420 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
3421 && peer->nsf[afi][safi]
3422 && !CHECK_FLAG(ri->flags, BGP_INFO_STALE)
3423 && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
3424 bgp_info_set_flag(rn, ri, BGP_INFO_STALE);
3425 else {
3426 /* If this is an EVPN route, process for
3427 * un-import. */
3428 if (safi == SAFI_EVPN)
3429 bgp_evpn_unimport_route(peer->bgp, afi,
3430 safi, &rn->p,
3431 ri);
3432 bgp_rib_remove(rn, ri, peer, afi, safi);
3433 }
3434 }
3435 return WQ_SUCCESS;
200df115 3436}
3437
d62a17ae 3438static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 3439{
d62a17ae 3440 struct bgp_clear_node_queue *cnq = data;
3441 struct bgp_node *rn = cnq->rn;
3442 struct bgp_table *table = bgp_node_table(rn);
228da428 3443
d62a17ae 3444 bgp_unlock_node(rn);
3445 bgp_table_unlock(table);
3446 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 3447}
3448
d62a17ae 3449static void bgp_clear_node_complete(struct work_queue *wq)
200df115 3450{
d62a17ae 3451 struct peer *peer = wq->spec.data;
64e580a7 3452
d62a17ae 3453 /* Tickle FSM to start moving again */
3454 BGP_EVENT_ADD(peer, Clearing_Completed);
3455
3456 peer_unlock(peer); /* bgp_clear_route */
200df115 3457}
718e3744 3458
d62a17ae 3459static void bgp_clear_node_queue_init(struct peer *peer)
200df115 3460{
d62a17ae 3461 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3462
3463 snprintf(wname, sizeof(wname), "clear %s", peer->host);
3464#undef CLEAR_QUEUE_NAME_LEN
3465
3466 if ((peer->clear_node_queue = work_queue_new(bm->master, wname))
3467 == NULL) {
3468 zlog_err("%s: Failed to allocate work queue", __func__);
3469 exit(1);
0c6262ed 3470 }
d62a17ae 3471 peer->clear_node_queue->spec.hold = 10;
3472 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
3473 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
3474 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
3475 peer->clear_node_queue->spec.max_retries = 0;
3476
3477 /* we only 'lock' this peer reference when the queue is actually active
3478 */
3479 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
3480}
3481
d62a17ae 3482static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
3483 struct bgp_table *table)
65ca75e0 3484{
d62a17ae 3485 struct bgp_node *rn;
3486 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 3487
d62a17ae 3488 if (!table)
3489 table = peer->bgp->rib[afi][safi];
dc83d712 3490
d62a17ae 3491 /* If still no table => afi/safi isn't configured at all or smth. */
3492 if (!table)
3493 return;
dc83d712 3494
d62a17ae 3495 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
3496 struct bgp_info *ri, *next;
3497 struct bgp_adj_in *ain;
3498 struct bgp_adj_in *ain_next;
3499
3500 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3501 * queued for every clearing peer, regardless of whether it is
3502 * relevant to the peer at hand.
3503 *
3504 * Overview: There are 3 different indices which need to be
3505 * scrubbed, potentially, when a peer is removed:
3506 *
3507 * 1 peer's routes visible via the RIB (ie accepted routes)
3508 * 2 peer's routes visible by the (optional) peer's adj-in index
3509 * 3 other routes visible by the peer's adj-out index
3510 *
3511 * 3 there is no hurry in scrubbing, once the struct peer is
3512 * removed from bgp->peer, we could just GC such deleted peer's
3513 * adj-outs at our leisure.
3514 *
3515 * 1 and 2 must be 'scrubbed' in some way, at least made
3516 * invisible via RIB index before peer session is allowed to be
3517 * brought back up. So one needs to know when such a 'search' is
3518 * complete.
3519 *
3520 * Ideally:
3521 *
3522 * - there'd be a single global queue or a single RIB walker
3523 * - rather than tracking which route_nodes still need to be
3524 * examined on a peer basis, we'd track which peers still
3525 * aren't cleared
3526 *
3527 * Given that our per-peer prefix-counts now should be reliable,
3528 * this may actually be achievable. It doesn't seem to be a huge
3529 * problem at this time,
3530 *
3531 * It is possible that we have multiple paths for a prefix from
3532 * a peer
3533 * if that peer is using AddPath.
3534 */
3535 ain = rn->adj_in;
3536 while (ain) {
3537 ain_next = ain->next;
3538
3539 if (ain->peer == peer) {
3540 bgp_adj_in_remove(rn, ain);
3541 bgp_unlock_node(rn);
3542 }
3543
3544 ain = ain_next;
3545 }
3546
3547 for (ri = rn->info; ri; ri = next) {
3548 next = ri->next;
3549 if (ri->peer != peer)
3550 continue;
3551
3552 if (force)
3553 bgp_info_reap(rn, ri);
3554 else {
3555 struct bgp_clear_node_queue *cnq;
3556
3557 /* both unlocked in bgp_clear_node_queue_del */
3558 bgp_table_lock(bgp_node_table(rn));
3559 bgp_lock_node(rn);
3560 cnq = XCALLOC(
3561 MTYPE_BGP_CLEAR_NODE_QUEUE,
3562 sizeof(struct bgp_clear_node_queue));
3563 cnq->rn = rn;
3564 work_queue_add(peer->clear_node_queue, cnq);
3565 break;
3566 }
3567 }
3568 }
3569 return;
3570}
3571
3572void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
3573{
3574 struct bgp_node *rn;
3575 struct bgp_table *table;
3576
3577 if (peer->clear_node_queue == NULL)
3578 bgp_clear_node_queue_init(peer);
3579
3580 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3581 * Idle until it receives a Clearing_Completed event. This protects
3582 * against peers which flap faster than we can we clear, which could
3583 * lead to:
3584 *
3585 * a) race with routes from the new session being installed before
3586 * clear_route_node visits the node (to delete the route of that
3587 * peer)
3588 * b) resource exhaustion, clear_route_node likely leads to an entry
3589 * on the process_main queue. Fast-flapping could cause that queue
3590 * to grow and grow.
3591 */
3592
3593 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3594 * the unlock will happen upon work-queue completion; other wise, the
3595 * unlock happens at the end of this function.
3596 */
3597 if (!peer->clear_node_queue->thread)
3598 peer_lock(peer);
3599
3600 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
3601 bgp_clear_route_table(peer, afi, safi, NULL);
3602 else
3603 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3604 rn = bgp_route_next(rn))
3605 if ((table = rn->info) != NULL)
3606 bgp_clear_route_table(peer, afi, safi, table);
3607
3608 /* unlock if no nodes got added to the clear-node-queue. */
3609 if (!peer->clear_node_queue->thread)
3610 peer_unlock(peer);
718e3744 3611}
d62a17ae 3612
3613void bgp_clear_route_all(struct peer *peer)
718e3744 3614{
d62a17ae 3615 afi_t afi;
3616 safi_t safi;
718e3744 3617
d62a17ae 3618 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3619 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3620 bgp_clear_route(peer, afi, safi);
65efcfce
LB
3621
3622#if ENABLE_BGP_VNC
d62a17ae 3623 rfapiProcessPeerDown(peer);
65efcfce 3624#endif
718e3744 3625}
3626
d62a17ae 3627void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3628{
d62a17ae 3629 struct bgp_table *table;
3630 struct bgp_node *rn;
3631 struct bgp_adj_in *ain;
3632 struct bgp_adj_in *ain_next;
718e3744 3633
d62a17ae 3634 table = peer->bgp->rib[afi][safi];
718e3744 3635
d62a17ae 3636 /* It is possible that we have multiple paths for a prefix from a peer
3637 * if that peer is using AddPath.
3638 */
3639 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
3640 ain = rn->adj_in;
43143c8f 3641
d62a17ae 3642 while (ain) {
3643 ain_next = ain->next;
43143c8f 3644
d62a17ae 3645 if (ain->peer == peer) {
3646 bgp_adj_in_remove(rn, ain);
3647 bgp_unlock_node(rn);
3648 }
43143c8f 3649
d62a17ae 3650 ain = ain_next;
3651 }
3652 }
718e3744 3653}
93406d87 3654
d62a17ae 3655void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
3656{
3657 struct bgp_node *rn;
3658 struct bgp_info *ri;
3659 struct bgp_table *table;
3660
3661 if (safi == SAFI_MPLS_VPN) {
3662 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3663 rn = bgp_route_next(rn)) {
3664 struct bgp_node *rm;
3665 struct bgp_info *ri;
3666
3667 /* look for neighbor in tables */
3668 if ((table = rn->info) != NULL) {
3669 for (rm = bgp_table_top(table); rm;
3670 rm = bgp_route_next(rm))
3671 for (ri = rm->info; ri; ri = ri->next)
3672 if (ri->peer == peer) {
3673 if (CHECK_FLAG(
3674 ri->flags,
3675 BGP_INFO_STALE))
3676 bgp_rib_remove(
3677 rm, ri,
3678 peer,
3679 afi,
3680 safi);
3681 break;
3682 }
3683 }
3684 }
3685 } else {
3686 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3687 rn = bgp_route_next(rn))
3688 for (ri = rn->info; ri; ri = ri->next)
3689 if (ri->peer == peer) {
3690 if (CHECK_FLAG(ri->flags,
3691 BGP_INFO_STALE))
3692 bgp_rib_remove(rn, ri, peer,
3693 afi, safi);
3694 break;
3695 }
3696 }
93406d87 3697}
6b0655a2 3698
d62a17ae 3699static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
bb86c601 3700{
d62a17ae 3701 struct bgp_node *rn;
3702 struct bgp_info *ri;
3703 struct bgp_info *next;
bb86c601 3704
d62a17ae 3705 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3706 for (ri = rn->info; ri; ri = next) {
3707 next = ri->next;
3708 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
3709 && ri->type == ZEBRA_ROUTE_BGP
3710 && (ri->sub_type == BGP_ROUTE_NORMAL
3711 || ri->sub_type == BGP_ROUTE_AGGREGATE)) {
3712 if (bgp_fibupd_safi(safi))
3713 bgp_zebra_withdraw(&rn->p, ri, safi);
3714 bgp_info_reap(rn, ri);
3715 }
3716 }
bb86c601
LB
3717}
3718
718e3744 3719/* Delete all kernel routes. */
d62a17ae 3720void bgp_cleanup_routes(struct bgp *bgp)
3721{
3722 afi_t afi;
3723 struct bgp_node *rn;
3724
3725 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
3726 if (afi == AFI_L2VPN)
3727 continue;
3728 bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST);
3729 /*
3730 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3731 */
3732 if (afi != AFI_L2VPN) {
3733 safi_t safi;
3734 safi = SAFI_MPLS_VPN;
3735 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
3736 rn = bgp_route_next(rn)) {
3737 if (rn->info) {
3738 bgp_cleanup_table(
3739 (struct bgp_table *)(rn->info),
3740 safi);
3741 bgp_table_finish((struct bgp_table **)&(
3742 rn->info));
3743 rn->info = NULL;
3744 bgp_unlock_node(rn);
3745 }
3746 }
3747 safi = SAFI_ENCAP;
3748 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
3749 rn = bgp_route_next(rn)) {
3750 if (rn->info) {
3751 bgp_cleanup_table(
3752 (struct bgp_table *)(rn->info),
3753 safi);
3754 bgp_table_finish((struct bgp_table **)&(
3755 rn->info));
3756 rn->info = NULL;
3757 bgp_unlock_node(rn);
3758 }
3759 }
3760 }
3761 }
3762 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
3763 rn = bgp_route_next(rn)) {
3764 if (rn->info) {
3765 bgp_cleanup_table((struct bgp_table *)(rn->info),
3766 SAFI_EVPN);
3767 bgp_table_finish((struct bgp_table **)&(rn->info));
3768 rn->info = NULL;
3769 bgp_unlock_node(rn);
3770 }
bb86c601 3771 }
718e3744 3772}
3773
d62a17ae 3774void bgp_reset(void)
718e3744 3775{
d62a17ae 3776 vty_reset();
3777 bgp_zclient_reset();
3778 access_list_reset();
3779 prefix_list_reset();
718e3744 3780}
6b0655a2 3781
d62a17ae 3782static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 3783{
d62a17ae 3784 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
3785 && CHECK_FLAG(peer->af_cap[afi][safi],
3786 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
3787}
3788
718e3744 3789/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3790 value. */
d62a17ae 3791int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
3792 struct bgp_nlri *packet)
3793{
3794 u_char *pnt;
3795 u_char *lim;
3796 struct prefix p;
3797 int psize;
3798 int ret;
3799 afi_t afi;
3800 safi_t safi;
3801 int addpath_encoded;
3802 u_int32_t addpath_id;
3803
3804 /* Check peer status. */
3805 if (peer->status != Established)
3806 return 0;
3807
3808 pnt = packet->nlri;
3809 lim = pnt + packet->length;
3810 afi = packet->afi;
3811 safi = packet->safi;
3812 addpath_id = 0;
3813 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
3814
3815 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3816 syntactic validity. If the field is syntactically incorrect,
3817 then the Error Subcode is set to Invalid Network Field. */
3818 for (; pnt < lim; pnt += psize) {
3819 /* Clear prefix structure. */
3820 memset(&p, 0, sizeof(struct prefix));
3821
3822 if (addpath_encoded) {
3823
3824 /* When packet overflow occurs return immediately. */
3825 if (pnt + BGP_ADDPATH_ID_LEN > lim)
3826 return -1;
3827
3828 addpath_id = ntohl(*((uint32_t *)pnt));
3829 pnt += BGP_ADDPATH_ID_LEN;
3830 }
718e3744 3831
d62a17ae 3832 /* Fetch prefix length. */
3833 p.prefixlen = *pnt++;
3834 /* afi/safi validity already verified by caller,
3835 * bgp_update_receive */
3836 p.family = afi2family(afi);
3837
3838 /* Prefix length check. */
3839 if (p.prefixlen > prefix_blen(&p) * 8) {
3840 zlog_err(
3841 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3842 peer->host, p.prefixlen, packet->afi);
3843 return -1;
3844 }
6b0655a2 3845
d62a17ae 3846 /* Packet size overflow check. */
3847 psize = PSIZE(p.prefixlen);
3848
3849 /* When packet overflow occur return immediately. */
3850 if (pnt + psize > lim) {
3851 zlog_err(
3852 "%s [Error] Update packet error (prefix length %d overflows packet)",
3853 peer->host, p.prefixlen);
3854 return -1;
3855 }
3856
3857 /* Defensive coding, double-check the psize fits in a struct
3858 * prefix */
3859 if (psize > (ssize_t)sizeof(p.u)) {
3860 zlog_err(
3861 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3862 peer->host, p.prefixlen, sizeof(p.u));
3863 return -1;
3864 }
3865
3866 /* Fetch prefix from NLRI packet. */
3867 memcpy(&p.u.prefix, pnt, psize);
3868
3869 /* Check address. */
3870 if (afi == AFI_IP && safi == SAFI_UNICAST) {
3871 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
3872 /* From RFC4271 Section 6.3:
3873 *
3874 * If a prefix in the NLRI field is semantically
3875 * incorrect
3876 * (e.g., an unexpected multicast IP address),
3877 * an error SHOULD
3878 * be logged locally, and the prefix SHOULD be
3879 * ignored.
9d303b37 3880 */
d62a17ae 3881 zlog_err(
3882 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3883 peer->host, inet_ntoa(p.u.prefix4));
3884 continue;
3885 }
3886 }
3887
3888 /* Check address. */
3889 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
3890 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
3891 char buf[BUFSIZ];
3892
3893 zlog_err(
3894 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3895 peer->host,
3896 inet_ntop(AF_INET6, &p.u.prefix6, buf,
3897 BUFSIZ));
3898
3899 continue;
3900 }
3901 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
3902 char buf[BUFSIZ];
3903
3904 zlog_err(
3905 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
3906 peer->host,
3907 inet_ntop(AF_INET6, &p.u.prefix6, buf,
3908 BUFSIZ));
3909
3910 continue;
3911 }
3912 }
3913
3914 /* Normal process. */
3915 if (attr)
3916 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
3917 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
3918 NULL, NULL, 0, NULL);
3919 else
3920 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
3921 safi, ZEBRA_ROUTE_BGP,
3922 BGP_ROUTE_NORMAL, NULL, NULL, NULL);
3923
3924 /* Address family configuration mismatch or maximum-prefix count
3925 overflow. */
3926 if (ret < 0)
3927 return -1;
3928 }
3929
3930 /* Packet length consistency check. */
3931 if (pnt != lim) {
3932 zlog_err(
3933 "%s [Error] Update packet error (prefix length mismatch with total length)",
3934 peer->host);
3935 return -1;
3936 }
6b0655a2 3937
d62a17ae 3938 return 0;
718e3744 3939}
3940
d62a17ae 3941static struct bgp_static *bgp_static_new(void)
718e3744 3942{
d62a17ae 3943 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 3944}
3945
d62a17ae 3946static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 3947{
d62a17ae 3948 if (bgp_static->rmap.name)
3949 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
3950 if (bgp_static->eth_s_id)
3951 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
3952 XFREE(MTYPE_BGP_STATIC, bgp_static);
3953}
3954
3955void bgp_static_update(struct bgp *bgp, struct prefix *p,
3956 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
3957{
3958 struct bgp_node *rn;
3959 struct bgp_info *ri;
3960 struct bgp_info *new;
3961 struct bgp_info info;
3962 struct attr attr;
3963 struct attr *attr_new;
3964 int ret;
65efcfce 3965#if ENABLE_BGP_VNC
d62a17ae 3966 int vnc_implicit_withdraw = 0;
65efcfce 3967#endif
fee0f4c6 3968
d62a17ae 3969 assert(bgp_static);
3970 if (!bgp_static)
3971 return;
dd8103a9 3972
d62a17ae 3973 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 3974
d62a17ae 3975 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 3976
d62a17ae 3977 attr.nexthop = bgp_static->igpnexthop;
3978 attr.med = bgp_static->igpmetric;
3979 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 3980
d62a17ae 3981 if (bgp_static->atomic)
3982 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 3983
d62a17ae 3984 /* Store label index, if required. */
3985 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
3986 attr.label_index = bgp_static->label_index;
3987 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3988 }
718e3744 3989
d62a17ae 3990 /* Apply route-map. */
3991 if (bgp_static->rmap.name) {
3992 struct attr attr_tmp = attr;
3993 info.peer = bgp->peer_self;
3994 info.attr = &attr_tmp;
fee0f4c6 3995
d62a17ae 3996 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 3997
d62a17ae 3998 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
fee0f4c6 3999
d62a17ae 4000 bgp->peer_self->rmap_type = 0;
718e3744 4001
d62a17ae 4002 if (ret == RMAP_DENYMATCH) {
4003 /* Free uninterned attribute. */
4004 bgp_attr_flush(&attr_tmp);
718e3744 4005
d62a17ae 4006 /* Unintern original. */
4007 aspath_unintern(&attr.aspath);
4008 bgp_static_withdraw(bgp, p, afi, safi);
4009 return;
4010 }
4011 attr_new = bgp_attr_intern(&attr_tmp);
4012 } else
4013 attr_new = bgp_attr_intern(&attr);
718e3744 4014
d62a17ae 4015 for (ri = rn->info; ri; ri = ri->next)
4016 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4017 && ri->sub_type == BGP_ROUTE_STATIC)
4018 break;
4019
4020 if (ri) {
4021 if (attrhash_cmp(ri->attr, attr_new)
4022 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
4023 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4024 bgp_unlock_node(rn);
4025 bgp_attr_unintern(&attr_new);
4026 aspath_unintern(&attr.aspath);
4027 return;
4028 } else {
4029 /* The attribute is changed. */
4030 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4031
4032 /* Rewrite BGP route information. */
4033 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4034 bgp_info_restore(rn, ri);
4035 else
4036 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
65efcfce 4037#if ENABLE_BGP_VNC
d62a17ae 4038 if ((afi == AFI_IP || afi == AFI_IP6)
4039 && (safi == SAFI_UNICAST)) {
4040 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
4041 /*
4042 * Implicit withdraw case.
4043 * We have to do this before ri is
4044 * changed
4045 */
4046 ++vnc_implicit_withdraw;
4047 vnc_import_bgp_del_route(bgp, p, ri);
4048 vnc_import_bgp_exterior_del_route(
4049 bgp, p, ri);
4050 }
4051 }
65efcfce 4052#endif
d62a17ae 4053 bgp_attr_unintern(&ri->attr);
4054 ri->attr = attr_new;
4055 ri->uptime = bgp_clock();
65efcfce 4056#if ENABLE_BGP_VNC
d62a17ae 4057 if ((afi == AFI_IP || afi == AFI_IP6)
4058 && (safi == SAFI_UNICAST)) {
4059 if (vnc_implicit_withdraw) {
4060 vnc_import_bgp_add_route(bgp, p, ri);
4061 vnc_import_bgp_exterior_add_route(
4062 bgp, p, ri);
4063 }
4064 }
65efcfce 4065#endif
718e3744 4066
d62a17ae 4067 /* Nexthop reachability check. */
4068 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4069 && (safi == SAFI_UNICAST
4070 || safi == SAFI_LABELED_UNICAST)) {
4071 if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL,
4072 0))
4073 bgp_info_set_flag(rn, ri,
4074 BGP_INFO_VALID);
4075 else {
4076 if (BGP_DEBUG(nht, NHT)) {
4077 char buf1[INET6_ADDRSTRLEN];
4078 inet_ntop(p->family,
4079 &p->u.prefix, buf1,
4080 INET6_ADDRSTRLEN);
4081 zlog_debug(
4082 "%s(%s): Route not in table, not advertising",
4083 __FUNCTION__, buf1);
4084 }
4085 bgp_info_unset_flag(rn, ri,
4086 BGP_INFO_VALID);
4087 }
4088 } else {
4089 /* Delete the NHT structure if any, if we're
4090 * toggling between
4091 * enabling/disabling import check. We
4092 * deregister the route
4093 * from NHT to avoid overloading NHT and the
4094 * process interaction
4095 */
4096 bgp_unlink_nexthop(ri);
4097 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
4098 }
4099 /* Process change. */
4100 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4101 bgp_process(bgp, rn, afi, safi);
4102 bgp_unlock_node(rn);
4103 aspath_unintern(&attr.aspath);
4104 return;
4105 }
718e3744 4106 }
718e3744 4107
d62a17ae 4108 /* Make new BGP info. */
4109 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4110 attr_new, rn);
4111 /* Nexthop reachability check. */
4112 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4113 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4114 if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, 0))
4115 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
4116 else {
4117 if (BGP_DEBUG(nht, NHT)) {
4118 char buf1[INET6_ADDRSTRLEN];
4119 inet_ntop(p->family, &p->u.prefix, buf1,
4120 INET6_ADDRSTRLEN);
4121 zlog_debug(
4122 "%s(%s): Route not in table, not advertising",
4123 __FUNCTION__, buf1);
4124 }
4125 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
4126 }
4127 } else {
4128 /* Delete the NHT structure if any, if we're toggling between
4129 * enabling/disabling import check. We deregister the route
4130 * from NHT to avoid overloading NHT and the process interaction
4131 */
4132 bgp_unlink_nexthop(new);
4133
4134 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
fc9a856f 4135 }
078430f6 4136
d62a17ae 4137 /* Aggregate address increment. */
4138 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4139
d62a17ae 4140 /* Register new BGP information. */
4141 bgp_info_add(rn, new);
718e3744 4142
d62a17ae 4143 /* route_node_get lock */
4144 bgp_unlock_node(rn);
4145
4146 /* Process change. */
4147 bgp_process(bgp, rn, afi, safi);
4148
4149 /* Unintern original. */
4150 aspath_unintern(&attr.aspath);
718e3744 4151}
4152
d62a17ae 4153void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4154 safi_t safi)
718e3744 4155{
d62a17ae 4156 struct bgp_node *rn;
4157 struct bgp_info *ri;
718e3744 4158
d62a17ae 4159 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4160
d62a17ae 4161 /* Check selected route and self inserted route. */
4162 for (ri = rn->info; ri; ri = ri->next)
4163 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4164 && ri->sub_type == BGP_ROUTE_STATIC)
4165 break;
4166
4167 /* Withdraw static BGP route from routing table. */
4168 if (ri) {
4169 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4170 bgp_unlink_nexthop(ri);
4171 bgp_info_delete(rn, ri);
4172 bgp_process(bgp, rn, afi, safi);
4173 }
718e3744 4174
d62a17ae 4175 /* Unlock bgp_node_lookup. */
4176 bgp_unlock_node(rn);
718e3744 4177}
4178
137446f9
LB
4179/*
4180 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4181 */
d62a17ae 4182static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4183 afi_t afi, safi_t safi,
4184 struct prefix_rd *prd)
718e3744 4185{
d62a17ae 4186 struct bgp_node *rn;
4187 struct bgp_info *ri;
718e3744 4188
d62a17ae 4189 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4190
d62a17ae 4191 /* Check selected route and self inserted route. */
4192 for (ri = rn->info; ri; ri = ri->next)
4193 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4194 && ri->sub_type == BGP_ROUTE_STATIC)
4195 break;
718e3744 4196
d62a17ae 4197 /* Withdraw static BGP route from routing table. */
4198 if (ri) {
65efcfce 4199#if ENABLE_BGP_VNC
d62a17ae 4200 rfapiProcessWithdraw(
4201 ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type,
4202 1); /* Kill, since it is an administrative change */
65efcfce 4203#endif
d62a17ae 4204 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4205 bgp_info_delete(rn, ri);
4206 bgp_process(bgp, rn, afi, safi);
4207 }
718e3744 4208
d62a17ae 4209 /* Unlock bgp_node_lookup. */
4210 bgp_unlock_node(rn);
718e3744 4211}
4212
d62a17ae 4213static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4214 struct bgp_static *bgp_static, afi_t afi,
4215 safi_t safi)
137446f9 4216{
d62a17ae 4217 struct bgp_node *rn;
4218 struct bgp_info *new;
4219 struct attr *attr_new;
4220 struct attr attr = {0};
4221 struct bgp_info *ri;
65efcfce 4222#if ENABLE_BGP_VNC
d62a17ae 4223 mpls_label_t label = 0;
65efcfce 4224#endif
d62a17ae 4225 union gw_addr add;
137446f9 4226
d62a17ae 4227 assert(bgp_static);
137446f9 4228
d62a17ae 4229 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4230 &bgp_static->prd);
137446f9 4231
d62a17ae 4232 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4233
d62a17ae 4234 attr.nexthop = bgp_static->igpnexthop;
4235 attr.med = bgp_static->igpmetric;
4236 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4237
d62a17ae 4238 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4239 || (safi == SAFI_ENCAP)) {
4240 if (afi == AFI_IP) {
4241 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4242 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4243 }
4244 }
4245 if (afi == AFI_L2VPN) {
4246 if (bgp_static->gatewayIp.family == AF_INET)
4247 add.ipv4.s_addr =
4248 bgp_static->gatewayIp.u.prefix4.s_addr;
4249 else if (bgp_static->gatewayIp.family == AF_INET6)
4250 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4251 sizeof(struct in6_addr));
4252 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4253 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4254 struct bgp_encap_type_vxlan bet;
4255 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
4256 bet.vnid = p->u.prefix_evpn.eth_tag;
4257 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4258 }
4259 if (bgp_static->router_mac) {
4260 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4261 }
4262 }
4263 /* Apply route-map. */
4264 if (bgp_static->rmap.name) {
4265 struct attr attr_tmp = attr;
4266 struct bgp_info info;
4267 int ret;
137446f9 4268
d62a17ae 4269 info.peer = bgp->peer_self;
4270 info.attr = &attr_tmp;
137446f9 4271
d62a17ae 4272 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4273
d62a17ae 4274 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
137446f9 4275
d62a17ae 4276 bgp->peer_self->rmap_type = 0;
137446f9 4277
d62a17ae 4278 if (ret == RMAP_DENYMATCH) {
4279 /* Free uninterned attribute. */
4280 bgp_attr_flush(&attr_tmp);
137446f9 4281
d62a17ae 4282 /* Unintern original. */
4283 aspath_unintern(&attr.aspath);
4284 bgp_static_withdraw_safi(bgp, p, afi, safi,
4285 &bgp_static->prd);
4286 return;
4287 }
137446f9 4288
d62a17ae 4289 attr_new = bgp_attr_intern(&attr_tmp);
4290 } else {
4291 attr_new = bgp_attr_intern(&attr);
4292 }
137446f9 4293
d62a17ae 4294 for (ri = rn->info; ri; ri = ri->next)
4295 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4296 && ri->sub_type == BGP_ROUTE_STATIC)
4297 break;
4298
4299 if (ri) {
4300 union gw_addr add;
4301 memset(&add, 0, sizeof(union gw_addr));
4302 if (attrhash_cmp(ri->attr, attr_new)
4303 && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add)
4304 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
4305 bgp_unlock_node(rn);
4306 bgp_attr_unintern(&attr_new);
4307 aspath_unintern(&attr.aspath);
4308 return;
4309 } else {
4310 /* The attribute is changed. */
4311 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4312
4313 /* Rewrite BGP route information. */
4314 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4315 bgp_info_restore(rn, ri);
4316 else
4317 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4318 bgp_attr_unintern(&ri->attr);
4319 ri->attr = attr_new;
4320 ri->uptime = bgp_clock();
65efcfce 4321#if ENABLE_BGP_VNC
d62a17ae 4322 if (ri->extra)
4323 label = decode_label(&ri->extra->label);
65efcfce 4324#endif
137446f9 4325
d62a17ae 4326 /* Process change. */
4327 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4328 bgp_process(bgp, rn, afi, safi);
65efcfce 4329#if ENABLE_BGP_VNC
d62a17ae 4330 rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
4331 ri->attr, afi, safi, ri->type,
4332 ri->sub_type, &label);
65efcfce 4333#endif
d62a17ae 4334 bgp_unlock_node(rn);
4335 aspath_unintern(&attr.aspath);
4336 return;
4337 }
4338 }
137446f9
LB
4339
4340
d62a17ae 4341 /* Make new BGP info. */
4342 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4343 attr_new, rn);
4344 SET_FLAG(new->flags, BGP_INFO_VALID);
4345 new->extra = bgp_info_extra_new();
4346 new->extra->label = bgp_static->label;
65efcfce 4347#if ENABLE_BGP_VNC
d62a17ae 4348 label = decode_label(&bgp_static->label);
65efcfce 4349#endif
137446f9 4350
d62a17ae 4351 /* Aggregate address increment. */
4352 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 4353
d62a17ae 4354 /* Register new BGP information. */
4355 bgp_info_add(rn, new);
4356 /* route_node_get lock */
4357 bgp_unlock_node(rn);
137446f9 4358
d62a17ae 4359 /* Process change. */
4360 bgp_process(bgp, rn, afi, safi);
137446f9 4361
65efcfce 4362#if ENABLE_BGP_VNC
d62a17ae 4363 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
4364 safi, new->type, new->sub_type, &label);
65efcfce
LB
4365#endif
4366
d62a17ae 4367 /* Unintern original. */
4368 aspath_unintern(&attr.aspath);
137446f9
LB
4369}
4370
718e3744 4371/* Configure static BGP network. When user don't run zebra, static
4372 route should be installed as valid. */
d62a17ae 4373static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi,
4374 safi_t safi, const char *rmap, int backdoor,
4375 u_int32_t label_index)
4376{
4377 VTY_DECLVAR_CONTEXT(bgp, bgp);
4378 int ret;
4379 struct prefix p;
4380 struct bgp_static *bgp_static;
4381 struct bgp_node *rn;
4382 u_char need_update = 0;
4383
4384 /* Convert IP prefix string to struct prefix. */
4385 ret = str2prefix(ip_str, &p);
4386 if (!ret) {
4387 vty_out(vty, "%% Malformed prefix\n");
4388 return CMD_WARNING_CONFIG_FAILED;
4389 }
4390 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4391 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4392 return CMD_WARNING_CONFIG_FAILED;
4393 }
718e3744 4394
d62a17ae 4395 apply_mask(&p);
718e3744 4396
d62a17ae 4397 /* Set BGP static route configuration. */
4398 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 4399
d62a17ae 4400 if (rn->info) {
4401 /* Configuration change. */
4402 bgp_static = rn->info;
4403
4404 /* Label index cannot be changed. */
4405 if (bgp_static->label_index != label_index) {
4406 vty_out(vty, "%% Label index cannot be changed\n");
4407 return CMD_WARNING_CONFIG_FAILED;
4408 }
4409
4410 /* Check previous routes are installed into BGP. */
4411 if (bgp_static->valid && bgp_static->backdoor != backdoor)
4412 need_update = 1;
4413
4414 bgp_static->backdoor = backdoor;
4415
4416 if (rmap) {
4417 if (bgp_static->rmap.name)
4418 XFREE(MTYPE_ROUTE_MAP_NAME,
4419 bgp_static->rmap.name);
4420 bgp_static->rmap.name =
4421 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4422 bgp_static->rmap.map = route_map_lookup_by_name(rmap);
4423 } else {
4424 if (bgp_static->rmap.name)
4425 XFREE(MTYPE_ROUTE_MAP_NAME,
4426 bgp_static->rmap.name);
4427 bgp_static->rmap.name = NULL;
4428 bgp_static->rmap.map = NULL;
4429 bgp_static->valid = 0;
4430 }
4431 bgp_unlock_node(rn);
4432 } else {
4433 /* New configuration. */
4434 bgp_static = bgp_static_new();
4435 bgp_static->backdoor = backdoor;
4436 bgp_static->valid = 0;
4437 bgp_static->igpmetric = 0;
4438 bgp_static->igpnexthop.s_addr = 0;
4439 bgp_static->label_index = label_index;
4440
4441 if (rmap) {
4442 if (bgp_static->rmap.name)
4443 XFREE(MTYPE_ROUTE_MAP_NAME,
4444 bgp_static->rmap.name);
4445 bgp_static->rmap.name =
4446 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4447 bgp_static->rmap.map = route_map_lookup_by_name(rmap);
4448 }
4449 rn->info = bgp_static;
4450 }
718e3744 4451
d62a17ae 4452 bgp_static->valid = 1;
4453 if (need_update)
4454 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 4455
d62a17ae 4456 if (!bgp_static->backdoor)
4457 bgp_static_update(bgp, &p, bgp_static, afi, safi);
718e3744 4458
d62a17ae 4459 return CMD_SUCCESS;
718e3744 4460}
4461
4462/* Configure static BGP network. */
d62a17ae 4463static int bgp_static_unset(struct vty *vty, const char *ip_str, afi_t afi,
4464 safi_t safi)
4465{
4466 VTY_DECLVAR_CONTEXT(bgp, bgp);
4467 int ret;
4468 struct prefix p;
4469 struct bgp_static *bgp_static;
4470 struct bgp_node *rn;
4471
4472 /* Convert IP prefix string to struct prefix. */
4473 ret = str2prefix(ip_str, &p);
4474 if (!ret) {
4475 vty_out(vty, "%% Malformed prefix\n");
4476 return CMD_WARNING_CONFIG_FAILED;
4477 }
4478 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4479 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4480 return CMD_WARNING_CONFIG_FAILED;
4481 }
718e3744 4482
d62a17ae 4483 apply_mask(&p);
718e3744 4484
d62a17ae 4485 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
4486 if (!rn) {
4487 vty_out(vty,
4488 "%% Can't find specified static route configuration.\n");
4489 return CMD_WARNING_CONFIG_FAILED;
4490 }
718e3744 4491
d62a17ae 4492 bgp_static = rn->info;
4493
4494 /* Update BGP RIB. */
4495 if (!bgp_static->backdoor)
4496 bgp_static_withdraw(bgp, &p, afi, safi);
4497
4498 /* Clear configuration. */
4499 bgp_static_free(bgp_static);
4500 rn->info = NULL;
4501 bgp_unlock_node(rn);
4502 bgp_unlock_node(rn);
4503
4504 return CMD_SUCCESS;
4505}
4506
4507void bgp_static_add(struct bgp *bgp)
4508{
4509 afi_t afi;
4510 safi_t safi;
4511 struct bgp_node *rn;
4512 struct bgp_node *rm;
4513 struct bgp_table *table;
4514 struct bgp_static *bgp_static;
4515
4516 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4517 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4518 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4519 rn = bgp_route_next(rn))
4520 if (rn->info != NULL) {
4521 if ((safi == SAFI_MPLS_VPN)
4522 || (safi == SAFI_ENCAP)
4523 || (safi == SAFI_EVPN)) {
4524 table = rn->info;
4525
4526 for (rm = bgp_table_top(table);
4527 rm;
4528 rm = bgp_route_next(rm)) {
4529 bgp_static = rm->info;
4530 bgp_static_update_safi(
4531 bgp, &rm->p,
4532 bgp_static, afi,
4533 safi);
4534 }
4535 } else {
4536 bgp_static_update(bgp, &rn->p,
4537 rn->info, afi,
4538 safi);
4539 }
4540 }
6aeb9e78
DS
4541}
4542
718e3744 4543/* Called from bgp_delete(). Delete all static routes from the BGP
4544 instance. */
d62a17ae 4545void bgp_static_delete(struct bgp *bgp)
4546{
4547 afi_t afi;
4548 safi_t safi;
4549 struct bgp_node *rn;
4550 struct bgp_node *rm;
4551 struct bgp_table *table;
4552 struct bgp_static *bgp_static;
4553
4554 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4555 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4556 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4557 rn = bgp_route_next(rn))
4558 if (rn->info != NULL) {
4559 if ((safi == SAFI_MPLS_VPN)
4560 || (safi == SAFI_ENCAP)
4561 || (safi == SAFI_EVPN)) {
4562 table = rn->info;
4563
4564 for (rm = bgp_table_top(table);
4565 rm;
4566 rm = bgp_route_next(rm)) {
4567 bgp_static = rm->info;
4568 bgp_static_withdraw_safi(
4569 bgp, &rm->p,
4570 AFI_IP, safi,
4571 (struct
4572 prefix_rd *)&rn
4573 ->p);
4574 bgp_static_free(
4575 bgp_static);
4576 rn->info = NULL;
4577 bgp_unlock_node(rn);
4578 }
4579 } else {
4580 bgp_static = rn->info;
4581 bgp_static_withdraw(bgp, &rn->p,
4582 afi, safi);
4583 bgp_static_free(bgp_static);
4584 rn->info = NULL;
4585 bgp_unlock_node(rn);
4586 }
4587 }
4588}
4589
4590void bgp_static_redo_import_check(struct bgp *bgp)
4591{
4592 afi_t afi;
4593 safi_t safi;
4594 struct bgp_node *rn;
4595 struct bgp_node *rm;
4596 struct bgp_table *table;
4597 struct bgp_static *bgp_static;
4598
4599 /* Use this flag to force reprocessing of the route */
4600 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
4601 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4602 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4603 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4604 rn = bgp_route_next(rn))
4605 if (rn->info != NULL) {
4606 if ((safi == SAFI_MPLS_VPN)
4607 || (safi == SAFI_ENCAP)
4608 || (safi == SAFI_EVPN)) {
4609 table = rn->info;
4610
4611 for (rm = bgp_table_top(table);
4612 rm;
4613 rm = bgp_route_next(rm)) {
4614 bgp_static = rm->info;
4615 bgp_static_update_safi(
4616 bgp, &rm->p,
4617 bgp_static, afi,
4618 safi);
4619 }
4620 } else {
4621 bgp_static = rn->info;
4622 bgp_static_update(bgp, &rn->p,
4623 bgp_static,
4624 afi, safi);
4625 }
4626 }
4627 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
4628}
4629
4630static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
4631 safi_t safi)
4632{
4633 struct bgp_table *table;
4634 struct bgp_node *rn;
4635 struct bgp_info *ri;
4636
4637 table = bgp->rib[afi][safi];
4638 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4639 for (ri = rn->info; ri; ri = ri->next) {
4640 if (ri->peer == bgp->peer_self
4641 && ((ri->type == ZEBRA_ROUTE_BGP
4642 && ri->sub_type == BGP_ROUTE_STATIC)
4643 || (ri->type != ZEBRA_ROUTE_BGP
4644 && ri->sub_type
4645 == BGP_ROUTE_REDISTRIBUTE))) {
4646 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
4647 safi);
4648 bgp_unlink_nexthop(ri);
4649 bgp_info_delete(rn, ri);
4650 bgp_process(bgp, rn, afi, safi);
4651 }
4652 }
4653 }
ad4cbda1 4654}
4655
4656/*
4657 * Purge all networks and redistributed routes from routing table.
4658 * Invoked upon the instance going down.
4659 */
d62a17ae 4660void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 4661{
d62a17ae 4662 afi_t afi;
4663 safi_t safi;
ad4cbda1 4664
d62a17ae 4665 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4666 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4667 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 4668}
4669
137446f9
LB
4670/*
4671 * gpz 110624
4672 * Currently this is used to set static routes for VPN and ENCAP.
4673 * I think it can probably be factored with bgp_static_set.
4674 */
d62a17ae 4675int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
4676 const char *ip_str, const char *rd_str,
4677 const char *label_str, const char *rmap_str,
4678 int evpn_type, const char *esi, const char *gwip,
4679 const char *ethtag, const char *routermac)
4680{
4681 VTY_DECLVAR_CONTEXT(bgp, bgp);
4682 int ret;
4683 struct prefix p;
4684 struct prefix_rd prd;
4685 struct bgp_node *prn;
4686 struct bgp_node *rn;
4687 struct bgp_table *table;
4688 struct bgp_static *bgp_static;
4689 mpls_label_t label = MPLS_INVALID_LABEL;
4690 struct prefix gw_ip;
4691
4692 /* validate ip prefix */
4693 ret = str2prefix(ip_str, &p);
4694 if (!ret) {
4695 vty_out(vty, "%% Malformed prefix\n");
4696 return CMD_WARNING_CONFIG_FAILED;
4697 }
4698 apply_mask(&p);
4699 if ((afi == AFI_L2VPN)
4700 && (bgp_build_evpn_prefix(evpn_type,
4701 ethtag != NULL ? atol(ethtag) : 0, &p))) {
4702 vty_out(vty, "%% L2VPN prefix could not be forged\n");
4703 return CMD_WARNING_CONFIG_FAILED;
4704 }
718e3744 4705
d62a17ae 4706 ret = str2prefix_rd(rd_str, &prd);
4707 if (!ret) {
4708 vty_out(vty, "%% Malformed rd\n");
4709 return CMD_WARNING_CONFIG_FAILED;
4710 }
718e3744 4711
d62a17ae 4712 if (label_str) {
4713 unsigned long label_val;
4714 label_val = strtoul(label_str, NULL, 10);
4715 encode_label(label_val, &label);
4716 }
9bedbb1e 4717
d62a17ae 4718 if (safi == SAFI_EVPN) {
4719 if (esi && str2esi(esi, NULL) == 0) {
4720 vty_out(vty, "%% Malformed ESI\n");
4721 return CMD_WARNING_CONFIG_FAILED;
4722 }
4723 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
4724 vty_out(vty, "%% Malformed Router MAC\n");
4725 return CMD_WARNING_CONFIG_FAILED;
4726 }
4727 if (gwip) {
4728 memset(&gw_ip, 0, sizeof(struct prefix));
4729 ret = str2prefix(gwip, &gw_ip);
4730 if (!ret) {
4731 vty_out(vty, "%% Malformed GatewayIp\n");
4732 return CMD_WARNING_CONFIG_FAILED;
4733 }
4734 if ((gw_ip.family == AF_INET
4735 && IS_EVPN_PREFIX_IPADDR_V6(
4736 (struct prefix_evpn *)&p))
4737 || (gw_ip.family == AF_INET6
4738 && IS_EVPN_PREFIX_IPADDR_V4(
4739 (struct prefix_evpn *)&p))) {
4740 vty_out(vty,
4741 "%% GatewayIp family differs with IP prefix\n");
4742 return CMD_WARNING_CONFIG_FAILED;
4743 }
4744 }
4745 }
4746 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
4747 if (prn->info == NULL)
4748 prn->info = bgp_table_init(afi, safi);
4749 else
4750 bgp_unlock_node(prn);
4751 table = prn->info;
4752
4753 rn = bgp_node_get(table, &p);
4754
4755 if (rn->info) {
4756 vty_out(vty, "%% Same network configuration exists\n");
4757 bgp_unlock_node(rn);
4758 } else {
4759 /* New configuration. */
4760 bgp_static = bgp_static_new();
4761 bgp_static->backdoor = 0;
4762 bgp_static->valid = 0;
4763 bgp_static->igpmetric = 0;
4764 bgp_static->igpnexthop.s_addr = 0;
4765 bgp_static->label = label;
4766 bgp_static->prd = prd;
4767
4768 if (rmap_str) {
4769 if (bgp_static->rmap.name)
4770 XFREE(MTYPE_ROUTE_MAP_NAME,
4771 bgp_static->rmap.name);
4772 bgp_static->rmap.name =
4773 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
4774 bgp_static->rmap.map =
4775 route_map_lookup_by_name(rmap_str);
4776 }
718e3744 4777
d62a17ae 4778 if (safi == SAFI_EVPN) {
4779 if (esi) {
4780 bgp_static->eth_s_id =
4781 XCALLOC(MTYPE_ATTR,
4782 sizeof(struct eth_segment_id));
4783 str2esi(esi, bgp_static->eth_s_id);
4784 }
4785 if (routermac) {
4786 bgp_static->router_mac =
28328ea9 4787 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
d62a17ae 4788 prefix_str2mac(routermac,
4789 bgp_static->router_mac);
4790 }
4791 if (gwip)
4792 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
4793 }
4794 rn->info = bgp_static;
718e3744 4795
d62a17ae 4796 bgp_static->valid = 1;
4797 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
4798 }
718e3744 4799
d62a17ae 4800 return CMD_SUCCESS;
718e3744 4801}
4802
4803/* Configure static BGP network. */
d62a17ae 4804int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
4805 const char *ip_str, const char *rd_str,
4806 const char *label_str, int evpn_type, const char *esi,
4807 const char *gwip, const char *ethtag)
4808{
4809 VTY_DECLVAR_CONTEXT(bgp, bgp);
4810 int ret;
4811 struct prefix p;
4812 struct prefix_rd prd;
4813 struct bgp_node *prn;
4814 struct bgp_node *rn;
4815 struct bgp_table *table;
4816 struct bgp_static *bgp_static;
4817 mpls_label_t label = MPLS_INVALID_LABEL;
4818
4819 /* Convert IP prefix string to struct prefix. */
4820 ret = str2prefix(ip_str, &p);
4821 if (!ret) {
4822 vty_out(vty, "%% Malformed prefix\n");
4823 return CMD_WARNING_CONFIG_FAILED;
4824 }
4825 apply_mask(&p);
4826 if ((afi == AFI_L2VPN)
4827 && (bgp_build_evpn_prefix(evpn_type,
4828 ethtag != NULL ? atol(ethtag) : 0, &p))) {
4829 vty_out(vty, "%% L2VPN prefix could not be forged\n");
4830 return CMD_WARNING_CONFIG_FAILED;
4831 }
4832 ret = str2prefix_rd(rd_str, &prd);
4833 if (!ret) {
4834 vty_out(vty, "%% Malformed rd\n");
4835 return CMD_WARNING_CONFIG_FAILED;
4836 }
718e3744 4837
d62a17ae 4838 if (label_str) {
4839 unsigned long label_val;
4840 label_val = strtoul(label_str, NULL, 10);
4841 encode_label(label_val, &label);
4842 }
718e3744 4843
d62a17ae 4844 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
4845 if (prn->info == NULL)
4846 prn->info = bgp_table_init(afi, safi);
4847 else
4848 bgp_unlock_node(prn);
4849 table = prn->info;
718e3744 4850
d62a17ae 4851 rn = bgp_node_lookup(table, &p);
6b0655a2 4852
d62a17ae 4853 if (rn) {
4854 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 4855
d62a17ae 4856 bgp_static = rn->info;
4857 bgp_static_free(bgp_static);
4858 rn->info = NULL;
4859 bgp_unlock_node(rn);
4860 bgp_unlock_node(rn);
4861 } else
4862 vty_out(vty, "%% Can't find the route\n");
4863
4864 return CMD_SUCCESS;
4865}
4866
4867static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
4868 const char *rmap_name)
4869{
4870 VTY_DECLVAR_CONTEXT(bgp, bgp);
4871 struct bgp_rmap *rmap;
4872
4873 rmap = &bgp->table_map[afi][safi];
4874 if (rmap_name) {
4875 if (rmap->name)
4876 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4877 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
4878 rmap->map = route_map_lookup_by_name(rmap_name);
4879 } else {
4880 if (rmap->name)
4881 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4882 rmap->name = NULL;
4883 rmap->map = NULL;
4884 }
73ac8160 4885
d62a17ae 4886 if (bgp_fibupd_safi(safi))
4887 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 4888
d62a17ae 4889 return CMD_SUCCESS;
73ac8160
DS
4890}
4891
d62a17ae 4892static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
4893 const char *rmap_name)
73ac8160 4894{
d62a17ae 4895 VTY_DECLVAR_CONTEXT(bgp, bgp);
4896 struct bgp_rmap *rmap;
73ac8160 4897
d62a17ae 4898 rmap = &bgp->table_map[afi][safi];
4899 if (rmap->name)
4900 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4901 rmap->name = NULL;
4902 rmap->map = NULL;
73ac8160 4903
d62a17ae 4904 if (bgp_fibupd_safi(safi))
4905 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 4906
d62a17ae 4907 return CMD_SUCCESS;
73ac8160
DS
4908}
4909
d62a17ae 4910int bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
4911 safi_t safi, int *write)
73ac8160 4912{
d62a17ae 4913 if (bgp->table_map[afi][safi].name) {
4914 bgp_config_write_family_header(vty, afi, safi, write);
4915 vty_out(vty, " table-map %s\n",
4916 bgp->table_map[afi][safi].name);
4917 }
73ac8160 4918
d62a17ae 4919 return 0;
73ac8160
DS
4920}
4921
73ac8160
DS
4922DEFUN (bgp_table_map,
4923 bgp_table_map_cmd,
4924 "table-map WORD",
4925 "BGP table to RIB route download filter\n"
4926 "Name of the route map\n")
4927{
d62a17ae 4928 int idx_word = 1;
4929 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
4930 argv[idx_word]->arg);
73ac8160
DS
4931}
4932DEFUN (no_bgp_table_map,
4933 no_bgp_table_map_cmd,
4934 "no table-map WORD",
3a2d747c 4935 NO_STR
73ac8160
DS
4936 "BGP table to RIB route download filter\n"
4937 "Name of the route map\n")
4938{
d62a17ae 4939 int idx_word = 2;
4940 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
4941 argv[idx_word]->arg);
73ac8160
DS
4942}
4943
718e3744 4944DEFUN (bgp_network,
4945 bgp_network_cmd,
4946 "network A.B.C.D/M",
4947 "Specify a network to announce via BGP\n"
0c7b1b01 4948 "IPv4 prefix\n")
718e3744 4949{
d62a17ae 4950 int idx_ipv4_prefixlen = 1;
4951 return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
4952 bgp_node_safi(vty), NULL, 0,
4953 BGP_INVALID_LABEL_INDEX);
718e3744 4954}
4955
4956DEFUN (bgp_network_route_map,
4957 bgp_network_route_map_cmd,
4958 "network A.B.C.D/M route-map WORD",
4959 "Specify a network to announce via BGP\n"
0c7b1b01 4960 "IPv4 prefix\n"
718e3744 4961 "Route-map to modify the attributes\n"
4962 "Name of the route map\n")
4963{
d62a17ae 4964 int idx_ipv4_prefixlen = 1;
4965 int idx_word = 3;
4966 return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
4967 bgp_node_safi(vty), argv[idx_word]->arg, 0,
4968 BGP_INVALID_LABEL_INDEX);
718e3744 4969}
4970
4971DEFUN (bgp_network_backdoor,
4972 bgp_network_backdoor_cmd,
4973 "network A.B.C.D/M backdoor",
4974 "Specify a network to announce via BGP\n"
0c7b1b01 4975 "IPv4 prefix\n"
718e3744 4976 "Specify a BGP backdoor route\n")
4977{
d62a17ae 4978 int idx_ipv4_prefixlen = 1;
4979 return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
4980 SAFI_UNICAST, NULL, 1, BGP_INVALID_LABEL_INDEX);
718e3744 4981}
4982
4983DEFUN (bgp_network_mask,
4984 bgp_network_mask_cmd,
4985 "network A.B.C.D mask A.B.C.D",
4986 "Specify a network to announce via BGP\n"
4987 "Network number\n"
4988 "Network mask\n"
4989 "Network mask\n")
4990{
d62a17ae 4991 int idx_ipv4 = 1;
4992 int idx_ipv4_2 = 3;
4993 int ret;
4994 char prefix_str[BUFSIZ];
4995
4996 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
4997 prefix_str);
4998 if (!ret) {
4999 vty_out(vty, "%% Inconsistent address and mask\n");
5000 return CMD_WARNING_CONFIG_FAILED;
5001 }
718e3744 5002
d62a17ae 5003 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL,
5004 0, BGP_INVALID_LABEL_INDEX);
718e3744 5005}
5006
5007DEFUN (bgp_network_mask_route_map,
5008 bgp_network_mask_route_map_cmd,
5009 "network A.B.C.D mask A.B.C.D route-map WORD",
5010 "Specify a network to announce via BGP\n"
5011 "Network number\n"
5012 "Network mask\n"
5013 "Network mask\n"
5014 "Route-map to modify the attributes\n"
5015 "Name of the route map\n")
5016{
d62a17ae 5017 int idx_ipv4 = 1;
5018 int idx_ipv4_2 = 3;
5019 int idx_word = 5;
5020 int ret;
5021 char prefix_str[BUFSIZ];
5022
5023 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5024 prefix_str);
5025 if (!ret) {
5026 vty_out(vty, "%% Inconsistent address and mask\n");
5027 return CMD_WARNING_CONFIG_FAILED;
5028 }
718e3744 5029
d62a17ae 5030 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5031 argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
718e3744 5032}
5033
5034DEFUN (bgp_network_mask_backdoor,
5035 bgp_network_mask_backdoor_cmd,
5036 "network A.B.C.D mask A.B.C.D backdoor",
5037 "Specify a network to announce via BGP\n"
5038 "Network number\n"
5039 "Network mask\n"
5040 "Network mask\n"
5041 "Specify a BGP backdoor route\n")
5042{
d62a17ae 5043 int idx_ipv4 = 1;
5044 int idx_ipv4_2 = 3;
5045 int ret;
5046 char prefix_str[BUFSIZ];
5047
5048 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5049 prefix_str);
5050 if (!ret) {
5051 vty_out(vty, "%% Inconsistent address and mask\n");
5052 return CMD_WARNING_CONFIG_FAILED;
5053 }
718e3744 5054
d62a17ae 5055 return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1,
5056 BGP_INVALID_LABEL_INDEX);
718e3744 5057}
5058
5059DEFUN (bgp_network_mask_natural,
5060 bgp_network_mask_natural_cmd,
5061 "network A.B.C.D",
5062 "Specify a network to announce via BGP\n"
5063 "Network number\n")
5064{
d62a17ae 5065 int idx_ipv4 = 1;
5066 int ret;
5067 char prefix_str[BUFSIZ];
718e3744 5068
d62a17ae 5069 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5070 if (!ret) {
5071 vty_out(vty, "%% Inconsistent address and mask\n");
5072 return CMD_WARNING_CONFIG_FAILED;
5073 }
718e3744 5074
d62a17ae 5075 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL,
5076 0, BGP_INVALID_LABEL_INDEX);
718e3744 5077}
5078
5079DEFUN (bgp_network_mask_natural_route_map,
5080 bgp_network_mask_natural_route_map_cmd,
5081 "network A.B.C.D route-map WORD",
5082 "Specify a network to announce via BGP\n"
5083 "Network number\n"
5084 "Route-map to modify the attributes\n"
5085 "Name of the route map\n")
5086{
d62a17ae 5087 int idx_ipv4 = 1;
5088 int idx_word = 3;
5089 int ret;
5090 char prefix_str[BUFSIZ];
718e3744 5091
d62a17ae 5092 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5093 if (!ret) {
5094 vty_out(vty, "%% Inconsistent address and mask\n");
5095 return CMD_WARNING_CONFIG_FAILED;
5096 }
718e3744 5097
d62a17ae 5098 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5099 argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
718e3744 5100}
5101
5102DEFUN (bgp_network_mask_natural_backdoor,
5103 bgp_network_mask_natural_backdoor_cmd,
5104 "network A.B.C.D backdoor",
5105 "Specify a network to announce via BGP\n"
5106 "Network number\n"
5107 "Specify a BGP backdoor route\n")
5108{
d62a17ae 5109 int idx_ipv4 = 1;
5110 int ret;
5111 char prefix_str[BUFSIZ];
718e3744 5112
d62a17ae 5113 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5114 if (!ret) {
5115 vty_out(vty, "%% Inconsistent address and mask\n");
5116 return CMD_WARNING_CONFIG_FAILED;
5117 }
718e3744 5118
d62a17ae 5119 return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1,
5120 BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5121}
5122
5123DEFUN (bgp_network_label_index,
5124 bgp_network_label_index_cmd,
8b81993e 5125 "network A.B.C.D/M label-index (0-1048560)",
1b6d5c7e
VV
5126 "Specify a network to announce via BGP\n"
5127 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5128 "Label index to associate with the prefix\n"
5129 "Label index value\n")
5130{
d62a17ae 5131 u_int32_t label_index;
1b6d5c7e 5132
d62a17ae 5133 label_index = strtoul(argv[3]->arg, NULL, 10);
5134 return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty),
5135 NULL, 0, label_index);
1b6d5c7e
VV
5136}
5137
5138DEFUN (bgp_network_label_index_route_map,
5139 bgp_network_label_index_route_map_cmd,
8b81993e 5140 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
1b6d5c7e
VV
5141 "Specify a network to announce via BGP\n"
5142 "IP prefix\n"
5143 "Label index to associate with the prefix\n"
5144 "Label index value\n"
5145 "Route-map to modify the attributes\n"
5146 "Name of the route map\n")
5147{
d62a17ae 5148 u_int32_t label_index;
1b6d5c7e 5149
d62a17ae 5150 label_index = strtoul(argv[3]->arg, NULL, 10);
5151 return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty),
5152 argv[5]->arg, 0, label_index);
718e3744 5153}
5154
5155DEFUN (no_bgp_network,
5156 no_bgp_network_cmd,
a636c635 5157 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
718e3744 5158 NO_STR
5159 "Specify a network to announce via BGP\n"
0c7b1b01 5160 "IPv4 prefix\n"
a636c635
DW
5161 "Specify a BGP backdoor route\n"
5162 "Route-map to modify the attributes\n"
5163 "Name of the route map\n")
718e3744 5164{
d62a17ae 5165 int idx_ipv4_prefixlen = 2;
5166 return bgp_static_unset(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
5167 bgp_node_safi(vty));
718e3744 5168}
5169
718e3744 5170DEFUN (no_bgp_network_mask,
5171 no_bgp_network_mask_cmd,
a636c635 5172 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
718e3744 5173 NO_STR
5174 "Specify a network to announce via BGP\n"
5175 "Network number\n"
5176 "Network mask\n"
a636c635
DW
5177 "Network mask\n"
5178 "Specify a BGP backdoor route\n"
5179 "Route-map to modify the attributes\n"
5180 "Name of the route map\n")
718e3744 5181{
d62a17ae 5182 int idx_ipv4 = 2;
5183 int idx_ipv4_2 = 4;
5184 int ret;
5185 char prefix_str[BUFSIZ];
718e3744 5186
d62a17ae 5187 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5188 prefix_str);
5189 if (!ret) {
5190 vty_out(vty, "%% Inconsistent address and mask\n");
5191 return CMD_WARNING_CONFIG_FAILED;
5192 }
718e3744 5193
d62a17ae 5194 return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 5195}
5196
718e3744 5197DEFUN (no_bgp_network_mask_natural,
5198 no_bgp_network_mask_natural_cmd,
a636c635 5199 "no network A.B.C.D [<backdoor|route-map WORD>]",
718e3744 5200 NO_STR
5201 "Specify a network to announce via BGP\n"
a636c635
DW
5202 "Network number\n"
5203 "Specify a BGP backdoor route\n"
5204 "Route-map to modify the attributes\n"
5205 "Name of the route map\n")
718e3744 5206{
d62a17ae 5207 int idx_ipv4 = 2;
5208 int ret;
5209 char prefix_str[BUFSIZ];
718e3744 5210
d62a17ae 5211 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5212 if (!ret) {
5213 vty_out(vty, "%% Inconsistent address and mask\n");
5214 return CMD_WARNING_CONFIG_FAILED;
5215 }
718e3744 5216
d62a17ae 5217 return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 5218}
5219
d62a17ae 5220ALIAS(no_bgp_network, no_bgp_network_label_index_cmd,
9d303b37 5221 "no network A.B.C.D/M label-index (0-1048560)", NO_STR
d62a17ae 5222 "Specify a network to announce via BGP\n"
5223 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5224 "Label index to associate with the prefix\n"
5225 "Label index value\n")
1b6d5c7e 5226
d62a17ae 5227ALIAS(no_bgp_network, no_bgp_network_label_index_route_map_cmd,
9d303b37 5228 "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
d62a17ae 5229 "Specify a network to announce via BGP\n"
5230 "IP prefix\n"
5231 "Label index to associate with the prefix\n"
5232 "Label index value\n"
5233 "Route-map to modify the attributes\n"
5234 "Name of the route map\n")
1b6d5c7e 5235
718e3744 5236DEFUN (ipv6_bgp_network,
5237 ipv6_bgp_network_cmd,
5238 "network X:X::X:X/M",
5239 "Specify a network to announce via BGP\n"
0c7b1b01 5240 "IPv6 prefix\n")
718e3744 5241{
d62a17ae 5242 int idx_ipv6_prefixlen = 1;
5243 return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
5244 bgp_node_safi(vty), NULL, 0,
5245 BGP_INVALID_LABEL_INDEX);
718e3744 5246}
5247
5248DEFUN (ipv6_bgp_network_route_map,
5249 ipv6_bgp_network_route_map_cmd,
5250 "network X:X::X:X/M route-map WORD",
5251 "Specify a network to announce via BGP\n"
0c7b1b01 5252 "IPv6 prefix\n"
718e3744 5253 "Route-map to modify the attributes\n"
5254 "Name of the route map\n")
5255{
d62a17ae 5256 int idx_ipv6_prefixlen = 1;
5257 int idx_word = 3;
5258 return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
5259 bgp_node_safi(vty), argv[idx_word]->arg, 0,
5260 BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5261}
5262
5263DEFUN (ipv6_bgp_network_label_index,
5264 ipv6_bgp_network_label_index_cmd,
8b81993e 5265 "network X:X::X:X/M label-index (0-1048560)",
1b6d5c7e
VV
5266 "Specify a network to announce via BGP\n"
5267 "IPv6 prefix <network>/<length>\n"
5268 "Label index to associate with the prefix\n"
5269 "Label index value\n")
5270{
d62a17ae 5271 u_int32_t label_index;
1b6d5c7e 5272
d62a17ae 5273 label_index = strtoul(argv[3]->arg, NULL, 10);
5274 return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty),
5275 NULL, 0, label_index);
1b6d5c7e
VV
5276}
5277
5278DEFUN (ipv6_bgp_network_label_index_route_map,
5279 ipv6_bgp_network_label_index_route_map_cmd,
8b81993e 5280 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
1b6d5c7e
VV
5281 "Specify a network to announce via BGP\n"
5282 "IPv6 prefix\n"
5283 "Label index to associate with the prefix\n"
5284 "Label index value\n"
5285 "Route-map to modify the attributes\n"
5286 "Name of the route map\n")
5287{
d62a17ae 5288 u_int32_t label_index;
1b6d5c7e 5289
d62a17ae 5290 label_index = strtoul(argv[3]->arg, NULL, 10);
5291 return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty),
5292 argv[5]->arg, 0, label_index);
718e3744 5293}
5294
5295DEFUN (no_ipv6_bgp_network,
5296 no_ipv6_bgp_network_cmd,
a636c635 5297 "no network X:X::X:X/M [route-map WORD]",
718e3744 5298 NO_STR
5299 "Specify a network to announce via BGP\n"
0c7b1b01 5300 "IPv6 prefix\n"
a636c635
DW
5301 "Route-map to modify the attributes\n"
5302 "Name of the route map\n")
718e3744 5303{
d62a17ae 5304 int idx_ipv6_prefixlen = 2;
5305 return bgp_static_unset(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
5306 bgp_node_safi(vty));
718e3744 5307}
5308
d62a17ae 5309ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_cmd,
9d303b37 5310 "no network X:X::X:X/M label-index (0-1048560)", NO_STR
d62a17ae 5311 "Specify a network to announce via BGP\n"
5312 "IPv6 prefix <network>/<length>\n"
5313 "Label index to associate with the prefix\n"
5314 "Label index value\n")
1b6d5c7e 5315
d62a17ae 5316ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_route_map_cmd,
9d303b37 5317 "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
d62a17ae 5318 "Specify a network to announce via BGP\n"
5319 "IPv6 prefix\n"
5320 "Label index to associate with the prefix\n"
5321 "Label index value\n"
5322 "Route-map to modify the attributes\n"
5323 "Name of the route map\n")
1b6d5c7e 5324
718e3744 5325/* Aggreagete address:
5326
5327 advertise-map Set condition to advertise attribute
5328 as-set Generate AS set path information
5329 attribute-map Set attributes of aggregate
5330 route-map Set parameters of aggregate
5331 summary-only Filter more specific routes from updates
5332 suppress-map Conditionally filter more specific routes from updates
5333 <cr>
5334 */
d62a17ae 5335struct bgp_aggregate {
5336 /* Summary-only flag. */
5337 u_char summary_only;
718e3744 5338
d62a17ae 5339 /* AS set generation. */
5340 u_char as_set;
718e3744 5341
d62a17ae 5342 /* Route-map for aggregated route. */
5343 struct route_map *map;
718e3744 5344
d62a17ae 5345 /* Suppress-count. */
5346 unsigned long count;
718e3744 5347
d62a17ae 5348 /* SAFI configuration. */
5349 safi_t safi;
718e3744 5350};
5351
d62a17ae 5352static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5353{
d62a17ae 5354 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5355}
5356
d62a17ae 5357static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5358{
d62a17ae 5359 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5360}
718e3744 5361
b5d58c32 5362/* Update an aggregate as routes are added/removed from the BGP table */
d62a17ae 5363static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
5364 struct bgp_info *rinew, afi_t afi, safi_t safi,
5365 struct bgp_info *del,
5366 struct bgp_aggregate *aggregate)
5367{
5368 struct bgp_table *table;
5369 struct bgp_node *top;
5370 struct bgp_node *rn;
5371 u_char origin;
5372 struct aspath *aspath = NULL;
5373 struct aspath *asmerge = NULL;
5374 struct community *community = NULL;
5375 struct community *commerge = NULL;
ffd0c037 5376#if defined(AGGREGATE_NEXTHOP_CHECK)
d62a17ae 5377 struct in_addr nexthop;
5378 u_int32_t med = 0;
ffd0c037 5379#endif
d62a17ae 5380 struct bgp_info *ri;
5381 struct bgp_info *new;
5382 int first = 1;
5383 unsigned long match = 0;
5384 u_char atomic_aggregate = 0;
5385
5386 /* Record adding route's nexthop and med. */
5387 if (rinew) {
ffd0c037 5388#if defined(AGGREGATE_NEXTHOP_CHECK)
d62a17ae 5389 nexthop = rinew->attr->nexthop;
5390 med = rinew->attr->med;
ffd0c037 5391#endif
d62a17ae 5392 }
718e3744 5393
d62a17ae 5394 /* ORIGIN attribute: If at least one route among routes that are
5395 aggregated has ORIGIN with the value INCOMPLETE, then the
5396 aggregated route must have the ORIGIN attribute with the value
5397 INCOMPLETE. Otherwise, if at least one route among routes that
5398 are aggregated has ORIGIN with the value EGP, then the aggregated
5399 route must have the origin attribute with the value EGP. In all
5400 other case the value of the ORIGIN attribute of the aggregated
5401 route is INTERNAL. */
5402 origin = BGP_ORIGIN_IGP;
718e3744 5403
d62a17ae 5404 table = bgp->rib[afi][safi];
718e3744 5405
d62a17ae 5406 top = bgp_node_get(table, p);
5407 for (rn = bgp_node_get(table, p); rn;
5408 rn = bgp_route_next_until(rn, top))
5409 if (rn->p.prefixlen > p->prefixlen) {
5410 match = 0;
5411
5412 for (ri = rn->info; ri; ri = ri->next) {
5413 if (BGP_INFO_HOLDDOWN(ri))
5414 continue;
5415
5416 if (del && ri == del)
5417 continue;
5418
5419 if (!rinew && first) {
ffd0c037 5420#if defined(AGGREGATE_NEXTHOP_CHECK)
d62a17ae 5421 nexthop = ri->attr->nexthop;
5422 med = ri->attr->med;
ffd0c037 5423#endif
d62a17ae 5424 first = 0;
5425 }
718e3744 5426
5427#ifdef AGGREGATE_NEXTHOP_CHECK
d62a17ae 5428 if (!IPV4_ADDR_SAME(&ri->attr->nexthop,
5429 &nexthop)
5430 || ri->attr->med != med) {
5431 if (aspath)
5432 aspath_free(aspath);
5433 if (community)
5434 community_free(community);
5435 bgp_unlock_node(rn);
5436 bgp_unlock_node(top);
5437 return;
5438 }
718e3744 5439#endif /* AGGREGATE_NEXTHOP_CHECK */
5440
d62a17ae 5441 if (ri->attr->flag
5442 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5443 atomic_aggregate = 1;
5444
5445 if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
5446 if (aggregate->summary_only) {
5447 (bgp_info_extra_get(ri))
5448 ->suppress++;
5449 bgp_info_set_flag(
5450 rn, ri,
5451 BGP_INFO_ATTR_CHANGED);
5452 match++;
5453 }
5454
5455 aggregate->count++;
5456
5457 if (origin < ri->attr->origin)
5458 origin = ri->attr->origin;
5459
5460 if (aggregate->as_set) {
5461 if (aspath) {
5462 asmerge = aspath_aggregate(
5463 aspath,
5464 ri->attr->aspath);
5465 aspath_free(aspath);
5466 aspath = asmerge;
5467 } else
5468 aspath = aspath_dup(
5469 ri->attr->aspath);
5470
5471 if (ri->attr->community) {
5472 if (community) {
5473 commerge = community_merge(
5474 community,
5475 ri->attr->community);
5476 community = community_uniq_sort(
5477 commerge);
5478 community_free(
5479 commerge);
5480 } else
5481 community = community_dup(
5482 ri->attr->community);
5483 }
5484 }
5485 }
5486 }
5487 if (match)
5488 bgp_process(bgp, rn, afi, safi);
5489 }
5490 bgp_unlock_node(top);
718e3744 5491
d62a17ae 5492 if (rinew) {
718e3744 5493 aggregate->count++;
5494
d62a17ae 5495 if (aggregate->summary_only)
5496 (bgp_info_extra_get(rinew))->suppress++;
5497
5498 if (origin < rinew->attr->origin)
5499 origin = rinew->attr->origin;
5500
5501 if (aggregate->as_set) {
5502 if (aspath) {
5503 asmerge = aspath_aggregate(aspath,
5504 rinew->attr->aspath);
5505 aspath_free(aspath);
5506 aspath = asmerge;
5507 } else
5508 aspath = aspath_dup(rinew->attr->aspath);
5509
5510 if (rinew->attr->community) {
5511 if (community) {
5512 commerge = community_merge(
5513 community,
5514 rinew->attr->community);
5515 community =
5516 community_uniq_sort(commerge);
5517 community_free(commerge);
5518 } else
5519 community = community_dup(
5520 rinew->attr->community);
5521 }
718e3744 5522 }
718e3744 5523 }
718e3744 5524
d62a17ae 5525 if (aggregate->count > 0) {
5526 rn = bgp_node_get(table, p);
5527 new = info_make(
5528 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5529 bgp_attr_aggregate_intern(bgp, origin, aspath,
5530 community, aggregate->as_set,
5531 atomic_aggregate),
5532 rn);
5533 SET_FLAG(new->flags, BGP_INFO_VALID);
5534
5535 bgp_info_add(rn, new);
5536 bgp_unlock_node(rn);
5537 bgp_process(bgp, rn, afi, safi);
5538 } else {
5539 if (aspath)
5540 aspath_free(aspath);
5541 if (community)
5542 community_free(community);
5543 }
718e3744 5544}
5545
d62a17ae 5546void bgp_aggregate_delete(struct bgp *, struct prefix *, afi_t, safi_t,
5547 struct bgp_aggregate *);
718e3744 5548
d62a17ae 5549void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
5550 struct bgp_info *ri, afi_t afi, safi_t safi)
718e3744 5551{
d62a17ae 5552 struct bgp_node *child;
5553 struct bgp_node *rn;
5554 struct bgp_aggregate *aggregate;
5555 struct bgp_table *table;
718e3744 5556
d62a17ae 5557 /* MPLS-VPN aggregation is not yet supported. */
5558 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5559 || (safi == SAFI_EVPN))
5560 return;
718e3744 5561
d62a17ae 5562 table = bgp->aggregate[afi][safi];
f018db83 5563
d62a17ae 5564 /* No aggregates configured. */
5565 if (bgp_table_top_nolock(table) == NULL)
5566 return;
f018db83 5567
d62a17ae 5568 if (p->prefixlen == 0)
5569 return;
718e3744 5570
d62a17ae 5571 if (BGP_INFO_HOLDDOWN(ri))
5572 return;
718e3744 5573
d62a17ae 5574 child = bgp_node_get(table, p);
718e3744 5575
d62a17ae 5576 /* Aggregate address configuration check. */
5577 for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
5578 if ((aggregate = rn->info) != NULL
5579 && rn->p.prefixlen < p->prefixlen) {
5580 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5581 bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL,
5582 aggregate);
5583 }
5584 bgp_unlock_node(child);
718e3744 5585}
5586
d62a17ae 5587void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
5588 struct bgp_info *del, afi_t afi, safi_t safi)
718e3744 5589{
d62a17ae 5590 struct bgp_node *child;
5591 struct bgp_node *rn;
5592 struct bgp_aggregate *aggregate;
5593 struct bgp_table *table;
718e3744 5594
d62a17ae 5595 /* MPLS-VPN aggregation is not yet supported. */
5596 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5597 || (safi == SAFI_EVPN))
5598 return;
f018db83 5599
d62a17ae 5600 table = bgp->aggregate[afi][safi];
718e3744 5601
d62a17ae 5602 /* No aggregates configured. */
5603 if (bgp_table_top_nolock(table) == NULL)
5604 return;
718e3744 5605
d62a17ae 5606 if (p->prefixlen == 0)
5607 return;
718e3744 5608
d62a17ae 5609 child = bgp_node_get(table, p);
718e3744 5610
d62a17ae 5611 /* Aggregate address configuration check. */
5612 for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
5613 if ((aggregate = rn->info) != NULL
5614 && rn->p.prefixlen < p->prefixlen) {
5615 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5616 bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
5617 aggregate);
5618 }
5619 bgp_unlock_node(child);
5620}
718e3744 5621
d62a17ae 5622/* Called via bgp_aggregate_set when the user configures aggregate-address */
5623static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
5624 safi_t safi, struct bgp_aggregate *aggregate)
5625{
5626 struct bgp_table *table;
5627 struct bgp_node *top;
5628 struct bgp_node *rn;
5629 struct bgp_info *new;
5630 struct bgp_info *ri;
5631 unsigned long match;
5632 u_char origin = BGP_ORIGIN_IGP;
5633 struct aspath *aspath = NULL;
5634 struct aspath *asmerge = NULL;
5635 struct community *community = NULL;
5636 struct community *commerge = NULL;
5637 u_char atomic_aggregate = 0;
5638
5639 table = bgp->rib[afi][safi];
5640
5641 /* Sanity check. */
5642 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5643 return;
5644 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5645 return;
42f7e184 5646
d62a17ae 5647 /* If routes exists below this node, generate aggregate routes. */
5648 top = bgp_node_get(table, p);
5649 for (rn = bgp_node_get(table, p); rn;
5650 rn = bgp_route_next_until(rn, top))
5651 if (rn->p.prefixlen > p->prefixlen) {
5652 match = 0;
5653
5654 for (ri = rn->info; ri; ri = ri->next) {
5655 if (BGP_INFO_HOLDDOWN(ri))
5656 continue;
5657
5658 if (ri->attr->flag
5659 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5660 atomic_aggregate = 1;
5661
5662 if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
5663 /* summary-only aggregate route suppress
5664 aggregated
5665 route announcement. */
5666 if (aggregate->summary_only) {
5667 (bgp_info_extra_get(ri))
5668 ->suppress++;
5669 bgp_info_set_flag(
5670 rn, ri,
5671 BGP_INFO_ATTR_CHANGED);
5672 match++;
5673 }
5674
5675 /* If at least one route among routes
5676 * that are aggregated has
5677 * ORIGIN with the value INCOMPLETE,
5678 * then the aggregated route
5679 * MUST have the ORIGIN attribute with
5680 * the value INCOMPLETE.
5681 * Otherwise, if at least one route
5682 * among routes that are
5683 * aggregated has ORIGIN with the value
5684 * EGP, then the aggregated
5685 * route MUST have the ORIGIN attribute
5686 * with the value EGP.
5687 */
5688 if (origin < ri->attr->origin)
5689 origin = ri->attr->origin;
5690
5691 /* as-set aggregate route generate
5692 origin, as path,
5693 community aggregation. */
5694 if (aggregate->as_set) {
5695 if (aspath) {
5696 asmerge = aspath_aggregate(
5697 aspath,
5698 ri->attr->aspath);
5699 aspath_free(aspath);
5700 aspath = asmerge;
5701 } else
5702 aspath = aspath_dup(
5703 ri->attr->aspath);
5704
5705 if (ri->attr->community) {
5706 if (community) {
5707 commerge = community_merge(
5708 community,
5709 ri->attr->community);
5710 community = community_uniq_sort(
5711 commerge);
5712 community_free(
5713 commerge);
5714 } else
5715 community = community_dup(
5716 ri->attr->community);
5717 }
5718 }
5719 aggregate->count++;
5720 }
5721 }
5722
5723 /* If this node is suppressed, process the change. */
5724 if (match)
5725 bgp_process(bgp, rn, afi, safi);
5726 }
5727 bgp_unlock_node(top);
5728
5729 /* Add aggregate route to BGP table. */
5730 if (aggregate->count) {
5731 rn = bgp_node_get(table, p);
5732 new = info_make(
5733 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5734 bgp_attr_aggregate_intern(bgp, origin, aspath,
5735 community, aggregate->as_set,
5736 atomic_aggregate),
5737 rn);
5738 SET_FLAG(new->flags, BGP_INFO_VALID);
5739
5740 bgp_info_add(rn, new);
5741 bgp_unlock_node(rn);
5742
5743 /* Process change. */
5744 bgp_process(bgp, rn, afi, safi);
5745 } else {
5746 if (aspath)
5747 aspath_free(aspath);
5748 if (community)
5749 community_free(community);
5750 }
718e3744 5751}
5752
d62a17ae 5753void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5754 safi_t safi, struct bgp_aggregate *aggregate)
718e3744 5755{
d62a17ae 5756 struct bgp_table *table;
5757 struct bgp_node *top;
5758 struct bgp_node *rn;
5759 struct bgp_info *ri;
5760 unsigned long match;
718e3744 5761
d62a17ae 5762 table = bgp->rib[afi][safi];
718e3744 5763
d62a17ae 5764 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5765 return;
5766 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5767 return;
5768
5769 /* If routes exists below this node, generate aggregate routes. */
5770 top = bgp_node_get(table, p);
5771 for (rn = bgp_node_get(table, p); rn;
5772 rn = bgp_route_next_until(rn, top))
5773 if (rn->p.prefixlen > p->prefixlen) {
5774 match = 0;
5775
5776 for (ri = rn->info; ri; ri = ri->next) {
5777 if (BGP_INFO_HOLDDOWN(ri))
5778 continue;
5779
5780 if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
5781 if (aggregate->summary_only
5782 && ri->extra) {
5783 ri->extra->suppress--;
5784
5785 if (ri->extra->suppress == 0) {
5786 bgp_info_set_flag(
5787 rn, ri,
5788 BGP_INFO_ATTR_CHANGED);
5789 match++;
5790 }
5791 }
5792 aggregate->count--;
5793 }
5794 }
5795
5796 /* If this node was suppressed, process the change. */
5797 if (match)
5798 bgp_process(bgp, rn, afi, safi);
5799 }
5800 bgp_unlock_node(top);
718e3744 5801
d62a17ae 5802 /* Delete aggregate route from BGP table. */
5803 rn = bgp_node_get(table, p);
718e3744 5804
5805 for (ri = rn->info; ri; ri = ri->next)
d62a17ae 5806 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
5807 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5808 break;
5809
5810 /* Withdraw static BGP route from routing table. */
5811 if (ri) {
5812 bgp_info_delete(rn, ri);
5813 bgp_process(bgp, rn, afi, safi);
5814 }
718e3744 5815
d62a17ae 5816 /* Unlock bgp_node_lookup. */
5817 bgp_unlock_node(rn);
718e3744 5818}
5819
5820/* Aggregate route attribute. */
5821#define AGGREGATE_SUMMARY_ONLY 1
5822#define AGGREGATE_AS_SET 1
5823
d62a17ae 5824static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5825 afi_t afi, safi_t safi)
718e3744 5826{
d62a17ae 5827 VTY_DECLVAR_CONTEXT(bgp, bgp);
5828 int ret;
5829 struct prefix p;
5830 struct bgp_node *rn;
5831 struct bgp_aggregate *aggregate;
718e3744 5832
d62a17ae 5833 /* Convert string to prefix structure. */
5834 ret = str2prefix(prefix_str, &p);
5835 if (!ret) {
5836 vty_out(vty, "Malformed prefix\n");
5837 return CMD_WARNING_CONFIG_FAILED;
5838 }
5839 apply_mask(&p);
5840
5841 /* Old configuration check. */
5842 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5843 if (!rn) {
5844 vty_out(vty,
5845 "%% There is no aggregate-address configuration.\n");
5846 return CMD_WARNING_CONFIG_FAILED;
5847 }
f6269b4f 5848
d62a17ae 5849 aggregate = rn->info;
5850 if (aggregate->safi == SAFI_UNICAST)
5851 bgp_aggregate_delete(bgp, &p, afi, SAFI_UNICAST, aggregate);
5852 if (aggregate->safi == SAFI_LABELED_UNICAST)
5853 bgp_aggregate_delete(bgp, &p, afi, SAFI_LABELED_UNICAST,
5854 aggregate);
5855 if (aggregate->safi == SAFI_MULTICAST)
5856 bgp_aggregate_delete(bgp, &p, afi, SAFI_MULTICAST, aggregate);
5857
5858 /* Unlock aggregate address configuration. */
5859 rn->info = NULL;
5860 bgp_aggregate_free(aggregate);
5861 bgp_unlock_node(rn);
5862 bgp_unlock_node(rn);
5863
5864 return CMD_SUCCESS;
5865}
5866
5867static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
5868 safi_t safi, u_char summary_only, u_char as_set)
5869{
5870 VTY_DECLVAR_CONTEXT(bgp, bgp);
5871 int ret;
5872 struct prefix p;
5873 struct bgp_node *rn;
5874 struct bgp_aggregate *aggregate;
5875
5876 /* Convert string to prefix structure. */
5877 ret = str2prefix(prefix_str, &p);
5878 if (!ret) {
5879 vty_out(vty, "Malformed prefix\n");
5880 return CMD_WARNING_CONFIG_FAILED;
5881 }
5882 apply_mask(&p);
5883
5884 /* Old configuration check. */
5885 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
5886
5887 if (rn->info) {
5888 vty_out(vty, "There is already same aggregate network.\n");
5889 /* try to remove the old entry */
5890 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
5891 if (ret) {
5892 vty_out(vty, "Error deleting aggregate.\n");
5893 bgp_unlock_node(rn);
5894 return CMD_WARNING_CONFIG_FAILED;
5895 }
5896 }
718e3744 5897
d62a17ae 5898 /* Make aggregate address structure. */
5899 aggregate = bgp_aggregate_new();
5900 aggregate->summary_only = summary_only;
5901 aggregate->as_set = as_set;
5902 aggregate->safi = safi;
5903 rn->info = aggregate;
718e3744 5904
d62a17ae 5905 /* Aggregate address insert into BGP routing table. */
5906 if (safi == SAFI_UNICAST)
5907 bgp_aggregate_add(bgp, &p, afi, SAFI_UNICAST, aggregate);
5908 if (safi == SAFI_LABELED_UNICAST)
5909 bgp_aggregate_add(bgp, &p, afi, SAFI_LABELED_UNICAST,
5910 aggregate);
5911 if (safi == SAFI_MULTICAST)
5912 bgp_aggregate_add(bgp, &p, afi, SAFI_MULTICAST, aggregate);
718e3744 5913
d62a17ae 5914 return CMD_SUCCESS;
718e3744 5915}
5916
5917DEFUN (aggregate_address,
5918 aggregate_address_cmd,
e3e6107d 5919 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5920 "Configure BGP aggregate entries\n"
5921 "Aggregate prefix\n"
5922 "Generate AS set path information\n"
a636c635
DW
5923 "Filter more specific routes from updates\n"
5924 "Filter more specific routes from updates\n"
5925 "Generate AS set path information\n")
718e3744 5926{
d62a17ae 5927 int idx = 0;
5928 argv_find(argv, argc, "A.B.C.D/M", &idx);
5929 char *prefix = argv[idx]->arg;
5930 int as_set =
5931 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5932 idx = 0;
5933 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5934 ? AGGREGATE_SUMMARY_ONLY
5935 : 0;
e3e6107d 5936
d62a17ae 5937 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
5938 summary_only, as_set);
718e3744 5939}
5940
e3e6107d
QY
5941DEFUN (aggregate_address_mask,
5942 aggregate_address_mask_cmd,
5943 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5944 "Configure BGP aggregate entries\n"
5945 "Aggregate address\n"
5946 "Aggregate mask\n"
5947 "Generate AS set path information\n"
a636c635
DW
5948 "Filter more specific routes from updates\n"
5949 "Filter more specific routes from updates\n"
5950 "Generate AS set path information\n")
718e3744 5951{
d62a17ae 5952 int idx = 0;
5953 argv_find(argv, argc, "A.B.C.D", &idx);
5954 char *prefix = argv[idx]->arg;
5955 char *mask = argv[idx + 1]->arg;
5956 int as_set =
5957 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5958 idx = 0;
5959 int summary_only = argv_find(argv, argc, "summary-only", &idx)
5960 ? AGGREGATE_SUMMARY_ONLY
5961 : 0;
5962
5963 char prefix_str[BUFSIZ];
5964 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
5965
5966 if (!ret) {
5967 vty_out(vty, "%% Inconsistent address and mask\n");
5968 return CMD_WARNING_CONFIG_FAILED;
5969 }
718e3744 5970
d62a17ae 5971 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5972 summary_only, as_set);
718e3744 5973}
5974
718e3744 5975DEFUN (no_aggregate_address,
5976 no_aggregate_address_cmd,
e3e6107d 5977 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5978 NO_STR
5979 "Configure BGP aggregate entries\n"
a636c635
DW
5980 "Aggregate prefix\n"
5981 "Generate AS set path information\n"
e3e6107d
QY
5982 "Filter more specific routes from updates\n"
5983 "Filter more specific routes from updates\n"
5984 "Generate AS set path information\n")
718e3744 5985{
d62a17ae 5986 int idx = 0;
5987 argv_find(argv, argc, "A.B.C.D/M", &idx);
5988 char *prefix = argv[idx]->arg;
5989 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 5990}
5991
718e3744 5992DEFUN (no_aggregate_address_mask,
5993 no_aggregate_address_mask_cmd,
e3e6107d 5994 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5995 NO_STR
5996 "Configure BGP aggregate entries\n"
5997 "Aggregate address\n"
a636c635
DW
5998 "Aggregate mask\n"
5999 "Generate AS set path information\n"
e3e6107d
QY
6000 "Filter more specific routes from updates\n"
6001 "Filter more specific routes from updates\n"
6002 "Generate AS set path information\n")
718e3744 6003{
d62a17ae 6004 int idx = 0;
6005 argv_find(argv, argc, "A.B.C.D", &idx);
6006 char *prefix = argv[idx]->arg;
6007 char *mask = argv[idx + 1]->arg;
718e3744 6008
d62a17ae 6009 char prefix_str[BUFSIZ];
6010 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6011
d62a17ae 6012 if (!ret) {
6013 vty_out(vty, "%% Inconsistent address and mask\n");
6014 return CMD_WARNING_CONFIG_FAILED;
6015 }
718e3744 6016
d62a17ae 6017 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6018}
6019
718e3744 6020DEFUN (ipv6_aggregate_address,
6021 ipv6_aggregate_address_cmd,
e3e6107d 6022 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6023 "Configure BGP aggregate entries\n"
6024 "Aggregate prefix\n"
6025 "Filter more specific routes from updates\n")
6026{
d62a17ae 6027 int idx = 0;
6028 argv_find(argv, argc, "X:X::X:X/M", &idx);
6029 char *prefix = argv[idx]->arg;
6030 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6031 ? AGGREGATE_SUMMARY_ONLY
6032 : 0;
6033 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6034 0);
718e3744 6035}
6036
6037DEFUN (no_ipv6_aggregate_address,
6038 no_ipv6_aggregate_address_cmd,
e3e6107d 6039 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6040 NO_STR
6041 "Configure BGP aggregate entries\n"
16cedbb0
QY
6042 "Aggregate prefix\n"
6043 "Filter more specific routes from updates\n")
718e3744 6044{
d62a17ae 6045 int idx = 0;
6046 argv_find(argv, argc, "X:X::X:X/M", &idx);
6047 char *prefix = argv[idx]->arg;
6048 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6049}
6050
718e3744 6051/* Redistribute route treatment. */
d62a17ae 6052void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
6053 const struct in_addr *nexthop,
6054 const struct in6_addr *nexthop6, unsigned int ifindex,
6055 u_int32_t metric, u_char type, u_short instance,
6056 route_tag_t tag)
6057{
6058 struct bgp_info *new;
6059 struct bgp_info *bi;
6060 struct bgp_info info;
6061 struct bgp_node *bn;
6062 struct attr attr;
6063 struct attr *new_attr;
6064 afi_t afi;
6065 int ret;
6066 struct bgp_redist *red;
6067
6068 /* Make default attribute. */
6069 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
6070 if (nexthop)
6071 attr.nexthop = *nexthop;
6072 attr.nh_ifindex = ifindex;
6073
6074 if (nexthop6) {
6075 attr.mp_nexthop_global = *nexthop6;
6076 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6077 }
f04a80a5 6078
d62a17ae 6079 attr.med = metric;
6080 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6081 attr.tag = tag;
718e3744 6082
d62a17ae 6083 afi = family2afi(p->family);
6aeb9e78 6084
d62a17ae 6085 red = bgp_redist_lookup(bgp, afi, type, instance);
6086 if (red) {
6087 struct attr attr_new;
718e3744 6088
d62a17ae 6089 /* Copy attribute for modification. */
6090 bgp_attr_dup(&attr_new, &attr);
718e3744 6091
d62a17ae 6092 if (red->redist_metric_flag)
6093 attr_new.med = red->redist_metric;
718e3744 6094
d62a17ae 6095 /* Apply route-map. */
6096 if (red->rmap.name) {
6097 info.peer = bgp->peer_self;
6098 info.attr = &attr_new;
718e3744 6099
d62a17ae 6100 SET_FLAG(bgp->peer_self->rmap_type,
6101 PEER_RMAP_TYPE_REDISTRIBUTE);
6102
6103 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
6104 &info);
6105
6106 bgp->peer_self->rmap_type = 0;
6107
6108 if (ret == RMAP_DENYMATCH) {
6109 /* Free uninterned attribute. */
6110 bgp_attr_flush(&attr_new);
6111
6112 /* Unintern original. */
6113 aspath_unintern(&attr.aspath);
6114 bgp_redistribute_delete(bgp, p, type, instance);
6115 return;
6116 }
6117 }
6118
6119 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6120 SAFI_UNICAST, p, NULL);
6121
6122 new_attr = bgp_attr_intern(&attr_new);
6123
6124 for (bi = bn->info; bi; bi = bi->next)
6125 if (bi->peer == bgp->peer_self
6126 && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
6127 break;
6128
6129 if (bi) {
6130 /* Ensure the (source route) type is updated. */
6131 bi->type = type;
6132 if (attrhash_cmp(bi->attr, new_attr)
6133 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
6134 bgp_attr_unintern(&new_attr);
6135 aspath_unintern(&attr.aspath);
6136 bgp_unlock_node(bn);
6137 return;
6138 } else {
6139 /* The attribute is changed. */
6140 bgp_info_set_flag(bn, bi,
6141 BGP_INFO_ATTR_CHANGED);
6142
6143 /* Rewrite BGP route information. */
6144 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
6145 bgp_info_restore(bn, bi);
6146 else
6147 bgp_aggregate_decrement(bgp, p, bi, afi,
6148 SAFI_UNICAST);
6149 bgp_attr_unintern(&bi->attr);
6150 bi->attr = new_attr;
6151 bi->uptime = bgp_clock();
6152
6153 /* Process change. */
6154 bgp_aggregate_increment(bgp, p, bi, afi,
6155 SAFI_UNICAST);
6156 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6157 bgp_unlock_node(bn);
6158 aspath_unintern(&attr.aspath);
6159 return;
6160 }
6161 }
6162
6163 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6164 bgp->peer_self, new_attr, bn);
6165 SET_FLAG(new->flags, BGP_INFO_VALID);
6166
6167 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
6168 bgp_info_add(bn, new);
6169 bgp_unlock_node(bn);
6170 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6171 }
6172
6173 /* Unintern original. */
6174 aspath_unintern(&attr.aspath);
718e3744 6175}
6176
d62a17ae 6177void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, u_char type,
6178 u_short instance)
718e3744 6179{
d62a17ae 6180 afi_t afi;
6181 struct bgp_node *rn;
6182 struct bgp_info *ri;
6183 struct bgp_redist *red;
718e3744 6184
d62a17ae 6185 afi = family2afi(p->family);
718e3744 6186
d62a17ae 6187 red = bgp_redist_lookup(bgp, afi, type, instance);
6188 if (red) {
6189 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6190 SAFI_UNICAST, p, NULL);
6191
6192 for (ri = rn->info; ri; ri = ri->next)
6193 if (ri->peer == bgp->peer_self && ri->type == type)
6194 break;
6195
6196 if (ri) {
6197 bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
6198 bgp_info_delete(rn, ri);
6199 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6200 }
6201 bgp_unlock_node(rn);
6202 }
6203}
6204
6205/* Withdraw specified route type's route. */
6206void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
6207 u_short instance)
6208{
6209 struct bgp_node *rn;
6210 struct bgp_info *ri;
6211 struct bgp_table *table;
6212
6213 table = bgp->rib[afi][SAFI_UNICAST];
6214
6215 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6216 for (ri = rn->info; ri; ri = ri->next)
6217 if (ri->peer == bgp->peer_self && ri->type == type
6218 && ri->instance == instance)
6219 break;
6220
6221 if (ri) {
6222 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
6223 SAFI_UNICAST);
6224 bgp_info_delete(rn, ri);
6225 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6226 }
718e3744 6227 }
718e3744 6228}
6b0655a2 6229
718e3744 6230/* Static function to display route. */
9c92b5f7
MK
6231static void route_vty_out_route(struct prefix *p, struct vty *vty,
6232 json_object *json)
718e3744 6233{
d62a17ae 6234 int len;
6235 u_int32_t destination;
6236 char buf[BUFSIZ];
718e3744 6237
d62a17ae 6238 if (p->family == AF_INET) {
c6462ff4
MK
6239 if (!json) {
6240 len = vty_out(vty, "%s",
6241 inet_ntop(p->family, &p->u.prefix, buf,
6242 BUFSIZ));
6243 destination = ntohl(p->u.prefix4.s_addr);
6244
6245 if ((IN_CLASSC(destination) && p->prefixlen == 24)
6246 || (IN_CLASSB(destination) && p->prefixlen == 16)
6247 || (IN_CLASSA(destination) && p->prefixlen == 8)
6248 || p->u.prefix4.s_addr == 0) {
b682f6de 6249 /* When mask is natural,
6250 mask is not displayed. */
c6462ff4
MK
6251 } else
6252 len += vty_out(vty, "/%d", p->prefixlen);
6253 } else {
6254 json_object_string_add(json, "prefix",
6255 inet_ntop(p->family,
6256 &p->u.prefix, buf,
6257 BUFSIZ));
6258 json_object_int_add(json, "prefixLen", p->prefixlen);
6259 }
d62a17ae 6260 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6261 prefix2str(p, buf, PREFIX_STRLEN);
6262 len = vty_out(vty, "%s", buf);
6263 } else if (p->family == AF_EVPN) {
d62a17ae 6264#if defined(HAVE_CUMULUS)
b682f6de 6265 if (!json)
6266 len = vty_out(vty, "%s",
6267 bgp_evpn_route2str((struct prefix_evpn *)p,
6268 buf, BUFSIZ));
6269 else
6270 bgp_evpn_route2json((struct prefix_evpn *) p, json);
520d5d76 6271#else
d62a17ae 6272 prefix2str(p, buf, PREFIX_STRLEN);
6273 len = vty_out(vty, "%s", buf);
520d5d76 6274#endif
9c92b5f7 6275 } else {
c6462ff4
MK
6276 if (!json)
6277 len = vty_out(vty, "%s/%d",
6278 inet_ntop(p->family, &p->u.prefix, buf,
6279 BUFSIZ),
6280 p->prefixlen);
9c92b5f7 6281 }
d62a17ae 6282
9c92b5f7
MK
6283 if (!json) {
6284 len = 17 - len;
6285 if (len < 1)
6286 vty_out(vty, "\n%*s", 20, " ");
6287 else
6288 vty_out(vty, "%*s", len, " ");
6289 }
718e3744 6290}
6291
d62a17ae 6292enum bgp_display_type {
6293 normal_list,
718e3744 6294};
6295
b40d939b 6296/* Print the short form route status for a bgp_info */
d62a17ae 6297static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo,
6298 json_object *json_path)
718e3744 6299{
d62a17ae 6300 if (json_path) {
b05a1c8b 6301
d62a17ae 6302 /* Route status display. */
6303 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6304 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6305
d62a17ae 6306 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6307 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6308
d62a17ae 6309 if (binfo->extra && binfo->extra->suppress)
6310 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6311
d62a17ae 6312 if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6313 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6314 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6315
d62a17ae 6316 /* Selected */
6317 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6318 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6319
d62a17ae 6320 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6321 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6322
d62a17ae 6323 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6324 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6325
d62a17ae 6326 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6327 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6328
d62a17ae 6329 /* Internal route. */
6330 if ((binfo->peer->as)
6331 && (binfo->peer->as == binfo->peer->local_as))
6332 json_object_string_add(json_path, "pathFrom",
6333 "internal");
6334 else
6335 json_object_string_add(json_path, "pathFrom",
6336 "external");
b05a1c8b 6337
d62a17ae 6338 return;
6339 }
b05a1c8b 6340
d62a17ae 6341 /* Route status display. */
6342 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6343 vty_out(vty, "R");
6344 else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6345 vty_out(vty, "S");
6346 else if (binfo->extra && binfo->extra->suppress)
6347 vty_out(vty, "s");
6348 else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6349 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6350 vty_out(vty, "*");
6351 else
6352 vty_out(vty, " ");
6353
6354 /* Selected */
6355 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6356 vty_out(vty, "h");
6357 else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6358 vty_out(vty, "d");
6359 else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6360 vty_out(vty, ">");
6361 else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6362 vty_out(vty, "=");
6363 else
6364 vty_out(vty, " ");
718e3744 6365
d62a17ae 6366 /* Internal route. */
6367 if (binfo->peer && (binfo->peer->as)
6368 && (binfo->peer->as == binfo->peer->local_as))
6369 vty_out(vty, "i");
6370 else
6371 vty_out(vty, " ");
b40d939b 6372}
6373
6374/* called from terminal list command */
d62a17ae 6375void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6376 int display, safi_t safi, json_object *json_paths)
6377{
6378 struct attr *attr;
6379 json_object *json_path = NULL;
6380 json_object *json_nexthops = NULL;
6381 json_object *json_nexthop_global = NULL;
6382 json_object *json_nexthop_ll = NULL;
6383
6384 if (json_paths)
6385 json_path = json_object_new_object();
6386
6387 /* short status lead text */
6388 route_vty_short_status_out(vty, binfo, json_path);
6389
6390 if (!json_paths) {
6391 /* print prefix and mask */
6392 if (!display)
9c92b5f7 6393 route_vty_out_route(p, vty, json_path);
d62a17ae 6394 else
6395 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6396 } else {
b682f6de 6397 route_vty_out_route(p, vty, json_path);
d62a17ae 6398 }
47fc97cc 6399
d62a17ae 6400 /* Print attribute */
6401 attr = binfo->attr;
6402 if (attr) {
6403 /*
6404 * For ENCAP and EVPN routes, nexthop address family is not
6405 * neccessarily the same as the prefix address family.
6406 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6407 * EVPN routes are also exchanged with a MP nexthop. Currently,
6408 * this
6409 * is only IPv4, the value will be present in either
6410 * attr->nexthop or
6411 * attr->mp_nexthop_global_in
6412 */
6413 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6414 char buf[BUFSIZ];
6415 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6416
6417 switch (af) {
6418 case AF_INET:
6419 vty_out(vty, "%s",
6420 inet_ntop(af,
6421 &attr->mp_nexthop_global_in,
6422 buf, BUFSIZ));
6423 break;
6424 case AF_INET6:
6425 vty_out(vty, "%s",
6426 inet_ntop(af, &attr->mp_nexthop_global,
6427 buf, BUFSIZ));
6428 break;
6429 default:
6430 vty_out(vty, "?");
6431 break;
6432 }
6433 } else if (safi == SAFI_EVPN) {
6434 if (json_paths) {
6435 json_nexthop_global = json_object_new_object();
6436
6437 json_object_string_add(
6438 json_nexthop_global, "ip",
6439 inet_ntoa(attr->nexthop));
6440 json_object_string_add(json_nexthop_global,
6441 "afi", "ipv4");
6442 json_object_boolean_true_add(
6443 json_nexthop_global, "used");
6444 } else
6445 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6446 }
6447 /* IPv4 Next Hop */
6448 else if (p->family == AF_INET
6449 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6450 if (json_paths) {
6451 json_nexthop_global = json_object_new_object();
6452
6453 if ((safi == SAFI_MPLS_VPN)
6454 || (safi == SAFI_EVPN))
6455 json_object_string_add(
6456 json_nexthop_global, "ip",
6457 inet_ntoa(
6458 attr->mp_nexthop_global_in));
6459 else
6460 json_object_string_add(
6461 json_nexthop_global, "ip",
6462 inet_ntoa(attr->nexthop));
6463
6464 json_object_string_add(json_nexthop_global,
6465 "afi", "ipv4");
6466 json_object_boolean_true_add(
6467 json_nexthop_global, "used");
6468 } else {
6469 if ((safi == SAFI_MPLS_VPN)
6470 || (safi == SAFI_EVPN))
6471 vty_out(vty, "%-16s",
6472 inet_ntoa(
6473 attr->mp_nexthop_global_in));
6474 else
6475 vty_out(vty, "%-16s",
6476 inet_ntoa(attr->nexthop));
6477 }
6478 }
b05a1c8b 6479
d62a17ae 6480 /* IPv6 Next Hop */
6481 else if (p->family == AF_INET6
6482 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6483 int len;
6484 char buf[BUFSIZ];
6485
6486 if (json_paths) {
6487 json_nexthop_global = json_object_new_object();
6488 json_object_string_add(
6489 json_nexthop_global, "ip",
6490 inet_ntop(AF_INET6,
6491 &attr->mp_nexthop_global, buf,
6492 BUFSIZ));
6493 json_object_string_add(json_nexthop_global,
6494 "afi", "ipv6");
6495 json_object_string_add(json_nexthop_global,
6496 "scope", "global");
6497
6498 /* We display both LL & GL if both have been
6499 * received */
6500 if ((attr->mp_nexthop_len == 32)
6501 || (binfo->peer->conf_if)) {
6502 json_nexthop_ll =
6503 json_object_new_object();
6504 json_object_string_add(
6505 json_nexthop_ll, "ip",
6506 inet_ntop(
6507 AF_INET6,
6508 &attr->mp_nexthop_local,
6509 buf, BUFSIZ));
6510 json_object_string_add(json_nexthop_ll,
6511 "afi", "ipv6");
6512 json_object_string_add(json_nexthop_ll,
6513 "scope",
6514 "link-local");
6515
6516 if ((IPV6_ADDR_CMP(
6517 &attr->mp_nexthop_global,
6518 &attr->mp_nexthop_local)
6519 != 0)
6520 && !attr->mp_nexthop_prefer_global)
6521 json_object_boolean_true_add(
6522 json_nexthop_ll,
6523 "used");
6524 else
6525 json_object_boolean_true_add(
6526 json_nexthop_global,
6527 "used");
6528 } else
6529 json_object_boolean_true_add(
6530 json_nexthop_global, "used");
6531 } else {
6532 /* Display LL if LL/Global both in table unless
6533 * prefer-global is set */
6534 if (((attr->mp_nexthop_len == 32)
6535 && !attr->mp_nexthop_prefer_global)
6536 || (binfo->peer->conf_if)) {
6537 if (binfo->peer->conf_if) {
6538 len = vty_out(
6539 vty, "%s",
6540 binfo->peer->conf_if);
4192df64
DS
6541 len = 16 - len; /* len of IPv6
6542 addr + max
6543 len of def
6544 ifname */
d62a17ae 6545
6546 if (len < 1)
6547 vty_out(vty, "\n%*s",
4192df64 6548 36, " ");
d62a17ae 6549 else
6550 vty_out(vty, "%*s", len,
6551 " ");
6552 } else {
6553 len = vty_out(
6554 vty, "%s",
6555 inet_ntop(
6556 AF_INET6,
6557 &attr->mp_nexthop_local,
6558 buf, BUFSIZ));
6559 len = 16 - len;
6560
6561 if (len < 1)
6562 vty_out(vty, "\n%*s",
6563 36, " ");
6564 else
6565 vty_out(vty, "%*s", len,
6566 " ");
6567 }
6568 } else {
6569 len = vty_out(
6570 vty, "%s",
6571 inet_ntop(
6572 AF_INET6,
6573 &attr->mp_nexthop_global,
6574 buf, BUFSIZ));
6575 len = 16 - len;
6576
6577 if (len < 1)
6578 vty_out(vty, "\n%*s", 36, " ");
6579 else
6580 vty_out(vty, "%*s", len, " ");
6581 }
6582 }
6583 }
718e3744 6584
d62a17ae 6585 /* MED/Metric */
6586 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6587 if (json_paths)
6588 json_object_int_add(json_path, "med",
6589 attr->med);
6590 else
6591 vty_out(vty, "%10u", attr->med);
6592 else if (!json_paths)
6593 vty_out(vty, " ");
6594
6595 /* Local Pref */
6596 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6597 if (json_paths)
6598 json_object_int_add(json_path, "localpref",
6599 attr->local_pref);
6600 else
6601 vty_out(vty, "%7u", attr->local_pref);
6602 else if (!json_paths)
6603 vty_out(vty, " ");
6604
6605 if (json_paths)
6606 json_object_int_add(json_path, "weight", attr->weight);
6607 else
6608 vty_out(vty, "%7u ", attr->weight);
6609
6610 if (json_paths) {
6611 char buf[BUFSIZ];
6612 json_object_string_add(json_path, "peerId",
6613 sockunion2str(&binfo->peer->su,
6614 buf,
6615 SU_ADDRSTRLEN));
6616 }
47fc97cc 6617
d62a17ae 6618 /* Print aspath */
6619 if (attr->aspath) {
6620 if (json_paths)
6621 json_object_string_add(json_path, "aspath",
6622 attr->aspath->str);
6623 else
6624 aspath_print_vty(vty, "%s", attr->aspath, " ");
6625 }
b05a1c8b 6626
d62a17ae 6627 /* Print origin */
6628 if (json_paths)
6629 json_object_string_add(
6630 json_path, "origin",
6631 bgp_origin_long_str[attr->origin]);
6632 else
6633 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6634 } else {
6635 if (json_paths)
6636 json_object_string_add(json_path, "alert",
6637 "No attributes");
6638 else
6639 vty_out(vty, "No attributes to print\n");
6640 }
f1aa5d8a 6641
d62a17ae 6642 if (json_paths) {
6643 if (json_nexthop_global || json_nexthop_ll) {
6644 json_nexthops = json_object_new_array();
f1aa5d8a 6645
d62a17ae 6646 if (json_nexthop_global)
6647 json_object_array_add(json_nexthops,
6648 json_nexthop_global);
f1aa5d8a 6649
d62a17ae 6650 if (json_nexthop_ll)
6651 json_object_array_add(json_nexthops,
6652 json_nexthop_ll);
f1aa5d8a 6653
d62a17ae 6654 json_object_object_add(json_path, "nexthops",
6655 json_nexthops);
6656 }
6657
6658 json_object_array_add(json_paths, json_path);
6659 } else {
6660 vty_out(vty, "\n");
65efcfce 6661#if ENABLE_BGP_VNC
d62a17ae 6662 /* prints an additional line, indented, with VNC info, if
6663 * present */
6664 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
6665 rfapi_vty_out_vncinfo(vty, p, binfo, safi);
65efcfce 6666#endif
d62a17ae 6667 }
6668}
718e3744 6669
6670/* called from terminal list command */
d62a17ae 6671void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
6672 safi_t safi, u_char use_json, json_object *json_ar)
6673{
6674 json_object *json_status = NULL;
6675 json_object *json_net = NULL;
6676 char buff[BUFSIZ];
6677 /* Route status display. */
6678 if (use_json) {
6679 json_status = json_object_new_object();
6680 json_net = json_object_new_object();
6681 } else {
6682 vty_out(vty, "*");
6683 vty_out(vty, ">");
6684 vty_out(vty, " ");
6685 }
718e3744 6686
d62a17ae 6687 /* print prefix and mask */
6688 if (use_json)
6689 json_object_string_add(
6690 json_net, "addrPrefix",
6691 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
6692 else
9c92b5f7 6693 route_vty_out_route(p, vty, NULL);
d62a17ae 6694
6695 /* Print attribute */
6696 if (attr) {
6697 if (use_json) {
6698 if (p->family == AF_INET
6699 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6700 || safi == SAFI_EVPN
6701 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6702 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6703 || safi == SAFI_EVPN)
6704 json_object_string_add(
6705 json_net, "nextHop",
6706 inet_ntoa(
6707 attr->mp_nexthop_global_in));
6708 else
6709 json_object_string_add(
6710 json_net, "nextHop",
6711 inet_ntoa(attr->nexthop));
6712 } else if (p->family == AF_INET6
6713 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6714 char buf[BUFSIZ];
6715
6716 json_object_string_add(
6717 json_net, "netHopGloabal",
6718 inet_ntop(AF_INET6,
6719 &attr->mp_nexthop_global, buf,
6720 BUFSIZ));
6721 }
6722
6723 if (attr->flag
6724 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6725 json_object_int_add(json_net, "metric",
6726 attr->med);
6727
6728 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6729 json_object_int_add(json_net, "localPref",
6730 attr->local_pref);
6731
6732 json_object_int_add(json_net, "weight", attr->weight);
6733
6734 /* Print aspath */
6735 if (attr->aspath)
6736 json_object_string_add(json_net, "asPath",
6737 attr->aspath->str);
6738
6739 /* Print origin */
6740 json_object_string_add(json_net, "bgpOriginCode",
6741 bgp_origin_str[attr->origin]);
6742 } else {
6743 if (p->family == AF_INET
6744 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6745 || safi == SAFI_EVPN
6746 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6747 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6748 || safi == SAFI_EVPN)
6749 vty_out(vty, "%-16s",
6750 inet_ntoa(
6751 attr->mp_nexthop_global_in));
6752 else
6753 vty_out(vty, "%-16s",
6754 inet_ntoa(attr->nexthop));
6755 } else if (p->family == AF_INET6
6756 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6757 int len;
6758 char buf[BUFSIZ];
6759
6760 len = vty_out(
6761 vty, "%s",
6762 inet_ntop(AF_INET6,
6763 &attr->mp_nexthop_global, buf,
6764 BUFSIZ));
6765 len = 16 - len;
6766 if (len < 1)
6767 vty_out(vty, "\n%*s", 36, " ");
6768 else
6769 vty_out(vty, "%*s", len, " ");
6770 }
6771 if (attr->flag
6772 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6773 vty_out(vty, "%10u", attr->med);
6774 else
6775 vty_out(vty, " ");
718e3744 6776
d62a17ae 6777 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6778 vty_out(vty, "%7u", attr->local_pref);
6779 else
6780 vty_out(vty, " ");
6781
6782 vty_out(vty, "%7u ", attr->weight);
6783
6784 /* Print aspath */
6785 if (attr->aspath)
6786 aspath_print_vty(vty, "%s", attr->aspath, " ");
6787
6788 /* Print origin */
6789 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6790 }
6791 }
6792 if (use_json) {
6793 json_object_boolean_true_add(json_status, "*");
6794 json_object_boolean_true_add(json_status, ">");
6795 json_object_object_add(json_net, "appliedStatusSymbols",
6796 json_status);
6797 char buf_cut[BUFSIZ];
6798 json_object_object_add(
6799 json_ar,
6800 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
6801 json_net);
6802 } else
6803 vty_out(vty, "\n");
6804}
6805
6806void route_vty_out_tag(struct vty *vty, struct prefix *p,
6807 struct bgp_info *binfo, int display, safi_t safi,
6808 json_object *json)
6809{
6810 json_object *json_out = NULL;
6811 struct attr *attr;
6812 mpls_label_t label = MPLS_INVALID_LABEL;
6813
6814 if (!binfo->extra)
6815 return;
6816
6817 if (json)
6818 json_out = json_object_new_object();
6819
6820 /* short status lead text */
6821 route_vty_short_status_out(vty, binfo, json_out);
6822
6823 /* print prefix and mask */
6824 if (json == NULL) {
6825 if (!display)
9c92b5f7 6826 route_vty_out_route(p, vty, NULL);
d62a17ae 6827 else
6828 vty_out(vty, "%*s", 17, " ");
6829 }
6830
6831 /* Print attribute */
6832 attr = binfo->attr;
6833 if (attr) {
6834 if (((p->family == AF_INET)
6835 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6836 || (safi == SAFI_EVPN
d62a17ae 6837 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6838 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6839 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6840 || safi == SAFI_EVPN) {
6841 if (json)
6842 json_object_string_add(
6843 json_out, "mpNexthopGlobalIn",
6844 inet_ntoa(
6845 attr->mp_nexthop_global_in));
6846 else
6847 vty_out(vty, "%-16s",
6848 inet_ntoa(
6849 attr->mp_nexthop_global_in));
6850 } else {
6851 if (json)
6852 json_object_string_add(
6853 json_out, "nexthop",
6854 inet_ntoa(attr->nexthop));
6855 else
6856 vty_out(vty, "%-16s",
6857 inet_ntoa(attr->nexthop));
6858 }
6859 } else if (((p->family == AF_INET6)
6860 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6861 || (safi == SAFI_EVPN
d62a17ae 6862 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6863 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6864 char buf_a[BUFSIZ];
6865 char buf_b[BUFSIZ];
6866 char buf_c[BUFSIZ];
6867 if (attr->mp_nexthop_len
6868 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
6869 if (json)
6870 json_object_string_add(
6871 json_out, "mpNexthopGlobalIn",
6872 inet_ntop(
6873 AF_INET6,
6874 &attr->mp_nexthop_global,
6875 buf_a, BUFSIZ));
6876 else
6877 vty_out(vty, "%s",
6878 inet_ntop(
6879 AF_INET6,
6880 &attr->mp_nexthop_global,
6881 buf_a, BUFSIZ));
6882 } else if (attr->mp_nexthop_len
6883 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
6884 if (json) {
6885 inet_ntop(AF_INET6,
6886 &attr->mp_nexthop_global,
6887 buf_a, BUFSIZ);
6888 inet_ntop(AF_INET6,
6889 &attr->mp_nexthop_local,
6890 buf_b, BUFSIZ);
6891 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
6892 json_object_string_add(
6893 json_out,
6894 "mpNexthopGlobalLocal", buf_c);
6895 } else
6896 vty_out(vty, "%s(%s)",
6897 inet_ntop(
6898 AF_INET6,
6899 &attr->mp_nexthop_global,
6900 buf_a, BUFSIZ),
6901 inet_ntop(
6902 AF_INET6,
6903 &attr->mp_nexthop_local,
6904 buf_b, BUFSIZ));
6905 }
6906 }
6907 }
6908
6909 label = decode_label(&binfo->extra->label);
6910
6911 if (bgp_is_valid_label(&label)) {
6912 if (json) {
6913 json_object_int_add(json_out, "notag", label);
6914 json_object_array_add(json, json_out);
6915 } else {
6916 vty_out(vty, "notag/%d", label);
6917 vty_out(vty, "\n");
6918 }
6919 }
6920}
718e3744 6921
d62a17ae 6922void route_vty_out_overlay(struct vty *vty, struct prefix *p,
6923 struct bgp_info *binfo, int display,
6924 json_object *json_paths)
718e3744 6925{
d62a17ae 6926 struct attr *attr;
6927 char buf[BUFSIZ];
6928 json_object *json_path = NULL;
784d3a42 6929
d62a17ae 6930 if (json_paths)
6931 json_path = json_object_new_object();
856ca177 6932
d62a17ae 6933 if (!binfo->extra)
6934 return;
718e3744 6935
d62a17ae 6936 /* short status lead text */
6937 route_vty_short_status_out(vty, binfo, json_path);
856ca177 6938
d62a17ae 6939 /* print prefix and mask */
6940 if (!display)
9c92b5f7 6941 route_vty_out_route(p, vty, NULL);
d62a17ae 6942 else
6943 vty_out(vty, "%*s", 17, " ");
6944
6945 /* Print attribute */
6946 attr = binfo->attr;
6947 if (attr) {
6948 char buf1[BUFSIZ];
6949 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6950
6951 switch (af) {
6952 case AF_INET:
6953 vty_out(vty, "%-16s",
6954 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
6955 BUFSIZ));
6956 break;
6957 case AF_INET6:
6958 vty_out(vty, "%s(%s)",
6959 inet_ntop(af, &attr->mp_nexthop_global, buf,
6960 BUFSIZ),
6961 inet_ntop(af, &attr->mp_nexthop_local, buf1,
6962 BUFSIZ));
6963 break;
6964 default:
6965 vty_out(vty, "?");
6966 }
718e3744 6967 }
718e3744 6968
d62a17ae 6969 struct eth_segment_id *id = &(attr->evpn_overlay.eth_s_id);
6970 char *str = esi2str(id);
6971 vty_out(vty, "%s", str);
6972 XFREE(MTYPE_TMP, str);
6973 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) {
6974 vty_out(vty, "/%s", inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
6975 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) {
6976 vty_out(vty, "/%s",
6977 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6),
6978 buf, BUFSIZ));
6979 }
6980 if (attr->ecommunity) {
6981 char *mac = NULL;
6982 struct ecommunity_val *routermac = ecommunity_lookup(
6983 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
6984 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
6985 if (routermac)
6986 mac = ecom_mac2str((char *)routermac->val);
6987 if (mac) {
6988 vty_out(vty, "/%s", (char *)mac);
6989 XFREE(MTYPE_TMP, mac);
6990 }
6991 }
6992 vty_out(vty, "\n");
6993}
718e3744 6994
d62a17ae 6995/* dampening route */
6996static void damp_route_vty_out(struct vty *vty, struct prefix *p,
6997 struct bgp_info *binfo, int display, safi_t safi,
6998 u_char use_json, json_object *json)
6999{
7000 struct attr *attr;
7001 int len;
7002 char timebuf[BGP_UPTIME_LEN];
7003
7004 /* short status lead text */
7005 route_vty_short_status_out(vty, binfo, json);
7006
7007 /* print prefix and mask */
7008 if (!use_json) {
7009 if (!display)
9c92b5f7 7010 route_vty_out_route(p, vty, NULL);
d62a17ae 7011 else
7012 vty_out(vty, "%*s", 17, " ");
7013 }
7014
7015 len = vty_out(vty, "%s", binfo->peer->host);
7016 len = 17 - len;
7017 if (len < 1) {
7018 if (!use_json)
7019 vty_out(vty, "\n%*s", 34, " ");
7020 } else {
7021 if (use_json)
7022 json_object_int_add(json, "peerHost", len);
7023 else
7024 vty_out(vty, "%*s", len, " ");
7025 }
7026
7027 if (use_json)
7028 bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN,
7029 use_json, json);
7030 else
9d303b37
DL
7031 vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7032 BGP_UPTIME_LEN,
7033 use_json, json));
d62a17ae 7034
7035 /* Print attribute */
7036 attr = binfo->attr;
7037 if (attr) {
7038 /* Print aspath */
7039 if (attr->aspath) {
7040 if (use_json)
7041 json_object_string_add(json, "asPath",
7042 attr->aspath->str);
7043 else
7044 aspath_print_vty(vty, "%s", attr->aspath, " ");
7045 }
7046
7047 /* Print origin */
7048 if (use_json)
7049 json_object_string_add(json, "origin",
7050 bgp_origin_str[attr->origin]);
7051 else
7052 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7053 }
7054 if (!use_json)
7055 vty_out(vty, "\n");
7056}
718e3744 7057
d62a17ae 7058/* flap route */
7059static void flap_route_vty_out(struct vty *vty, struct prefix *p,
7060 struct bgp_info *binfo, int display, safi_t safi,
7061 u_char use_json, json_object *json)
784d3a42 7062{
d62a17ae 7063 struct attr *attr;
7064 struct bgp_damp_info *bdi;
7065 char timebuf[BGP_UPTIME_LEN];
7066 int len;
784d3a42 7067
d62a17ae 7068 if (!binfo->extra)
7069 return;
784d3a42 7070
d62a17ae 7071 bdi = binfo->extra->damp_info;
784d3a42 7072
d62a17ae 7073 /* short status lead text */
7074 route_vty_short_status_out(vty, binfo, json);
784d3a42 7075
d62a17ae 7076 /* print prefix and mask */
7077 if (!use_json) {
7078 if (!display)
9c92b5f7 7079 route_vty_out_route(p, vty, NULL);
d62a17ae 7080 else
7081 vty_out(vty, "%*s", 17, " ");
7082 }
784d3a42 7083
d62a17ae 7084 len = vty_out(vty, "%s", binfo->peer->host);
7085 len = 16 - len;
7086 if (len < 1) {
7087 if (!use_json)
7088 vty_out(vty, "\n%*s", 33, " ");
7089 } else {
7090 if (use_json)
7091 json_object_int_add(json, "peerHost", len);
7092 else
7093 vty_out(vty, "%*s", len, " ");
7094 }
784d3a42 7095
d62a17ae 7096 len = vty_out(vty, "%d", bdi->flap);
7097 len = 5 - len;
7098 if (len < 1) {
7099 if (!use_json)
7100 vty_out(vty, " ");
7101 } else {
7102 if (use_json)
7103 json_object_int_add(json, "bdiFlap", len);
7104 else
7105 vty_out(vty, "%*s", len, " ");
7106 }
7107
7108 if (use_json)
7109 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7110 json);
7111 else
9d303b37
DL
7112 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7113 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7114
7115 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
7116 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7117 if (use_json)
7118 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7119 BGP_UPTIME_LEN, use_json, json);
7120 else
7121 vty_out(vty, "%s ",
7122 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7123 BGP_UPTIME_LEN,
7124 use_json, json));
7125 } else {
7126 if (!use_json)
7127 vty_out(vty, "%*s ", 8, " ");
7128 }
7129
7130 /* Print attribute */
7131 attr = binfo->attr;
7132 if (attr) {
7133 /* Print aspath */
7134 if (attr->aspath) {
7135 if (use_json)
7136 json_object_string_add(json, "asPath",
7137 attr->aspath->str);
7138 else
7139 aspath_print_vty(vty, "%s", attr->aspath, " ");
7140 }
7141
7142 /* Print origin */
7143 if (use_json)
7144 json_object_string_add(json, "origin",
7145 bgp_origin_str[attr->origin]);
7146 else
7147 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7148 }
7149 if (!use_json)
7150 vty_out(vty, "\n");
7151}
7152
7153static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7154 int *first, const char *header,
7155 json_object *json_adv_to)
7156{
7157 char buf1[INET6_ADDRSTRLEN];
7158 json_object *json_peer = NULL;
7159
7160 if (json_adv_to) {
7161 /* 'advertised-to' is a dictionary of peers we have advertised
7162 * this
7163 * prefix too. The key is the peer's IP or swpX, the value is
7164 * the
7165 * hostname if we know it and "" if not.
7166 */
7167 json_peer = json_object_new_object();
7168
7169 if (peer->hostname)
7170 json_object_string_add(json_peer, "hostname",
7171 peer->hostname);
7172
7173 if (peer->conf_if)
7174 json_object_object_add(json_adv_to, peer->conf_if,
7175 json_peer);
7176 else
7177 json_object_object_add(
7178 json_adv_to,
7179 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7180 json_peer);
7181 } else {
7182 if (*first) {
7183 vty_out(vty, "%s", header);
7184 *first = 0;
7185 }
7186
7187 if (peer->hostname
7188 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7189 if (peer->conf_if)
7190 vty_out(vty, " %s(%s)", peer->hostname,
7191 peer->conf_if);
7192 else
7193 vty_out(vty, " %s(%s)", peer->hostname,
7194 sockunion2str(&peer->su, buf1,
7195 SU_ADDRSTRLEN));
7196 } else {
7197 if (peer->conf_if)
7198 vty_out(vty, " %s", peer->conf_if);
7199 else
7200 vty_out(vty, " %s",
7201 sockunion2str(&peer->su, buf1,
7202 SU_ADDRSTRLEN));
7203 }
7204 }
784d3a42
PG
7205}
7206
d62a17ae 7207void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
7208 struct bgp_info *binfo, afi_t afi, safi_t safi,
7209 json_object *json_paths)
7210{
7211 char buf[INET6_ADDRSTRLEN];
7212 char buf1[BUFSIZ];
7213#if defined(HAVE_CUMULUS)
7214 char buf2[EVPN_ROUTE_STRLEN];
7215#endif
7216 struct attr *attr;
7217 int sockunion_vty_out(struct vty *, union sockunion *);
7218 time_t tbuf;
7219 json_object *json_bestpath = NULL;
7220 json_object *json_cluster_list = NULL;
7221 json_object *json_cluster_list_list = NULL;
7222 json_object *json_ext_community = NULL;
7223 json_object *json_last_update = NULL;
7224 json_object *json_nexthop_global = NULL;
7225 json_object *json_nexthop_ll = NULL;
7226 json_object *json_nexthops = NULL;
7227 json_object *json_path = NULL;
7228 json_object *json_peer = NULL;
7229 json_object *json_string = NULL;
7230 json_object *json_adv_to = NULL;
7231 int first = 0;
7232 struct listnode *node, *nnode;
7233 struct peer *peer;
7234 int addpath_capable;
7235 int has_adj;
7236 unsigned int first_as;
7237
7238 if (json_paths) {
7239 json_path = json_object_new_object();
7240 json_peer = json_object_new_object();
7241 json_nexthop_global = json_object_new_object();
7242 }
7243
7244#if defined(HAVE_CUMULUS)
7245 if (!json_paths && safi == SAFI_EVPN) {
7246 char tag_buf[20];
7247
7248 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7249 vty_out(vty, " Route %s", buf2);
7250 tag_buf[0] = '\0';
7251 if (binfo->extra) {
7252 bgp_evpn_label2str(&binfo->extra->label, tag_buf,
7253 sizeof(tag_buf));
7254 vty_out(vty, " VNI %s", tag_buf);
7255 }
7256 vty_out(vty, "\n");
7257 if (binfo->extra && binfo->extra->parent) {
7258 struct bgp_info *parent_ri;
7259 struct bgp_node *rn, *prn;
7260
7261 parent_ri = (struct bgp_info *)binfo->extra->parent;
7262 rn = parent_ri->net;
7263 if (rn && rn->prn) {
7264 prn = rn->prn;
7265 vty_out(vty, " Imported from %s:%s\n",
7266 prefix_rd2str(
7267 (struct prefix_rd *)&prn->p,
7268 buf1, RD_ADDRSTRLEN),
7269 buf2);
7270 }
7271 }
7272 }
7273#endif
7274
7275 attr = binfo->attr;
7276
7277 if (attr) {
7278 /* Line1 display AS-path, Aggregator */
7279 if (attr->aspath) {
7280 if (json_paths) {
7281 json_object_lock(attr->aspath->json);
7282 json_object_object_add(json_path, "aspath",
7283 attr->aspath->json);
7284 } else {
7285 if (attr->aspath->segments)
7286 aspath_print_vty(vty, " %s",
7287 attr->aspath, "");
7288 else
7289 vty_out(vty, " Local");
7290 }
7291 }
7292
7293 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) {
7294 if (json_paths)
7295 json_object_boolean_true_add(json_path,
7296 "removed");
7297 else
7298 vty_out(vty, ", (removed)");
7299 }
7300
7301 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) {
7302 if (json_paths)
7303 json_object_boolean_true_add(json_path,
7304 "stale");
7305 else
7306 vty_out(vty, ", (stale)");
7307 }
7308
7309 if (CHECK_FLAG(attr->flag,
7310 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7311 if (json_paths) {
7312 json_object_int_add(json_path, "aggregatorAs",
7313 attr->aggregator_as);
7314 json_object_string_add(
7315 json_path, "aggregatorId",
7316 inet_ntoa(attr->aggregator_addr));
7317 } else {
7318 vty_out(vty, ", (aggregated by %u %s)",
7319 attr->aggregator_as,
7320 inet_ntoa(attr->aggregator_addr));
7321 }
7322 }
7323
7324 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7325 PEER_FLAG_REFLECTOR_CLIENT)) {
7326 if (json_paths)
7327 json_object_boolean_true_add(
7328 json_path, "rxedFromRrClient");
7329 else
7330 vty_out(vty, ", (Received from a RR-client)");
7331 }
7332
7333 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7334 PEER_FLAG_RSERVER_CLIENT)) {
7335 if (json_paths)
7336 json_object_boolean_true_add(
7337 json_path, "rxedFromRsClient");
7338 else
7339 vty_out(vty, ", (Received from a RS-client)");
7340 }
7341
7342 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7343 if (json_paths)
7344 json_object_boolean_true_add(
7345 json_path, "dampeningHistoryEntry");
7346 else
7347 vty_out(vty, ", (history entry)");
7348 } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
7349 if (json_paths)
7350 json_object_boolean_true_add(
7351 json_path, "dampeningSuppressed");
7352 else
7353 vty_out(vty, ", (suppressed due to dampening)");
7354 }
7355
7356 if (!json_paths)
7357 vty_out(vty, "\n");
7358
7359 /* Line2 display Next-hop, Neighbor, Router-id */
7360 /* Display the nexthop */
b03b8898
DS
7361 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
7362 p->family == AF_EVPN)
d62a17ae 7363 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7364 || safi == SAFI_EVPN
7365 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7366 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7367 || safi == SAFI_EVPN) {
7368 if (json_paths)
7369 json_object_string_add(
7370 json_nexthop_global, "ip",
7371 inet_ntoa(
7372 attr->mp_nexthop_global_in));
7373 else
7374 vty_out(vty, " %s",
7375 inet_ntoa(
7376 attr->mp_nexthop_global_in));
7377 } else {
7378 if (json_paths)
7379 json_object_string_add(
7380 json_nexthop_global, "ip",
7381 inet_ntoa(attr->nexthop));
7382 else
7383 vty_out(vty, " %s",
7384 inet_ntoa(attr->nexthop));
7385 }
7386
7387 if (json_paths)
7388 json_object_string_add(json_nexthop_global,
7389 "afi", "ipv4");
7390 } else {
7391 if (json_paths) {
7392 json_object_string_add(
7393 json_nexthop_global, "ip",
7394 inet_ntop(AF_INET6,
7395 &attr->mp_nexthop_global, buf,
7396 INET6_ADDRSTRLEN));
7397 json_object_string_add(json_nexthop_global,
7398 "afi", "ipv6");
7399 json_object_string_add(json_nexthop_global,
7400 "scope", "global");
7401 } else {
7402 vty_out(vty, " %s",
7403 inet_ntop(AF_INET6,
7404 &attr->mp_nexthop_global, buf,
7405 INET6_ADDRSTRLEN));
7406 }
7407 }
7408
7409 /* Display the IGP cost or 'inaccessible' */
7410 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7411 if (json_paths)
7412 json_object_boolean_false_add(
7413 json_nexthop_global, "accessible");
7414 else
7415 vty_out(vty, " (inaccessible)");
7416 } else {
7417 if (binfo->extra && binfo->extra->igpmetric) {
7418 if (json_paths)
7419 json_object_int_add(
7420 json_nexthop_global, "metric",
7421 binfo->extra->igpmetric);
7422 else
7423 vty_out(vty, " (metric %u)",
7424 binfo->extra->igpmetric);
7425 }
7426
7427 /* IGP cost is 0, display this only for json */
7428 else {
7429 if (json_paths)
7430 json_object_int_add(json_nexthop_global,
7431 "metric", 0);
7432 }
7433
7434 if (json_paths)
7435 json_object_boolean_true_add(
7436 json_nexthop_global, "accessible");
7437 }
7438
7439 /* Display peer "from" output */
7440 /* This path was originated locally */
7441 if (binfo->peer == bgp->peer_self) {
7442
7443 if (safi == SAFI_EVPN
7444 || (p->family == AF_INET
7445 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7446 if (json_paths)
7447 json_object_string_add(
7448 json_peer, "peerId", "0.0.0.0");
7449 else
7450 vty_out(vty, " from 0.0.0.0 ");
7451 } else {
7452 if (json_paths)
7453 json_object_string_add(json_peer,
7454 "peerId", "::");
7455 else
7456 vty_out(vty, " from :: ");
7457 }
7458
7459 if (json_paths)
7460 json_object_string_add(
7461 json_peer, "routerId",
7462 inet_ntoa(bgp->router_id));
7463 else
7464 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7465 }
7466
7467 /* We RXed this path from one of our peers */
7468 else {
7469
7470 if (json_paths) {
7471 json_object_string_add(
7472 json_peer, "peerId",
7473 sockunion2str(&binfo->peer->su, buf,
7474 SU_ADDRSTRLEN));
7475 json_object_string_add(
7476 json_peer, "routerId",
7477 inet_ntop(AF_INET,
7478 &binfo->peer->remote_id, buf1,
7479 BUFSIZ));
7480
7481 if (binfo->peer->hostname)
7482 json_object_string_add(
7483 json_peer, "hostname",
7484 binfo->peer->hostname);
7485
7486 if (binfo->peer->domainname)
7487 json_object_string_add(
7488 json_peer, "domainname",
7489 binfo->peer->domainname);
7490
7491 if (binfo->peer->conf_if)
7492 json_object_string_add(
7493 json_peer, "interface",
7494 binfo->peer->conf_if);
7495 } else {
7496 if (binfo->peer->conf_if) {
7497 if (binfo->peer->hostname
7498 && bgp_flag_check(
7499 binfo->peer->bgp,
7500 BGP_FLAG_SHOW_HOSTNAME))
7501 vty_out(vty, " from %s(%s)",
7502 binfo->peer->hostname,
7503 binfo->peer->conf_if);
7504 else
7505 vty_out(vty, " from %s",
7506 binfo->peer->conf_if);
7507 } else {
7508 if (binfo->peer->hostname
7509 && bgp_flag_check(
7510 binfo->peer->bgp,
7511 BGP_FLAG_SHOW_HOSTNAME))
7512 vty_out(vty, " from %s(%s)",
7513 binfo->peer->hostname,
7514 binfo->peer->host);
7515 else
7516 vty_out(vty, " from %s",
7517 sockunion2str(
7518 &binfo->peer
7519 ->su,
7520 buf,
7521 SU_ADDRSTRLEN));
7522 }
7523
7524 if (attr->flag
7525 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7526 vty_out(vty, " (%s)",
7527 inet_ntoa(attr->originator_id));
7528 else
7529 vty_out(vty, " (%s)",
7530 inet_ntop(
7531 AF_INET,
7532 &binfo->peer->remote_id,
7533 buf1, BUFSIZ));
7534 }
7535 }
7536
7537 if (!json_paths)
7538 vty_out(vty, "\n");
7539
7540 /* display the link-local nexthop */
7541 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7542 if (json_paths) {
7543 json_nexthop_ll = json_object_new_object();
7544 json_object_string_add(
7545 json_nexthop_ll, "ip",
7546 inet_ntop(AF_INET6,
7547 &attr->mp_nexthop_local, buf,
7548 INET6_ADDRSTRLEN));
7549 json_object_string_add(json_nexthop_ll, "afi",
7550 "ipv6");
7551 json_object_string_add(json_nexthop_ll, "scope",
7552 "link-local");
7553
7554 json_object_boolean_true_add(json_nexthop_ll,
7555 "accessible");
7556
7557 if (!attr->mp_nexthop_prefer_global)
7558 json_object_boolean_true_add(
7559 json_nexthop_ll, "used");
7560 else
7561 json_object_boolean_true_add(
7562 json_nexthop_global, "used");
7563 } else {
7564 vty_out(vty, " (%s) %s\n",
7565 inet_ntop(AF_INET6,
7566 &attr->mp_nexthop_local, buf,
7567 INET6_ADDRSTRLEN),
7568 attr->mp_nexthop_prefer_global
7569 ? "(prefer-global)"
7570 : "(used)");
7571 }
7572 }
7573 /* If we do not have a link-local nexthop then we must flag the
7574 global as "used" */
7575 else {
7576 if (json_paths)
7577 json_object_boolean_true_add(
7578 json_nexthop_global, "used");
7579 }
718e3744 7580
d62a17ae 7581 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7582 * Int/Ext/Local, Atomic, best */
7583 if (json_paths)
7584 json_object_string_add(
7585 json_path, "origin",
7586 bgp_origin_long_str[attr->origin]);
7587 else
7588 vty_out(vty, " Origin %s",
7589 bgp_origin_long_str[attr->origin]);
7590
7591 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
7592 if (json_paths)
7593 json_object_int_add(json_path, "med",
7594 attr->med);
7595 else
7596 vty_out(vty, ", metric %u", attr->med);
7597 }
718e3744 7598
d62a17ae 7599 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7600 if (json_paths)
7601 json_object_int_add(json_path, "localpref",
7602 attr->local_pref);
7603 else
7604 vty_out(vty, ", localpref %u",
7605 attr->local_pref);
7606 } else {
7607 if (json_paths)
7608 json_object_int_add(json_path, "localpref",
7609 bgp->default_local_pref);
7610 else
7611 vty_out(vty, ", localpref %u",
7612 bgp->default_local_pref);
7613 }
718e3744 7614
d62a17ae 7615 if (attr->weight != 0) {
7616 if (json_paths)
7617 json_object_int_add(json_path, "weight",
7618 attr->weight);
7619 else
7620 vty_out(vty, ", weight %u", attr->weight);
7621 }
718e3744 7622
d62a17ae 7623 if (attr->tag != 0) {
7624 if (json_paths)
7625 json_object_int_add(json_path, "tag",
7626 attr->tag);
7627 else
7628 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7629 attr->tag);
7630 }
718e3744 7631
d62a17ae 7632 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7633 if (json_paths)
7634 json_object_boolean_false_add(json_path,
7635 "valid");
7636 else
7637 vty_out(vty, ", invalid");
7638 } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7639 if (json_paths)
7640 json_object_boolean_true_add(json_path,
7641 "valid");
7642 else
7643 vty_out(vty, ", valid");
7644 }
718e3744 7645
d62a17ae 7646 if (binfo->peer != bgp->peer_self) {
7647 if (binfo->peer->as == binfo->peer->local_as) {
7648 if (CHECK_FLAG(bgp->config,
7649 BGP_CONFIG_CONFEDERATION)) {
7650 if (json_paths)
7651 json_object_string_add(
7652 json_peer, "type",
7653 "confed-internal");
7654 else
7655 vty_out(vty,
7656 ", confed-internal");
7657 } else {
7658 if (json_paths)
7659 json_object_string_add(
7660 json_peer, "type",
7661 "internal");
7662 else
7663 vty_out(vty, ", internal");
7664 }
7665 } else {
7666 if (bgp_confederation_peers_check(
7667 bgp, binfo->peer->as)) {
7668 if (json_paths)
7669 json_object_string_add(
7670 json_peer, "type",
7671 "confed-external");
7672 else
7673 vty_out(vty,
7674 ", confed-external");
7675 } else {
7676 if (json_paths)
7677 json_object_string_add(
7678 json_peer, "type",
7679 "external");
7680 else
7681 vty_out(vty, ", external");
7682 }
7683 }
7684 } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) {
7685 if (json_paths) {
7686 json_object_boolean_true_add(json_path,
7687 "aggregated");
7688 json_object_boolean_true_add(json_path,
7689 "local");
7690 } else {
7691 vty_out(vty, ", aggregated, local");
7692 }
7693 } else if (binfo->type != ZEBRA_ROUTE_BGP) {
7694 if (json_paths)
7695 json_object_boolean_true_add(json_path,
7696 "sourced");
7697 else
7698 vty_out(vty, ", sourced");
7699 } else {
7700 if (json_paths) {
7701 json_object_boolean_true_add(json_path,
7702 "sourced");
7703 json_object_boolean_true_add(json_path,
7704 "local");
7705 } else {
7706 vty_out(vty, ", sourced, local");
7707 }
7708 }
718e3744 7709
d62a17ae 7710 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
7711 if (json_paths)
7712 json_object_boolean_true_add(json_path,
7713 "atomicAggregate");
7714 else
7715 vty_out(vty, ", atomic-aggregate");
7716 }
718e3744 7717
d62a17ae 7718 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)
7719 || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)
7720 && bgp_info_mpath_count(binfo))) {
7721 if (json_paths)
7722 json_object_boolean_true_add(json_path,
7723 "multipath");
7724 else
7725 vty_out(vty, ", multipath");
7726 }
856ca177 7727
d62a17ae 7728 // Mark the bestpath(s)
7729 if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) {
7730 first_as = aspath_get_first_as(attr->aspath);
7731
7732 if (json_paths) {
7733 if (!json_bestpath)
7734 json_bestpath =
7735 json_object_new_object();
7736 json_object_int_add(json_bestpath,
7737 "bestpathFromAs", first_as);
7738 } else {
7739 if (first_as)
7740 vty_out(vty, ", bestpath-from-AS %d",
7741 first_as);
7742 else
7743 vty_out(vty,
7744 ", bestpath-from-AS Local");
7745 }
7746 }
718e3744 7747
d62a17ae 7748 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) {
7749 if (json_paths) {
7750 if (!json_bestpath)
7751 json_bestpath =
7752 json_object_new_object();
7753 json_object_boolean_true_add(json_bestpath,
7754 "overall");
7755 } else
7756 vty_out(vty, ", best");
7757 }
718e3744 7758
d62a17ae 7759 if (json_bestpath)
7760 json_object_object_add(json_path, "bestpath",
7761 json_bestpath);
7762
7763 if (!json_paths)
7764 vty_out(vty, "\n");
7765
7766 /* Line 4 display Community */
7767 if (attr->community) {
7768 if (json_paths) {
7769 json_object_lock(attr->community->json);
7770 json_object_object_add(json_path, "community",
7771 attr->community->json);
7772 } else {
7773 vty_out(vty, " Community: %s\n",
7774 attr->community->str);
7775 }
7776 }
718e3744 7777
d62a17ae 7778 /* Line 5 display Extended-community */
7779 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7780 if (json_paths) {
7781 json_ext_community = json_object_new_object();
7782 json_object_string_add(json_ext_community,
7783 "string",
7784 attr->ecommunity->str);
7785 json_object_object_add(json_path,
7786 "extendedCommunity",
7787 json_ext_community);
7788 } else {
7789 vty_out(vty, " Extended Community: %s\n",
7790 attr->ecommunity->str);
7791 }
7792 }
adbac85e 7793
d62a17ae 7794 /* Line 6 display Large community */
7795 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))
7796 vty_out(vty, " Large Community: %s\n",
7797 attr->lcommunity->str);
7798
7799 /* Line 7 display Originator, Cluster-id */
7800 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7801 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
7802 if (attr->flag
7803 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
7804 if (json_paths)
7805 json_object_string_add(
7806 json_path, "originatorId",
7807 inet_ntoa(attr->originator_id));
7808 else
7809 vty_out(vty, " Originator: %s",
7810 inet_ntoa(attr->originator_id));
7811 }
7812
7813 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
7814 int i;
7815
7816 if (json_paths) {
7817 json_cluster_list =
7818 json_object_new_object();
7819 json_cluster_list_list =
7820 json_object_new_array();
7821
7822 for (i = 0;
7823 i < attr->cluster->length / 4;
7824 i++) {
7825 json_string = json_object_new_string(
7826 inet_ntoa(
7827 attr->cluster->list
7828 [i]));
7829 json_object_array_add(
7830 json_cluster_list_list,
7831 json_string);
7832 }
7833
7834 /* struct cluster_list does not have
7835 "str" variable like
7836 * aspath and community do. Add this
7837 someday if someone
7838 * asks for it.
7839 json_object_string_add(json_cluster_list,
7840 "string", attr->cluster->str);
7841 */
7842 json_object_object_add(
7843 json_cluster_list, "list",
7844 json_cluster_list_list);
7845 json_object_object_add(
7846 json_path, "clusterList",
7847 json_cluster_list);
7848 } else {
7849 vty_out(vty, ", Cluster list: ");
7850
7851 for (i = 0;
7852 i < attr->cluster->length / 4;
7853 i++) {
7854 vty_out(vty, "%s ",
7855 inet_ntoa(
7856 attr->cluster->list
7857 [i]));
7858 }
7859 }
7860 }
7861
7862 if (!json_paths)
7863 vty_out(vty, "\n");
7864 }
adbac85e 7865
d62a17ae 7866 if (binfo->extra && binfo->extra->damp_info)
7867 bgp_damp_info_vty(vty, binfo, json_path);
7868
7869/* Remote Label */
8c197128 7870#if defined(HAVE_CUMULUS)
d62a17ae 7871 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label)
7872 && safi != SAFI_EVPN)
7873#else
7874 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label))
8c197128 7875#endif
d62a17ae 7876 {
7877 mpls_label_t label = label_pton(&binfo->extra->label);
7878 if (json_paths)
7879 json_object_int_add(json_path, "remoteLabel",
7880 label);
7881 else
7882 vty_out(vty, " Remote label: %d\n", label);
7883 }
b05a1c8b 7884
d62a17ae 7885 /* Label Index */
7886 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
7887 if (json_paths)
7888 json_object_int_add(json_path, "labelIndex",
7889 attr->label_index);
7890 else
7891 vty_out(vty, " Label Index: %d\n",
7892 attr->label_index);
7893 }
520d5d76 7894
d62a17ae 7895 /* Line 8 display Addpath IDs */
7896 if (binfo->addpath_rx_id || binfo->addpath_tx_id) {
7897 if (json_paths) {
7898 json_object_int_add(json_path, "addpathRxId",
7899 binfo->addpath_rx_id);
7900 json_object_int_add(json_path, "addpathTxId",
7901 binfo->addpath_tx_id);
7902 } else {
7903 vty_out(vty, " AddPath ID: RX %u, TX %u\n",
7904 binfo->addpath_rx_id,
7905 binfo->addpath_tx_id);
7906 }
7907 }
718e3744 7908
d62a17ae 7909 /* If we used addpath to TX a non-bestpath we need to display
7910 * "Advertised to" on a path-by-path basis */
7911 if (bgp->addpath_tx_used[afi][safi]) {
7912 first = 1;
7913
7914 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7915 addpath_capable =
7916 bgp_addpath_encode_tx(peer, afi, safi);
7917 has_adj = bgp_adj_out_lookup(
7918 peer, binfo->net, binfo->addpath_tx_id);
7919
7920 if ((addpath_capable && has_adj)
7921 || (!addpath_capable && has_adj
7922 && CHECK_FLAG(binfo->flags,
7923 BGP_INFO_SELECTED))) {
7924 if (json_path && !json_adv_to)
7925 json_adv_to =
7926 json_object_new_object();
7927
7928 route_vty_out_advertised_to(
7929 vty, peer, &first,
7930 " Advertised to:",
7931 json_adv_to);
7932 }
7933 }
7934
7935 if (json_path) {
7936 if (json_adv_to) {
7937 json_object_object_add(json_path,
7938 "advertisedTo",
7939 json_adv_to);
7940 }
7941 } else {
7942 if (!first) {
7943 vty_out(vty, "\n");
7944 }
7945 }
7946 }
b05a1c8b 7947
d62a17ae 7948 /* Line 9 display Uptime */
7949 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
7950 if (json_paths) {
7951 json_last_update = json_object_new_object();
7952 json_object_int_add(json_last_update, "epoch", tbuf);
7953 json_object_string_add(json_last_update, "string",
7954 ctime(&tbuf));
7955 json_object_object_add(json_path, "lastUpdate",
7956 json_last_update);
7957 } else
7958 vty_out(vty, " Last update: %s", ctime(&tbuf));
7959 }
f1aa5d8a 7960
d62a17ae 7961 /* We've constructed the json object for this path, add it to the json
7962 * array of paths
7963 */
7964 if (json_paths) {
7965 if (json_nexthop_global || json_nexthop_ll) {
7966 json_nexthops = json_object_new_array();
f1aa5d8a 7967
d62a17ae 7968 if (json_nexthop_global)
7969 json_object_array_add(json_nexthops,
7970 json_nexthop_global);
f1aa5d8a 7971
d62a17ae 7972 if (json_nexthop_ll)
7973 json_object_array_add(json_nexthops,
7974 json_nexthop_ll);
f1aa5d8a 7975
d62a17ae 7976 json_object_object_add(json_path, "nexthops",
7977 json_nexthops);
7978 }
7979
7980 json_object_object_add(json_path, "peer", json_peer);
7981 json_object_array_add(json_paths, json_path);
7982 } else
7983 vty_out(vty, "\n");
b366b518
BB
7984}
7985
96ade3ed 7986#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
7987#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
7988#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 7989
d62a17ae 7990static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
7991 const char *prefix_list_str, afi_t afi,
7992 safi_t safi, enum bgp_show_type type);
7993static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
7994 const char *filter, afi_t afi, safi_t safi,
7995 enum bgp_show_type type);
7996static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
7997 const char *rmap_str, afi_t afi, safi_t safi,
7998 enum bgp_show_type type);
7999static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8000 const char *com, int exact, afi_t afi,
8001 safi_t safi);
8002static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8003 const char *prefix, afi_t afi, safi_t safi,
8004 enum bgp_show_type type);
8005static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
8006 safi_t safi, enum bgp_show_type type);
8007static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
8008 struct cmd_token **argv, int exact, afi_t afi,
8009 safi_t safi);
8010
8011static int bgp_show_table(struct vty *vty, struct bgp *bgp,
8012 struct bgp_table *table, enum bgp_show_type type,
8013 void *output_arg, u_char use_json)
8014{
8015 struct bgp_info *ri;
8016 struct bgp_node *rn;
8017 int header = 1;
8018 int display;
8019 unsigned long output_count;
8020 unsigned long total_count;
8021 struct prefix *p;
8022 char buf[BUFSIZ];
8023 char buf2[BUFSIZ];
8024 json_object *json_paths = NULL;
8025 int first = 1;
8026
8027 if (use_json) {
8028 vty_out(vty,
8029 "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64
8030 ", \"routerId\": \"%s\", \"routes\": { ",
8031 bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id,
8032 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
8033 : bgp->name,
8034 table->version, inet_ntoa(bgp->router_id));
8035 json_paths = json_object_new_object();
8036 }
718e3744 8037
d62a17ae 8038 /* This is first entry point, so reset total line. */
8039 output_count = 0;
8040 total_count = 0;
8041
8042 /* Start processing of routes. */
8043 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
8044 if (rn->info != NULL) {
8045 display = 0;
8046 if (!first && use_json) {
8047 vty_out(vty, ",");
8048 }
8049 if (use_json)
8050 json_paths = json_object_new_array();
8051 else
8052 json_paths = NULL;
8053
8054 for (ri = rn->info; ri; ri = ri->next) {
8055 total_count++;
8056 if (type == bgp_show_type_flap_statistics
8057 || type == bgp_show_type_flap_neighbor
8058 || type == bgp_show_type_dampend_paths
8059 || type == bgp_show_type_damp_neighbor) {
8060 if (!(ri->extra
8061 && ri->extra->damp_info))
8062 continue;
8063 }
8064 if (type == bgp_show_type_regexp) {
8065 regex_t *regex = output_arg;
8066
8067 if (bgp_regexec(regex, ri->attr->aspath)
8068 == REG_NOMATCH)
8069 continue;
8070 }
8071 if (type == bgp_show_type_prefix_list) {
8072 struct prefix_list *plist = output_arg;
8073
8074 if (prefix_list_apply(plist, &rn->p)
8075 != PREFIX_PERMIT)
8076 continue;
8077 }
8078 if (type == bgp_show_type_filter_list) {
8079 struct as_list *as_list = output_arg;
8080
8081 if (as_list_apply(as_list,
8082 ri->attr->aspath)
8083 != AS_FILTER_PERMIT)
8084 continue;
8085 }
8086 if (type == bgp_show_type_route_map) {
8087 struct route_map *rmap = output_arg;
8088 struct bgp_info binfo;
8089 struct attr dummy_attr;
8090 int ret;
8091
8092 bgp_attr_dup(&dummy_attr, ri->attr);
8093
8094 binfo.peer = ri->peer;
8095 binfo.attr = &dummy_attr;
8096
8097 ret = route_map_apply(rmap, &rn->p,
8098 RMAP_BGP, &binfo);
8099 if (ret == RMAP_DENYMATCH)
8100 continue;
8101 }
8102 if (type == bgp_show_type_neighbor
8103 || type == bgp_show_type_flap_neighbor
8104 || type == bgp_show_type_damp_neighbor) {
8105 union sockunion *su = output_arg;
8106
8107 if (ri->peer == NULL
8108 || ri->peer->su_remote == NULL
8109 || !sockunion_same(
8110 ri->peer->su_remote, su))
8111 continue;
8112 }
8113 if (type == bgp_show_type_cidr_only) {
8114 u_int32_t destination;
8115
8116 destination =
8117 ntohl(rn->p.u.prefix4.s_addr);
8118 if (IN_CLASSC(destination)
8119 && rn->p.prefixlen == 24)
8120 continue;
8121 if (IN_CLASSB(destination)
8122 && rn->p.prefixlen == 16)
8123 continue;
8124 if (IN_CLASSA(destination)
8125 && rn->p.prefixlen == 8)
8126 continue;
8127 }
8128 if (type == bgp_show_type_prefix_longer) {
8129 struct prefix *p = output_arg;
8130
8131 if (!prefix_match(p, &rn->p))
8132 continue;
8133 }
8134 if (type == bgp_show_type_community_all) {
8135 if (!ri->attr->community)
8136 continue;
8137 }
8138 if (type == bgp_show_type_community) {
8139 struct community *com = output_arg;
8140
8141 if (!ri->attr->community
8142 || !community_match(
8143 ri->attr->community,
8144 com))
8145 continue;
8146 }
8147 if (type == bgp_show_type_community_exact) {
8148 struct community *com = output_arg;
8149
8150 if (!ri->attr->community
8151 || !community_cmp(
8152 ri->attr->community,
8153 com))
8154 continue;
8155 }
8156 if (type == bgp_show_type_community_list) {
8157 struct community_list *list =
8158 output_arg;
8159
8160 if (!community_list_match(
8161 ri->attr->community, list))
8162 continue;
8163 }
8164 if (type
8165 == bgp_show_type_community_list_exact) {
8166 struct community_list *list =
8167 output_arg;
8168
8169 if (!community_list_exact_match(
8170 ri->attr->community, list))
8171 continue;
8172 }
8173 if (type == bgp_show_type_lcommunity) {
8174 struct lcommunity *lcom = output_arg;
8175
8176 if (!ri->attr->lcommunity
8177 || !lcommunity_match(
8178 ri->attr->lcommunity,
8179 lcom))
8180 continue;
8181 }
8182 if (type == bgp_show_type_lcommunity_list) {
8183 struct community_list *list =
8184 output_arg;
8185
8186 if (!lcommunity_list_match(
8187 ri->attr->lcommunity, list))
8188 continue;
8189 }
8190 if (type == bgp_show_type_lcommunity_all) {
8191 if (!ri->attr->lcommunity)
8192 continue;
8193 }
8194 if (type == bgp_show_type_dampend_paths
8195 || type == bgp_show_type_damp_neighbor) {
8196 if (!CHECK_FLAG(ri->flags,
8197 BGP_INFO_DAMPED)
8198 || CHECK_FLAG(ri->flags,
8199 BGP_INFO_HISTORY))
8200 continue;
8201 }
8202
8203 if (!use_json && header) {
8204 vty_out(vty,
8205 "BGP table version is %" PRIu64
8206 ", local router ID is %s\n",
8207 table->version,
8208 inet_ntoa(bgp->router_id));
8209 vty_out(vty, BGP_SHOW_SCODE_HEADER);
8210 vty_out(vty, BGP_SHOW_OCODE_HEADER);
8211 if (type == bgp_show_type_dampend_paths
8212 || type == bgp_show_type_damp_neighbor)
8213 vty_out(vty,
8214 BGP_SHOW_DAMP_HEADER);
8215 else if (
8216 type == bgp_show_type_flap_statistics
8217 || type == bgp_show_type_flap_neighbor)
8218 vty_out(vty,
8219 BGP_SHOW_FLAP_HEADER);
8220 else
8221 vty_out(vty, BGP_SHOW_HEADER);
8222 header = 0;
8223 }
8224
8225 if (type == bgp_show_type_dampend_paths
8226 || type == bgp_show_type_damp_neighbor)
8227 damp_route_vty_out(
8228 vty, &rn->p, ri, display,
8229 SAFI_UNICAST, use_json,
8230 json_paths);
8231 else if (type == bgp_show_type_flap_statistics
8232 || type == bgp_show_type_flap_neighbor)
8233 flap_route_vty_out(
8234 vty, &rn->p, ri, display,
8235 SAFI_UNICAST, use_json,
8236 json_paths);
8237 else
8238 route_vty_out(vty, &rn->p, ri, display,
8239 SAFI_UNICAST, json_paths);
8240 display++;
8241 }
8242
8243 if (display) {
8244 output_count++;
8245 if (use_json) {
8246 p = &rn->p;
8247 sprintf(buf2, "%s/%d",
8248 inet_ntop(p->family,
8249 &p->u.prefix, buf,
8250 BUFSIZ),
8251 p->prefixlen);
8252 vty_out(vty, "\"%s\": ", buf2);
8253 vty_out(vty, "%s",
8254 json_object_to_json_string(
8255 json_paths));
8256 json_object_free(json_paths);
8257 first = 0;
8258 }
8259 }
8260 }
8261
8262 if (use_json) {
8263 json_object_free(json_paths);
8264 vty_out(vty, " } }\n");
8265 } else {
8266 /* No route is displayed */
8267 if (output_count == 0) {
8268 if (type == bgp_show_type_normal)
8269 vty_out(vty,
8270 "No BGP prefixes displayed, %ld exist\n",
8271 total_count);
8272 } else
8273 vty_out(vty,
8274 "\nDisplayed %ld routes and %ld total paths\n",
8275 output_count, total_count);
8276 }
718e3744 8277
d62a17ae 8278 return CMD_SUCCESS;
718e3744 8279}
8280
d62a17ae 8281static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
8282 enum bgp_show_type type, void *output_arg, u_char use_json)
fee0f4c6 8283{
d62a17ae 8284 struct bgp_table *table;
fee0f4c6 8285
d62a17ae 8286 if (bgp == NULL) {
8287 bgp = bgp_get_default();
8288 }
fee0f4c6 8289
d62a17ae 8290 if (bgp == NULL) {
8291 if (!use_json)
8292 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8293 else
8294 vty_out(vty, "{}\n");
d62a17ae 8295 return CMD_WARNING;
8296 }
4dd6177e 8297
d62a17ae 8298 /* use MPLS and ENCAP specific shows until they are merged */
8299 if (safi == SAFI_MPLS_VPN) {
8300 return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg, 0,
8301 use_json);
8302 }
8303 /* labeled-unicast routes live in the unicast table */
8304 else if (safi == SAFI_LABELED_UNICAST)
8305 safi = SAFI_UNICAST;
fee0f4c6 8306
d62a17ae 8307 table = bgp->rib[afi][safi];
fee0f4c6 8308
d62a17ae 8309 return bgp_show_table(vty, bgp, table, type, output_arg, use_json);
fee0f4c6 8310}
8311
d62a17ae 8312static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
8313 safi_t safi, u_char use_json)
f186de26 8314{
d62a17ae 8315 struct listnode *node, *nnode;
8316 struct bgp *bgp;
8317 int is_first = 1;
f186de26 8318
d62a17ae 8319 if (use_json)
8320 vty_out(vty, "{\n");
9f689658 8321
d62a17ae 8322 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
8323 if (use_json) {
8324 if (!is_first)
8325 vty_out(vty, ",\n");
8326 else
8327 is_first = 0;
8328
8329 vty_out(vty, "\"%s\":",
8330 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8331 ? "Default"
8332 : bgp->name);
8333 } else {
8334 vty_out(vty, "\nInstance %s:\n",
8335 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8336 ? "Default"
8337 : bgp->name);
8338 }
8339 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
8340 use_json);
8341 }
9f689658 8342
d62a17ae 8343 if (use_json)
8344 vty_out(vty, "}\n");
f186de26 8345}
8346
718e3744 8347/* Header of detailed BGP route information */
d62a17ae 8348void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
8349 struct bgp_node *rn, struct prefix_rd *prd,
8350 afi_t afi, safi_t safi, json_object *json)
8351{
8352 struct bgp_info *ri;
8353 struct prefix *p;
8354 struct peer *peer;
8355 struct listnode *node, *nnode;
8356 char buf1[INET6_ADDRSTRLEN];
8357 char buf2[INET6_ADDRSTRLEN];
8c197128 8358#if defined(HAVE_CUMULUS)
d62a17ae 8359 char buf3[EVPN_ROUTE_STRLEN];
8c197128 8360#endif
9c92b5f7 8361 char prefix_str[BUFSIZ];
d62a17ae 8362 int count = 0;
8363 int best = 0;
8364 int suppress = 0;
8365 int no_export = 0;
8366 int no_advertise = 0;
8367 int local_as = 0;
8368 int first = 1;
8369 int has_valid_label = 0;
8370 mpls_label_t label = 0;
8371 json_object *json_adv_to = NULL;
9bedbb1e 8372
d62a17ae 8373 p = &rn->p;
8374 has_valid_label = bgp_is_valid_label(&rn->local_label);
8375
8376 if (has_valid_label)
8377 label = label_pton(&rn->local_label);
8378
8379 if (json) {
8380 if (has_valid_label)
8381 json_object_int_add(json, "localLabel", label);
8382
b682f6de 8383 json_object_string_add(json, "prefix",
8384 prefix2str(p, prefix_str,
8385 sizeof(prefix_str)));
d62a17ae 8386 } else {
8387#if defined(HAVE_CUMULUS)
8388 if (safi == SAFI_EVPN)
8389 vty_out(vty, "BGP routing table entry for %s%s%s\n",
8390 prd ? prefix_rd2str(prd, buf1, RD_ADDRSTRLEN)
8391 : "",
8392 prd ? ":" : "",
8393 bgp_evpn_route2str((struct prefix_evpn *)p,
8394 buf3, sizeof(buf3)));
8395 else
8396 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8397 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8398 ? prefix_rd2str(prd, buf1,
8399 RD_ADDRSTRLEN)
8400 : ""),
8401 safi == SAFI_MPLS_VPN ? ":" : "",
8402 inet_ntop(p->family, &p->u.prefix, buf2,
8403 INET6_ADDRSTRLEN),
8404 p->prefixlen);
520d5d76 8405#else
d62a17ae 8406 if (p->family == AF_ETHERNET)
8407 prefix2str(p, buf2, INET6_ADDRSTRLEN);
8408 else
8409 inet_ntop(p->family, &p->u.prefix, buf2,
8410 INET6_ADDRSTRLEN);
8411 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
8412 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8413 || safi == SAFI_EVPN)
8414 ? prefix_rd2str(prd, buf1, RD_ADDRSTRLEN)
8415 : ""),
8416 ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":"
8417 : "",
8418 buf2, p->prefixlen);
520d5d76 8419#endif
cd1964ff 8420
d62a17ae 8421 if (has_valid_label)
8422 vty_out(vty, "Local label: %d\n", label);
8423#if defined(HAVE_CUMULUS)
8424 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
520d5d76 8425#else
d62a17ae 8426 if (bgp_labeled_safi(safi))
520d5d76 8427#endif
d62a17ae 8428 vty_out(vty, "not allocated\n");
8429 }
718e3744 8430
d62a17ae 8431 for (ri = rn->info; ri; ri = ri->next) {
8432 count++;
8433 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
8434 best = count;
8435 if (ri->extra && ri->extra->suppress)
8436 suppress = 1;
8437 if (ri->attr->community != NULL) {
8438 if (community_include(ri->attr->community,
8439 COMMUNITY_NO_ADVERTISE))
8440 no_advertise = 1;
8441 if (community_include(ri->attr->community,
8442 COMMUNITY_NO_EXPORT))
8443 no_export = 1;
8444 if (community_include(ri->attr->community,
8445 COMMUNITY_LOCAL_AS))
8446 local_as = 1;
8447 }
8448 }
718e3744 8449 }
718e3744 8450
d62a17ae 8451 if (!json) {
8452 vty_out(vty, "Paths: (%d available", count);
8453 if (best) {
8454 vty_out(vty, ", best #%d", best);
8455 if (safi == SAFI_UNICAST)
8456 vty_out(vty, ", table %s",
8457 (bgp->inst_type
8458 == BGP_INSTANCE_TYPE_DEFAULT)
8459 ? "Default-IP-Routing-Table"
8460 : bgp->name);
8461 } else
8462 vty_out(vty, ", no best path");
8463
8464 if (no_advertise)
8465 vty_out(vty, ", not advertised to any peer");
8466 else if (no_export)
8467 vty_out(vty, ", not advertised to EBGP peer");
8468 else if (local_as)
8469 vty_out(vty, ", not advertised outside local AS");
8470
8471 if (suppress)
8472 vty_out(vty,
8473 ", Advertisements suppressed by an aggregate.");
8474 vty_out(vty, ")\n");
8475 }
718e3744 8476
d62a17ae 8477 /* If we are not using addpath then we can display Advertised to and
8478 * that will
8479 * show what peers we advertised the bestpath to. If we are using
8480 * addpath
8481 * though then we must display Advertised to on a path-by-path basis. */
8482 if (!bgp->addpath_tx_used[afi][safi]) {
8483 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8484 if (bgp_adj_out_lookup(peer, rn, 0)) {
8485 if (json && !json_adv_to)
8486 json_adv_to = json_object_new_object();
8487
8488 route_vty_out_advertised_to(
8489 vty, peer, &first,
8490 " Advertised to non peer-group peers:\n ",
8491 json_adv_to);
8492 }
8493 }
8494
8495 if (json) {
8496 if (json_adv_to) {
8497 json_object_object_add(json, "advertisedTo",
8498 json_adv_to);
8499 }
8500 } else {
8501 if (first)
8502 vty_out(vty, " Not advertised to any peer");
8503 vty_out(vty, "\n");
8504 }
8505 }
718e3744 8506}
8507
8508/* Display specified route of BGP table. */
d62a17ae 8509static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
8510 struct bgp_table *rib, const char *ip_str,
8511 afi_t afi, safi_t safi,
8512 struct prefix_rd *prd, int prefix_check,
8513 enum bgp_path_type pathtype, u_char use_json)
8514{
8515 int ret;
8516 int header;
8517 int display = 0;
8518 struct prefix match;
8519 struct bgp_node *rn;
8520 struct bgp_node *rm;
8521 struct bgp_info *ri;
8522 struct bgp_table *table;
8523 json_object *json = NULL;
8524 json_object *json_paths = NULL;
8525
8526 /* Check IP address argument. */
8527 ret = str2prefix(ip_str, &match);
8528 if (!ret) {
8529 vty_out(vty, "address is malformed\n");
8530 return CMD_WARNING;
8531 }
718e3744 8532
d62a17ae 8533 match.family = afi2family(afi);
b05a1c8b 8534
d62a17ae 8535 if (use_json) {
8536 json = json_object_new_object();
8537 json_paths = json_object_new_array();
8538 }
718e3744 8539
d62a17ae 8540 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
8541 for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
8542 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
8543 continue;
8544
8545 if ((table = rn->info) != NULL) {
8546 header = 1;
8547
8548 if ((rm = bgp_node_match(table, &match))
8549 != NULL) {
8550 if (prefix_check
8551 && rm->p.prefixlen
8552 != match.prefixlen) {
8553 bgp_unlock_node(rm);
8554 continue;
8555 }
8556
8557 for (ri = rm->info; ri; ri = ri->next) {
8558 if (header) {
8559 route_vty_out_detail_header(
8560 vty, bgp, rm,
8561 (struct
8562 prefix_rd *)&rn
8563 ->p,
8564 AFI_IP, safi,
8565 json);
8566 header = 0;
8567 }
8568 display++;
8569
8570 if (pathtype == BGP_PATH_ALL
8571 || (pathtype
8572 == BGP_PATH_BESTPATH
8573 && CHECK_FLAG(
8574 ri->flags,
8575 BGP_INFO_SELECTED))
8576 || (pathtype
8577 == BGP_PATH_MULTIPATH
8578 && (CHECK_FLAG(
8579 ri->flags,
8580 BGP_INFO_MULTIPATH)
8581 || CHECK_FLAG(
8582 ri->flags,
8583 BGP_INFO_SELECTED))))
8584 route_vty_out_detail(
8585 vty, bgp,
8586 &rm->p, ri,
8587 AFI_IP, safi,
8588 json_paths);
8589 }
8590
8591 bgp_unlock_node(rm);
8592 }
8593 }
8594 }
8595 } else {
8596 header = 1;
8597
8598 if ((rn = bgp_node_match(rib, &match)) != NULL) {
8599 if (!prefix_check
8600 || rn->p.prefixlen == match.prefixlen) {
8601 for (ri = rn->info; ri; ri = ri->next) {
8602 if (header) {
8603 route_vty_out_detail_header(
8604 vty, bgp, rn, NULL, afi,
8605 safi, json);
8606 header = 0;
8607 }
8608 display++;
8609
8610 if (pathtype == BGP_PATH_ALL
8611 || (pathtype == BGP_PATH_BESTPATH
8612 && CHECK_FLAG(
8613 ri->flags,
8614 BGP_INFO_SELECTED))
8615 || (pathtype == BGP_PATH_MULTIPATH
8616 && (CHECK_FLAG(
8617 ri->flags,
8618 BGP_INFO_MULTIPATH)
8619 || CHECK_FLAG(
8620 ri->flags,
8621 BGP_INFO_SELECTED))))
8622 route_vty_out_detail(
8623 vty, bgp, &rn->p, ri,
8624 afi, safi, json_paths);
8625 }
8626 }
8627
8628 bgp_unlock_node(rn);
8629 }
8630 }
e5eee9af 8631
d62a17ae 8632 if (use_json) {
8633 if (display)
8634 json_object_object_add(json, "paths", json_paths);
8635
9d303b37
DL
8636 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8637 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 8638 json_object_free(json);
8639 } else {
8640 if (!display) {
8641 vty_out(vty, "%% Network not in table\n");
8642 return CMD_WARNING;
8643 }
8644 }
b05a1c8b 8645
d62a17ae 8646 return CMD_SUCCESS;
718e3744 8647}
8648
fee0f4c6 8649/* Display specified route of Main RIB */
d62a17ae 8650static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
8651 afi_t afi, safi_t safi, struct prefix_rd *prd,
8652 int prefix_check, enum bgp_path_type pathtype,
8653 u_char use_json)
8654{
9b86009a 8655 if (!bgp) {
d62a17ae 8656 bgp = bgp_get_default();
9b86009a
RW
8657 if (!bgp) {
8658 if (!use_json)
8659 vty_out(vty, "No BGP process is configured\n");
16307668
RW
8660 else
8661 vty_out(vty, "{}\n");
9b86009a
RW
8662 return CMD_WARNING;
8663 }
8664 }
d62a17ae 8665
8666 /* labeled-unicast routes live in the unicast table */
8667 if (safi == SAFI_LABELED_UNICAST)
8668 safi = SAFI_UNICAST;
8669
8670 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
8671 afi, safi, prd, prefix_check, pathtype,
8672 use_json);
8673}
8674
8675static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
8676 struct cmd_token **argv, afi_t afi, safi_t safi,
8677 u_char uj)
8678{
8679 struct lcommunity *lcom;
8680 struct buffer *b;
8681 int i;
8682 char *str;
8683 int first = 0;
8684
8685 b = buffer_new(1024);
8686 for (i = 0; i < argc; i++) {
8687 if (first)
8688 buffer_putc(b, ' ');
8689 else {
8690 if (strmatch(argv[i]->text, "AA:BB:CC")) {
8691 first = 1;
8692 buffer_putstr(b, argv[i]->arg);
8693 }
8694 }
8695 }
8696 buffer_putc(b, '\0');
57d187bc 8697
d62a17ae 8698 str = buffer_getstr(b);
8699 buffer_free(b);
57d187bc 8700
d62a17ae 8701 lcom = lcommunity_str2com(str);
8702 XFREE(MTYPE_TMP, str);
8703 if (!lcom) {
8704 vty_out(vty, "%% Large-community malformed\n");
8705 return CMD_WARNING;
8706 }
57d187bc 8707
d62a17ae 8708 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
8709 uj);
57d187bc
JS
8710}
8711
d62a17ae 8712static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
8713 const char *lcom, afi_t afi, safi_t safi,
8714 u_char uj)
57d187bc 8715{
d62a17ae 8716 struct community_list *list;
57d187bc 8717
d62a17ae 8718 list = community_list_lookup(bgp_clist, lcom,
8719 LARGE_COMMUNITY_LIST_MASTER);
8720 if (list == NULL) {
8721 vty_out(vty, "%% %s is not a valid large-community-list name\n",
8722 lcom);
8723 return CMD_WARNING;
8724 }
57d187bc 8725
d62a17ae 8726 return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
8727 list, uj);
fee0f4c6 8728}
8729
52951b63
DS
8730DEFUN (show_ip_bgp_large_community_list,
8731 show_ip_bgp_large_community_list_cmd,
4dd6177e 8732 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
52951b63
DS
8733 SHOW_STR
8734 IP_STR
8735 BGP_STR
8736 BGP_INSTANCE_HELP_STR
9bedbb1e 8737 BGP_AFI_HELP_STR
4dd6177e 8738 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
8739 "Display routes matching the large-community-list\n"
8740 "large-community-list number\n"
8741 "large-community-list name\n"
8742 JSON_STR)
8743{
d62a17ae 8744 char *vrf = NULL;
8745 afi_t afi = AFI_IP6;
8746 safi_t safi = SAFI_UNICAST;
8747 int idx = 0;
8748
8749 if (argv_find(argv, argc, "ip", &idx))
8750 afi = AFI_IP;
8751 if (argv_find(argv, argc, "view", &idx)
8752 || argv_find(argv, argc, "vrf", &idx))
8753 vrf = argv[++idx]->arg;
8754 if (argv_find(argv, argc, "ipv4", &idx)
8755 || argv_find(argv, argc, "ipv6", &idx)) {
8756 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
8757 if (argv_find(argv, argc, "unicast", &idx)
8758 || argv_find(argv, argc, "multicast", &idx))
8759 safi = bgp_vty_safi_from_str(argv[idx]->text);
8760 }
8761
8762 int uj = use_json(argc, argv);
8763
8764 struct bgp *bgp = bgp_lookup_by_name(vrf);
8765 if (bgp == NULL) {
8766 vty_out(vty, "Can't find BGP instance %s\n", vrf);
8767 return CMD_WARNING;
8768 }
8769
8770 argv_find(argv, argc, "large-community-list", &idx);
8771 return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
8772 uj);
52951b63
DS
8773}
8774DEFUN (show_ip_bgp_large_community,
8775 show_ip_bgp_large_community_cmd,
4dd6177e 8776 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
8777 SHOW_STR
8778 IP_STR
8779 BGP_STR
8780 BGP_INSTANCE_HELP_STR
9bedbb1e 8781 BGP_AFI_HELP_STR
4dd6177e 8782 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
8783 "Display routes matching the large-communities\n"
8784 "List of large-community numbers\n"
8785 JSON_STR)
8786{
d62a17ae 8787 char *vrf = NULL;
8788 afi_t afi = AFI_IP6;
8789 safi_t safi = SAFI_UNICAST;
8790 int idx = 0;
8791
8792 if (argv_find(argv, argc, "ip", &idx))
8793 afi = AFI_IP;
8794 if (argv_find(argv, argc, "view", &idx)
8795 || argv_find(argv, argc, "vrf", &idx))
8796 vrf = argv[++idx]->arg;
8797 if (argv_find(argv, argc, "ipv4", &idx)
8798 || argv_find(argv, argc, "ipv6", &idx)) {
8799 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
8800 if (argv_find(argv, argc, "unicast", &idx)
8801 || argv_find(argv, argc, "multicast", &idx))
8802 safi = bgp_vty_safi_from_str(argv[idx]->text);
8803 }
8804
8805 int uj = use_json(argc, argv);
8806
8807 struct bgp *bgp = bgp_lookup_by_name(vrf);
8808 if (bgp == NULL) {
8809 vty_out(vty, "Can't find BGP instance %s\n", vrf);
8810 return CMD_WARNING;
8811 }
8812
8813 if (argv_find(argv, argc, "AA:BB:CC", &idx))
8814 return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
8815 else
8816 return bgp_show(vty, bgp, afi, safi,
8817 bgp_show_type_lcommunity_all, NULL, uj);
52951b63
DS
8818}
8819
d62a17ae 8820static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
8821 safi_t safi);
e01ca200 8822
718e3744 8823/* BGP route print out function. */
af462945
DS
8824DEFUN (show_ip_bgp,
8825 show_ip_bgp_cmd,
4dd6177e 8826 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
ae19d7dd
QY
8827 [<\
8828 cidr-only\
8c3deaae 8829 |dampening <flap-statistics|dampened-paths|parameters>\
ae19d7dd
QY
8830 |route-map WORD\
8831 |prefix-list WORD\
8832 |filter-list WORD\
e01ca200 8833 |statistics\
0c7b1b01 8834 |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
ae19d7dd
QY
8835 |community-list <(1-500)|WORD> [exact-match]\
8836 |A.B.C.D/M longer-prefixes\
9711caf8
DS
8837 |X:X::X:X/M longer-prefixes>\
8838 ] [json]",
718e3744 8839 SHOW_STR
8840 IP_STR
8841 BGP_STR
a636c635 8842 BGP_INSTANCE_HELP_STR
4f280b15 8843 BGP_AFI_HELP_STR
4dd6177e 8844 BGP_SAFI_WITH_LABEL_HELP_STR
a636c635 8845 "Display only routes with non-natural netmasks\n"
a636c635
DW
8846 "Display detailed information about dampening\n"
8847 "Display flap statistics of routes\n"
8848 "Display paths suppressed due to dampening\n"
af462945 8849 "Display detail of configured dampening parameters\n"
a636c635
DW
8850 "Display routes matching the route-map\n"
8851 "A route-map to match on\n"
8852 "Display routes conforming to the prefix-list\n"
8c3deaae 8853 "Prefix-list name\n"
a636c635
DW
8854 "Display routes conforming to the filter-list\n"
8855 "Regular expression access list name\n"
e01ca200 8856 "BGP RIB advertisement statistics\n"
a636c635
DW
8857 "Display routes matching the communities\n"
8858 COMMUNITY_AANN_STR
8859 "Do not send outside local AS (well-known community)\n"
8860 "Do not advertise to any peer (well-known community)\n"
8861 "Do not export to next AS (well-known community)\n"
8862 "Exact match of the communities\n"
8863 "Display routes matching the community-list\n"
8864 "community-list number\n"
8865 "community-list name\n"
8866 "Exact match of the communities\n"
0c7b1b01 8867 "IPv4 prefix\n"
8c3deaae 8868 "Display route and more specific routes\n"
0c7b1b01 8869 "IPv6 prefix\n"
a636c635 8870 "Display route and more specific routes\n"
9973d184 8871 JSON_STR)
718e3744 8872{
d62a17ae 8873 afi_t afi = AFI_IP6;
8874 safi_t safi = SAFI_UNICAST;
8875 int exact_match = 0;
8876 enum bgp_show_type sh_type = bgp_show_type_normal;
8877 struct bgp *bgp = NULL;
8878 int idx = 0;
8879
8880 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
8881 &bgp);
8882 if (!idx)
8883 return CMD_WARNING;
8884
8885 int uj = use_json(argc, argv);
8886 if (uj)
8887 argc--;
8888
8889 if (argv_find(argv, argc, "cidr-only", &idx))
8890 return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
8891 NULL, uj);
8892
8893 if (argv_find(argv, argc, "dampening", &idx)) {
8894 if (argv_find(argv, argc, "dampened-paths", &idx))
8895 return bgp_show(vty, bgp, afi, safi,
8896 bgp_show_type_dampend_paths, NULL, uj);
8897 else if (argv_find(argv, argc, "flap-statistics", &idx))
8898 return bgp_show(vty, bgp, afi, safi,
8899 bgp_show_type_flap_statistics, NULL,
8900 uj);
8901 else if (argv_find(argv, argc, "parameters", &idx))
8902 return bgp_show_dampening_parameters(vty, afi, safi);
8903 }
c016b6c7 8904
d62a17ae 8905 if (argv_find(argv, argc, "prefix-list", &idx))
8906 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
8907 safi, bgp_show_type_prefix_list);
8908
8909 if (argv_find(argv, argc, "filter-list", &idx))
8910 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
8911 safi, bgp_show_type_filter_list);
8912
8913 if (argv_find(argv, argc, "statistics", &idx))
8914 return bgp_table_stats(vty, bgp, afi, safi);
8915
8916 if (argv_find(argv, argc, "route-map", &idx))
8917 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
8918 safi, bgp_show_type_route_map);
8919
8920 if (argv_find(argv, argc, "community", &idx)) {
8921 /* show a specific community */
8922 if (argv_find(argv, argc, "local-AS", &idx)
8923 || argv_find(argv, argc, "no-advertise", &idx)
8924 || argv_find(argv, argc, "no-export", &idx)) {
8925 if (argv_find(argv, argc, "exact_match", &idx))
8926 exact_match = 1;
8927 return bgp_show_community(vty, bgp, argc, argv,
8928 exact_match, afi, safi);
8929 }
8930 /* show all communities */
8931 else
8932 return bgp_show(vty, bgp, afi, safi,
8933 bgp_show_type_community_all, NULL, uj);
8934 }
a636c635 8935
d62a17ae 8936 if (argv_find(argv, argc, "community-list", &idx)) {
8937 const char *clist_number_or_name = argv[++idx]->arg;
8938 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
8939 exact_match = 1;
8940 return bgp_show_community_list(vty, bgp, clist_number_or_name,
8941 exact_match, afi, safi);
8942 }
8943 /* prefix-longer */
8944 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
8945 || argv_find(argv, argc, "X:X::X:X/M", &idx))
8946 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
8947 safi,
8948 bgp_show_type_prefix_longer);
8949
8950 if (safi == SAFI_MPLS_VPN)
8951 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
8952 NULL, 0, uj);
8953 else
8954 return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 8955}
47fc97cc 8956
718e3744 8957DEFUN (show_ip_bgp_route,
8958 show_ip_bgp_route_cmd,
4dd6177e 8959 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]"
ae19d7dd 8960 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 8961 SHOW_STR
8962 IP_STR
8963 BGP_STR
a636c635 8964 BGP_INSTANCE_HELP_STR
4f280b15 8965 BGP_AFI_HELP_STR
4dd6177e 8966 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 8967 "Network in the BGP routing table to display\n"
0c7b1b01 8968 "IPv4 prefix\n"
8c3deaae 8969 "Network in the BGP routing table to display\n"
0c7b1b01 8970 "IPv6 prefix\n"
4092b06c 8971 "Display only the bestpath\n"
b05a1c8b 8972 "Display only multipaths\n"
9973d184 8973 JSON_STR)
4092b06c 8974{
d62a17ae 8975 int prefix_check = 0;
ae19d7dd 8976
d62a17ae 8977 afi_t afi = AFI_IP6;
8978 safi_t safi = SAFI_UNICAST;
8979 char *prefix = NULL;
8980 struct bgp *bgp = NULL;
8981 enum bgp_path_type path_type;
8982 u_char uj = use_json(argc, argv);
b05a1c8b 8983
d62a17ae 8984 int idx = 0;
ae19d7dd 8985
d62a17ae 8986 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
8987 &bgp);
8988 if (!idx)
8989 return CMD_WARNING;
c41247f5 8990
d62a17ae 8991 if (!bgp) {
8992 vty_out(vty,
8993 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
8994 return CMD_WARNING;
8995 }
a636c635 8996
d62a17ae 8997 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8998 if (argv_find(argv, argc, "A.B.C.D", &idx)
8999 || argv_find(argv, argc, "X:X::X:X", &idx))
9000 prefix_check = 0;
9001 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
9002 || argv_find(argv, argc, "X:X::X:X/M", &idx))
9003 prefix_check = 1;
9004
9005 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
9006 && afi != AFI_IP6) {
9007 vty_out(vty,
9008 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9009 return CMD_WARNING;
9010 }
9011 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
9012 && afi != AFI_IP) {
9013 vty_out(vty,
9014 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9015 return CMD_WARNING;
9016 }
9017
9018 prefix = argv[idx]->arg;
9019
9020 /* [<bestpath|multipath>] */
9021 if (argv_find(argv, argc, "bestpath", &idx))
9022 path_type = BGP_PATH_BESTPATH;
9023 else if (argv_find(argv, argc, "multipath", &idx))
9024 path_type = BGP_PATH_MULTIPATH;
9025 else
9026 path_type = BGP_PATH_ALL;
a636c635 9027
d62a17ae 9028 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
9029 path_type, uj);
4092b06c
DS
9030}
9031
8c3deaae
QY
9032DEFUN (show_ip_bgp_regexp,
9033 show_ip_bgp_regexp_cmd,
4dd6177e 9034 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
9035 SHOW_STR
9036 IP_STR
9037 BGP_STR
b00b230a 9038 BGP_INSTANCE_HELP_STR
4f280b15 9039 BGP_AFI_HELP_STR
4dd6177e 9040 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae
QY
9041 "Display routes matching the AS path regular expression\n"
9042 "A regular-expression to match the BGP AS paths\n")
9043{
d62a17ae 9044 afi_t afi = AFI_IP6;
9045 safi_t safi = SAFI_UNICAST;
9046 struct bgp *bgp = NULL;
8c3deaae 9047
d62a17ae 9048 int idx = 0;
9049 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9050 &bgp);
9051 if (!idx)
9052 return CMD_WARNING;
8c3deaae 9053
d62a17ae 9054 // get index of regex
9055 argv_find(argv, argc, "regexp", &idx);
9056 idx++;
8c3deaae 9057
d62a17ae 9058 char *regstr = argv_concat(argv, argc, idx);
9059 int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi,
9060 bgp_show_type_regexp);
9061 XFREE(MTYPE_TMP, regstr);
9062 return rc;
8c3deaae
QY
9063}
9064
a636c635
DW
9065DEFUN (show_ip_bgp_instance_all,
9066 show_ip_bgp_instance_all_cmd,
4dd6177e 9067 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]",
4092b06c 9068 SHOW_STR
a636c635 9069 IP_STR
4092b06c 9070 BGP_STR
a636c635 9071 BGP_INSTANCE_ALL_HELP_STR
4f280b15 9072 BGP_AFI_HELP_STR
4dd6177e 9073 BGP_SAFI_WITH_LABEL_HELP_STR
9973d184 9074 JSON_STR)
4092b06c 9075{
d62a17ae 9076 afi_t afi = AFI_IP;
9077 safi_t safi = SAFI_UNICAST;
9078 struct bgp *bgp = NULL;
ae19d7dd 9079
d62a17ae 9080 int idx = 0;
9081 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9082 &bgp);
9083 if (!idx)
9084 return CMD_WARNING;
ae19d7dd 9085
d62a17ae 9086 int uj = use_json(argc, argv);
9087 if (uj)
9088 argc--;
e3e29b32 9089
d62a17ae 9090 bgp_show_all_instances_routes_vty(vty, afi, safi, uj);
9091 return CMD_SUCCESS;
e3e29b32
LB
9092}
9093
d62a17ae 9094static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
9095 safi_t safi, enum bgp_show_type type)
718e3744 9096{
d62a17ae 9097 regex_t *regex;
9098 int rc;
e3e29b32 9099
d62a17ae 9100 regex = bgp_regcomp(regstr);
9101 if (!regex) {
9102 vty_out(vty, "Can't compile regexp %s\n", regstr);
9103 return CMD_WARNING;
9104 }
a636c635 9105
d62a17ae 9106 rc = bgp_show(vty, NULL, afi, safi, type, regex, 0);
9107 bgp_regex_free(regex);
9108 return rc;
e3e29b32
LB
9109}
9110
d62a17ae 9111static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9112 const char *prefix_list_str, afi_t afi,
9113 safi_t safi, enum bgp_show_type type)
e3e29b32 9114{
d62a17ae 9115 struct prefix_list *plist;
718e3744 9116
d62a17ae 9117 plist = prefix_list_lookup(afi, prefix_list_str);
9118 if (plist == NULL) {
9119 vty_out(vty, "%% %s is not a valid prefix-list name\n",
9120 prefix_list_str);
9121 return CMD_WARNING;
9122 }
718e3744 9123
d62a17ae 9124 return bgp_show(vty, bgp, afi, safi, type, plist, 0);
4092b06c
DS
9125}
9126
d62a17ae 9127static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9128 const char *filter, afi_t afi, safi_t safi,
9129 enum bgp_show_type type)
4092b06c 9130{
d62a17ae 9131 struct as_list *as_list;
718e3744 9132
d62a17ae 9133 as_list = as_list_lookup(filter);
9134 if (as_list == NULL) {
9135 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
9136 filter);
9137 return CMD_WARNING;
9138 }
a636c635 9139
d62a17ae 9140 return bgp_show(vty, bgp, afi, safi, type, as_list, 0);
718e3744 9141}
9142
d62a17ae 9143static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9144 const char *rmap_str, afi_t afi, safi_t safi,
9145 enum bgp_show_type type)
718e3744 9146{
d62a17ae 9147 struct route_map *rmap;
bb46e94f 9148
d62a17ae 9149 rmap = route_map_lookup_by_name(rmap_str);
9150 if (!rmap) {
9151 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
9152 return CMD_WARNING;
9153 }
9154
9155 return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
9156}
9157
9158static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
9159 struct cmd_token **argv, int exact, afi_t afi,
9160 safi_t safi)
9161{
9162 struct community *com;
9163 struct buffer *b;
9164 int i;
9165 char *str;
9166 int first = 0;
9167 int ret = 0;
9168
9169 b = buffer_new(1024);
9170 for (i = 0; i < argc; i++) {
9171 if (first)
9172 buffer_putc(b, ' ');
9173 else {
9174 if (strmatch(argv[i]->text, "unicast")
9175 || strmatch(argv[i]->text, "multicast"))
9176 continue;
9177 first = 1;
9178 }
718e3744 9179
d62a17ae 9180 buffer_putstr(b, argv[i]->arg);
9181 }
9182 buffer_putc(b, '\0');
f186de26 9183
d62a17ae 9184 str = buffer_getstr(b);
9185 buffer_free(b);
f186de26 9186
d62a17ae 9187 com = community_str2com(str);
9188 XFREE(MTYPE_TMP, str);
9189 if (!com) {
9190 vty_out(vty, "%% Community malformed: \n");
9191 return CMD_WARNING;
9192 }
9193
9194 ret = bgp_show(vty, bgp, afi, safi,
9195 (exact ? bgp_show_type_community_exact
9196 : bgp_show_type_community),
9197 com, 0);
9198 community_free(com);
46c3ce83 9199
d62a17ae 9200 return ret;
718e3744 9201}
9202
d62a17ae 9203static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9204 const char *com, int exact, afi_t afi,
9205 safi_t safi)
50ef26d4 9206{
d62a17ae 9207 struct community_list *list;
50ef26d4 9208
d62a17ae 9209 list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
9210 if (list == NULL) {
9211 vty_out(vty, "%% %s is not a valid community-list name\n", com);
9212 return CMD_WARNING;
9213 }
718e3744 9214
d62a17ae 9215 return bgp_show(vty, bgp, afi, safi,
9216 (exact ? bgp_show_type_community_list_exact
9217 : bgp_show_type_community_list),
9218 list, 0);
50ef26d4 9219}
9220
d62a17ae 9221static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9222 const char *prefix, afi_t afi, safi_t safi,
9223 enum bgp_show_type type)
718e3744 9224{
d62a17ae 9225 int ret;
9226 struct prefix *p;
47fc97cc 9227
d62a17ae 9228 p = prefix_new();
95cbbd2a 9229
d62a17ae 9230 ret = str2prefix(prefix, p);
9231 if (!ret) {
9232 vty_out(vty, "%% Malformed Prefix\n");
9233 return CMD_WARNING;
9234 }
47e9b292 9235
d62a17ae 9236 ret = bgp_show(vty, bgp, afi, safi, type, p, 0);
9237 prefix_free(p);
9238 return ret;
9239}
9240
9241static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
9242 const char *ip_str, u_char use_json)
9243{
9244 int ret;
9245 struct peer *peer;
9246 union sockunion su;
9247
9248 /* Get peer sockunion. */
9249 ret = str2sockunion(ip_str, &su);
9250 if (ret < 0) {
9251 peer = peer_lookup_by_conf_if(bgp, ip_str);
9252 if (!peer) {
9253 peer = peer_lookup_by_hostname(bgp, ip_str);
9254
9255 if (!peer) {
9256 if (use_json) {
9257 json_object *json_no = NULL;
9258 json_no = json_object_new_object();
9259 json_object_string_add(
9260 json_no,
9261 "malformedAddressOrName",
9262 ip_str);
9263 vty_out(vty, "%s\n",
9264 json_object_to_json_string(
9265 json_no));
9266 json_object_free(json_no);
9267 } else
9268 vty_out(vty,
9269 "%% Malformed address or name: %s\n",
9270 ip_str);
9271 return NULL;
9272 }
9273 }
9274 return peer;
9275 }
718e3744 9276
d62a17ae 9277 /* Peer structure lookup. */
9278 peer = peer_lookup(bgp, &su);
9279 if (!peer) {
9280 if (use_json) {
9281 json_object *json_no = NULL;
9282 json_no = json_object_new_object();
9283 json_object_string_add(json_no, "warning",
9284 "No such neighbor");
9285 vty_out(vty, "%s\n",
9286 json_object_to_json_string(json_no));
9287 json_object_free(json_no);
9288 } else
9289 vty_out(vty, "No such neighbor\n");
9290 return NULL;
9291 }
2815e61f 9292
d62a17ae 9293 return peer;
9294}
9295
9296enum bgp_stats {
9297 BGP_STATS_MAXBITLEN = 0,
9298 BGP_STATS_RIB,
9299 BGP_STATS_PREFIXES,
9300 BGP_STATS_TOTPLEN,
9301 BGP_STATS_UNAGGREGATEABLE,
9302 BGP_STATS_MAX_AGGREGATEABLE,
9303 BGP_STATS_AGGREGATES,
9304 BGP_STATS_SPACE,
9305 BGP_STATS_ASPATH_COUNT,
9306 BGP_STATS_ASPATH_MAXHOPS,
9307 BGP_STATS_ASPATH_TOTHOPS,
9308 BGP_STATS_ASPATH_MAXSIZE,
9309 BGP_STATS_ASPATH_TOTSIZE,
9310 BGP_STATS_ASN_HIGHEST,
9311 BGP_STATS_MAX,
a636c635 9312};
2815e61f 9313
d62a17ae 9314static const char *table_stats_strs[] = {
9d303b37
DL
9315 [BGP_STATS_PREFIXES] = "Total Prefixes",
9316 [BGP_STATS_TOTPLEN] = "Average prefix length",
9317 [BGP_STATS_RIB] = "Total Advertisements",
9318 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9319 [BGP_STATS_MAX_AGGREGATEABLE] =
9320 "Maximum aggregateable prefixes",
9321 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9322 [BGP_STATS_SPACE] = "Address space advertised",
9323 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9324 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9325 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9326 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9327 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9328 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9329 [BGP_STATS_MAX] = NULL,
a636c635 9330};
2815e61f 9331
d62a17ae 9332struct bgp_table_stats {
9333 struct bgp_table *table;
9334 unsigned long long counts[BGP_STATS_MAX];
ff7924f6
PJ
9335};
9336
a636c635
DW
9337#if 0
9338#define TALLY_SIGFIG 100000
9339static unsigned long
9340ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9341{
a636c635
DW
9342 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9343 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9344 unsigned long ret = newtot / count;
9345
9346 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9347 return ret + 1;
9348 else
9349 return ret;
9350}
9351#endif
ff7924f6 9352
d62a17ae 9353static int bgp_table_stats_walker(struct thread *t)
2815e61f 9354{
d62a17ae 9355 struct bgp_node *rn;
9356 struct bgp_node *top;
9357 struct bgp_table_stats *ts = THREAD_ARG(t);
9358 unsigned int space = 0;
a636c635 9359
d62a17ae 9360 if (!(top = bgp_table_top(ts->table)))
9361 return 0;
2815e61f 9362
d62a17ae 9363 switch (top->p.family) {
9364 case AF_INET:
9365 space = IPV4_MAX_BITLEN;
9366 break;
9367 case AF_INET6:
9368 space = IPV6_MAX_BITLEN;
9369 break;
9370 }
9371
9372 ts->counts[BGP_STATS_MAXBITLEN] = space;
9373
9374 for (rn = top; rn; rn = bgp_route_next(rn)) {
9375 struct bgp_info *ri;
9376 struct bgp_node *prn = bgp_node_parent_nolock(rn);
9377 unsigned int rinum = 0;
9378
9379 if (rn == top)
9380 continue;
9381
9382 if (!rn->info)
9383 continue;
9384
9385 ts->counts[BGP_STATS_PREFIXES]++;
9386 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9387
a636c635
DW
9388#if 0
9389 ts->counts[BGP_STATS_AVGPLEN]
9390 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9391 ts->counts[BGP_STATS_AVGPLEN],
9392 rn->p.prefixlen);
9393#endif
d62a17ae 9394
9395 /* check if the prefix is included by any other announcements */
9396 while (prn && !prn->info)
9397 prn = bgp_node_parent_nolock(prn);
9398
9399 if (prn == NULL || prn == top) {
9400 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9401 /* announced address space */
9402 if (space)
9403 ts->counts[BGP_STATS_SPACE] +=
9404 1 << (space - rn->p.prefixlen);
9405 } else if (prn->info)
9406 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9407
9408 for (ri = rn->info; ri; ri = ri->next) {
9409 rinum++;
9410 ts->counts[BGP_STATS_RIB]++;
9411
9412 if (ri->attr
9413 && (CHECK_FLAG(ri->attr->flag,
9414 ATTR_FLAG_BIT(
9415 BGP_ATTR_ATOMIC_AGGREGATE))))
9416 ts->counts[BGP_STATS_AGGREGATES]++;
9417
9418 /* as-path stats */
9419 if (ri->attr && ri->attr->aspath) {
9420 unsigned int hops =
9421 aspath_count_hops(ri->attr->aspath);
9422 unsigned int size =
9423 aspath_size(ri->attr->aspath);
9424 as_t highest = aspath_highest(ri->attr->aspath);
9425
9426 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9427
9428 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
9429 ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
9430 hops;
9431
9432 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
9433 ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
9434 size;
9435
9436 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
9437 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635
DW
9438#if 0
9439 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
9440 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9441 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
9442 hops);
9443 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
9444 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9445 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
9446 size);
9447#endif
d62a17ae 9448 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
9449 ts->counts[BGP_STATS_ASN_HIGHEST] =
9450 highest;
9451 }
9452 }
9453 }
9454 return 0;
2815e61f 9455}
ff7924f6 9456
d62a17ae 9457static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
9458 safi_t safi)
2815e61f 9459{
d62a17ae 9460 struct bgp_table_stats ts;
9461 unsigned int i;
019386c2 9462
d62a17ae 9463 if (!bgp->rib[afi][safi]) {
9464 vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9465 afi, safi);
9466 return CMD_WARNING;
9467 }
019386c2 9468
d62a17ae 9469 vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
019386c2 9470
d62a17ae 9471 /* labeled-unicast routes live in the unicast table */
9472 if (safi == SAFI_LABELED_UNICAST)
9473 safi = SAFI_UNICAST;
019386c2 9474
d62a17ae 9475 memset(&ts, 0, sizeof(ts));
9476 ts.table = bgp->rib[afi][safi];
9477 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 9478
d62a17ae 9479 for (i = 0; i < BGP_STATS_MAX; i++) {
9480 if (!table_stats_strs[i])
9481 continue;
9482
9483 switch (i) {
a636c635
DW
9484#if 0
9485 case BGP_STATS_ASPATH_AVGHOPS:
9486 case BGP_STATS_ASPATH_AVGSIZE:
9487 case BGP_STATS_AVGPLEN:
9488 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9489 vty_out (vty, "%12.2f",
9490 (float)ts.counts[i] / (float)TALLY_SIGFIG);
9491 break;
9492#endif
d62a17ae 9493 case BGP_STATS_ASPATH_TOTHOPS:
9494 case BGP_STATS_ASPATH_TOTSIZE:
9495 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9496 vty_out(vty, "%12.2f",
9497 ts.counts[i]
9498 ? (float)ts.counts[i]
9499 / (float)ts.counts
9500 [BGP_STATS_ASPATH_COUNT]
9501 : 0);
9502 break;
9503 case BGP_STATS_TOTPLEN:
9504 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9505 vty_out(vty, "%12.2f",
9506 ts.counts[i]
9507 ? (float)ts.counts[i]
9508 / (float)ts.counts
9509 [BGP_STATS_PREFIXES]
9510 : 0);
9511 break;
9512 case BGP_STATS_SPACE:
9513 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9514 vty_out(vty, "%12llu\n", ts.counts[i]);
9515 if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
9516 break;
9517 vty_out(vty, "%30s: ", "%% announced ");
9518 vty_out(vty, "%12.2f\n",
9519 100 * (float)ts.counts[BGP_STATS_SPACE]
9520 / (float)((uint64_t)1UL
9521 << ts.counts
9522 [BGP_STATS_MAXBITLEN]));
9523 vty_out(vty, "%30s: ", "/8 equivalent ");
9524 vty_out(vty, "%12.2f\n",
9525 (float)ts.counts[BGP_STATS_SPACE]
9526 / (float)(1UL
9527 << (ts.counts
9528 [BGP_STATS_MAXBITLEN]
9529 - 8)));
9530 if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
9531 break;
9532 vty_out(vty, "%30s: ", "/24 equivalent ");
9533 vty_out(vty, "%12.2f",
9534 (float)ts.counts[BGP_STATS_SPACE]
9535 / (float)(1UL
9536 << (ts.counts
9537 [BGP_STATS_MAXBITLEN]
9538 - 24)));
9539 break;
9540 default:
9541 vty_out(vty, "%-30s: ", table_stats_strs[i]);
9542 vty_out(vty, "%12llu", ts.counts[i]);
9543 }
ff7924f6 9544
d62a17ae 9545 vty_out(vty, "\n");
9546 }
9547 return CMD_SUCCESS;
9548}
9549
9550enum bgp_pcounts {
9551 PCOUNT_ADJ_IN = 0,
9552 PCOUNT_DAMPED,
9553 PCOUNT_REMOVED,
9554 PCOUNT_HISTORY,
9555 PCOUNT_STALE,
9556 PCOUNT_VALID,
9557 PCOUNT_ALL,
9558 PCOUNT_COUNTED,
9559 PCOUNT_PFCNT, /* the figure we display to users */
9560 PCOUNT_MAX,
a636c635 9561};
718e3744 9562
d62a17ae 9563static const char *pcount_strs[] = {
9d303b37
DL
9564 [PCOUNT_ADJ_IN] = "Adj-in",
9565 [PCOUNT_DAMPED] = "Damped",
9566 [PCOUNT_REMOVED] = "Removed",
9567 [PCOUNT_HISTORY] = "History",
9568 [PCOUNT_STALE] = "Stale",
9569 [PCOUNT_VALID] = "Valid",
9570 [PCOUNT_ALL] = "All RIB",
9571 [PCOUNT_COUNTED] = "PfxCt counted",
9572 [PCOUNT_PFCNT] = "Useable",
9573 [PCOUNT_MAX] = NULL,
a636c635 9574};
718e3744 9575
d62a17ae 9576struct peer_pcounts {
9577 unsigned int count[PCOUNT_MAX];
9578 const struct peer *peer;
9579 const struct bgp_table *table;
a636c635 9580};
47fc97cc 9581
d62a17ae 9582static int bgp_peer_count_walker(struct thread *t)
9583{
9584 struct bgp_node *rn;
9585 struct peer_pcounts *pc = THREAD_ARG(t);
9586 const struct peer *peer = pc->peer;
9587
9588 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) {
9589 struct bgp_adj_in *ain;
9590 struct bgp_info *ri;
9591
9592 for (ain = rn->adj_in; ain; ain = ain->next)
9593 if (ain->peer == peer)
9594 pc->count[PCOUNT_ADJ_IN]++;
9595
9596 for (ri = rn->info; ri; ri = ri->next) {
9597 char buf[SU_ADDRSTRLEN];
9598
9599 if (ri->peer != peer)
9600 continue;
9601
9602 pc->count[PCOUNT_ALL]++;
9603
9604 if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED))
9605 pc->count[PCOUNT_DAMPED]++;
9606 if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
9607 pc->count[PCOUNT_HISTORY]++;
9608 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
9609 pc->count[PCOUNT_REMOVED]++;
9610 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
9611 pc->count[PCOUNT_STALE]++;
9612 if (CHECK_FLAG(ri->flags, BGP_INFO_VALID))
9613 pc->count[PCOUNT_VALID]++;
9614 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9615 pc->count[PCOUNT_PFCNT]++;
9616
9617 if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
9618 pc->count[PCOUNT_COUNTED]++;
9619 if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9620 zlog_warn(
9621 "%s [pcount] %s/%d is counted but flags 0x%x",
9622 peer->host,
9623 inet_ntop(rn->p.family,
9624 &rn->p.u.prefix, buf,
9625 SU_ADDRSTRLEN),
9626 rn->p.prefixlen, ri->flags);
9627 } else {
9628 if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
9629 zlog_warn(
9630 "%s [pcount] %s/%d not counted but flags 0x%x",
9631 peer->host,
9632 inet_ntop(rn->p.family,
9633 &rn->p.u.prefix, buf,
9634 SU_ADDRSTRLEN),
9635 rn->p.prefixlen, ri->flags);
9636 }
9637 }
9638 }
9639 return 0;
718e3744 9640}
9641
d62a17ae 9642static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9643 safi_t safi, u_char use_json)
856ca177 9644{
d62a17ae 9645 struct peer_pcounts pcounts = {.peer = peer};
9646 unsigned int i;
9647 json_object *json = NULL;
9648 json_object *json_loop = NULL;
856ca177 9649
d62a17ae 9650 if (use_json) {
9651 json = json_object_new_object();
9652 json_loop = json_object_new_object();
9653 }
718e3744 9654
d62a17ae 9655 if (!peer || !peer->bgp || !peer->afc[afi][safi]
9656 || !peer->bgp->rib[afi][safi]) {
9657 if (use_json) {
9658 json_object_string_add(
9659 json, "warning",
9660 "No such neighbor or address family");
9661 vty_out(vty, "%s\n", json_object_to_json_string(json));
9662 json_object_free(json);
9663 } else
9664 vty_out(vty, "%% No such neighbor or address family\n");
9665
9666 return CMD_WARNING;
9667 }
2a71e9ce 9668
d62a17ae 9669 memset(&pcounts, 0, sizeof(pcounts));
9670 pcounts.peer = peer;
9671 pcounts.table = peer->bgp->rib[afi][safi];
9672
9673 /* in-place call via thread subsystem so as to record execution time
9d303b37
DL
9674 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9675 * * on just vty_read()).
9676 * */
d62a17ae 9677 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
9678
9679 if (use_json) {
9680 json_object_string_add(json, "prefixCountsFor", peer->host);
9681 json_object_string_add(json, "multiProtocol",
9682 afi_safi_print(afi, safi));
9683 json_object_int_add(json, "pfxCounter",
9684 peer->pcount[afi][safi]);
9685
9686 for (i = 0; i < PCOUNT_MAX; i++)
9687 json_object_int_add(json_loop, pcount_strs[i],
9688 pcounts.count[i]);
9689
9690 json_object_object_add(json, "ribTableWalkCounters", json_loop);
9691
9692 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
9693 json_object_string_add(json, "pfxctDriftFor",
9694 peer->host);
9695 json_object_string_add(
9696 json, "recommended",
9697 "Please report this bug, with the above command output");
9698 }
9699 vty_out(vty, "%s\n", json_object_to_json_string(json));
9700 json_object_free(json);
9701 } else {
9702
9703 if (peer->hostname
9704 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
9705 vty_out(vty, "Prefix counts for %s/%s, %s\n",
9706 peer->hostname, peer->host,
9707 afi_safi_print(afi, safi));
9708 } else {
9709 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
9710 afi_safi_print(afi, safi));
9711 }
9712
9713 vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
9714 vty_out(vty, "\nCounts from RIB table walk:\n\n");
9715
9716 for (i = 0; i < PCOUNT_MAX; i++)
9717 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
9718 pcounts.count[i]);
9719
9720 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
9721 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
9722 vty_out(vty,
9723 "Please report this bug, with the above command output\n");
9724 }
9725 }
9726
9727 return CMD_SUCCESS;
718e3744 9728}
9729
a636c635
DW
9730DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
9731 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 9732 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 9733 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 9734 SHOW_STR
9735 IP_STR
9736 BGP_STR
8386ac43 9737 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
9738 BGP_AFI_HELP_STR
9739 BGP_SAFI_HELP_STR
0b16f239
DS
9740 "Detailed information on TCP and BGP neighbor connections\n"
9741 "Neighbor to display information about\n"
9742 "Neighbor to display information about\n"
91d37724 9743 "Neighbor on BGP configured interface\n"
a636c635 9744 "Display detailed prefix count information\n"
9973d184 9745 JSON_STR)
0b16f239 9746{
d62a17ae 9747 afi_t afi = AFI_IP6;
9748 safi_t safi = SAFI_UNICAST;
9749 struct peer *peer;
9750 int idx = 0;
9751 struct bgp *bgp = NULL;
856ca177 9752
d62a17ae 9753 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9754 &bgp);
9755 if (!idx)
9756 return CMD_WARNING;
0b16f239 9757
d62a17ae 9758 int uj = use_json(argc, argv);
9759 if (uj)
9760 argc--;
0b16f239 9761
d62a17ae 9762 argv_find(argv, argc, "neighbors", &idx);
9763 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
9764 if (!peer)
9765 return CMD_WARNING;
bb46e94f 9766
d62a17ae 9767 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj);
a636c635 9768}
0b16f239 9769
d6902373
PG
9770#ifdef KEEP_OLD_VPN_COMMANDS
9771DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
9772 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
9773 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
9774 SHOW_STR
9775 IP_STR
9776 BGP_STR
d6902373 9777 BGP_VPNVX_HELP_STR
91d37724 9778 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
9779 "Detailed information on TCP and BGP neighbor connections\n"
9780 "Neighbor to display information about\n"
9781 "Neighbor to display information about\n"
91d37724 9782 "Neighbor on BGP configured interface\n"
a636c635 9783 "Display detailed prefix count information\n"
9973d184 9784 JSON_STR)
a636c635 9785{
d62a17ae 9786 int idx_peer = 6;
9787 struct peer *peer;
9788 u_char uj = use_json(argc, argv);
a636c635 9789
d62a17ae 9790 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
9791 if (!peer)
9792 return CMD_WARNING;
9793
9794 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
9795}
9796
d6902373
PG
9797DEFUN (show_ip_bgp_vpn_all_route_prefix,
9798 show_ip_bgp_vpn_all_route_prefix_cmd,
9799 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
9800 SHOW_STR
9801 IP_STR
9802 BGP_STR
d6902373 9803 BGP_VPNVX_HELP_STR
91d37724
QY
9804 "Display information about all VPNv4 NLRIs\n"
9805 "Network in the BGP routing table to display\n"
3a2d747c 9806 "Network in the BGP routing table to display\n"
9973d184 9807 JSON_STR)
91d37724 9808{
d62a17ae 9809 int idx = 0;
9810 char *network = NULL;
9811 struct bgp *bgp = bgp_get_default();
9812 if (!bgp) {
9813 vty_out(vty, "Can't find default instance\n");
9814 return CMD_WARNING;
9815 }
87e34b58 9816
d62a17ae 9817 if (argv_find(argv, argc, "A.B.C.D", &idx))
9818 network = argv[idx]->arg;
9819 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
9820 network = argv[idx]->arg;
9821 else {
9822 vty_out(vty, "Unable to figure out Network\n");
9823 return CMD_WARNING;
9824 }
87e34b58 9825
d62a17ae 9826 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
9827 BGP_PATH_ALL, use_json(argc, argv));
91d37724 9828}
d6902373 9829#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 9830
4c63a661
PG
9831DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
9832 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
9833 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9834 SHOW_STR
9835 IP_STR
9836 BGP_STR
9837 L2VPN_HELP_STR
9838 EVPN_HELP_STR
9839 "Display information about all EVPN NLRIs\n"
9840 "Network in the BGP routing table to display\n"
9841 "Network in the BGP routing table to display\n"
9842 JSON_STR)
9843{
d62a17ae 9844 int idx = 0;
9845 char *network = NULL;
a636c635 9846
d62a17ae 9847 if (argv_find(argv, argc, "A.B.C.D", &idx))
9848 network = argv[idx]->arg;
9849 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
9850 network = argv[idx]->arg;
9851 else {
9852 vty_out(vty, "Unable to figure out Network\n");
9853 return CMD_WARNING;
9854 }
9855 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
9856 BGP_PATH_ALL, use_json(argc, argv));
9857}
9858
9859static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
9860 safi_t safi, int in, const char *rmap_name,
9861 u_char use_json, json_object *json)
9862{
9863 struct bgp_table *table;
9864 struct bgp_adj_in *ain;
9865 struct bgp_adj_out *adj;
9866 unsigned long output_count;
9867 unsigned long filtered_count;
9868 struct bgp_node *rn;
9869 int header1 = 1;
9870 struct bgp *bgp;
9871 int header2 = 1;
9872 struct attr attr;
9873 int ret;
9874 struct update_subgroup *subgrp;
9875 json_object *json_scode = NULL;
9876 json_object *json_ocode = NULL;
9877 json_object *json_ar = NULL;
9878 struct peer_af *paf;
9879
9880 if (use_json) {
9881 json_scode = json_object_new_object();
9882 json_ocode = json_object_new_object();
9883 json_ar = json_object_new_object();
9884
9885 json_object_string_add(json_scode, "suppressed", "s");
9886 json_object_string_add(json_scode, "damped", "d");
9887 json_object_string_add(json_scode, "history", "h");
9888 json_object_string_add(json_scode, "valid", "*");
9889 json_object_string_add(json_scode, "best", ">");
9890 json_object_string_add(json_scode, "multipath", "=");
9891 json_object_string_add(json_scode, "internal", "i");
9892 json_object_string_add(json_scode, "ribFailure", "r");
9893 json_object_string_add(json_scode, "stale", "S");
9894 json_object_string_add(json_scode, "removed", "R");
9895
9896 json_object_string_add(json_ocode, "igp", "i");
9897 json_object_string_add(json_ocode, "egp", "e");
9898 json_object_string_add(json_ocode, "incomplete", "?");
9899 }
a636c635 9900
d62a17ae 9901 bgp = peer->bgp;
a636c635 9902
d62a17ae 9903 if (!bgp) {
9904 if (use_json) {
9905 json_object_string_add(json, "alert", "no BGP");
9906 vty_out(vty, "%s\n", json_object_to_json_string(json));
9907 json_object_free(json);
9908 } else
9909 vty_out(vty, "%% No bgp\n");
9910 return;
9911 }
a636c635 9912
d62a17ae 9913 table = bgp->rib[afi][safi];
9914
9915 output_count = filtered_count = 0;
9916 subgrp = peer_subgroup(peer, afi, safi);
9917
9918 if (!in && subgrp
9919 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
9920 if (use_json) {
9921 json_object_int_add(json, "bgpTableVersion",
9922 table->version);
9923 json_object_string_add(json, "bgpLocalRouterId",
9924 inet_ntoa(bgp->router_id));
9925 json_object_object_add(json, "bgpStatusCodes",
9926 json_scode);
9927 json_object_object_add(json, "bgpOriginCodes",
9928 json_ocode);
9929 json_object_string_add(json,
9930 "bgpOriginatingDefaultNetwork",
9931 "0.0.0.0");
9932 } else {
9d303b37
DL
9933 vty_out(vty, "BGP table version is %" PRIu64
9934 ", local router ID is %s\n",
d62a17ae 9935 table->version, inet_ntoa(bgp->router_id));
9936 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9937 vty_out(vty, BGP_SHOW_OCODE_HEADER);
9938
9939 vty_out(vty, "Originating default network 0.0.0.0\n\n");
9940 }
9941 header1 = 0;
9942 }
a636c635 9943
d62a17ae 9944 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
9945 if (in) {
9946 for (ain = rn->adj_in; ain; ain = ain->next) {
9947 if (ain->peer == peer) {
9948 if (header1) {
9949 if (use_json) {
9950 json_object_int_add(
9951 json,
9952 "bgpTableVersion",
9953 0);
9954 json_object_string_add(
9955 json,
9956 "bgpLocalRouterId",
9957 inet_ntoa(
9958 bgp->router_id));
9959 json_object_object_add(
9960 json,
9961 "bgpStatusCodes",
9962 json_scode);
9963 json_object_object_add(
9964 json,
9965 "bgpOriginCodes",
9966 json_ocode);
9967 } else {
9968 vty_out(vty,
9969 "BGP table version is 0, local router ID is %s\n",
9970 inet_ntoa(
9971 bgp->router_id));
9972 vty_out(vty,
9973 BGP_SHOW_SCODE_HEADER);
9974 vty_out(vty,
9975 BGP_SHOW_OCODE_HEADER);
9976 }
9977 header1 = 0;
9978 }
9979 if (header2) {
9980 if (!use_json)
9981 vty_out(vty,
9982 BGP_SHOW_HEADER);
9983 header2 = 0;
9984 }
9985 if (ain->attr) {
9986 bgp_attr_dup(&attr, ain->attr);
9987 if (bgp_input_modifier(
9988 peer, &rn->p, &attr,
9989 afi, safi,
9990 rmap_name)
9991 != RMAP_DENY) {
9992 route_vty_out_tmp(
9993 vty, &rn->p,
9994 &attr, safi,
9995 use_json,
9996 json_ar);
9997 output_count++;
9998 } else
9999 filtered_count++;
10000 }
10001 }
10002 }
10003 } else {
10004 for (adj = rn->adj_out; adj; adj = adj->next)
10005 SUBGRP_FOREACH_PEER(adj->subgroup, paf)
10006 if (paf->peer == peer) {
10007 if (header1) {
10008 if (use_json) {
10009 json_object_int_add(
10010 json, "bgpTableVersion",
10011 table->version);
10012 json_object_string_add(
10013 json,
10014 "bgpLocalRouterId",
10015 inet_ntoa(
10016 bgp->router_id));
10017 json_object_object_add(
10018 json, "bgpStatusCodes",
10019 json_scode);
10020 json_object_object_add(
10021 json, "bgpOriginCodes",
10022 json_ocode);
10023 } else {
10024 vty_out(vty,
10025 "BGP table version is %" PRIu64
10026 ", local router ID is %s\n",
10027 table->version,
10028 inet_ntoa(
10029 bgp->router_id));
10030 vty_out(vty,
10031 BGP_SHOW_SCODE_HEADER);
10032 vty_out(vty,
10033 BGP_SHOW_OCODE_HEADER);
10034 }
10035 header1 = 0;
10036 }
10037
10038 if (header2) {
10039 if (!use_json)
10040 vty_out(vty, BGP_SHOW_HEADER);
10041 header2 = 0;
10042 }
10043
10044 if (adj->attr) {
10045 bgp_attr_dup(&attr, adj->attr);
10046 ret = bgp_output_modifier(
10047 peer, &rn->p, &attr, afi, safi,
10048 rmap_name);
10049 if (ret != RMAP_DENY) {
10050 route_vty_out_tmp(vty, &rn->p,
10051 &attr, safi,
10052 use_json,
10053 json_ar);
10054 output_count++;
10055 } else
10056 filtered_count++;
10057 }
10058 }
10059 }
10060 }
10061 if (use_json)
10062 json_object_object_add(json, "advertisedRoutes", json_ar);
10063
10064 if (output_count != 0) {
10065 if (use_json)
10066 json_object_int_add(json, "totalPrefixCounter",
10067 output_count);
10068 else
10069 vty_out(vty, "\nTotal number of prefixes %ld\n",
10070 output_count);
10071 }
10072 if (use_json) {
10073 vty_out(vty, "%s\n", json_object_to_json_string(json));
10074 json_object_free(json);
10075 }
a636c635 10076}
2a71e9ce 10077
d62a17ae 10078static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
10079 safi_t safi, int in, const char *rmap_name,
10080 u_char use_json)
0b16f239 10081{
d62a17ae 10082 json_object *json = NULL;
0b16f239 10083
d62a17ae 10084 if (use_json)
10085 json = json_object_new_object();
0b16f239 10086
d62a17ae 10087 /* labeled-unicast routes live in the unicast table */
10088 if (safi == SAFI_LABELED_UNICAST)
10089 safi = SAFI_UNICAST;
4dd6177e 10090
d62a17ae 10091 if (!peer || !peer->afc[afi][safi]) {
10092 if (use_json) {
10093 json_object_string_add(
10094 json, "warning",
10095 "No such neighbor or address family");
10096 vty_out(vty, "%s\n", json_object_to_json_string(json));
10097 json_object_free(json);
10098 } else
10099 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10100
d62a17ae 10101 return CMD_WARNING;
10102 }
10103
10104 if (in
10105 && !CHECK_FLAG(peer->af_flags[afi][safi],
10106 PEER_FLAG_SOFT_RECONFIG)) {
10107 if (use_json) {
10108 json_object_string_add(
10109 json, "warning",
10110 "Inbound soft reconfiguration not enabled");
10111 vty_out(vty, "%s\n", json_object_to_json_string(json));
10112 json_object_free(json);
10113 } else
10114 vty_out(vty,
10115 "%% Inbound soft reconfiguration not enabled\n");
10116
10117 return CMD_WARNING;
10118 }
0b16f239 10119
d62a17ae 10120 show_adj_route(vty, peer, afi, safi, in, rmap_name, use_json, json);
0b16f239 10121
d62a17ae 10122 return CMD_SUCCESS;
a636c635 10123}
50ef26d4 10124
a636c635
DW
10125DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10126 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10127 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
1edcd642 10128 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
718e3744 10129 SHOW_STR
10130 IP_STR
10131 BGP_STR
a636c635 10132 BGP_INSTANCE_HELP_STR
7395a2c9 10133 BGP_AFI_HELP_STR
4dd6177e 10134 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10135 "Detailed information on TCP and BGP neighbor connections\n"
10136 "Neighbor to display information about\n"
10137 "Neighbor to display information about\n"
91d37724 10138 "Neighbor on BGP configured interface\n"
856ca177 10139 "Display the received routes from neighbor\n"
a636c635
DW
10140 "Display the routes advertised to a BGP neighbor\n"
10141 "Route-map to modify the attributes\n"
10142 "Name of the route map\n"
9973d184 10143 JSON_STR)
718e3744 10144{
d62a17ae 10145 afi_t afi = AFI_IP6;
10146 safi_t safi = SAFI_UNICAST;
10147 char *rmap_name = NULL;
10148 char *peerstr = NULL;
10149 int rcvd = 0;
10150 struct bgp *bgp = NULL;
10151 struct peer *peer;
bb46e94f 10152
d62a17ae 10153 int idx = 0;
718e3744 10154
d62a17ae 10155 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10156 &bgp);
10157 if (!idx)
10158 return CMD_WARNING;
c493f2d8 10159
d62a17ae 10160 int uj = use_json(argc, argv);
10161 if (uj)
10162 argc--;
30a6a167 10163
d62a17ae 10164 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10165 argv_find(argv, argc, "neighbors", &idx);
10166 peerstr = argv[++idx]->arg;
8c3deaae 10167
d62a17ae 10168 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10169 if (!peer)
10170 return CMD_WARNING;
856ca177 10171
d62a17ae 10172 if (argv_find(argv, argc, "received-routes", &idx))
10173 rcvd = 1;
10174 if (argv_find(argv, argc, "advertised-routes", &idx))
10175 rcvd = 0;
10176 if (argv_find(argv, argc, "route-map", &idx))
10177 rmap_name = argv[++idx]->arg;
95cbbd2a 10178
d62a17ae 10179 return peer_adj_routes(vty, peer, afi, safi, rcvd, rmap_name, uj);
95cbbd2a
ML
10180}
10181
718e3744 10182DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10183 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10184 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10185 SHOW_STR
10186 IP_STR
10187 BGP_STR
8c3deaae
QY
10188 "Address Family\n"
10189 "Address Family\n"
718e3744 10190 "Address Family modifier\n"
10191 "Detailed information on TCP and BGP neighbor connections\n"
10192 "Neighbor to display information about\n"
10193 "Neighbor to display information about\n"
91d37724 10194 "Neighbor on BGP configured interface\n"
718e3744 10195 "Display information received from a BGP neighbor\n"
856ca177 10196 "Display the prefixlist filter\n"
9973d184 10197 JSON_STR)
718e3744 10198{
d62a17ae 10199 afi_t afi = AFI_IP6;
10200 safi_t safi = SAFI_UNICAST;
10201 char *peerstr = NULL;
10202
10203 char name[BUFSIZ];
10204 union sockunion su;
10205 struct peer *peer;
10206 int count, ret;
10207
10208 int idx = 0;
10209
10210 /* show [ip] bgp */
10211 if (argv_find(argv, argc, "ip", &idx))
10212 afi = AFI_IP;
10213 /* [<ipv4|ipv6> [unicast]] */
10214 if (argv_find(argv, argc, "ipv4", &idx))
10215 afi = AFI_IP;
10216 if (argv_find(argv, argc, "ipv6", &idx))
10217 afi = AFI_IP6;
10218 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10219 argv_find(argv, argc, "neighbors", &idx);
10220 peerstr = argv[++idx]->arg;
10221
10222 u_char uj = use_json(argc, argv);
10223
10224 ret = str2sockunion(peerstr, &su);
10225 if (ret < 0) {
10226 peer = peer_lookup_by_conf_if(NULL, peerstr);
10227 if (!peer) {
10228 if (uj)
10229 vty_out(vty, "{}\n");
10230 else
10231 vty_out(vty,
10232 "%% Malformed address or name: %s\n",
10233 peerstr);
10234 return CMD_WARNING;
10235 }
10236 } else {
10237 peer = peer_lookup(NULL, &su);
10238 if (!peer) {
10239 if (uj)
10240 vty_out(vty, "{}\n");
10241 else
10242 vty_out(vty, "No peer\n");
10243 return CMD_WARNING;
10244 }
10245 }
718e3744 10246
d62a17ae 10247 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10248 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10249 if (count) {
10250 if (!uj)
10251 vty_out(vty, "Address Family: %s\n",
10252 afi_safi_print(afi, safi));
10253 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10254 } else {
10255 if (uj)
10256 vty_out(vty, "{}\n");
10257 else
10258 vty_out(vty, "No functional output\n");
10259 }
718e3744 10260
d62a17ae 10261 return CMD_SUCCESS;
10262}
10263
10264static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10265 afi_t afi, safi_t safi,
10266 enum bgp_show_type type, u_char use_json)
10267{
8a893163
DW
10268 /* labeled-unicast routes live in the unicast table */
10269 if (safi == SAFI_LABELED_UNICAST)
10270 safi = SAFI_UNICAST;
10271
d62a17ae 10272 if (!peer || !peer->afc[afi][safi]) {
10273 if (use_json) {
10274 json_object *json_no = NULL;
10275 json_no = json_object_new_object();
10276 json_object_string_add(
10277 json_no, "warning",
10278 "No such neighbor or address family");
10279 vty_out(vty, "%s\n",
10280 json_object_to_json_string(json_no));
10281 json_object_free(json_no);
10282 } else
10283 vty_out(vty, "%% No such neighbor or address family\n");
10284 return CMD_WARNING;
10285 }
47fc97cc 10286
d62a17ae 10287 /* labeled-unicast routes live in the unicast table */
10288 if (safi == SAFI_LABELED_UNICAST)
10289 safi = SAFI_UNICAST;
019386c2 10290
d62a17ae 10291 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10292}
10293
10294DEFUN (show_ip_bgp_neighbor_routes,
10295 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10296 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10297 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10298 SHOW_STR
10299 IP_STR
10300 BGP_STR
8386ac43 10301 BGP_INSTANCE_HELP_STR
4f280b15 10302 BGP_AFI_HELP_STR
4dd6177e 10303 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10304 "Detailed information on TCP and BGP neighbor connections\n"
10305 "Neighbor to display information about\n"
10306 "Neighbor to display information about\n"
91d37724 10307 "Neighbor on BGP configured interface\n"
2525cf39 10308 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10309 "Display the dampened routes received from neighbor\n"
10310 "Display routes learned from neighbor\n"
9973d184 10311 JSON_STR)
718e3744 10312{
d62a17ae 10313 char *peerstr = NULL;
10314 struct bgp *bgp = NULL;
10315 afi_t afi = AFI_IP6;
10316 safi_t safi = SAFI_UNICAST;
10317 struct peer *peer;
10318 enum bgp_show_type sh_type = bgp_show_type_neighbor;
856ca177 10319
d62a17ae 10320 int idx = 0;
bb46e94f 10321
d62a17ae 10322 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10323 &bgp);
10324 if (!idx)
10325 return CMD_WARNING;
c493f2d8 10326
d62a17ae 10327 int uj = use_json(argc, argv);
10328 if (uj)
10329 argc--;
30a6a167 10330
d62a17ae 10331 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10332 argv_find(argv, argc, "neighbors", &idx);
10333 peerstr = argv[++idx]->arg;
8c3deaae 10334
d62a17ae 10335 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10336 if (!peer) {
10337 vty_out(vty, "No such neighbor\n");
10338 return CMD_WARNING;
10339 }
bb46e94f 10340
d62a17ae 10341 if (argv_find(argv, argc, "flap-statistics", &idx))
10342 sh_type = bgp_show_type_flap_neighbor;
10343 else if (argv_find(argv, argc, "dampened-routes", &idx))
10344 sh_type = bgp_show_type_damp_neighbor;
10345 else if (argv_find(argv, argc, "routes", &idx))
10346 sh_type = bgp_show_type_neighbor;
2525cf39 10347
d62a17ae 10348 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 10349}
6b0655a2 10350
734b349e 10351struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10352
d62a17ae 10353struct bgp_distance {
10354 /* Distance value for the IP source prefix. */
10355 u_char distance;
718e3744 10356
d62a17ae 10357 /* Name of the access-list to be matched. */
10358 char *access_list;
718e3744 10359};
10360
4f280b15
LB
10361DEFUN (show_bgp_afi_vpn_rd_route,
10362 show_bgp_afi_vpn_rd_route_cmd,
10363 "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]",
10364 SHOW_STR
10365 BGP_STR
10366 BGP_AFI_HELP_STR
10367 "Address Family modifier\n"
10368 "Display information for a route distinguisher\n"
10369 "Route Distinguisher\n"
7395a2c9
DS
10370 "Network in the BGP routing table to display\n"
10371 "Network in the BGP routing table to display\n"
10372 JSON_STR)
4f280b15 10373{
d62a17ae 10374 int ret;
10375 struct prefix_rd prd;
10376 afi_t afi = AFI_MAX;
10377 int idx = 0;
4f280b15 10378
d62a17ae 10379 argv_find_and_parse_afi(argv, argc, &idx, &afi);
10380 ret = str2prefix_rd(argv[5]->arg, &prd);
10381 if (!ret) {
10382 vty_out(vty, "%% Malformed Route Distinguisher\n");
10383 return CMD_WARNING;
10384 }
10385 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
10386 0, BGP_PATH_ALL, use_json(argc, argv));
4f280b15
LB
10387}
10388
d62a17ae 10389static struct bgp_distance *bgp_distance_new(void)
718e3744 10390{
d62a17ae 10391 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 10392}
10393
d62a17ae 10394static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 10395{
d62a17ae 10396 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 10397}
10398
d62a17ae 10399static int bgp_distance_set(struct vty *vty, const char *distance_str,
10400 const char *ip_str, const char *access_list_str)
718e3744 10401{
d62a17ae 10402 int ret;
10403 afi_t afi;
10404 safi_t safi;
10405 struct prefix p;
10406 u_char distance;
10407 struct bgp_node *rn;
10408 struct bgp_distance *bdistance;
718e3744 10409
d62a17ae 10410 afi = bgp_node_afi(vty);
10411 safi = bgp_node_safi(vty);
734b349e 10412
d62a17ae 10413 ret = str2prefix(ip_str, &p);
10414 if (ret == 0) {
10415 vty_out(vty, "Malformed prefix\n");
10416 return CMD_WARNING_CONFIG_FAILED;
10417 }
718e3744 10418
d62a17ae 10419 distance = atoi(distance_str);
718e3744 10420
d62a17ae 10421 /* Get BGP distance node. */
10422 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
10423 if (rn->info) {
10424 bdistance = rn->info;
10425 bgp_unlock_node(rn);
10426 } else {
10427 bdistance = bgp_distance_new();
10428 rn->info = bdistance;
10429 }
718e3744 10430
d62a17ae 10431 /* Set distance value. */
10432 bdistance->distance = distance;
718e3744 10433
d62a17ae 10434 /* Reset access-list configuration. */
10435 if (bdistance->access_list) {
10436 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10437 bdistance->access_list = NULL;
10438 }
10439 if (access_list_str)
10440 bdistance->access_list =
10441 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 10442
d62a17ae 10443 return CMD_SUCCESS;
718e3744 10444}
10445
d62a17ae 10446static int bgp_distance_unset(struct vty *vty, const char *distance_str,
10447 const char *ip_str, const char *access_list_str)
718e3744 10448{
d62a17ae 10449 int ret;
10450 afi_t afi;
10451 safi_t safi;
10452 struct prefix p;
10453 int distance;
10454 struct bgp_node *rn;
10455 struct bgp_distance *bdistance;
718e3744 10456
d62a17ae 10457 afi = bgp_node_afi(vty);
10458 safi = bgp_node_safi(vty);
734b349e 10459
d62a17ae 10460 ret = str2prefix(ip_str, &p);
10461 if (ret == 0) {
10462 vty_out(vty, "Malformed prefix\n");
10463 return CMD_WARNING_CONFIG_FAILED;
10464 }
718e3744 10465
d62a17ae 10466 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
10467 (struct prefix *)&p);
10468 if (!rn) {
10469 vty_out(vty, "Can't find specified prefix\n");
10470 return CMD_WARNING_CONFIG_FAILED;
10471 }
718e3744 10472
d62a17ae 10473 bdistance = rn->info;
10474 distance = atoi(distance_str);
1f9a9fff 10475
d62a17ae 10476 if (bdistance->distance != distance) {
10477 vty_out(vty, "Distance does not match configured\n");
10478 return CMD_WARNING_CONFIG_FAILED;
10479 }
718e3744 10480
d62a17ae 10481 if (bdistance->access_list)
10482 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10483 bgp_distance_free(bdistance);
718e3744 10484
d62a17ae 10485 rn->info = NULL;
10486 bgp_unlock_node(rn);
10487 bgp_unlock_node(rn);
718e3744 10488
d62a17ae 10489 return CMD_SUCCESS;
718e3744 10490}
10491
718e3744 10492/* Apply BGP information to distance method. */
d62a17ae 10493u_char bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
10494 safi_t safi, struct bgp *bgp)
10495{
10496 struct bgp_node *rn;
10497 struct prefix q;
10498 struct peer *peer;
10499 struct bgp_distance *bdistance;
10500 struct access_list *alist;
10501 struct bgp_static *bgp_static;
10502
10503 if (!bgp)
10504 return 0;
10505
10506 peer = rinfo->peer;
10507
10508 /* Check source address. */
10509 sockunion2hostprefix(&peer->su, &q);
10510 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
10511 if (rn) {
10512 bdistance = rn->info;
10513 bgp_unlock_node(rn);
10514
10515 if (bdistance->access_list) {
10516 alist = access_list_lookup(afi, bdistance->access_list);
10517 if (alist
10518 && access_list_apply(alist, p) == FILTER_PERMIT)
10519 return bdistance->distance;
10520 } else
10521 return bdistance->distance;
718e3744 10522 }
718e3744 10523
d62a17ae 10524 /* Backdoor check. */
10525 rn = bgp_node_lookup(bgp->route[afi][safi], p);
10526 if (rn) {
10527 bgp_static = rn->info;
10528 bgp_unlock_node(rn);
718e3744 10529
d62a17ae 10530 if (bgp_static->backdoor) {
10531 if (bgp->distance_local[afi][safi])
10532 return bgp->distance_local[afi][safi];
10533 else
10534 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10535 }
718e3744 10536 }
718e3744 10537
d62a17ae 10538 if (peer->sort == BGP_PEER_EBGP) {
10539 if (bgp->distance_ebgp[afi][safi])
10540 return bgp->distance_ebgp[afi][safi];
10541 return ZEBRA_EBGP_DISTANCE_DEFAULT;
10542 } else {
10543 if (bgp->distance_ibgp[afi][safi])
10544 return bgp->distance_ibgp[afi][safi];
10545 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10546 }
718e3744 10547}
10548
10549DEFUN (bgp_distance,
10550 bgp_distance_cmd,
6147e2c6 10551 "distance bgp (1-255) (1-255) (1-255)",
718e3744 10552 "Define an administrative distance\n"
10553 "BGP distance\n"
10554 "Distance for routes external to the AS\n"
10555 "Distance for routes internal to the AS\n"
10556 "Distance for local routes\n")
10557{
d62a17ae 10558 VTY_DECLVAR_CONTEXT(bgp, bgp);
10559 int idx_number = 2;
10560 int idx_number_2 = 3;
10561 int idx_number_3 = 4;
10562 afi_t afi;
10563 safi_t safi;
718e3744 10564
d62a17ae 10565 afi = bgp_node_afi(vty);
10566 safi = bgp_node_safi(vty);
718e3744 10567
d62a17ae 10568 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
10569 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
10570 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
10571 return CMD_SUCCESS;
718e3744 10572}
10573
10574DEFUN (no_bgp_distance,
10575 no_bgp_distance_cmd,
a636c635 10576 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 10577 NO_STR
10578 "Define an administrative distance\n"
10579 "BGP distance\n"
10580 "Distance for routes external to the AS\n"
10581 "Distance for routes internal to the AS\n"
10582 "Distance for local routes\n")
10583{
d62a17ae 10584 VTY_DECLVAR_CONTEXT(bgp, bgp);
10585 afi_t afi;
10586 safi_t safi;
718e3744 10587
d62a17ae 10588 afi = bgp_node_afi(vty);
10589 safi = bgp_node_safi(vty);
718e3744 10590
d62a17ae 10591 bgp->distance_ebgp[afi][safi] = 0;
10592 bgp->distance_ibgp[afi][safi] = 0;
10593 bgp->distance_local[afi][safi] = 0;
10594 return CMD_SUCCESS;
718e3744 10595}
10596
718e3744 10597
10598DEFUN (bgp_distance_source,
10599 bgp_distance_source_cmd,
6147e2c6 10600 "distance (1-255) A.B.C.D/M",
718e3744 10601 "Define an administrative distance\n"
10602 "Administrative distance\n"
10603 "IP source prefix\n")
10604{
d62a17ae 10605 int idx_number = 1;
10606 int idx_ipv4_prefixlen = 2;
10607 bgp_distance_set(vty, argv[idx_number]->arg,
10608 argv[idx_ipv4_prefixlen]->arg, NULL);
10609 return CMD_SUCCESS;
718e3744 10610}
10611
10612DEFUN (no_bgp_distance_source,
10613 no_bgp_distance_source_cmd,
6147e2c6 10614 "no distance (1-255) A.B.C.D/M",
718e3744 10615 NO_STR
10616 "Define an administrative distance\n"
10617 "Administrative distance\n"
10618 "IP source prefix\n")
10619{
d62a17ae 10620 int idx_number = 2;
10621 int idx_ipv4_prefixlen = 3;
10622 bgp_distance_unset(vty, argv[idx_number]->arg,
10623 argv[idx_ipv4_prefixlen]->arg, NULL);
10624 return CMD_SUCCESS;
718e3744 10625}
10626
10627DEFUN (bgp_distance_source_access_list,
10628 bgp_distance_source_access_list_cmd,
6147e2c6 10629 "distance (1-255) A.B.C.D/M WORD",
718e3744 10630 "Define an administrative distance\n"
10631 "Administrative distance\n"
10632 "IP source prefix\n"
10633 "Access list name\n")
10634{
d62a17ae 10635 int idx_number = 1;
10636 int idx_ipv4_prefixlen = 2;
10637 int idx_word = 3;
10638 bgp_distance_set(vty, argv[idx_number]->arg,
10639 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
10640 return CMD_SUCCESS;
718e3744 10641}
10642
10643DEFUN (no_bgp_distance_source_access_list,
10644 no_bgp_distance_source_access_list_cmd,
6147e2c6 10645 "no distance (1-255) A.B.C.D/M WORD",
718e3744 10646 NO_STR
10647 "Define an administrative distance\n"
10648 "Administrative distance\n"
10649 "IP source prefix\n"
10650 "Access list name\n")
10651{
d62a17ae 10652 int idx_number = 2;
10653 int idx_ipv4_prefixlen = 3;
10654 int idx_word = 4;
10655 bgp_distance_unset(vty, argv[idx_number]->arg,
10656 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
10657 return CMD_SUCCESS;
718e3744 10658}
6b0655a2 10659
734b349e
MZ
10660DEFUN (ipv6_bgp_distance_source,
10661 ipv6_bgp_distance_source_cmd,
39e92c06 10662 "distance (1-255) X:X::X:X/M",
734b349e
MZ
10663 "Define an administrative distance\n"
10664 "Administrative distance\n"
10665 "IP source prefix\n")
10666{
d62a17ae 10667 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
10668 return CMD_SUCCESS;
734b349e
MZ
10669}
10670
10671DEFUN (no_ipv6_bgp_distance_source,
10672 no_ipv6_bgp_distance_source_cmd,
39e92c06 10673 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
10674 NO_STR
10675 "Define an administrative distance\n"
10676 "Administrative distance\n"
10677 "IP source prefix\n")
10678{
d62a17ae 10679 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
10680 return CMD_SUCCESS;
734b349e
MZ
10681}
10682
10683DEFUN (ipv6_bgp_distance_source_access_list,
10684 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10685 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10686 "Define an administrative distance\n"
10687 "Administrative distance\n"
10688 "IP source prefix\n"
10689 "Access list name\n")
10690{
d62a17ae 10691 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
10692 return CMD_SUCCESS;
734b349e
MZ
10693}
10694
10695DEFUN (no_ipv6_bgp_distance_source_access_list,
10696 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10697 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10698 NO_STR
10699 "Define an administrative distance\n"
10700 "Administrative distance\n"
10701 "IP source prefix\n"
10702 "Access list name\n")
10703{
d62a17ae 10704 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
10705 return CMD_SUCCESS;
734b349e
MZ
10706}
10707
718e3744 10708DEFUN (bgp_damp_set,
10709 bgp_damp_set_cmd,
31500417 10710 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10711 "BGP Specific commands\n"
10712 "Enable route-flap dampening\n"
10713 "Half-life time for the penalty\n"
10714 "Value to start reusing a route\n"
10715 "Value to start suppressing a route\n"
10716 "Maximum duration to suppress a stable route\n")
10717{
d62a17ae 10718 VTY_DECLVAR_CONTEXT(bgp, bgp);
10719 int idx_half_life = 2;
10720 int idx_reuse = 3;
10721 int idx_suppress = 4;
10722 int idx_max_suppress = 5;
10723 int half = DEFAULT_HALF_LIFE * 60;
10724 int reuse = DEFAULT_REUSE;
10725 int suppress = DEFAULT_SUPPRESS;
10726 int max = 4 * half;
10727
10728 if (argc == 6) {
10729 half = atoi(argv[idx_half_life]->arg) * 60;
10730 reuse = atoi(argv[idx_reuse]->arg);
10731 suppress = atoi(argv[idx_suppress]->arg);
10732 max = atoi(argv[idx_max_suppress]->arg) * 60;
10733 } else if (argc == 3) {
10734 half = atoi(argv[idx_half_life]->arg) * 60;
10735 max = 4 * half;
10736 }
718e3744 10737
d62a17ae 10738 if (suppress < reuse) {
10739 vty_out(vty,
10740 "Suppress value cannot be less than reuse value \n");
10741 return 0;
10742 }
7ebe9748 10743
d62a17ae 10744 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
10745 reuse, suppress, max);
718e3744 10746}
10747
718e3744 10748DEFUN (bgp_damp_unset,
10749 bgp_damp_unset_cmd,
d04c479d 10750 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10751 NO_STR
10752 "BGP Specific commands\n"
16cedbb0
QY
10753 "Enable route-flap dampening\n"
10754 "Half-life time for the penalty\n"
10755 "Value to start reusing a route\n"
10756 "Value to start suppressing a route\n"
10757 "Maximum duration to suppress a stable route\n")
718e3744 10758{
d62a17ae 10759 VTY_DECLVAR_CONTEXT(bgp, bgp);
10760 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 10761}
10762
718e3744 10763/* Display specified route of BGP table. */
d62a17ae 10764static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
10765 const char *ip_str, afi_t afi, safi_t safi,
10766 struct prefix_rd *prd, int prefix_check)
10767{
10768 int ret;
10769 struct prefix match;
10770 struct bgp_node *rn;
10771 struct bgp_node *rm;
10772 struct bgp_info *ri;
10773 struct bgp_info *ri_temp;
10774 struct bgp *bgp;
10775 struct bgp_table *table;
10776
10777 /* BGP structure lookup. */
10778 if (view_name) {
10779 bgp = bgp_lookup_by_name(view_name);
10780 if (bgp == NULL) {
10781 vty_out(vty, "%% Can't find BGP instance %s\n",
10782 view_name);
10783 return CMD_WARNING;
10784 }
10785 } else {
10786 bgp = bgp_get_default();
10787 if (bgp == NULL) {
10788 vty_out(vty, "%% No BGP process is configured\n");
10789 return CMD_WARNING;
10790 }
718e3744 10791 }
718e3744 10792
d62a17ae 10793 /* Check IP address argument. */
10794 ret = str2prefix(ip_str, &match);
10795 if (!ret) {
10796 vty_out(vty, "%% address is malformed\n");
10797 return CMD_WARNING;
10798 }
718e3744 10799
d62a17ae 10800 match.family = afi2family(afi);
10801
10802 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
10803 || (safi == SAFI_EVPN)) {
10804 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
10805 rn = bgp_route_next(rn)) {
10806 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
10807 continue;
10808
10809 if ((table = rn->info) != NULL)
10810 if ((rm = bgp_node_match(table, &match))
10811 != NULL) {
10812 if (!prefix_check
10813 || rm->p.prefixlen
10814 == match.prefixlen) {
10815 ri = rm->info;
10816 while (ri) {
10817 if (ri->extra
10818 && ri->extra
10819 ->damp_info) {
10820 ri_temp =
10821 ri->next;
10822 bgp_damp_info_free(
10823 ri->extra
10824 ->damp_info,
10825 1);
10826 ri = ri_temp;
10827 } else
10828 ri = ri->next;
10829 }
10830 }
10831
10832 bgp_unlock_node(rm);
10833 }
10834 }
10835 } else {
10836 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
10837 != NULL) {
10838 if (!prefix_check
10839 || rn->p.prefixlen == match.prefixlen) {
10840 ri = rn->info;
10841 while (ri) {
10842 if (ri->extra && ri->extra->damp_info) {
10843 ri_temp = ri->next;
10844 bgp_damp_info_free(
10845 ri->extra->damp_info,
10846 1);
10847 ri = ri_temp;
10848 } else
10849 ri = ri->next;
10850 }
10851 }
10852
10853 bgp_unlock_node(rn);
10854 }
10855 }
718e3744 10856
d62a17ae 10857 return CMD_SUCCESS;
718e3744 10858}
10859
10860DEFUN (clear_ip_bgp_dampening,
10861 clear_ip_bgp_dampening_cmd,
10862 "clear ip bgp dampening",
10863 CLEAR_STR
10864 IP_STR
10865 BGP_STR
10866 "Clear route flap dampening information\n")
10867{
d62a17ae 10868 bgp_damp_info_clean();
10869 return CMD_SUCCESS;
718e3744 10870}
10871
10872DEFUN (clear_ip_bgp_dampening_prefix,
10873 clear_ip_bgp_dampening_prefix_cmd,
10874 "clear ip bgp dampening A.B.C.D/M",
10875 CLEAR_STR
10876 IP_STR
10877 BGP_STR
10878 "Clear route flap dampening information\n"
0c7b1b01 10879 "IPv4 prefix\n")
718e3744 10880{
d62a17ae 10881 int idx_ipv4_prefixlen = 4;
10882 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
10883 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 10884}
10885
10886DEFUN (clear_ip_bgp_dampening_address,
10887 clear_ip_bgp_dampening_address_cmd,
10888 "clear ip bgp dampening A.B.C.D",
10889 CLEAR_STR
10890 IP_STR
10891 BGP_STR
10892 "Clear route flap dampening information\n"
10893 "Network to clear damping information\n")
10894{
d62a17ae 10895 int idx_ipv4 = 4;
10896 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
10897 SAFI_UNICAST, NULL, 0);
718e3744 10898}
10899
10900DEFUN (clear_ip_bgp_dampening_address_mask,
10901 clear_ip_bgp_dampening_address_mask_cmd,
10902 "clear ip bgp dampening A.B.C.D A.B.C.D",
10903 CLEAR_STR
10904 IP_STR
10905 BGP_STR
10906 "Clear route flap dampening information\n"
10907 "Network to clear damping information\n"
10908 "Network mask\n")
10909{
d62a17ae 10910 int idx_ipv4 = 4;
10911 int idx_ipv4_2 = 5;
10912 int ret;
10913 char prefix_str[BUFSIZ];
718e3744 10914
d62a17ae 10915 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
10916 prefix_str);
10917 if (!ret) {
10918 vty_out(vty, "%% Inconsistent address and mask\n");
10919 return CMD_WARNING;
10920 }
718e3744 10921
d62a17ae 10922 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
10923 NULL, 0);
718e3744 10924}
6b0655a2 10925
587ff0fd 10926/* also used for encap safi */
d62a17ae 10927static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
10928 afi_t afi, safi_t safi, int *write)
10929{
10930 struct bgp_node *prn;
10931 struct bgp_node *rn;
10932 struct bgp_table *table;
10933 struct prefix *p;
10934 struct prefix_rd *prd;
10935 struct bgp_static *bgp_static;
10936 mpls_label_t label;
10937 char buf[SU_ADDRSTRLEN];
10938 char rdbuf[RD_ADDRSTRLEN];
10939
10940 /* Network configuration. */
10941 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
10942 prn = bgp_route_next(prn))
10943 if ((table = prn->info) != NULL)
10944 for (rn = bgp_table_top(table); rn;
10945 rn = bgp_route_next(rn))
10946 if ((bgp_static = rn->info) != NULL) {
10947 p = &rn->p;
10948 prd = (struct prefix_rd *)&prn->p;
10949
10950 /* "address-family" display. */
10951 bgp_config_write_family_header(
10952 vty, afi, safi, write);
10953
10954 /* "network" configuration display. */
10955 prefix_rd2str(prd, rdbuf,
10956 RD_ADDRSTRLEN);
10957 label = decode_label(
10958 &bgp_static->label);
10959
10960 vty_out(vty, " network %s/%d rd %s",
10961 inet_ntop(p->family,
10962 &p->u.prefix, buf,
10963 SU_ADDRSTRLEN),
10964 p->prefixlen, rdbuf);
10965 if (safi == SAFI_MPLS_VPN)
10966 vty_out(vty, " label %u",
10967 label);
10968
10969 if (bgp_static->rmap.name)
10970 vty_out(vty, " route-map %s",
10971 bgp_static->rmap.name);
10972 else {
10973 if (bgp_static->backdoor)
10974 vty_out(vty,
10975 " backdoor");
10976 }
10977 vty_out(vty, "\n");
10978 }
10979 return 0;
10980}
10981
10982static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
10983 afi_t afi, safi_t safi, int *write)
10984{
10985 struct bgp_node *prn;
10986 struct bgp_node *rn;
10987 struct bgp_table *table;
10988 struct prefix *p;
10989 struct prefix_rd *prd;
10990 struct bgp_static *bgp_static;
10991 char buf[PREFIX_STRLEN];
10992 char buf2[SU_ADDRSTRLEN];
10993 char rdbuf[RD_ADDRSTRLEN];
10994
10995 /* Network configuration. */
10996 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
10997 prn = bgp_route_next(prn))
10998 if ((table = prn->info) != NULL)
10999 for (rn = bgp_table_top(table); rn;
11000 rn = bgp_route_next(rn))
11001 if ((bgp_static = rn->info) != NULL) {
11002 char *macrouter = NULL;
11003 char *esi = NULL;
11004
11005 if (bgp_static->router_mac)
11006 macrouter = prefix_mac2str(
11007 bgp_static->router_mac,
11008 NULL, 0);
11009 if (bgp_static->eth_s_id)
11010 esi = esi2str(
11011 bgp_static->eth_s_id);
11012 p = &rn->p;
11013 prd = (struct prefix_rd *)&prn->p;
11014
11015 /* "address-family" display. */
11016 bgp_config_write_family_header(
11017 vty, afi, safi, write);
11018
11019 /* "network" configuration display. */
11020 prefix_rd2str(prd, rdbuf,
11021 RD_ADDRSTRLEN);
11022
11023 inet_ntop(AF_INET,
11024 &bgp_static->igpnexthop, buf2,
11025 SU_ADDRSTRLEN);
11026
11027 prefix2str(p, buf, sizeof(buf)),
11028 vty_out(vty,
11029 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
11030 buf, rdbuf,
11031 p->u.prefix_evpn
11032 .eth_tag,
11033 decode_label(
11034 &bgp_static
11035 ->label),
11036 esi, buf2, macrouter);
11037 vty_out(vty, "\n");
11038 if (macrouter)
11039 XFREE(MTYPE_TMP, macrouter);
11040 if (esi)
11041 XFREE(MTYPE_TMP, esi);
11042 }
11043 return 0;
3da6fcd5
PG
11044}
11045
718e3744 11046/* Configuration of static route announcement and aggregate
11047 information. */
d62a17ae 11048int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11049 safi_t safi, int *write)
11050{
11051 struct bgp_node *rn;
11052 struct prefix *p;
11053 struct bgp_static *bgp_static;
11054 struct bgp_aggregate *bgp_aggregate;
11055 char buf[SU_ADDRSTRLEN];
11056
11057 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
11058 return bgp_config_write_network_vpn(vty, bgp, afi, safi, write);
11059
11060 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
11061 return bgp_config_write_network_evpn(vty, bgp, afi, safi,
11062 write);
11063
11064 /* Network configuration. */
11065 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
11066 rn = bgp_route_next(rn))
11067 if ((bgp_static = rn->info) != NULL) {
11068 p = &rn->p;
11069
11070 /* "address-family" display. */
11071 bgp_config_write_family_header(vty, afi, safi, write);
11072
11073 /* "network" configuration display. */
11074 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
11075 && afi == AFI_IP) {
11076 u_int32_t destination;
11077 struct in_addr netmask;
11078
11079 destination = ntohl(p->u.prefix4.s_addr);
11080 masklen2ip(p->prefixlen, &netmask);
11081 vty_out(vty, " network %s",
11082 inet_ntop(p->family, &p->u.prefix, buf,
11083 SU_ADDRSTRLEN));
11084
11085 if ((IN_CLASSC(destination)
11086 && p->prefixlen == 24)
11087 || (IN_CLASSB(destination)
11088 && p->prefixlen == 16)
11089 || (IN_CLASSA(destination)
11090 && p->prefixlen == 8)
11091 || p->u.prefix4.s_addr == 0) {
11092 /* Natural mask is not display. */
11093 } else
11094 vty_out(vty, " mask %s",
11095 inet_ntoa(netmask));
11096 } else {
11097 vty_out(vty, " network %s/%d",
11098 inet_ntop(p->family, &p->u.prefix, buf,
11099 SU_ADDRSTRLEN),
11100 p->prefixlen);
11101 }
11102
11103 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11104 vty_out(vty, " label-index %u",
11105 bgp_static->label_index);
11106
11107 if (bgp_static->rmap.name)
11108 vty_out(vty, " route-map %s",
11109 bgp_static->rmap.name);
11110 else {
11111 if (bgp_static->backdoor)
11112 vty_out(vty, " backdoor");
11113 }
11114
11115 vty_out(vty, "\n");
11116 }
718e3744 11117
d62a17ae 11118 /* Aggregate-address configuration. */
11119 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
11120 rn = bgp_route_next(rn))
11121 if ((bgp_aggregate = rn->info) != NULL) {
11122 p = &rn->p;
11123
11124 /* "address-family" display. */
11125 bgp_config_write_family_header(vty, afi, safi, write);
11126
11127 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
11128 && afi == AFI_IP) {
11129 struct in_addr netmask;
11130
11131 masklen2ip(p->prefixlen, &netmask);
11132 vty_out(vty, " aggregate-address %s %s",
11133 inet_ntop(p->family, &p->u.prefix, buf,
11134 SU_ADDRSTRLEN),
11135 inet_ntoa(netmask));
11136 } else {
11137 vty_out(vty, " aggregate-address %s/%d",
11138 inet_ntop(p->family, &p->u.prefix, buf,
11139 SU_ADDRSTRLEN),
11140 p->prefixlen);
11141 }
11142
11143 if (bgp_aggregate->as_set)
11144 vty_out(vty, " as-set");
11145
11146 if (bgp_aggregate->summary_only)
11147 vty_out(vty, " summary-only");
11148
11149 vty_out(vty, "\n");
11150 }
718e3744 11151
d62a17ae 11152 return 0;
11153}
734b349e 11154
d62a17ae 11155int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
11156 safi_t safi, int *write)
11157{
11158 struct bgp_node *rn;
11159 struct bgp_distance *bdistance;
11160
11161 /* Distance configuration. */
11162 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11163 && bgp->distance_local[afi][safi]
11164 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11165 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11166 || bgp->distance_local[afi][safi]
11167 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
11168 bgp_config_write_family_header(vty, afi, safi, write);
11169 vty_out(vty, " distance bgp %d %d %d\n",
11170 bgp->distance_ebgp[afi][safi],
11171 bgp->distance_ibgp[afi][safi],
11172 bgp->distance_local[afi][safi]);
11173 }
734b349e 11174
d62a17ae 11175 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
11176 rn = bgp_route_next(rn))
11177 if ((bdistance = rn->info) != NULL) {
11178 char buf[PREFIX_STRLEN];
11179
11180 bgp_config_write_family_header(vty, afi, safi, write);
11181 vty_out(vty, " distance %d %s %s\n",
11182 bdistance->distance,
11183 prefix2str(&rn->p, buf, sizeof(buf)),
11184 bdistance->access_list ? bdistance->access_list
11185 : "");
11186 }
718e3744 11187
d62a17ae 11188 return *write;
718e3744 11189}
11190
11191/* Allocate routing table structure and install commands. */
d62a17ae 11192void bgp_route_init(void)
11193{
11194 afi_t afi;
11195 safi_t safi;
11196
11197 /* Init BGP distance table. */
11198 for (afi = AFI_IP; afi < AFI_MAX; afi++)
11199 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
11200 bgp_distance_table[afi][safi] =
11201 bgp_table_init(afi, safi);
11202
11203 /* IPv4 BGP commands. */
11204 install_element(BGP_NODE, &bgp_table_map_cmd);
11205 install_element(BGP_NODE, &bgp_network_cmd);
11206 install_element(BGP_NODE, &bgp_network_mask_cmd);
11207 install_element(BGP_NODE, &bgp_network_mask_natural_cmd);
11208 install_element(BGP_NODE, &bgp_network_route_map_cmd);
11209 install_element(BGP_NODE, &bgp_network_mask_route_map_cmd);
11210 install_element(BGP_NODE, &bgp_network_mask_natural_route_map_cmd);
11211 install_element(BGP_NODE, &bgp_network_backdoor_cmd);
11212 install_element(BGP_NODE, &bgp_network_mask_backdoor_cmd);
11213 install_element(BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
11214 install_element(BGP_NODE, &no_bgp_table_map_cmd);
11215 install_element(BGP_NODE, &no_bgp_network_cmd);
11216 install_element(BGP_NODE, &no_bgp_network_mask_cmd);
11217 install_element(BGP_NODE, &no_bgp_network_mask_natural_cmd);
11218
11219 install_element(BGP_NODE, &aggregate_address_cmd);
11220 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11221 install_element(BGP_NODE, &no_aggregate_address_cmd);
11222 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11223
11224 /* IPv4 unicast configuration. */
11225 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11226 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
11227 install_element(BGP_IPV4_NODE, &bgp_network_mask_cmd);
11228 install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_cmd);
11229 install_element(BGP_IPV4_NODE, &bgp_network_route_map_cmd);
11230 install_element(BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
11231 install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
11232 install_element(BGP_IPV4_NODE, &bgp_network_label_index_cmd);
11233 install_element(BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd);
11234 install_element(BGP_IPV4_NODE, &no_bgp_network_label_index_cmd);
11235 install_element(BGP_IPV4_NODE,
11236 &no_bgp_network_label_index_route_map_cmd);
11237 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
11238 install_element(BGP_IPV4_NODE, &no_bgp_network_cmd);
11239 install_element(BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
11240 install_element(BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
11241
11242 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11243 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11244 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11245 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11246
11247 /* IPv4 multicast configuration. */
11248 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11249 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
11250 install_element(BGP_IPV4M_NODE, &bgp_network_mask_cmd);
11251 install_element(BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd);
11252 install_element(BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
11253 install_element(BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
11254 install_element(BGP_IPV4M_NODE,
11255 &bgp_network_mask_natural_route_map_cmd);
11256 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
11257 install_element(BGP_IPV4M_NODE, &no_bgp_network_cmd);
11258 install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
11259 install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
11260 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11261 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11262 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11263 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11264
11265 /* IPv4 labeled-unicast configuration. */
11266 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11267 install_element(VIEW_NODE, &show_ip_bgp_cmd);
11268 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11269 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11270
11271 install_element(VIEW_NODE,
11272 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11273 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11274 install_element(VIEW_NODE,
11275 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11276#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11277 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11278#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11279 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11280 install_element(VIEW_NODE,
11281 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11282
d62a17ae 11283 /* BGP dampening clear commands */
11284 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11285 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11286
d62a17ae 11287 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11288 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11289
11290 /* prefix count */
11291 install_element(ENABLE_NODE,
11292 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11293#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11294 install_element(ENABLE_NODE,
11295 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11296#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11297
d62a17ae 11298 /* New config IPv6 BGP commands. */
11299 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11300 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
11301 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
11302 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
11303 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
11304 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd);
11305 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd);
11306 install_element(BGP_IPV6_NODE,
11307 &ipv6_bgp_network_label_index_route_map_cmd);
11308 install_element(BGP_IPV6_NODE,
11309 &no_ipv6_bgp_network_label_index_route_map_cmd);
11310
11311 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11312 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11313
11314 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
11315 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
11316
11317 install_element(BGP_IPV6L_NODE, &bgp_table_map_cmd);
11318 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
11319 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_route_map_cmd);
11320 install_element(BGP_IPV6L_NODE, &no_bgp_table_map_cmd);
11321 install_element(BGP_IPV6L_NODE, &no_ipv6_bgp_network_cmd);
11322
11323 install_element(BGP_NODE, &bgp_distance_cmd);
11324 install_element(BGP_NODE, &no_bgp_distance_cmd);
11325 install_element(BGP_NODE, &bgp_distance_source_cmd);
11326 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11327 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11328 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11329 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11330 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11331 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11332 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11333 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11334 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11335 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11336 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11337 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11338 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11339 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11340 install_element(BGP_IPV4M_NODE,
11341 &no_bgp_distance_source_access_list_cmd);
11342 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11343 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11344 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11345 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11346 install_element(BGP_IPV6_NODE,
11347 &ipv6_bgp_distance_source_access_list_cmd);
11348 install_element(BGP_IPV6_NODE,
11349 &no_ipv6_bgp_distance_source_access_list_cmd);
11350 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11351 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11352 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11353 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11354 install_element(BGP_IPV6M_NODE,
11355 &ipv6_bgp_distance_source_access_list_cmd);
11356 install_element(BGP_IPV6M_NODE,
11357 &no_ipv6_bgp_distance_source_access_list_cmd);
11358
11359 install_element(BGP_NODE, &bgp_damp_set_cmd);
11360 install_element(BGP_NODE, &bgp_damp_unset_cmd);
11361 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
11362 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
11363
11364 /* IPv4 Multicast Mode */
11365 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
11366 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
11367
11368 /* Large Communities */
11369 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11370 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
11371}
11372
11373void bgp_route_finish(void)
11374{
11375 afi_t afi;
11376 safi_t safi;
11377
11378 for (afi = AFI_IP; afi < AFI_MAX; afi++)
11379 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
11380 bgp_table_unlock(bgp_distance_table[afi][safi]);
11381 bgp_distance_table[afi][safi] = NULL;
11382 }
228da428 11383}