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