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