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