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