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