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