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