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