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