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