]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #1527 from donaldsharp/zserv_thread
[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_info info;
1161 route_map_result_t ret;
1162 struct route_map *rmap = NULL;
0f672529 1163 u_char rmap_type;
0b16f239 1164
b787157a
DS
1165 /*
1166 * So if we get to this point and have no rmap_name
1167 * we want to just show the output as it currently
1168 * exists.
1169 */
1170 if (!rmap_name)
1171 return RMAP_PERMIT;
0b16f239 1172
d62a17ae 1173 /* Apply default weight value. */
1174 if (peer->weight[afi][safi])
1175 attr->weight = peer->weight[afi][safi];
0b16f239 1176
b787157a 1177 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1178
b787157a
DS
1179 /*
1180 * If we have a route map name and we do not find
1181 * the routemap that means we have an implicit
1182 * deny.
1183 */
1184 if (rmap == NULL)
1185 return RMAP_DENY;
0b16f239 1186
d62a17ae 1187 /* Route map apply. */
b787157a
DS
1188 /* Duplicate current value to new strucutre for modification. */
1189 info.peer = peer;
1190 info.attr = attr;
0b16f239 1191
0f672529 1192 rmap_type = peer->rmap_type;
b787157a 1193 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1194
b787157a
DS
1195 /* Apply BGP route map to the attribute. */
1196 ret = route_map_apply(rmap, p, RMAP_BGP, &info);
ac41b2a2 1197
0f672529 1198 peer->rmap_type = rmap_type;
b787157a
DS
1199
1200 if (ret == RMAP_DENYMATCH)
1201 /*
1202 * caller has multiple error paths with bgp_attr_flush()
1203 */
1204 return RMAP_DENY;
ac41b2a2 1205
d62a17ae 1206 return RMAP_PERMIT;
718e3744 1207}
6b0655a2 1208
5000f21c 1209/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1210static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1211 struct peer *peer, struct attr *attr)
1212{
1213 if (peer->sort == BGP_PEER_EBGP
1214 && (peer_af_flag_check(peer, afi, safi,
1215 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1216 || peer_af_flag_check(peer, afi, safi,
1217 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1218 || peer_af_flag_check(peer, afi, safi,
1219 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1220 || peer_af_flag_check(peer, afi, safi,
1221 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1222 // Take action on the entire aspath
1223 if (peer_af_flag_check(peer, afi, safi,
1224 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1225 || peer_af_flag_check(peer, afi, safi,
1226 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1227 if (peer_af_flag_check(
1228 peer, afi, safi,
1229 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1230 attr->aspath = aspath_replace_private_asns(
1231 attr->aspath, bgp->as);
1232
1233 // The entire aspath consists of private ASNs so create
1234 // an empty aspath
1235 else if (aspath_private_as_check(attr->aspath))
1236 attr->aspath = aspath_empty_get();
1237
1238 // There are some public and some private ASNs, remove
1239 // the private ASNs
1240 else
1241 attr->aspath = aspath_remove_private_asns(
1242 attr->aspath);
1243 }
1244
1245 // 'all' was not specified so the entire aspath must be private
1246 // ASNs
1247 // for us to do anything
1248 else if (aspath_private_as_check(attr->aspath)) {
1249 if (peer_af_flag_check(
1250 peer, afi, safi,
1251 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1252 attr->aspath = aspath_replace_private_asns(
1253 attr->aspath, bgp->as);
1254 else
1255 attr->aspath = aspath_empty_get();
1256 }
1257 }
5000f21c
DS
1258}
1259
c7122e14 1260/* If this is an EBGP peer with as-override */
d62a17ae 1261static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1262 struct peer *peer, struct attr *attr)
1263{
1264 if (peer->sort == BGP_PEER_EBGP
1265 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1266 if (aspath_single_asn_check(attr->aspath, peer->as))
1267 attr->aspath = aspath_replace_specific_asn(
1268 attr->aspath, peer->as, bgp->as);
1269 }
1270}
1271
7f323236
DW
1272void bgp_attr_add_gshut_community(struct attr *attr)
1273{
1274 struct community *old;
1275 struct community *new;
1276 struct community *merge;
1277 struct community *gshut;
1278
1279 old = attr->community;
1280 gshut = community_str2com("graceful-shutdown");
1281
1282 if (old) {
1283 merge = community_merge(community_dup(old), gshut);
1284
1285 if (old->refcnt== 0)
1286 community_free(old);
1287
1288 new = community_uniq_sort(merge);
1289 community_free(merge);
1290 } else {
1291 new = community_dup(gshut);
1292 }
1293
1294 community_free(gshut);
1295 attr->community = new;
1296 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1297
1298 /* When we add the graceful-shutdown community we must also
1299 * lower the local-preference */
1300 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1301 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1302}
1303
1304
d62a17ae 1305static void subgroup_announce_reset_nhop(u_char family, struct attr *attr)
c7122e14 1306{
d62a17ae 1307 if (family == AF_INET)
1308 attr->nexthop.s_addr = 0;
1309 if (family == AF_INET6)
1310 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
c7122e14
DS
1311}
1312
d62a17ae 1313int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
1314 struct update_subgroup *subgrp, struct prefix *p,
1315 struct attr *attr)
1316{
1317 struct bgp_filter *filter;
1318 struct peer *from;
1319 struct peer *peer;
1320 struct peer *onlypeer;
1321 struct bgp *bgp;
1322 struct attr *riattr;
d62a17ae 1323 char buf[PREFIX_STRLEN];
1324 int ret;
1325 int transparent;
1326 int reflect;
1327 afi_t afi;
1328 safi_t safi;
1329 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
1330
1331 if (DISABLE_BGP_ANNOUNCE)
1332 return 0;
1333
1334 afi = SUBGRP_AFI(subgrp);
1335 safi = SUBGRP_SAFI(subgrp);
1336 peer = SUBGRP_PEER(subgrp);
1337 onlypeer = NULL;
1338 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1339 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1340
1341 from = ri->peer;
1342 filter = &peer->filter[afi][safi];
1343 bgp = SUBGRP_INST(subgrp);
1344 riattr = bgp_info_mpath_count(ri) ? bgp_info_mpath_attr(ri) : ri->attr;
3f9c7369 1345
65efcfce 1346#if ENABLE_BGP_VNC
d62a17ae 1347 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
1348 && ((ri->type == ZEBRA_ROUTE_BGP_DIRECT)
1349 || (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
1350
1351 /*
1352 * direct and direct_ext type routes originate internally even
1353 * though they can have peer pointers that reference other
1354 * systems
1355 */
1356 prefix2str(p, buf, PREFIX_STRLEN);
1357 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1358 __func__, buf);
1359 samepeer_safe = 1;
1360 }
65efcfce
LB
1361#endif
1362
d62a17ae 1363 /* With addpath we may be asked to TX all kinds of paths so make sure
1364 * ri is valid */
1365 if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID)
1366 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)
1367 || CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
1368 return 0;
1369 }
adbac85e 1370
d62a17ae 1371 /* If this is not the bestpath then check to see if there is an enabled
1372 * addpath
1373 * feature that requires us to advertise it */
1374 if (!CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
1375 if (!bgp_addpath_tx_path(peer, afi, safi, ri)) {
1376 return 0;
1377 }
1378 }
06370dac 1379
d62a17ae 1380 /* Aggregate-address suppress check. */
1381 if (ri->extra && ri->extra->suppress)
1382 if (!UNSUPPRESS_MAP_NAME(filter)) {
1383 return 0;
1384 }
3f9c7369 1385
d62a17ae 1386 /* If it's labeled safi, make sure the route has a valid label. */
1387 if (safi == SAFI_LABELED_UNICAST) {
1388 mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi);
1389 if (!bgp_is_valid_label(&label)) {
1390 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1391 zlog_debug("u%" PRIu64 ":s%" PRIu64
1392 " %s/%d is filtered - no label (%p)",
1393 subgrp->update_group->id, subgrp->id,
1394 inet_ntop(p->family, &p->u.prefix,
1395 buf, SU_ADDRSTRLEN),
1396 p->prefixlen, &label);
1397 return 0;
1398 }
1399 }
cd1964ff 1400
d62a17ae 1401 /* Do not send back route to sender. */
1402 if (onlypeer && from == onlypeer) {
1403 return 0;
1404 }
3f9c7369 1405
d62a17ae 1406 /* Do not send the default route in the BGP table if the neighbor is
1407 * configured for default-originate */
1408 if (CHECK_FLAG(peer->af_flags[afi][safi],
1409 PEER_FLAG_DEFAULT_ORIGINATE)) {
1410 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
1411 return 0;
1412 else if (p->family == AF_INET6 && p->prefixlen == 0)
1413 return 0;
1414 }
4125bb67 1415
d62a17ae 1416 /* Transparency check. */
1417 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1418 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1419 transparent = 1;
1420 else
1421 transparent = 0;
1422
1423 /* If community is not disabled check the no-export and local. */
1424 if (!transparent && bgp_community_filter(peer, riattr)) {
1425 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1426 zlog_debug(
1427 "subgrpannouncecheck: community filter check fail");
1428 return 0;
1429 }
3f9c7369 1430
d62a17ae 1431 /* If the attribute has originator-id and it is same as remote
1432 peer's id. */
1433 if (onlypeer && riattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1434 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &riattr->originator_id))) {
1435 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1436 zlog_debug(
1437 "%s [Update:SEND] %s originator-id is same as "
1438 "remote router-id",
1439 onlypeer->host,
1440 prefix2str(p, buf, sizeof(buf)));
1441 return 0;
1442 }
3f9c7369 1443
d62a17ae 1444 /* ORF prefix-list filter check */
1445 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1446 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1447 || CHECK_FLAG(peer->af_cap[afi][safi],
1448 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1449 if (peer->orf_plist[afi][safi]) {
1450 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1451 == PREFIX_DENY) {
1452 if (bgp_debug_update(NULL, p,
1453 subgrp->update_group, 0))
1454 zlog_debug(
1455 "%s [Update:SEND] %s is filtered via ORF",
1456 peer->host,
1457 prefix2str(p, buf,
1458 sizeof(buf)));
1459 return 0;
1460 }
1461 }
1462
1463 /* Output filter check. */
1464 if (bgp_output_filter(peer, p, riattr, afi, safi) == FILTER_DENY) {
1465 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1466 zlog_debug("%s [Update:SEND] %s is filtered",
1467 peer->host, prefix2str(p, buf, sizeof(buf)));
1468 return 0;
1469 }
3f9c7369
DS
1470
1471#ifdef BGP_SEND_ASPATH_CHECK
d62a17ae 1472 /* AS path loop check. */
1473 if (onlypeer && aspath_loop_check(riattr->aspath, onlypeer->as)) {
1474 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1475 zlog_debug(
1476 "%s [Update:SEND] suppress announcement to peer AS %u "
1477 "that is part of AS path.",
1478 onlypeer->host, onlypeer->as);
1479 return 0;
1480 }
3f9c7369
DS
1481#endif /* BGP_SEND_ASPATH_CHECK */
1482
d62a17ae 1483 /* If we're a CONFED we need to loop check the CONFED ID too */
1484 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1485 if (aspath_loop_check(riattr->aspath, bgp->confed_id)) {
1486 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1487 zlog_debug(
1488 "%s [Update:SEND] suppress announcement to peer AS %u"
1489 " is AS path.",
1490 peer->host, bgp->confed_id);
1491 return 0;
1492 }
3f9c7369 1493 }
3f9c7369 1494
d62a17ae 1495 /* Route-Reflect check. */
1496 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1497 reflect = 1;
1498 else
1499 reflect = 0;
1500
1501 /* IBGP reflection check. */
1502 if (reflect && !samepeer_safe) {
1503 /* A route from a Client peer. */
1504 if (CHECK_FLAG(from->af_flags[afi][safi],
1505 PEER_FLAG_REFLECTOR_CLIENT)) {
1506 /* Reflect to all the Non-Client peers and also to the
1507 Client peers other than the originator. Originator
1508 check
1509 is already done. So there is noting to do. */
1510 /* no bgp client-to-client reflection check. */
1511 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
1512 if (CHECK_FLAG(peer->af_flags[afi][safi],
1513 PEER_FLAG_REFLECTOR_CLIENT))
1514 return 0;
1515 } else {
1516 /* A route from a Non-client peer. Reflect to all other
1517 clients. */
1518 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1519 PEER_FLAG_REFLECTOR_CLIENT))
1520 return 0;
1521 }
1522 }
3f9c7369 1523
d62a17ae 1524 /* For modify attribute, copy it to temporary structure. */
1525 bgp_attr_dup(attr, riattr);
1526
1527 /* If local-preference is not set. */
1528 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1529 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1530 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1531 attr->local_pref = bgp->default_local_pref;
3f9c7369 1532 }
3f9c7369 1533
d62a17ae 1534 /* If originator-id is not set and the route is to be reflected,
1535 set the originator id */
1536 if (reflect
1537 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1538 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1539 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1540 }
3f9c7369 1541
d62a17ae 1542 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1543 */
1544 if (peer->sort == BGP_PEER_EBGP
1545 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1546 if (from != bgp->peer_self && !transparent
1547 && !CHECK_FLAG(peer->af_flags[afi][safi],
1548 PEER_FLAG_MED_UNCHANGED))
1549 attr->flag &=
1550 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1551 }
3f9c7369 1552
d62a17ae 1553 /* Since the nexthop attribute can vary per peer, it is not explicitly
1554 * set
1555 * in announce check, only certain flags and length (or number of
1556 * nexthops
1557 * -- for IPv6/MP_REACH) are set here in order to guide the update
1558 * formation
1559 * code in setting the nexthop(s) on a per peer basis in
1560 * reformat_peer().
1561 * Typically, the source nexthop in the attribute is preserved but in
1562 * the
1563 * scenarios where we know it will always be overwritten, we reset the
1564 * nexthop to "0" in an attempt to achieve better Update packing. An
1565 * example of this is when a prefix from each of 2 IBGP peers needs to
1566 * be
1567 * announced to an EBGP peer (and they have the same attributes barring
1568 * their nexthop).
1569 */
1570 if (reflect)
1571 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1572
1573#define NEXTHOP_IS_V6 \
1574 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1575 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1576 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1577 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1578
1579 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1580 * if
1581 * the peer (group) is configured to receive link-local nexthop
1582 * unchanged
1583 * and it is available in the prefix OR we're not reflecting the route
1584 * and
1585 * the peer (group) to whom we're going to announce is on a shared
1586 * network
1587 * and this is either a self-originated route or the peer is EBGP.
1588 */
1589 if (NEXTHOP_IS_V6) {
1590 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1591 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1592 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1593 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
1594 || (!reflect && peer->shared_network
1595 && (from == bgp->peer_self
1596 || peer->sort == BGP_PEER_EBGP))) {
1597 attr->mp_nexthop_len =
1598 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1599 }
3f9c7369 1600
d62a17ae 1601 /* Clear off link-local nexthop in source, whenever it is not
1602 * needed to
1603 * ensure more prefixes share the same attribute for
1604 * announcement.
1605 */
1606 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1607 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1608 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1609 }
3f9c7369 1610
d62a17ae 1611 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1612 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1613
1614 /* Route map & unsuppress-map apply. */
1615 if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) {
1616 struct bgp_info info;
16f7ce2b 1617 struct bgp_info_extra dummy_info_extra;
d62a17ae 1618 struct attr dummy_attr;
1619
1620 info.peer = peer;
1621 info.attr = attr;
d37ba549 1622
16f7ce2b
MK
1623 if (ri->extra) {
1624 memcpy(&dummy_info_extra, ri->extra,
1625 sizeof(struct bgp_info_extra));
1626 info.extra = &dummy_info_extra;
1627 }
1628
d62a17ae 1629 /* don't confuse inbound and outbound setting */
1630 RESET_FLAG(attr->rmap_change_flags);
1631
1632 /*
1633 * The route reflector is not allowed to modify the attributes
1634 * of the reflected IBGP routes unless explicitly allowed.
1635 */
1636 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1637 && !bgp_flag_check(bgp,
1638 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
1639 bgp_attr_dup(&dummy_attr, attr);
1640 info.attr = &dummy_attr;
1641 }
3f9c7369 1642
d62a17ae 1643 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1644
d62a17ae 1645 if (ri->extra && ri->extra->suppress)
1646 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1647 RMAP_BGP, &info);
1648 else
1649 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1650 RMAP_BGP, &info);
1651
1652 peer->rmap_type = 0;
1653
1654 if (ret == RMAP_DENYMATCH) {
1655 bgp_attr_flush(attr);
1656 return 0;
1657 }
3f9c7369 1658 }
3f9c7369 1659
7f323236
DW
1660 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
1661 if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
1662 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1663 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1664 } else {
1665 bgp_attr_add_gshut_community(attr);
1666 }
1667 }
1668
d62a17ae 1669 /* After route-map has been applied, we check to see if the nexthop to
1670 * be carried in the attribute (that is used for the announcement) can
1671 * be cleared off or not. We do this in all cases where we would be
1672 * setting the nexthop to "ourselves". For IPv6, we only need to
1673 * consider
1674 * the global nexthop here; the link-local nexthop would have been
1675 * cleared
1676 * already, and if not, it is required by the update formation code.
1677 * Also see earlier comments in this function.
1678 */
1679 /*
1680 * If route-map has performed some operation on the nexthop or the peer
1681 * configuration says to pass it unchanged, we cannot reset the nexthop
1682 * here, so only attempt to do it if these aren't true. Note that the
1683 * route-map handler itself might have cleared the nexthop, if for
1684 * example,
1685 * it is configured as 'peer-address'.
1686 */
1687 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
1688 riattr->rmap_change_flags)
1689 && !transparent
1690 && !CHECK_FLAG(peer->af_flags[afi][safi],
1691 PEER_FLAG_NEXTHOP_UNCHANGED)) {
1692 /* We can reset the nexthop, if setting (or forcing) it to
1693 * 'self' */
1694 if (CHECK_FLAG(peer->af_flags[afi][safi],
1695 PEER_FLAG_NEXTHOP_SELF)
1696 || CHECK_FLAG(peer->af_flags[afi][safi],
1697 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
1698 if (!reflect
1699 || CHECK_FLAG(peer->af_flags[afi][safi],
1700 PEER_FLAG_FORCE_NEXTHOP_SELF))
1701 subgroup_announce_reset_nhop(
1702 (peer_cap_enhe(peer, afi, safi)
1703 ? AF_INET6
1704 : p->family),
1705 attr);
1706 } else if (peer->sort == BGP_PEER_EBGP) {
1707 /* Can also reset the nexthop if announcing to EBGP, but
1708 * only if
1709 * no peer in the subgroup is on a shared subnet.
1710 * Note: 3rd party nexthop currently implemented for
1711 * IPv4 only.
1712 */
65d4e0c6
DS
1713 if (!bgp_subgrp_multiaccess_check_v4(riattr->nexthop,
1714 subgrp))
d62a17ae 1715 subgroup_announce_reset_nhop(
1716 (peer_cap_enhe(peer, afi, safi)
65d4e0c6
DS
1717 ? AF_INET6
1718 : p->family),
d62a17ae 1719 attr);
1720 }
1721 /* If IPv6/MP and nexthop does not have any override and happens
1722 * to
1723 * be a link-local address, reset it so that we don't pass along
1724 * the
1725 * source's link-local IPv6 address to recipients who may not be
1726 * on
1727 * the same interface.
1728 */
1729 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
1730 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
1731 subgroup_announce_reset_nhop(AF_INET6, attr);
1732 }
1733 }
3f9c7369 1734
d62a17ae 1735 return 1;
3f9c7369
DS
1736}
1737
d62a17ae 1738void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
1739 struct bgp_maxpaths_cfg *mpath_cfg,
1740 struct bgp_info_pair *result, afi_t afi, safi_t safi)
1741{
1742 struct bgp_info *new_select;
1743 struct bgp_info *old_select;
1744 struct bgp_info *ri;
1745 struct bgp_info *ri1;
1746 struct bgp_info *ri2;
1747 struct bgp_info *nextri = NULL;
1748 int paths_eq, do_mpath, debug;
1749 struct list mp_list;
1750 char pfx_buf[PREFIX2STR_BUFFER];
1751 char path_buf[PATH_ADDPATH_STR_BUFFER];
1752
1753 bgp_mp_list_init(&mp_list);
1754 do_mpath =
1755 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
1756
1757 debug = bgp_debug_bestpath(&rn->p);
1758
1759 if (debug)
1760 prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
1761
1762 /* bgp deterministic-med */
1763 new_select = NULL;
1764 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
1765
1766 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1767 for (ri1 = rn->info; ri1; ri1 = ri1->next)
1768 bgp_info_unset_flag(rn, ri1, BGP_INFO_DMED_SELECTED);
1769
1770 for (ri1 = rn->info; ri1; ri1 = ri1->next) {
1771 if (CHECK_FLAG(ri1->flags, BGP_INFO_DMED_CHECK))
1772 continue;
1773 if (BGP_INFO_HOLDDOWN(ri1))
1774 continue;
1775 if (ri1->peer && ri1->peer != bgp->peer_self)
1776 if (ri1->peer->status != Established)
1777 continue;
1778
1779 new_select = ri1;
1780 if (ri1->next) {
1781 for (ri2 = ri1->next; ri2; ri2 = ri2->next) {
1782 if (CHECK_FLAG(ri2->flags,
1783 BGP_INFO_DMED_CHECK))
1784 continue;
1785 if (BGP_INFO_HOLDDOWN(ri2))
1786 continue;
1787 if (ri2->peer
1788 && ri2->peer != bgp->peer_self
1789 && !CHECK_FLAG(
1790 ri2->peer->sflags,
1791 PEER_STATUS_NSF_WAIT))
1792 if (ri2->peer->status
1793 != Established)
1794 continue;
1795
1796 if (aspath_cmp_left(ri1->attr->aspath,
1797 ri2->attr->aspath)
1798 || aspath_cmp_left_confed(
1799 ri1->attr->aspath,
1800 ri2->attr->aspath)) {
1801 if (bgp_info_cmp(bgp, ri2,
1802 new_select,
1803 &paths_eq,
1804 mpath_cfg,
1805 debug, pfx_buf,
1806 afi, safi)) {
1807 bgp_info_unset_flag(
1808 rn, new_select,
1809 BGP_INFO_DMED_SELECTED);
1810 new_select = ri2;
1811 }
1812
1813 bgp_info_set_flag(
1814 rn, ri2,
1815 BGP_INFO_DMED_CHECK);
1816 }
1817 }
1818 }
1819 bgp_info_set_flag(rn, new_select, BGP_INFO_DMED_CHECK);
1820 bgp_info_set_flag(rn, new_select,
1821 BGP_INFO_DMED_SELECTED);
1822
1823 if (debug) {
1824 bgp_info_path_with_addpath_rx_str(new_select,
1825 path_buf);
1826 zlog_debug("%s: %s is the bestpath from AS %d",
1827 pfx_buf, path_buf,
1828 aspath_get_first_as(
1829 new_select->attr->aspath));
1830 }
1831 }
1832 }
96450faf 1833
d62a17ae 1834 /* Check old selected route and new selected route. */
1835 old_select = NULL;
1836 new_select = NULL;
1837 for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1);
1838 ri = nextri) {
1839 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED))
1840 old_select = ri;
1841
1842 if (BGP_INFO_HOLDDOWN(ri)) {
1843 /* reap REMOVED routes, if needs be
1844 * selected route must stay for a while longer though
1845 */
1846 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
1847 && (ri != old_select))
1848 bgp_info_reap(rn, ri);
1849
1850 continue;
1851 }
96450faf 1852
d62a17ae 1853 if (ri->peer && ri->peer != bgp->peer_self
1854 && !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT))
1855 if (ri->peer->status != Established)
1856 continue;
9fbdd100 1857
d62a17ae 1858 if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
1859 && (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) {
1860 bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
1861 continue;
1862 }
9fbdd100 1863
d62a17ae 1864 bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
06370dac 1865
d62a17ae 1866 if (bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg,
1867 debug, pfx_buf, afi, safi)) {
1868 new_select = ri;
1869 }
1870 }
718e3744 1871
d62a17ae 1872 /* Now that we know which path is the bestpath see if any of the other
1873 * paths
1874 * qualify as multipaths
1875 */
1876 if (debug) {
1877 if (new_select)
1878 bgp_info_path_with_addpath_rx_str(new_select, path_buf);
1879 else
1880 sprintf(path_buf, "NONE");
1881 zlog_debug(
1882 "%s: After path selection, newbest is %s oldbest was %s",
1883 pfx_buf, path_buf,
1884 old_select ? old_select->peer->host : "NONE");
96450faf 1885 }
9fbdd100 1886
d62a17ae 1887 if (do_mpath && new_select) {
1888 for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1);
1889 ri = nextri) {
1890
1891 if (debug)
1892 bgp_info_path_with_addpath_rx_str(ri, path_buf);
1893
1894 if (ri == new_select) {
1895 if (debug)
1896 zlog_debug(
1897 "%s: %s is the bestpath, add to the multipath list",
1898 pfx_buf, path_buf);
1899 bgp_mp_list_add(&mp_list, ri);
1900 continue;
1901 }
1902
1903 if (BGP_INFO_HOLDDOWN(ri))
1904 continue;
1905
1906 if (ri->peer && ri->peer != bgp->peer_self
1907 && !CHECK_FLAG(ri->peer->sflags,
1908 PEER_STATUS_NSF_WAIT))
1909 if (ri->peer->status != Established)
1910 continue;
1911
1912 if (!bgp_info_nexthop_cmp(ri, new_select)) {
1913 if (debug)
1914 zlog_debug(
1915 "%s: %s has the same nexthop as the bestpath, skip it",
1916 pfx_buf, path_buf);
1917 continue;
1918 }
1919
1920 bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg,
1921 debug, pfx_buf, afi, safi);
1922
1923 if (paths_eq) {
1924 if (debug)
1925 zlog_debug(
1926 "%s: %s is equivalent to the bestpath, add to the multipath list",
1927 pfx_buf, path_buf);
1928 bgp_mp_list_add(&mp_list, ri);
1929 }
1930 }
1931 }
fee0f4c6 1932
d62a17ae 1933 bgp_info_mpath_update(rn, new_select, old_select, &mp_list, mpath_cfg);
1934 bgp_info_mpath_aggregate_update(new_select, old_select);
1935 bgp_mp_list_clear(&mp_list);
96450faf 1936
d62a17ae 1937 result->old = old_select;
1938 result->new = new_select;
96450faf 1939
d62a17ae 1940 return;
fee0f4c6 1941}
1942
3f9c7369
DS
1943/*
1944 * A new route/change in bestpath of an existing route. Evaluate the path
1945 * for advertisement to the subgroup.
1946 */
d62a17ae 1947int subgroup_process_announce_selected(struct update_subgroup *subgrp,
1948 struct bgp_info *selected,
1949 struct bgp_node *rn,
1950 u_int32_t addpath_tx_id)
1951{
1952 struct prefix *p;
1953 struct peer *onlypeer;
1954 struct attr attr;
1955 afi_t afi;
1956 safi_t safi;
adbac85e 1957
d62a17ae 1958 p = &rn->p;
1959 afi = SUBGRP_AFI(subgrp);
1960 safi = SUBGRP_SAFI(subgrp);
1961 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
1962 : NULL);
1963
1964 /* First update is deferred until ORF or ROUTE-REFRESH is received */
9d303b37
DL
1965 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
1966 PEER_STATUS_ORF_WAIT_REFRESH))
d62a17ae 1967 return 0;
1968
1969 memset(&attr, 0, sizeof(struct attr));
1970 /* It's initialized in bgp_announce_check() */
1971
1972 /* Announcement to the subgroup. If the route is filtered withdraw it.
1973 */
1974 if (selected) {
1975 if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
1976 bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
1977 else
1978 bgp_adj_out_unset_subgroup(rn, subgrp, 1,
1979 selected->addpath_tx_id);
1980 }
1981
1982 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1983 else {
1984 bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id);
1985 }
558d1fec 1986
d62a17ae 1987 return 0;
200df115 1988}
fee0f4c6 1989
3064bf43 1990/*
e1072051 1991 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1992 * This is called at the end of route processing.
3064bf43 1993 */
d62a17ae 1994void bgp_zebra_clear_route_change_flags(struct bgp_node *rn)
3064bf43 1995{
d62a17ae 1996 struct bgp_info *ri;
3064bf43 1997
d62a17ae 1998 for (ri = rn->info; ri; ri = ri->next) {
1999 if (BGP_INFO_HOLDDOWN(ri))
2000 continue;
2001 UNSET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
2002 UNSET_FLAG(ri->flags, BGP_INFO_ATTR_CHANGED);
2003 }
3064bf43 2004}
2005
2006/*
2007 * Has the route changed from the RIB's perspective? This is invoked only
2008 * if the route selection returns the same best route as earlier - to
2009 * determine if we need to update zebra or not.
2010 */
d62a17ae 2011int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected)
2012{
2013 struct bgp_info *mpinfo;
2014
2015 /* If this is multipath, check all selected paths for any nexthop change
2016 * or
2017 * attribute change. Some attribute changes (e.g., community) aren't of
2018 * relevance to the RIB, but we'll update zebra to ensure we handle the
2019 * case of BGP nexthop change. This is the behavior when the best path
2020 * has
2021 * an attribute change anyway.
2022 */
2023 if (CHECK_FLAG(selected->flags, BGP_INFO_IGP_CHANGED)
2024 || CHECK_FLAG(selected->flags, BGP_INFO_MULTIPATH_CHG))
2025 return 1;
2026
2027 /* If this is multipath, check all selected paths for any nexthop change
2028 */
2029 for (mpinfo = bgp_info_mpath_first(selected); mpinfo;
2030 mpinfo = bgp_info_mpath_next(mpinfo)) {
2031 if (CHECK_FLAG(mpinfo->flags, BGP_INFO_IGP_CHANGED)
2032 || CHECK_FLAG(mpinfo->flags, BGP_INFO_ATTR_CHANGED))
2033 return 1;
2034 }
3064bf43 2035
d62a17ae 2036 /* Nothing has changed from the RIB's perspective. */
2037 return 0;
3064bf43 2038}
2039
d62a17ae 2040struct bgp_process_queue {
2041 struct bgp *bgp;
aac24838
JB
2042 STAILQ_HEAD(, bgp_node)pqueue;
2043#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2044 unsigned int flags;
2045 unsigned int queued;
200df115 2046};
2047
aac24838
JB
2048static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
2049 afi_t afi, safi_t safi)
d62a17ae 2050{
d62a17ae 2051 struct prefix *p = &rn->p;
2052 struct bgp_info *new_select;
2053 struct bgp_info *old_select;
2054 struct bgp_info_pair old_and_new;
2055
2056 /* Is it end of initial update? (after startup) */
2057 if (!rn) {
2058 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2059 sizeof(bgp->update_delay_zebra_resume_time));
2060
2061 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2062 FOREACH_AFI_SAFI (afi, safi) {
2063 if (bgp_fibupd_safi(safi))
2064 bgp_zebra_announce_table(bgp, afi, safi);
2065 }
d62a17ae 2066 bgp->main_peers_update_hold = 0;
2067
2068 bgp_start_routeadv(bgp);
aac24838 2069 return;
d62a17ae 2070 }
cb1faec9 2071
d62a17ae 2072 /* Best path selection. */
2073 bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
2074 afi, safi);
2075 old_select = old_and_new.old;
2076 new_select = old_and_new.new;
2077
2078 /* Do we need to allocate or free labels?
2079 * Right now, since we only deal with per-prefix labels, it is not
cb499ebb 2080 * necessary to do this upon changes to best path except if the label
09fdc88c 2081 * index changes
d62a17ae 2082 */
318cac96 2083 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2084 if (new_select) {
2085 if (!old_select
2086 || bgp_label_index_differs(new_select, old_select)
2087 || new_select->sub_type != old_select->sub_type) {
2088 if (new_select->sub_type == BGP_ROUTE_STATIC
2089 && new_select->attr->flag
2090 & ATTR_FLAG_BIT(
2091 BGP_ATTR_PREFIX_SID)
2092 && new_select->attr->label_index
2093 != BGP_INVALID_LABEL_INDEX) {
2094 if (CHECK_FLAG(
2095 rn->flags,
2096 BGP_NODE_REGISTERED_FOR_LABEL))
2097 bgp_unregister_for_label(rn);
2098 label_ntop(MPLS_IMP_NULL_LABEL, 1,
2099 &rn->local_label);
2100 bgp_set_valid_label(&rn->local_label);
2101 } else
2102 bgp_register_for_label(rn, new_select);
2103 }
318cac96 2104 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
d62a17ae 2105 bgp_unregister_for_label(rn);
318cac96
DW
2106 }
2107 } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2108 bgp_unregister_for_label(rn);
d62a17ae 2109 }
cd1964ff 2110
d62a17ae 2111 /* If best route remains the same and this is not due to user-initiated
2112 * clear, see exactly what needs to be done.
2113 */
cd1964ff 2114
d62a17ae 2115 if (old_select && old_select == new_select
2116 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
2117 && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
2118 && !bgp->addpath_tx_used[afi][safi]) {
2119 if (bgp_zebra_has_route_changed(rn, old_select)) {
65efcfce 2120#if ENABLE_BGP_VNC
d62a17ae 2121 vnc_import_bgp_add_route(bgp, p, old_select);
2122 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2123#endif
bb744275 2124 if (bgp_fibupd_safi(safi)
d62a17ae 2125 && !bgp_option_check(BGP_OPT_NO_FIB)
2126 && new_select->type == ZEBRA_ROUTE_BGP
2127 && new_select->sub_type == BGP_ROUTE_NORMAL)
2128 bgp_zebra_announce(rn, p, old_select, bgp, afi,
2129 safi);
2130 }
2131 UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
2132 bgp_zebra_clear_route_change_flags(rn);
2133
2134 /* If there is a change of interest to peers, reannounce the
2135 * route. */
2136 if (CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
2137 || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
2138 group_announce_route(bgp, afi, safi, rn, new_select);
2139
2140 /* unicast routes must also be annouced to
2141 * labeled-unicast update-groups */
2142 if (safi == SAFI_UNICAST)
2143 group_announce_route(bgp, afi,
2144 SAFI_LABELED_UNICAST, rn,
2145 new_select);
2146
2147 UNSET_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED);
2148 UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
2149 }
fee0f4c6 2150
d62a17ae 2151 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2152 return;
d62a17ae 2153 }
8ad7271d 2154
d62a17ae 2155 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2156 */
2157 UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
2158
2159 /* bestpath has changed; bump version */
2160 if (old_select || new_select) {
2161 bgp_bump_version(rn);
2162
2163 if (!bgp->t_rmap_def_originate_eval) {
2164 bgp_lock(bgp);
2165 thread_add_timer(
2166 bm->master,
2167 update_group_refresh_default_originate_route_map,
2168 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2169 &bgp->t_rmap_def_originate_eval);
2170 }
2171 }
3f9c7369 2172
d62a17ae 2173 if (old_select)
2174 bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
2175 if (new_select) {
2176 bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
2177 bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
2178 UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
2179 }
338b3424 2180
65efcfce 2181#if ENABLE_BGP_VNC
d62a17ae 2182 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2183 if (old_select != new_select) {
2184 if (old_select) {
2185 vnc_import_bgp_exterior_del_route(bgp, p,
2186 old_select);
2187 vnc_import_bgp_del_route(bgp, p, old_select);
2188 }
2189 if (new_select) {
2190 vnc_import_bgp_exterior_add_route(bgp, p,
2191 new_select);
2192 vnc_import_bgp_add_route(bgp, p, new_select);
2193 }
2194 }
2195 }
65efcfce
LB
2196#endif
2197
d62a17ae 2198 group_announce_route(bgp, afi, safi, rn, new_select);
2199
2200 /* unicast routes must also be annouced to labeled-unicast update-groups
2201 */
2202 if (safi == SAFI_UNICAST)
2203 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn,
2204 new_select);
2205
2206 /* FIB update. */
2207 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2208 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2209 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2210 && (new_select->sub_type == BGP_ROUTE_NORMAL
2211 || new_select->sub_type == BGP_ROUTE_AGGREGATE))
2212 bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
2213 else {
2214 /* Withdraw the route from the kernel. */
2215 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2216 && (old_select->sub_type == BGP_ROUTE_NORMAL
2217 || old_select->sub_type == BGP_ROUTE_AGGREGATE))
2218 bgp_zebra_withdraw(p, old_select, safi);
2219 }
718e3744 2220 }
3064bf43 2221
d62a17ae 2222 /* Clear any route change flags. */
2223 bgp_zebra_clear_route_change_flags(rn);
3064bf43 2224
d62a17ae 2225 /* Reap old select bgp_info, if it has been removed */
2226 if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED))
2227 bgp_info_reap(rn, old_select);
2228
2229 UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2230 return;
718e3744 2231}
2232
aac24838 2233static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2234{
aac24838
JB
2235 struct bgp_process_queue *pqnode = data;
2236 struct bgp *bgp = pqnode->bgp;
d62a17ae 2237 struct bgp_table *table;
ac021f40 2238 struct bgp_node *rn;
aac24838
JB
2239
2240 /* eoiu marker */
2241 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2242 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2243 /* should always have dedicated wq call */
2244 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2245 return WQ_SUCCESS;
2246 }
2247
ac021f40
LB
2248 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
2249 rn = STAILQ_FIRST(&pqnode->pqueue);
2250 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
b3e1dd3c 2251 STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
aac24838 2252 table = bgp_node_table(rn);
ac021f40 2253 /* note, new RNs may be added as part of processing */
aac24838 2254 bgp_process_main_one(bgp, rn, table->afi, table->safi);
cb1faec9 2255
aac24838 2256 bgp_unlock_node(rn);
d62a17ae 2257 bgp_table_unlock(table);
2258 }
aac24838
JB
2259
2260 return WQ_SUCCESS;
2261}
2262
2263static void bgp_processq_del(struct work_queue *wq, void *data)
2264{
2265 struct bgp_process_queue *pqnode = data;
2266
2267 bgp_unlock(pqnode->bgp);
2268
2269 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2270}
2271
d62a17ae 2272void bgp_process_queue_init(void)
200df115 2273{
d62a17ae 2274 if (!bm->process_main_queue) {
2275 bm->process_main_queue =
2276 work_queue_new(bm->master, "process_main_queue");
2277
2278 if (!bm->process_main_queue) {
2279 zlog_err("%s: Failed to allocate work queue", __func__);
2280 exit(1);
2281 }
2282 }
2283
aac24838 2284 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2285 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2286 bm->process_main_queue->spec.max_retries = 0;
2287 bm->process_main_queue->spec.hold = 50;
2288 /* Use a higher yield value of 50ms for main queue processing */
2289 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2290}
2291
cfe8d15a 2292static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2293{
2294 struct bgp_process_queue *pqnode;
2295
2296 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, sizeof(struct bgp_process_queue));
2297
2298 /* unlocked in bgp_processq_del */
2299 pqnode->bgp = bgp_lock(bgp);
2300 STAILQ_INIT(&pqnode->pqueue);
2301
aac24838
JB
2302 return pqnode;
2303}
2304
d62a17ae 2305void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
fee0f4c6 2306{
aac24838
JB
2307#define ARBITRARY_PROCESS_QLEN 10000
2308 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2309 struct bgp_process_queue *pqnode;
cfe8d15a 2310 int pqnode_reuse = 0;
495f0b13 2311
d62a17ae 2312 /* already scheduled for processing? */
2313 if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
2314 return;
2e02b9b2 2315
aac24838 2316 if (wq == NULL)
d62a17ae 2317 return;
2318
aac24838
JB
2319 /* Add route nodes to an existing work queue item until reaching the
2320 limit only if is from the same BGP view and it's not an EOIU marker */
2321 if (work_queue_item_count(wq)) {
2322 struct work_queue_item *item = work_queue_last_item(wq);
2323 pqnode = item->data;
228da428 2324
aac24838
JB
2325 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER) ||
2326 pqnode->bgp != bgp || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
2327 pqnode = bgp_processq_alloc(bgp);
2328 else
2329 pqnode_reuse = 1;
aac24838 2330 } else
cfe8d15a 2331 pqnode = bgp_processq_alloc(bgp);
aac24838 2332 /* all unlocked in bgp_process_wq */
d62a17ae 2333 bgp_table_lock(bgp_node_table(rn));
aac24838 2334
d62a17ae 2335 SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838
JB
2336 bgp_lock_node(rn);
2337
60466a63
QY
2338 /* can't be enqueued twice */
2339 assert(STAILQ_NEXT(rn, pq) == NULL);
aac24838
JB
2340 STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
2341 pqnode->queued++;
2342
cfe8d15a
LB
2343 if (!pqnode_reuse)
2344 work_queue_add(wq, pqnode);
2345
d62a17ae 2346 return;
fee0f4c6 2347}
0a486e5f 2348
d62a17ae 2349void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 2350{
d62a17ae 2351 struct bgp_process_queue *pqnode;
cb1faec9 2352
d62a17ae 2353 if (bm->process_main_queue == NULL)
2354 return;
2e02b9b2 2355
cfe8d15a 2356 pqnode = bgp_processq_alloc(bgp);
cb1faec9 2357
aac24838 2358 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 2359 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
2360}
2361
d62a17ae 2362static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 2363{
d62a17ae 2364 struct peer *peer;
0a486e5f 2365
d62a17ae 2366 peer = THREAD_ARG(thread);
2367 peer->t_pmax_restart = NULL;
0a486e5f 2368
d62a17ae 2369 if (bgp_debug_neighbor_events(peer))
2370 zlog_debug(
2371 "%s Maximum-prefix restart timer expired, restore peering",
2372 peer->host);
0a486e5f 2373
d62a17ae 2374 peer_clear(peer, NULL);
0a486e5f 2375
d62a17ae 2376 return 0;
0a486e5f 2377}
2378
d62a17ae 2379int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
2380 int always)
718e3744 2381{
d62a17ae 2382 iana_afi_t pkt_afi;
5c525538 2383 iana_safi_t pkt_safi;
9cabb64b 2384
d62a17ae 2385 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
2386 return 0;
e0701b79 2387
d62a17ae 2388 if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) {
2389 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2390 PEER_STATUS_PREFIX_LIMIT)
2391 && !always)
2392 return 0;
e0701b79 2393
d62a17ae 2394 zlog_info(
2395 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2396 "limit %ld",
2397 afi_safi_print(afi, safi), peer->host,
2398 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2399 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
2400
2401 if (CHECK_FLAG(peer->af_flags[afi][safi],
2402 PEER_FLAG_MAX_PREFIX_WARNING))
2403 return 0;
2404
2405 /* Convert AFI, SAFI to values for packet. */
2406 pkt_afi = afi_int2iana(afi);
2407 pkt_safi = safi_int2iana(safi);
2408 {
2409 u_int8_t ndata[7];
2410
2411 ndata[0] = (pkt_afi >> 8);
2412 ndata[1] = pkt_afi;
2413 ndata[2] = pkt_safi;
2414 ndata[3] = (peer->pmax[afi][safi] >> 24);
2415 ndata[4] = (peer->pmax[afi][safi] >> 16);
2416 ndata[5] = (peer->pmax[afi][safi] >> 8);
2417 ndata[6] = (peer->pmax[afi][safi]);
2418
2419 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2420 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
2421 BGP_NOTIFY_CEASE_MAX_PREFIX,
2422 ndata, 7);
2423 }
2424
2425 /* Dynamic peers will just close their connection. */
2426 if (peer_dynamic_neighbor(peer))
2427 return 1;
2428
2429 /* restart timer start */
2430 if (peer->pmax_restart[afi][safi]) {
2431 peer->v_pmax_restart =
2432 peer->pmax_restart[afi][safi] * 60;
2433
2434 if (bgp_debug_neighbor_events(peer))
2435 zlog_debug(
2436 "%s Maximum-prefix restart timer started for %d secs",
2437 peer->host, peer->v_pmax_restart);
2438
2439 BGP_TIMER_ON(peer->t_pmax_restart,
2440 bgp_maximum_prefix_restart_timer,
2441 peer->v_pmax_restart);
2442 }
2443
2444 return 1;
2445 } else
2446 UNSET_FLAG(peer->af_sflags[afi][safi],
2447 PEER_STATUS_PREFIX_LIMIT);
2448
2449 if (peer->pcount[afi][safi]
2450 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
2451 if (CHECK_FLAG(peer->af_sflags[afi][safi],
2452 PEER_STATUS_PREFIX_THRESHOLD)
2453 && !always)
2454 return 0;
2455
2456 zlog_info(
2457 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2458 afi_safi_print(afi, safi), peer->host,
2459 peer->pcount[afi][safi], peer->pmax[afi][safi]);
2460 SET_FLAG(peer->af_sflags[afi][safi],
2461 PEER_STATUS_PREFIX_THRESHOLD);
2462 } else
2463 UNSET_FLAG(peer->af_sflags[afi][safi],
2464 PEER_STATUS_PREFIX_THRESHOLD);
2465 return 0;
718e3744 2466}
2467
b40d939b 2468/* Unconditionally remove the route from the RIB, without taking
2469 * damping into consideration (eg, because the session went down)
2470 */
60466a63
QY
2471void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
2472 afi_t afi, safi_t safi)
718e3744 2473{
d62a17ae 2474 bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
2475
2476 if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
2477 bgp_info_delete(rn, ri); /* keep historical info */
2478
2479 bgp_process(peer->bgp, rn, afi, safi);
2480}
2481
2482static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri,
2483 struct peer *peer, afi_t afi, safi_t safi,
2484 struct prefix_rd *prd)
2485{
2486 int status = BGP_DAMP_NONE;
2487
2488 /* apply dampening, if result is suppressed, we'll be retaining
2489 * the bgp_info in the RIB for historical reference.
2490 */
2491 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2492 && peer->sort == BGP_PEER_EBGP)
2493 if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0))
2494 == BGP_DAMP_SUPPRESSED) {
2495 bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi,
2496 safi);
2497 return;
2498 }
2499
65efcfce 2500#if ENABLE_BGP_VNC
d62a17ae 2501 if (safi == SAFI_MPLS_VPN) {
2502 struct bgp_node *prn = NULL;
2503 struct bgp_table *table = NULL;
2504
2505 prn = bgp_node_get(peer->bgp->rib[afi][safi],
2506 (struct prefix *)prd);
2507 if (prn->info) {
2508 table = (struct bgp_table *)(prn->info);
2509
2510 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2511 peer->bgp, prd, table, &rn->p, ri);
2512 }
2513 bgp_unlock_node(prn);
2514 }
2515 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2516 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
65efcfce 2517
d62a17ae 2518 vnc_import_bgp_del_route(peer->bgp, &rn->p, ri);
2519 vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p,
2520 ri);
2521 }
65efcfce 2522 }
d62a17ae 2523#endif
128ea8ab 2524
d62a17ae 2525 /* If this is an EVPN route, process for un-import. */
2526 if (safi == SAFI_EVPN)
2527 bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, ri);
128ea8ab 2528
d62a17ae 2529 bgp_rib_remove(rn, ri, peer, afi, safi);
718e3744 2530}
2531
d62a17ae 2532struct bgp_info *info_make(int type, int sub_type, u_short instance,
2533 struct peer *peer, struct attr *attr,
2534 struct bgp_node *rn)
fb018d25 2535{
d62a17ae 2536 struct bgp_info *new;
fb018d25 2537
d62a17ae 2538 /* Make new BGP info. */
2539 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info));
2540 new->type = type;
2541 new->instance = instance;
2542 new->sub_type = sub_type;
2543 new->peer = peer;
2544 new->attr = attr;
2545 new->uptime = bgp_clock();
2546 new->net = rn;
2547 new->addpath_tx_id = ++peer->bgp->addpath_tx_id;
2548 return new;
fb018d25
DS
2549}
2550
d62a17ae 2551static void overlay_index_update(struct attr *attr,
2552 struct eth_segment_id *eth_s_id,
2553 union gw_addr *gw_ip)
684a7227 2554{
d62a17ae 2555 if (!attr)
2556 return;
684a7227 2557
d62a17ae 2558 if (eth_s_id == NULL) {
2559 memset(&(attr->evpn_overlay.eth_s_id), 0,
2560 sizeof(struct eth_segment_id));
2561 } else {
2562 memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id,
2563 sizeof(struct eth_segment_id));
2564 }
2565 if (gw_ip == NULL) {
2566 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
2567 } else {
2568 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
2569 sizeof(union gw_addr));
2570 }
684a7227
PG
2571}
2572
d62a17ae 2573static bool overlay_index_equal(afi_t afi, struct bgp_info *info,
2574 struct eth_segment_id *eth_s_id,
2575 union gw_addr *gw_ip)
2576{
2577 struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote;
2578 union gw_addr *info_gw_ip, *info_gw_ip_remote;
2579 char temp[16];
2580
2581 if (afi != AFI_L2VPN)
2582 return true;
2583 if (!info->attr) {
2584 memset(&temp, 0, 16);
2585 info_eth_s_id = (struct eth_segment_id *)&temp;
2586 info_gw_ip = (union gw_addr *)&temp;
2587 if (eth_s_id == NULL && gw_ip == NULL)
2588 return true;
2589 } else {
2590 info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id);
2591 info_gw_ip = &(info->attr->evpn_overlay.gw_ip);
2592 }
2593 if (gw_ip == NULL)
2594 info_gw_ip_remote = (union gw_addr *)&temp;
2595 else
2596 info_gw_ip_remote = gw_ip;
2597 if (eth_s_id == NULL)
2598 info_eth_s_id_remote = (struct eth_segment_id *)&temp;
2599 else
2600 info_eth_s_id_remote = eth_s_id;
2601 if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr)))
2602 return false;
2603 return !memcmp(info_eth_s_id, info_eth_s_id_remote,
2604 sizeof(struct eth_segment_id));
684a7227
PG
2605}
2606
c265ee22 2607/* Check if received nexthop is valid or not. */
d62a17ae 2608static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
2609 struct attr *attr)
2610{
2611 int ret = 0;
2612
2613 /* Only validated for unicast and multicast currently. */
2614 /* Also valid for EVPN where the nexthop is an IP address. */
2615 if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
2616 return 0;
2617
2618 /* If NEXT_HOP is present, validate it. */
2619 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
2620 if (attr->nexthop.s_addr == 0
2621 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
2622 || bgp_nexthop_self(bgp, attr->nexthop))
2623 return 1;
2624 }
c265ee22 2625
d62a17ae 2626 /* If MP_NEXTHOP is present, validate it. */
2627 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2628 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2629 * it is not an IPv6 link-local address.
2630 */
2631 if (attr->mp_nexthop_len) {
2632 switch (attr->mp_nexthop_len) {
2633 case BGP_ATTR_NHLEN_IPV4:
2634 case BGP_ATTR_NHLEN_VPNV4:
2635 ret = (attr->mp_nexthop_global_in.s_addr == 0
2636 || IPV4_CLASS_DE(ntohl(
2637 attr->mp_nexthop_global_in.s_addr))
2638 || bgp_nexthop_self(bgp,
2639 attr->mp_nexthop_global_in));
2640 break;
2641
2642 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2643 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2644 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2645 ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
2646 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
2647 || IN6_IS_ADDR_MULTICAST(
2648 &attr->mp_nexthop_global));
2649 break;
2650
2651 default:
2652 ret = 1;
2653 break;
2654 }
2655 }
c265ee22 2656
d62a17ae 2657 return ret;
2658}
2659
2660int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
2661 struct attr *attr, afi_t afi, safi_t safi, int type,
2662 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
2663 int soft_reconfig, struct bgp_route_evpn *evpn)
2664{
2665 int ret;
2666 int aspath_loop_count = 0;
2667 struct bgp_node *rn;
2668 struct bgp *bgp;
2669 struct attr new_attr;
2670 struct attr *attr_new;
2671 struct bgp_info *ri;
2672 struct bgp_info *new;
2673 const char *reason;
2674 char pfx_buf[BGP_PRD_PATH_STRLEN];
2675 char label_buf[20];
2676 int connected = 0;
2677 int do_loop_check = 1;
2678 int has_valid_label = 0;
65efcfce 2679#if ENABLE_BGP_VNC
d62a17ae 2680 int vnc_implicit_withdraw = 0;
65efcfce 2681#endif
d62a17ae 2682 int same_attr = 0;
718e3744 2683
d62a17ae 2684 memset(&new_attr, 0, sizeof(struct attr));
2685 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
2686 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 2687
d62a17ae 2688 bgp = peer->bgp;
2689 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
2690 has_valid_label = bgp_is_valid_label(label);
9bedbb1e 2691
d62a17ae 2692 if (has_valid_label)
2693 sprintf(label_buf, "label %u", label_pton(label));
718e3744 2694
d62a17ae 2695 /* When peer's soft reconfiguration enabled. Record input packet in
2696 Adj-RIBs-In. */
2697 if (!soft_reconfig
2698 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
2699 && peer != bgp->peer_self)
2700 bgp_adj_in_set(rn, peer, attr, addpath_id);
2701
2702 /* Check previously received route. */
2703 for (ri = rn->info; ri; ri = ri->next)
2704 if (ri->peer == peer && ri->type == type
2705 && ri->sub_type == sub_type
2706 && ri->addpath_rx_id == addpath_id)
2707 break;
2708
2709 /* AS path local-as loop check. */
2710 if (peer->change_local_as) {
2711 if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
2712 aspath_loop_count = 1;
2713
2714 if (aspath_loop_check(attr->aspath, peer->change_local_as)
2715 > aspath_loop_count) {
2716 reason = "as-path contains our own AS;";
2717 goto filtered;
2718 }
718e3744 2719 }
718e3744 2720
d62a17ae 2721 /* If the peer is configured for "allowas-in origin" and the last ASN in
2722 * the
2723 * as-path is our ASN then we do not need to call aspath_loop_check
2724 */
2725 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
2726 if (aspath_get_last_as(attr->aspath) == bgp->as)
2727 do_loop_check = 0;
2728
2729 /* AS path loop check. */
2730 if (do_loop_check) {
2731 if (aspath_loop_check(attr->aspath, bgp->as)
2732 > peer->allowas_in[afi][safi]
2733 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
2734 && aspath_loop_check(attr->aspath, bgp->confed_id)
2735 > peer->allowas_in[afi][safi])) {
2736 reason = "as-path contains our own AS;";
2737 goto filtered;
2738 }
2739 }
aac9ef6c 2740
d62a17ae 2741 /* Route reflector originator ID check. */
2742 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2743 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
2744 reason = "originator is us;";
2745 goto filtered;
2746 }
718e3744 2747
d62a17ae 2748 /* Route reflector cluster ID check. */
2749 if (bgp_cluster_filter(peer, attr)) {
2750 reason = "reflected from the same cluster;";
2751 goto filtered;
2752 }
718e3744 2753
d62a17ae 2754 /* Apply incoming filter. */
2755 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
2756 reason = "filter;";
2757 goto filtered;
2758 }
718e3744 2759
d62a17ae 2760 bgp_attr_dup(&new_attr, attr);
2761
2762 /* Apply incoming route-map.
2763 * NB: new_attr may now contain newly allocated values from route-map
2764 * "set"
2765 * commands, so we need bgp_attr_flush in the error paths, until we
2766 * intern
2767 * the attr (which takes over the memory references) */
2768 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
2769 == RMAP_DENY) {
2770 reason = "route-map;";
2771 bgp_attr_flush(&new_attr);
2772 goto filtered;
2773 }
718e3744 2774
7f323236
DW
2775 if (peer->sort == BGP_PEER_EBGP) {
2776
2777 /* If we receive the graceful-shutdown community from an eBGP peer we
2778 * must lower local-preference */
2779 if (new_attr.community &&
2780 community_include(new_attr.community, COMMUNITY_GSHUT)) {
2781 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2782 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
2783
2784 /* If graceful-shutdown is configured then add the GSHUT community to
2785 * all paths received from eBGP peers */
2786 } else if (bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
2787 bgp_attr_add_gshut_community(&new_attr);
2788 }
2789 }
2790
d62a17ae 2791 /* next hop check. */
e1541bf6 2792 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
02a82b47 2793 bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
d62a17ae 2794 reason = "martian or self next-hop;";
2795 bgp_attr_flush(&new_attr);
2796 goto filtered;
2797 }
718e3744 2798
d62a17ae 2799 attr_new = bgp_attr_intern(&new_attr);
2800
2801 /* If the update is implicit withdraw. */
2802 if (ri) {
2803 ri->uptime = bgp_clock();
2804 same_attr = attrhash_cmp(ri->attr, attr_new);
2805
2806 /* Same attribute comes in. */
2807 if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
2808 && attrhash_cmp(ri->attr, attr_new)
2809 && (!has_valid_label
2810 || memcmp(&(bgp_info_extra_get(ri))->label, label,
2811 BGP_LABEL_BYTES)
2812 == 0)
2813 && (overlay_index_equal(
2814 afi, ri, evpn == NULL ? NULL : &evpn->eth_s_id,
2815 evpn == NULL ? NULL : &evpn->gw_ip))) {
2816 if (CHECK_FLAG(bgp->af_flags[afi][safi],
2817 BGP_CONFIG_DAMPENING)
2818 && peer->sort == BGP_PEER_EBGP
2819 && CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) {
2820 if (bgp_debug_update(peer, p, NULL, 1)) {
2821 bgp_debug_rdpfxpath2str(
2822 afi, safi, prd, p, label,
2823 addpath_id ? 1 : 0, addpath_id,
2824 pfx_buf, sizeof(pfx_buf));
2825 zlog_debug("%s rcvd %s", peer->host,
2826 pfx_buf);
2827 }
2828
2829 if (bgp_damp_update(ri, rn, afi, safi)
2830 != BGP_DAMP_SUPPRESSED) {
2831 bgp_aggregate_increment(bgp, p, ri, afi,
2832 safi);
2833 bgp_process(bgp, rn, afi, safi);
2834 }
2835 } else /* Duplicate - odd */
2836 {
2837 if (bgp_debug_update(peer, p, NULL, 1)) {
2838 if (!peer->rcvd_attr_printed) {
2839 zlog_debug(
2840 "%s rcvd UPDATE w/ attr: %s",
2841 peer->host,
2842 peer->rcvd_attr_str);
2843 peer->rcvd_attr_printed = 1;
2844 }
2845
2846 bgp_debug_rdpfxpath2str(
2847 afi, safi, prd, p, label,
2848 addpath_id ? 1 : 0, addpath_id,
2849 pfx_buf, sizeof(pfx_buf));
2850 zlog_debug(
2851 "%s rcvd %s...duplicate ignored",
2852 peer->host, pfx_buf);
2853 }
2854
2855 /* graceful restart STALE flag unset. */
2856 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) {
2857 bgp_info_unset_flag(rn, ri,
2858 BGP_INFO_STALE);
2859 bgp_process(bgp, rn, afi, safi);
2860 }
2861 }
2862
2863 bgp_unlock_node(rn);
2864 bgp_attr_unintern(&attr_new);
2865
2866 return 0;
2867 }
718e3744 2868
d62a17ae 2869 /* Withdraw/Announce before we fully processed the withdraw */
2870 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
2871 if (bgp_debug_update(peer, p, NULL, 1)) {
2872 bgp_debug_rdpfxpath2str(
2873 afi, safi, prd, p, label,
2874 addpath_id ? 1 : 0, addpath_id, pfx_buf,
2875 sizeof(pfx_buf));
2876 zlog_debug(
2877 "%s rcvd %s, flapped quicker than processing",
2878 peer->host, pfx_buf);
2879 }
2880
2881 bgp_info_restore(rn, ri);
2882 }
718e3744 2883
d62a17ae 2884 /* Received Logging. */
2885 if (bgp_debug_update(peer, p, NULL, 1)) {
2886 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
2887 addpath_id ? 1 : 0, addpath_id,
2888 pfx_buf, sizeof(pfx_buf));
2889 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
2890 }
718e3744 2891
d62a17ae 2892 /* graceful restart STALE flag unset. */
2893 if (CHECK_FLAG(ri->flags, BGP_INFO_STALE))
2894 bgp_info_unset_flag(rn, ri, BGP_INFO_STALE);
2895
2896 /* The attribute is changed. */
2897 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
2898
2899 /* implicit withdraw, decrement aggregate and pcount here.
2900 * only if update is accepted, they'll increment below.
2901 */
2902 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
2903
2904 /* Update bgp route dampening information. */
2905 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
2906 && peer->sort == BGP_PEER_EBGP) {
2907 /* This is implicit withdraw so we should update
2908 dampening
2909 information. */
2910 if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
2911 bgp_damp_withdraw(ri, rn, afi, safi, 1);
2912 }
65efcfce 2913#if ENABLE_BGP_VNC
d62a17ae 2914 if (safi == SAFI_MPLS_VPN) {
2915 struct bgp_node *prn = NULL;
2916 struct bgp_table *table = NULL;
2917
2918 prn = bgp_node_get(bgp->rib[afi][safi],
2919 (struct prefix *)prd);
2920 if (prn->info) {
2921 table = (struct bgp_table *)(prn->info);
2922
2923 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2924 bgp, prd, table, p, ri);
2925 }
2926 bgp_unlock_node(prn);
2927 }
2928 if ((afi == AFI_IP || afi == AFI_IP6)
2929 && (safi == SAFI_UNICAST)) {
2930 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
2931 /*
2932 * Implicit withdraw case.
2933 */
2934 ++vnc_implicit_withdraw;
2935 vnc_import_bgp_del_route(bgp, p, ri);
2936 vnc_import_bgp_exterior_del_route(bgp, p, ri);
2937 }
2938 }
65efcfce 2939#endif
128ea8ab 2940
d62a17ae 2941 /* Special handling for EVPN update of an existing route. If the
2942 * extended community attribute has changed, we need to
2943 * un-import
2944 * the route using its existing extended community. It will be
2945 * subsequently processed for import with the new extended
2946 * community.
2947 */
2948 if (safi == SAFI_EVPN && !same_attr) {
2949 if ((ri->attr->flag
2950 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
2951 && (attr_new->flag
2952 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
2953 int cmp;
2954
2955 cmp = ecommunity_cmp(ri->attr->ecommunity,
2956 attr_new->ecommunity);
2957 if (!cmp) {
2958 if (bgp_debug_update(peer, p, NULL, 1))
2959 zlog_debug(
2960 "Change in EXT-COMM, existing %s new %s",
2961 ecommunity_str(
2962 ri->attr->ecommunity),
2963 ecommunity_str(
2964 attr_new->ecommunity));
2965 bgp_evpn_unimport_route(bgp, afi, safi,
2966 p, ri);
2967 }
2968 }
2969 }
718e3744 2970
d62a17ae 2971 /* Update to new attribute. */
2972 bgp_attr_unintern(&ri->attr);
2973 ri->attr = attr_new;
2974
2975 /* Update MPLS label */
2976 if (has_valid_label) {
2977 memcpy(&(bgp_info_extra_get(ri))->label, label,
2978 BGP_LABEL_BYTES);
2979 bgp_set_valid_label(&(bgp_info_extra_get(ri))->label);
fc9a856f 2980 }
718e3744 2981
65efcfce 2982#if ENABLE_BGP_VNC
d62a17ae 2983 if ((afi == AFI_IP || afi == AFI_IP6)
2984 && (safi == SAFI_UNICAST)) {
2985 if (vnc_implicit_withdraw) {
2986 /*
2987 * Add back the route with its new attributes
2988 * (e.g., nexthop).
2989 * The route is still selected, until the route
2990 * selection
2991 * queued by bgp_process actually runs. We have
2992 * to make this
2993 * update to the VNC side immediately to avoid
2994 * racing against
2995 * configuration changes (e.g., route-map
2996 * changes) which
2997 * trigger re-importation of the entire RIB.
2998 */
2999 vnc_import_bgp_add_route(bgp, p, ri);
3000 vnc_import_bgp_exterior_add_route(bgp, p, ri);
3001 }
3002 }
65efcfce 3003#endif
d62a17ae 3004 /* Update Overlay Index */
3005 if (afi == AFI_L2VPN) {
3006 overlay_index_update(
3007 ri->attr, evpn == NULL ? NULL : &evpn->eth_s_id,
3008 evpn == NULL ? NULL : &evpn->gw_ip);
3009 }
65efcfce 3010
d62a17ae 3011 /* Update bgp route dampening information. */
3012 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3013 && peer->sort == BGP_PEER_EBGP) {
3014 /* Now we do normal update dampening. */
3015 ret = bgp_damp_update(ri, rn, afi, safi);
3016 if (ret == BGP_DAMP_SUPPRESSED) {
3017 bgp_unlock_node(rn);
3018 return 0;
3019 }
3020 }
128ea8ab 3021
d62a17ae 3022 /* Nexthop reachability check - for unicast and
3023 * labeled-unicast.. */
3024 if ((afi == AFI_IP || afi == AFI_IP6)
3025 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3026 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3027 && !CHECK_FLAG(peer->flags,
3028 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3029 && !bgp_flag_check(
3030 bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3031 connected = 1;
3032 else
3033 connected = 0;
3034
3035 if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL,
02a82b47
LB
3036 connected) ||
3037 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
d62a17ae 3038 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
3039 else {
3040 if (BGP_DEBUG(nht, NHT)) {
3041 char buf1[INET6_ADDRSTRLEN];
3042 inet_ntop(AF_INET,
3043 (const void *)&attr_new
3044 ->nexthop,
3045 buf1, INET6_ADDRSTRLEN);
3046 zlog_debug("%s(%s): NH unresolved",
3047 __FUNCTION__, buf1);
3048 }
3049 bgp_info_unset_flag(rn, ri, BGP_INFO_VALID);
3050 }
3051 } else
3052 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
3053
3054#if ENABLE_BGP_VNC
3055 if (safi == SAFI_MPLS_VPN) {
3056 struct bgp_node *prn = NULL;
3057 struct bgp_table *table = NULL;
3058
3059 prn = bgp_node_get(bgp->rib[afi][safi],
3060 (struct prefix *)prd);
3061 if (prn->info) {
3062 table = (struct bgp_table *)(prn->info);
3063
3064 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3065 bgp, prd, table, p, ri);
3066 }
3067 bgp_unlock_node(prn);
3068 }
3069#endif
718e3744 3070
d62a17ae 3071 /* If this is an EVPN route and some attribute has changed,
3072 * process
3073 * route for import. If the extended community has changed, we
3074 * would
3075 * have done the un-import earlier and the import would result
3076 * in the
3077 * route getting injected into appropriate L2 VNIs. If it is
3078 * just
3079 * some other attribute change, the import will result in
3080 * updating
3081 * the attributes for the route in the VNI(s).
3082 */
3083 if (safi == SAFI_EVPN && !same_attr)
3084 bgp_evpn_import_route(bgp, afi, safi, p, ri);
3085
3086 /* Process change. */
3087 bgp_aggregate_increment(bgp, p, ri, afi, safi);
3088
3089 bgp_process(bgp, rn, afi, safi);
3090 bgp_unlock_node(rn);
558d1fec 3091
28070ee3 3092#if ENABLE_BGP_VNC
d62a17ae 3093 if (SAFI_MPLS_VPN == safi) {
3094 mpls_label_t label_decoded = decode_label(label);
28070ee3 3095
d62a17ae 3096 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3097 type, sub_type, &label_decoded);
3098 }
3099 if (SAFI_ENCAP == safi) {
3100 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3101 type, sub_type, NULL);
3102 }
28070ee3
PZ
3103#endif
3104
d62a17ae 3105 return 0;
3106 } // End of implicit withdraw
718e3744 3107
d62a17ae 3108 /* Received Logging. */
3109 if (bgp_debug_update(peer, p, NULL, 1)) {
3110 if (!peer->rcvd_attr_printed) {
3111 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3112 peer->rcvd_attr_str);
3113 peer->rcvd_attr_printed = 1;
3114 }
718e3744 3115
d62a17ae 3116 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3117 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3118 sizeof(pfx_buf));
3119 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3120 }
718e3744 3121
d62a17ae 3122 /* Make new BGP info. */
3123 new = info_make(type, sub_type, 0, peer, attr_new, rn);
718e3744 3124
d62a17ae 3125 /* Update MPLS label */
3126 if (has_valid_label) {
3127 memcpy(&(bgp_info_extra_get(new))->label, label,
3128 BGP_LABEL_BYTES);
3129 bgp_set_valid_label(&(bgp_info_extra_get(new))->label);
fc9a856f 3130 }
718e3744 3131
d62a17ae 3132 /* Update Overlay Index */
3133 if (afi == AFI_L2VPN) {
3134 overlay_index_update(new->attr,
3135 evpn == NULL ? NULL : &evpn->eth_s_id,
3136 evpn == NULL ? NULL : &evpn->gw_ip);
3137 }
3138 /* Nexthop reachability check. */
3139 if ((afi == AFI_IP || afi == AFI_IP6)
3140 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
3141 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
3142 && !CHECK_FLAG(peer->flags,
3143 PEER_FLAG_DISABLE_CONNECTED_CHECK)
3144 && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
3145 connected = 1;
3146 else
3147 connected = 0;
3148
02a82b47
LB
3149 if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, connected) ||
3150 CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
d62a17ae 3151 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
3152 else {
3153 if (BGP_DEBUG(nht, NHT)) {
3154 char buf1[INET6_ADDRSTRLEN];
3155 inet_ntop(AF_INET,
3156 (const void *)&attr_new->nexthop,
3157 buf1, INET6_ADDRSTRLEN);
3158 zlog_debug("%s(%s): NH unresolved",
3159 __FUNCTION__, buf1);
3160 }
3161 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
3162 }
3163 } else
3164 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
a82478b9 3165
d62a17ae 3166 /* Addpath ID */
3167 new->addpath_rx_id = addpath_id;
3168
3169 /* Increment prefix */
3170 bgp_aggregate_increment(bgp, p, new, afi, safi);
3171
3172 /* Register new BGP information. */
3173 bgp_info_add(rn, new);
3174
3175 /* route_node_get lock */
3176 bgp_unlock_node(rn);
558d1fec 3177
65efcfce 3178#if ENABLE_BGP_VNC
d62a17ae 3179 if (safi == SAFI_MPLS_VPN) {
3180 struct bgp_node *prn = NULL;
3181 struct bgp_table *table = NULL;
3182
3183 prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
3184 if (prn->info) {
3185 table = (struct bgp_table *)(prn->info);
3186
3187 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3188 bgp, prd, table, p, new);
3189 }
3190 bgp_unlock_node(prn);
3191 }
65efcfce
LB
3192#endif
3193
d62a17ae 3194 /* If maximum prefix count is configured and current prefix
3195 count exeed it. */
3196 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3197 return -1;
718e3744 3198
d62a17ae 3199 /* If this is an EVPN route, process for import. */
3200 if (safi == SAFI_EVPN)
3201 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 3202
d62a17ae 3203 /* Process change. */
3204 bgp_process(bgp, rn, afi, safi);
718e3744 3205
28070ee3 3206#if ENABLE_BGP_VNC
d62a17ae 3207 if (SAFI_MPLS_VPN == safi) {
3208 mpls_label_t label_decoded = decode_label(label);
28070ee3 3209
d62a17ae 3210 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3211 sub_type, &label_decoded);
3212 }
3213 if (SAFI_ENCAP == safi) {
3214 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
3215 sub_type, NULL);
3216 }
28070ee3
PZ
3217#endif
3218
d62a17ae 3219 return 0;
718e3744 3220
d62a17ae 3221/* This BGP update is filtered. Log the reason then update BGP
3222 entry. */
3223filtered:
3224 if (bgp_debug_update(peer, p, NULL, 1)) {
3225 if (!peer->rcvd_attr_printed) {
3226 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3227 peer->rcvd_attr_str);
3228 peer->rcvd_attr_printed = 1;
3229 }
718e3744 3230
d62a17ae 3231 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3232 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3233 sizeof(pfx_buf));
3234 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3235 peer->host, pfx_buf, reason);
3236 }
128ea8ab 3237
d62a17ae 3238 if (ri) {
3239 /* If this is an EVPN route, un-import it as it is now filtered.
3240 */
3241 if (safi == SAFI_EVPN)
3242 bgp_evpn_unimport_route(bgp, afi, safi, p, ri);
718e3744 3243
d62a17ae 3244 bgp_rib_remove(rn, ri, peer, afi, safi);
3245 }
3246
3247 bgp_unlock_node(rn);
558d1fec 3248
97736e32 3249#if ENABLE_BGP_VNC
d62a17ae 3250 /*
3251 * Filtered update is treated as an implicit withdrawal (see
3252 * bgp_rib_remove()
3253 * a few lines above)
3254 */
3255 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3256 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3257 0);
3258 }
97736e32
PZ
3259#endif
3260
d62a17ae 3261 return 0;
718e3744 3262}
3263
d62a17ae 3264int bgp_withdraw(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
3265 struct attr *attr, afi_t afi, safi_t safi, int type,
3266 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
3267 struct bgp_route_evpn *evpn)
718e3744 3268{
d62a17ae 3269 struct bgp *bgp;
3270 char pfx_buf[BGP_PRD_PATH_STRLEN];
3271 struct bgp_node *rn;
3272 struct bgp_info *ri;
718e3744 3273
28070ee3 3274#if ENABLE_BGP_VNC
d62a17ae 3275 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
3276 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
3277 0);
3278 }
28070ee3
PZ
3279#endif
3280
d62a17ae 3281 bgp = peer->bgp;
3282
3283 /* Lookup node. */
3284 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
3285
3286 /* If peer is soft reconfiguration enabled. Record input packet for
3287 * further calculation.
3288 *
3289 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3290 * routes that are filtered. This tanks out Quagga RS pretty badly due
3291 * to
3292 * the iteration over all RS clients.
3293 * Since we need to remove the entry from adj_in anyway, do that first
3294 * and
3295 * if there was no entry, we don't need to do anything more.
3296 */
3297 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3298 && peer != bgp->peer_self)
3299 if (!bgp_adj_in_unset(rn, peer, addpath_id)) {
3300 if (bgp_debug_update(peer, p, NULL, 1)) {
3301 bgp_debug_rdpfxpath2str(
3302 afi, safi, prd, p, label,
3303 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3304 sizeof(pfx_buf));
3305 zlog_debug(
3306 "%s withdrawing route %s not in adj-in",
3307 peer->host, pfx_buf);
3308 }
3309 bgp_unlock_node(rn);
3310 return 0;
3311 }
cd808e74 3312
d62a17ae 3313 /* Lookup withdrawn route. */
3314 for (ri = rn->info; ri; ri = ri->next)
3315 if (ri->peer == peer && ri->type == type
3316 && ri->sub_type == sub_type
3317 && ri->addpath_rx_id == addpath_id)
3318 break;
3319
3320 /* Logging. */
3321 if (bgp_debug_update(peer, p, NULL, 1)) {
3322 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3323 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3324 sizeof(pfx_buf));
3325 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
3326 pfx_buf);
3327 }
718e3744 3328
d62a17ae 3329 /* Withdraw specified route from routing table. */
3330 if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
3331 bgp_rib_withdraw(rn, ri, peer, afi, safi, prd);
3332 else if (bgp_debug_update(peer, p, NULL, 1)) {
3333 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3334 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3335 sizeof(pfx_buf));
3336 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
3337 }
718e3744 3338
d62a17ae 3339 /* Unlock bgp_node_get() lock. */
3340 bgp_unlock_node(rn);
3341
3342 return 0;
718e3744 3343}
6b0655a2 3344
d62a17ae 3345void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
3346 int withdraw)
718e3744 3347{
d62a17ae 3348 struct update_subgroup *subgrp;
3349 subgrp = peer_subgroup(peer, afi, safi);
3350 subgroup_default_originate(subgrp, withdraw);
3f9c7369 3351}
6182d65b 3352
718e3744 3353
3f9c7369
DS
3354/*
3355 * bgp_stop_announce_route_timer
3356 */
d62a17ae 3357void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 3358{
d62a17ae 3359 if (!paf->t_announce_route)
3360 return;
3361
3362 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 3363}
6b0655a2 3364
3f9c7369
DS
3365/*
3366 * bgp_announce_route_timer_expired
3367 *
3368 * Callback that is invoked when the route announcement timer for a
3369 * peer_af expires.
3370 */
d62a17ae 3371static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 3372{
d62a17ae 3373 struct peer_af *paf;
3374 struct peer *peer;
558d1fec 3375
d62a17ae 3376 paf = THREAD_ARG(t);
3377 peer = paf->peer;
718e3744 3378
d62a17ae 3379 if (peer->status != Established)
3380 return 0;
3f9c7369 3381
d62a17ae 3382 if (!peer->afc_nego[paf->afi][paf->safi])
3383 return 0;
3f9c7369 3384
d62a17ae 3385 peer_af_announce_route(paf, 1);
3386 return 0;
718e3744 3387}
3388
3f9c7369
DS
3389/*
3390 * bgp_announce_route
3391 *
3392 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3393 */
d62a17ae 3394void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
3395{
3396 struct peer_af *paf;
3397 struct update_subgroup *subgrp;
3398
3399 paf = peer_af_find(peer, afi, safi);
3400 if (!paf)
3401 return;
3402 subgrp = PAF_SUBGRP(paf);
3403
3404 /*
3405 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3406 * or a refresh has already been triggered.
3407 */
3408 if (!subgrp || paf->t_announce_route)
3409 return;
3410
3411 /*
3412 * Start a timer to stagger/delay the announce. This serves
3413 * two purposes - announcement can potentially be combined for
3414 * multiple peers and the announcement doesn't happen in the
3415 * vty context.
3416 */
3417 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
3418 (subgrp->peer_count == 1)
3419 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3420 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
3421 &paf->t_announce_route);
3f9c7369
DS
3422}
3423
3424/*
3425 * Announce routes from all AF tables to a peer.
3426 *
3427 * This should ONLY be called when there is a need to refresh the
3428 * routes to the peer based on a policy change for this peer alone
3429 * or a route refresh request received from the peer.
3430 * The operation will result in splitting the peer from its existing
3431 * subgroups and putting it in new subgroups.
3432 */
d62a17ae 3433void bgp_announce_route_all(struct peer *peer)
718e3744 3434{
d62a17ae 3435 afi_t afi;
3436 safi_t safi;
3437
05c7a1cc
QY
3438 FOREACH_AFI_SAFI (afi, safi)
3439 bgp_announce_route(peer, afi, safi);
718e3744 3440}
6b0655a2 3441
d62a17ae 3442static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
3443 struct bgp_table *table,
3444 struct prefix_rd *prd)
718e3744 3445{
d62a17ae 3446 int ret;
3447 struct bgp_node *rn;
3448 struct bgp_adj_in *ain;
718e3744 3449
d62a17ae 3450 if (!table)
3451 table = peer->bgp->rib[afi][safi];
718e3744 3452
d62a17ae 3453 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3454 for (ain = rn->adj_in; ain; ain = ain->next) {
ea47320b
DL
3455 if (ain->peer != peer)
3456 continue;
8692c506 3457
ea47320b 3458 struct bgp_info *ri = rn->info;
60466a63
QY
3459 mpls_label_t label = (ri && ri->extra)
3460 ? ri->extra->label
3461 : MPLS_INVALID_LABEL;
8692c506 3462
ea47320b
DL
3463 ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
3464 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
3465 BGP_ROUTE_NORMAL, prd, &label, 1,
3466 NULL);
3467
3468 if (ret < 0) {
3469 bgp_unlock_node(rn);
3470 return;
d62a17ae 3471 }
3472 }
718e3744 3473}
3474
d62a17ae 3475void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3476{
d62a17ae 3477 struct bgp_node *rn;
3478 struct bgp_table *table;
718e3744 3479
d62a17ae 3480 if (peer->status != Established)
3481 return;
718e3744 3482
d62a17ae 3483 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
3484 && (safi != SAFI_EVPN))
3485 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
3486 else
3487 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3488 rn = bgp_route_next(rn))
3489 if ((table = rn->info) != NULL) {
3490 struct prefix_rd prd;
3491 prd.family = AF_UNSPEC;
3492 prd.prefixlen = 64;
3493 memcpy(&prd.val, rn->p.u.val, 8);
8692c506 3494
d62a17ae 3495 bgp_soft_reconfig_table(peer, afi, safi, table,
3496 &prd);
3497 }
718e3744 3498}
6b0655a2 3499
228da428 3500
d62a17ae 3501struct bgp_clear_node_queue {
3502 struct bgp_node *rn;
228da428
CC
3503};
3504
d62a17ae 3505static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 3506{
d62a17ae 3507 struct bgp_clear_node_queue *cnq = data;
3508 struct bgp_node *rn = cnq->rn;
3509 struct peer *peer = wq->spec.data;
3510 struct bgp_info *ri;
3511 afi_t afi = bgp_node_table(rn)->afi;
3512 safi_t safi = bgp_node_table(rn)->safi;
3513
3514 assert(rn && peer);
3515
3516 /* It is possible that we have multiple paths for a prefix from a peer
3517 * if that peer is using AddPath.
3518 */
ea47320b
DL
3519 for (ri = rn->info; ri; ri = ri->next) {
3520 if (ri->peer != peer)
3521 continue;
3522
3523 /* graceful restart STALE flag set. */
3524 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
3525 && peer->nsf[afi][safi]
3526 && !CHECK_FLAG(ri->flags, BGP_INFO_STALE)
3527 && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
3528 bgp_info_set_flag(rn, ri, BGP_INFO_STALE);
3529 else {
3530 /* If this is an EVPN route, process for
3531 * un-import. */
3532 if (safi == SAFI_EVPN)
3533 bgp_evpn_unimport_route(peer->bgp, afi, safi,
3534 &rn->p, ri);
3535 bgp_rib_remove(rn, ri, peer, afi, safi);
d62a17ae 3536 }
ea47320b 3537 }
d62a17ae 3538 return WQ_SUCCESS;
200df115 3539}
3540
d62a17ae 3541static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 3542{
d62a17ae 3543 struct bgp_clear_node_queue *cnq = data;
3544 struct bgp_node *rn = cnq->rn;
3545 struct bgp_table *table = bgp_node_table(rn);
228da428 3546
d62a17ae 3547 bgp_unlock_node(rn);
3548 bgp_table_unlock(table);
3549 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 3550}
3551
d62a17ae 3552static void bgp_clear_node_complete(struct work_queue *wq)
200df115 3553{
d62a17ae 3554 struct peer *peer = wq->spec.data;
64e580a7 3555
d62a17ae 3556 /* Tickle FSM to start moving again */
3557 BGP_EVENT_ADD(peer, Clearing_Completed);
3558
3559 peer_unlock(peer); /* bgp_clear_route */
200df115 3560}
718e3744 3561
d62a17ae 3562static void bgp_clear_node_queue_init(struct peer *peer)
200df115 3563{
d62a17ae 3564 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3565
3566 snprintf(wname, sizeof(wname), "clear %s", peer->host);
3567#undef CLEAR_QUEUE_NAME_LEN
3568
3569 if ((peer->clear_node_queue = work_queue_new(bm->master, wname))
3570 == NULL) {
3571 zlog_err("%s: Failed to allocate work queue", __func__);
3572 exit(1);
0c6262ed 3573 }
d62a17ae 3574 peer->clear_node_queue->spec.hold = 10;
3575 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
3576 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
3577 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
3578 peer->clear_node_queue->spec.max_retries = 0;
3579
3580 /* we only 'lock' this peer reference when the queue is actually active
3581 */
3582 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
3583}
3584
d62a17ae 3585static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
3586 struct bgp_table *table)
65ca75e0 3587{
d62a17ae 3588 struct bgp_node *rn;
3589 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 3590
d62a17ae 3591 if (!table)
3592 table = peer->bgp->rib[afi][safi];
dc83d712 3593
d62a17ae 3594 /* If still no table => afi/safi isn't configured at all or smth. */
3595 if (!table)
3596 return;
dc83d712 3597
d62a17ae 3598 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
3599 struct bgp_info *ri, *next;
3600 struct bgp_adj_in *ain;
3601 struct bgp_adj_in *ain_next;
3602
3603 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3604 * queued for every clearing peer, regardless of whether it is
3605 * relevant to the peer at hand.
3606 *
3607 * Overview: There are 3 different indices which need to be
3608 * scrubbed, potentially, when a peer is removed:
3609 *
3610 * 1 peer's routes visible via the RIB (ie accepted routes)
3611 * 2 peer's routes visible by the (optional) peer's adj-in index
3612 * 3 other routes visible by the peer's adj-out index
3613 *
3614 * 3 there is no hurry in scrubbing, once the struct peer is
3615 * removed from bgp->peer, we could just GC such deleted peer's
3616 * adj-outs at our leisure.
3617 *
3618 * 1 and 2 must be 'scrubbed' in some way, at least made
3619 * invisible via RIB index before peer session is allowed to be
3620 * brought back up. So one needs to know when such a 'search' is
3621 * complete.
3622 *
3623 * Ideally:
3624 *
3625 * - there'd be a single global queue or a single RIB walker
3626 * - rather than tracking which route_nodes still need to be
3627 * examined on a peer basis, we'd track which peers still
3628 * aren't cleared
3629 *
3630 * Given that our per-peer prefix-counts now should be reliable,
3631 * this may actually be achievable. It doesn't seem to be a huge
3632 * problem at this time,
3633 *
3634 * It is possible that we have multiple paths for a prefix from
3635 * a peer
3636 * if that peer is using AddPath.
3637 */
3638 ain = rn->adj_in;
3639 while (ain) {
3640 ain_next = ain->next;
3641
3642 if (ain->peer == peer) {
3643 bgp_adj_in_remove(rn, ain);
3644 bgp_unlock_node(rn);
3645 }
3646
3647 ain = ain_next;
3648 }
3649
3650 for (ri = rn->info; ri; ri = next) {
3651 next = ri->next;
3652 if (ri->peer != peer)
3653 continue;
3654
3655 if (force)
3656 bgp_info_reap(rn, ri);
3657 else {
3658 struct bgp_clear_node_queue *cnq;
3659
3660 /* both unlocked in bgp_clear_node_queue_del */
3661 bgp_table_lock(bgp_node_table(rn));
3662 bgp_lock_node(rn);
3663 cnq = XCALLOC(
3664 MTYPE_BGP_CLEAR_NODE_QUEUE,
3665 sizeof(struct bgp_clear_node_queue));
3666 cnq->rn = rn;
3667 work_queue_add(peer->clear_node_queue, cnq);
3668 break;
3669 }
3670 }
3671 }
3672 return;
3673}
3674
3675void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
3676{
3677 struct bgp_node *rn;
3678 struct bgp_table *table;
3679
3680 if (peer->clear_node_queue == NULL)
3681 bgp_clear_node_queue_init(peer);
3682
3683 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3684 * Idle until it receives a Clearing_Completed event. This protects
3685 * against peers which flap faster than we can we clear, which could
3686 * lead to:
3687 *
3688 * a) race with routes from the new session being installed before
3689 * clear_route_node visits the node (to delete the route of that
3690 * peer)
3691 * b) resource exhaustion, clear_route_node likely leads to an entry
3692 * on the process_main queue. Fast-flapping could cause that queue
3693 * to grow and grow.
3694 */
3695
3696 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3697 * the unlock will happen upon work-queue completion; other wise, the
3698 * unlock happens at the end of this function.
3699 */
3700 if (!peer->clear_node_queue->thread)
3701 peer_lock(peer);
3702
3703 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
3704 bgp_clear_route_table(peer, afi, safi, NULL);
3705 else
3706 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3707 rn = bgp_route_next(rn))
3708 if ((table = rn->info) != NULL)
3709 bgp_clear_route_table(peer, afi, safi, table);
3710
3711 /* unlock if no nodes got added to the clear-node-queue. */
3712 if (!peer->clear_node_queue->thread)
3713 peer_unlock(peer);
718e3744 3714}
d62a17ae 3715
3716void bgp_clear_route_all(struct peer *peer)
718e3744 3717{
d62a17ae 3718 afi_t afi;
3719 safi_t safi;
718e3744 3720
05c7a1cc
QY
3721 FOREACH_AFI_SAFI (afi, safi)
3722 bgp_clear_route(peer, afi, safi);
65efcfce
LB
3723
3724#if ENABLE_BGP_VNC
d62a17ae 3725 rfapiProcessPeerDown(peer);
65efcfce 3726#endif
718e3744 3727}
3728
d62a17ae 3729void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 3730{
d62a17ae 3731 struct bgp_table *table;
3732 struct bgp_node *rn;
3733 struct bgp_adj_in *ain;
3734 struct bgp_adj_in *ain_next;
718e3744 3735
d62a17ae 3736 table = peer->bgp->rib[afi][safi];
718e3744 3737
d62a17ae 3738 /* It is possible that we have multiple paths for a prefix from a peer
3739 * if that peer is using AddPath.
3740 */
3741 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
3742 ain = rn->adj_in;
43143c8f 3743
d62a17ae 3744 while (ain) {
3745 ain_next = ain->next;
43143c8f 3746
d62a17ae 3747 if (ain->peer == peer) {
3748 bgp_adj_in_remove(rn, ain);
3749 bgp_unlock_node(rn);
3750 }
43143c8f 3751
d62a17ae 3752 ain = ain_next;
3753 }
3754 }
718e3744 3755}
93406d87 3756
d62a17ae 3757void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
3758{
3759 struct bgp_node *rn;
3760 struct bgp_info *ri;
3761 struct bgp_table *table;
3762
3763 if (safi == SAFI_MPLS_VPN) {
3764 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3765 rn = bgp_route_next(rn)) {
3766 struct bgp_node *rm;
3767 struct bgp_info *ri;
3768
3769 /* look for neighbor in tables */
ea47320b
DL
3770 if ((table = rn->info) == NULL)
3771 continue;
3772
3773 for (rm = bgp_table_top(table); rm;
3774 rm = bgp_route_next(rm))
3775 for (ri = rm->info; ri; ri = ri->next) {
3776 if (ri->peer != peer)
3777 continue;
3778 if (!CHECK_FLAG(ri->flags,
3779 BGP_INFO_STALE))
3780 break;
3781
3782 bgp_rib_remove(rm, ri, peer, afi, safi);
3783 break;
3784 }
d62a17ae 3785 }
3786 } else {
3787 for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
3788 rn = bgp_route_next(rn))
ea47320b
DL
3789 for (ri = rn->info; ri; ri = ri->next) {
3790 if (ri->peer != peer)
3791 continue;
3792 if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE))
d62a17ae 3793 break;
ea47320b
DL
3794 bgp_rib_remove(rn, ri, peer, afi, safi);
3795 break;
3796 }
d62a17ae 3797 }
93406d87 3798}
6b0655a2 3799
d62a17ae 3800static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
bb86c601 3801{
d62a17ae 3802 struct bgp_node *rn;
3803 struct bgp_info *ri;
3804 struct bgp_info *next;
bb86c601 3805
d62a17ae 3806 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
3807 for (ri = rn->info; ri; ri = next) {
3808 next = ri->next;
3809 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
3810 && ri->type == ZEBRA_ROUTE_BGP
3811 && (ri->sub_type == BGP_ROUTE_NORMAL
3812 || ri->sub_type == BGP_ROUTE_AGGREGATE)) {
3813 if (bgp_fibupd_safi(safi))
3814 bgp_zebra_withdraw(&rn->p, ri, safi);
3815 bgp_info_reap(rn, ri);
3816 }
3817 }
bb86c601
LB
3818}
3819
718e3744 3820/* Delete all kernel routes. */
d62a17ae 3821void bgp_cleanup_routes(struct bgp *bgp)
3822{
3823 afi_t afi;
3824 struct bgp_node *rn;
3825
3826 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
3827 if (afi == AFI_L2VPN)
3828 continue;
3829 bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST);
3830 /*
3831 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3832 */
3833 if (afi != AFI_L2VPN) {
3834 safi_t safi;
3835 safi = SAFI_MPLS_VPN;
3836 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
3837 rn = bgp_route_next(rn)) {
3838 if (rn->info) {
3839 bgp_cleanup_table(
3840 (struct bgp_table *)(rn->info),
3841 safi);
3842 bgp_table_finish((struct bgp_table **)&(
3843 rn->info));
3844 rn->info = NULL;
3845 bgp_unlock_node(rn);
3846 }
3847 }
3848 safi = SAFI_ENCAP;
3849 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
3850 rn = bgp_route_next(rn)) {
3851 if (rn->info) {
3852 bgp_cleanup_table(
3853 (struct bgp_table *)(rn->info),
3854 safi);
3855 bgp_table_finish((struct bgp_table **)&(
3856 rn->info));
3857 rn->info = NULL;
3858 bgp_unlock_node(rn);
3859 }
3860 }
3861 }
3862 }
3863 for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
3864 rn = bgp_route_next(rn)) {
3865 if (rn->info) {
3866 bgp_cleanup_table((struct bgp_table *)(rn->info),
3867 SAFI_EVPN);
3868 bgp_table_finish((struct bgp_table **)&(rn->info));
3869 rn->info = NULL;
3870 bgp_unlock_node(rn);
3871 }
bb86c601 3872 }
718e3744 3873}
3874
d62a17ae 3875void bgp_reset(void)
718e3744 3876{
d62a17ae 3877 vty_reset();
3878 bgp_zclient_reset();
3879 access_list_reset();
3880 prefix_list_reset();
718e3744 3881}
6b0655a2 3882
d62a17ae 3883static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 3884{
d62a17ae 3885 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
3886 && CHECK_FLAG(peer->af_cap[afi][safi],
3887 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
3888}
3889
718e3744 3890/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3891 value. */
d62a17ae 3892int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
3893 struct bgp_nlri *packet)
3894{
3895 u_char *pnt;
3896 u_char *lim;
3897 struct prefix p;
3898 int psize;
3899 int ret;
3900 afi_t afi;
3901 safi_t safi;
3902 int addpath_encoded;
3903 u_int32_t addpath_id;
3904
3905 /* Check peer status. */
3906 if (peer->status != Established)
3907 return 0;
3908
3909 pnt = packet->nlri;
3910 lim = pnt + packet->length;
3911 afi = packet->afi;
3912 safi = packet->safi;
3913 addpath_id = 0;
3914 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
3915
3916 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3917 syntactic validity. If the field is syntactically incorrect,
3918 then the Error Subcode is set to Invalid Network Field. */
3919 for (; pnt < lim; pnt += psize) {
3920 /* Clear prefix structure. */
3921 memset(&p, 0, sizeof(struct prefix));
3922
3923 if (addpath_encoded) {
3924
3925 /* When packet overflow occurs return immediately. */
3926 if (pnt + BGP_ADDPATH_ID_LEN > lim)
3927 return -1;
3928
3929 addpath_id = ntohl(*((uint32_t *)pnt));
3930 pnt += BGP_ADDPATH_ID_LEN;
3931 }
718e3744 3932
d62a17ae 3933 /* Fetch prefix length. */
3934 p.prefixlen = *pnt++;
3935 /* afi/safi validity already verified by caller,
3936 * bgp_update_receive */
3937 p.family = afi2family(afi);
3938
3939 /* Prefix length check. */
3940 if (p.prefixlen > prefix_blen(&p) * 8) {
3941 zlog_err(
3942 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3943 peer->host, p.prefixlen, packet->afi);
3944 return -1;
3945 }
6b0655a2 3946
d62a17ae 3947 /* Packet size overflow check. */
3948 psize = PSIZE(p.prefixlen);
3949
3950 /* When packet overflow occur return immediately. */
3951 if (pnt + psize > lim) {
3952 zlog_err(
3953 "%s [Error] Update packet error (prefix length %d overflows packet)",
3954 peer->host, p.prefixlen);
3955 return -1;
3956 }
3957
3958 /* Defensive coding, double-check the psize fits in a struct
3959 * prefix */
3960 if (psize > (ssize_t)sizeof(p.u)) {
3961 zlog_err(
3962 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3963 peer->host, p.prefixlen, sizeof(p.u));
3964 return -1;
3965 }
3966
3967 /* Fetch prefix from NLRI packet. */
3968 memcpy(&p.u.prefix, pnt, psize);
3969
3970 /* Check address. */
3971 if (afi == AFI_IP && safi == SAFI_UNICAST) {
3972 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
3973 /* From RFC4271 Section 6.3:
3974 *
3975 * If a prefix in the NLRI field is semantically
3976 * incorrect
3977 * (e.g., an unexpected multicast IP address),
3978 * an error SHOULD
3979 * be logged locally, and the prefix SHOULD be
3980 * ignored.
9d303b37 3981 */
d62a17ae 3982 zlog_err(
3983 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3984 peer->host, inet_ntoa(p.u.prefix4));
3985 continue;
3986 }
3987 }
3988
3989 /* Check address. */
3990 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
3991 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
3992 char buf[BUFSIZ];
3993
3994 zlog_err(
3995 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3996 peer->host,
3997 inet_ntop(AF_INET6, &p.u.prefix6, buf,
3998 BUFSIZ));
3999
4000 continue;
4001 }
4002 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
4003 char buf[BUFSIZ];
4004
4005 zlog_err(
4006 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4007 peer->host,
4008 inet_ntop(AF_INET6, &p.u.prefix6, buf,
4009 BUFSIZ));
4010
4011 continue;
4012 }
4013 }
4014
4015 /* Normal process. */
4016 if (attr)
4017 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
4018 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
4019 NULL, NULL, 0, NULL);
4020 else
4021 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
4022 safi, ZEBRA_ROUTE_BGP,
4023 BGP_ROUTE_NORMAL, NULL, NULL, NULL);
4024
4025 /* Address family configuration mismatch or maximum-prefix count
4026 overflow. */
4027 if (ret < 0)
4028 return -1;
4029 }
4030
4031 /* Packet length consistency check. */
4032 if (pnt != lim) {
4033 zlog_err(
4034 "%s [Error] Update packet error (prefix length mismatch with total length)",
4035 peer->host);
4036 return -1;
4037 }
6b0655a2 4038
d62a17ae 4039 return 0;
718e3744 4040}
4041
d62a17ae 4042static struct bgp_static *bgp_static_new(void)
718e3744 4043{
d62a17ae 4044 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 4045}
4046
d62a17ae 4047static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 4048{
d62a17ae 4049 if (bgp_static->rmap.name)
4050 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4051 if (bgp_static->eth_s_id)
4052 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
4053 XFREE(MTYPE_BGP_STATIC, bgp_static);
4054}
4055
4056void bgp_static_update(struct bgp *bgp, struct prefix *p,
4057 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
4058{
4059 struct bgp_node *rn;
4060 struct bgp_info *ri;
4061 struct bgp_info *new;
4062 struct bgp_info info;
4063 struct attr attr;
4064 struct attr *attr_new;
4065 int ret;
65efcfce 4066#if ENABLE_BGP_VNC
d62a17ae 4067 int vnc_implicit_withdraw = 0;
65efcfce 4068#endif
fee0f4c6 4069
d62a17ae 4070 assert(bgp_static);
4071 if (!bgp_static)
4072 return;
dd8103a9 4073
d62a17ae 4074 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4075
d62a17ae 4076 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 4077
d62a17ae 4078 attr.nexthop = bgp_static->igpnexthop;
4079 attr.med = bgp_static->igpmetric;
4080 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 4081
d62a17ae 4082 if (bgp_static->atomic)
4083 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 4084
d62a17ae 4085 /* Store label index, if required. */
4086 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
4087 attr.label_index = bgp_static->label_index;
4088 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
4089 }
718e3744 4090
d62a17ae 4091 /* Apply route-map. */
4092 if (bgp_static->rmap.name) {
4093 struct attr attr_tmp = attr;
4094 info.peer = bgp->peer_self;
4095 info.attr = &attr_tmp;
fee0f4c6 4096
d62a17ae 4097 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 4098
d62a17ae 4099 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
fee0f4c6 4100
d62a17ae 4101 bgp->peer_self->rmap_type = 0;
718e3744 4102
d62a17ae 4103 if (ret == RMAP_DENYMATCH) {
4104 /* Free uninterned attribute. */
4105 bgp_attr_flush(&attr_tmp);
718e3744 4106
d62a17ae 4107 /* Unintern original. */
4108 aspath_unintern(&attr.aspath);
4109 bgp_static_withdraw(bgp, p, afi, safi);
4110 return;
4111 }
7f323236
DW
4112
4113 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4114 bgp_attr_add_gshut_community(&attr_tmp);
4115
d62a17ae 4116 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
4117 } else {
4118
4119 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
4120 bgp_attr_add_gshut_community(&attr);
4121
d62a17ae 4122 attr_new = bgp_attr_intern(&attr);
7f323236 4123 }
718e3744 4124
d62a17ae 4125 for (ri = rn->info; ri; ri = ri->next)
4126 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4127 && ri->sub_type == BGP_ROUTE_STATIC)
4128 break;
4129
4130 if (ri) {
4131 if (attrhash_cmp(ri->attr, attr_new)
4132 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
4133 && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
4134 bgp_unlock_node(rn);
4135 bgp_attr_unintern(&attr_new);
4136 aspath_unintern(&attr.aspath);
4137 return;
4138 } else {
4139 /* The attribute is changed. */
4140 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4141
4142 /* Rewrite BGP route information. */
4143 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4144 bgp_info_restore(rn, ri);
4145 else
4146 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
65efcfce 4147#if ENABLE_BGP_VNC
d62a17ae 4148 if ((afi == AFI_IP || afi == AFI_IP6)
4149 && (safi == SAFI_UNICAST)) {
4150 if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
4151 /*
4152 * Implicit withdraw case.
4153 * We have to do this before ri is
4154 * changed
4155 */
4156 ++vnc_implicit_withdraw;
4157 vnc_import_bgp_del_route(bgp, p, ri);
4158 vnc_import_bgp_exterior_del_route(
4159 bgp, p, ri);
4160 }
4161 }
65efcfce 4162#endif
d62a17ae 4163 bgp_attr_unintern(&ri->attr);
4164 ri->attr = attr_new;
4165 ri->uptime = bgp_clock();
65efcfce 4166#if ENABLE_BGP_VNC
d62a17ae 4167 if ((afi == AFI_IP || afi == AFI_IP6)
4168 && (safi == SAFI_UNICAST)) {
4169 if (vnc_implicit_withdraw) {
4170 vnc_import_bgp_add_route(bgp, p, ri);
4171 vnc_import_bgp_exterior_add_route(
4172 bgp, p, ri);
4173 }
4174 }
65efcfce 4175#endif
718e3744 4176
d62a17ae 4177 /* Nexthop reachability check. */
4178 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4179 && (safi == SAFI_UNICAST
4180 || safi == SAFI_LABELED_UNICAST)) {
4181 if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL,
4182 0))
4183 bgp_info_set_flag(rn, ri,
4184 BGP_INFO_VALID);
4185 else {
4186 if (BGP_DEBUG(nht, NHT)) {
4187 char buf1[INET6_ADDRSTRLEN];
4188 inet_ntop(p->family,
4189 &p->u.prefix, buf1,
4190 INET6_ADDRSTRLEN);
4191 zlog_debug(
4192 "%s(%s): Route not in table, not advertising",
4193 __FUNCTION__, buf1);
4194 }
4195 bgp_info_unset_flag(rn, ri,
4196 BGP_INFO_VALID);
4197 }
4198 } else {
4199 /* Delete the NHT structure if any, if we're
4200 * toggling between
4201 * enabling/disabling import check. We
4202 * deregister the route
4203 * from NHT to avoid overloading NHT and the
4204 * process interaction
4205 */
4206 bgp_unlink_nexthop(ri);
4207 bgp_info_set_flag(rn, ri, BGP_INFO_VALID);
4208 }
4209 /* Process change. */
4210 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4211 bgp_process(bgp, rn, afi, safi);
4212 bgp_unlock_node(rn);
4213 aspath_unintern(&attr.aspath);
4214 return;
4215 }
718e3744 4216 }
718e3744 4217
d62a17ae 4218 /* Make new BGP info. */
4219 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4220 attr_new, rn);
4221 /* Nexthop reachability check. */
4222 if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
4223 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4224 if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, 0))
4225 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
4226 else {
4227 if (BGP_DEBUG(nht, NHT)) {
4228 char buf1[INET6_ADDRSTRLEN];
4229 inet_ntop(p->family, &p->u.prefix, buf1,
4230 INET6_ADDRSTRLEN);
4231 zlog_debug(
4232 "%s(%s): Route not in table, not advertising",
4233 __FUNCTION__, buf1);
4234 }
4235 bgp_info_unset_flag(rn, new, BGP_INFO_VALID);
4236 }
4237 } else {
4238 /* Delete the NHT structure if any, if we're toggling between
4239 * enabling/disabling import check. We deregister the route
4240 * from NHT to avoid overloading NHT and the process interaction
4241 */
4242 bgp_unlink_nexthop(new);
4243
4244 bgp_info_set_flag(rn, new, BGP_INFO_VALID);
fc9a856f 4245 }
078430f6 4246
d62a17ae 4247 /* Aggregate address increment. */
4248 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 4249
d62a17ae 4250 /* Register new BGP information. */
4251 bgp_info_add(rn, new);
718e3744 4252
d62a17ae 4253 /* route_node_get lock */
4254 bgp_unlock_node(rn);
4255
4256 /* Process change. */
4257 bgp_process(bgp, rn, afi, safi);
4258
4259 /* Unintern original. */
4260 aspath_unintern(&attr.aspath);
718e3744 4261}
4262
d62a17ae 4263void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
4264 safi_t safi)
718e3744 4265{
d62a17ae 4266 struct bgp_node *rn;
4267 struct bgp_info *ri;
718e3744 4268
d62a17ae 4269 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 4270
d62a17ae 4271 /* Check selected route and self inserted route. */
4272 for (ri = rn->info; ri; ri = ri->next)
4273 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4274 && ri->sub_type == BGP_ROUTE_STATIC)
4275 break;
4276
4277 /* Withdraw static BGP route from routing table. */
4278 if (ri) {
4279 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4280 bgp_unlink_nexthop(ri);
4281 bgp_info_delete(rn, ri);
4282 bgp_process(bgp, rn, afi, safi);
4283 }
718e3744 4284
d62a17ae 4285 /* Unlock bgp_node_lookup. */
4286 bgp_unlock_node(rn);
718e3744 4287}
4288
137446f9
LB
4289/*
4290 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4291 */
d62a17ae 4292static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
4293 afi_t afi, safi_t safi,
4294 struct prefix_rd *prd)
718e3744 4295{
d62a17ae 4296 struct bgp_node *rn;
4297 struct bgp_info *ri;
718e3744 4298
d62a17ae 4299 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 4300
d62a17ae 4301 /* Check selected route and self inserted route. */
4302 for (ri = rn->info; ri; ri = ri->next)
4303 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4304 && ri->sub_type == BGP_ROUTE_STATIC)
4305 break;
718e3744 4306
d62a17ae 4307 /* Withdraw static BGP route from routing table. */
4308 if (ri) {
65efcfce 4309#if ENABLE_BGP_VNC
d62a17ae 4310 rfapiProcessWithdraw(
4311 ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type,
4312 1); /* Kill, since it is an administrative change */
65efcfce 4313#endif
d62a17ae 4314 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4315 bgp_info_delete(rn, ri);
4316 bgp_process(bgp, rn, afi, safi);
4317 }
718e3744 4318
d62a17ae 4319 /* Unlock bgp_node_lookup. */
4320 bgp_unlock_node(rn);
718e3744 4321}
4322
d62a17ae 4323static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
4324 struct bgp_static *bgp_static, afi_t afi,
4325 safi_t safi)
137446f9 4326{
d62a17ae 4327 struct bgp_node *rn;
4328 struct bgp_info *new;
4329 struct attr *attr_new;
4330 struct attr attr = {0};
4331 struct bgp_info *ri;
65efcfce 4332#if ENABLE_BGP_VNC
d62a17ae 4333 mpls_label_t label = 0;
65efcfce 4334#endif
d62a17ae 4335 union gw_addr add;
137446f9 4336
d62a17ae 4337 assert(bgp_static);
137446f9 4338
d62a17ae 4339 rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
4340 &bgp_static->prd);
137446f9 4341
d62a17ae 4342 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 4343
d62a17ae 4344 attr.nexthop = bgp_static->igpnexthop;
4345 attr.med = bgp_static->igpmetric;
4346 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 4347
d62a17ae 4348 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
4349 || (safi == SAFI_ENCAP)) {
4350 if (afi == AFI_IP) {
4351 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
4352 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
4353 }
4354 }
4355 if (afi == AFI_L2VPN) {
4356 if (bgp_static->gatewayIp.family == AF_INET)
4357 add.ipv4.s_addr =
4358 bgp_static->gatewayIp.u.prefix4.s_addr;
4359 else if (bgp_static->gatewayIp.family == AF_INET6)
4360 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
4361 sizeof(struct in6_addr));
4362 overlay_index_update(&attr, bgp_static->eth_s_id, &add);
4363 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
4364 struct bgp_encap_type_vxlan bet;
4365 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
4366 bet.vnid = p->u.prefix_evpn.eth_tag;
4367 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4368 }
4369 if (bgp_static->router_mac) {
4370 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
4371 }
4372 }
4373 /* Apply route-map. */
4374 if (bgp_static->rmap.name) {
4375 struct attr attr_tmp = attr;
4376 struct bgp_info info;
4377 int ret;
137446f9 4378
d62a17ae 4379 info.peer = bgp->peer_self;
4380 info.attr = &attr_tmp;
137446f9 4381
d62a17ae 4382 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 4383
d62a17ae 4384 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info);
137446f9 4385
d62a17ae 4386 bgp->peer_self->rmap_type = 0;
137446f9 4387
d62a17ae 4388 if (ret == RMAP_DENYMATCH) {
4389 /* Free uninterned attribute. */
4390 bgp_attr_flush(&attr_tmp);
137446f9 4391
d62a17ae 4392 /* Unintern original. */
4393 aspath_unintern(&attr.aspath);
4394 bgp_static_withdraw_safi(bgp, p, afi, safi,
4395 &bgp_static->prd);
4396 return;
4397 }
137446f9 4398
d62a17ae 4399 attr_new = bgp_attr_intern(&attr_tmp);
4400 } else {
4401 attr_new = bgp_attr_intern(&attr);
4402 }
137446f9 4403
d62a17ae 4404 for (ri = rn->info; ri; ri = ri->next)
4405 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4406 && ri->sub_type == BGP_ROUTE_STATIC)
4407 break;
4408
4409 if (ri) {
4410 union gw_addr add;
4411 memset(&add, 0, sizeof(union gw_addr));
4412 if (attrhash_cmp(ri->attr, attr_new)
4413 && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add)
4414 && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
4415 bgp_unlock_node(rn);
4416 bgp_attr_unintern(&attr_new);
4417 aspath_unintern(&attr.aspath);
4418 return;
4419 } else {
4420 /* The attribute is changed. */
4421 bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
4422
4423 /* Rewrite BGP route information. */
4424 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4425 bgp_info_restore(rn, ri);
4426 else
4427 bgp_aggregate_decrement(bgp, p, ri, afi, safi);
4428 bgp_attr_unintern(&ri->attr);
4429 ri->attr = attr_new;
4430 ri->uptime = bgp_clock();
65efcfce 4431#if ENABLE_BGP_VNC
d62a17ae 4432 if (ri->extra)
4433 label = decode_label(&ri->extra->label);
65efcfce 4434#endif
137446f9 4435
d62a17ae 4436 /* Process change. */
4437 bgp_aggregate_increment(bgp, p, ri, afi, safi);
4438 bgp_process(bgp, rn, afi, safi);
65efcfce 4439#if ENABLE_BGP_VNC
d62a17ae 4440 rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
4441 ri->attr, afi, safi, ri->type,
4442 ri->sub_type, &label);
65efcfce 4443#endif
d62a17ae 4444 bgp_unlock_node(rn);
4445 aspath_unintern(&attr.aspath);
4446 return;
4447 }
4448 }
137446f9
LB
4449
4450
d62a17ae 4451 /* Make new BGP info. */
4452 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
4453 attr_new, rn);
4454 SET_FLAG(new->flags, BGP_INFO_VALID);
4455 new->extra = bgp_info_extra_new();
4456 new->extra->label = bgp_static->label;
65efcfce 4457#if ENABLE_BGP_VNC
d62a17ae 4458 label = decode_label(&bgp_static->label);
65efcfce 4459#endif
137446f9 4460
d62a17ae 4461 /* Aggregate address increment. */
4462 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 4463
d62a17ae 4464 /* Register new BGP information. */
4465 bgp_info_add(rn, new);
4466 /* route_node_get lock */
4467 bgp_unlock_node(rn);
137446f9 4468
d62a17ae 4469 /* Process change. */
4470 bgp_process(bgp, rn, afi, safi);
137446f9 4471
65efcfce 4472#if ENABLE_BGP_VNC
d62a17ae 4473 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
4474 safi, new->type, new->sub_type, &label);
65efcfce
LB
4475#endif
4476
d62a17ae 4477 /* Unintern original. */
4478 aspath_unintern(&attr.aspath);
137446f9
LB
4479}
4480
718e3744 4481/* Configure static BGP network. When user don't run zebra, static
4482 route should be installed as valid. */
d62a17ae 4483static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi,
4484 safi_t safi, const char *rmap, int backdoor,
4485 u_int32_t label_index)
4486{
4487 VTY_DECLVAR_CONTEXT(bgp, bgp);
4488 int ret;
4489 struct prefix p;
4490 struct bgp_static *bgp_static;
4491 struct bgp_node *rn;
4492 u_char need_update = 0;
4493
4494 /* Convert IP prefix string to struct prefix. */
4495 ret = str2prefix(ip_str, &p);
4496 if (!ret) {
4497 vty_out(vty, "%% Malformed prefix\n");
4498 return CMD_WARNING_CONFIG_FAILED;
4499 }
4500 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4501 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4502 return CMD_WARNING_CONFIG_FAILED;
4503 }
718e3744 4504
d62a17ae 4505 apply_mask(&p);
718e3744 4506
d62a17ae 4507 /* Set BGP static route configuration. */
4508 rn = bgp_node_get(bgp->route[afi][safi], &p);
718e3744 4509
d62a17ae 4510 if (rn->info) {
4511 /* Configuration change. */
4512 bgp_static = rn->info;
4513
4514 /* Label index cannot be changed. */
4515 if (bgp_static->label_index != label_index) {
4516 vty_out(vty, "%% Label index cannot be changed\n");
4517 return CMD_WARNING_CONFIG_FAILED;
4518 }
4519
4520 /* Check previous routes are installed into BGP. */
4521 if (bgp_static->valid && bgp_static->backdoor != backdoor)
4522 need_update = 1;
4523
4524 bgp_static->backdoor = backdoor;
4525
4526 if (rmap) {
4527 if (bgp_static->rmap.name)
4528 XFREE(MTYPE_ROUTE_MAP_NAME,
4529 bgp_static->rmap.name);
4530 bgp_static->rmap.name =
4531 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4532 bgp_static->rmap.map = route_map_lookup_by_name(rmap);
4533 } else {
4534 if (bgp_static->rmap.name)
4535 XFREE(MTYPE_ROUTE_MAP_NAME,
4536 bgp_static->rmap.name);
4537 bgp_static->rmap.name = NULL;
4538 bgp_static->rmap.map = NULL;
4539 bgp_static->valid = 0;
4540 }
4541 bgp_unlock_node(rn);
4542 } else {
4543 /* New configuration. */
4544 bgp_static = bgp_static_new();
4545 bgp_static->backdoor = backdoor;
4546 bgp_static->valid = 0;
4547 bgp_static->igpmetric = 0;
4548 bgp_static->igpnexthop.s_addr = 0;
4549 bgp_static->label_index = label_index;
4550
4551 if (rmap) {
4552 if (bgp_static->rmap.name)
4553 XFREE(MTYPE_ROUTE_MAP_NAME,
4554 bgp_static->rmap.name);
4555 bgp_static->rmap.name =
4556 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4557 bgp_static->rmap.map = route_map_lookup_by_name(rmap);
4558 }
4559 rn->info = bgp_static;
4560 }
718e3744 4561
d62a17ae 4562 bgp_static->valid = 1;
4563 if (need_update)
4564 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 4565
d62a17ae 4566 if (!bgp_static->backdoor)
4567 bgp_static_update(bgp, &p, bgp_static, afi, safi);
718e3744 4568
d62a17ae 4569 return CMD_SUCCESS;
718e3744 4570}
4571
4572/* Configure static BGP network. */
d62a17ae 4573static int bgp_static_unset(struct vty *vty, const char *ip_str, afi_t afi,
4574 safi_t safi)
4575{
4576 VTY_DECLVAR_CONTEXT(bgp, bgp);
4577 int ret;
4578 struct prefix p;
4579 struct bgp_static *bgp_static;
4580 struct bgp_node *rn;
4581
4582 /* Convert IP prefix string to struct prefix. */
4583 ret = str2prefix(ip_str, &p);
4584 if (!ret) {
4585 vty_out(vty, "%% Malformed prefix\n");
4586 return CMD_WARNING_CONFIG_FAILED;
4587 }
4588 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4589 vty_out(vty, "%% Malformed prefix (link-local address)\n");
4590 return CMD_WARNING_CONFIG_FAILED;
4591 }
718e3744 4592
d62a17ae 4593 apply_mask(&p);
718e3744 4594
d62a17ae 4595 rn = bgp_node_lookup(bgp->route[afi][safi], &p);
4596 if (!rn) {
4597 vty_out(vty,
4598 "%% Can't find specified static route configuration.\n");
4599 return CMD_WARNING_CONFIG_FAILED;
4600 }
718e3744 4601
d62a17ae 4602 bgp_static = rn->info;
4603
4604 /* Update BGP RIB. */
4605 if (!bgp_static->backdoor)
4606 bgp_static_withdraw(bgp, &p, afi, safi);
4607
4608 /* Clear configuration. */
4609 bgp_static_free(bgp_static);
4610 rn->info = NULL;
4611 bgp_unlock_node(rn);
4612 bgp_unlock_node(rn);
4613
4614 return CMD_SUCCESS;
4615}
4616
4617void bgp_static_add(struct bgp *bgp)
4618{
4619 afi_t afi;
4620 safi_t safi;
4621 struct bgp_node *rn;
4622 struct bgp_node *rm;
4623 struct bgp_table *table;
4624 struct bgp_static *bgp_static;
4625
05c7a1cc
QY
4626 FOREACH_AFI_SAFI (afi, safi)
4627 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4628 rn = bgp_route_next(rn)) {
4629 if (rn->info == NULL)
4630 continue;
ea47320b 4631
05c7a1cc
QY
4632 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4633 || (safi == SAFI_EVPN)) {
4634 table = rn->info;
4635
4636 for (rm = bgp_table_top(table); rm;
4637 rm = bgp_route_next(rm)) {
4638 bgp_static = rm->info;
4639 bgp_static_update_safi(bgp, &rm->p,
4640 bgp_static, afi,
4641 safi);
d62a17ae 4642 }
05c7a1cc
QY
4643 } else {
4644 bgp_static_update(bgp, &rn->p, rn->info, afi,
4645 safi);
ea47320b 4646 }
05c7a1cc 4647 }
6aeb9e78
DS
4648}
4649
718e3744 4650/* Called from bgp_delete(). Delete all static routes from the BGP
4651 instance. */
d62a17ae 4652void bgp_static_delete(struct bgp *bgp)
4653{
4654 afi_t afi;
4655 safi_t safi;
4656 struct bgp_node *rn;
4657 struct bgp_node *rm;
4658 struct bgp_table *table;
4659 struct bgp_static *bgp_static;
4660
05c7a1cc
QY
4661 FOREACH_AFI_SAFI (afi, safi)
4662 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4663 rn = bgp_route_next(rn)) {
4664 if (rn->info == NULL)
4665 continue;
ea47320b 4666
05c7a1cc
QY
4667 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4668 || (safi == SAFI_EVPN)) {
4669 table = rn->info;
4670
4671 for (rm = bgp_table_top(table); rm;
4672 rm = bgp_route_next(rm)) {
4673 bgp_static = rm->info;
4674 bgp_static_withdraw_safi(
4675 bgp, &rm->p, AFI_IP, safi,
4676 (struct prefix_rd *)&rn->p);
ea47320b
DL
4677 bgp_static_free(bgp_static);
4678 rn->info = NULL;
4679 bgp_unlock_node(rn);
d62a17ae 4680 }
05c7a1cc
QY
4681 } else {
4682 bgp_static = rn->info;
4683 bgp_static_withdraw(bgp, &rn->p, afi, safi);
4684 bgp_static_free(bgp_static);
4685 rn->info = NULL;
4686 bgp_unlock_node(rn);
ea47320b 4687 }
05c7a1cc 4688 }
d62a17ae 4689}
4690
4691void bgp_static_redo_import_check(struct bgp *bgp)
4692{
4693 afi_t afi;
4694 safi_t safi;
4695 struct bgp_node *rn;
4696 struct bgp_node *rm;
4697 struct bgp_table *table;
4698 struct bgp_static *bgp_static;
4699
4700 /* Use this flag to force reprocessing of the route */
4701 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc
QY
4702 FOREACH_AFI_SAFI (afi, safi) {
4703 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
4704 rn = bgp_route_next(rn)) {
4705 if (rn->info == NULL)
4706 continue;
ea47320b 4707
05c7a1cc
QY
4708 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
4709 || (safi == SAFI_EVPN)) {
4710 table = rn->info;
4711
4712 for (rm = bgp_table_top(table); rm;
4713 rm = bgp_route_next(rm)) {
4714 bgp_static = rm->info;
4715 bgp_static_update_safi(bgp, &rm->p,
4716 bgp_static, afi,
4717 safi);
d62a17ae 4718 }
05c7a1cc
QY
4719 } else {
4720 bgp_static = rn->info;
4721 bgp_static_update(bgp, &rn->p, bgp_static, afi,
4722 safi);
ea47320b 4723 }
05c7a1cc
QY
4724 }
4725 }
d62a17ae 4726 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
4727}
4728
4729static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
4730 safi_t safi)
4731{
4732 struct bgp_table *table;
4733 struct bgp_node *rn;
4734 struct bgp_info *ri;
4735
4736 table = bgp->rib[afi][safi];
4737 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
4738 for (ri = rn->info; ri; ri = ri->next) {
4739 if (ri->peer == bgp->peer_self
4740 && ((ri->type == ZEBRA_ROUTE_BGP
4741 && ri->sub_type == BGP_ROUTE_STATIC)
4742 || (ri->type != ZEBRA_ROUTE_BGP
4743 && ri->sub_type
4744 == BGP_ROUTE_REDISTRIBUTE))) {
4745 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
4746 safi);
4747 bgp_unlink_nexthop(ri);
4748 bgp_info_delete(rn, ri);
4749 bgp_process(bgp, rn, afi, safi);
4750 }
4751 }
4752 }
ad4cbda1 4753}
4754
4755/*
4756 * Purge all networks and redistributed routes from routing table.
4757 * Invoked upon the instance going down.
4758 */
d62a17ae 4759void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 4760{
d62a17ae 4761 afi_t afi;
4762 safi_t safi;
ad4cbda1 4763
05c7a1cc
QY
4764 FOREACH_AFI_SAFI (afi, safi)
4765 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 4766}
4767
137446f9
LB
4768/*
4769 * gpz 110624
4770 * Currently this is used to set static routes for VPN and ENCAP.
4771 * I think it can probably be factored with bgp_static_set.
4772 */
d62a17ae 4773int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
4774 const char *ip_str, const char *rd_str,
4775 const char *label_str, const char *rmap_str,
4776 int evpn_type, const char *esi, const char *gwip,
4777 const char *ethtag, const char *routermac)
4778{
4779 VTY_DECLVAR_CONTEXT(bgp, bgp);
4780 int ret;
4781 struct prefix p;
4782 struct prefix_rd prd;
4783 struct bgp_node *prn;
4784 struct bgp_node *rn;
4785 struct bgp_table *table;
4786 struct bgp_static *bgp_static;
4787 mpls_label_t label = MPLS_INVALID_LABEL;
4788 struct prefix gw_ip;
4789
4790 /* validate ip prefix */
4791 ret = str2prefix(ip_str, &p);
4792 if (!ret) {
4793 vty_out(vty, "%% Malformed prefix\n");
4794 return CMD_WARNING_CONFIG_FAILED;
4795 }
4796 apply_mask(&p);
4797 if ((afi == AFI_L2VPN)
4798 && (bgp_build_evpn_prefix(evpn_type,
4799 ethtag != NULL ? atol(ethtag) : 0, &p))) {
4800 vty_out(vty, "%% L2VPN prefix could not be forged\n");
4801 return CMD_WARNING_CONFIG_FAILED;
4802 }
718e3744 4803
d62a17ae 4804 ret = str2prefix_rd(rd_str, &prd);
4805 if (!ret) {
4806 vty_out(vty, "%% Malformed rd\n");
4807 return CMD_WARNING_CONFIG_FAILED;
4808 }
718e3744 4809
d62a17ae 4810 if (label_str) {
4811 unsigned long label_val;
4812 label_val = strtoul(label_str, NULL, 10);
4813 encode_label(label_val, &label);
4814 }
9bedbb1e 4815
d62a17ae 4816 if (safi == SAFI_EVPN) {
4817 if (esi && str2esi(esi, NULL) == 0) {
4818 vty_out(vty, "%% Malformed ESI\n");
4819 return CMD_WARNING_CONFIG_FAILED;
4820 }
4821 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
4822 vty_out(vty, "%% Malformed Router MAC\n");
4823 return CMD_WARNING_CONFIG_FAILED;
4824 }
4825 if (gwip) {
4826 memset(&gw_ip, 0, sizeof(struct prefix));
4827 ret = str2prefix(gwip, &gw_ip);
4828 if (!ret) {
4829 vty_out(vty, "%% Malformed GatewayIp\n");
4830 return CMD_WARNING_CONFIG_FAILED;
4831 }
4832 if ((gw_ip.family == AF_INET
4833 && IS_EVPN_PREFIX_IPADDR_V6(
4834 (struct prefix_evpn *)&p))
4835 || (gw_ip.family == AF_INET6
4836 && IS_EVPN_PREFIX_IPADDR_V4(
4837 (struct prefix_evpn *)&p))) {
4838 vty_out(vty,
4839 "%% GatewayIp family differs with IP prefix\n");
4840 return CMD_WARNING_CONFIG_FAILED;
4841 }
4842 }
4843 }
4844 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
4845 if (prn->info == NULL)
4846 prn->info = bgp_table_init(afi, safi);
4847 else
4848 bgp_unlock_node(prn);
4849 table = prn->info;
4850
4851 rn = bgp_node_get(table, &p);
4852
4853 if (rn->info) {
4854 vty_out(vty, "%% Same network configuration exists\n");
4855 bgp_unlock_node(rn);
4856 } else {
4857 /* New configuration. */
4858 bgp_static = bgp_static_new();
4859 bgp_static->backdoor = 0;
4860 bgp_static->valid = 0;
4861 bgp_static->igpmetric = 0;
4862 bgp_static->igpnexthop.s_addr = 0;
4863 bgp_static->label = label;
4864 bgp_static->prd = prd;
4865
4866 if (rmap_str) {
4867 if (bgp_static->rmap.name)
4868 XFREE(MTYPE_ROUTE_MAP_NAME,
4869 bgp_static->rmap.name);
4870 bgp_static->rmap.name =
4871 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
4872 bgp_static->rmap.map =
4873 route_map_lookup_by_name(rmap_str);
4874 }
718e3744 4875
d62a17ae 4876 if (safi == SAFI_EVPN) {
4877 if (esi) {
4878 bgp_static->eth_s_id =
4879 XCALLOC(MTYPE_ATTR,
4880 sizeof(struct eth_segment_id));
4881 str2esi(esi, bgp_static->eth_s_id);
4882 }
4883 if (routermac) {
4884 bgp_static->router_mac =
28328ea9 4885 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
d62a17ae 4886 prefix_str2mac(routermac,
4887 bgp_static->router_mac);
4888 }
4889 if (gwip)
4890 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
4891 }
4892 rn->info = bgp_static;
718e3744 4893
d62a17ae 4894 bgp_static->valid = 1;
4895 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
4896 }
718e3744 4897
d62a17ae 4898 return CMD_SUCCESS;
718e3744 4899}
4900
4901/* Configure static BGP network. */
d62a17ae 4902int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
4903 const char *ip_str, const char *rd_str,
4904 const char *label_str, int evpn_type, const char *esi,
4905 const char *gwip, const char *ethtag)
4906{
4907 VTY_DECLVAR_CONTEXT(bgp, bgp);
4908 int ret;
4909 struct prefix p;
4910 struct prefix_rd prd;
4911 struct bgp_node *prn;
4912 struct bgp_node *rn;
4913 struct bgp_table *table;
4914 struct bgp_static *bgp_static;
4915 mpls_label_t label = MPLS_INVALID_LABEL;
4916
4917 /* Convert IP prefix string to struct prefix. */
4918 ret = str2prefix(ip_str, &p);
4919 if (!ret) {
4920 vty_out(vty, "%% Malformed prefix\n");
4921 return CMD_WARNING_CONFIG_FAILED;
4922 }
4923 apply_mask(&p);
4924 if ((afi == AFI_L2VPN)
4925 && (bgp_build_evpn_prefix(evpn_type,
4926 ethtag != NULL ? atol(ethtag) : 0, &p))) {
4927 vty_out(vty, "%% L2VPN prefix could not be forged\n");
4928 return CMD_WARNING_CONFIG_FAILED;
4929 }
4930 ret = str2prefix_rd(rd_str, &prd);
4931 if (!ret) {
4932 vty_out(vty, "%% Malformed rd\n");
4933 return CMD_WARNING_CONFIG_FAILED;
4934 }
718e3744 4935
d62a17ae 4936 if (label_str) {
4937 unsigned long label_val;
4938 label_val = strtoul(label_str, NULL, 10);
4939 encode_label(label_val, &label);
4940 }
718e3744 4941
d62a17ae 4942 prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
4943 if (prn->info == NULL)
4944 prn->info = bgp_table_init(afi, safi);
4945 else
4946 bgp_unlock_node(prn);
4947 table = prn->info;
718e3744 4948
d62a17ae 4949 rn = bgp_node_lookup(table, &p);
6b0655a2 4950
d62a17ae 4951 if (rn) {
4952 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 4953
d62a17ae 4954 bgp_static = rn->info;
4955 bgp_static_free(bgp_static);
4956 rn->info = NULL;
4957 bgp_unlock_node(rn);
4958 bgp_unlock_node(rn);
4959 } else
4960 vty_out(vty, "%% Can't find the route\n");
4961
4962 return CMD_SUCCESS;
4963}
4964
4965static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
4966 const char *rmap_name)
4967{
4968 VTY_DECLVAR_CONTEXT(bgp, bgp);
4969 struct bgp_rmap *rmap;
4970
4971 rmap = &bgp->table_map[afi][safi];
4972 if (rmap_name) {
4973 if (rmap->name)
4974 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4975 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
4976 rmap->map = route_map_lookup_by_name(rmap_name);
4977 } else {
4978 if (rmap->name)
4979 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4980 rmap->name = NULL;
4981 rmap->map = NULL;
4982 }
73ac8160 4983
d62a17ae 4984 if (bgp_fibupd_safi(safi))
4985 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 4986
d62a17ae 4987 return CMD_SUCCESS;
73ac8160
DS
4988}
4989
d62a17ae 4990static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
4991 const char *rmap_name)
73ac8160 4992{
d62a17ae 4993 VTY_DECLVAR_CONTEXT(bgp, bgp);
4994 struct bgp_rmap *rmap;
73ac8160 4995
d62a17ae 4996 rmap = &bgp->table_map[afi][safi];
4997 if (rmap->name)
4998 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4999 rmap->name = NULL;
5000 rmap->map = NULL;
73ac8160 5001
d62a17ae 5002 if (bgp_fibupd_safi(safi))
5003 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 5004
d62a17ae 5005 return CMD_SUCCESS;
73ac8160
DS
5006}
5007
2b791107 5008void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 5009 safi_t safi)
73ac8160 5010{
d62a17ae 5011 if (bgp->table_map[afi][safi].name) {
d62a17ae 5012 vty_out(vty, " table-map %s\n",
5013 bgp->table_map[afi][safi].name);
5014 }
73ac8160
DS
5015}
5016
73ac8160
DS
5017DEFUN (bgp_table_map,
5018 bgp_table_map_cmd,
5019 "table-map WORD",
5020 "BGP table to RIB route download filter\n"
5021 "Name of the route map\n")
5022{
d62a17ae 5023 int idx_word = 1;
5024 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5025 argv[idx_word]->arg);
73ac8160
DS
5026}
5027DEFUN (no_bgp_table_map,
5028 no_bgp_table_map_cmd,
5029 "no table-map WORD",
3a2d747c 5030 NO_STR
73ac8160
DS
5031 "BGP table to RIB route download filter\n"
5032 "Name of the route map\n")
5033{
d62a17ae 5034 int idx_word = 2;
5035 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
5036 argv[idx_word]->arg);
73ac8160
DS
5037}
5038
718e3744 5039DEFUN (bgp_network,
5040 bgp_network_cmd,
5041 "network A.B.C.D/M",
5042 "Specify a network to announce via BGP\n"
0c7b1b01 5043 "IPv4 prefix\n")
718e3744 5044{
d62a17ae 5045 int idx_ipv4_prefixlen = 1;
5046 return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
5047 bgp_node_safi(vty), NULL, 0,
5048 BGP_INVALID_LABEL_INDEX);
718e3744 5049}
5050
5051DEFUN (bgp_network_route_map,
5052 bgp_network_route_map_cmd,
5053 "network A.B.C.D/M route-map WORD",
5054 "Specify a network to announce via BGP\n"
0c7b1b01 5055 "IPv4 prefix\n"
718e3744 5056 "Route-map to modify the attributes\n"
5057 "Name of the route map\n")
5058{
d62a17ae 5059 int idx_ipv4_prefixlen = 1;
5060 int idx_word = 3;
5061 return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
5062 bgp_node_safi(vty), argv[idx_word]->arg, 0,
5063 BGP_INVALID_LABEL_INDEX);
718e3744 5064}
5065
5066DEFUN (bgp_network_backdoor,
5067 bgp_network_backdoor_cmd,
5068 "network A.B.C.D/M backdoor",
5069 "Specify a network to announce via BGP\n"
0c7b1b01 5070 "IPv4 prefix\n"
718e3744 5071 "Specify a BGP backdoor route\n")
5072{
d62a17ae 5073 int idx_ipv4_prefixlen = 1;
5074 return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
5075 SAFI_UNICAST, NULL, 1, BGP_INVALID_LABEL_INDEX);
718e3744 5076}
5077
5078DEFUN (bgp_network_mask,
5079 bgp_network_mask_cmd,
5080 "network A.B.C.D mask A.B.C.D",
5081 "Specify a network to announce via BGP\n"
5082 "Network number\n"
5083 "Network mask\n"
5084 "Network mask\n")
5085{
d62a17ae 5086 int idx_ipv4 = 1;
5087 int idx_ipv4_2 = 3;
5088 int ret;
5089 char prefix_str[BUFSIZ];
5090
5091 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5092 prefix_str);
5093 if (!ret) {
5094 vty_out(vty, "%% Inconsistent address and mask\n");
5095 return CMD_WARNING_CONFIG_FAILED;
5096 }
718e3744 5097
d62a17ae 5098 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL,
5099 0, BGP_INVALID_LABEL_INDEX);
718e3744 5100}
5101
5102DEFUN (bgp_network_mask_route_map,
5103 bgp_network_mask_route_map_cmd,
5104 "network A.B.C.D mask A.B.C.D route-map WORD",
5105 "Specify a network to announce via BGP\n"
5106 "Network number\n"
5107 "Network mask\n"
5108 "Network mask\n"
5109 "Route-map to modify the attributes\n"
5110 "Name of the route map\n")
5111{
d62a17ae 5112 int idx_ipv4 = 1;
5113 int idx_ipv4_2 = 3;
5114 int idx_word = 5;
5115 int ret;
5116 char prefix_str[BUFSIZ];
5117
5118 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5119 prefix_str);
5120 if (!ret) {
5121 vty_out(vty, "%% Inconsistent address and mask\n");
5122 return CMD_WARNING_CONFIG_FAILED;
5123 }
718e3744 5124
d62a17ae 5125 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5126 argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
718e3744 5127}
5128
5129DEFUN (bgp_network_mask_backdoor,
5130 bgp_network_mask_backdoor_cmd,
5131 "network A.B.C.D mask A.B.C.D backdoor",
5132 "Specify a network to announce via BGP\n"
5133 "Network number\n"
5134 "Network mask\n"
5135 "Network mask\n"
5136 "Specify a BGP backdoor route\n")
5137{
d62a17ae 5138 int idx_ipv4 = 1;
5139 int idx_ipv4_2 = 3;
5140 int ret;
5141 char prefix_str[BUFSIZ];
5142
5143 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5144 prefix_str);
5145 if (!ret) {
5146 vty_out(vty, "%% Inconsistent address and mask\n");
5147 return CMD_WARNING_CONFIG_FAILED;
5148 }
718e3744 5149
d62a17ae 5150 return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1,
5151 BGP_INVALID_LABEL_INDEX);
718e3744 5152}
5153
5154DEFUN (bgp_network_mask_natural,
5155 bgp_network_mask_natural_cmd,
5156 "network A.B.C.D",
5157 "Specify a network to announce via BGP\n"
5158 "Network number\n")
5159{
d62a17ae 5160 int idx_ipv4 = 1;
5161 int ret;
5162 char prefix_str[BUFSIZ];
718e3744 5163
d62a17ae 5164 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5165 if (!ret) {
5166 vty_out(vty, "%% Inconsistent address and mask\n");
5167 return CMD_WARNING_CONFIG_FAILED;
5168 }
718e3744 5169
d62a17ae 5170 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL,
5171 0, BGP_INVALID_LABEL_INDEX);
718e3744 5172}
5173
5174DEFUN (bgp_network_mask_natural_route_map,
5175 bgp_network_mask_natural_route_map_cmd,
5176 "network A.B.C.D route-map WORD",
5177 "Specify a network to announce via BGP\n"
5178 "Network number\n"
5179 "Route-map to modify the attributes\n"
5180 "Name of the route map\n")
5181{
d62a17ae 5182 int idx_ipv4 = 1;
5183 int idx_word = 3;
5184 int ret;
5185 char prefix_str[BUFSIZ];
718e3744 5186
d62a17ae 5187 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5188 if (!ret) {
5189 vty_out(vty, "%% Inconsistent address and mask\n");
5190 return CMD_WARNING_CONFIG_FAILED;
5191 }
718e3744 5192
d62a17ae 5193 return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
5194 argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
718e3744 5195}
5196
5197DEFUN (bgp_network_mask_natural_backdoor,
5198 bgp_network_mask_natural_backdoor_cmd,
5199 "network A.B.C.D backdoor",
5200 "Specify a network to announce via BGP\n"
5201 "Network number\n"
5202 "Specify a BGP backdoor route\n")
5203{
d62a17ae 5204 int idx_ipv4 = 1;
5205 int ret;
5206 char prefix_str[BUFSIZ];
718e3744 5207
d62a17ae 5208 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5209 if (!ret) {
5210 vty_out(vty, "%% Inconsistent address and mask\n");
5211 return CMD_WARNING_CONFIG_FAILED;
5212 }
718e3744 5213
d62a17ae 5214 return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1,
5215 BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5216}
5217
5218DEFUN (bgp_network_label_index,
5219 bgp_network_label_index_cmd,
8b81993e 5220 "network A.B.C.D/M label-index (0-1048560)",
1b6d5c7e
VV
5221 "Specify a network to announce via BGP\n"
5222 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5223 "Label index to associate with the prefix\n"
5224 "Label index value\n")
5225{
d62a17ae 5226 u_int32_t label_index;
1b6d5c7e 5227
d62a17ae 5228 label_index = strtoul(argv[3]->arg, NULL, 10);
5229 return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty),
5230 NULL, 0, label_index);
1b6d5c7e
VV
5231}
5232
5233DEFUN (bgp_network_label_index_route_map,
5234 bgp_network_label_index_route_map_cmd,
8b81993e 5235 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
1b6d5c7e
VV
5236 "Specify a network to announce via BGP\n"
5237 "IP prefix\n"
5238 "Label index to associate with the prefix\n"
5239 "Label index value\n"
5240 "Route-map to modify the attributes\n"
5241 "Name of the route map\n")
5242{
d62a17ae 5243 u_int32_t label_index;
1b6d5c7e 5244
d62a17ae 5245 label_index = strtoul(argv[3]->arg, NULL, 10);
5246 return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty),
5247 argv[5]->arg, 0, label_index);
718e3744 5248}
5249
5250DEFUN (no_bgp_network,
5251 no_bgp_network_cmd,
a636c635 5252 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
718e3744 5253 NO_STR
5254 "Specify a network to announce via BGP\n"
0c7b1b01 5255 "IPv4 prefix\n"
a636c635
DW
5256 "Specify a BGP backdoor route\n"
5257 "Route-map to modify the attributes\n"
5258 "Name of the route map\n")
718e3744 5259{
d62a17ae 5260 int idx_ipv4_prefixlen = 2;
5261 return bgp_static_unset(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
5262 bgp_node_safi(vty));
718e3744 5263}
5264
718e3744 5265DEFUN (no_bgp_network_mask,
5266 no_bgp_network_mask_cmd,
a636c635 5267 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
718e3744 5268 NO_STR
5269 "Specify a network to announce via BGP\n"
5270 "Network number\n"
5271 "Network mask\n"
a636c635
DW
5272 "Network mask\n"
5273 "Specify a BGP backdoor route\n"
5274 "Route-map to modify the attributes\n"
5275 "Name of the route map\n")
718e3744 5276{
d62a17ae 5277 int idx_ipv4 = 2;
5278 int idx_ipv4_2 = 4;
5279 int ret;
5280 char prefix_str[BUFSIZ];
718e3744 5281
d62a17ae 5282 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
5283 prefix_str);
5284 if (!ret) {
5285 vty_out(vty, "%% Inconsistent address and mask\n");
5286 return CMD_WARNING_CONFIG_FAILED;
5287 }
718e3744 5288
d62a17ae 5289 return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 5290}
5291
718e3744 5292DEFUN (no_bgp_network_mask_natural,
5293 no_bgp_network_mask_natural_cmd,
a636c635 5294 "no network A.B.C.D [<backdoor|route-map WORD>]",
718e3744 5295 NO_STR
5296 "Specify a network to announce via BGP\n"
a636c635
DW
5297 "Network number\n"
5298 "Specify a BGP backdoor route\n"
5299 "Route-map to modify the attributes\n"
5300 "Name of the route map\n")
718e3744 5301{
d62a17ae 5302 int idx_ipv4 = 2;
5303 int ret;
5304 char prefix_str[BUFSIZ];
718e3744 5305
d62a17ae 5306 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
5307 if (!ret) {
5308 vty_out(vty, "%% Inconsistent address and mask\n");
5309 return CMD_WARNING_CONFIG_FAILED;
5310 }
718e3744 5311
d62a17ae 5312 return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 5313}
5314
d62a17ae 5315ALIAS(no_bgp_network, no_bgp_network_label_index_cmd,
9d303b37 5316 "no network A.B.C.D/M label-index (0-1048560)", NO_STR
d62a17ae 5317 "Specify a network to announce via BGP\n"
5318 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5319 "Label index to associate with the prefix\n"
5320 "Label index value\n")
1b6d5c7e 5321
d62a17ae 5322ALIAS(no_bgp_network, no_bgp_network_label_index_route_map_cmd,
9d303b37 5323 "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
d62a17ae 5324 "Specify a network to announce via BGP\n"
5325 "IP prefix\n"
5326 "Label index to associate with the prefix\n"
5327 "Label index value\n"
5328 "Route-map to modify the attributes\n"
5329 "Name of the route map\n")
1b6d5c7e 5330
718e3744 5331DEFUN (ipv6_bgp_network,
5332 ipv6_bgp_network_cmd,
5333 "network X:X::X:X/M",
5334 "Specify a network to announce via BGP\n"
0c7b1b01 5335 "IPv6 prefix\n")
718e3744 5336{
d62a17ae 5337 int idx_ipv6_prefixlen = 1;
5338 return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
5339 bgp_node_safi(vty), NULL, 0,
5340 BGP_INVALID_LABEL_INDEX);
718e3744 5341}
5342
5343DEFUN (ipv6_bgp_network_route_map,
5344 ipv6_bgp_network_route_map_cmd,
5345 "network X:X::X:X/M route-map WORD",
5346 "Specify a network to announce via BGP\n"
0c7b1b01 5347 "IPv6 prefix\n"
718e3744 5348 "Route-map to modify the attributes\n"
5349 "Name of the route map\n")
5350{
d62a17ae 5351 int idx_ipv6_prefixlen = 1;
5352 int idx_word = 3;
5353 return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
5354 bgp_node_safi(vty), argv[idx_word]->arg, 0,
5355 BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
5356}
5357
5358DEFUN (ipv6_bgp_network_label_index,
5359 ipv6_bgp_network_label_index_cmd,
8b81993e 5360 "network X:X::X:X/M label-index (0-1048560)",
1b6d5c7e
VV
5361 "Specify a network to announce via BGP\n"
5362 "IPv6 prefix <network>/<length>\n"
5363 "Label index to associate with the prefix\n"
5364 "Label index value\n")
5365{
d62a17ae 5366 u_int32_t label_index;
1b6d5c7e 5367
d62a17ae 5368 label_index = strtoul(argv[3]->arg, NULL, 10);
5369 return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty),
5370 NULL, 0, label_index);
1b6d5c7e
VV
5371}
5372
5373DEFUN (ipv6_bgp_network_label_index_route_map,
5374 ipv6_bgp_network_label_index_route_map_cmd,
8b81993e 5375 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
1b6d5c7e
VV
5376 "Specify a network to announce via BGP\n"
5377 "IPv6 prefix\n"
5378 "Label index to associate with the prefix\n"
5379 "Label index value\n"
5380 "Route-map to modify the attributes\n"
5381 "Name of the route map\n")
5382{
d62a17ae 5383 u_int32_t label_index;
1b6d5c7e 5384
d62a17ae 5385 label_index = strtoul(argv[3]->arg, NULL, 10);
5386 return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty),
5387 argv[5]->arg, 0, label_index);
718e3744 5388}
5389
5390DEFUN (no_ipv6_bgp_network,
5391 no_ipv6_bgp_network_cmd,
a636c635 5392 "no network X:X::X:X/M [route-map WORD]",
718e3744 5393 NO_STR
5394 "Specify a network to announce via BGP\n"
0c7b1b01 5395 "IPv6 prefix\n"
a636c635
DW
5396 "Route-map to modify the attributes\n"
5397 "Name of the route map\n")
718e3744 5398{
d62a17ae 5399 int idx_ipv6_prefixlen = 2;
5400 return bgp_static_unset(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
5401 bgp_node_safi(vty));
718e3744 5402}
5403
d62a17ae 5404ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_cmd,
9d303b37 5405 "no network X:X::X:X/M label-index (0-1048560)", NO_STR
d62a17ae 5406 "Specify a network to announce via BGP\n"
5407 "IPv6 prefix <network>/<length>\n"
5408 "Label index to associate with the prefix\n"
5409 "Label index value\n")
1b6d5c7e 5410
d62a17ae 5411ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_route_map_cmd,
9d303b37 5412 "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
d62a17ae 5413 "Specify a network to announce via BGP\n"
5414 "IPv6 prefix\n"
5415 "Label index to associate with the prefix\n"
5416 "Label index value\n"
5417 "Route-map to modify the attributes\n"
5418 "Name of the route map\n")
1b6d5c7e 5419
718e3744 5420/* Aggreagete address:
5421
5422 advertise-map Set condition to advertise attribute
5423 as-set Generate AS set path information
5424 attribute-map Set attributes of aggregate
5425 route-map Set parameters of aggregate
5426 summary-only Filter more specific routes from updates
5427 suppress-map Conditionally filter more specific routes from updates
5428 <cr>
5429 */
d62a17ae 5430struct bgp_aggregate {
5431 /* Summary-only flag. */
5432 u_char summary_only;
718e3744 5433
d62a17ae 5434 /* AS set generation. */
5435 u_char as_set;
718e3744 5436
d62a17ae 5437 /* Route-map for aggregated route. */
5438 struct route_map *map;
718e3744 5439
d62a17ae 5440 /* Suppress-count. */
5441 unsigned long count;
718e3744 5442
d62a17ae 5443 /* SAFI configuration. */
5444 safi_t safi;
718e3744 5445};
5446
d62a17ae 5447static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 5448{
d62a17ae 5449 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 5450}
5451
d62a17ae 5452static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 5453{
d62a17ae 5454 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
5455}
718e3744 5456
b5d58c32 5457/* Update an aggregate as routes are added/removed from the BGP table */
d62a17ae 5458static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
5459 struct bgp_info *rinew, afi_t afi, safi_t safi,
5460 struct bgp_info *del,
5461 struct bgp_aggregate *aggregate)
5462{
5463 struct bgp_table *table;
5464 struct bgp_node *top;
5465 struct bgp_node *rn;
5466 u_char origin;
5467 struct aspath *aspath = NULL;
5468 struct aspath *asmerge = NULL;
5469 struct community *community = NULL;
5470 struct community *commerge = NULL;
ffd0c037 5471#if defined(AGGREGATE_NEXTHOP_CHECK)
d62a17ae 5472 struct in_addr nexthop;
5473 u_int32_t med = 0;
ffd0c037 5474#endif
d62a17ae 5475 struct bgp_info *ri;
5476 struct bgp_info *new;
5477 int first = 1;
5478 unsigned long match = 0;
5479 u_char atomic_aggregate = 0;
5480
5481 /* Record adding route's nexthop and med. */
5482 if (rinew) {
ffd0c037 5483#if defined(AGGREGATE_NEXTHOP_CHECK)
d62a17ae 5484 nexthop = rinew->attr->nexthop;
5485 med = rinew->attr->med;
ffd0c037 5486#endif
d62a17ae 5487 }
718e3744 5488
d62a17ae 5489 /* ORIGIN attribute: If at least one route among routes that are
5490 aggregated has ORIGIN with the value INCOMPLETE, then the
5491 aggregated route must have the ORIGIN attribute with the value
5492 INCOMPLETE. Otherwise, if at least one route among routes that
5493 are aggregated has ORIGIN with the value EGP, then the aggregated
5494 route must have the origin attribute with the value EGP. In all
5495 other case the value of the ORIGIN attribute of the aggregated
5496 route is INTERNAL. */
5497 origin = BGP_ORIGIN_IGP;
718e3744 5498
d62a17ae 5499 table = bgp->rib[afi][safi];
718e3744 5500
d62a17ae 5501 top = bgp_node_get(table, p);
5502 for (rn = bgp_node_get(table, p); rn;
5503 rn = bgp_route_next_until(rn, top))
5504 if (rn->p.prefixlen > p->prefixlen) {
5505 match = 0;
5506
5507 for (ri = rn->info; ri; ri = ri->next) {
5508 if (BGP_INFO_HOLDDOWN(ri))
5509 continue;
5510
5511 if (del && ri == del)
5512 continue;
5513
5514 if (!rinew && first) {
ffd0c037 5515#if defined(AGGREGATE_NEXTHOP_CHECK)
d62a17ae 5516 nexthop = ri->attr->nexthop;
5517 med = ri->attr->med;
ffd0c037 5518#endif
d62a17ae 5519 first = 0;
5520 }
718e3744 5521
5522#ifdef AGGREGATE_NEXTHOP_CHECK
d62a17ae 5523 if (!IPV4_ADDR_SAME(&ri->attr->nexthop,
5524 &nexthop)
5525 || ri->attr->med != med) {
5526 if (aspath)
5527 aspath_free(aspath);
5528 if (community)
5529 community_free(community);
5530 bgp_unlock_node(rn);
5531 bgp_unlock_node(top);
5532 return;
5533 }
718e3744 5534#endif /* AGGREGATE_NEXTHOP_CHECK */
5535
d62a17ae 5536 if (ri->attr->flag
5537 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5538 atomic_aggregate = 1;
5539
5540 if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
5541 if (aggregate->summary_only) {
5542 (bgp_info_extra_get(ri))
5543 ->suppress++;
5544 bgp_info_set_flag(
5545 rn, ri,
5546 BGP_INFO_ATTR_CHANGED);
5547 match++;
5548 }
5549
5550 aggregate->count++;
5551
5552 if (origin < ri->attr->origin)
5553 origin = ri->attr->origin;
5554
5555 if (aggregate->as_set) {
5556 if (aspath) {
5557 asmerge = aspath_aggregate(
5558 aspath,
5559 ri->attr->aspath);
5560 aspath_free(aspath);
5561 aspath = asmerge;
5562 } else
5563 aspath = aspath_dup(
5564 ri->attr->aspath);
5565
5566 if (ri->attr->community) {
5567 if (community) {
5568 commerge = community_merge(
5569 community,
5570 ri->attr->community);
5571 community = community_uniq_sort(
5572 commerge);
5573 community_free(
5574 commerge);
5575 } else
5576 community = community_dup(
5577 ri->attr->community);
5578 }
5579 }
5580 }
5581 }
5582 if (match)
5583 bgp_process(bgp, rn, afi, safi);
5584 }
5585 bgp_unlock_node(top);
718e3744 5586
d62a17ae 5587 if (rinew) {
718e3744 5588 aggregate->count++;
5589
d62a17ae 5590 if (aggregate->summary_only)
5591 (bgp_info_extra_get(rinew))->suppress++;
5592
5593 if (origin < rinew->attr->origin)
5594 origin = rinew->attr->origin;
5595
5596 if (aggregate->as_set) {
5597 if (aspath) {
5598 asmerge = aspath_aggregate(aspath,
5599 rinew->attr->aspath);
5600 aspath_free(aspath);
5601 aspath = asmerge;
5602 } else
5603 aspath = aspath_dup(rinew->attr->aspath);
5604
5605 if (rinew->attr->community) {
5606 if (community) {
5607 commerge = community_merge(
5608 community,
5609 rinew->attr->community);
5610 community =
5611 community_uniq_sort(commerge);
5612 community_free(commerge);
5613 } else
5614 community = community_dup(
5615 rinew->attr->community);
5616 }
718e3744 5617 }
718e3744 5618 }
718e3744 5619
d62a17ae 5620 if (aggregate->count > 0) {
5621 rn = bgp_node_get(table, p);
5622 new = info_make(
5623 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5624 bgp_attr_aggregate_intern(bgp, origin, aspath,
5625 community, aggregate->as_set,
5626 atomic_aggregate),
5627 rn);
5628 SET_FLAG(new->flags, BGP_INFO_VALID);
5629
5630 bgp_info_add(rn, new);
5631 bgp_unlock_node(rn);
5632 bgp_process(bgp, rn, afi, safi);
5633 } else {
5634 if (aspath)
5635 aspath_free(aspath);
5636 if (community)
5637 community_free(community);
5638 }
718e3744 5639}
5640
d62a17ae 5641void bgp_aggregate_delete(struct bgp *, struct prefix *, afi_t, safi_t,
5642 struct bgp_aggregate *);
718e3744 5643
d62a17ae 5644void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
5645 struct bgp_info *ri, afi_t afi, safi_t safi)
718e3744 5646{
d62a17ae 5647 struct bgp_node *child;
5648 struct bgp_node *rn;
5649 struct bgp_aggregate *aggregate;
5650 struct bgp_table *table;
718e3744 5651
d62a17ae 5652 /* MPLS-VPN aggregation is not yet supported. */
5653 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5654 || (safi == SAFI_EVPN))
5655 return;
718e3744 5656
d62a17ae 5657 table = bgp->aggregate[afi][safi];
f018db83 5658
d62a17ae 5659 /* No aggregates configured. */
5660 if (bgp_table_top_nolock(table) == NULL)
5661 return;
f018db83 5662
d62a17ae 5663 if (p->prefixlen == 0)
5664 return;
718e3744 5665
d62a17ae 5666 if (BGP_INFO_HOLDDOWN(ri))
5667 return;
718e3744 5668
d62a17ae 5669 child = bgp_node_get(table, p);
718e3744 5670
d62a17ae 5671 /* Aggregate address configuration check. */
5672 for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
5673 if ((aggregate = rn->info) != NULL
5674 && rn->p.prefixlen < p->prefixlen) {
5675 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5676 bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL,
5677 aggregate);
5678 }
5679 bgp_unlock_node(child);
718e3744 5680}
5681
d62a17ae 5682void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
5683 struct bgp_info *del, afi_t afi, safi_t safi)
718e3744 5684{
d62a17ae 5685 struct bgp_node *child;
5686 struct bgp_node *rn;
5687 struct bgp_aggregate *aggregate;
5688 struct bgp_table *table;
718e3744 5689
d62a17ae 5690 /* MPLS-VPN aggregation is not yet supported. */
5691 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5692 || (safi == SAFI_EVPN))
5693 return;
f018db83 5694
d62a17ae 5695 table = bgp->aggregate[afi][safi];
718e3744 5696
d62a17ae 5697 /* No aggregates configured. */
5698 if (bgp_table_top_nolock(table) == NULL)
5699 return;
718e3744 5700
d62a17ae 5701 if (p->prefixlen == 0)
5702 return;
718e3744 5703
d62a17ae 5704 child = bgp_node_get(table, p);
718e3744 5705
d62a17ae 5706 /* Aggregate address configuration check. */
5707 for (rn = child; rn; rn = bgp_node_parent_nolock(rn))
5708 if ((aggregate = rn->info) != NULL
5709 && rn->p.prefixlen < p->prefixlen) {
5710 bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
5711 bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
5712 aggregate);
5713 }
5714 bgp_unlock_node(child);
5715}
718e3744 5716
d62a17ae 5717/* Called via bgp_aggregate_set when the user configures aggregate-address */
5718static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
5719 safi_t safi, struct bgp_aggregate *aggregate)
5720{
5721 struct bgp_table *table;
5722 struct bgp_node *top;
5723 struct bgp_node *rn;
5724 struct bgp_info *new;
5725 struct bgp_info *ri;
5726 unsigned long match;
5727 u_char origin = BGP_ORIGIN_IGP;
5728 struct aspath *aspath = NULL;
5729 struct aspath *asmerge = NULL;
5730 struct community *community = NULL;
5731 struct community *commerge = NULL;
5732 u_char atomic_aggregate = 0;
5733
5734 table = bgp->rib[afi][safi];
5735
5736 /* Sanity check. */
5737 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5738 return;
5739 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5740 return;
42f7e184 5741
d62a17ae 5742 /* If routes exists below this node, generate aggregate routes. */
5743 top = bgp_node_get(table, p);
5744 for (rn = bgp_node_get(table, p); rn;
ea47320b
DL
5745 rn = bgp_route_next_until(rn, top)) {
5746 if (rn->p.prefixlen <= p->prefixlen)
5747 continue;
d62a17ae 5748
ea47320b 5749 match = 0;
d62a17ae 5750
ea47320b
DL
5751 for (ri = rn->info; ri; ri = ri->next) {
5752 if (BGP_INFO_HOLDDOWN(ri))
5753 continue;
d62a17ae 5754
ea47320b
DL
5755 if (ri->attr->flag
5756 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5757 atomic_aggregate = 1;
d62a17ae 5758
ea47320b
DL
5759 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5760 continue;
d62a17ae 5761
ea47320b
DL
5762 /* summary-only aggregate route suppress
5763 * aggregated route announcement. */
5764 if (aggregate->summary_only) {
5765 (bgp_info_extra_get(ri))->suppress++;
5766 bgp_info_set_flag(rn, ri,
5767 BGP_INFO_ATTR_CHANGED);
5768 match++;
5769 }
d62a17ae 5770
ea47320b
DL
5771 /* If at least one route among routes that are
5772 * aggregated has ORIGIN with the value INCOMPLETE,
5773 * then the aggregated route MUST have the ORIGIN
5774 * attribute with the value INCOMPLETE. Otherwise, if
5775 * at least one route among routes that are aggregated
5776 * has ORIGIN with the value EGP, then the aggregated
5777 * route MUST have the ORIGIN attribute with the value
5778 * EGP.
5779 */
5780 if (origin < ri->attr->origin)
5781 origin = ri->attr->origin;
5782
5783 /* as-set aggregate route generate origin, as path,
5784 * community aggregation. */
5785 if (aggregate->as_set) {
5786 if (aspath) {
60466a63
QY
5787 asmerge = aspath_aggregate(
5788 aspath, ri->attr->aspath);
ea47320b
DL
5789 aspath_free(aspath);
5790 aspath = asmerge;
5791 } else
5792 aspath = aspath_dup(ri->attr->aspath);
5793
5794 if (ri->attr->community) {
5795 if (community) {
5796 commerge = community_merge(
5797 community,
5798 ri->attr->community);
5799 community = community_uniq_sort(
5800 commerge);
60466a63 5801 community_free(commerge);
ea47320b
DL
5802 } else
5803 community = community_dup(
5804 ri->attr->community);
d62a17ae 5805 }
5806 }
ea47320b 5807 aggregate->count++;
d62a17ae 5808 }
ea47320b
DL
5809
5810 /* If this node is suppressed, process the change. */
5811 if (match)
5812 bgp_process(bgp, rn, afi, safi);
5813 }
d62a17ae 5814 bgp_unlock_node(top);
5815
5816 /* Add aggregate route to BGP table. */
5817 if (aggregate->count) {
5818 rn = bgp_node_get(table, p);
5819 new = info_make(
5820 ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
5821 bgp_attr_aggregate_intern(bgp, origin, aspath,
5822 community, aggregate->as_set,
5823 atomic_aggregate),
5824 rn);
5825 SET_FLAG(new->flags, BGP_INFO_VALID);
5826
5827 bgp_info_add(rn, new);
5828 bgp_unlock_node(rn);
5829
5830 /* Process change. */
5831 bgp_process(bgp, rn, afi, safi);
5832 } else {
5833 if (aspath)
5834 aspath_free(aspath);
5835 if (community)
5836 community_free(community);
5837 }
718e3744 5838}
5839
d62a17ae 5840void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
5841 safi_t safi, struct bgp_aggregate *aggregate)
718e3744 5842{
d62a17ae 5843 struct bgp_table *table;
5844 struct bgp_node *top;
5845 struct bgp_node *rn;
5846 struct bgp_info *ri;
5847 unsigned long match;
718e3744 5848
d62a17ae 5849 table = bgp->rib[afi][safi];
718e3744 5850
d62a17ae 5851 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5852 return;
5853 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5854 return;
5855
5856 /* If routes exists below this node, generate aggregate routes. */
5857 top = bgp_node_get(table, p);
5858 for (rn = bgp_node_get(table, p); rn;
ea47320b
DL
5859 rn = bgp_route_next_until(rn, top)) {
5860 if (rn->p.prefixlen <= p->prefixlen)
5861 continue;
5862 match = 0;
d62a17ae 5863
ea47320b
DL
5864 for (ri = rn->info; ri; ri = ri->next) {
5865 if (BGP_INFO_HOLDDOWN(ri))
5866 continue;
d62a17ae 5867
ea47320b
DL
5868 if (ri->sub_type == BGP_ROUTE_AGGREGATE)
5869 continue;
5870
5871 if (aggregate->summary_only && ri->extra) {
5872 ri->extra->suppress--;
5873
5874 if (ri->extra->suppress == 0) {
60466a63
QY
5875 bgp_info_set_flag(
5876 rn, ri, BGP_INFO_ATTR_CHANGED);
ea47320b 5877 match++;
d62a17ae 5878 }
5879 }
ea47320b 5880 aggregate->count--;
d62a17ae 5881 }
ea47320b
DL
5882
5883 /* If this node was suppressed, process the change. */
5884 if (match)
5885 bgp_process(bgp, rn, afi, safi);
5886 }
d62a17ae 5887 bgp_unlock_node(top);
718e3744 5888
d62a17ae 5889 /* Delete aggregate route from BGP table. */
5890 rn = bgp_node_get(table, p);
718e3744 5891
5892 for (ri = rn->info; ri; ri = ri->next)
d62a17ae 5893 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
5894 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5895 break;
5896
5897 /* Withdraw static BGP route from routing table. */
5898 if (ri) {
5899 bgp_info_delete(rn, ri);
5900 bgp_process(bgp, rn, afi, safi);
5901 }
718e3744 5902
d62a17ae 5903 /* Unlock bgp_node_lookup. */
5904 bgp_unlock_node(rn);
718e3744 5905}
5906
5907/* Aggregate route attribute. */
5908#define AGGREGATE_SUMMARY_ONLY 1
5909#define AGGREGATE_AS_SET 1
5910
d62a17ae 5911static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
5912 afi_t afi, safi_t safi)
718e3744 5913{
d62a17ae 5914 VTY_DECLVAR_CONTEXT(bgp, bgp);
5915 int ret;
5916 struct prefix p;
5917 struct bgp_node *rn;
5918 struct bgp_aggregate *aggregate;
718e3744 5919
d62a17ae 5920 /* Convert string to prefix structure. */
5921 ret = str2prefix(prefix_str, &p);
5922 if (!ret) {
5923 vty_out(vty, "Malformed prefix\n");
5924 return CMD_WARNING_CONFIG_FAILED;
5925 }
5926 apply_mask(&p);
5927
5928 /* Old configuration check. */
5929 rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
5930 if (!rn) {
5931 vty_out(vty,
5932 "%% There is no aggregate-address configuration.\n");
5933 return CMD_WARNING_CONFIG_FAILED;
5934 }
f6269b4f 5935
d62a17ae 5936 aggregate = rn->info;
5937 if (aggregate->safi == SAFI_UNICAST)
5938 bgp_aggregate_delete(bgp, &p, afi, SAFI_UNICAST, aggregate);
5939 if (aggregate->safi == SAFI_LABELED_UNICAST)
5940 bgp_aggregate_delete(bgp, &p, afi, SAFI_LABELED_UNICAST,
5941 aggregate);
5942 if (aggregate->safi == SAFI_MULTICAST)
5943 bgp_aggregate_delete(bgp, &p, afi, SAFI_MULTICAST, aggregate);
5944
5945 /* Unlock aggregate address configuration. */
5946 rn->info = NULL;
5947 bgp_aggregate_free(aggregate);
5948 bgp_unlock_node(rn);
5949 bgp_unlock_node(rn);
5950
5951 return CMD_SUCCESS;
5952}
5953
5954static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
5955 safi_t safi, u_char summary_only, u_char as_set)
5956{
5957 VTY_DECLVAR_CONTEXT(bgp, bgp);
5958 int ret;
5959 struct prefix p;
5960 struct bgp_node *rn;
5961 struct bgp_aggregate *aggregate;
5962
5963 /* Convert string to prefix structure. */
5964 ret = str2prefix(prefix_str, &p);
5965 if (!ret) {
5966 vty_out(vty, "Malformed prefix\n");
5967 return CMD_WARNING_CONFIG_FAILED;
5968 }
5969 apply_mask(&p);
5970
5971 /* Old configuration check. */
5972 rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
5973
5974 if (rn->info) {
5975 vty_out(vty, "There is already same aggregate network.\n");
5976 /* try to remove the old entry */
5977 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
5978 if (ret) {
5979 vty_out(vty, "Error deleting aggregate.\n");
5980 bgp_unlock_node(rn);
5981 return CMD_WARNING_CONFIG_FAILED;
5982 }
5983 }
718e3744 5984
d62a17ae 5985 /* Make aggregate address structure. */
5986 aggregate = bgp_aggregate_new();
5987 aggregate->summary_only = summary_only;
5988 aggregate->as_set = as_set;
5989 aggregate->safi = safi;
5990 rn->info = aggregate;
718e3744 5991
d62a17ae 5992 /* Aggregate address insert into BGP routing table. */
5993 if (safi == SAFI_UNICAST)
5994 bgp_aggregate_add(bgp, &p, afi, SAFI_UNICAST, aggregate);
5995 if (safi == SAFI_LABELED_UNICAST)
5996 bgp_aggregate_add(bgp, &p, afi, SAFI_LABELED_UNICAST,
5997 aggregate);
5998 if (safi == SAFI_MULTICAST)
5999 bgp_aggregate_add(bgp, &p, afi, SAFI_MULTICAST, aggregate);
718e3744 6000
d62a17ae 6001 return CMD_SUCCESS;
718e3744 6002}
6003
6004DEFUN (aggregate_address,
6005 aggregate_address_cmd,
e3e6107d 6006 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6007 "Configure BGP aggregate entries\n"
6008 "Aggregate prefix\n"
6009 "Generate AS set path information\n"
a636c635
DW
6010 "Filter more specific routes from updates\n"
6011 "Filter more specific routes from updates\n"
6012 "Generate AS set path information\n")
718e3744 6013{
d62a17ae 6014 int idx = 0;
6015 argv_find(argv, argc, "A.B.C.D/M", &idx);
6016 char *prefix = argv[idx]->arg;
6017 int as_set =
6018 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6019 idx = 0;
6020 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6021 ? AGGREGATE_SUMMARY_ONLY
6022 : 0;
e3e6107d 6023
d62a17ae 6024 return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
6025 summary_only, as_set);
718e3744 6026}
6027
e3e6107d
QY
6028DEFUN (aggregate_address_mask,
6029 aggregate_address_mask_cmd,
6030 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6031 "Configure BGP aggregate entries\n"
6032 "Aggregate address\n"
6033 "Aggregate mask\n"
6034 "Generate AS set path information\n"
a636c635
DW
6035 "Filter more specific routes from updates\n"
6036 "Filter more specific routes from updates\n"
6037 "Generate AS set path information\n")
718e3744 6038{
d62a17ae 6039 int idx = 0;
6040 argv_find(argv, argc, "A.B.C.D", &idx);
6041 char *prefix = argv[idx]->arg;
6042 char *mask = argv[idx + 1]->arg;
6043 int as_set =
6044 argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
6045 idx = 0;
6046 int summary_only = argv_find(argv, argc, "summary-only", &idx)
6047 ? AGGREGATE_SUMMARY_ONLY
6048 : 0;
6049
6050 char prefix_str[BUFSIZ];
6051 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
6052
6053 if (!ret) {
6054 vty_out(vty, "%% Inconsistent address and mask\n");
6055 return CMD_WARNING_CONFIG_FAILED;
6056 }
718e3744 6057
d62a17ae 6058 return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
6059 summary_only, as_set);
718e3744 6060}
6061
718e3744 6062DEFUN (no_aggregate_address,
6063 no_aggregate_address_cmd,
e3e6107d 6064 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6065 NO_STR
6066 "Configure BGP aggregate entries\n"
a636c635
DW
6067 "Aggregate prefix\n"
6068 "Generate AS set path information\n"
e3e6107d
QY
6069 "Filter more specific routes from updates\n"
6070 "Filter more specific routes from updates\n"
6071 "Generate AS set path information\n")
718e3744 6072{
d62a17ae 6073 int idx = 0;
6074 argv_find(argv, argc, "A.B.C.D/M", &idx);
6075 char *prefix = argv[idx]->arg;
6076 return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
718e3744 6077}
6078
718e3744 6079DEFUN (no_aggregate_address_mask,
6080 no_aggregate_address_mask_cmd,
e3e6107d 6081 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 6082 NO_STR
6083 "Configure BGP aggregate entries\n"
6084 "Aggregate address\n"
a636c635
DW
6085 "Aggregate mask\n"
6086 "Generate AS set path information\n"
e3e6107d
QY
6087 "Filter more specific routes from updates\n"
6088 "Filter more specific routes from updates\n"
6089 "Generate AS set path information\n")
718e3744 6090{
d62a17ae 6091 int idx = 0;
6092 argv_find(argv, argc, "A.B.C.D", &idx);
6093 char *prefix = argv[idx]->arg;
6094 char *mask = argv[idx + 1]->arg;
718e3744 6095
d62a17ae 6096 char prefix_str[BUFSIZ];
6097 int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
718e3744 6098
d62a17ae 6099 if (!ret) {
6100 vty_out(vty, "%% Inconsistent address and mask\n");
6101 return CMD_WARNING_CONFIG_FAILED;
6102 }
718e3744 6103
d62a17ae 6104 return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
718e3744 6105}
6106
718e3744 6107DEFUN (ipv6_aggregate_address,
6108 ipv6_aggregate_address_cmd,
e3e6107d 6109 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 6110 "Configure BGP aggregate entries\n"
6111 "Aggregate prefix\n"
6112 "Filter more specific routes from updates\n")
6113{
d62a17ae 6114 int idx = 0;
6115 argv_find(argv, argc, "X:X::X:X/M", &idx);
6116 char *prefix = argv[idx]->arg;
6117 int sum_only = argv_find(argv, argc, "summary-only", &idx)
6118 ? AGGREGATE_SUMMARY_ONLY
6119 : 0;
6120 return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
6121 0);
718e3744 6122}
6123
6124DEFUN (no_ipv6_aggregate_address,
6125 no_ipv6_aggregate_address_cmd,
e3e6107d 6126 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 6127 NO_STR
6128 "Configure BGP aggregate entries\n"
16cedbb0
QY
6129 "Aggregate prefix\n"
6130 "Filter more specific routes from updates\n")
718e3744 6131{
d62a17ae 6132 int idx = 0;
6133 argv_find(argv, argc, "X:X::X:X/M", &idx);
6134 char *prefix = argv[idx]->arg;
6135 return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 6136}
6137
718e3744 6138/* Redistribute route treatment. */
d62a17ae 6139void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
6140 const union g_addr *nexthop, ifindex_t ifindex,
6141 enum nexthop_types_t nhtype, uint32_t metric,
6142 u_char type, u_short instance,
d62a17ae 6143 route_tag_t tag)
6144{
6145 struct bgp_info *new;
6146 struct bgp_info *bi;
6147 struct bgp_info info;
6148 struct bgp_node *bn;
6149 struct attr attr;
6150 struct attr *new_attr;
6151 afi_t afi;
6152 int ret;
6153 struct bgp_redist *red;
6154
6155 /* Make default attribute. */
6156 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
9de1f7ff
DS
6157
6158 switch(nhtype) {
6159 case NEXTHOP_TYPE_IFINDEX:
6160 break;
6161 case NEXTHOP_TYPE_IPV4:
6162 case NEXTHOP_TYPE_IPV4_IFINDEX:
6163 attr.nexthop = nexthop->ipv4;
6164 break;
6165 case NEXTHOP_TYPE_IPV6:
6166 case NEXTHOP_TYPE_IPV6_IFINDEX:
6167 attr.mp_nexthop_global = nexthop->ipv6;
6168 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
6169 break;
6170 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
6171 switch (p->family) {
6172 case AF_INET:
9de1f7ff 6173 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
6174 break;
6175 case AF_INET6:
9de1f7ff
DS
6176 memset(&attr.mp_nexthop_global, 0,
6177 sizeof(attr.mp_nexthop_global));
74489921 6178 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 6179 break;
74489921 6180 }
9de1f7ff 6181 break;
d62a17ae 6182 }
74489921 6183 attr.nh_ifindex = ifindex;
f04a80a5 6184
d62a17ae 6185 attr.med = metric;
6186 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
6187 attr.tag = tag;
718e3744 6188
d62a17ae 6189 afi = family2afi(p->family);
6aeb9e78 6190
d62a17ae 6191 red = bgp_redist_lookup(bgp, afi, type, instance);
6192 if (red) {
6193 struct attr attr_new;
718e3744 6194
d62a17ae 6195 /* Copy attribute for modification. */
6196 bgp_attr_dup(&attr_new, &attr);
718e3744 6197
d62a17ae 6198 if (red->redist_metric_flag)
6199 attr_new.med = red->redist_metric;
718e3744 6200
d62a17ae 6201 /* Apply route-map. */
6202 if (red->rmap.name) {
6203 info.peer = bgp->peer_self;
6204 info.attr = &attr_new;
718e3744 6205
d62a17ae 6206 SET_FLAG(bgp->peer_self->rmap_type,
6207 PEER_RMAP_TYPE_REDISTRIBUTE);
6208
6209 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
6210 &info);
6211
6212 bgp->peer_self->rmap_type = 0;
6213
6214 if (ret == RMAP_DENYMATCH) {
6215 /* Free uninterned attribute. */
6216 bgp_attr_flush(&attr_new);
6217
6218 /* Unintern original. */
6219 aspath_unintern(&attr.aspath);
6220 bgp_redistribute_delete(bgp, p, type, instance);
6221 return;
6222 }
6223 }
6224
7f323236
DW
6225 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
6226 bgp_attr_add_gshut_community(&attr_new);
6227
d62a17ae 6228 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6229 SAFI_UNICAST, p, NULL);
6230
6231 new_attr = bgp_attr_intern(&attr_new);
6232
6233 for (bi = bn->info; bi; bi = bi->next)
6234 if (bi->peer == bgp->peer_self
6235 && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
6236 break;
6237
6238 if (bi) {
6239 /* Ensure the (source route) type is updated. */
6240 bi->type = type;
6241 if (attrhash_cmp(bi->attr, new_attr)
6242 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
6243 bgp_attr_unintern(&new_attr);
6244 aspath_unintern(&attr.aspath);
6245 bgp_unlock_node(bn);
6246 return;
6247 } else {
6248 /* The attribute is changed. */
6249 bgp_info_set_flag(bn, bi,
6250 BGP_INFO_ATTR_CHANGED);
6251
6252 /* Rewrite BGP route information. */
6253 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
6254 bgp_info_restore(bn, bi);
6255 else
6256 bgp_aggregate_decrement(bgp, p, bi, afi,
6257 SAFI_UNICAST);
6258 bgp_attr_unintern(&bi->attr);
6259 bi->attr = new_attr;
6260 bi->uptime = bgp_clock();
6261
6262 /* Process change. */
6263 bgp_aggregate_increment(bgp, p, bi, afi,
6264 SAFI_UNICAST);
6265 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6266 bgp_unlock_node(bn);
6267 aspath_unintern(&attr.aspath);
6268 return;
6269 }
6270 }
6271
6272 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
6273 bgp->peer_self, new_attr, bn);
6274 SET_FLAG(new->flags, BGP_INFO_VALID);
6275
6276 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
6277 bgp_info_add(bn, new);
6278 bgp_unlock_node(bn);
6279 bgp_process(bgp, bn, afi, SAFI_UNICAST);
6280 }
6281
6282 /* Unintern original. */
6283 aspath_unintern(&attr.aspath);
718e3744 6284}
6285
d62a17ae 6286void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, u_char type,
6287 u_short instance)
718e3744 6288{
d62a17ae 6289 afi_t afi;
6290 struct bgp_node *rn;
6291 struct bgp_info *ri;
6292 struct bgp_redist *red;
718e3744 6293
d62a17ae 6294 afi = family2afi(p->family);
718e3744 6295
d62a17ae 6296 red = bgp_redist_lookup(bgp, afi, type, instance);
6297 if (red) {
6298 rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
6299 SAFI_UNICAST, p, NULL);
6300
6301 for (ri = rn->info; ri; ri = ri->next)
6302 if (ri->peer == bgp->peer_self && ri->type == type)
6303 break;
6304
6305 if (ri) {
6306 bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
6307 bgp_info_delete(rn, ri);
6308 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6309 }
6310 bgp_unlock_node(rn);
6311 }
6312}
6313
6314/* Withdraw specified route type's route. */
6315void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
6316 u_short instance)
6317{
6318 struct bgp_node *rn;
6319 struct bgp_info *ri;
6320 struct bgp_table *table;
6321
6322 table = bgp->rib[afi][SAFI_UNICAST];
6323
6324 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
6325 for (ri = rn->info; ri; ri = ri->next)
6326 if (ri->peer == bgp->peer_self && ri->type == type
6327 && ri->instance == instance)
6328 break;
6329
6330 if (ri) {
6331 bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
6332 SAFI_UNICAST);
6333 bgp_info_delete(rn, ri);
6334 bgp_process(bgp, rn, afi, SAFI_UNICAST);
6335 }
718e3744 6336 }
718e3744 6337}
6b0655a2 6338
718e3744 6339/* Static function to display route. */
9c92b5f7
MK
6340static void route_vty_out_route(struct prefix *p, struct vty *vty,
6341 json_object *json)
718e3744 6342{
be054588 6343 int len = 0;
d62a17ae 6344 u_int32_t destination;
6345 char buf[BUFSIZ];
718e3744 6346
d62a17ae 6347 if (p->family == AF_INET) {
c6462ff4
MK
6348 if (!json) {
6349 len = vty_out(vty, "%s",
6350 inet_ntop(p->family, &p->u.prefix, buf,
6351 BUFSIZ));
6352 destination = ntohl(p->u.prefix4.s_addr);
6353
6354 if ((IN_CLASSC(destination) && p->prefixlen == 24)
6355 || (IN_CLASSB(destination) && p->prefixlen == 16)
6356 || (IN_CLASSA(destination) && p->prefixlen == 8)
6357 || p->u.prefix4.s_addr == 0) {
b682f6de 6358 /* When mask is natural,
6359 mask is not displayed. */
c6462ff4
MK
6360 } else
6361 len += vty_out(vty, "/%d", p->prefixlen);
6362 } else {
6363 json_object_string_add(json, "prefix",
6364 inet_ntop(p->family,
6365 &p->u.prefix, buf,
6366 BUFSIZ));
6367 json_object_int_add(json, "prefixLen", p->prefixlen);
6368 }
d62a17ae 6369 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
6370 prefix2str(p, buf, PREFIX_STRLEN);
6371 len = vty_out(vty, "%s", buf);
6372 } else if (p->family == AF_EVPN) {
d62a17ae 6373#if defined(HAVE_CUMULUS)
57f7feb6 6374 if (!json)
60466a63
QY
6375 len = vty_out(
6376 vty, "%s",
6377 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
6378 BUFSIZ));
57f7feb6 6379 else
60466a63 6380 bgp_evpn_route2json((struct prefix_evpn *)p, json);
520d5d76 6381#else
d62a17ae 6382 prefix2str(p, buf, PREFIX_STRLEN);
6383 len = vty_out(vty, "%s", buf);
520d5d76 6384#endif
9c92b5f7 6385 } else {
c6462ff4 6386 if (!json)
60466a63
QY
6387 len = vty_out(
6388 vty, "%s/%d",
6389 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
6390 p->prefixlen);
9c92b5f7 6391 }
d62a17ae 6392
9c92b5f7
MK
6393 if (!json) {
6394 len = 17 - len;
6395 if (len < 1)
6396 vty_out(vty, "\n%*s", 20, " ");
6397 else
6398 vty_out(vty, "%*s", len, " ");
6399 }
718e3744 6400}
6401
d62a17ae 6402enum bgp_display_type {
6403 normal_list,
718e3744 6404};
6405
b40d939b 6406/* Print the short form route status for a bgp_info */
d62a17ae 6407static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo,
6408 json_object *json_path)
718e3744 6409{
d62a17ae 6410 if (json_path) {
b05a1c8b 6411
d62a17ae 6412 /* Route status display. */
6413 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6414 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 6415
d62a17ae 6416 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6417 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 6418
d62a17ae 6419 if (binfo->extra && binfo->extra->suppress)
6420 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 6421
d62a17ae 6422 if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6423 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6424 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 6425
d62a17ae 6426 /* Selected */
6427 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6428 json_object_boolean_true_add(json_path, "history");
b05a1c8b 6429
d62a17ae 6430 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6431 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 6432
d62a17ae 6433 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6434 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 6435
d62a17ae 6436 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6437 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 6438
d62a17ae 6439 /* Internal route. */
6440 if ((binfo->peer->as)
6441 && (binfo->peer->as == binfo->peer->local_as))
6442 json_object_string_add(json_path, "pathFrom",
6443 "internal");
6444 else
6445 json_object_string_add(json_path, "pathFrom",
6446 "external");
b05a1c8b 6447
d62a17ae 6448 return;
6449 }
b05a1c8b 6450
d62a17ae 6451 /* Route status display. */
6452 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED))
6453 vty_out(vty, "R");
6454 else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE))
6455 vty_out(vty, "S");
6456 else if (binfo->extra && binfo->extra->suppress)
6457 vty_out(vty, "s");
6458 else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID)
6459 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6460 vty_out(vty, "*");
6461 else
6462 vty_out(vty, " ");
6463
6464 /* Selected */
6465 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
6466 vty_out(vty, "h");
6467 else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
6468 vty_out(vty, "d");
6469 else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
6470 vty_out(vty, ">");
6471 else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH))
6472 vty_out(vty, "=");
6473 else
6474 vty_out(vty, " ");
718e3744 6475
d62a17ae 6476 /* Internal route. */
6477 if (binfo->peer && (binfo->peer->as)
6478 && (binfo->peer->as == binfo->peer->local_as))
6479 vty_out(vty, "i");
6480 else
6481 vty_out(vty, " ");
b40d939b 6482}
6483
6484/* called from terminal list command */
d62a17ae 6485void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6486 int display, safi_t safi, json_object *json_paths)
6487{
6488 struct attr *attr;
6489 json_object *json_path = NULL;
6490 json_object *json_nexthops = NULL;
6491 json_object *json_nexthop_global = NULL;
6492 json_object *json_nexthop_ll = NULL;
6493
6494 if (json_paths)
6495 json_path = json_object_new_object();
6496
6497 /* short status lead text */
6498 route_vty_short_status_out(vty, binfo, json_path);
6499
6500 if (!json_paths) {
6501 /* print prefix and mask */
6502 if (!display)
9c92b5f7 6503 route_vty_out_route(p, vty, json_path);
d62a17ae 6504 else
6505 vty_out(vty, "%*s", 17, " ");
9c92b5f7 6506 } else {
b682f6de 6507 route_vty_out_route(p, vty, json_path);
d62a17ae 6508 }
47fc97cc 6509
d62a17ae 6510 /* Print attribute */
6511 attr = binfo->attr;
445c2480
DS
6512 if (!attr) {
6513 if (json_paths)
6514 json_object_array_add(json_paths, json_path);
6515 else
6516 vty_out(vty, "\n");
d62a17ae 6517
445c2480
DS
6518 return;
6519 }
6520
6521 /*
6522 * For ENCAP and EVPN routes, nexthop address family is not
6523 * neccessarily the same as the prefix address family.
6524 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6525 * EVPN routes are also exchanged with a MP nexthop. Currently,
6526 * this
6527 * is only IPv4, the value will be present in either
6528 * attr->nexthop or
6529 * attr->mp_nexthop_global_in
6530 */
6531 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
6532 char buf[BUFSIZ];
6533 char nexthop[128];
6534 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
6535
6536 switch (af) {
6537 case AF_INET:
6538 sprintf(nexthop, "%s",
6539 inet_ntop(af, &attr->mp_nexthop_global_in,
6540 buf, BUFSIZ));
6541 break;
6542 case AF_INET6:
6543 sprintf(nexthop, "%s",
6544 inet_ntop(af, &attr->mp_nexthop_global,
6545 buf, BUFSIZ));
6546 break;
6547 default:
6548 sprintf(nexthop, "?");
6549 break;
d62a17ae 6550 }
d62a17ae 6551
445c2480
DS
6552 if (json_paths) {
6553 json_nexthop_global = json_object_new_object();
6554
6555 json_object_string_add(json_nexthop_global,
6556 "afi",
6557 (af == AF_INET) ?
6558 "ip" : "ipv6");
6559 json_object_string_add(json_nexthop_global,
6560 (af == AF_INET) ?
6561 "ip" : "ipv6",
6562 nexthop);
6563 json_object_boolean_true_add(json_nexthop_global,
6564 "used");
6565 } else
6566 vty_out(vty, "%s", nexthop);
6567 } else if (safi == SAFI_EVPN) {
6568 if (json_paths) {
6569 json_nexthop_global = json_object_new_object();
6570
6571 json_object_string_add(json_nexthop_global, "ip",
6572 inet_ntoa(attr->nexthop));
6573 json_object_string_add(json_nexthop_global,
6574 "afi", "ipv4");
6575 json_object_boolean_true_add(json_nexthop_global,
6576 "used");
6577 } else
6578 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
6579 }
6580 /* IPv4 Next Hop */
6581 else if (p->family == AF_INET
6582 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6583 if (json_paths) {
6584 json_nexthop_global = json_object_new_object();
d62a17ae 6585
445c2480
DS
6586 if ((safi == SAFI_MPLS_VPN)
6587 || (safi == SAFI_EVPN))
d62a17ae 6588 json_object_string_add(json_nexthop_global,
445c2480
DS
6589 "ip",
6590 inet_ntoa(attr->mp_nexthop_global_in));
6591 else
6592 json_object_string_add(json_nexthop_global,
6593 "ip",
6594 inet_ntoa(attr->nexthop));
6595
6596 json_object_string_add(json_nexthop_global,
6597 "afi", "ipv4");
6598 json_object_boolean_true_add(json_nexthop_global,
6599 "used");
6600 } else {
6601 if ((safi == SAFI_MPLS_VPN)
6602 || (safi == SAFI_EVPN))
6603 vty_out(vty, "%-16s",
6604 inet_ntoa(
6605 attr->mp_nexthop_global_in));
6606 else
6607 vty_out(vty, "%-16s",
6608 inet_ntoa(attr->nexthop));
d62a17ae 6609 }
445c2480 6610 }
b05a1c8b 6611
445c2480
DS
6612 /* IPv6 Next Hop */
6613 else if (p->family == AF_INET6
6614 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6615 int len;
6616 char buf[BUFSIZ];
d62a17ae 6617
445c2480
DS
6618 if (json_paths) {
6619 json_nexthop_global = json_object_new_object();
6620 json_object_string_add(json_nexthop_global, "ip",
6621 inet_ntop(AF_INET6,
6622 &attr->mp_nexthop_global, buf,
6623 BUFSIZ));
6624 json_object_string_add(json_nexthop_global,
6625 "afi", "ipv6");
6626 json_object_string_add(json_nexthop_global,
6627 "scope", "global");
6628
6629 /* We display both LL & GL if both have been
6630 * received */
6631 if ((attr->mp_nexthop_len == 32)
6632 || (binfo->peer->conf_if)) {
6633 json_nexthop_ll =
6634 json_object_new_object();
d62a17ae 6635 json_object_string_add(
445c2480
DS
6636 json_nexthop_ll, "ip",
6637 inet_ntop(
6638 AF_INET6,
6639 &attr->mp_nexthop_local,
6640 buf, BUFSIZ));
6641 json_object_string_add(json_nexthop_ll,
d62a17ae 6642 "afi", "ipv6");
445c2480
DS
6643 json_object_string_add(json_nexthop_ll,
6644 "scope",
6645 "link-local");
d62a17ae 6646
445c2480
DS
6647 if ((IPV6_ADDR_CMP(
6648 &attr->mp_nexthop_global,
6649 &attr->mp_nexthop_local)
6650 != 0)
6651 && !attr->mp_nexthop_prefer_global)
d62a17ae 6652 json_object_boolean_true_add(
445c2480
DS
6653 json_nexthop_ll,
6654 "used");
6655 else
6656 json_object_boolean_true_add(
6657 json_nexthop_global,
6658 "used");
6659 } else
6660 json_object_boolean_true_add(
6661 json_nexthop_global, "used");
6662 } else {
6663 /* Display LL if LL/Global both in table unless
6664 * prefer-global is set */
6665 if (((attr->mp_nexthop_len == 32)
6666 && !attr->mp_nexthop_prefer_global)
6667 || (binfo->peer->conf_if)) {
6668 if (binfo->peer->conf_if) {
6669 len = vty_out(
6670 vty, "%s",
6671 binfo->peer->conf_if);
6672 len = 16 - len; /* len of IPv6
6673 addr + max
6674 len of def
6675 ifname */
6676
6677 if (len < 1)
6678 vty_out(vty, "\n%*s",
6679 36, " ");
6680 else
6681 vty_out(vty, "%*s", len,
6682 " ");
d62a17ae 6683 } else {
6684 len = vty_out(
6685 vty, "%s",
6686 inet_ntop(
6687 AF_INET6,
445c2480 6688 &attr->mp_nexthop_local,
d62a17ae 6689 buf, BUFSIZ));
6690 len = 16 - len;
6691
6692 if (len < 1)
445c2480
DS
6693 vty_out(vty, "\n%*s",
6694 36, " ");
d62a17ae 6695 else
445c2480
DS
6696 vty_out(vty, "%*s", len,
6697 " ");
d62a17ae 6698 }
445c2480
DS
6699 } else {
6700 len = vty_out(vty, "%s",
6701 inet_ntop(AF_INET6,
6702 &attr->mp_nexthop_global,
6703 buf, BUFSIZ));
6704 len = 16 - len;
6705
6706 if (len < 1)
6707 vty_out(vty, "\n%*s", 36, " ");
6708 else
6709 vty_out(vty, "%*s", len, " ");
d62a17ae 6710 }
6711 }
445c2480 6712 }
718e3744 6713
445c2480
DS
6714 /* MED/Metric */
6715 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6716 if (json_paths)
6717 json_object_int_add(json_path, "med",
6718 attr->med);
6719 else
6720 vty_out(vty, "%10u", attr->med);
6721 else if (!json_paths)
6722 vty_out(vty, " ");
d62a17ae 6723
445c2480
DS
6724 /* Local Pref */
6725 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
d62a17ae 6726 if (json_paths)
445c2480
DS
6727 json_object_int_add(json_path, "localpref",
6728 attr->local_pref);
d62a17ae 6729 else
445c2480
DS
6730 vty_out(vty, "%7u", attr->local_pref);
6731 else if (!json_paths)
6732 vty_out(vty, " ");
d62a17ae 6733
445c2480
DS
6734 if (json_paths)
6735 json_object_int_add(json_path, "weight", attr->weight);
6736 else
6737 vty_out(vty, "%7u ", attr->weight);
47fc97cc 6738
445c2480
DS
6739 if (json_paths) {
6740 char buf[BUFSIZ];
6741 json_object_string_add(json_path, "peerId",
6742 sockunion2str(&binfo->peer->su,
6743 buf,
6744 SU_ADDRSTRLEN));
6745 }
b05a1c8b 6746
445c2480
DS
6747 /* Print aspath */
6748 if (attr->aspath) {
d62a17ae 6749 if (json_paths)
445c2480
DS
6750 json_object_string_add(json_path, "aspath",
6751 attr->aspath->str);
d62a17ae 6752 else
445c2480 6753 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 6754 }
f1aa5d8a 6755
445c2480
DS
6756 /* Print origin */
6757 if (json_paths)
6758 json_object_string_add(
6759 json_path, "origin",
6760 bgp_origin_long_str[attr->origin]);
6761 else
6762 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6763
d62a17ae 6764 if (json_paths) {
6765 if (json_nexthop_global || json_nexthop_ll) {
6766 json_nexthops = json_object_new_array();
f1aa5d8a 6767
d62a17ae 6768 if (json_nexthop_global)
6769 json_object_array_add(json_nexthops,
6770 json_nexthop_global);
f1aa5d8a 6771
d62a17ae 6772 if (json_nexthop_ll)
6773 json_object_array_add(json_nexthops,
6774 json_nexthop_ll);
f1aa5d8a 6775
d62a17ae 6776 json_object_object_add(json_path, "nexthops",
6777 json_nexthops);
6778 }
6779
6780 json_object_array_add(json_paths, json_path);
6781 } else {
6782 vty_out(vty, "\n");
65efcfce 6783#if ENABLE_BGP_VNC
d62a17ae 6784 /* prints an additional line, indented, with VNC info, if
6785 * present */
6786 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
6787 rfapi_vty_out_vncinfo(vty, p, binfo, safi);
65efcfce 6788#endif
d62a17ae 6789 }
6790}
718e3744 6791
6792/* called from terminal list command */
d62a17ae 6793void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
6794 safi_t safi, u_char use_json, json_object *json_ar)
6795{
6796 json_object *json_status = NULL;
6797 json_object *json_net = NULL;
6798 char buff[BUFSIZ];
6799 /* Route status display. */
6800 if (use_json) {
6801 json_status = json_object_new_object();
6802 json_net = json_object_new_object();
6803 } else {
6804 vty_out(vty, "*");
6805 vty_out(vty, ">");
6806 vty_out(vty, " ");
6807 }
718e3744 6808
d62a17ae 6809 /* print prefix and mask */
6810 if (use_json)
6811 json_object_string_add(
6812 json_net, "addrPrefix",
6813 inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
6814 else
9c92b5f7 6815 route_vty_out_route(p, vty, NULL);
d62a17ae 6816
6817 /* Print attribute */
6818 if (attr) {
6819 if (use_json) {
6820 if (p->family == AF_INET
6821 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6822 || safi == SAFI_EVPN
6823 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6824 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6825 || safi == SAFI_EVPN)
6826 json_object_string_add(
6827 json_net, "nextHop",
6828 inet_ntoa(
6829 attr->mp_nexthop_global_in));
6830 else
6831 json_object_string_add(
6832 json_net, "nextHop",
6833 inet_ntoa(attr->nexthop));
6834 } else if (p->family == AF_INET6
6835 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6836 char buf[BUFSIZ];
6837
6838 json_object_string_add(
6839 json_net, "netHopGloabal",
6840 inet_ntop(AF_INET6,
6841 &attr->mp_nexthop_global, buf,
6842 BUFSIZ));
6843 }
6844
6845 if (attr->flag
6846 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6847 json_object_int_add(json_net, "metric",
6848 attr->med);
6849
6850 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6851 json_object_int_add(json_net, "localPref",
6852 attr->local_pref);
6853
6854 json_object_int_add(json_net, "weight", attr->weight);
6855
6856 /* Print aspath */
6857 if (attr->aspath)
6858 json_object_string_add(json_net, "asPath",
6859 attr->aspath->str);
6860
6861 /* Print origin */
6862 json_object_string_add(json_net, "bgpOriginCode",
6863 bgp_origin_str[attr->origin]);
6864 } else {
6865 if (p->family == AF_INET
6866 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6867 || safi == SAFI_EVPN
6868 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6869 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6870 || safi == SAFI_EVPN)
6871 vty_out(vty, "%-16s",
6872 inet_ntoa(
6873 attr->mp_nexthop_global_in));
6874 else
6875 vty_out(vty, "%-16s",
6876 inet_ntoa(attr->nexthop));
6877 } else if (p->family == AF_INET6
6878 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
6879 int len;
6880 char buf[BUFSIZ];
6881
6882 len = vty_out(
6883 vty, "%s",
6884 inet_ntop(AF_INET6,
6885 &attr->mp_nexthop_global, buf,
6886 BUFSIZ));
6887 len = 16 - len;
6888 if (len < 1)
6889 vty_out(vty, "\n%*s", 36, " ");
6890 else
6891 vty_out(vty, "%*s", len, " ");
6892 }
6893 if (attr->flag
6894 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
6895 vty_out(vty, "%10u", attr->med);
6896 else
6897 vty_out(vty, " ");
718e3744 6898
d62a17ae 6899 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
6900 vty_out(vty, "%7u", attr->local_pref);
6901 else
6902 vty_out(vty, " ");
6903
6904 vty_out(vty, "%7u ", attr->weight);
6905
6906 /* Print aspath */
6907 if (attr->aspath)
6908 aspath_print_vty(vty, "%s", attr->aspath, " ");
6909
6910 /* Print origin */
6911 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
6912 }
6913 }
6914 if (use_json) {
6915 json_object_boolean_true_add(json_status, "*");
6916 json_object_boolean_true_add(json_status, ">");
6917 json_object_object_add(json_net, "appliedStatusSymbols",
6918 json_status);
6919 char buf_cut[BUFSIZ];
6920 json_object_object_add(
6921 json_ar,
6922 inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
6923 json_net);
6924 } else
6925 vty_out(vty, "\n");
6926}
6927
6928void route_vty_out_tag(struct vty *vty, struct prefix *p,
6929 struct bgp_info *binfo, int display, safi_t safi,
6930 json_object *json)
6931{
6932 json_object *json_out = NULL;
6933 struct attr *attr;
6934 mpls_label_t label = MPLS_INVALID_LABEL;
6935
6936 if (!binfo->extra)
6937 return;
6938
6939 if (json)
6940 json_out = json_object_new_object();
6941
6942 /* short status lead text */
6943 route_vty_short_status_out(vty, binfo, json_out);
6944
6945 /* print prefix and mask */
6946 if (json == NULL) {
6947 if (!display)
9c92b5f7 6948 route_vty_out_route(p, vty, NULL);
d62a17ae 6949 else
6950 vty_out(vty, "%*s", 17, " ");
6951 }
6952
6953 /* Print attribute */
6954 attr = binfo->attr;
6955 if (attr) {
6956 if (((p->family == AF_INET)
6957 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6958 || (safi == SAFI_EVPN
d62a17ae 6959 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6960 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6961 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
6962 || safi == SAFI_EVPN) {
6963 if (json)
6964 json_object_string_add(
6965 json_out, "mpNexthopGlobalIn",
6966 inet_ntoa(
6967 attr->mp_nexthop_global_in));
6968 else
6969 vty_out(vty, "%-16s",
6970 inet_ntoa(
6971 attr->mp_nexthop_global_in));
6972 } else {
6973 if (json)
6974 json_object_string_add(
6975 json_out, "nexthop",
6976 inet_ntoa(attr->nexthop));
6977 else
6978 vty_out(vty, "%-16s",
6979 inet_ntoa(attr->nexthop));
6980 }
6981 } else if (((p->family == AF_INET6)
6982 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
b03b8898 6983 || (safi == SAFI_EVPN
d62a17ae 6984 && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6985 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
6986 char buf_a[BUFSIZ];
6987 char buf_b[BUFSIZ];
6988 char buf_c[BUFSIZ];
6989 if (attr->mp_nexthop_len
6990 == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
6991 if (json)
6992 json_object_string_add(
6993 json_out, "mpNexthopGlobalIn",
6994 inet_ntop(
6995 AF_INET6,
6996 &attr->mp_nexthop_global,
6997 buf_a, BUFSIZ));
6998 else
6999 vty_out(vty, "%s",
7000 inet_ntop(
7001 AF_INET6,
7002 &attr->mp_nexthop_global,
7003 buf_a, BUFSIZ));
7004 } else if (attr->mp_nexthop_len
7005 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7006 if (json) {
7007 inet_ntop(AF_INET6,
7008 &attr->mp_nexthop_global,
7009 buf_a, BUFSIZ);
7010 inet_ntop(AF_INET6,
7011 &attr->mp_nexthop_local,
7012 buf_b, BUFSIZ);
7013 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
7014 json_object_string_add(
7015 json_out,
7016 "mpNexthopGlobalLocal", buf_c);
7017 } else
7018 vty_out(vty, "%s(%s)",
7019 inet_ntop(
7020 AF_INET6,
7021 &attr->mp_nexthop_global,
7022 buf_a, BUFSIZ),
7023 inet_ntop(
7024 AF_INET6,
7025 &attr->mp_nexthop_local,
7026 buf_b, BUFSIZ));
7027 }
7028 }
7029 }
7030
7031 label = decode_label(&binfo->extra->label);
7032
7033 if (bgp_is_valid_label(&label)) {
7034 if (json) {
7035 json_object_int_add(json_out, "notag", label);
7036 json_object_array_add(json, json_out);
7037 } else {
7038 vty_out(vty, "notag/%d", label);
7039 vty_out(vty, "\n");
7040 }
7041 }
7042}
718e3744 7043
d62a17ae 7044void route_vty_out_overlay(struct vty *vty, struct prefix *p,
7045 struct bgp_info *binfo, int display,
7046 json_object *json_paths)
718e3744 7047{
d62a17ae 7048 struct attr *attr;
7049 char buf[BUFSIZ];
7050 json_object *json_path = NULL;
784d3a42 7051
d62a17ae 7052 if (json_paths)
7053 json_path = json_object_new_object();
856ca177 7054
d62a17ae 7055 if (!binfo->extra)
7056 return;
718e3744 7057
d62a17ae 7058 /* short status lead text */
7059 route_vty_short_status_out(vty, binfo, json_path);
856ca177 7060
d62a17ae 7061 /* print prefix and mask */
7062 if (!display)
9c92b5f7 7063 route_vty_out_route(p, vty, NULL);
d62a17ae 7064 else
7065 vty_out(vty, "%*s", 17, " ");
7066
7067 /* Print attribute */
7068 attr = binfo->attr;
7069 if (attr) {
7070 char buf1[BUFSIZ];
7071 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7072
7073 switch (af) {
7074 case AF_INET:
7075 vty_out(vty, "%-16s",
7076 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7077 BUFSIZ));
7078 break;
7079 case AF_INET6:
7080 vty_out(vty, "%s(%s)",
7081 inet_ntop(af, &attr->mp_nexthop_global, buf,
7082 BUFSIZ),
7083 inet_ntop(af, &attr->mp_nexthop_local, buf1,
7084 BUFSIZ));
7085 break;
7086 default:
7087 vty_out(vty, "?");
7088 }
718e3744 7089 }
718e3744 7090
d62a17ae 7091 struct eth_segment_id *id = &(attr->evpn_overlay.eth_s_id);
7092 char *str = esi2str(id);
7093 vty_out(vty, "%s", str);
7094 XFREE(MTYPE_TMP, str);
7095 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) {
7096 vty_out(vty, "/%s", inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
7097 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) {
7098 vty_out(vty, "/%s",
7099 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6),
7100 buf, BUFSIZ));
7101 }
7102 if (attr->ecommunity) {
7103 char *mac = NULL;
7104 struct ecommunity_val *routermac = ecommunity_lookup(
7105 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
7106 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
7107 if (routermac)
7108 mac = ecom_mac2str((char *)routermac->val);
7109 if (mac) {
7110 vty_out(vty, "/%s", (char *)mac);
7111 XFREE(MTYPE_TMP, mac);
7112 }
7113 }
7114 vty_out(vty, "\n");
7115}
718e3744 7116
d62a17ae 7117/* dampening route */
7118static void damp_route_vty_out(struct vty *vty, struct prefix *p,
7119 struct bgp_info *binfo, int display, safi_t safi,
7120 u_char use_json, json_object *json)
7121{
7122 struct attr *attr;
7123 int len;
7124 char timebuf[BGP_UPTIME_LEN];
7125
7126 /* short status lead text */
7127 route_vty_short_status_out(vty, binfo, json);
7128
7129 /* print prefix and mask */
7130 if (!use_json) {
7131 if (!display)
9c92b5f7 7132 route_vty_out_route(p, vty, NULL);
d62a17ae 7133 else
7134 vty_out(vty, "%*s", 17, " ");
7135 }
7136
7137 len = vty_out(vty, "%s", binfo->peer->host);
7138 len = 17 - len;
7139 if (len < 1) {
7140 if (!use_json)
7141 vty_out(vty, "\n%*s", 34, " ");
7142 } else {
7143 if (use_json)
7144 json_object_int_add(json, "peerHost", len);
7145 else
7146 vty_out(vty, "%*s", len, " ");
7147 }
7148
7149 if (use_json)
7150 bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN,
7151 use_json, json);
7152 else
9d303b37
DL
7153 vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7154 BGP_UPTIME_LEN,
7155 use_json, json));
d62a17ae 7156
7157 /* Print attribute */
7158 attr = binfo->attr;
7159 if (attr) {
7160 /* Print aspath */
7161 if (attr->aspath) {
7162 if (use_json)
7163 json_object_string_add(json, "asPath",
7164 attr->aspath->str);
7165 else
7166 aspath_print_vty(vty, "%s", attr->aspath, " ");
7167 }
7168
7169 /* Print origin */
7170 if (use_json)
7171 json_object_string_add(json, "origin",
7172 bgp_origin_str[attr->origin]);
7173 else
7174 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7175 }
7176 if (!use_json)
7177 vty_out(vty, "\n");
7178}
718e3744 7179
d62a17ae 7180/* flap route */
7181static void flap_route_vty_out(struct vty *vty, struct prefix *p,
7182 struct bgp_info *binfo, int display, safi_t safi,
7183 u_char use_json, json_object *json)
784d3a42 7184{
d62a17ae 7185 struct attr *attr;
7186 struct bgp_damp_info *bdi;
7187 char timebuf[BGP_UPTIME_LEN];
7188 int len;
784d3a42 7189
d62a17ae 7190 if (!binfo->extra)
7191 return;
784d3a42 7192
d62a17ae 7193 bdi = binfo->extra->damp_info;
784d3a42 7194
d62a17ae 7195 /* short status lead text */
7196 route_vty_short_status_out(vty, binfo, json);
784d3a42 7197
d62a17ae 7198 /* print prefix and mask */
7199 if (!use_json) {
7200 if (!display)
9c92b5f7 7201 route_vty_out_route(p, vty, NULL);
d62a17ae 7202 else
7203 vty_out(vty, "%*s", 17, " ");
7204 }
784d3a42 7205
d62a17ae 7206 len = vty_out(vty, "%s", binfo->peer->host);
7207 len = 16 - len;
7208 if (len < 1) {
7209 if (!use_json)
7210 vty_out(vty, "\n%*s", 33, " ");
7211 } else {
7212 if (use_json)
7213 json_object_int_add(json, "peerHost", len);
7214 else
7215 vty_out(vty, "%*s", len, " ");
7216 }
784d3a42 7217
d62a17ae 7218 len = vty_out(vty, "%d", bdi->flap);
7219 len = 5 - len;
7220 if (len < 1) {
7221 if (!use_json)
7222 vty_out(vty, " ");
7223 } else {
7224 if (use_json)
7225 json_object_int_add(json, "bdiFlap", len);
7226 else
7227 vty_out(vty, "%*s", len, " ");
7228 }
7229
7230 if (use_json)
7231 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
7232 json);
7233 else
9d303b37
DL
7234 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
7235 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 7236
7237 if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
7238 && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7239 if (use_json)
7240 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7241 BGP_UPTIME_LEN, use_json, json);
7242 else
7243 vty_out(vty, "%s ",
7244 bgp_damp_reuse_time_vty(vty, binfo, timebuf,
7245 BGP_UPTIME_LEN,
7246 use_json, json));
7247 } else {
7248 if (!use_json)
7249 vty_out(vty, "%*s ", 8, " ");
7250 }
7251
7252 /* Print attribute */
7253 attr = binfo->attr;
7254 if (attr) {
7255 /* Print aspath */
7256 if (attr->aspath) {
7257 if (use_json)
7258 json_object_string_add(json, "asPath",
7259 attr->aspath->str);
7260 else
7261 aspath_print_vty(vty, "%s", attr->aspath, " ");
7262 }
7263
7264 /* Print origin */
7265 if (use_json)
7266 json_object_string_add(json, "origin",
7267 bgp_origin_str[attr->origin]);
7268 else
7269 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
7270 }
7271 if (!use_json)
7272 vty_out(vty, "\n");
7273}
7274
7275static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
7276 int *first, const char *header,
7277 json_object *json_adv_to)
7278{
7279 char buf1[INET6_ADDRSTRLEN];
7280 json_object *json_peer = NULL;
7281
7282 if (json_adv_to) {
7283 /* 'advertised-to' is a dictionary of peers we have advertised
7284 * this
7285 * prefix too. The key is the peer's IP or swpX, the value is
7286 * the
7287 * hostname if we know it and "" if not.
7288 */
7289 json_peer = json_object_new_object();
7290
7291 if (peer->hostname)
7292 json_object_string_add(json_peer, "hostname",
7293 peer->hostname);
7294
7295 if (peer->conf_if)
7296 json_object_object_add(json_adv_to, peer->conf_if,
7297 json_peer);
7298 else
7299 json_object_object_add(
7300 json_adv_to,
7301 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
7302 json_peer);
7303 } else {
7304 if (*first) {
7305 vty_out(vty, "%s", header);
7306 *first = 0;
7307 }
7308
7309 if (peer->hostname
7310 && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
7311 if (peer->conf_if)
7312 vty_out(vty, " %s(%s)", peer->hostname,
7313 peer->conf_if);
7314 else
7315 vty_out(vty, " %s(%s)", peer->hostname,
7316 sockunion2str(&peer->su, buf1,
7317 SU_ADDRSTRLEN));
7318 } else {
7319 if (peer->conf_if)
7320 vty_out(vty, " %s", peer->conf_if);
7321 else
7322 vty_out(vty, " %s",
7323 sockunion2str(&peer->su, buf1,
7324 SU_ADDRSTRLEN));
7325 }
7326 }
784d3a42
PG
7327}
7328
d62a17ae 7329void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
7330 struct bgp_info *binfo, afi_t afi, safi_t safi,
7331 json_object *json_paths)
7332{
7333 char buf[INET6_ADDRSTRLEN];
7334 char buf1[BUFSIZ];
7335#if defined(HAVE_CUMULUS)
7336 char buf2[EVPN_ROUTE_STRLEN];
7337#endif
7338 struct attr *attr;
7339 int sockunion_vty_out(struct vty *, union sockunion *);
7340 time_t tbuf;
7341 json_object *json_bestpath = NULL;
7342 json_object *json_cluster_list = NULL;
7343 json_object *json_cluster_list_list = NULL;
7344 json_object *json_ext_community = NULL;
b96879c0 7345 json_object *json_lcommunity = NULL;
d62a17ae 7346 json_object *json_last_update = NULL;
7347 json_object *json_nexthop_global = NULL;
7348 json_object *json_nexthop_ll = NULL;
7349 json_object *json_nexthops = NULL;
7350 json_object *json_path = NULL;
7351 json_object *json_peer = NULL;
7352 json_object *json_string = NULL;
7353 json_object *json_adv_to = NULL;
7354 int first = 0;
7355 struct listnode *node, *nnode;
7356 struct peer *peer;
7357 int addpath_capable;
7358 int has_adj;
7359 unsigned int first_as;
7360
7361 if (json_paths) {
7362 json_path = json_object_new_object();
7363 json_peer = json_object_new_object();
7364 json_nexthop_global = json_object_new_object();
7365 }
7366
7367#if defined(HAVE_CUMULUS)
7368 if (!json_paths && safi == SAFI_EVPN) {
7369 char tag_buf[20];
7370
7371 bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2));
7372 vty_out(vty, " Route %s", buf2);
7373 tag_buf[0] = '\0';
7374 if (binfo->extra) {
7375 bgp_evpn_label2str(&binfo->extra->label, tag_buf,
7376 sizeof(tag_buf));
7377 vty_out(vty, " VNI %s", tag_buf);
7378 }
7379 vty_out(vty, "\n");
7380 if (binfo->extra && binfo->extra->parent) {
7381 struct bgp_info *parent_ri;
7382 struct bgp_node *rn, *prn;
7383
7384 parent_ri = (struct bgp_info *)binfo->extra->parent;
7385 rn = parent_ri->net;
7386 if (rn && rn->prn) {
7387 prn = rn->prn;
7388 vty_out(vty, " Imported from %s:%s\n",
7389 prefix_rd2str(
7390 (struct prefix_rd *)&prn->p,
06b9f471 7391 buf1, sizeof(buf1)),
d62a17ae 7392 buf2);
7393 }
7394 }
7395 }
7396#endif
7397
7398 attr = binfo->attr;
7399
7400 if (attr) {
7401 /* Line1 display AS-path, Aggregator */
7402 if (attr->aspath) {
7403 if (json_paths) {
68e1a55b
DS
7404 if (!attr->aspath->json)
7405 aspath_str_update(attr->aspath, true);
d62a17ae 7406 json_object_lock(attr->aspath->json);
7407 json_object_object_add(json_path, "aspath",
7408 attr->aspath->json);
7409 } else {
7410 if (attr->aspath->segments)
7411 aspath_print_vty(vty, " %s",
7412 attr->aspath, "");
7413 else
7414 vty_out(vty, " Local");
7415 }
7416 }
7417
7418 if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) {
7419 if (json_paths)
7420 json_object_boolean_true_add(json_path,
7421 "removed");
7422 else
7423 vty_out(vty, ", (removed)");
7424 }
7425
7426 if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) {
7427 if (json_paths)
7428 json_object_boolean_true_add(json_path,
7429 "stale");
7430 else
7431 vty_out(vty, ", (stale)");
7432 }
7433
7434 if (CHECK_FLAG(attr->flag,
7435 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
7436 if (json_paths) {
7437 json_object_int_add(json_path, "aggregatorAs",
7438 attr->aggregator_as);
7439 json_object_string_add(
7440 json_path, "aggregatorId",
7441 inet_ntoa(attr->aggregator_addr));
7442 } else {
7443 vty_out(vty, ", (aggregated by %u %s)",
7444 attr->aggregator_as,
7445 inet_ntoa(attr->aggregator_addr));
7446 }
7447 }
7448
7449 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7450 PEER_FLAG_REFLECTOR_CLIENT)) {
7451 if (json_paths)
7452 json_object_boolean_true_add(
7453 json_path, "rxedFromRrClient");
7454 else
7455 vty_out(vty, ", (Received from a RR-client)");
7456 }
7457
7458 if (CHECK_FLAG(binfo->peer->af_flags[afi][safi],
7459 PEER_FLAG_RSERVER_CLIENT)) {
7460 if (json_paths)
7461 json_object_boolean_true_add(
7462 json_path, "rxedFromRsClient");
7463 else
7464 vty_out(vty, ", (Received from a RS-client)");
7465 }
7466
7467 if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7468 if (json_paths)
7469 json_object_boolean_true_add(
7470 json_path, "dampeningHistoryEntry");
7471 else
7472 vty_out(vty, ", (history entry)");
7473 } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
7474 if (json_paths)
7475 json_object_boolean_true_add(
7476 json_path, "dampeningSuppressed");
7477 else
7478 vty_out(vty, ", (suppressed due to dampening)");
7479 }
7480
7481 if (!json_paths)
7482 vty_out(vty, "\n");
7483
7484 /* Line2 display Next-hop, Neighbor, Router-id */
7485 /* Display the nexthop */
b03b8898
DS
7486 if ((p->family == AF_INET || p->family == AF_ETHERNET ||
7487 p->family == AF_EVPN)
d62a17ae 7488 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7489 || safi == SAFI_EVPN
7490 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7491 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
7492 || safi == SAFI_EVPN) {
7493 if (json_paths)
7494 json_object_string_add(
7495 json_nexthop_global, "ip",
7496 inet_ntoa(
7497 attr->mp_nexthop_global_in));
7498 else
7499 vty_out(vty, " %s",
7500 inet_ntoa(
7501 attr->mp_nexthop_global_in));
7502 } else {
7503 if (json_paths)
7504 json_object_string_add(
7505 json_nexthop_global, "ip",
7506 inet_ntoa(attr->nexthop));
7507 else
7508 vty_out(vty, " %s",
7509 inet_ntoa(attr->nexthop));
7510 }
7511
7512 if (json_paths)
7513 json_object_string_add(json_nexthop_global,
7514 "afi", "ipv4");
7515 } else {
7516 if (json_paths) {
7517 json_object_string_add(
7518 json_nexthop_global, "ip",
7519 inet_ntop(AF_INET6,
7520 &attr->mp_nexthop_global, buf,
7521 INET6_ADDRSTRLEN));
7522 json_object_string_add(json_nexthop_global,
7523 "afi", "ipv6");
7524 json_object_string_add(json_nexthop_global,
7525 "scope", "global");
7526 } else {
7527 vty_out(vty, " %s",
7528 inet_ntop(AF_INET6,
7529 &attr->mp_nexthop_global, buf,
7530 INET6_ADDRSTRLEN));
7531 }
7532 }
7533
7534 /* Display the IGP cost or 'inaccessible' */
7535 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7536 if (json_paths)
7537 json_object_boolean_false_add(
7538 json_nexthop_global, "accessible");
7539 else
7540 vty_out(vty, " (inaccessible)");
7541 } else {
7542 if (binfo->extra && binfo->extra->igpmetric) {
7543 if (json_paths)
7544 json_object_int_add(
7545 json_nexthop_global, "metric",
7546 binfo->extra->igpmetric);
7547 else
7548 vty_out(vty, " (metric %u)",
7549 binfo->extra->igpmetric);
7550 }
7551
7552 /* IGP cost is 0, display this only for json */
7553 else {
7554 if (json_paths)
7555 json_object_int_add(json_nexthop_global,
7556 "metric", 0);
7557 }
7558
7559 if (json_paths)
7560 json_object_boolean_true_add(
7561 json_nexthop_global, "accessible");
7562 }
7563
7564 /* Display peer "from" output */
7565 /* This path was originated locally */
7566 if (binfo->peer == bgp->peer_self) {
7567
7568 if (safi == SAFI_EVPN
7569 || (p->family == AF_INET
7570 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
7571 if (json_paths)
7572 json_object_string_add(
7573 json_peer, "peerId", "0.0.0.0");
7574 else
7575 vty_out(vty, " from 0.0.0.0 ");
7576 } else {
7577 if (json_paths)
7578 json_object_string_add(json_peer,
7579 "peerId", "::");
7580 else
7581 vty_out(vty, " from :: ");
7582 }
7583
7584 if (json_paths)
7585 json_object_string_add(
7586 json_peer, "routerId",
7587 inet_ntoa(bgp->router_id));
7588 else
7589 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
7590 }
7591
7592 /* We RXed this path from one of our peers */
7593 else {
7594
7595 if (json_paths) {
7596 json_object_string_add(
7597 json_peer, "peerId",
7598 sockunion2str(&binfo->peer->su, buf,
7599 SU_ADDRSTRLEN));
7600 json_object_string_add(
7601 json_peer, "routerId",
7602 inet_ntop(AF_INET,
7603 &binfo->peer->remote_id, buf1,
06b9f471 7604 sizeof(buf1)));
d62a17ae 7605
7606 if (binfo->peer->hostname)
7607 json_object_string_add(
7608 json_peer, "hostname",
7609 binfo->peer->hostname);
7610
7611 if (binfo->peer->domainname)
7612 json_object_string_add(
7613 json_peer, "domainname",
7614 binfo->peer->domainname);
7615
7616 if (binfo->peer->conf_if)
7617 json_object_string_add(
7618 json_peer, "interface",
7619 binfo->peer->conf_if);
7620 } else {
7621 if (binfo->peer->conf_if) {
7622 if (binfo->peer->hostname
7623 && bgp_flag_check(
7624 binfo->peer->bgp,
7625 BGP_FLAG_SHOW_HOSTNAME))
7626 vty_out(vty, " from %s(%s)",
7627 binfo->peer->hostname,
7628 binfo->peer->conf_if);
7629 else
7630 vty_out(vty, " from %s",
7631 binfo->peer->conf_if);
7632 } else {
7633 if (binfo->peer->hostname
7634 && bgp_flag_check(
7635 binfo->peer->bgp,
7636 BGP_FLAG_SHOW_HOSTNAME))
7637 vty_out(vty, " from %s(%s)",
7638 binfo->peer->hostname,
7639 binfo->peer->host);
7640 else
7641 vty_out(vty, " from %s",
7642 sockunion2str(
7643 &binfo->peer
7644 ->su,
7645 buf,
7646 SU_ADDRSTRLEN));
7647 }
7648
7649 if (attr->flag
7650 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7651 vty_out(vty, " (%s)",
7652 inet_ntoa(attr->originator_id));
7653 else
7654 vty_out(vty, " (%s)",
7655 inet_ntop(
7656 AF_INET,
7657 &binfo->peer->remote_id,
06b9f471 7658 buf1, sizeof(buf1)));
d62a17ae 7659 }
7660 }
7661
7662 if (!json_paths)
7663 vty_out(vty, "\n");
7664
7665 /* display the link-local nexthop */
7666 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
7667 if (json_paths) {
7668 json_nexthop_ll = json_object_new_object();
7669 json_object_string_add(
7670 json_nexthop_ll, "ip",
7671 inet_ntop(AF_INET6,
7672 &attr->mp_nexthop_local, buf,
7673 INET6_ADDRSTRLEN));
7674 json_object_string_add(json_nexthop_ll, "afi",
7675 "ipv6");
7676 json_object_string_add(json_nexthop_ll, "scope",
7677 "link-local");
7678
7679 json_object_boolean_true_add(json_nexthop_ll,
7680 "accessible");
7681
7682 if (!attr->mp_nexthop_prefer_global)
7683 json_object_boolean_true_add(
7684 json_nexthop_ll, "used");
7685 else
7686 json_object_boolean_true_add(
7687 json_nexthop_global, "used");
7688 } else {
7689 vty_out(vty, " (%s) %s\n",
7690 inet_ntop(AF_INET6,
7691 &attr->mp_nexthop_local, buf,
7692 INET6_ADDRSTRLEN),
7693 attr->mp_nexthop_prefer_global
7694 ? "(prefer-global)"
7695 : "(used)");
7696 }
7697 }
7698 /* If we do not have a link-local nexthop then we must flag the
7699 global as "used" */
7700 else {
7701 if (json_paths)
7702 json_object_boolean_true_add(
7703 json_nexthop_global, "used");
7704 }
718e3744 7705
d62a17ae 7706 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7707 * Int/Ext/Local, Atomic, best */
7708 if (json_paths)
7709 json_object_string_add(
7710 json_path, "origin",
7711 bgp_origin_long_str[attr->origin]);
7712 else
7713 vty_out(vty, " Origin %s",
7714 bgp_origin_long_str[attr->origin]);
7715
7716 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
7717 if (json_paths)
7718 json_object_int_add(json_path, "med",
7719 attr->med);
7720 else
7721 vty_out(vty, ", metric %u", attr->med);
7722 }
718e3744 7723
d62a17ae 7724 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
7725 if (json_paths)
7726 json_object_int_add(json_path, "localpref",
7727 attr->local_pref);
7728 else
7729 vty_out(vty, ", localpref %u",
7730 attr->local_pref);
7731 } else {
7732 if (json_paths)
7733 json_object_int_add(json_path, "localpref",
7734 bgp->default_local_pref);
7735 else
7736 vty_out(vty, ", localpref %u",
7737 bgp->default_local_pref);
7738 }
718e3744 7739
d62a17ae 7740 if (attr->weight != 0) {
7741 if (json_paths)
7742 json_object_int_add(json_path, "weight",
7743 attr->weight);
7744 else
7745 vty_out(vty, ", weight %u", attr->weight);
7746 }
718e3744 7747
d62a17ae 7748 if (attr->tag != 0) {
7749 if (json_paths)
7750 json_object_int_add(json_path, "tag",
7751 attr->tag);
7752 else
7753 vty_out(vty, ", tag %" ROUTE_TAG_PRI,
7754 attr->tag);
7755 }
718e3744 7756
d62a17ae 7757 if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) {
7758 if (json_paths)
7759 json_object_boolean_false_add(json_path,
7760 "valid");
7761 else
7762 vty_out(vty, ", invalid");
7763 } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
7764 if (json_paths)
7765 json_object_boolean_true_add(json_path,
7766 "valid");
7767 else
7768 vty_out(vty, ", valid");
7769 }
718e3744 7770
d62a17ae 7771 if (binfo->peer != bgp->peer_self) {
7772 if (binfo->peer->as == binfo->peer->local_as) {
7773 if (CHECK_FLAG(bgp->config,
7774 BGP_CONFIG_CONFEDERATION)) {
7775 if (json_paths)
7776 json_object_string_add(
7777 json_peer, "type",
7778 "confed-internal");
7779 else
7780 vty_out(vty,
7781 ", confed-internal");
7782 } else {
7783 if (json_paths)
7784 json_object_string_add(
7785 json_peer, "type",
7786 "internal");
7787 else
7788 vty_out(vty, ", internal");
7789 }
7790 } else {
7791 if (bgp_confederation_peers_check(
7792 bgp, binfo->peer->as)) {
7793 if (json_paths)
7794 json_object_string_add(
7795 json_peer, "type",
7796 "confed-external");
7797 else
7798 vty_out(vty,
7799 ", confed-external");
7800 } else {
7801 if (json_paths)
7802 json_object_string_add(
7803 json_peer, "type",
7804 "external");
7805 else
7806 vty_out(vty, ", external");
7807 }
7808 }
7809 } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) {
7810 if (json_paths) {
7811 json_object_boolean_true_add(json_path,
7812 "aggregated");
7813 json_object_boolean_true_add(json_path,
7814 "local");
7815 } else {
7816 vty_out(vty, ", aggregated, local");
7817 }
7818 } else if (binfo->type != ZEBRA_ROUTE_BGP) {
7819 if (json_paths)
7820 json_object_boolean_true_add(json_path,
7821 "sourced");
7822 else
7823 vty_out(vty, ", sourced");
7824 } else {
7825 if (json_paths) {
7826 json_object_boolean_true_add(json_path,
7827 "sourced");
7828 json_object_boolean_true_add(json_path,
7829 "local");
7830 } else {
7831 vty_out(vty, ", sourced, local");
7832 }
7833 }
718e3744 7834
d62a17ae 7835 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
7836 if (json_paths)
7837 json_object_boolean_true_add(json_path,
7838 "atomicAggregate");
7839 else
7840 vty_out(vty, ", atomic-aggregate");
7841 }
718e3744 7842
d62a17ae 7843 if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)
7844 || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)
7845 && bgp_info_mpath_count(binfo))) {
7846 if (json_paths)
7847 json_object_boolean_true_add(json_path,
7848 "multipath");
7849 else
7850 vty_out(vty, ", multipath");
7851 }
856ca177 7852
d62a17ae 7853 // Mark the bestpath(s)
7854 if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) {
7855 first_as = aspath_get_first_as(attr->aspath);
7856
7857 if (json_paths) {
7858 if (!json_bestpath)
7859 json_bestpath =
7860 json_object_new_object();
7861 json_object_int_add(json_bestpath,
7862 "bestpathFromAs", first_as);
7863 } else {
7864 if (first_as)
fb2b0934 7865 vty_out(vty, ", bestpath-from-AS %u",
d62a17ae 7866 first_as);
7867 else
7868 vty_out(vty,
7869 ", bestpath-from-AS Local");
7870 }
7871 }
718e3744 7872
d62a17ae 7873 if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) {
7874 if (json_paths) {
7875 if (!json_bestpath)
7876 json_bestpath =
7877 json_object_new_object();
7878 json_object_boolean_true_add(json_bestpath,
7879 "overall");
7880 } else
7881 vty_out(vty, ", best");
7882 }
718e3744 7883
d62a17ae 7884 if (json_bestpath)
7885 json_object_object_add(json_path, "bestpath",
7886 json_bestpath);
7887
7888 if (!json_paths)
7889 vty_out(vty, "\n");
7890
7891 /* Line 4 display Community */
7892 if (attr->community) {
7893 if (json_paths) {
a69ea8ae
DS
7894 if (!attr->community->json)
7895 community_str(attr->community,
7896 true);
d62a17ae 7897 json_object_lock(attr->community->json);
7898 json_object_object_add(json_path, "community",
7899 attr->community->json);
7900 } else {
7901 vty_out(vty, " Community: %s\n",
7902 attr->community->str);
7903 }
7904 }
718e3744 7905
d62a17ae 7906 /* Line 5 display Extended-community */
7907 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
7908 if (json_paths) {
7909 json_ext_community = json_object_new_object();
7910 json_object_string_add(json_ext_community,
7911 "string",
7912 attr->ecommunity->str);
7913 json_object_object_add(json_path,
7914 "extendedCommunity",
7915 json_ext_community);
7916 } else {
7917 vty_out(vty, " Extended Community: %s\n",
7918 attr->ecommunity->str);
7919 }
7920 }
adbac85e 7921
d62a17ae 7922 /* Line 6 display Large community */
b96879c0
DS
7923 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
7924 if (json_paths) {
7925 json_lcommunity = json_object_new_object();
7926 json_object_string_add(json_lcommunity,
7927 "string",
7928 attr->lcommunity->str);
7929 json_object_object_add(json_path,
7930 "largeCommunity",
7931 json_lcommunity);
7932 } else {
7933 vty_out(vty, " Large Community: %s\n",
7934 attr->lcommunity->str);
7935 }
7936 }
d62a17ae 7937
7938 /* Line 7 display Originator, Cluster-id */
7939 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
7940 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
7941 if (attr->flag
7942 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
7943 if (json_paths)
7944 json_object_string_add(
7945 json_path, "originatorId",
7946 inet_ntoa(attr->originator_id));
7947 else
7948 vty_out(vty, " Originator: %s",
7949 inet_ntoa(attr->originator_id));
7950 }
7951
7952 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
7953 int i;
7954
7955 if (json_paths) {
7956 json_cluster_list =
7957 json_object_new_object();
7958 json_cluster_list_list =
7959 json_object_new_array();
7960
7961 for (i = 0;
7962 i < attr->cluster->length / 4;
7963 i++) {
7964 json_string = json_object_new_string(
7965 inet_ntoa(
7966 attr->cluster->list
7967 [i]));
7968 json_object_array_add(
7969 json_cluster_list_list,
7970 json_string);
7971 }
7972
7973 /* struct cluster_list does not have
7974 "str" variable like
7975 * aspath and community do. Add this
7976 someday if someone
7977 * asks for it.
7978 json_object_string_add(json_cluster_list,
7979 "string", attr->cluster->str);
7980 */
7981 json_object_object_add(
7982 json_cluster_list, "list",
7983 json_cluster_list_list);
7984 json_object_object_add(
7985 json_path, "clusterList",
7986 json_cluster_list);
7987 } else {
7988 vty_out(vty, ", Cluster list: ");
7989
7990 for (i = 0;
7991 i < attr->cluster->length / 4;
7992 i++) {
7993 vty_out(vty, "%s ",
7994 inet_ntoa(
7995 attr->cluster->list
7996 [i]));
7997 }
7998 }
7999 }
8000
8001 if (!json_paths)
8002 vty_out(vty, "\n");
8003 }
adbac85e 8004
d62a17ae 8005 if (binfo->extra && binfo->extra->damp_info)
8006 bgp_damp_info_vty(vty, binfo, json_path);
8007
8008/* Remote Label */
8c197128 8009#if defined(HAVE_CUMULUS)
d62a17ae 8010 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label)
8011 && safi != SAFI_EVPN)
8012#else
8013 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label))
8c197128 8014#endif
d62a17ae 8015 {
8016 mpls_label_t label = label_pton(&binfo->extra->label);
8017 if (json_paths)
8018 json_object_int_add(json_path, "remoteLabel",
8019 label);
8020 else
8021 vty_out(vty, " Remote label: %d\n", label);
8022 }
b05a1c8b 8023
d62a17ae 8024 /* Label Index */
8025 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
8026 if (json_paths)
8027 json_object_int_add(json_path, "labelIndex",
8028 attr->label_index);
8029 else
8030 vty_out(vty, " Label Index: %d\n",
8031 attr->label_index);
8032 }
520d5d76 8033
d62a17ae 8034 /* Line 8 display Addpath IDs */
8035 if (binfo->addpath_rx_id || binfo->addpath_tx_id) {
8036 if (json_paths) {
8037 json_object_int_add(json_path, "addpathRxId",
8038 binfo->addpath_rx_id);
8039 json_object_int_add(json_path, "addpathTxId",
8040 binfo->addpath_tx_id);
8041 } else {
8042 vty_out(vty, " AddPath ID: RX %u, TX %u\n",
8043 binfo->addpath_rx_id,
8044 binfo->addpath_tx_id);
8045 }
8046 }
718e3744 8047
d62a17ae 8048 /* If we used addpath to TX a non-bestpath we need to display
8049 * "Advertised to" on a path-by-path basis */
8050 if (bgp->addpath_tx_used[afi][safi]) {
8051 first = 1;
8052
8053 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
8054 addpath_capable =
8055 bgp_addpath_encode_tx(peer, afi, safi);
8056 has_adj = bgp_adj_out_lookup(
8057 peer, binfo->net, binfo->addpath_tx_id);
8058
8059 if ((addpath_capable && has_adj)
8060 || (!addpath_capable && has_adj
8061 && CHECK_FLAG(binfo->flags,
8062 BGP_INFO_SELECTED))) {
8063 if (json_path && !json_adv_to)
8064 json_adv_to =
8065 json_object_new_object();
8066
8067 route_vty_out_advertised_to(
8068 vty, peer, &first,
8069 " Advertised to:",
8070 json_adv_to);
8071 }
8072 }
8073
8074 if (json_path) {
8075 if (json_adv_to) {
8076 json_object_object_add(json_path,
8077 "advertisedTo",
8078 json_adv_to);
8079 }
8080 } else {
8081 if (!first) {
8082 vty_out(vty, "\n");
8083 }
8084 }
8085 }
b05a1c8b 8086
d62a17ae 8087 /* Line 9 display Uptime */
8088 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
8089 if (json_paths) {
8090 json_last_update = json_object_new_object();
8091 json_object_int_add(json_last_update, "epoch", tbuf);
8092 json_object_string_add(json_last_update, "string",
8093 ctime(&tbuf));
8094 json_object_object_add(json_path, "lastUpdate",
8095 json_last_update);
8096 } else
8097 vty_out(vty, " Last update: %s", ctime(&tbuf));
8098 }
f1aa5d8a 8099
d62a17ae 8100 /* We've constructed the json object for this path, add it to the json
8101 * array of paths
8102 */
8103 if (json_paths) {
8104 if (json_nexthop_global || json_nexthop_ll) {
8105 json_nexthops = json_object_new_array();
f1aa5d8a 8106
d62a17ae 8107 if (json_nexthop_global)
8108 json_object_array_add(json_nexthops,
8109 json_nexthop_global);
f1aa5d8a 8110
d62a17ae 8111 if (json_nexthop_ll)
8112 json_object_array_add(json_nexthops,
8113 json_nexthop_ll);
f1aa5d8a 8114
d62a17ae 8115 json_object_object_add(json_path, "nexthops",
8116 json_nexthops);
8117 }
8118
8119 json_object_object_add(json_path, "peer", json_peer);
8120 json_object_array_add(json_paths, json_path);
8121 } else
8122 vty_out(vty, "\n");
b366b518
BB
8123}
8124
96ade3ed 8125#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
8126#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8127#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 8128
d62a17ae 8129static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
8130 const char *prefix_list_str, afi_t afi,
8131 safi_t safi, enum bgp_show_type type);
8132static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
8133 const char *filter, afi_t afi, safi_t safi,
8134 enum bgp_show_type type);
8135static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
8136 const char *rmap_str, afi_t afi, safi_t safi,
8137 enum bgp_show_type type);
8138static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
8139 const char *com, int exact, afi_t afi,
8140 safi_t safi);
8141static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
8142 const char *prefix, afi_t afi, safi_t safi,
8143 enum bgp_show_type type);
e889891d
DW
8144static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
8145 const char *regstr, afi_t afi,
d62a17ae 8146 safi_t safi, enum bgp_show_type type);
7f323236
DW
8147static int bgp_show_community(struct vty *vty, struct bgp *bgp,
8148 const char *comstr, int exact, afi_t afi,
d62a17ae 8149 safi_t safi);
8150
1ae44dfc
LB
8151
8152static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 8153 struct bgp_table *table, enum bgp_show_type type,
1ae44dfc
LB
8154 void *output_arg, u_char use_json,
8155 char *rd, int is_last,
8156 unsigned long *output_cum, unsigned long *total_cum)
d62a17ae 8157{
8158 struct bgp_info *ri;
8159 struct bgp_node *rn;
8160 int header = 1;
8161 int display;
1ae44dfc
LB
8162 unsigned long output_count = 0;
8163 unsigned long total_count = 0;
d62a17ae 8164 struct prefix *p;
8165 char buf[BUFSIZ];
8166 char buf2[BUFSIZ];
8167 json_object *json_paths = NULL;
8168 int first = 1;
8169
1ae44dfc
LB
8170 if (output_cum && *output_cum != 0)
8171 header = 0;
8172
8173 if (use_json && header) {
d62a17ae 8174 vty_out(vty,
66f80d74
DS
8175 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8176 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
d62a17ae 8177 bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id,
8178 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
8179 : bgp->name,
8180 table->version, inet_ntoa(bgp->router_id));
445c2480
DS
8181 if (rd)
8182 vty_out(vty, " \"routeDistinguishers\" : {");
d62a17ae 8183 json_paths = json_object_new_object();
8184 }
718e3744 8185
445c2480
DS
8186 if (use_json && rd) {
8187 vty_out(vty, " \"%s\" : { ", rd);
8188 }
8189
d62a17ae 8190 /* Start processing of routes. */
98ce9a06
DS
8191 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
8192 if (rn->info == NULL)
8193 continue;
d62a17ae 8194
98ce9a06 8195 display = 0;
98ce9a06
DS
8196 if (use_json)
8197 json_paths = json_object_new_array();
8198 else
8199 json_paths = NULL;
d62a17ae 8200
98ce9a06
DS
8201 for (ri = rn->info; ri; ri = ri->next) {
8202 total_count++;
8203 if (type == bgp_show_type_flap_statistics
8204 || type == bgp_show_type_flap_neighbor
8205 || type == bgp_show_type_dampend_paths
8206 || type == bgp_show_type_damp_neighbor) {
8207 if (!(ri->extra
8208 && ri->extra->damp_info))
8209 continue;
8210 }
8211 if (type == bgp_show_type_regexp) {
8212 regex_t *regex = output_arg;
d62a17ae 8213
98ce9a06
DS
8214 if (bgp_regexec(regex, ri->attr->aspath)
8215 == REG_NOMATCH)
8216 continue;
8217 }
8218 if (type == bgp_show_type_prefix_list) {
8219 struct prefix_list *plist = output_arg;
d62a17ae 8220
98ce9a06
DS
8221 if (prefix_list_apply(plist, &rn->p)
8222 != PREFIX_PERMIT)
8223 continue;
8224 }
8225 if (type == bgp_show_type_filter_list) {
8226 struct as_list *as_list = output_arg;
d62a17ae 8227
98ce9a06
DS
8228 if (as_list_apply(as_list, ri->attr->aspath)
8229 != AS_FILTER_PERMIT)
8230 continue;
8231 }
8232 if (type == bgp_show_type_route_map) {
8233 struct route_map *rmap = output_arg;
8234 struct bgp_info binfo;
8235 struct attr dummy_attr;
8236 int ret;
d62a17ae 8237
98ce9a06 8238 bgp_attr_dup(&dummy_attr, ri->attr);
d62a17ae 8239
98ce9a06
DS
8240 binfo.peer = ri->peer;
8241 binfo.attr = &dummy_attr;
d62a17ae 8242
98ce9a06
DS
8243 ret = route_map_apply(rmap, &rn->p,
8244 RMAP_BGP, &binfo);
8245 if (ret == RMAP_DENYMATCH)
8246 continue;
8247 }
8248 if (type == bgp_show_type_neighbor
8249 || type == bgp_show_type_flap_neighbor
8250 || type == bgp_show_type_damp_neighbor) {
8251 union sockunion *su = output_arg;
8252
8253 if (ri->peer == NULL
8254 || ri->peer->su_remote == NULL
8255 || !sockunion_same(ri->peer->su_remote,
8256 su))
8257 continue;
8258 }
8259 if (type == bgp_show_type_cidr_only) {
8260 u_int32_t destination;
d62a17ae 8261
98ce9a06
DS
8262 destination = ntohl(rn->p.u.prefix4.s_addr);
8263 if (IN_CLASSC(destination)
8264 && rn->p.prefixlen == 24)
8265 continue;
8266 if (IN_CLASSB(destination)
8267 && rn->p.prefixlen == 16)
8268 continue;
8269 if (IN_CLASSA(destination)
8270 && rn->p.prefixlen == 8)
8271 continue;
8272 }
8273 if (type == bgp_show_type_prefix_longer) {
8274 struct prefix *p = output_arg;
d62a17ae 8275
98ce9a06
DS
8276 if (!prefix_match(p, &rn->p))
8277 continue;
8278 }
8279 if (type == bgp_show_type_community_all) {
8280 if (!ri->attr->community)
8281 continue;
8282 }
8283 if (type == bgp_show_type_community) {
8284 struct community *com = output_arg;
d62a17ae 8285
98ce9a06
DS
8286 if (!ri->attr->community
8287 || !community_match(ri->attr->community,
8288 com))
8289 continue;
8290 }
8291 if (type == bgp_show_type_community_exact) {
8292 struct community *com = output_arg;
d62a17ae 8293
98ce9a06
DS
8294 if (!ri->attr->community
8295 || !community_cmp(ri->attr->community,
8296 com))
8297 continue;
8298 }
8299 if (type == bgp_show_type_community_list) {
8300 struct community_list *list = output_arg;
d62a17ae 8301
98ce9a06
DS
8302 if (!community_list_match(
8303 ri->attr->community, list))
8304 continue;
8305 }
8306 if (type
8307 == bgp_show_type_community_list_exact) {
8308 struct community_list *list = output_arg;
d62a17ae 8309
98ce9a06
DS
8310 if (!community_list_exact_match(
8311 ri->attr->community, list))
8312 continue;
8313 }
8314 if (type == bgp_show_type_lcommunity) {
8315 struct lcommunity *lcom = output_arg;
d62a17ae 8316
98ce9a06
DS
8317 if (!ri->attr->lcommunity
8318 || !lcommunity_match(ri->attr->lcommunity,
8319 lcom))
8320 continue;
8321 }
8322 if (type == bgp_show_type_lcommunity_list) {
8323 struct community_list *list = output_arg;
d62a17ae 8324
98ce9a06
DS
8325 if (!lcommunity_list_match(
8326 ri->attr->lcommunity, list))
8327 continue;
8328 }
8329 if (type == bgp_show_type_lcommunity_all) {
8330 if (!ri->attr->lcommunity)
8331 continue;
8332 }
8333 if (type == bgp_show_type_dampend_paths
8334 || type == bgp_show_type_damp_neighbor) {
8335 if (!CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)
8336 || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
8337 continue;
8338 }
8339
8340 if (!use_json && header) {
8341 vty_out(vty,
8342 "BGP table version is %" PRIu64
8343 ", local router ID is %s\n",
8344 table->version,
8345 inet_ntoa(bgp->router_id));
8346 vty_out(vty, BGP_SHOW_SCODE_HEADER);
8347 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 8348 if (type == bgp_show_type_dampend_paths
8349 || type == bgp_show_type_damp_neighbor)
98ce9a06
DS
8350 vty_out(vty, BGP_SHOW_DAMP_HEADER);
8351 else if (
8352 type == bgp_show_type_flap_statistics
8353 || type == bgp_show_type_flap_neighbor)
8354 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 8355 else
98ce9a06
DS
8356 vty_out(vty, BGP_SHOW_HEADER);
8357 header = 0;
d62a17ae 8358 }
98ce9a06
DS
8359 if (rd != NULL && !display && !output_count) {
8360 if (!use_json)
8361 vty_out(vty,
8362 "Route Distinguisher: %s\n",
8363 rd);
d62a17ae 8364 }
98ce9a06
DS
8365 if (type == bgp_show_type_dampend_paths
8366 || type == bgp_show_type_damp_neighbor)
8367 damp_route_vty_out(vty, &rn->p, ri, display,
8368 safi, use_json,
8369 json_paths);
8370 else if (type == bgp_show_type_flap_statistics
8371 || type == bgp_show_type_flap_neighbor)
8372 flap_route_vty_out(vty, &rn->p, ri, display,
8373 safi, use_json,
8374 json_paths);
8375 else
8376 route_vty_out(vty, &rn->p, ri, display,
8377 safi, json_paths);
8378 display++;
d62a17ae 8379 }
8380
98ce9a06
DS
8381 if (display) {
8382 output_count++;
8383 if (!use_json)
8384 continue;
8385
8386 p = &rn->p;
8387 sprintf(buf2, "%s/%d",
8388 inet_ntop(p->family, &p->u.prefix,
8389 buf, BUFSIZ),
8390 p->prefixlen);
8cc84563
DS
8391 if (first)
8392 vty_out(vty, "\"%s\": ", buf2);
8393 else
8394 vty_out(vty, ",\"%s\": ", buf2);
8395
98ce9a06 8396 vty_out(vty, "%s",
66f80d74 8397 json_object_to_json_string_ext(json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06
DS
8398 json_object_free(json_paths);
8399 first = 0;
8400 }
8401 }
8402
1ae44dfc
LB
8403 if (output_cum) {
8404 output_count += *output_cum;
8405 *output_cum = output_count;
8406 }
8407 if (total_cum) {
8408 total_count += *total_cum;
8409 *total_cum = total_count;
8410 }
d62a17ae 8411 if (use_json) {
8412 json_object_free(json_paths);
1ae44dfc
LB
8413 if (is_last)
8414 vty_out(vty, " } }\n");
8415 else
8416 vty_out(vty, " }, ");
d62a17ae 8417 } else {
1ae44dfc
LB
8418 if (is_last) {
8419 /* No route is displayed */
8420 if (output_count == 0) {
8421 if (type == bgp_show_type_normal)
8422 vty_out(vty,
8423 "No BGP prefixes displayed, %ld exist\n",
8424 total_count);
8425 } else
d62a17ae 8426 vty_out(vty,
1ae44dfc
LB
8427 "\nDisplayed %ld routes and %ld total paths\n",
8428 output_count, total_count);
8429 }
d62a17ae 8430 }
718e3744 8431
d62a17ae 8432 return CMD_SUCCESS;
718e3744 8433}
8434
1ae44dfc
LB
8435int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
8436 struct bgp_table *table, struct prefix_rd *prd_match,
8437 enum bgp_show_type type, void *output_arg,
8438 u_char use_json)
8439{
8440 struct bgp_node *rn, *next;
8441 unsigned long output_cum = 0;
8442 unsigned long total_cum = 0;
8443
8444 for (rn = bgp_table_top(table); rn; rn = next) {
8445 next = bgp_route_next(rn);
8446 if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0)
8447 continue;
8448 if (rn->info != NULL) {
8449 struct prefix_rd prd;
06b9f471 8450 char rd[RD_ADDRSTRLEN];
1ae44dfc
LB
8451
8452 memcpy(&prd, &(rn->p), sizeof(struct prefix_rd));
06b9f471 8453 prefix_rd2str(&prd, rd, sizeof(rd));
1ae44dfc
LB
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;
06b9f471 8539 char buf1[RD_ADDRSTRLEN];
d62a17ae 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",
06b9f471 8573 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
d62a17ae 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,
06b9f471 8582 sizeof(buf1))
d62a17ae 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)
06b9f471
DS
8597 ? prefix_rd2str(prd, buf1, sizeof(buf1))
8598 : ""),
d62a17ae 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++;
f46d8e1e
DS
10247
10248 bgp_attr_undup(&attr,
10249 adj->attr);
a2addae8 10250 }
924c3f6a 10251 }
d62a17ae 10252 }
10253 }
10254 if (use_json)
10255 json_object_object_add(json, "advertisedRoutes", json_ar);
10256
10257 if (output_count != 0) {
10258 if (use_json)
10259 json_object_int_add(json, "totalPrefixCounter",
10260 output_count);
10261 else
10262 vty_out(vty, "\nTotal number of prefixes %ld\n",
10263 output_count);
10264 }
10265 if (use_json) {
66f80d74
DS
10266 vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
10267 JSON_C_TO_STRING_PRETTY));
d62a17ae 10268 json_object_free(json);
10269 }
a636c635 10270}
2a71e9ce 10271
d62a17ae 10272static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
10273 safi_t safi, int in, const char *rmap_name,
10274 u_char use_json)
0b16f239 10275{
d62a17ae 10276 json_object *json = NULL;
0b16f239 10277
d62a17ae 10278 if (use_json)
10279 json = json_object_new_object();
0b16f239 10280
d62a17ae 10281 /* labeled-unicast routes live in the unicast table */
10282 if (safi == SAFI_LABELED_UNICAST)
10283 safi = SAFI_UNICAST;
4dd6177e 10284
d62a17ae 10285 if (!peer || !peer->afc[afi][safi]) {
10286 if (use_json) {
10287 json_object_string_add(
10288 json, "warning",
10289 "No such neighbor or address family");
10290 vty_out(vty, "%s\n", json_object_to_json_string(json));
10291 json_object_free(json);
10292 } else
10293 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 10294
d62a17ae 10295 return CMD_WARNING;
10296 }
10297
10298 if (in
10299 && !CHECK_FLAG(peer->af_flags[afi][safi],
10300 PEER_FLAG_SOFT_RECONFIG)) {
10301 if (use_json) {
10302 json_object_string_add(
10303 json, "warning",
10304 "Inbound soft reconfiguration not enabled");
10305 vty_out(vty, "%s\n", json_object_to_json_string(json));
10306 json_object_free(json);
10307 } else
10308 vty_out(vty,
10309 "%% Inbound soft reconfiguration not enabled\n");
10310
10311 return CMD_WARNING;
10312 }
0b16f239 10313
d62a17ae 10314 show_adj_route(vty, peer, afi, safi, in, rmap_name, use_json, json);
0b16f239 10315
d62a17ae 10316 return CMD_SUCCESS;
a636c635 10317}
50ef26d4 10318
a636c635
DW
10319DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
10320 show_ip_bgp_instance_neighbor_advertised_route_cmd,
4dd6177e 10321 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
1edcd642 10322 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
718e3744 10323 SHOW_STR
10324 IP_STR
10325 BGP_STR
a636c635 10326 BGP_INSTANCE_HELP_STR
7395a2c9 10327 BGP_AFI_HELP_STR
4dd6177e 10328 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10329 "Detailed information on TCP and BGP neighbor connections\n"
10330 "Neighbor to display information about\n"
10331 "Neighbor to display information about\n"
91d37724 10332 "Neighbor on BGP configured interface\n"
856ca177 10333 "Display the received routes from neighbor\n"
a636c635
DW
10334 "Display the routes advertised to a BGP neighbor\n"
10335 "Route-map to modify the attributes\n"
10336 "Name of the route map\n"
9973d184 10337 JSON_STR)
718e3744 10338{
d62a17ae 10339 afi_t afi = AFI_IP6;
10340 safi_t safi = SAFI_UNICAST;
10341 char *rmap_name = NULL;
10342 char *peerstr = NULL;
10343 int rcvd = 0;
10344 struct bgp *bgp = NULL;
10345 struct peer *peer;
bb46e94f 10346
d62a17ae 10347 int idx = 0;
718e3744 10348
d62a17ae 10349 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10350 &bgp);
10351 if (!idx)
10352 return CMD_WARNING;
c493f2d8 10353
d62a17ae 10354 int uj = use_json(argc, argv);
10355 if (uj)
10356 argc--;
30a6a167 10357
d62a17ae 10358 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10359 argv_find(argv, argc, "neighbors", &idx);
10360 peerstr = argv[++idx]->arg;
8c3deaae 10361
d62a17ae 10362 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10363 if (!peer)
10364 return CMD_WARNING;
856ca177 10365
d62a17ae 10366 if (argv_find(argv, argc, "received-routes", &idx))
10367 rcvd = 1;
10368 if (argv_find(argv, argc, "advertised-routes", &idx))
10369 rcvd = 0;
10370 if (argv_find(argv, argc, "route-map", &idx))
10371 rmap_name = argv[++idx]->arg;
95cbbd2a 10372
d62a17ae 10373 return peer_adj_routes(vty, peer, afi, safi, rcvd, rmap_name, uj);
95cbbd2a
ML
10374}
10375
718e3744 10376DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10377 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10378 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10379 SHOW_STR
10380 IP_STR
10381 BGP_STR
8c3deaae
QY
10382 "Address Family\n"
10383 "Address Family\n"
718e3744 10384 "Address Family modifier\n"
10385 "Detailed information on TCP and BGP neighbor connections\n"
10386 "Neighbor to display information about\n"
10387 "Neighbor to display information about\n"
91d37724 10388 "Neighbor on BGP configured interface\n"
718e3744 10389 "Display information received from a BGP neighbor\n"
856ca177 10390 "Display the prefixlist filter\n"
9973d184 10391 JSON_STR)
718e3744 10392{
d62a17ae 10393 afi_t afi = AFI_IP6;
10394 safi_t safi = SAFI_UNICAST;
10395 char *peerstr = NULL;
10396
10397 char name[BUFSIZ];
10398 union sockunion su;
10399 struct peer *peer;
10400 int count, ret;
10401
10402 int idx = 0;
10403
10404 /* show [ip] bgp */
10405 if (argv_find(argv, argc, "ip", &idx))
10406 afi = AFI_IP;
10407 /* [<ipv4|ipv6> [unicast]] */
10408 if (argv_find(argv, argc, "ipv4", &idx))
10409 afi = AFI_IP;
10410 if (argv_find(argv, argc, "ipv6", &idx))
10411 afi = AFI_IP6;
10412 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10413 argv_find(argv, argc, "neighbors", &idx);
10414 peerstr = argv[++idx]->arg;
10415
10416 u_char uj = use_json(argc, argv);
10417
10418 ret = str2sockunion(peerstr, &su);
10419 if (ret < 0) {
10420 peer = peer_lookup_by_conf_if(NULL, peerstr);
10421 if (!peer) {
10422 if (uj)
10423 vty_out(vty, "{}\n");
10424 else
10425 vty_out(vty,
10426 "%% Malformed address or name: %s\n",
10427 peerstr);
10428 return CMD_WARNING;
10429 }
10430 } else {
10431 peer = peer_lookup(NULL, &su);
10432 if (!peer) {
10433 if (uj)
10434 vty_out(vty, "{}\n");
10435 else
10436 vty_out(vty, "No peer\n");
10437 return CMD_WARNING;
10438 }
10439 }
718e3744 10440
d62a17ae 10441 sprintf(name, "%s.%d.%d", peer->host, afi, safi);
10442 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
10443 if (count) {
10444 if (!uj)
10445 vty_out(vty, "Address Family: %s\n",
10446 afi_safi_print(afi, safi));
10447 prefix_bgp_show_prefix_list(vty, afi, name, uj);
10448 } else {
10449 if (uj)
10450 vty_out(vty, "{}\n");
10451 else
10452 vty_out(vty, "No functional output\n");
10453 }
718e3744 10454
d62a17ae 10455 return CMD_SUCCESS;
10456}
10457
10458static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
10459 afi_t afi, safi_t safi,
10460 enum bgp_show_type type, u_char use_json)
10461{
8a893163
DW
10462 /* labeled-unicast routes live in the unicast table */
10463 if (safi == SAFI_LABELED_UNICAST)
10464 safi = SAFI_UNICAST;
10465
d62a17ae 10466 if (!peer || !peer->afc[afi][safi]) {
10467 if (use_json) {
10468 json_object *json_no = NULL;
10469 json_no = json_object_new_object();
10470 json_object_string_add(
10471 json_no, "warning",
10472 "No such neighbor or address family");
10473 vty_out(vty, "%s\n",
10474 json_object_to_json_string(json_no));
10475 json_object_free(json_no);
10476 } else
10477 vty_out(vty, "%% No such neighbor or address family\n");
10478 return CMD_WARNING;
10479 }
47fc97cc 10480
d62a17ae 10481 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10482}
10483
10484DEFUN (show_ip_bgp_neighbor_routes,
10485 show_ip_bgp_neighbor_routes_cmd,
4dd6177e 10486 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] "
30a6a167 10487 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10488 SHOW_STR
10489 IP_STR
10490 BGP_STR
8386ac43 10491 BGP_INSTANCE_HELP_STR
4f280b15 10492 BGP_AFI_HELP_STR
4dd6177e 10493 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 10494 "Detailed information on TCP and BGP neighbor connections\n"
10495 "Neighbor to display information about\n"
10496 "Neighbor to display information about\n"
91d37724 10497 "Neighbor on BGP configured interface\n"
2525cf39 10498 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10499 "Display the dampened routes received from neighbor\n"
10500 "Display routes learned from neighbor\n"
9973d184 10501 JSON_STR)
718e3744 10502{
d62a17ae 10503 char *peerstr = NULL;
10504 struct bgp *bgp = NULL;
10505 afi_t afi = AFI_IP6;
10506 safi_t safi = SAFI_UNICAST;
10507 struct peer *peer;
10508 enum bgp_show_type sh_type = bgp_show_type_neighbor;
856ca177 10509
d62a17ae 10510 int idx = 0;
bb46e94f 10511
d62a17ae 10512 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10513 &bgp);
10514 if (!idx)
10515 return CMD_WARNING;
c493f2d8 10516
d62a17ae 10517 int uj = use_json(argc, argv);
10518 if (uj)
10519 argc--;
30a6a167 10520
d62a17ae 10521 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10522 argv_find(argv, argc, "neighbors", &idx);
10523 peerstr = argv[++idx]->arg;
8c3deaae 10524
d62a17ae 10525 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
10526 if (!peer) {
10527 vty_out(vty, "No such neighbor\n");
10528 return CMD_WARNING;
10529 }
bb46e94f 10530
d62a17ae 10531 if (argv_find(argv, argc, "flap-statistics", &idx))
10532 sh_type = bgp_show_type_flap_neighbor;
10533 else if (argv_find(argv, argc, "dampened-routes", &idx))
10534 sh_type = bgp_show_type_damp_neighbor;
10535 else if (argv_find(argv, argc, "routes", &idx))
10536 sh_type = bgp_show_type_neighbor;
2525cf39 10537
d62a17ae 10538 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 10539}
6b0655a2 10540
734b349e 10541struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10542
d62a17ae 10543struct bgp_distance {
10544 /* Distance value for the IP source prefix. */
10545 u_char distance;
718e3744 10546
d62a17ae 10547 /* Name of the access-list to be matched. */
10548 char *access_list;
718e3744 10549};
10550
4f280b15
LB
10551DEFUN (show_bgp_afi_vpn_rd_route,
10552 show_bgp_afi_vpn_rd_route_cmd,
d114b977 10553 "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
10554 SHOW_STR
10555 BGP_STR
10556 BGP_AFI_HELP_STR
10557 "Address Family modifier\n"
10558 "Display information for a route distinguisher\n"
10559 "Route Distinguisher\n"
7395a2c9
DS
10560 "Network in the BGP routing table to display\n"
10561 "Network in the BGP routing table to display\n"
10562 JSON_STR)
4f280b15 10563{
d62a17ae 10564 int ret;
10565 struct prefix_rd prd;
10566 afi_t afi = AFI_MAX;
10567 int idx = 0;
4f280b15 10568
ff6566f3
DS
10569 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
10570 vty_out(vty, "%% Malformed Address Family\n");
10571 return CMD_WARNING;
10572 }
10573
d62a17ae 10574 ret = str2prefix_rd(argv[5]->arg, &prd);
10575 if (!ret) {
10576 vty_out(vty, "%% Malformed Route Distinguisher\n");
10577 return CMD_WARNING;
10578 }
ff6566f3 10579
d62a17ae 10580 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
10581 0, BGP_PATH_ALL, use_json(argc, argv));
4f280b15
LB
10582}
10583
d62a17ae 10584static struct bgp_distance *bgp_distance_new(void)
718e3744 10585{
d62a17ae 10586 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 10587}
10588
d62a17ae 10589static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 10590{
d62a17ae 10591 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 10592}
10593
d62a17ae 10594static int bgp_distance_set(struct vty *vty, const char *distance_str,
10595 const char *ip_str, const char *access_list_str)
718e3744 10596{
d62a17ae 10597 int ret;
10598 afi_t afi;
10599 safi_t safi;
10600 struct prefix p;
10601 u_char distance;
10602 struct bgp_node *rn;
10603 struct bgp_distance *bdistance;
718e3744 10604
d62a17ae 10605 afi = bgp_node_afi(vty);
10606 safi = bgp_node_safi(vty);
734b349e 10607
d62a17ae 10608 ret = str2prefix(ip_str, &p);
10609 if (ret == 0) {
10610 vty_out(vty, "Malformed prefix\n");
10611 return CMD_WARNING_CONFIG_FAILED;
10612 }
718e3744 10613
d62a17ae 10614 distance = atoi(distance_str);
718e3744 10615
d62a17ae 10616 /* Get BGP distance node. */
10617 rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
10618 if (rn->info) {
10619 bdistance = rn->info;
10620 bgp_unlock_node(rn);
10621 } else {
10622 bdistance = bgp_distance_new();
10623 rn->info = bdistance;
10624 }
718e3744 10625
d62a17ae 10626 /* Set distance value. */
10627 bdistance->distance = distance;
718e3744 10628
d62a17ae 10629 /* Reset access-list configuration. */
10630 if (bdistance->access_list) {
10631 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10632 bdistance->access_list = NULL;
10633 }
10634 if (access_list_str)
10635 bdistance->access_list =
10636 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 10637
d62a17ae 10638 return CMD_SUCCESS;
718e3744 10639}
10640
d62a17ae 10641static int bgp_distance_unset(struct vty *vty, const char *distance_str,
10642 const char *ip_str, const char *access_list_str)
718e3744 10643{
d62a17ae 10644 int ret;
10645 afi_t afi;
10646 safi_t safi;
10647 struct prefix p;
10648 int distance;
10649 struct bgp_node *rn;
10650 struct bgp_distance *bdistance;
718e3744 10651
d62a17ae 10652 afi = bgp_node_afi(vty);
10653 safi = bgp_node_safi(vty);
734b349e 10654
d62a17ae 10655 ret = str2prefix(ip_str, &p);
10656 if (ret == 0) {
10657 vty_out(vty, "Malformed prefix\n");
10658 return CMD_WARNING_CONFIG_FAILED;
10659 }
718e3744 10660
d62a17ae 10661 rn = bgp_node_lookup(bgp_distance_table[afi][safi],
10662 (struct prefix *)&p);
10663 if (!rn) {
10664 vty_out(vty, "Can't find specified prefix\n");
10665 return CMD_WARNING_CONFIG_FAILED;
10666 }
718e3744 10667
d62a17ae 10668 bdistance = rn->info;
10669 distance = atoi(distance_str);
1f9a9fff 10670
d62a17ae 10671 if (bdistance->distance != distance) {
10672 vty_out(vty, "Distance does not match configured\n");
10673 return CMD_WARNING_CONFIG_FAILED;
10674 }
718e3744 10675
d62a17ae 10676 if (bdistance->access_list)
10677 XFREE(MTYPE_AS_LIST, bdistance->access_list);
10678 bgp_distance_free(bdistance);
718e3744 10679
d62a17ae 10680 rn->info = NULL;
10681 bgp_unlock_node(rn);
10682 bgp_unlock_node(rn);
718e3744 10683
d62a17ae 10684 return CMD_SUCCESS;
718e3744 10685}
10686
718e3744 10687/* Apply BGP information to distance method. */
d62a17ae 10688u_char bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi,
10689 safi_t safi, struct bgp *bgp)
10690{
10691 struct bgp_node *rn;
10692 struct prefix q;
10693 struct peer *peer;
10694 struct bgp_distance *bdistance;
10695 struct access_list *alist;
10696 struct bgp_static *bgp_static;
10697
10698 if (!bgp)
10699 return 0;
10700
10701 peer = rinfo->peer;
10702
10703 /* Check source address. */
10704 sockunion2hostprefix(&peer->su, &q);
10705 rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
10706 if (rn) {
10707 bdistance = rn->info;
10708 bgp_unlock_node(rn);
10709
10710 if (bdistance->access_list) {
10711 alist = access_list_lookup(afi, bdistance->access_list);
10712 if (alist
10713 && access_list_apply(alist, p) == FILTER_PERMIT)
10714 return bdistance->distance;
10715 } else
10716 return bdistance->distance;
718e3744 10717 }
718e3744 10718
d62a17ae 10719 /* Backdoor check. */
10720 rn = bgp_node_lookup(bgp->route[afi][safi], p);
10721 if (rn) {
10722 bgp_static = rn->info;
10723 bgp_unlock_node(rn);
718e3744 10724
d62a17ae 10725 if (bgp_static->backdoor) {
10726 if (bgp->distance_local[afi][safi])
10727 return bgp->distance_local[afi][safi];
10728 else
10729 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10730 }
718e3744 10731 }
718e3744 10732
d62a17ae 10733 if (peer->sort == BGP_PEER_EBGP) {
10734 if (bgp->distance_ebgp[afi][safi])
10735 return bgp->distance_ebgp[afi][safi];
10736 return ZEBRA_EBGP_DISTANCE_DEFAULT;
10737 } else {
10738 if (bgp->distance_ibgp[afi][safi])
10739 return bgp->distance_ibgp[afi][safi];
10740 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10741 }
718e3744 10742}
10743
10744DEFUN (bgp_distance,
10745 bgp_distance_cmd,
6147e2c6 10746 "distance bgp (1-255) (1-255) (1-255)",
718e3744 10747 "Define an administrative distance\n"
10748 "BGP distance\n"
10749 "Distance for routes external to the AS\n"
10750 "Distance for routes internal to the AS\n"
10751 "Distance for local routes\n")
10752{
d62a17ae 10753 VTY_DECLVAR_CONTEXT(bgp, bgp);
10754 int idx_number = 2;
10755 int idx_number_2 = 3;
10756 int idx_number_3 = 4;
10757 afi_t afi;
10758 safi_t safi;
718e3744 10759
d62a17ae 10760 afi = bgp_node_afi(vty);
10761 safi = bgp_node_safi(vty);
718e3744 10762
d62a17ae 10763 bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg);
10764 bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg);
10765 bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg);
10766 return CMD_SUCCESS;
718e3744 10767}
10768
10769DEFUN (no_bgp_distance,
10770 no_bgp_distance_cmd,
a636c635 10771 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 10772 NO_STR
10773 "Define an administrative distance\n"
10774 "BGP distance\n"
10775 "Distance for routes external to the AS\n"
10776 "Distance for routes internal to the AS\n"
10777 "Distance for local routes\n")
10778{
d62a17ae 10779 VTY_DECLVAR_CONTEXT(bgp, bgp);
10780 afi_t afi;
10781 safi_t safi;
718e3744 10782
d62a17ae 10783 afi = bgp_node_afi(vty);
10784 safi = bgp_node_safi(vty);
718e3744 10785
d62a17ae 10786 bgp->distance_ebgp[afi][safi] = 0;
10787 bgp->distance_ibgp[afi][safi] = 0;
10788 bgp->distance_local[afi][safi] = 0;
10789 return CMD_SUCCESS;
718e3744 10790}
10791
718e3744 10792
10793DEFUN (bgp_distance_source,
10794 bgp_distance_source_cmd,
6147e2c6 10795 "distance (1-255) A.B.C.D/M",
718e3744 10796 "Define an administrative distance\n"
10797 "Administrative distance\n"
10798 "IP source prefix\n")
10799{
d62a17ae 10800 int idx_number = 1;
10801 int idx_ipv4_prefixlen = 2;
10802 bgp_distance_set(vty, argv[idx_number]->arg,
10803 argv[idx_ipv4_prefixlen]->arg, NULL);
10804 return CMD_SUCCESS;
718e3744 10805}
10806
10807DEFUN (no_bgp_distance_source,
10808 no_bgp_distance_source_cmd,
6147e2c6 10809 "no distance (1-255) A.B.C.D/M",
718e3744 10810 NO_STR
10811 "Define an administrative distance\n"
10812 "Administrative distance\n"
10813 "IP source prefix\n")
10814{
d62a17ae 10815 int idx_number = 2;
10816 int idx_ipv4_prefixlen = 3;
10817 bgp_distance_unset(vty, argv[idx_number]->arg,
10818 argv[idx_ipv4_prefixlen]->arg, NULL);
10819 return CMD_SUCCESS;
718e3744 10820}
10821
10822DEFUN (bgp_distance_source_access_list,
10823 bgp_distance_source_access_list_cmd,
6147e2c6 10824 "distance (1-255) A.B.C.D/M WORD",
718e3744 10825 "Define an administrative distance\n"
10826 "Administrative distance\n"
10827 "IP source prefix\n"
10828 "Access list name\n")
10829{
d62a17ae 10830 int idx_number = 1;
10831 int idx_ipv4_prefixlen = 2;
10832 int idx_word = 3;
10833 bgp_distance_set(vty, argv[idx_number]->arg,
10834 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
10835 return CMD_SUCCESS;
718e3744 10836}
10837
10838DEFUN (no_bgp_distance_source_access_list,
10839 no_bgp_distance_source_access_list_cmd,
6147e2c6 10840 "no distance (1-255) A.B.C.D/M WORD",
718e3744 10841 NO_STR
10842 "Define an administrative distance\n"
10843 "Administrative distance\n"
10844 "IP source prefix\n"
10845 "Access list name\n")
10846{
d62a17ae 10847 int idx_number = 2;
10848 int idx_ipv4_prefixlen = 3;
10849 int idx_word = 4;
10850 bgp_distance_unset(vty, argv[idx_number]->arg,
10851 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
10852 return CMD_SUCCESS;
718e3744 10853}
6b0655a2 10854
734b349e
MZ
10855DEFUN (ipv6_bgp_distance_source,
10856 ipv6_bgp_distance_source_cmd,
39e92c06 10857 "distance (1-255) X:X::X:X/M",
734b349e
MZ
10858 "Define an administrative distance\n"
10859 "Administrative distance\n"
10860 "IP source prefix\n")
10861{
d62a17ae 10862 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
10863 return CMD_SUCCESS;
734b349e
MZ
10864}
10865
10866DEFUN (no_ipv6_bgp_distance_source,
10867 no_ipv6_bgp_distance_source_cmd,
39e92c06 10868 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
10869 NO_STR
10870 "Define an administrative distance\n"
10871 "Administrative distance\n"
10872 "IP source prefix\n")
10873{
d62a17ae 10874 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
10875 return CMD_SUCCESS;
734b349e
MZ
10876}
10877
10878DEFUN (ipv6_bgp_distance_source_access_list,
10879 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10880 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10881 "Define an administrative distance\n"
10882 "Administrative distance\n"
10883 "IP source prefix\n"
10884 "Access list name\n")
10885{
d62a17ae 10886 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
10887 return CMD_SUCCESS;
734b349e
MZ
10888}
10889
10890DEFUN (no_ipv6_bgp_distance_source_access_list,
10891 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10892 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10893 NO_STR
10894 "Define an administrative distance\n"
10895 "Administrative distance\n"
10896 "IP source prefix\n"
10897 "Access list name\n")
10898{
d62a17ae 10899 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
10900 return CMD_SUCCESS;
734b349e
MZ
10901}
10902
718e3744 10903DEFUN (bgp_damp_set,
10904 bgp_damp_set_cmd,
31500417 10905 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10906 "BGP Specific commands\n"
10907 "Enable route-flap dampening\n"
10908 "Half-life time for the penalty\n"
10909 "Value to start reusing a route\n"
10910 "Value to start suppressing a route\n"
10911 "Maximum duration to suppress a stable route\n")
10912{
d62a17ae 10913 VTY_DECLVAR_CONTEXT(bgp, bgp);
10914 int idx_half_life = 2;
10915 int idx_reuse = 3;
10916 int idx_suppress = 4;
10917 int idx_max_suppress = 5;
10918 int half = DEFAULT_HALF_LIFE * 60;
10919 int reuse = DEFAULT_REUSE;
10920 int suppress = DEFAULT_SUPPRESS;
10921 int max = 4 * half;
10922
10923 if (argc == 6) {
10924 half = atoi(argv[idx_half_life]->arg) * 60;
10925 reuse = atoi(argv[idx_reuse]->arg);
10926 suppress = atoi(argv[idx_suppress]->arg);
10927 max = atoi(argv[idx_max_suppress]->arg) * 60;
10928 } else if (argc == 3) {
10929 half = atoi(argv[idx_half_life]->arg) * 60;
10930 max = 4 * half;
10931 }
718e3744 10932
d62a17ae 10933 if (suppress < reuse) {
10934 vty_out(vty,
10935 "Suppress value cannot be less than reuse value \n");
10936 return 0;
10937 }
7ebe9748 10938
d62a17ae 10939 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
10940 reuse, suppress, max);
718e3744 10941}
10942
718e3744 10943DEFUN (bgp_damp_unset,
10944 bgp_damp_unset_cmd,
d04c479d 10945 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10946 NO_STR
10947 "BGP Specific commands\n"
16cedbb0
QY
10948 "Enable route-flap dampening\n"
10949 "Half-life time for the penalty\n"
10950 "Value to start reusing a route\n"
10951 "Value to start suppressing a route\n"
10952 "Maximum duration to suppress a stable route\n")
718e3744 10953{
d62a17ae 10954 VTY_DECLVAR_CONTEXT(bgp, bgp);
10955 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 10956}
10957
718e3744 10958/* Display specified route of BGP table. */
d62a17ae 10959static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
10960 const char *ip_str, afi_t afi, safi_t safi,
10961 struct prefix_rd *prd, int prefix_check)
10962{
10963 int ret;
10964 struct prefix match;
10965 struct bgp_node *rn;
10966 struct bgp_node *rm;
10967 struct bgp_info *ri;
10968 struct bgp_info *ri_temp;
10969 struct bgp *bgp;
10970 struct bgp_table *table;
10971
10972 /* BGP structure lookup. */
10973 if (view_name) {
10974 bgp = bgp_lookup_by_name(view_name);
10975 if (bgp == NULL) {
10976 vty_out(vty, "%% Can't find BGP instance %s\n",
10977 view_name);
10978 return CMD_WARNING;
10979 }
10980 } else {
10981 bgp = bgp_get_default();
10982 if (bgp == NULL) {
10983 vty_out(vty, "%% No BGP process is configured\n");
10984 return CMD_WARNING;
10985 }
718e3744 10986 }
718e3744 10987
d62a17ae 10988 /* Check IP address argument. */
10989 ret = str2prefix(ip_str, &match);
10990 if (!ret) {
10991 vty_out(vty, "%% address is malformed\n");
10992 return CMD_WARNING;
10993 }
718e3744 10994
d62a17ae 10995 match.family = afi2family(afi);
10996
10997 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
10998 || (safi == SAFI_EVPN)) {
10999 for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn;
11000 rn = bgp_route_next(rn)) {
11001 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
11002 continue;
ea47320b
DL
11003 if ((table = rn->info) == NULL)
11004 continue;
11005 if ((rm = bgp_node_match(table, &match)) == NULL)
11006 continue;
d62a17ae 11007
ea47320b
DL
11008 if (!prefix_check
11009 || rm->p.prefixlen == match.prefixlen) {
11010 ri = rm->info;
11011 while (ri) {
60466a63 11012 if (ri->extra && ri->extra->damp_info) {
ea47320b
DL
11013 ri_temp = ri->next;
11014 bgp_damp_info_free(
60466a63
QY
11015 ri->extra->damp_info,
11016 1);
ea47320b
DL
11017 ri = ri_temp;
11018 } else
11019 ri = ri->next;
d62a17ae 11020 }
ea47320b
DL
11021 }
11022
11023 bgp_unlock_node(rm);
d62a17ae 11024 }
11025 } else {
11026 if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
11027 != NULL) {
11028 if (!prefix_check
11029 || rn->p.prefixlen == match.prefixlen) {
11030 ri = rn->info;
11031 while (ri) {
11032 if (ri->extra && ri->extra->damp_info) {
11033 ri_temp = ri->next;
11034 bgp_damp_info_free(
11035 ri->extra->damp_info,
11036 1);
11037 ri = ri_temp;
11038 } else
11039 ri = ri->next;
11040 }
11041 }
11042
11043 bgp_unlock_node(rn);
11044 }
11045 }
718e3744 11046
d62a17ae 11047 return CMD_SUCCESS;
718e3744 11048}
11049
11050DEFUN (clear_ip_bgp_dampening,
11051 clear_ip_bgp_dampening_cmd,
11052 "clear ip bgp dampening",
11053 CLEAR_STR
11054 IP_STR
11055 BGP_STR
11056 "Clear route flap dampening information\n")
11057{
d62a17ae 11058 bgp_damp_info_clean();
11059 return CMD_SUCCESS;
718e3744 11060}
11061
11062DEFUN (clear_ip_bgp_dampening_prefix,
11063 clear_ip_bgp_dampening_prefix_cmd,
11064 "clear ip bgp dampening A.B.C.D/M",
11065 CLEAR_STR
11066 IP_STR
11067 BGP_STR
11068 "Clear route flap dampening information\n"
0c7b1b01 11069 "IPv4 prefix\n")
718e3744 11070{
d62a17ae 11071 int idx_ipv4_prefixlen = 4;
11072 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
11073 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 11074}
11075
11076DEFUN (clear_ip_bgp_dampening_address,
11077 clear_ip_bgp_dampening_address_cmd,
11078 "clear ip bgp dampening A.B.C.D",
11079 CLEAR_STR
11080 IP_STR
11081 BGP_STR
11082 "Clear route flap dampening information\n"
11083 "Network to clear damping information\n")
11084{
d62a17ae 11085 int idx_ipv4 = 4;
11086 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
11087 SAFI_UNICAST, NULL, 0);
718e3744 11088}
11089
11090DEFUN (clear_ip_bgp_dampening_address_mask,
11091 clear_ip_bgp_dampening_address_mask_cmd,
11092 "clear ip bgp dampening A.B.C.D A.B.C.D",
11093 CLEAR_STR
11094 IP_STR
11095 BGP_STR
11096 "Clear route flap dampening information\n"
11097 "Network to clear damping information\n"
11098 "Network mask\n")
11099{
d62a17ae 11100 int idx_ipv4 = 4;
11101 int idx_ipv4_2 = 5;
11102 int ret;
11103 char prefix_str[BUFSIZ];
718e3744 11104
d62a17ae 11105 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
11106 prefix_str);
11107 if (!ret) {
11108 vty_out(vty, "%% Inconsistent address and mask\n");
11109 return CMD_WARNING;
11110 }
718e3744 11111
d62a17ae 11112 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
11113 NULL, 0);
718e3744 11114}
6b0655a2 11115
587ff0fd 11116/* also used for encap safi */
2b791107
DL
11117static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
11118 afi_t afi, safi_t safi)
d62a17ae 11119{
11120 struct bgp_node *prn;
11121 struct bgp_node *rn;
11122 struct bgp_table *table;
11123 struct prefix *p;
11124 struct prefix_rd *prd;
11125 struct bgp_static *bgp_static;
11126 mpls_label_t label;
11127 char buf[SU_ADDRSTRLEN];
11128 char rdbuf[RD_ADDRSTRLEN];
11129
11130 /* Network configuration. */
11131 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11132 prn = bgp_route_next(prn)) {
11133 if ((table = prn->info) == NULL)
11134 continue;
d62a17ae 11135
60466a63 11136 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
ea47320b
DL
11137 if ((bgp_static = rn->info) == NULL)
11138 continue;
d62a17ae 11139
ea47320b
DL
11140 p = &rn->p;
11141 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11142
ea47320b 11143 /* "network" configuration display. */
06b9f471 11144 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
11145 label = decode_label(&bgp_static->label);
11146
11147 vty_out(vty, " network %s/%d rd %s",
11148 inet_ntop(p->family, &p->u.prefix, buf,
11149 SU_ADDRSTRLEN),
11150 p->prefixlen, rdbuf);
11151 if (safi == SAFI_MPLS_VPN)
11152 vty_out(vty, " label %u", label);
11153
11154 if (bgp_static->rmap.name)
11155 vty_out(vty, " route-map %s",
11156 bgp_static->rmap.name);
11157 else {
11158 if (bgp_static->backdoor)
11159 vty_out(vty, " backdoor");
11160 }
11161 vty_out(vty, "\n");
11162 }
11163 }
d62a17ae 11164}
11165
2b791107
DL
11166static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
11167 afi_t afi, safi_t safi)
d62a17ae 11168{
11169 struct bgp_node *prn;
11170 struct bgp_node *rn;
11171 struct bgp_table *table;
11172 struct prefix *p;
11173 struct prefix_rd *prd;
11174 struct bgp_static *bgp_static;
11175 char buf[PREFIX_STRLEN];
11176 char buf2[SU_ADDRSTRLEN];
11177 char rdbuf[RD_ADDRSTRLEN];
11178
11179 /* Network configuration. */
11180 for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
ea47320b
DL
11181 prn = bgp_route_next(prn)) {
11182 if ((table = prn->info) == NULL)
11183 continue;
d62a17ae 11184
60466a63 11185 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
ea47320b
DL
11186 if ((bgp_static = rn->info) == NULL)
11187 continue;
d62a17ae 11188
ea47320b
DL
11189 char *macrouter = NULL;
11190 char *esi = NULL;
d62a17ae 11191
ea47320b
DL
11192 if (bgp_static->router_mac)
11193 macrouter = prefix_mac2str(
11194 bgp_static->router_mac, NULL, 0);
11195 if (bgp_static->eth_s_id)
11196 esi = esi2str(bgp_static->eth_s_id);
11197 p = &rn->p;
11198 prd = (struct prefix_rd *)&prn->p;
d62a17ae 11199
ea47320b 11200 /* "network" configuration display. */
06b9f471 11201 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
11202 if (p->u.prefix_evpn.route_type == 5) {
11203 char local_buf[PREFIX_STRLEN];
11204 uint8_t family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
11205 ? AF_INET
11206 : AF_INET6;
11207 inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, local_buf,
11208 PREFIX_STRLEN);
11209 sprintf(buf, "%s/%u", local_buf,p->u.prefix_evpn.ip_prefix_length);
11210 } else {
11211 prefix2str(p, buf, sizeof(buf));
11212 }
ea47320b 11213
197cb530
PG
11214 if (bgp_static->gatewayIp.family == AF_INET ||
11215 bgp_static->gatewayIp.family == AF_INET6)
11216 inet_ntop(bgp_static->gatewayIp.family,
11217 &bgp_static->gatewayIp.u.prefix, buf2,
11218 sizeof(buf2));
ea47320b
DL
11219 vty_out(vty,
11220 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
60466a63
QY
11221 buf, rdbuf, p->u.prefix_evpn.eth_tag,
11222 decode_label(&bgp_static->label), esi, buf2,
ea47320b
DL
11223 macrouter);
11224
11225 if (macrouter)
11226 XFREE(MTYPE_TMP, macrouter);
11227 if (esi)
11228 XFREE(MTYPE_TMP, esi);
11229 }
11230 }
3da6fcd5
PG
11231}
11232
718e3744 11233/* Configuration of static route announcement and aggregate
11234 information. */
2b791107
DL
11235void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
11236 safi_t safi)
d62a17ae 11237{
11238 struct bgp_node *rn;
11239 struct prefix *p;
11240 struct bgp_static *bgp_static;
11241 struct bgp_aggregate *bgp_aggregate;
11242 char buf[SU_ADDRSTRLEN];
11243
2b791107
DL
11244 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
11245 bgp_config_write_network_vpn(vty, bgp, afi, safi);
11246 return;
11247 }
d62a17ae 11248
2b791107
DL
11249 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
11250 bgp_config_write_network_evpn(vty, bgp, afi, safi);
11251 return;
11252 }
d62a17ae 11253
11254 /* Network configuration. */
11255 for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
ea47320b
DL
11256 rn = bgp_route_next(rn)) {
11257 if ((bgp_static = rn->info) == NULL)
11258 continue;
d62a17ae 11259
ea47320b 11260 p = &rn->p;
d62a17ae 11261
ea47320b 11262 /* "network" configuration display. */
60466a63 11263 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
ea47320b
DL
11264 u_int32_t destination;
11265 struct in_addr netmask;
d62a17ae 11266
ea47320b
DL
11267 destination = ntohl(p->u.prefix4.s_addr);
11268 masklen2ip(p->prefixlen, &netmask);
11269 vty_out(vty, " network %s",
11270 inet_ntop(p->family, &p->u.prefix, buf,
11271 SU_ADDRSTRLEN));
d62a17ae 11272
ea47320b
DL
11273 if ((IN_CLASSC(destination) && p->prefixlen == 24)
11274 || (IN_CLASSB(destination) && p->prefixlen == 16)
11275 || (IN_CLASSA(destination) && p->prefixlen == 8)
11276 || p->u.prefix4.s_addr == 0) {
11277 /* Natural mask is not display. */
11278 } else
11279 vty_out(vty, " mask %s", inet_ntoa(netmask));
11280 } else {
11281 vty_out(vty, " network %s/%d",
11282 inet_ntop(p->family, &p->u.prefix, buf,
11283 SU_ADDRSTRLEN),
11284 p->prefixlen);
11285 }
d62a17ae 11286
ea47320b
DL
11287 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
11288 vty_out(vty, " label-index %u",
11289 bgp_static->label_index);
d62a17ae 11290
ea47320b
DL
11291 if (bgp_static->rmap.name)
11292 vty_out(vty, " route-map %s", bgp_static->rmap.name);
11293 else {
11294 if (bgp_static->backdoor)
11295 vty_out(vty, " backdoor");
d62a17ae 11296 }
718e3744 11297
ea47320b
DL
11298 vty_out(vty, "\n");
11299 }
11300
d62a17ae 11301 /* Aggregate-address configuration. */
11302 for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
ea47320b
DL
11303 rn = bgp_route_next(rn)) {
11304 if ((bgp_aggregate = rn->info) == NULL)
11305 continue;
d62a17ae 11306
ea47320b 11307 p = &rn->p;
d62a17ae 11308
ea47320b
DL
11309 if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
11310 struct in_addr netmask;
d62a17ae 11311
ea47320b
DL
11312 masklen2ip(p->prefixlen, &netmask);
11313 vty_out(vty, " aggregate-address %s %s",
11314 inet_ntop(p->family, &p->u.prefix, buf,
11315 SU_ADDRSTRLEN),
11316 inet_ntoa(netmask));
11317 } else {
11318 vty_out(vty, " aggregate-address %s/%d",
11319 inet_ntop(p->family, &p->u.prefix, buf,
11320 SU_ADDRSTRLEN),
11321 p->prefixlen);
11322 }
d62a17ae 11323
ea47320b
DL
11324 if (bgp_aggregate->as_set)
11325 vty_out(vty, " as-set");
d62a17ae 11326
ea47320b
DL
11327 if (bgp_aggregate->summary_only)
11328 vty_out(vty, " summary-only");
718e3744 11329
ea47320b
DL
11330 vty_out(vty, "\n");
11331 }
d62a17ae 11332}
734b349e 11333
2b791107 11334void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 11335 safi_t safi)
d62a17ae 11336{
11337 struct bgp_node *rn;
11338 struct bgp_distance *bdistance;
11339
11340 /* Distance configuration. */
11341 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
11342 && bgp->distance_local[afi][safi]
11343 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11344 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11345 || bgp->distance_local[afi][safi]
11346 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 11347 vty_out(vty, " distance bgp %d %d %d\n",
11348 bgp->distance_ebgp[afi][safi],
11349 bgp->distance_ibgp[afi][safi],
11350 bgp->distance_local[afi][safi]);
11351 }
734b349e 11352
d62a17ae 11353 for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn;
11354 rn = bgp_route_next(rn))
11355 if ((bdistance = rn->info) != NULL) {
11356 char buf[PREFIX_STRLEN];
11357
d62a17ae 11358 vty_out(vty, " distance %d %s %s\n",
11359 bdistance->distance,
11360 prefix2str(&rn->p, buf, sizeof(buf)),
11361 bdistance->access_list ? bdistance->access_list
11362 : "");
11363 }
718e3744 11364}
11365
11366/* Allocate routing table structure and install commands. */
d62a17ae 11367void bgp_route_init(void)
11368{
11369 afi_t afi;
11370 safi_t safi;
11371
11372 /* Init BGP distance table. */
05c7a1cc
QY
11373 FOREACH_AFI_SAFI (afi, safi)
11374 bgp_distance_table[afi][safi] = bgp_table_init(afi, safi);
d62a17ae 11375
11376 /* IPv4 BGP commands. */
11377 install_element(BGP_NODE, &bgp_table_map_cmd);
11378 install_element(BGP_NODE, &bgp_network_cmd);
11379 install_element(BGP_NODE, &bgp_network_mask_cmd);
11380 install_element(BGP_NODE, &bgp_network_mask_natural_cmd);
11381 install_element(BGP_NODE, &bgp_network_route_map_cmd);
11382 install_element(BGP_NODE, &bgp_network_mask_route_map_cmd);
11383 install_element(BGP_NODE, &bgp_network_mask_natural_route_map_cmd);
11384 install_element(BGP_NODE, &bgp_network_backdoor_cmd);
11385 install_element(BGP_NODE, &bgp_network_mask_backdoor_cmd);
11386 install_element(BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
11387 install_element(BGP_NODE, &no_bgp_table_map_cmd);
11388 install_element(BGP_NODE, &no_bgp_network_cmd);
11389 install_element(BGP_NODE, &no_bgp_network_mask_cmd);
11390 install_element(BGP_NODE, &no_bgp_network_mask_natural_cmd);
11391
11392 install_element(BGP_NODE, &aggregate_address_cmd);
11393 install_element(BGP_NODE, &aggregate_address_mask_cmd);
11394 install_element(BGP_NODE, &no_aggregate_address_cmd);
11395 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
11396
11397 /* IPv4 unicast configuration. */
11398 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
11399 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
11400 install_element(BGP_IPV4_NODE, &bgp_network_mask_cmd);
11401 install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_cmd);
11402 install_element(BGP_IPV4_NODE, &bgp_network_route_map_cmd);
11403 install_element(BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
11404 install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
11405 install_element(BGP_IPV4_NODE, &bgp_network_label_index_cmd);
11406 install_element(BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd);
11407 install_element(BGP_IPV4_NODE, &no_bgp_network_label_index_cmd);
11408 install_element(BGP_IPV4_NODE,
11409 &no_bgp_network_label_index_route_map_cmd);
11410 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
11411 install_element(BGP_IPV4_NODE, &no_bgp_network_cmd);
11412 install_element(BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
11413 install_element(BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
11414
11415 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
11416 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
11417 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
11418 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
11419
11420 /* IPv4 multicast configuration. */
11421 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
11422 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
11423 install_element(BGP_IPV4M_NODE, &bgp_network_mask_cmd);
11424 install_element(BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd);
11425 install_element(BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
11426 install_element(BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
11427 install_element(BGP_IPV4M_NODE,
11428 &bgp_network_mask_natural_route_map_cmd);
11429 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
11430 install_element(BGP_IPV4M_NODE, &no_bgp_network_cmd);
11431 install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
11432 install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
11433 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
11434 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
11435 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
11436 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
11437
11438 /* IPv4 labeled-unicast configuration. */
11439 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
11440 install_element(VIEW_NODE, &show_ip_bgp_cmd);
7b2ff250 11441 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 11442 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
11443 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
11444
11445 install_element(VIEW_NODE,
11446 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
11447 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
11448 install_element(VIEW_NODE,
11449 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 11450#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11451 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 11452#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 11453 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
11454 install_element(VIEW_NODE,
11455 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
57d187bc 11456
d62a17ae 11457 /* BGP dampening clear commands */
11458 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11459 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 11460
d62a17ae 11461 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11462 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11463
11464 /* prefix count */
11465 install_element(ENABLE_NODE,
11466 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 11467#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 11468 install_element(ENABLE_NODE,
11469 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 11470#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11471
d62a17ae 11472 /* New config IPv6 BGP commands. */
11473 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
11474 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
11475 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
11476 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
11477 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
11478 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd);
11479 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd);
11480 install_element(BGP_IPV6_NODE,
11481 &ipv6_bgp_network_label_index_route_map_cmd);
11482 install_element(BGP_IPV6_NODE,
11483 &no_ipv6_bgp_network_label_index_route_map_cmd);
11484
11485 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
11486 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
11487
11488 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
11489 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
11490
d62a17ae 11491 install_element(BGP_NODE, &bgp_distance_cmd);
11492 install_element(BGP_NODE, &no_bgp_distance_cmd);
11493 install_element(BGP_NODE, &bgp_distance_source_cmd);
11494 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
11495 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
11496 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
11497 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
11498 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
11499 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
11500 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11501 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11502 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11503 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
11504 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
11505 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11506 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11507 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11508 install_element(BGP_IPV4M_NODE,
11509 &no_bgp_distance_source_access_list_cmd);
11510 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
11511 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
11512 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11513 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11514 install_element(BGP_IPV6_NODE,
11515 &ipv6_bgp_distance_source_access_list_cmd);
11516 install_element(BGP_IPV6_NODE,
11517 &no_ipv6_bgp_distance_source_access_list_cmd);
11518 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
11519 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
11520 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11521 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11522 install_element(BGP_IPV6M_NODE,
11523 &ipv6_bgp_distance_source_access_list_cmd);
11524 install_element(BGP_IPV6M_NODE,
11525 &no_ipv6_bgp_distance_source_access_list_cmd);
11526
11527 install_element(BGP_NODE, &bgp_damp_set_cmd);
11528 install_element(BGP_NODE, &bgp_damp_unset_cmd);
11529 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
11530 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
11531
11532 /* IPv4 Multicast Mode */
11533 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
11534 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
11535
11536 /* Large Communities */
11537 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11538 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
11539}
11540
11541void bgp_route_finish(void)
11542{
11543 afi_t afi;
11544 safi_t safi;
11545
05c7a1cc
QY
11546 FOREACH_AFI_SAFI (afi, safi) {
11547 bgp_table_unlock(bgp_distance_table[afi][safi]);
11548 bgp_distance_table[afi][safi] = NULL;
11549 }
228da428 11550}