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