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