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