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