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