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