]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: introduction of vxlan tunnel attribute
[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
137446f9
LB
3996
3997 assert (bgp_static);
3998
3999 rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd);
4000
4001 bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
4002
4003 attr.nexthop = bgp_static->igpnexthop;
4004 attr.med = bgp_static->igpmetric;
4005 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
4006
684a7227 4007 if(afi == AFI_L2VPN)
aee875b5 4008 {
684a7227 4009 overlay_index_update(&attr, bgp_static->eth_s_id, NULL);
aee875b5
PG
4010 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN)
4011 {
4012 struct bgp_encap_type_vxlan bet;
4013 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
4014 bet.vnid = p->u.prefix_evpn.eth_tag;
4015 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
4016 }
4017 }
137446f9
LB
4018 /* Apply route-map. */
4019 if (bgp_static->rmap.name)
4020 {
4021 struct attr attr_tmp = attr;
4022 struct bgp_info info;
4023 int ret;
4024
4025 info.peer = bgp->peer_self;
4026 info.attr = &attr_tmp;
4027
4028 SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
4029
4030 ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info);
4031
4032 bgp->peer_self->rmap_type = 0;
4033
4034 if (ret == RMAP_DENYMATCH)
4035 {
4036 /* Free uninterned attribute. */
4037 bgp_attr_flush (&attr_tmp);
4038
4039 /* Unintern original. */
4040 aspath_unintern (&attr.aspath);
4041 bgp_attr_extra_free (&attr);
4042 bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd,
4043 bgp_static->tag);
4044 return;
4045 }
4046
4047 attr_new = bgp_attr_intern (&attr_tmp);
4048 }
4049 else
4050 {
4051 attr_new = bgp_attr_intern (&attr);
4052 }
4053
4054 for (ri = rn->info; ri; ri = ri->next)
4055 if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
4056 && ri->sub_type == BGP_ROUTE_STATIC)
4057 break;
4058
4059 if (ri)
4060 {
684a7227
PG
4061 union gw_addr add;
4062 memset(&add, 0, sizeof(union gw_addr));
137446f9 4063 if (attrhash_cmp (ri->attr, attr_new) &&
684a7227 4064 overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) &&
137446f9
LB
4065 !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4066 {
4067 bgp_unlock_node (rn);
4068 bgp_attr_unintern (&attr_new);
4069 aspath_unintern (&attr.aspath);
4070 bgp_attr_extra_free (&attr);
4071 return;
4072 }
4073 else
4074 {
4075 /* The attribute is changed. */
4076 bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
4077
4078 /* Rewrite BGP route information. */
4079 if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
4080 bgp_info_restore(rn, ri);
4081 else
4082 bgp_aggregate_decrement (bgp, p, ri, afi, safi);
4083 bgp_attr_unintern (&ri->attr);
4084 ri->attr = attr_new;
4085 ri->uptime = bgp_clock ();
65efcfce
LB
4086#if ENABLE_BGP_VNC
4087 if (ri->extra)
4088 label = decode_label (ri->extra->tag);
4089#endif
137446f9
LB
4090
4091 /* Process change. */
4092 bgp_aggregate_increment (bgp, p, ri, afi, safi);
4093 bgp_process (bgp, rn, afi, safi);
65efcfce
LB
4094#if ENABLE_BGP_VNC
4095 rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
4096 ri->attr, afi, safi,
4097 ri->type, ri->sub_type, &label);
4098#endif
137446f9
LB
4099 bgp_unlock_node (rn);
4100 aspath_unintern (&attr.aspath);
4101 bgp_attr_extra_free (&attr);
4102 return;
4103 }
4104 }
4105
4106
4107 /* Make new BGP info. */
4108 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new,
4109 rn);
4110 SET_FLAG (new->flags, BGP_INFO_VALID);
4111 new->extra = bgp_info_extra_new();
4112 memcpy (new->extra->tag, bgp_static->tag, 3);
65efcfce
LB
4113#if ENABLE_BGP_VNC
4114 label = decode_label (bgp_static->tag);
4115#endif
137446f9
LB
4116
4117 /* Aggregate address increment. */
4118 bgp_aggregate_increment (bgp, p, new, afi, safi);
4119
4120 /* Register new BGP information. */
4121 bgp_info_add (rn, new);
4122
4123 /* route_node_get lock */
4124 bgp_unlock_node (rn);
4125
4126 /* Process change. */
4127 bgp_process (bgp, rn, afi, safi);
4128
65efcfce
LB
4129#if ENABLE_BGP_VNC
4130 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd,
4131 new->attr, afi, safi,
4132 new->type, new->sub_type, &label);
4133#endif
4134
137446f9
LB
4135 /* Unintern original. */
4136 aspath_unintern (&attr.aspath);
4137 bgp_attr_extra_free (&attr);
4138}
4139
718e3744 4140/* Configure static BGP network. When user don't run zebra, static
4141 route should be installed as valid. */
94f2b392 4142static int
cdc2d765 4143bgp_static_set (struct vty *vty, const char *ip_str,
c8f3fe30 4144 afi_t afi, safi_t safi, const char *rmap, int backdoor)
718e3744 4145{
cdc2d765 4146 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 4147 int ret;
4148 struct prefix p;
4149 struct bgp_static *bgp_static;
4150 struct bgp_node *rn;
41367172 4151 u_char need_update = 0;
718e3744 4152
4153 /* Convert IP prefix string to struct prefix. */
4154 ret = str2prefix (ip_str, &p);
4155 if (! ret)
4156 {
4157 vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
4158 return CMD_WARNING;
4159 }
718e3744 4160 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
4161 {
4162 vty_out (vty, "%% Malformed prefix (link-local address)%s",
4163 VTY_NEWLINE);
4164 return CMD_WARNING;
4165 }
718e3744 4166
4167 apply_mask (&p);
4168
4169 /* Set BGP static route configuration. */
4170 rn = bgp_node_get (bgp->route[afi][safi], &p);
4171
4172 if (rn->info)
4173 {
4174 /* Configuration change. */
4175 bgp_static = rn->info;
4176
4177 /* Check previous routes are installed into BGP. */
c8f3fe30
PJ
4178 if (bgp_static->valid && bgp_static->backdoor != backdoor)
4179 need_update = 1;
41367172 4180
718e3744 4181 bgp_static->backdoor = backdoor;
41367172 4182
718e3744 4183 if (rmap)
4184 {
4185 if (bgp_static->rmap.name)
6e919709
DS
4186 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4187 bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
718e3744 4188 bgp_static->rmap.map = route_map_lookup_by_name (rmap);
4189 }
4190 else
4191 {
4192 if (bgp_static->rmap.name)
6e919709 4193 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
718e3744 4194 bgp_static->rmap.name = NULL;
4195 bgp_static->rmap.map = NULL;
4196 bgp_static->valid = 0;
4197 }
4198 bgp_unlock_node (rn);
4199 }
4200 else
4201 {
4202 /* New configuration. */
4203 bgp_static = bgp_static_new ();
4204 bgp_static->backdoor = backdoor;
4205 bgp_static->valid = 0;
4206 bgp_static->igpmetric = 0;
4207 bgp_static->igpnexthop.s_addr = 0;
41367172 4208
718e3744 4209 if (rmap)
4210 {
4211 if (bgp_static->rmap.name)
6e919709
DS
4212 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
4213 bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
718e3744 4214 bgp_static->rmap.map = route_map_lookup_by_name (rmap);
4215 }
4216 rn->info = bgp_static;
4217 }
4218
fc9a856f
DS
4219 bgp_static->valid = 1;
4220 if (need_update)
4221 bgp_static_withdraw (bgp, &p, afi, safi);
718e3744 4222
fc9a856f
DS
4223 if (! bgp_static->backdoor)
4224 bgp_static_update (bgp, &p, bgp_static, afi, safi);
718e3744 4225
4226 return CMD_SUCCESS;
4227}
4228
4229/* Configure static BGP network. */
94f2b392 4230static int
cdc2d765 4231bgp_static_unset (struct vty *vty, const char *ip_str,
4c9641ba 4232 afi_t afi, safi_t safi)
718e3744 4233{
cdc2d765 4234 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 4235 int ret;
4236 struct prefix p;
4237 struct bgp_static *bgp_static;
4238 struct bgp_node *rn;
4239
4240 /* Convert IP prefix string to struct prefix. */
4241 ret = str2prefix (ip_str, &p);
4242 if (! ret)
4243 {
4244 vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
4245 return CMD_WARNING;
4246 }
718e3744 4247 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
4248 {
4249 vty_out (vty, "%% Malformed prefix (link-local address)%s",
4250 VTY_NEWLINE);
4251 return CMD_WARNING;
4252 }
718e3744 4253
4254 apply_mask (&p);
4255
4256 rn = bgp_node_lookup (bgp->route[afi][safi], &p);
4257 if (! rn)
4258 {
4259 vty_out (vty, "%% Can't find specified static route configuration.%s",
4260 VTY_NEWLINE);
4261 return CMD_WARNING;
4262 }
4263
4264 bgp_static = rn->info;
41367172 4265
718e3744 4266 /* Update BGP RIB. */
4267 if (! bgp_static->backdoor)
4268 bgp_static_withdraw (bgp, &p, afi, safi);
4269
4270 /* Clear configuration. */
4271 bgp_static_free (bgp_static);
4272 rn->info = NULL;
4273 bgp_unlock_node (rn);
4274 bgp_unlock_node (rn);
4275
4276 return CMD_SUCCESS;
4277}
4278
6aeb9e78
DS
4279void
4280bgp_static_add (struct bgp *bgp)
4281{
4282 afi_t afi;
4283 safi_t safi;
4284 struct bgp_node *rn;
4285 struct bgp_node *rm;
4286 struct bgp_table *table;
4287 struct bgp_static *bgp_static;
4288
4289 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4290 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4291 for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
4292 if (rn->info != NULL)
4293 {
3d6c0dfa 4294 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN))
6aeb9e78
DS
4295 {
4296 table = rn->info;
4297
4298 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
4299 {
4300 bgp_static = rn->info;
137446f9 4301 bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi);
6aeb9e78
DS
4302 }
4303 }
4304 else
4305 {
4306 bgp_static_update (bgp, &rn->p, rn->info, afi, safi);
4307 }
4308 }
4309}
4310
718e3744 4311/* Called from bgp_delete(). Delete all static routes from the BGP
4312 instance. */
4313void
4314bgp_static_delete (struct bgp *bgp)
4315{
4316 afi_t afi;
4317 safi_t safi;
4318 struct bgp_node *rn;
4319 struct bgp_node *rm;
4320 struct bgp_table *table;
4321 struct bgp_static *bgp_static;
4322
4323 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4324 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4325 for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
4326 if (rn->info != NULL)
4327 {
3d6c0dfa 4328 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN))
718e3744 4329 {
4330 table = rn->info;
4331
4332 for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
4333 {
4334 bgp_static = rn->info;
137446f9
LB
4335 bgp_static_withdraw_safi (bgp, &rm->p,
4336 AFI_IP, safi,
718e3744 4337 (struct prefix_rd *)&rn->p,
4338 bgp_static->tag);
4339 bgp_static_free (bgp_static);
4340 rn->info = NULL;
4341 bgp_unlock_node (rn);
4342 }
4343 }
4344 else
4345 {
4346 bgp_static = rn->info;
4347 bgp_static_withdraw (bgp, &rn->p, afi, safi);
4348 bgp_static_free (bgp_static);
4349 rn->info = NULL;
4350 bgp_unlock_node (rn);
4351 }
4352 }
4353}
4354
078430f6
DS
4355void
4356bgp_static_redo_import_check (struct bgp *bgp)
4357{
4358 afi_t afi;
4359 safi_t safi;
4360 struct bgp_node *rn;
078430f6
DS
4361 struct bgp_static *bgp_static;
4362
4363 /* Use this flag to force reprocessing of the route */
4364 bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
4365 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4366 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4367 for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
4368 if (rn->info != NULL)
4369 {
4370 bgp_static = rn->info;
4371 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
4372 }
4373 bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
4374}
4375
ad4cbda1 4376static void
4377bgp_purge_af_static_redist_routes (struct bgp *bgp, afi_t afi, safi_t safi)
4378{
4379 struct bgp_table *table;
4380 struct bgp_node *rn;
4381 struct bgp_info *ri;
4382
4383 table = bgp->rib[afi][safi];
4384 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
4385 {
4386 for (ri = rn->info; ri; ri = ri->next)
4387 {
4388 if (ri->peer == bgp->peer_self &&
4389 ((ri->type == ZEBRA_ROUTE_BGP &&
4390 ri->sub_type == BGP_ROUTE_STATIC) ||
4391 (ri->type != ZEBRA_ROUTE_BGP &&
4392 ri->sub_type == BGP_ROUTE_REDISTRIBUTE)))
4393 {
4394 bgp_aggregate_decrement (bgp, &rn->p, ri, afi, safi);
4395 bgp_unlink_nexthop(ri);
4396 bgp_info_delete (rn, ri);
4397 bgp_process (bgp, rn, afi, safi);
4398 }
4399 }
4400 }
4401}
4402
4403/*
4404 * Purge all networks and redistributed routes from routing table.
4405 * Invoked upon the instance going down.
4406 */
4407void
4408bgp_purge_static_redist_routes (struct bgp *bgp)
4409{
4410 afi_t afi;
4411 safi_t safi;
4412
4413 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4414 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4415 bgp_purge_af_static_redist_routes (bgp, afi, safi);
4416}
4417
137446f9
LB
4418/*
4419 * gpz 110624
4420 * Currently this is used to set static routes for VPN and ENCAP.
4421 * I think it can probably be factored with bgp_static_set.
4422 */
718e3744 4423int
137446f9
LB
4424bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str,
4425 const char *rd_str, const char *tag_str,
4426 const char *rmap_str)
718e3744 4427{
cdc2d765 4428 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 4429 int ret;
4430 struct prefix p;
4431 struct prefix_rd prd;
718e3744 4432 struct bgp_node *prn;
4433 struct bgp_node *rn;
4434 struct bgp_table *table;
4435 struct bgp_static *bgp_static;
4436 u_char tag[3];
c286be96 4437 afi_t afi;
718e3744 4438
718e3744 4439 ret = str2prefix (ip_str, &p);
4440 if (! ret)
4441 {
4442 vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
4443 return CMD_WARNING;
4444 }
4445 apply_mask (&p);
4446
4447 ret = str2prefix_rd (rd_str, &prd);
4448 if (! ret)
4449 {
4450 vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE);
4451 return CMD_WARNING;
4452 }
4453
4454 ret = str2tag (tag_str, tag);
4455 if (! ret)
4456 {
4457 vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
4458 return CMD_WARNING;
4459 }
c286be96
LX
4460 if (p.family == AF_INET)
4461 afi = AFI_IP;
4462 else if (p.family == AF_INET6)
4463 afi = AFI_IP6;
4464 else
4465 {
4466 vty_out (vty, "%% Non Supported prefix%s", VTY_NEWLINE);
4467 return CMD_WARNING;
4468 }
4469 prn = bgp_node_get (bgp->route[afi][safi],
718e3744 4470 (struct prefix *)&prd);
4471 if (prn->info == NULL)
c286be96 4472 prn->info = bgp_table_init (afi, safi);
718e3744 4473 else
4474 bgp_unlock_node (prn);
4475 table = prn->info;
4476
4477 rn = bgp_node_get (table, &p);
4478
4479 if (rn->info)
4480 {
4481 vty_out (vty, "%% Same network configuration exists%s", VTY_NEWLINE);
4482 bgp_unlock_node (rn);
4483 }
4484 else
4485 {
4486 /* New configuration. */
4487 bgp_static = bgp_static_new ();
137446f9
LB
4488 bgp_static->backdoor = 0;
4489 bgp_static->valid = 0;
4490 bgp_static->igpmetric = 0;
4491 bgp_static->igpnexthop.s_addr = 0;
4492 memcpy(bgp_static->tag, tag, 3);
4493 bgp_static->prd = prd;
4494
4495 if (rmap_str)
4496 {
4497 if (bgp_static->rmap.name)
4498 free (bgp_static->rmap.name);
4499 bgp_static->rmap.name = strdup (rmap_str);
4500 bgp_static->rmap.map = route_map_lookup_by_name (rmap_str);
4501 }
718e3744 4502 rn->info = bgp_static;
4503
137446f9 4504 bgp_static->valid = 1;
c286be96 4505 bgp_static_update_safi (bgp, &p, bgp_static, afi, safi);
718e3744 4506 }
4507
4508 return CMD_SUCCESS;
4509}
4510
4511/* Configure static BGP network. */
4512int
137446f9
LB
4513bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str,
4514 const char *rd_str, const char *tag_str)
718e3744 4515{
cdc2d765 4516 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 4517 int ret;
718e3744 4518 struct prefix p;
4519 struct prefix_rd prd;
4520 struct bgp_node *prn;
4521 struct bgp_node *rn;
4522 struct bgp_table *table;
4523 struct bgp_static *bgp_static;
4524 u_char tag[3];
4525
718e3744 4526 /* Convert IP prefix string to struct prefix. */
4527 ret = str2prefix (ip_str, &p);
4528 if (! ret)
4529 {
4530 vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
4531 return CMD_WARNING;
4532 }
4533 apply_mask (&p);
4534
4535 ret = str2prefix_rd (rd_str, &prd);
4536 if (! ret)
4537 {
4538 vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE);
4539 return CMD_WARNING;
4540 }
4541
4542 ret = str2tag (tag_str, tag);
4543 if (! ret)
4544 {
4545 vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
4546 return CMD_WARNING;
4547 }
4548
137446f9 4549 prn = bgp_node_get (bgp->route[AFI_IP][safi],
718e3744 4550 (struct prefix *)&prd);
4551 if (prn->info == NULL)
137446f9 4552 prn->info = bgp_table_init (AFI_IP, safi);
718e3744 4553 else
4554 bgp_unlock_node (prn);
4555 table = prn->info;
4556
4557 rn = bgp_node_lookup (table, &p);
4558
4559 if (rn)
4560 {
137446f9 4561 bgp_static_withdraw_safi (bgp, &p, AFI_IP, safi, &prd, tag);
718e3744 4562
4563 bgp_static = rn->info;
4564 bgp_static_free (bgp_static);
4565 rn->info = NULL;
4566 bgp_unlock_node (rn);
4567 bgp_unlock_node (rn);
4568 }
4569 else
4570 vty_out (vty, "%% Can't find the route%s", VTY_NEWLINE);
4571
4572 return CMD_SUCCESS;
4573}
6b0655a2 4574
73ac8160 4575static int
cdc2d765 4576bgp_table_map_set (struct vty *vty, afi_t afi, safi_t safi,
73ac8160
DS
4577 const char *rmap_name)
4578{
cdc2d765 4579 VTY_DECLVAR_CONTEXT(bgp, bgp);
73ac8160
DS
4580 struct bgp_rmap *rmap;
4581
4582 rmap = &bgp->table_map[afi][safi];
4583 if (rmap_name)
4584 {
4585 if (rmap->name)
6e919709
DS
4586 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
4587 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
73ac8160
DS
4588 rmap->map = route_map_lookup_by_name (rmap_name);
4589 }
4590 else
4591 {
4592 if (rmap->name)
6e919709 4593 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
73ac8160
DS
4594 rmap->name = NULL;
4595 rmap->map = NULL;
4596 }
4597
4598 bgp_zebra_announce_table(bgp, afi, safi);
4599
4600 return CMD_SUCCESS;
4601}
4602
4603static int
cdc2d765 4604bgp_table_map_unset (struct vty *vty, afi_t afi, safi_t safi,
73ac8160
DS
4605 const char *rmap_name)
4606{
cdc2d765 4607 VTY_DECLVAR_CONTEXT(bgp, bgp);
73ac8160
DS
4608 struct bgp_rmap *rmap;
4609
4610 rmap = &bgp->table_map[afi][safi];
4611 if (rmap->name)
6e919709 4612 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
73ac8160
DS
4613 rmap->name = NULL;
4614 rmap->map = NULL;
4615
4616 bgp_zebra_announce_table(bgp, afi, safi);
4617
4618 return CMD_SUCCESS;
4619}
4620
4621int
4622bgp_config_write_table_map (struct vty *vty, struct bgp *bgp, afi_t afi,
4623 safi_t safi, int *write)
4624{
4625 if (bgp->table_map[afi][safi].name)
4626 {
4627 bgp_config_write_family_header (vty, afi, safi, write);
0b960b4d 4628 vty_out (vty, " table-map %s%s",
73ac8160
DS
4629 bgp->table_map[afi][safi].name, VTY_NEWLINE);
4630 }
4631
4632 return 0;
4633}
4634
73ac8160
DS
4635DEFUN (bgp_table_map,
4636 bgp_table_map_cmd,
4637 "table-map WORD",
4638 "BGP table to RIB route download filter\n"
4639 "Name of the route map\n")
4640{
c500ae40 4641 int idx_word = 1;
cdc2d765 4642 return bgp_table_map_set (vty,
c500ae40 4643 bgp_node_afi (vty), bgp_node_safi (vty), argv[idx_word]->arg);
73ac8160
DS
4644}
4645DEFUN (no_bgp_table_map,
4646 no_bgp_table_map_cmd,
4647 "no table-map WORD",
3a2d747c 4648 NO_STR
73ac8160
DS
4649 "BGP table to RIB route download filter\n"
4650 "Name of the route map\n")
4651{
c500ae40 4652 int idx_word = 2;
cdc2d765 4653 return bgp_table_map_unset (vty,
c500ae40 4654 bgp_node_afi (vty), bgp_node_safi (vty), argv[idx_word]->arg);
73ac8160
DS
4655}
4656
718e3744 4657DEFUN (bgp_network,
4658 bgp_network_cmd,
4659 "network A.B.C.D/M",
4660 "Specify a network to announce via BGP\n"
0c7b1b01 4661 "IPv4 prefix\n")
718e3744 4662{
c500ae40 4663 int idx_ipv4_prefixlen = 1;
cdc2d765 4664 return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg,
c8f3fe30 4665 AFI_IP, bgp_node_safi (vty), NULL, 0);
718e3744 4666}
4667
4668DEFUN (bgp_network_route_map,
4669 bgp_network_route_map_cmd,
4670 "network A.B.C.D/M route-map WORD",
4671 "Specify a network to announce via BGP\n"
0c7b1b01 4672 "IPv4 prefix\n"
718e3744 4673 "Route-map to modify the attributes\n"
4674 "Name of the route map\n")
4675{
c500ae40
DW
4676 int idx_ipv4_prefixlen = 1;
4677 int idx_word = 3;
cdc2d765 4678 return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg,
c500ae40 4679 AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
718e3744 4680}
4681
4682DEFUN (bgp_network_backdoor,
4683 bgp_network_backdoor_cmd,
4684 "network A.B.C.D/M backdoor",
4685 "Specify a network to announce via BGP\n"
0c7b1b01 4686 "IPv4 prefix\n"
718e3744 4687 "Specify a BGP backdoor route\n")
4688{
c500ae40 4689 int idx_ipv4_prefixlen = 1;
cdc2d765 4690 return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, SAFI_UNICAST,
c8f3fe30 4691 NULL, 1);
718e3744 4692}
4693
4694DEFUN (bgp_network_mask,
4695 bgp_network_mask_cmd,
4696 "network A.B.C.D mask A.B.C.D",
4697 "Specify a network to announce via BGP\n"
4698 "Network number\n"
4699 "Network mask\n"
4700 "Network mask\n")
4701{
c500ae40
DW
4702 int idx_ipv4 = 1;
4703 int idx_ipv4_2 = 3;
718e3744 4704 int ret;
4705 char prefix_str[BUFSIZ];
41367172 4706
c500ae40 4707 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str);
718e3744 4708 if (! ret)
4709 {
4710 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4711 return CMD_WARNING;
4712 }
4713
cdc2d765 4714 return bgp_static_set (vty, prefix_str,
c8f3fe30 4715 AFI_IP, bgp_node_safi (vty), NULL, 0);
718e3744 4716}
4717
4718DEFUN (bgp_network_mask_route_map,
4719 bgp_network_mask_route_map_cmd,
4720 "network A.B.C.D mask A.B.C.D route-map WORD",
4721 "Specify a network to announce via BGP\n"
4722 "Network number\n"
4723 "Network mask\n"
4724 "Network mask\n"
4725 "Route-map to modify the attributes\n"
4726 "Name of the route map\n")
4727{
c500ae40
DW
4728 int idx_ipv4 = 1;
4729 int idx_ipv4_2 = 3;
4730 int idx_word = 5;
718e3744 4731 int ret;
4732 char prefix_str[BUFSIZ];
41367172 4733
c500ae40 4734 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str);
718e3744 4735 if (! ret)
4736 {
4737 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4738 return CMD_WARNING;
4739 }
4740
cdc2d765 4741 return bgp_static_set (vty, prefix_str,
c500ae40 4742 AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
718e3744 4743}
4744
4745DEFUN (bgp_network_mask_backdoor,
4746 bgp_network_mask_backdoor_cmd,
4747 "network A.B.C.D mask A.B.C.D backdoor",
4748 "Specify a network to announce via BGP\n"
4749 "Network number\n"
4750 "Network mask\n"
4751 "Network mask\n"
4752 "Specify a BGP backdoor route\n")
4753{
c500ae40
DW
4754 int idx_ipv4 = 1;
4755 int idx_ipv4_2 = 3;
718e3744 4756 int ret;
4757 char prefix_str[BUFSIZ];
41367172 4758
c500ae40 4759 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str);
718e3744 4760 if (! ret)
4761 {
4762 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4763 return CMD_WARNING;
4764 }
4765
cdc2d765 4766 return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST,
c8f3fe30 4767 NULL, 1);
718e3744 4768}
4769
4770DEFUN (bgp_network_mask_natural,
4771 bgp_network_mask_natural_cmd,
4772 "network A.B.C.D",
4773 "Specify a network to announce via BGP\n"
4774 "Network number\n")
4775{
c500ae40 4776 int idx_ipv4 = 1;
718e3744 4777 int ret;
4778 char prefix_str[BUFSIZ];
4779
c500ae40 4780 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str);
718e3744 4781 if (! ret)
4782 {
4783 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4784 return CMD_WARNING;
4785 }
4786
cdc2d765 4787 return bgp_static_set (vty, prefix_str,
c8f3fe30 4788 AFI_IP, bgp_node_safi (vty), NULL, 0);
718e3744 4789}
4790
4791DEFUN (bgp_network_mask_natural_route_map,
4792 bgp_network_mask_natural_route_map_cmd,
4793 "network A.B.C.D route-map WORD",
4794 "Specify a network to announce via BGP\n"
4795 "Network number\n"
4796 "Route-map to modify the attributes\n"
4797 "Name of the route map\n")
4798{
c500ae40
DW
4799 int idx_ipv4 = 1;
4800 int idx_word = 3;
718e3744 4801 int ret;
4802 char prefix_str[BUFSIZ];
4803
c500ae40 4804 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str);
718e3744 4805 if (! ret)
4806 {
4807 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4808 return CMD_WARNING;
4809 }
4810
cdc2d765 4811 return bgp_static_set (vty, prefix_str,
c500ae40 4812 AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
718e3744 4813}
4814
4815DEFUN (bgp_network_mask_natural_backdoor,
4816 bgp_network_mask_natural_backdoor_cmd,
4817 "network A.B.C.D backdoor",
4818 "Specify a network to announce via BGP\n"
4819 "Network number\n"
4820 "Specify a BGP backdoor route\n")
4821{
c500ae40 4822 int idx_ipv4 = 1;
718e3744 4823 int ret;
4824 char prefix_str[BUFSIZ];
4825
c500ae40 4826 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str);
718e3744 4827 if (! ret)
4828 {
4829 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4830 return CMD_WARNING;
4831 }
4832
cdc2d765 4833 return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST,
c8f3fe30 4834 NULL, 1);
718e3744 4835}
4836
4837DEFUN (no_bgp_network,
4838 no_bgp_network_cmd,
a636c635 4839 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
718e3744 4840 NO_STR
4841 "Specify a network to announce via BGP\n"
0c7b1b01 4842 "IPv4 prefix\n"
a636c635
DW
4843 "Specify a BGP backdoor route\n"
4844 "Route-map to modify the attributes\n"
4845 "Name of the route map\n")
718e3744 4846{
c500ae40 4847 int idx_ipv4_prefixlen = 2;
cdc2d765 4848 return bgp_static_unset (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
718e3744 4849 bgp_node_safi (vty));
4850}
4851
718e3744 4852DEFUN (no_bgp_network_mask,
4853 no_bgp_network_mask_cmd,
a636c635 4854 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
718e3744 4855 NO_STR
4856 "Specify a network to announce via BGP\n"
4857 "Network number\n"
4858 "Network mask\n"
a636c635
DW
4859 "Network mask\n"
4860 "Specify a BGP backdoor route\n"
4861 "Route-map to modify the attributes\n"
4862 "Name of the route map\n")
718e3744 4863{
c500ae40
DW
4864 int idx_ipv4 = 2;
4865 int idx_ipv4_2 = 4;
718e3744 4866 int ret;
4867 char prefix_str[BUFSIZ];
4868
c500ae40 4869 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str);
718e3744 4870 if (! ret)
4871 {
4872 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4873 return CMD_WARNING;
4874 }
4875
cdc2d765 4876 return bgp_static_unset (vty, prefix_str, AFI_IP,
718e3744 4877 bgp_node_safi (vty));
4878}
4879
718e3744 4880DEFUN (no_bgp_network_mask_natural,
4881 no_bgp_network_mask_natural_cmd,
a636c635 4882 "no network A.B.C.D [<backdoor|route-map WORD>]",
718e3744 4883 NO_STR
4884 "Specify a network to announce via BGP\n"
a636c635
DW
4885 "Network number\n"
4886 "Specify a BGP backdoor route\n"
4887 "Route-map to modify the attributes\n"
4888 "Name of the route map\n")
718e3744 4889{
c500ae40 4890 int idx_ipv4 = 2;
718e3744 4891 int ret;
4892 char prefix_str[BUFSIZ];
4893
c500ae40 4894 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str);
718e3744 4895 if (! ret)
4896 {
4897 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
4898 return CMD_WARNING;
4899 }
4900
cdc2d765 4901 return bgp_static_unset (vty, prefix_str, AFI_IP,
718e3744 4902 bgp_node_safi (vty));
4903}
4904
718e3744 4905DEFUN (ipv6_bgp_network,
4906 ipv6_bgp_network_cmd,
4907 "network X:X::X:X/M",
4908 "Specify a network to announce via BGP\n"
0c7b1b01 4909 "IPv6 prefix\n")
718e3744 4910{
c500ae40 4911 int idx_ipv6_prefixlen = 1;
cdc2d765 4912 return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty),
c8f3fe30 4913 NULL, 0);
718e3744 4914}
4915
4916DEFUN (ipv6_bgp_network_route_map,
4917 ipv6_bgp_network_route_map_cmd,
4918 "network X:X::X:X/M route-map WORD",
4919 "Specify a network to announce via BGP\n"
0c7b1b01 4920 "IPv6 prefix\n"
718e3744 4921 "Route-map to modify the attributes\n"
4922 "Name of the route map\n")
4923{
c500ae40
DW
4924 int idx_ipv6_prefixlen = 1;
4925 int idx_word = 3;
cdc2d765 4926 return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
c500ae40 4927 bgp_node_safi (vty), argv[idx_word]->arg, 0);
718e3744 4928}
4929
4930DEFUN (no_ipv6_bgp_network,
4931 no_ipv6_bgp_network_cmd,
a636c635 4932 "no network X:X::X:X/M [route-map WORD]",
718e3744 4933 NO_STR
4934 "Specify a network to announce via BGP\n"
0c7b1b01 4935 "IPv6 prefix\n"
a636c635
DW
4936 "Route-map to modify the attributes\n"
4937 "Name of the route map\n")
718e3744 4938{
c500ae40 4939 int idx_ipv6_prefixlen = 2;
cdc2d765 4940 return bgp_static_unset (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty));
718e3744 4941}
4942
718e3744 4943/* Aggreagete address:
4944
4945 advertise-map Set condition to advertise attribute
4946 as-set Generate AS set path information
4947 attribute-map Set attributes of aggregate
4948 route-map Set parameters of aggregate
4949 summary-only Filter more specific routes from updates
4950 suppress-map Conditionally filter more specific routes from updates
4951 <cr>
4952 */
4953struct bgp_aggregate
4954{
4955 /* Summary-only flag. */
4956 u_char summary_only;
4957
4958 /* AS set generation. */
4959 u_char as_set;
4960
4961 /* Route-map for aggregated route. */
4962 struct route_map *map;
4963
4964 /* Suppress-count. */
4965 unsigned long count;
4966
4967 /* SAFI configuration. */
4968 safi_t safi;
4969};
4970
94f2b392 4971static struct bgp_aggregate *
66e5cd87 4972bgp_aggregate_new (void)
718e3744 4973{
393deb9b 4974 return XCALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
718e3744 4975}
4976
94f2b392 4977static void
718e3744 4978bgp_aggregate_free (struct bgp_aggregate *aggregate)
4979{
4980 XFREE (MTYPE_BGP_AGGREGATE, aggregate);
4981}
4982
b5d58c32 4983/* Update an aggregate as routes are added/removed from the BGP table */
94f2b392 4984static void
718e3744 4985bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
4986 afi_t afi, safi_t safi, struct bgp_info *del,
4987 struct bgp_aggregate *aggregate)
4988{
4989 struct bgp_table *table;
4990 struct bgp_node *top;
4991 struct bgp_node *rn;
4992 u_char origin;
4993 struct aspath *aspath = NULL;
4994 struct aspath *asmerge = NULL;
4995 struct community *community = NULL;
4996 struct community *commerge = NULL;
ffd0c037 4997#if defined(AGGREGATE_NEXTHOP_CHECK)
718e3744 4998 struct in_addr nexthop;
4999 u_int32_t med = 0;
ffd0c037 5000#endif
718e3744 5001 struct bgp_info *ri;
5002 struct bgp_info *new;
5003 int first = 1;
5004 unsigned long match = 0;
42f7e184 5005 u_char atomic_aggregate = 0;
718e3744 5006
5007 /* Record adding route's nexthop and med. */
ffd0c037
DS
5008 if (rinew)
5009 {
5010#if defined(AGGREGATE_NEXTHOP_CHECK)
5011 nexthop = rinew->attr->nexthop;
5012 med = rinew->attr->med;
5013#endif
5014 }
718e3744 5015
5016 /* ORIGIN attribute: If at least one route among routes that are
5017 aggregated has ORIGIN with the value INCOMPLETE, then the
5018 aggregated route must have the ORIGIN attribute with the value
5019 INCOMPLETE. Otherwise, if at least one route among routes that
5020 are aggregated has ORIGIN with the value EGP, then the aggregated
5021 route must have the origin attribute with the value EGP. In all
5022 other case the value of the ORIGIN attribute of the aggregated
5023 route is INTERNAL. */
5024 origin = BGP_ORIGIN_IGP;
5025
5026 table = bgp->rib[afi][safi];
5027
5028 top = bgp_node_get (table, p);
5029 for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
5030 if (rn->p.prefixlen > p->prefixlen)
5031 {
5032 match = 0;
5033
5034 for (ri = rn->info; ri; ri = ri->next)
5035 {
5036 if (BGP_INFO_HOLDDOWN (ri))
5037 continue;
5038
5039 if (del && ri == del)
5040 continue;
5041
5042 if (! rinew && first)
5043 {
ffd0c037 5044#if defined(AGGREGATE_NEXTHOP_CHECK)
718e3744 5045 nexthop = ri->attr->nexthop;
5046 med = ri->attr->med;
ffd0c037 5047#endif
718e3744 5048 first = 0;
5049 }
5050
5051#ifdef AGGREGATE_NEXTHOP_CHECK
5052 if (! IPV4_ADDR_SAME (&ri->attr->nexthop, &nexthop)
5053 || ri->attr->med != med)
5054 {
5055 if (aspath)
5056 aspath_free (aspath);
5057 if (community)
5058 community_free (community);
5059 bgp_unlock_node (rn);
5060 bgp_unlock_node (top);
5061 return;
5062 }
5063#endif /* AGGREGATE_NEXTHOP_CHECK */
5064
42f7e184
DS
5065 if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5066 atomic_aggregate = 1;
5067
718e3744 5068 if (ri->sub_type != BGP_ROUTE_AGGREGATE)
5069 {
5070 if (aggregate->summary_only)
5071 {
fb982c25 5072 (bgp_info_extra_get (ri))->suppress++;
1a392d46 5073 bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
718e3744 5074 match++;
5075 }
5076
5077 aggregate->count++;
5078
b5d58c32
DS
5079 if (origin < ri->attr->origin)
5080 origin = ri->attr->origin;
5081
718e3744 5082 if (aggregate->as_set)
5083 {
718e3744 5084 if (aspath)
5085 {
5086 asmerge = aspath_aggregate (aspath, ri->attr->aspath);
5087 aspath_free (aspath);
5088 aspath = asmerge;
5089 }
5090 else
5091 aspath = aspath_dup (ri->attr->aspath);
5092
5093 if (ri->attr->community)
5094 {
5095 if (community)
5096 {
5097 commerge = community_merge (community,
5098 ri->attr->community);
5099 community = community_uniq_sort (commerge);
5100 community_free (commerge);
5101 }
5102 else
5103 community = community_dup (ri->attr->community);
5104 }
5105 }
5106 }
5107 }
5108 if (match)
5109 bgp_process (bgp, rn, afi, safi);
5110 }
5111 bgp_unlock_node (top);
5112
5113 if (rinew)
5114 {
5115 aggregate->count++;
5116
5117 if (aggregate->summary_only)
fb982c25 5118 (bgp_info_extra_get (rinew))->suppress++;
718e3744 5119
b5d58c32
DS
5120 if (origin < rinew->attr->origin)
5121 origin = rinew->attr->origin;
5122
718e3744 5123 if (aggregate->as_set)
5124 {
718e3744 5125 if (aspath)
5126 {
5127 asmerge = aspath_aggregate (aspath, rinew->attr->aspath);
5128 aspath_free (aspath);
5129 aspath = asmerge;
5130 }
5131 else
5132 aspath = aspath_dup (rinew->attr->aspath);
5133
5134 if (rinew->attr->community)
5135 {
5136 if (community)
5137 {
5138 commerge = community_merge (community,
5139 rinew->attr->community);
5140 community = community_uniq_sort (commerge);
5141 community_free (commerge);
5142 }
5143 else
5144 community = community_dup (rinew->attr->community);
5145 }
5146 }
5147 }
5148
5149 if (aggregate->count > 0)
5150 {
5151 rn = bgp_node_get (table, p);
7c8ff89e 5152 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
fb018d25 5153 bgp_attr_aggregate_intern(bgp, origin, aspath, community,
42f7e184
DS
5154 aggregate->as_set,
5155 atomic_aggregate), rn);
718e3744 5156 SET_FLAG (new->flags, BGP_INFO_VALID);
718e3744 5157
5158 bgp_info_add (rn, new);
200df115 5159 bgp_unlock_node (rn);
718e3744 5160 bgp_process (bgp, rn, afi, safi);
5161 }
5162 else
5163 {
5164 if (aspath)
5165 aspath_free (aspath);
5166 if (community)
5167 community_free (community);
5168 }
5169}
5170
5171void bgp_aggregate_delete (struct bgp *, struct prefix *, afi_t, safi_t,
5172 struct bgp_aggregate *);
5173
5174void
5175bgp_aggregate_increment (struct bgp *bgp, struct prefix *p,
5176 struct bgp_info *ri, afi_t afi, safi_t safi)
5177{
5178 struct bgp_node *child;
5179 struct bgp_node *rn;
5180 struct bgp_aggregate *aggregate;
f018db83 5181 struct bgp_table *table;
718e3744 5182
5183 /* MPLS-VPN aggregation is not yet supported. */
3d6c0dfa 5184 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi = SAFI_EVPN))
718e3744 5185 return;
5186
f018db83
JBD
5187 table = bgp->aggregate[afi][safi];
5188
5189 /* No aggregates configured. */
67174041 5190 if (bgp_table_top_nolock (table) == NULL)
f018db83
JBD
5191 return;
5192
718e3744 5193 if (p->prefixlen == 0)
5194 return;
5195
5196 if (BGP_INFO_HOLDDOWN (ri))
5197 return;
5198
bb782fb5 5199 child = bgp_node_get (table, p);
718e3744 5200
5201 /* Aggregate address configuration check. */
67174041 5202 for (rn = child; rn; rn = bgp_node_parent_nolock (rn))
718e3744 5203 if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen)
5204 {
5205 bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate);
286e1e71 5206 bgp_aggregate_route (bgp, &rn->p, ri, afi, safi, NULL, aggregate);
718e3744 5207 }
5208 bgp_unlock_node (child);
5209}
5210
5211void
5212bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p,
5213 struct bgp_info *del, afi_t afi, safi_t safi)
5214{
5215 struct bgp_node *child;
5216 struct bgp_node *rn;
5217 struct bgp_aggregate *aggregate;
f018db83 5218 struct bgp_table *table;
718e3744 5219
5220 /* MPLS-VPN aggregation is not yet supported. */
3d6c0dfa 5221 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi = SAFI_EVPN))
718e3744 5222 return;
5223
f018db83
JBD
5224 table = bgp->aggregate[afi][safi];
5225
5226 /* No aggregates configured. */
67174041 5227 if (bgp_table_top_nolock (table) == NULL)
f018db83
JBD
5228 return;
5229
718e3744 5230 if (p->prefixlen == 0)
5231 return;
5232
bb782fb5 5233 child = bgp_node_get (table, p);
718e3744 5234
5235 /* Aggregate address configuration check. */
67174041 5236 for (rn = child; rn; rn = bgp_node_parent_nolock (rn))
718e3744 5237 if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen)
5238 {
5239 bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate);
286e1e71 5240 bgp_aggregate_route (bgp, &rn->p, NULL, afi, safi, del, aggregate);
718e3744 5241 }
5242 bgp_unlock_node (child);
5243}
5244
b5d58c32 5245/* Called via bgp_aggregate_set when the user configures aggregate-address */
94f2b392 5246static void
718e3744 5247bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
5248 struct bgp_aggregate *aggregate)
5249{
5250 struct bgp_table *table;
5251 struct bgp_node *top;
5252 struct bgp_node *rn;
5253 struct bgp_info *new;
5254 struct bgp_info *ri;
5255 unsigned long match;
5256 u_char origin = BGP_ORIGIN_IGP;
5257 struct aspath *aspath = NULL;
5258 struct aspath *asmerge = NULL;
5259 struct community *community = NULL;
5260 struct community *commerge = NULL;
42f7e184 5261 u_char atomic_aggregate = 0;
718e3744 5262
5263 table = bgp->rib[afi][safi];
5264
5265 /* Sanity check. */
5266 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5267 return;
5268 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5269 return;
5270
5271 /* If routes exists below this node, generate aggregate routes. */
5272 top = bgp_node_get (table, p);
5273 for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
5274 if (rn->p.prefixlen > p->prefixlen)
5275 {
5276 match = 0;
5277
5278 for (ri = rn->info; ri; ri = ri->next)
5279 {
5280 if (BGP_INFO_HOLDDOWN (ri))
5281 continue;
5282
42f7e184
DS
5283 if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
5284 atomic_aggregate = 1;
5285
718e3744 5286 if (ri->sub_type != BGP_ROUTE_AGGREGATE)
5287 {
5288 /* summary-only aggregate route suppress aggregated
5289 route announcement. */
5290 if (aggregate->summary_only)
5291 {
fb982c25 5292 (bgp_info_extra_get (ri))->suppress++;
1a392d46 5293 bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
718e3744 5294 match++;
5295 }
b5d58c32
DS
5296
5297 /* If at least one route among routes that are aggregated has
5298 * ORIGIN with the value INCOMPLETE, then the aggregated route
5299 * MUST have the ORIGIN attribute with the value INCOMPLETE.
5300 * Otherwise, if at least one route among routes that are
5301 * aggregated has ORIGIN with the value EGP, then the aggregated
5302 * route MUST have the ORIGIN attribute with the value EGP.
5303 */
5304 if (origin < ri->attr->origin)
5305 origin = ri->attr->origin;
5306
718e3744 5307 /* as-set aggregate route generate origin, as path,
5308 community aggregation. */
5309 if (aggregate->as_set)
5310 {
718e3744 5311 if (aspath)
5312 {
5313 asmerge = aspath_aggregate (aspath, ri->attr->aspath);
5314 aspath_free (aspath);
5315 aspath = asmerge;
5316 }
5317 else
5318 aspath = aspath_dup (ri->attr->aspath);
5319
5320 if (ri->attr->community)
5321 {
5322 if (community)
5323 {
5324 commerge = community_merge (community,
5325 ri->attr->community);
5326 community = community_uniq_sort (commerge);
5327 community_free (commerge);
5328 }
5329 else
5330 community = community_dup (ri->attr->community);
5331 }
5332 }
5333 aggregate->count++;
5334 }
5335 }
5336
5337 /* If this node is suppressed, process the change. */
5338 if (match)
5339 bgp_process (bgp, rn, afi, safi);
5340 }
5341 bgp_unlock_node (top);
5342
5343 /* Add aggregate route to BGP table. */
5344 if (aggregate->count)
5345 {
5346 rn = bgp_node_get (table, p);
7c8ff89e 5347 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self,
fb018d25 5348 bgp_attr_aggregate_intern(bgp, origin, aspath, community,
42f7e184
DS
5349 aggregate->as_set,
5350 atomic_aggregate), rn);
718e3744 5351 SET_FLAG (new->flags, BGP_INFO_VALID);
718e3744 5352
5353 bgp_info_add (rn, new);
200df115 5354 bgp_unlock_node (rn);
5355
718e3744 5356 /* Process change. */
5357 bgp_process (bgp, rn, afi, safi);
5358 }
610f23cf
DV
5359 else
5360 {
5361 if (aspath)
5362 aspath_free (aspath);
5363 if (community)
5364 community_free (community);
5365 }
718e3744 5366}
5367
5368void
5369bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
5370 safi_t safi, struct bgp_aggregate *aggregate)
5371{
5372 struct bgp_table *table;
5373 struct bgp_node *top;
5374 struct bgp_node *rn;
5375 struct bgp_info *ri;
5376 unsigned long match;
5377
5378 table = bgp->rib[afi][safi];
5379
5380 if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
5381 return;
5382 if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
5383 return;
5384
5385 /* If routes exists below this node, generate aggregate routes. */
5386 top = bgp_node_get (table, p);
5387 for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
5388 if (rn->p.prefixlen > p->prefixlen)
5389 {
5390 match = 0;
5391
5392 for (ri = rn->info; ri; ri = ri->next)
5393 {
5394 if (BGP_INFO_HOLDDOWN (ri))
5395 continue;
5396
5397 if (ri->sub_type != BGP_ROUTE_AGGREGATE)
5398 {
fb982c25 5399 if (aggregate->summary_only && ri->extra)
718e3744 5400 {
fb982c25 5401 ri->extra->suppress--;
718e3744 5402
fb982c25 5403 if (ri->extra->suppress == 0)
718e3744 5404 {
1a392d46 5405 bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
718e3744 5406 match++;
5407 }
5408 }
5409 aggregate->count--;
5410 }
5411 }
5412
fb982c25 5413 /* If this node was suppressed, process the change. */
718e3744 5414 if (match)
5415 bgp_process (bgp, rn, afi, safi);
5416 }
5417 bgp_unlock_node (top);
5418
5419 /* Delete aggregate route from BGP table. */
5420 rn = bgp_node_get (table, p);
5421
5422 for (ri = rn->info; ri; ri = ri->next)
5423 if (ri->peer == bgp->peer_self
5424 && ri->type == ZEBRA_ROUTE_BGP
5425 && ri->sub_type == BGP_ROUTE_AGGREGATE)
5426 break;
5427
5428 /* Withdraw static BGP route from routing table. */
5429 if (ri)
5430 {
718e3744 5431 bgp_info_delete (rn, ri);
1a392d46 5432 bgp_process (bgp, rn, afi, safi);
718e3744 5433 }
5434
5435 /* Unlock bgp_node_lookup. */
5436 bgp_unlock_node (rn);
5437}
5438
5439/* Aggregate route attribute. */
5440#define AGGREGATE_SUMMARY_ONLY 1
5441#define AGGREGATE_AS_SET 1
5442
94f2b392 5443static int
f6269b4f
RB
5444bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
5445 afi_t afi, safi_t safi)
718e3744 5446{
cdc2d765 5447 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 5448 int ret;
5449 struct prefix p;
5450 struct bgp_node *rn;
718e3744 5451 struct bgp_aggregate *aggregate;
5452
5453 /* Convert string to prefix structure. */
5454 ret = str2prefix (prefix_str, &p);
5455 if (!ret)
5456 {
5457 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
5458 return CMD_WARNING;
5459 }
5460 apply_mask (&p);
5461
718e3744 5462 /* Old configuration check. */
f6269b4f
RB
5463 rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
5464 if (! rn)
718e3744 5465 {
f6269b4f
RB
5466 vty_out (vty, "%% There is no aggregate-address configuration.%s",
5467 VTY_NEWLINE);
718e3744 5468 return CMD_WARNING;
5469 }
5470
f6269b4f
RB
5471 aggregate = rn->info;
5472 if (aggregate->safi & SAFI_UNICAST)
5473 bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
5474 if (aggregate->safi & SAFI_MULTICAST)
5475 bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
718e3744 5476
f6269b4f
RB
5477 /* Unlock aggregate address configuration. */
5478 rn->info = NULL;
5479 bgp_aggregate_free (aggregate);
5480 bgp_unlock_node (rn);
5481 bgp_unlock_node (rn);
718e3744 5482
5483 return CMD_SUCCESS;
5484}
5485
94f2b392 5486static int
f6269b4f
RB
5487bgp_aggregate_set (struct vty *vty, const char *prefix_str,
5488 afi_t afi, safi_t safi,
5489 u_char summary_only, u_char as_set)
718e3744 5490{
cdc2d765 5491 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 5492 int ret;
5493 struct prefix p;
5494 struct bgp_node *rn;
718e3744 5495 struct bgp_aggregate *aggregate;
5496
5497 /* Convert string to prefix structure. */
5498 ret = str2prefix (prefix_str, &p);
5499 if (!ret)
5500 {
5501 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
5502 return CMD_WARNING;
5503 }
5504 apply_mask (&p);
5505
718e3744 5506 /* Old configuration check. */
f6269b4f
RB
5507 rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
5508
5509 if (rn->info)
718e3744 5510 {
f6269b4f 5511 vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
368473f6 5512 /* try to remove the old entry */
f6269b4f
RB
5513 ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
5514 if (ret)
5515 {
368473f6
RB
5516 vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE);
5517 bgp_unlock_node (rn);
f6269b4f
RB
5518 return CMD_WARNING;
5519 }
718e3744 5520 }
5521
f6269b4f
RB
5522 /* Make aggregate address structure. */
5523 aggregate = bgp_aggregate_new ();
5524 aggregate->summary_only = summary_only;
5525 aggregate->as_set = as_set;
5526 aggregate->safi = safi;
5527 rn->info = aggregate;
718e3744 5528
f6269b4f
RB
5529 /* Aggregate address insert into BGP routing table. */
5530 if (safi & SAFI_UNICAST)
5531 bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
5532 if (safi & SAFI_MULTICAST)
5533 bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
718e3744 5534
5535 return CMD_SUCCESS;
5536}
5537
5538DEFUN (aggregate_address,
5539 aggregate_address_cmd,
e3e6107d 5540 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5541 "Configure BGP aggregate entries\n"
5542 "Aggregate prefix\n"
5543 "Generate AS set path information\n"
a636c635
DW
5544 "Filter more specific routes from updates\n"
5545 "Filter more specific routes from updates\n"
5546 "Generate AS set path information\n")
718e3744 5547{
e3e6107d
QY
5548 int idx = 0;
5549 argv_find (argv, argc, "A.B.C.D/M", &idx);
5550 char *prefix = argv[idx]->arg;
5551 int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5552 idx = 0;
5553 int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0;
5554
5555 return bgp_aggregate_set (vty, prefix, AFI_IP, bgp_node_safi (vty), summary_only, as_set);
718e3744 5556}
5557
e3e6107d
QY
5558DEFUN (aggregate_address_mask,
5559 aggregate_address_mask_cmd,
5560 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5561 "Configure BGP aggregate entries\n"
5562 "Aggregate address\n"
5563 "Aggregate mask\n"
5564 "Generate AS set path information\n"
a636c635
DW
5565 "Filter more specific routes from updates\n"
5566 "Filter more specific routes from updates\n"
5567 "Generate AS set path information\n")
718e3744 5568{
e3e6107d
QY
5569 int idx = 0;
5570 argv_find (argv, argc, "A.B.C.D", &idx);
921e4a7c 5571 char *prefix = argv[idx++]->arg;
e3e6107d
QY
5572 argv_find (argv, argc, "A.B.C.D", &idx);
5573 char *mask = argv[idx]->arg;
5574 int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
5575 idx = 0;
5576 int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0;
718e3744 5577
e3e6107d
QY
5578 char prefix_str[BUFSIZ];
5579 int ret = netmask_str2prefix_str (prefix, mask, prefix_str);
718e3744 5580
5581 if (! ret)
5582 {
5583 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
5584 return CMD_WARNING;
5585 }
5586
e3e6107d 5587 return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), summary_only, as_set);
718e3744 5588}
5589
718e3744 5590DEFUN (no_aggregate_address,
5591 no_aggregate_address_cmd,
e3e6107d 5592 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5593 NO_STR
5594 "Configure BGP aggregate entries\n"
a636c635
DW
5595 "Aggregate prefix\n"
5596 "Generate AS set path information\n"
e3e6107d
QY
5597 "Filter more specific routes from updates\n"
5598 "Filter more specific routes from updates\n"
5599 "Generate AS set path information\n")
718e3744 5600{
e3e6107d
QY
5601 int idx = 0;
5602 argv_find (argv, argc, "A.B.C.D/M", &idx);
5603 char *prefix = argv[idx]->arg;
5604 return bgp_aggregate_unset (vty, prefix, AFI_IP, bgp_node_safi (vty));
718e3744 5605}
5606
718e3744 5607DEFUN (no_aggregate_address_mask,
5608 no_aggregate_address_mask_cmd,
e3e6107d 5609 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
718e3744 5610 NO_STR
5611 "Configure BGP aggregate entries\n"
5612 "Aggregate address\n"
a636c635
DW
5613 "Aggregate mask\n"
5614 "Generate AS set path information\n"
e3e6107d
QY
5615 "Filter more specific routes from updates\n"
5616 "Filter more specific routes from updates\n"
5617 "Generate AS set path information\n")
718e3744 5618{
e3e6107d
QY
5619 int idx = 0;
5620 argv_find (argv, argc, "A.B.C.D", &idx);
921e4a7c 5621 char *prefix = argv[idx++]->arg;
e3e6107d
QY
5622 argv_find (argv, argc, "A.B.C.D", &idx);
5623 char *mask = argv[idx]->arg;
718e3744 5624
e3e6107d
QY
5625 char prefix_str[BUFSIZ];
5626 int ret = netmask_str2prefix_str (prefix, mask, prefix_str);
718e3744 5627
5628 if (! ret)
5629 {
5630 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
5631 return CMD_WARNING;
5632 }
5633
5634 return bgp_aggregate_unset (vty, prefix_str, AFI_IP, bgp_node_safi (vty));
5635}
5636
718e3744 5637DEFUN (ipv6_aggregate_address,
5638 ipv6_aggregate_address_cmd,
e3e6107d 5639 "aggregate-address X:X::X:X/M [summary-only]",
718e3744 5640 "Configure BGP aggregate entries\n"
5641 "Aggregate prefix\n"
5642 "Filter more specific routes from updates\n")
5643{
e3e6107d
QY
5644 int idx = 0;
5645 argv_find (argv, argc, "X:X::X:X/M", &idx);
5646 char *prefix = argv[idx]->arg;
5647 int sum_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0;
5648 return bgp_aggregate_set (vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only, 0);
718e3744 5649}
5650
5651DEFUN (no_ipv6_aggregate_address,
5652 no_ipv6_aggregate_address_cmd,
e3e6107d 5653 "no aggregate-address X:X::X:X/M [summary-only]",
718e3744 5654 NO_STR
5655 "Configure BGP aggregate entries\n"
16cedbb0
QY
5656 "Aggregate prefix\n"
5657 "Filter more specific routes from updates\n")
718e3744 5658{
e3e6107d
QY
5659 int idx = 0;
5660 argv_find (argv, argc, "X:X::X:X/M", &idx);
5661 char *prefix = argv[idx]->arg;
5662 return bgp_aggregate_unset (vty, prefix, AFI_IP6, SAFI_UNICAST);
718e3744 5663}
5664
718e3744 5665/* Redistribute route treatment. */
5666void
6aeb9e78 5667bgp_redistribute_add (struct bgp *bgp, struct prefix *p, const struct in_addr *nexthop,
bc413143 5668 const struct in6_addr *nexthop6, unsigned int ifindex,
dc9ffce8 5669 u_int32_t metric, u_char type, u_short instance, route_tag_t tag)
718e3744 5670{
718e3744 5671 struct bgp_info *new;
5672 struct bgp_info *bi;
5673 struct bgp_info info;
5674 struct bgp_node *bn;
e16a4133 5675 struct attr attr;
718e3744 5676 struct attr *new_attr;
5677 afi_t afi;
5678 int ret;
7c8ff89e 5679 struct bgp_redist *red;
718e3744 5680
5681 /* Make default attribute. */
5682 bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
5683 if (nexthop)
5684 attr.nexthop = *nexthop;
bc413143 5685 attr.nh_ifindex = ifindex;
718e3744 5686
f04a80a5
SH
5687 if (nexthop6)
5688 {
5689 struct attr_extra *extra = bgp_attr_extra_get(&attr);
5690 extra->mp_nexthop_global = *nexthop6;
801a9bcc 5691 extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
f04a80a5 5692 }
f04a80a5 5693
718e3744 5694 attr.med = metric;
5695 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
0d9551dc 5696 attr.extra->tag = tag;
718e3744 5697
6aeb9e78
DS
5698 afi = family2afi (p->family);
5699
5700 red = bgp_redist_lookup(bgp, afi, type, instance);
5701 if (red)
718e3744 5702 {
6aeb9e78
DS
5703 struct attr attr_new;
5704 struct attr_extra extra_new;
718e3744 5705
6aeb9e78
DS
5706 /* Copy attribute for modification. */
5707 attr_new.extra = &extra_new;
5708 bgp_attr_dup (&attr_new, &attr);
558d1fec 5709
6aeb9e78
DS
5710 if (red->redist_metric_flag)
5711 attr_new.med = red->redist_metric;
718e3744 5712
6aeb9e78
DS
5713 /* Apply route-map. */
5714 if (red->rmap.name)
5715 {
5716 info.peer = bgp->peer_self;
5717 info.attr = &attr_new;
718e3744 5718
6aeb9e78 5719 SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE);
718e3744 5720
6aeb9e78 5721 ret = route_map_apply (red->rmap.map, p, RMAP_BGP, &info);
fee0f4c6 5722
6aeb9e78 5723 bgp->peer_self->rmap_type = 0;
fee0f4c6 5724
6aeb9e78
DS
5725 if (ret == RMAP_DENYMATCH)
5726 {
5727 /* Free uninterned attribute. */
5728 bgp_attr_flush (&attr_new);
5729
5730 /* Unintern original. */
5731 aspath_unintern (&attr.aspath);
5732 bgp_attr_extra_free (&attr);
5733 bgp_redistribute_delete (bgp, p, type, instance);
5734 return;
5735 }
5736 }
fee0f4c6 5737
6aeb9e78
DS
5738 bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST],
5739 afi, SAFI_UNICAST, p, NULL);
718e3744 5740
6aeb9e78 5741 new_attr = bgp_attr_intern (&attr_new);
558d1fec 5742
6aeb9e78
DS
5743 for (bi = bn->info; bi; bi = bi->next)
5744 if (bi->peer == bgp->peer_self
5745 && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
5746 break;
5747
5748 if (bi)
5749 {
5750 /* Ensure the (source route) type is updated. */
5751 bi->type = type;
5752 if (attrhash_cmp (bi->attr, new_attr) &&
5753 !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
5754 {
5755 bgp_attr_unintern (&new_attr);
5756 aspath_unintern (&attr.aspath);
5757 bgp_attr_extra_free (&attr);
5758 bgp_unlock_node (bn);
5759 return;
5760 }
5761 else
5762 {
5763 /* The attribute is changed. */
5764 bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED);
718e3744 5765
6aeb9e78
DS
5766 /* Rewrite BGP route information. */
5767 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
5768 bgp_info_restore(bn, bi);
5769 else
5770 bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
5771 bgp_attr_unintern (&bi->attr);
5772 bi->attr = new_attr;
5773 bi->uptime = bgp_clock ();
5774
5775 /* Process change. */
5776 bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
5777 bgp_process (bgp, bn, afi, SAFI_UNICAST);
5778 bgp_unlock_node (bn);
5779 aspath_unintern (&attr.aspath);
5780 bgp_attr_extra_free (&attr);
5781 return;
5782 }
5783 }
718e3744 5784
6aeb9e78
DS
5785 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance, bgp->peer_self,
5786 new_attr, bn);
5787 SET_FLAG (new->flags, BGP_INFO_VALID);
5788
5789 bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
5790 bgp_info_add (bn, new);
5791 bgp_unlock_node (bn);
5792 bgp_process (bgp, bn, afi, SAFI_UNICAST);
718e3744 5793 }
5794
5795 /* Unintern original. */
f6f434b2 5796 aspath_unintern (&attr.aspath);
fb982c25 5797 bgp_attr_extra_free (&attr);
718e3744 5798}
5799
5800void
6aeb9e78 5801bgp_redistribute_delete (struct bgp *bgp, struct prefix *p, u_char type, u_short instance)
718e3744 5802{
718e3744 5803 afi_t afi;
5804 struct bgp_node *rn;
5805 struct bgp_info *ri;
7c8ff89e 5806 struct bgp_redist *red;
718e3744 5807
6aeb9e78 5808 afi = family2afi (p->family);
718e3744 5809
6aeb9e78
DS
5810 red = bgp_redist_lookup(bgp, afi, type, instance);
5811 if (red)
5812 {
5813 rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL);
718e3744 5814
6aeb9e78
DS
5815 for (ri = rn->info; ri; ri = ri->next)
5816 if (ri->peer == bgp->peer_self
5817 && ri->type == type)
5818 break;
718e3744 5819
6aeb9e78
DS
5820 if (ri)
5821 {
5822 bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
5823 bgp_info_delete (rn, ri);
5824 bgp_process (bgp, rn, afi, SAFI_UNICAST);
5825 }
5826 bgp_unlock_node (rn);
718e3744 5827 }
5828}
5829
5830/* Withdraw specified route type's route. */
5831void
7c8ff89e 5832bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type, u_short instance)
718e3744 5833{
5834 struct bgp_node *rn;
5835 struct bgp_info *ri;
5836 struct bgp_table *table;
5837
5838 table = bgp->rib[afi][SAFI_UNICAST];
5839
5840 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
5841 {
5842 for (ri = rn->info; ri; ri = ri->next)
5843 if (ri->peer == bgp->peer_self
7c8ff89e
DS
5844 && ri->type == type
5845 && ri->instance == instance)
718e3744 5846 break;
5847
5848 if (ri)
5849 {
5850 bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST);
718e3744 5851 bgp_info_delete (rn, ri);
1a392d46 5852 bgp_process (bgp, rn, afi, SAFI_UNICAST);
718e3744 5853 }
5854 }
5855}
6b0655a2 5856
718e3744 5857/* Static function to display route. */
94f2b392 5858static void
718e3744 5859route_vty_out_route (struct prefix *p, struct vty *vty)
5860{
5861 int len;
5862 u_int32_t destination;
5863 char buf[BUFSIZ];
5864
5865 if (p->family == AF_INET)
5866 {
5867 len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ));
5868 destination = ntohl (p->u.prefix4.s_addr);
5869
5870 if ((IN_CLASSC (destination) && p->prefixlen == 24)
856ca177
MS
5871 || (IN_CLASSB (destination) && p->prefixlen == 16)
5872 || (IN_CLASSA (destination) && p->prefixlen == 8)
5873 || p->u.prefix4.s_addr == 0)
5874 {
5875 /* When mask is natural, mask is not displayed. */
5876 }
718e3744 5877 else
856ca177 5878 len += vty_out (vty, "/%d", p->prefixlen);
718e3744 5879 }
5880 else
5881 len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
5882 p->prefixlen);
5883
5884 len = 17 - len;
5885 if (len < 1)
5886 vty_out (vty, "%s%*s", VTY_NEWLINE, 20, " ");
5887 else
5888 vty_out (vty, "%*s", len, " ");
5889}
5890
718e3744 5891enum bgp_display_type
5892{
5893 normal_list,
5894};
5895
b40d939b 5896/* Print the short form route status for a bgp_info */
5897static void
b05a1c8b
DS
5898route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo,
5899 json_object *json_path)
718e3744 5900{
b05a1c8b
DS
5901 if (json_path)
5902 {
b05a1c8b
DS
5903
5904 /* Route status display. */
5905 if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
f1aa5d8a 5906 json_object_boolean_true_add(json_path, "removed");
b05a1c8b
DS
5907
5908 if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
f1aa5d8a 5909 json_object_boolean_true_add(json_path, "stale");
b05a1c8b
DS
5910
5911 if (binfo->extra && binfo->extra->suppress)
f1aa5d8a 5912 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b
DS
5913
5914 if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) &&
5915 ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
f1aa5d8a 5916 json_object_boolean_true_add(json_path, "valid");
b05a1c8b
DS
5917
5918 /* Selected */
5919 if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
f1aa5d8a 5920 json_object_boolean_true_add(json_path, "history");
b05a1c8b
DS
5921
5922 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
f1aa5d8a 5923 json_object_boolean_true_add(json_path, "damped");
b05a1c8b
DS
5924
5925 if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
f1aa5d8a 5926 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b
DS
5927
5928 if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH))
f1aa5d8a 5929 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b
DS
5930
5931 /* Internal route. */
5932 if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as))
62d6dca0 5933 json_object_string_add(json_path, "pathFrom", "internal");
b05a1c8b 5934 else
62d6dca0 5935 json_object_string_add(json_path, "pathFrom", "external");
b05a1c8b
DS
5936
5937 return;
5938 }
5939
b40d939b 5940 /* Route status display. */
5941 if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
5942 vty_out (vty, "R");
5943 else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
93406d87 5944 vty_out (vty, "S");
fb982c25 5945 else if (binfo->extra && binfo->extra->suppress)
718e3744 5946 vty_out (vty, "s");
31eba040
DS
5947 else if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) &&
5948 ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
718e3744 5949 vty_out (vty, "*");
5950 else
5951 vty_out (vty, " ");
5952
5953 /* Selected */
5954 if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
5955 vty_out (vty, "h");
5956 else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
5957 vty_out (vty, "d");
5958 else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
5959 vty_out (vty, ">");
b366b518
BB
5960 else if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH))
5961 vty_out (vty, "=");
718e3744 5962 else
5963 vty_out (vty, " ");
5964
5965 /* Internal route. */
4f280b15
LB
5966 if (binfo->peer &&
5967 (binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as))
b05a1c8b
DS
5968 vty_out (vty, "i");
5969 else
5970 vty_out (vty, " ");
b40d939b 5971}
5972
5973/* called from terminal list command */
5974void
5975route_vty_out (struct vty *vty, struct prefix *p,
b05a1c8b
DS
5976 struct bgp_info *binfo, int display, safi_t safi,
5977 json_object *json_paths)
b40d939b 5978{
5979 struct attr *attr;
f1aa5d8a
DS
5980 json_object *json_path = NULL;
5981 json_object *json_nexthops = NULL;
5982 json_object *json_nexthop_global = NULL;
5983 json_object *json_nexthop_ll = NULL;
47fc97cc 5984
b05a1c8b
DS
5985 if (json_paths)
5986 json_path = json_object_new_object();
b05a1c8b
DS
5987
5988 /* short status lead text */
5989 route_vty_short_status_out (vty, binfo, json_path);
718e3744 5990
b05a1c8b
DS
5991 if (!json_paths)
5992 {
5993 /* print prefix and mask */
5994 if (! display)
5995 route_vty_out_route (p, vty);
5996 else
5997 vty_out (vty, "%*s", 17, " ");
5998 }
47fc97cc 5999
718e3744 6000 /* Print attribute */
6001 attr = binfo->attr;
6002 if (attr)
6003 {
587ff0fd
LB
6004 /*
6005 * For ENCAP routes, nexthop address family is not
6006 * neccessarily the same as the prefix address family.
6007 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6008 */
3d6c0dfa 6009 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN))
587ff0fd
LB
6010 {
6011 if (attr->extra)
6012 {
6013 char buf[BUFSIZ];
6014 int af = NEXTHOP_FAMILY(attr->extra->mp_nexthop_len);
b05a1c8b 6015
587ff0fd
LB
6016 switch (af)
6017 {
6018 case AF_INET:
6019 vty_out (vty, "%s", inet_ntop(af,
6020 &attr->extra->mp_nexthop_global_in, buf, BUFSIZ));
6021 break;
587ff0fd
LB
6022 case AF_INET6:
6023 vty_out (vty, "%s", inet_ntop(af,
6024 &attr->extra->mp_nexthop_global, buf, BUFSIZ));
6025 break;
587ff0fd
LB
6026 default:
6027 vty_out(vty, "?");
6028 break;
6029 }
6030 }
6031 else
6032 vty_out(vty, "?");
6033 }
b05a1c8b 6034 /* IPv4 Next Hop */
f81e127e 6035 else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
718e3744 6036 {
b05a1c8b
DS
6037 if (json_paths)
6038 {
f1aa5d8a
DS
6039 json_nexthop_global = json_object_new_object();
6040
3d6c0dfa 6041 if ((safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN))
f1aa5d8a 6042 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
b05a1c8b 6043 else
f1aa5d8a
DS
6044 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop));
6045
6046 json_object_string_add(json_nexthop_global, "afi", "ipv4");
6047 json_object_boolean_true_add(json_nexthop_global, "used");
b05a1c8b
DS
6048 }
6049 else
6050 {
3d6c0dfa 6051 if ((safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN))
b05a1c8b
DS
6052 vty_out (vty, "%-16s",
6053 inet_ntoa (attr->extra->mp_nexthop_global_in));
6054 else
6055 vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
6056 }
718e3744 6057 }
161995ea 6058
b05a1c8b 6059 /* IPv6 Next Hop */
8a92a8a0 6060 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr))
718e3744 6061 {
6062 int len;
6063 char buf[BUFSIZ];
6064
b05a1c8b
DS
6065 if (json_paths)
6066 {
f1aa5d8a
DS
6067 json_nexthop_global = json_object_new_object();
6068 json_object_string_add(json_nexthop_global, "ip",
6069 inet_ntop (AF_INET6,
6070 &attr->extra->mp_nexthop_global,
6071 buf, BUFSIZ));
6072 json_object_string_add(json_nexthop_global, "afi", "ipv6");
6073 json_object_string_add(json_nexthop_global, "scope", "global");
6074
6075 /* We display both LL & GL if both have been received */
6076 if ((attr->extra->mp_nexthop_len == 32) || (binfo->peer->conf_if))
6077 {
6078 json_nexthop_ll = json_object_new_object();
6079 json_object_string_add(json_nexthop_ll, "ip",
6080 inet_ntop (AF_INET6,
6081 &attr->extra->mp_nexthop_local,
6082 buf, BUFSIZ));
6083 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
6084 json_object_string_add(json_nexthop_ll, "scope", "link-local");
6085
161995ea
DS
6086 if ((IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global,
6087 &attr->extra->mp_nexthop_local) != 0) &&
6088 !attr->extra->mp_nexthop_prefer_global)
f1aa5d8a
DS
6089 json_object_boolean_true_add(json_nexthop_ll, "used");
6090 else
6091 json_object_boolean_true_add(json_nexthop_global, "used");
6092 }
6093 else
6094 json_object_boolean_true_add(json_nexthop_global, "used");
b05a1c8b
DS
6095 }
6096 else
6097 {
161995ea
DS
6098 /* Display LL if LL/Global both in table unless prefer-global is set */
6099 if (((attr->extra->mp_nexthop_len == 32) &&
6100 !attr->extra->mp_nexthop_prefer_global) ||
6101 (binfo->peer->conf_if))
433e8b67
DS
6102 {
6103 if (binfo->peer->conf_if)
6104 {
6105 len = vty_out (vty, "%s",
6106 binfo->peer->conf_if);
6107 len = 7 - len; /* len of IPv6 addr + max len of def ifname */
6108
6109 if (len < 1)
6110 vty_out (vty, "%s%*s", VTY_NEWLINE, 45, " ");
6111 else
6112 vty_out (vty, "%*s", len, " ");
6113 }
6114 else
6115 {
6116 len = vty_out (vty, "%s",
6117 inet_ntop (AF_INET6,
6118 &attr->extra->mp_nexthop_local,
6119 buf, BUFSIZ));
6120 len = 16 - len;
6121
6122 if (len < 1)
6123 vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
6124 else
6125 vty_out (vty, "%*s", len, " ");
6126 }
6127 }
6128 else
6129 {
6130 len = vty_out (vty, "%s",
6131 inet_ntop (AF_INET6,
6132 &attr->extra->mp_nexthop_global,
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 }
b05a1c8b 6141 }
718e3744 6142 }
718e3744 6143
b05a1c8b 6144 /* MED/Metric */
718e3744 6145 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
b05a1c8b 6146 if (json_paths)
f1aa5d8a 6147 json_object_int_add(json_path, "med", attr->med);
b05a1c8b
DS
6148 else
6149 vty_out (vty, "%10u", attr->med);
718e3744 6150 else
b05a1c8b
DS
6151 if (!json_paths)
6152 vty_out (vty, " ");
47fc97cc 6153
b05a1c8b 6154 /* Local Pref */
718e3744 6155 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
b05a1c8b 6156 if (json_paths)
f1aa5d8a 6157 json_object_int_add(json_path, "localpref", attr->local_pref);
b05a1c8b
DS
6158 else
6159 vty_out (vty, "%7u", attr->local_pref);
718e3744 6160 else
b05a1c8b
DS
6161 if (!json_paths)
6162 vty_out (vty, " ");
718e3744 6163
b05a1c8b
DS
6164 if (json_paths)
6165 {
6166 if (attr->extra)
f1aa5d8a 6167 json_object_int_add(json_path, "weight", attr->extra->weight);
b05a1c8b 6168 else
f1aa5d8a 6169 json_object_int_add(json_path, "weight", 0);
b05a1c8b
DS
6170 }
6171 else
6172 vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
47fc97cc 6173
39e871e6
ST
6174 if (json_paths) {
6175 char buf[BUFSIZ];
6176 json_object_string_add(json_path, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
6177 }
6178
b2518c1e
PJ
6179 /* Print aspath */
6180 if (attr->aspath)
b05a1c8b
DS
6181 {
6182 if (json_paths)
f1aa5d8a 6183 json_object_string_add(json_path, "aspath", attr->aspath->str);
b05a1c8b 6184 else
f1aa5d8a 6185 aspath_print_vty (vty, "%s", attr->aspath, " ");
b05a1c8b 6186 }
47fc97cc 6187
b2518c1e 6188 /* Print origin */
b05a1c8b 6189 if (json_paths)
f1aa5d8a 6190 json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]);
b05a1c8b
DS
6191 else
6192 vty_out (vty, "%s", bgp_origin_str[attr->origin]);
b2518c1e 6193 }
856ca177
MS
6194 else
6195 {
6196 if (json_paths)
6197 json_object_string_add(json_path, "alert", "No attributes");
6198 else
6199 vty_out (vty, "No attributes to print%s", VTY_NEWLINE);
6200 }
b05a1c8b
DS
6201
6202 if (json_paths)
f1aa5d8a
DS
6203 {
6204 if (json_nexthop_global || json_nexthop_ll)
6205 {
6206 json_nexthops = json_object_new_array();
6207
6208 if (json_nexthop_global)
6209 json_object_array_add(json_nexthops, json_nexthop_global);
6210
6211 if (json_nexthop_ll)
6212 json_object_array_add(json_nexthops, json_nexthop_ll);
6213
6214 json_object_object_add(json_path, "nexthops", json_nexthops);
6215 }
6216
6217 json_object_array_add(json_paths, json_path);
6218 }
b05a1c8b 6219 else
65efcfce 6220 {
b05a1c8b 6221 vty_out (vty, "%s", VTY_NEWLINE);
65efcfce
LB
6222#if ENABLE_BGP_VNC
6223 /* prints an additional line, indented, with VNC info, if present */
61263032 6224 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
65efcfce
LB
6225 rfapi_vty_out_vncinfo(vty, p, binfo, safi);
6226#endif
6227 }
718e3744 6228}
6229
6230/* called from terminal list command */
6231void
856ca177
MS
6232route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t safi,
6233 u_char use_json, json_object *json_ar)
718e3744 6234{
856ca177
MS
6235 json_object *json_status = NULL;
6236 json_object *json_net = NULL;
6237 char buff[BUFSIZ];
718e3744 6238 /* Route status display. */
856ca177
MS
6239 if (use_json)
6240 {
6241 json_status = json_object_new_object();
6242 json_net = json_object_new_object();
6243 }
6244 else
6245 {
6246 vty_out (vty, "*");
6247 vty_out (vty, ">");
6248 vty_out (vty, " ");
6249 }
718e3744 6250
6251 /* print prefix and mask */
856ca177
MS
6252 if (use_json)
6253 json_object_string_add(json_net, "addrPrefix", inet_ntop (p->family, &p->u.prefix, buff, BUFSIZ));
6254 else
6255 route_vty_out_route (p, vty);
718e3744 6256
6257 /* Print attribute */
6258 if (attr)
6259 {
856ca177 6260 if (use_json)
718e3744 6261 {
587ff0fd
LB
6262 if (p->family == AF_INET &&
6263 (safi == SAFI_MPLS_VPN ||
6264 safi == SAFI_ENCAP ||
3d6c0dfa 6265 safi == SAFI_EVPN ||
587ff0fd 6266 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
856ca177 6267 {
3d6c0dfa 6268 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
856ca177
MS
6269 json_object_string_add(json_net, "nextHop", inet_ntoa (attr->extra->mp_nexthop_global_in));
6270 else
6271 json_object_string_add(json_net, "nextHop", inet_ntoa (attr->nexthop));
6272 }
856ca177
MS
6273 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6274 {
6275 char buf[BUFSIZ];
718e3744 6276
856ca177
MS
6277 json_object_string_add(json_net, "netHopGloabal", inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6278 buf, BUFSIZ));
6279 }
856ca177
MS
6280
6281 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
6282 json_object_int_add(json_net, "metric", attr->med);
6283
6284 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
6285 json_object_int_add(json_net, "localPref", attr->local_pref);
6286
6287 if (attr->extra)
6288 json_object_int_add(json_net, "weight", attr->extra->weight);
718e3744 6289 else
856ca177
MS
6290 json_object_int_add(json_net, "weight", 0);
6291
6292 /* Print aspath */
6293 if (attr->aspath)
6294 json_object_string_add(json_net, "asPath", attr->aspath->str);
6295
6296 /* Print origin */
6297 json_object_string_add(json_net, "bgpOriginCode", bgp_origin_str[attr->origin]);
718e3744 6298 }
856ca177
MS
6299 else
6300 {
587ff0fd
LB
6301 if (p->family == AF_INET &&
6302 (safi == SAFI_MPLS_VPN ||
6303 safi == SAFI_ENCAP ||
3d6c0dfa 6304 safi == SAFI_EVPN ||
587ff0fd 6305 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
856ca177 6306 {
3d6c0dfa 6307 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
856ca177
MS
6308 vty_out (vty, "%-16s",
6309 inet_ntoa (attr->extra->mp_nexthop_global_in));
6310 else
6311 vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
6312 }
856ca177
MS
6313 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr))
6314 {
6315 int len;
6316 char buf[BUFSIZ];
6317
6318 assert (attr->extra);
6319
6320 len = vty_out (vty, "%s",
6321 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6322 buf, BUFSIZ));
6323 len = 16 - len;
6324 if (len < 1)
6325 vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
6326 else
6327 vty_out (vty, "%*s", len, " ");
6328 }
856ca177
MS
6329 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
6330 vty_out (vty, "%10u", attr->med);
6331 else
6332 vty_out (vty, " ");
718e3744 6333
856ca177
MS
6334 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
6335 vty_out (vty, "%7u", attr->local_pref);
6336 else
6337 vty_out (vty, " ");
718e3744 6338
856ca177 6339 vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
718e3744 6340
856ca177
MS
6341 /* Print aspath */
6342 if (attr->aspath)
6343 aspath_print_vty (vty, "%s", attr->aspath, " ");
718e3744 6344
856ca177
MS
6345 /* Print origin */
6346 vty_out (vty, "%s", bgp_origin_str[attr->origin]);
6347 }
6348 }
6349 if (use_json)
6350 {
6351 json_object_boolean_true_add(json_status, "*");
6352 json_object_boolean_true_add(json_status, ">");
6353 json_object_object_add(json_net, "appliedStatusSymbols", json_status);
6354 char buf_cut[BUFSIZ];
6355 json_object_object_add(json_ar, inet_ntop (p->family, &p->u.prefix, buf_cut, BUFSIZ), json_net);
6356 }
6357 else
6358 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6359}
6360
5a646650 6361void
718e3744 6362route_vty_out_tag (struct vty *vty, struct prefix *p,
856ca177 6363 struct bgp_info *binfo, int display, safi_t safi, json_object *json)
718e3744 6364{
856ca177 6365 json_object *json_out = NULL;
718e3744 6366 struct attr *attr;
718e3744 6367 u_int32_t label = 0;
fb982c25
PJ
6368
6369 if (!binfo->extra)
6370 return;
856ca177
MS
6371
6372 if (json)
6373 json_out = json_object_new_object();
fb982c25 6374
b40d939b 6375 /* short status lead text */
856ca177 6376 route_vty_short_status_out (vty, binfo, json_out);
b40d939b 6377
718e3744 6378 /* print prefix and mask */
856ca177
MS
6379 if (json == NULL)
6380 {
6381 if (! display)
6382 route_vty_out_route (p, vty);
6383 else
6384 vty_out (vty, "%*s", 17, " ");
6385 }
718e3744 6386
6387 /* Print attribute */
6388 attr = binfo->attr;
6389 if (attr)
6390 {
8a92a8a0
DS
6391 if (p->family == AF_INET
6392 && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
718e3744 6393 {
3d6c0dfa 6394 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
856ca177
MS
6395 {
6396 if (json)
6397 json_object_string_add(json_out, "mpNexthopGlobalIn", inet_ntoa (attr->extra->mp_nexthop_global_in));
6398 else
6399 vty_out (vty, "%-16s", inet_ntoa (attr->extra->mp_nexthop_global_in));
6400 }
718e3744 6401 else
856ca177
MS
6402 {
6403 if (json)
6404 json_object_string_add(json_out, "nexthop", inet_ntoa (attr->nexthop));
6405 else
6406 vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
6407 }
718e3744 6408 }
8a92a8a0 6409 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr))
718e3744 6410 {
fb982c25 6411 assert (attr->extra);
856ca177
MS
6412 char buf_a[BUFSIZ];
6413 char buf_b[BUFSIZ];
6414 char buf_c[BUFSIZ];
801a9bcc 6415 if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL)
856ca177
MS
6416 {
6417 if (json)
6418 json_object_string_add(json_out, "mpNexthopGlobalIn",
6419 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, buf_a, BUFSIZ));
6420 else
6421 vty_out (vty, "%s",
6422 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6423 buf_a, BUFSIZ));
6424 }
801a9bcc 6425 else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
856ca177
MS
6426 {
6427 if (json)
6428 {
6429 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6430 buf_a, BUFSIZ);
6431 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
6432 buf_b, BUFSIZ);
6433 sprintf(buf_c, "%s(%s)", buf_a, buf_b);
6434 json_object_string_add(json_out, "mpNexthopGlobalLocal", buf_c);
6435 }
6436 else
6437 vty_out (vty, "%s(%s)",
6438 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6439 buf_a, BUFSIZ),
6440 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
6441 buf_b, BUFSIZ));
6442 }
6443
718e3744 6444 }
718e3744 6445 }
6446
fb982c25 6447 label = decode_label (binfo->extra->tag);
718e3744 6448
856ca177
MS
6449 if (json)
6450 {
6451 if (label)
6452 json_object_int_add(json_out, "notag", label);
6453 json_object_array_add(json, json_out);
6454 }
6455 else
6456 {
6457 vty_out (vty, "notag/%d", label);
6458 vty_out (vty, "%s", VTY_NEWLINE);
6459 }
718e3744 6460}
6461
6462/* dampening route */
5a646650 6463static void
856ca177
MS
6464damp_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6465 int display, safi_t safi, u_char use_json, json_object *json)
718e3744 6466{
6467 struct attr *attr;
718e3744 6468 int len;
50aef6f3 6469 char timebuf[BGP_UPTIME_LEN];
718e3744 6470
b40d939b 6471 /* short status lead text */
856ca177 6472 route_vty_short_status_out (vty, binfo, json);
b40d939b 6473
718e3744 6474 /* print prefix and mask */
856ca177
MS
6475 if (!use_json)
6476 {
6477 if (! display)
6478 route_vty_out_route (p, vty);
6479 else
6480 vty_out (vty, "%*s", 17, " ");
6481 }
718e3744 6482
6483 len = vty_out (vty, "%s", binfo->peer->host);
6484 len = 17 - len;
6485 if (len < 1)
856ca177
MS
6486 {
6487 if (!use_json)
6488 vty_out (vty, "%s%*s", VTY_NEWLINE, 34, " ");
6489 }
718e3744 6490 else
856ca177
MS
6491 {
6492 if (use_json)
6493 json_object_int_add(json, "peerHost", len);
6494 else
6495 vty_out (vty, "%*s", len, " ");
6496 }
718e3744 6497
856ca177
MS
6498 if (use_json)
6499 bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json);
6500 else
6501 vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json));
718e3744 6502
6503 /* Print attribute */
6504 attr = binfo->attr;
6505 if (attr)
6506 {
6507 /* Print aspath */
6508 if (attr->aspath)
856ca177
MS
6509 {
6510 if (use_json)
6511 json_object_string_add(json, "asPath", attr->aspath->str);
6512 else
6513 aspath_print_vty (vty, "%s", attr->aspath, " ");
6514 }
718e3744 6515
6516 /* Print origin */
856ca177
MS
6517 if (use_json)
6518 json_object_string_add(json, "origin", bgp_origin_str[attr->origin]);
6519 else
6520 vty_out (vty, "%s", bgp_origin_str[attr->origin]);
718e3744 6521 }
856ca177
MS
6522 if (!use_json)
6523 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6524}
6525
718e3744 6526/* flap route */
5a646650 6527static void
856ca177
MS
6528flap_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo,
6529 int display, safi_t safi, u_char use_json, json_object *json)
718e3744 6530{
6531 struct attr *attr;
6532 struct bgp_damp_info *bdi;
718e3744 6533 char timebuf[BGP_UPTIME_LEN];
6534 int len;
fb982c25
PJ
6535
6536 if (!binfo->extra)
6537 return;
6538
6539 bdi = binfo->extra->damp_info;
718e3744 6540
b40d939b 6541 /* short status lead text */
856ca177 6542 route_vty_short_status_out (vty, binfo, json);
b40d939b 6543
718e3744 6544 /* print prefix and mask */
856ca177
MS
6545 if (!use_json)
6546 {
6547 if (! display)
6548 route_vty_out_route (p, vty);
6549 else
6550 vty_out (vty, "%*s", 17, " ");
6551 }
718e3744 6552
6553 len = vty_out (vty, "%s", binfo->peer->host);
6554 len = 16 - len;
6555 if (len < 1)
856ca177
MS
6556 {
6557 if (!use_json)
6558 vty_out (vty, "%s%*s", VTY_NEWLINE, 33, " ");
6559 }
718e3744 6560 else
856ca177
MS
6561 {
6562 if (use_json)
6563 json_object_int_add(json, "peerHost", len);
6564 else
6565 vty_out (vty, "%*s", len, " ");
6566 }
718e3744 6567
6568 len = vty_out (vty, "%d", bdi->flap);
6569 len = 5 - len;
6570 if (len < 1)
856ca177
MS
6571 {
6572 if (!use_json)
6573 vty_out (vty, " ");
6574 }
718e3744 6575 else
856ca177
MS
6576 {
6577 if (use_json)
6578 json_object_int_add(json, "bdiFlap", len);
6579 else
6580 vty_out (vty, "%*s", len, " ");
6581 }
6582
6583 if (use_json)
6584 peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, json);
6585 else
6586 vty_out (vty, "%s ", peer_uptime (bdi->start_time,
6587 timebuf, BGP_UPTIME_LEN, 0, NULL));
718e3744 6588
6589 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
6590 && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
856ca177
MS
6591 {
6592 if (use_json)
6593 bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json);
6594 else
6595 vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json));
6596 }
718e3744 6597 else
856ca177
MS
6598 {
6599 if (!use_json)
6600 vty_out (vty, "%*s ", 8, " ");
6601 }
718e3744 6602
6603 /* Print attribute */
6604 attr = binfo->attr;
6605 if (attr)
6606 {
6607 /* Print aspath */
6608 if (attr->aspath)
856ca177
MS
6609 {
6610 if (use_json)
6611 json_object_string_add(json, "asPath", attr->aspath->str);
6612 else
6613 aspath_print_vty (vty, "%s", attr->aspath, " ");
6614 }
718e3744 6615
6616 /* Print origin */
856ca177
MS
6617 if (use_json)
6618 json_object_string_add(json, "origin", bgp_origin_str[attr->origin]);
6619 else
6620 vty_out (vty, "%s", bgp_origin_str[attr->origin]);
718e3744 6621 }
856ca177
MS
6622 if (!use_json)
6623 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6624}
6625
adbac85e
DW
6626static void
6627route_vty_out_advertised_to (struct vty *vty, struct peer *peer, int *first,
6628 const char *header, json_object *json_adv_to)
6629{
6630 char buf1[INET6_ADDRSTRLEN];
6631 json_object *json_peer = NULL;
6632
6633 if (json_adv_to)
6634 {
6635 /* 'advertised-to' is a dictionary of peers we have advertised this
6636 * prefix too. The key is the peer's IP or swpX, the value is the
6637 * hostname if we know it and "" if not.
6638 */
6639 json_peer = json_object_new_object();
6640
6641 if (peer->hostname)
6642 json_object_string_add(json_peer, "hostname", peer->hostname);
6643
6644 if (peer->conf_if)
6645 json_object_object_add(json_adv_to, peer->conf_if, json_peer);
6646 else
6647 json_object_object_add(json_adv_to,
6648 sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN),
6649 json_peer);
6650 }
6651 else
6652 {
6653 if (*first)
6654 {
6655 vty_out (vty, "%s", header);
6656 *first = 0;
6657 }
6658
6659 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
6660 {
6661 if (peer->conf_if)
6662 vty_out (vty, " %s(%s)", peer->hostname, peer->conf_if);
6663 else
6664 vty_out (vty, " %s(%s)", peer->hostname,
6665 sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
6666 }
6667 else
6668 {
6669 if (peer->conf_if)
6670 vty_out (vty, " %s", peer->conf_if);
6671 else
6672 vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
6673 }
6674 }
6675}
6676
94f2b392 6677static void
718e3744 6678route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
b05a1c8b
DS
6679 struct bgp_info *binfo, afi_t afi, safi_t safi,
6680 json_object *json_paths)
718e3744 6681{
6682 char buf[INET6_ADDRSTRLEN];
6683 char buf1[BUFSIZ];
6684 struct attr *attr;
6685 int sockunion_vty_out (struct vty *, union sockunion *);
30b00176 6686 time_t tbuf;
f1aa5d8a 6687 json_object *json_bestpath = NULL;
ffd0c037 6688 json_object *json_cluster_list = NULL;
f1aa5d8a
DS
6689 json_object *json_cluster_list_list = NULL;
6690 json_object *json_ext_community = NULL;
6691 json_object *json_last_update = NULL;
6692 json_object *json_nexthop_global = NULL;
6693 json_object *json_nexthop_ll = NULL;
6694 json_object *json_nexthops = NULL;
6695 json_object *json_path = NULL;
6696 json_object *json_peer = NULL;
6697 json_object *json_string = NULL;
adbac85e
DW
6698 json_object *json_adv_to = NULL;
6699 int first = 0;
6700 struct listnode *node, *nnode;
6701 struct peer *peer;
6702 int addpath_capable;
6703 int has_adj;
aac9ef6c 6704 unsigned int first_as;
b05a1c8b
DS
6705
6706 if (json_paths)
6707 {
6708 json_path = json_object_new_object();
f1aa5d8a
DS
6709 json_peer = json_object_new_object();
6710 json_nexthop_global = json_object_new_object();
b05a1c8b
DS
6711 }
6712
718e3744 6713 attr = binfo->attr;
6714
6715 if (attr)
6716 {
6717 /* Line1 display AS-path, Aggregator */
6718 if (attr->aspath)
6719 {
f1aa5d8a
DS
6720 if (json_paths)
6721 {
6722 json_object_lock(attr->aspath->json);
6723 json_object_object_add(json_path, "aspath", attr->aspath->json);
6724 }
6725 else
b05a1c8b 6726 {
f1aa5d8a
DS
6727 if (attr->aspath->segments)
6728 aspath_print_vty (vty, " %s", attr->aspath, "");
b05a1c8b 6729 else
f1aa5d8a 6730 vty_out (vty, " Local");
b05a1c8b 6731 }
718e3744 6732 }
6733
b40d939b 6734 if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
b05a1c8b
DS
6735 {
6736 if (json_paths)
f1aa5d8a 6737 json_object_boolean_true_add(json_path, "removed");
b05a1c8b
DS
6738 else
6739 vty_out (vty, ", (removed)");
6740 }
6741
93406d87 6742 if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
b05a1c8b
DS
6743 {
6744 if (json_paths)
f1aa5d8a 6745 json_object_boolean_true_add(json_path, "stale");
b05a1c8b
DS
6746 else
6747 vty_out (vty, ", (stale)");
6748 }
6749
93406d87 6750 if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
b05a1c8b
DS
6751 {
6752 if (json_paths)
6753 {
62d6dca0
DS
6754 json_object_int_add(json_path, "aggregatorAs", attr->extra->aggregator_as);
6755 json_object_string_add(json_path, "aggregatorId", inet_ntoa (attr->extra->aggregator_addr));
b05a1c8b
DS
6756 }
6757 else
6758 {
6759 vty_out (vty, ", (aggregated by %u %s)",
6760 attr->extra->aggregator_as,
6761 inet_ntoa (attr->extra->aggregator_addr));
6762 }
6763 }
6764
93406d87 6765 if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
b05a1c8b
DS
6766 {
6767 if (json_paths)
62d6dca0 6768 json_object_boolean_true_add(json_path, "rxedFromRrClient");
b05a1c8b
DS
6769 else
6770 vty_out (vty, ", (Received from a RR-client)");
6771 }
6772
93406d87 6773 if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
b05a1c8b
DS
6774 {
6775 if (json_paths)
62d6dca0 6776 json_object_boolean_true_add(json_path, "rxedFromRsClient");
b05a1c8b
DS
6777 else
6778 vty_out (vty, ", (Received from a RS-client)");
6779 }
6780
93406d87 6781 if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
b05a1c8b
DS
6782 {
6783 if (json_paths)
62d6dca0 6784 json_object_boolean_true_add(json_path, "dampeningHistoryEntry");
b05a1c8b
DS
6785 else
6786 vty_out (vty, ", (history entry)");
6787 }
93406d87 6788 else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
b05a1c8b
DS
6789 {
6790 if (json_paths)
62d6dca0 6791 json_object_boolean_true_add(json_path, "dampeningSuppressed");
b05a1c8b
DS
6792 else
6793 vty_out (vty, ", (suppressed due to dampening)");
6794 }
6795
6796 if (!json_paths)
6797 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6798
6799 /* Line2 display Next-hop, Neighbor, Router-id */
f1aa5d8a 6800 /* Display the nexthop */
587ff0fd
LB
6801 if (p->family == AF_INET &&
6802 (safi == SAFI_MPLS_VPN ||
6803 safi == SAFI_ENCAP ||
3d6c0dfa 6804 safi == SAFI_EVPN ||
587ff0fd 6805 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
718e3744 6806 {
3d6c0dfa 6807 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
b05a1c8b
DS
6808 {
6809 if (json_paths)
f1aa5d8a 6810 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
b05a1c8b
DS
6811 else
6812 vty_out (vty, " %s", inet_ntoa (attr->extra->mp_nexthop_global_in));
6813 }
6814 else
6815 {
6816 if (json_paths)
f1aa5d8a 6817 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop));
b05a1c8b
DS
6818 else
6819 vty_out (vty, " %s", inet_ntoa (attr->nexthop));
6820 }
6821
6822 if (json_paths)
f1aa5d8a 6823 json_object_string_add(json_nexthop_global, "afi", "ipv4");
718e3744 6824 }
718e3744 6825 else
6826 {
fb982c25 6827 assert (attr->extra);
b05a1c8b
DS
6828 if (json_paths)
6829 {
f1aa5d8a
DS
6830 json_object_string_add(json_nexthop_global, "ip",
6831 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6832 buf, INET6_ADDRSTRLEN));
6833 json_object_string_add(json_nexthop_global, "afi", "ipv6");
6834 json_object_string_add(json_nexthop_global, "scope", "global");
b05a1c8b
DS
6835 }
6836 else
6837 {
6838 vty_out (vty, " %s",
6839 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
6840 buf, INET6_ADDRSTRLEN));
6841 }
718e3744 6842 }
b05a1c8b 6843
f1aa5d8a
DS
6844 /* Display the IGP cost or 'inaccessible' */
6845 if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
6846 {
6847 if (json_paths)
6848 json_object_boolean_false_add(json_nexthop_global, "accessible");
6849 else
6850 vty_out (vty, " (inaccessible)");
6851 }
6852 else
6853 {
6854 if (binfo->extra && binfo->extra->igpmetric)
b05a1c8b
DS
6855 {
6856 if (json_paths)
f1aa5d8a 6857 json_object_int_add(json_nexthop_global, "metric", binfo->extra->igpmetric);
b05a1c8b 6858 else
f1aa5d8a 6859 vty_out (vty, " (metric %u)", binfo->extra->igpmetric);
b05a1c8b 6860 }
f1aa5d8a
DS
6861
6862 /* IGP cost is 0, display this only for json */
b05a1c8b
DS
6863 else
6864 {
6865 if (json_paths)
f1aa5d8a 6866 json_object_int_add(json_nexthop_global, "metric", 0);
b05a1c8b
DS
6867 }
6868
6869 if (json_paths)
f1aa5d8a
DS
6870 json_object_boolean_true_add(json_nexthop_global, "accessible");
6871 }
6872
6873 /* Display peer "from" output */
6874 /* This path was originated locally */
6875 if (binfo->peer == bgp->peer_self)
718e3744 6876 {
f1aa5d8a
DS
6877
6878 if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
b05a1c8b
DS
6879 {
6880 if (json_paths)
62d6dca0 6881 json_object_string_add(json_peer, "peerId", "0.0.0.0");
b05a1c8b 6882 else
f1aa5d8a 6883 vty_out (vty, " from 0.0.0.0 ");
b05a1c8b 6884 }
f1aa5d8a 6885 else
b05a1c8b
DS
6886 {
6887 if (json_paths)
62d6dca0 6888 json_object_string_add(json_peer, "peerId", "::");
b05a1c8b 6889 else
f1aa5d8a 6890 vty_out (vty, " from :: ");
b05a1c8b
DS
6891 }
6892
f1aa5d8a 6893 if (json_paths)
62d6dca0 6894 json_object_string_add(json_peer, "routerId", inet_ntoa(bgp->router_id));
b05a1c8b 6895 else
f1aa5d8a
DS
6896 vty_out (vty, "(%s)", inet_ntoa(bgp->router_id));
6897 }
6898
6899 /* We RXed this path from one of our peers */
6900 else
6901 {
b05a1c8b
DS
6902
6903 if (json_paths)
6904 {
62d6dca0
DS
6905 json_object_string_add(json_peer, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
6906 json_object_string_add(json_peer, "routerId", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
f1aa5d8a 6907
04b6bdc0
DW
6908 if (binfo->peer->hostname)
6909 json_object_string_add(json_peer, "hostname", binfo->peer->hostname);
6910
6911 if (binfo->peer->domainname)
6912 json_object_string_add(json_peer, "domainname", binfo->peer->domainname);
6913
036a4e7d 6914 if (binfo->peer->conf_if)
f1aa5d8a 6915 json_object_string_add(json_peer, "interface", binfo->peer->conf_if);
b05a1c8b
DS
6916 }
6917 else
6918 {
036a4e7d 6919 if (binfo->peer->conf_if)
04b6bdc0
DW
6920 {
6921 if (binfo->peer->hostname &&
6922 bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
6923 vty_out (vty, " from %s(%s)", binfo->peer->hostname,
6924 binfo->peer->conf_if);
6925 else
6926 vty_out (vty, " from %s", binfo->peer->conf_if);
6927 }
036a4e7d 6928 else
04b6bdc0
DW
6929 {
6930 if (binfo->peer->hostname &&
6931 bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
6932 vty_out (vty, " from %s(%s)", binfo->peer->hostname,
6933 binfo->peer->host);
6934 else
6935 vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
6936 }
b05a1c8b 6937
f1aa5d8a
DS
6938 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
6939 vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
6940 else
6941 vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
b05a1c8b 6942 }
718e3744 6943 }
b05a1c8b
DS
6944
6945 if (!json_paths)
6946 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6947
f1aa5d8a 6948 /* display the link-local nexthop */
801a9bcc 6949 if (attr->extra && attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
718e3744 6950 {
b05a1c8b
DS
6951 if (json_paths)
6952 {
f1aa5d8a
DS
6953 json_nexthop_ll = json_object_new_object();
6954 json_object_string_add(json_nexthop_ll, "ip",
6955 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
6956 buf, INET6_ADDRSTRLEN));
6957 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
6958 json_object_string_add(json_nexthop_ll, "scope", "link-local");
6959
6960 json_object_boolean_true_add(json_nexthop_ll, "accessible");
161995ea
DS
6961
6962 if (!attr->extra->mp_nexthop_prefer_global)
6963 json_object_boolean_true_add(json_nexthop_ll, "used");
6964 else
6965 json_object_boolean_true_add(json_nexthop_global, "used");
b05a1c8b
DS
6966 }
6967 else
6968 {
161995ea
DS
6969 vty_out (vty, " (%s) %s%s",
6970 inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
b05a1c8b 6971 buf, INET6_ADDRSTRLEN),
161995ea
DS
6972 attr->extra->mp_nexthop_prefer_global ?
6973 "(prefer-global)" : "(used)",
b05a1c8b
DS
6974 VTY_NEWLINE);
6975 }
718e3744 6976 }
f1aa5d8a
DS
6977 /* If we do not have a link-local nexthop then we must flag the global as "used" */
6978 else
6979 {
6980 if (json_paths)
6981 json_object_boolean_true_add(json_nexthop_global, "used");
6982 }
718e3744 6983
0d9551dc 6984 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */
b05a1c8b 6985 if (json_paths)
f1aa5d8a 6986 json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]);
b05a1c8b 6987 else
f1aa5d8a 6988 vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]);
718e3744 6989
6990 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
b05a1c8b
DS
6991 {
6992 if (json_paths)
f1aa5d8a 6993 json_object_int_add(json_path, "med", attr->med);
b05a1c8b 6994 else
f1aa5d8a 6995 vty_out (vty, ", metric %u", attr->med);
b05a1c8b 6996 }
718e3744 6997
6998 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
b05a1c8b
DS
6999 {
7000 if (json_paths)
f1aa5d8a 7001 json_object_int_add(json_path, "localpref", attr->local_pref);
b05a1c8b 7002 else
f1aa5d8a 7003 vty_out (vty, ", localpref %u", attr->local_pref);
b05a1c8b 7004 }
718e3744 7005 else
b05a1c8b
DS
7006 {
7007 if (json_paths)
f1aa5d8a 7008 json_object_int_add(json_path, "localpref", bgp->default_local_pref);
b05a1c8b 7009 else
f1aa5d8a 7010 vty_out (vty, ", localpref %u", bgp->default_local_pref);
b05a1c8b 7011 }
718e3744 7012
fb982c25 7013 if (attr->extra && attr->extra->weight != 0)
b05a1c8b
DS
7014 {
7015 if (json_paths)
f1aa5d8a 7016 json_object_int_add(json_path, "weight", attr->extra->weight);
b05a1c8b 7017 else
f1aa5d8a 7018 vty_out (vty, ", weight %u", attr->extra->weight);
b05a1c8b 7019 }
0d9551dc
DS
7020
7021 if (attr->extra && attr->extra->tag != 0)
b05a1c8b
DS
7022 {
7023 if (json_paths)
f1aa5d8a 7024 json_object_int_add(json_path, "tag", attr->extra->tag);
b05a1c8b 7025 else
dc9ffce8 7026 vty_out (vty, ", tag %"ROUTE_TAG_PRI, attr->extra->tag);
b05a1c8b 7027 }
718e3744 7028
31eba040 7029 if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
b05a1c8b
DS
7030 {
7031 if (json_paths)
f1aa5d8a 7032 json_object_boolean_false_add(json_path, "valid");
b05a1c8b
DS
7033 else
7034 vty_out (vty, ", invalid");
7035 }
31eba040 7036 else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
b05a1c8b
DS
7037 {
7038 if (json_paths)
f1aa5d8a 7039 json_object_boolean_true_add(json_path, "valid");
b05a1c8b
DS
7040 else
7041 vty_out (vty, ", valid");
7042 }
718e3744 7043
7044 if (binfo->peer != bgp->peer_self)
7045 {
f1aa5d8a 7046 if (binfo->peer->as == binfo->peer->local_as)
b05a1c8b 7047 {
66b199b2
DS
7048 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
7049 {
7050 if (json_paths)
f1aa5d8a 7051 json_object_string_add(json_peer, "type", "confed-internal");
66b199b2 7052 else
f1aa5d8a 7053 vty_out (vty, ", confed-internal");
66b199b2 7054 }
b05a1c8b 7055 else
66b199b2
DS
7056 {
7057 if (json_paths)
f1aa5d8a 7058 json_object_string_add(json_peer, "type", "internal");
66b199b2 7059 else
f1aa5d8a 7060 vty_out (vty, ", internal");
66b199b2 7061 }
b05a1c8b 7062 }
f1aa5d8a 7063 else
b05a1c8b
DS
7064 {
7065 if (bgp_confederation_peers_check(bgp, binfo->peer->as))
7066 {
7067 if (json_paths)
f1aa5d8a 7068 json_object_string_add(json_peer, "type", "confed-external");
b05a1c8b 7069 else
f1aa5d8a 7070 vty_out (vty, ", confed-external");
b05a1c8b
DS
7071 }
7072 else
7073 {
7074 if (json_paths)
f1aa5d8a 7075 json_object_string_add(json_peer, "type", "external");
b05a1c8b 7076 else
f1aa5d8a 7077 vty_out (vty, ", external");
b05a1c8b
DS
7078 }
7079 }
718e3744 7080 }
7081 else if (binfo->sub_type == BGP_ROUTE_AGGREGATE)
b05a1c8b
DS
7082 {
7083 if (json_paths)
7084 {
f1aa5d8a
DS
7085 json_object_boolean_true_add(json_path, "aggregated");
7086 json_object_boolean_true_add(json_path, "local");
b05a1c8b
DS
7087 }
7088 else
7089 {
7090 vty_out (vty, ", aggregated, local");
7091 }
7092 }
718e3744 7093 else if (binfo->type != ZEBRA_ROUTE_BGP)
b05a1c8b
DS
7094 {
7095 if (json_paths)
f1aa5d8a 7096 json_object_boolean_true_add(json_path, "sourced");
b05a1c8b
DS
7097 else
7098 vty_out (vty, ", sourced");
7099 }
718e3744 7100 else
b05a1c8b
DS
7101 {
7102 if (json_paths)
7103 {
f1aa5d8a
DS
7104 json_object_boolean_true_add(json_path, "sourced");
7105 json_object_boolean_true_add(json_path, "local");
b05a1c8b
DS
7106 }
7107 else
7108 {
7109 vty_out (vty, ", sourced, local");
7110 }
7111 }
718e3744 7112
7113 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
b05a1c8b
DS
7114 {
7115 if (json_paths)
62d6dca0 7116 json_object_boolean_true_add(json_path, "atomicAggregate");
b05a1c8b
DS
7117 else
7118 vty_out (vty, ", atomic-aggregate");
7119 }
718e3744 7120
de8d5dff
JB
7121 if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) ||
7122 (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) &&
7123 bgp_info_mpath_count (binfo)))
b05a1c8b
DS
7124 {
7125 if (json_paths)
f1aa5d8a 7126 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b
DS
7127 else
7128 vty_out (vty, ", multipath");
7129 }
de8d5dff 7130
06370dac
DW
7131 // Mark the bestpath(s)
7132 if (CHECK_FLAG (binfo->flags, BGP_INFO_DMED_SELECTED))
7133 {
aac9ef6c 7134 first_as = aspath_get_first_as(attr->aspath);
06370dac
DW
7135
7136 if (json_paths)
7137 {
7138 if (!json_bestpath)
7139 json_bestpath = json_object_new_object();
7140 json_object_int_add(json_bestpath, "bestpathFromAs", first_as);
7141 }
7142 else
7143 {
7144 if (first_as)
7145 vty_out (vty, ", bestpath-from-AS %d", first_as);
7146 else
7147 vty_out (vty, ", bestpath-from-AS Local");
7148 }
7149 }
7150
718e3744 7151 if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
b05a1c8b
DS
7152 {
7153 if (json_paths)
f1aa5d8a 7154 {
06370dac
DW
7155 if (!json_bestpath)
7156 json_bestpath = json_object_new_object();
f1aa5d8a 7157 json_object_boolean_true_add(json_bestpath, "overall");
f1aa5d8a 7158 }
b05a1c8b
DS
7159 else
7160 vty_out (vty, ", best");
7161 }
718e3744 7162
06370dac
DW
7163 if (json_bestpath)
7164 json_object_object_add(json_path, "bestpath", json_bestpath);
7165
b05a1c8b
DS
7166 if (!json_paths)
7167 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 7168
7169 /* Line 4 display Community */
7170 if (attr->community)
b05a1c8b
DS
7171 {
7172 if (json_paths)
7173 {
f1aa5d8a
DS
7174 json_object_lock(attr->community->json);
7175 json_object_object_add(json_path, "community", attr->community->json);
b05a1c8b
DS
7176 }
7177 else
7178 {
7179 vty_out (vty, " Community: %s%s", attr->community->str,
7180 VTY_NEWLINE);
7181 }
7182 }
718e3744 7183
7184 /* Line 5 display Extended-community */
7185 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
b05a1c8b
DS
7186 {
7187 if (json_paths)
7188 {
f1aa5d8a
DS
7189 json_ext_community = json_object_new_object();
7190 json_object_string_add(json_ext_community, "string", attr->extra->ecommunity->str);
62d6dca0 7191 json_object_object_add(json_path, "extendedCommunity", json_ext_community);
b05a1c8b
DS
7192 }
7193 else
7194 {
7195 vty_out (vty, " Extended Community: %s%s",
7196 attr->extra->ecommunity->str, VTY_NEWLINE);
7197 }
7198 }
7199
57d187bc
JS
7200 /* Line 6 display Large community */
7201 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))
2acb4ac2
DL
7202 vty_out (vty, " Large Community: %s%s",
7203 attr->extra->lcommunity->str, VTY_NEWLINE);
57d187bc
JS
7204
7205 /* Line 7 display Originator, Cluster-id */
718e3744 7206 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) ||
7207 (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)))
7208 {
fb982c25 7209 assert (attr->extra);
718e3744 7210 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
b05a1c8b
DS
7211 {
7212 if (json_paths)
62d6dca0 7213 json_object_string_add(json_path, "originatorId", inet_ntoa (attr->extra->originator_id));
b05a1c8b 7214 else
f1aa5d8a
DS
7215 vty_out (vty, " Originator: %s",
7216 inet_ntoa (attr->extra->originator_id));
b05a1c8b 7217 }
718e3744 7218
7219 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
7220 {
7221 int i;
b05a1c8b
DS
7222
7223 if (json_paths)
7224 {
f1aa5d8a
DS
7225 json_cluster_list = json_object_new_object();
7226 json_cluster_list_list = json_object_new_array();
7227
b05a1c8b
DS
7228 for (i = 0; i < attr->extra->cluster->length / 4; i++)
7229 {
7230 json_string = json_object_new_string(inet_ntoa (attr->extra->cluster->list[i]));
f1aa5d8a 7231 json_object_array_add(json_cluster_list_list, json_string);
b05a1c8b 7232 }
f1aa5d8a
DS
7233
7234 /* struct cluster_list does not have "str" variable like
7235 * aspath and community do. Add this someday if someone
7236 * asks for it.
7237 json_object_string_add(json_cluster_list, "string", attr->extra->cluster->str);
7238 */
7239 json_object_object_add(json_cluster_list, "list", json_cluster_list_list);
62d6dca0 7240 json_object_object_add(json_path, "clusterList", json_cluster_list);
b05a1c8b
DS
7241 }
7242 else
7243 {
7244 vty_out (vty, ", Cluster list: ");
7245
7246 for (i = 0; i < attr->extra->cluster->length / 4; i++)
7247 {
7248 vty_out (vty, "%s ",
7249 inet_ntoa (attr->extra->cluster->list[i]));
7250 }
7251 }
718e3744 7252 }
b05a1c8b
DS
7253
7254 if (!json_paths)
7255 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 7256 }
b05a1c8b 7257
fb982c25 7258 if (binfo->extra && binfo->extra->damp_info)
b05a1c8b 7259 bgp_damp_info_vty (vty, binfo, json_path);
718e3744 7260
57d187bc 7261 /* Line 8 display Addpath IDs */
a82478b9 7262 if (binfo->addpath_rx_id || binfo->addpath_tx_id)
b05a1c8b
DS
7263 {
7264 if (json_paths)
7265 {
62d6dca0
DS
7266 json_object_int_add(json_path, "addpathRxId", binfo->addpath_rx_id);
7267 json_object_int_add(json_path, "addpathTxId", binfo->addpath_tx_id);
b05a1c8b
DS
7268 }
7269 else
7270 {
7271 vty_out (vty, " AddPath ID: RX %u, TX %u%s",
7272 binfo->addpath_rx_id, binfo->addpath_tx_id,
7273 VTY_NEWLINE);
7274 }
7275 }
a82478b9 7276
adbac85e
DW
7277 /* If we used addpath to TX a non-bestpath we need to display
7278 * "Advertised to" on a path-by-path basis */
7279 if (bgp->addpath_tx_used[afi][safi])
7280 {
7281 first = 1;
7282
7283 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
7284 {
7285 addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
7286 has_adj = bgp_adj_out_lookup (peer, binfo->net, binfo->addpath_tx_id);
7287
7288 if ((addpath_capable && has_adj) ||
7289 (!addpath_capable && has_adj && CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)))
7290 {
7291 if (json_path && !json_adv_to)
7292 json_adv_to = json_object_new_object();
7293
7294 route_vty_out_advertised_to(vty, peer, &first,
7295 " Advertised to:",
7296 json_adv_to);
7297 }
7298 }
7299
7300 if (json_path)
7301 {
7302 if (json_adv_to)
7303 {
7304 json_object_object_add(json_path, "advertisedTo", json_adv_to);
7305 }
7306 }
7307 else
7308 {
7309 if (!first)
7310 {
7311 vty_out (vty, "%s", VTY_NEWLINE);
7312 }
7313 }
7314 }
7315
57d187bc 7316 /* Line 9 display Uptime */
30b00176 7317 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
b05a1c8b 7318 if (json_paths)
f1aa5d8a
DS
7319 {
7320 json_last_update = json_object_new_object();
7321 json_object_int_add(json_last_update, "epoch", tbuf);
7322 json_object_string_add(json_last_update, "string", ctime(&tbuf));
62d6dca0 7323 json_object_object_add(json_path, "lastUpdate", json_last_update);
f1aa5d8a 7324 }
b05a1c8b
DS
7325 else
7326 vty_out (vty, " Last update: %s", ctime(&tbuf));
718e3744 7327 }
b05a1c8b
DS
7328
7329 /* We've constructed the json object for this path, add it to the json
7330 * array of paths
7331 */
7332 if (json_paths)
f1aa5d8a
DS
7333 {
7334 if (json_nexthop_global || json_nexthop_ll)
7335 {
7336 json_nexthops = json_object_new_array();
7337
7338 if (json_nexthop_global)
7339 json_object_array_add(json_nexthops, json_nexthop_global);
7340
7341 if (json_nexthop_ll)
7342 json_object_array_add(json_nexthops, json_nexthop_ll);
7343
7344 json_object_object_add(json_path, "nexthops", json_nexthops);
7345 }
7346
7347 json_object_object_add(json_path, "peer", json_peer);
7348 json_object_array_add(json_paths, json_path);
7349 }
b05a1c8b
DS
7350 else
7351 vty_out (vty, "%s", VTY_NEWLINE);
b366b518
BB
7352}
7353
47fc97cc 7354#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path%s"
718e3744 7355#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path%s"
7356#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path%s"
7357
50ef26d4 7358static int
af462945 7359bgp_show_prefix_list (struct vty *vty, struct bgp *bgp,
50ef26d4 7360 const char *prefix_list_str, afi_t afi,
7361 safi_t safi, enum bgp_show_type type);
7362static int
af462945 7363bgp_show_filter_list (struct vty *vty, struct bgp *bgp,
50ef26d4 7364 const char *filter, afi_t afi,
7365 safi_t safi, enum bgp_show_type type);
7366static int
af462945 7367bgp_show_route_map (struct vty *vty, struct bgp *bgp,
50ef26d4 7368 const char *rmap_str, afi_t afi,
7369 safi_t safi, enum bgp_show_type type);
7370static int
af462945 7371bgp_show_community_list (struct vty *vty, struct bgp *bgp,
50ef26d4 7372 const char *com, int exact,
7373 afi_t afi, safi_t safi);
7374static int
af462945 7375bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp,
50ef26d4 7376 const char *prefix, afi_t afi,
7377 safi_t safi, enum bgp_show_type type);
a636c635 7378static int
8c3deaae 7379bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi,
a636c635
DW
7380 safi_t safi, enum bgp_show_type type);
7381static int
af462945 7382bgp_show_community (struct vty *vty, struct bgp *bgp, int argc,
a636c635 7383 struct cmd_token **argv, int exact, afi_t afi, safi_t safi);
50ef26d4 7384
5a646650 7385static int
31303c3e
DS
7386bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table,
7387 enum bgp_show_type type, void *output_arg, u_char use_json)
718e3744 7388{
718e3744 7389 struct bgp_info *ri;
7390 struct bgp_node *rn;
718e3744 7391 int header = 1;
718e3744 7392 int display;
5a646650 7393 unsigned long output_count;
18200902 7394 unsigned long total_count;
b05a1c8b
DS
7395 struct prefix *p;
7396 char buf[BUFSIZ];
7397 char buf2[BUFSIZ];
f1aa5d8a 7398 json_object *json_paths = NULL;
31303c3e 7399 int first = 1;
b05a1c8b
DS
7400
7401 if (use_json)
7402 {
31303c3e
DS
7403 vty_out (vty, "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 ", \"routerId\": \"%s\", \"routes\": { ",
7404 bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id,
7405 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" : bgp->name,
7406 table->version, inet_ntoa (bgp->router_id));
7407 json_paths = json_object_new_object();
b05a1c8b 7408 }
718e3744 7409
7410 /* This is first entry point, so reset total line. */
5a646650 7411 output_count = 0;
18200902 7412 total_count = 0;
718e3744 7413
718e3744 7414 /* Start processing of routes. */
7415 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
7416 if (rn->info != NULL)
7417 {
856ca177 7418 display = 0;
31303c3e
DS
7419 if (!first && use_json)
7420 {
7421 vty_out (vty, ",");
7422 }
b05a1c8b
DS
7423 if (use_json)
7424 json_paths = json_object_new_array();
7425 else
7426 json_paths = NULL;
7427
856ca177
MS
7428 for (ri = rn->info; ri; ri = ri->next)
7429 {
18200902 7430 total_count++;
856ca177 7431 if (type == bgp_show_type_flap_statistics
856ca177
MS
7432 || type == bgp_show_type_flap_neighbor
7433 || type == bgp_show_type_dampend_paths
7434 || type == bgp_show_type_damp_neighbor)
7435 {
7436 if (!(ri->extra && ri->extra->damp_info))
7437 continue;
7438 }
a636c635 7439 if (type == bgp_show_type_regexp)
856ca177
MS
7440 {
7441 regex_t *regex = output_arg;
718e3744 7442
856ca177
MS
7443 if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH)
7444 continue;
7445 }
a636c635 7446 if (type == bgp_show_type_prefix_list)
856ca177
MS
7447 {
7448 struct prefix_list *plist = output_arg;
718e3744 7449
856ca177
MS
7450 if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT)
7451 continue;
7452 }
a636c635 7453 if (type == bgp_show_type_filter_list)
856ca177
MS
7454 {
7455 struct as_list *as_list = output_arg;
558d1fec 7456
856ca177
MS
7457 if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT)
7458 continue;
7459 }
a636c635 7460 if (type == bgp_show_type_route_map)
856ca177
MS
7461 {
7462 struct route_map *rmap = output_arg;
7463 struct bgp_info binfo;
7464 struct attr dummy_attr;
7465 struct attr_extra dummy_extra;
7466 int ret;
718e3744 7467
856ca177
MS
7468 dummy_attr.extra = &dummy_extra;
7469 bgp_attr_dup (&dummy_attr, ri->attr);
718e3744 7470
856ca177
MS
7471 binfo.peer = ri->peer;
7472 binfo.attr = &dummy_attr;
718e3744 7473
856ca177
MS
7474 ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo);
7475 if (ret == RMAP_DENYMATCH)
7476 continue;
7477 }
7478 if (type == bgp_show_type_neighbor
7479 || type == bgp_show_type_flap_neighbor
7480 || type == bgp_show_type_damp_neighbor)
7481 {
7482 union sockunion *su = output_arg;
718e3744 7483
4f280b15
LB
7484 if (ri->peer == NULL ||
7485 ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
856ca177
MS
7486 continue;
7487 }
a636c635 7488 if (type == bgp_show_type_cidr_only)
856ca177
MS
7489 {
7490 u_int32_t destination;
718e3744 7491
856ca177
MS
7492 destination = ntohl (rn->p.u.prefix4.s_addr);
7493 if (IN_CLASSC (destination) && rn->p.prefixlen == 24)
7494 continue;
7495 if (IN_CLASSB (destination) && rn->p.prefixlen == 16)
7496 continue;
7497 if (IN_CLASSA (destination) && rn->p.prefixlen == 8)
7498 continue;
7499 }
a636c635 7500 if (type == bgp_show_type_prefix_longer)
856ca177
MS
7501 {
7502 struct prefix *p = output_arg;
718e3744 7503
856ca177
MS
7504 if (! prefix_match (p, &rn->p))
7505 continue;
7506 }
7507 if (type == bgp_show_type_community_all)
7508 {
7509 if (! ri->attr->community)
7510 continue;
7511 }
7512 if (type == bgp_show_type_community)
7513 {
7514 struct community *com = output_arg;
718e3744 7515
856ca177
MS
7516 if (! ri->attr->community ||
7517 ! community_match (ri->attr->community, com))
7518 continue;
7519 }
7520 if (type == bgp_show_type_community_exact)
7521 {
7522 struct community *com = output_arg;
718e3744 7523
856ca177
MS
7524 if (! ri->attr->community ||
7525 ! community_cmp (ri->attr->community, com))
7526 continue;
7527 }
7528 if (type == bgp_show_type_community_list)
7529 {
7530 struct community_list *list = output_arg;
718e3744 7531
856ca177
MS
7532 if (! community_list_match (ri->attr->community, list))
7533 continue;
7534 }
7535 if (type == bgp_show_type_community_list_exact)
7536 {
7537 struct community_list *list = output_arg;
718e3744 7538
856ca177
MS
7539 if (! community_list_exact_match (ri->attr->community, list))
7540 continue;
7541 }
2acb4ac2
DL
7542 if (type == bgp_show_type_lcommunity)
7543 {
7544 struct lcommunity *lcom = output_arg;
57d187bc 7545
2acb4ac2
DL
7546 if (! ri->attr->extra || ! ri->attr->extra->lcommunity ||
7547 ! lcommunity_match (ri->attr->extra->lcommunity, lcom))
7548 continue;
7549 }
7550 if (type == bgp_show_type_lcommunity_list)
7551 {
7552 struct community_list *list = output_arg;
57d187bc 7553
2acb4ac2
DL
7554 if (! ri->attr->extra ||
7555 ! lcommunity_list_match (ri->attr->extra->lcommunity, list))
7556 continue;
7557 }
7558 if (type == bgp_show_type_lcommunity_all)
7559 {
7560 if (! ri->attr->extra || ! ri->attr->extra->lcommunity)
7561 continue;
7562 }
856ca177
MS
7563 if (type == bgp_show_type_dampend_paths
7564 || type == bgp_show_type_damp_neighbor)
7565 {
7566 if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)
7567 || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
7568 continue;
7569 }
7570
7571 if (!use_json && header)
7572 {
31303c3e 7573 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
7574 vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
7575 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
7576 if (type == bgp_show_type_dampend_paths
7577 || type == bgp_show_type_damp_neighbor)
7578 vty_out (vty, BGP_SHOW_DAMP_HEADER, VTY_NEWLINE);
7579 else if (type == bgp_show_type_flap_statistics
856ca177
MS
7580 || type == bgp_show_type_flap_neighbor)
7581 vty_out (vty, BGP_SHOW_FLAP_HEADER, VTY_NEWLINE);
7582 else
7583 vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
7584 header = 0;
7585 }
7586
7587 if (type == bgp_show_type_dampend_paths
7588 || type == bgp_show_type_damp_neighbor)
7589 damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths);
7590 else if (type == bgp_show_type_flap_statistics
856ca177
MS
7591 || type == bgp_show_type_flap_neighbor)
7592 flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths);
7593 else
7594 route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, json_paths);
7595 display++;
b05a1c8b
DS
7596 }
7597
856ca177
MS
7598 if (display)
7599 {
7600 output_count++;
7601 if (use_json)
7602 {
7603 p = &rn->p;
7604 sprintf(buf2, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
31303c3e
DS
7605 vty_out (vty, "\"%s\": ", buf2);
7606 vty_out (vty, "%s", json_object_to_json_string (json_paths));
7607 json_object_free (json_paths);
7608 first = 0;
7609
856ca177
MS
7610 }
7611 }
9f689658 7612 }
718e3744 7613
b05a1c8b 7614 if (use_json)
718e3744 7615 {
31303c3e
DS
7616 json_object_free (json_paths);
7617 vty_out (vty, " } }%s", VTY_NEWLINE);
718e3744 7618 }
7619 else
b05a1c8b
DS
7620 {
7621 /* No route is displayed */
7622 if (output_count == 0)
7623 {
7624 if (type == bgp_show_type_normal)
18200902 7625 vty_out (vty, "No BGP prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
b05a1c8b
DS
7626 }
7627 else
5c3cc3ae 7628 vty_out (vty, "%sDisplayed %ld routes and %ld total paths%s",
18200902 7629 VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
b05a1c8b 7630 }
718e3744 7631
7632 return CMD_SUCCESS;
7633}
7634
5a646650 7635static int
fee0f4c6 7636bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
856ca177 7637 enum bgp_show_type type, void *output_arg, u_char use_json)
fee0f4c6 7638{
7639 struct bgp_table *table;
7640
856ca177
MS
7641 if (bgp == NULL)
7642 {
7643 bgp = bgp_get_default ();
7644 }
fee0f4c6 7645
7646 if (bgp == NULL)
7647 {
856ca177
MS
7648 if (!use_json)
7649 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
fee0f4c6 7650 return CMD_WARNING;
7651 }
4f280b15
LB
7652 /* use MPLS and ENCAP specific shows until they are merged */
7653 if (safi == SAFI_MPLS_VPN)
7654 {
7655 return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg,
7656 0, use_json);
7657 }
7658 if (safi == SAFI_ENCAP)
7659 {
7660 return bgp_show_encap(vty, afi, NULL, type, output_arg,
7661 0);
7662 }
7663
fee0f4c6 7664
fee0f4c6 7665 table = bgp->rib[afi][safi];
7666
31303c3e
DS
7667 return bgp_show_table (vty, bgp, table, type, output_arg,
7668 use_json);
fee0f4c6 7669}
7670
f186de26 7671static void
7672bgp_show_all_instances_routes_vty (struct vty *vty, afi_t afi, safi_t safi,
7673 u_char use_json)
7674{
7675 struct listnode *node, *nnode;
7676 struct bgp *bgp;
7677 struct bgp_table *table;
9f689658
DD
7678 int is_first = 1;
7679
7680 if (use_json)
7681 vty_out (vty, "{%s", VTY_NEWLINE);
f186de26 7682
7683 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
7684 {
9f689658
DD
7685 if (use_json)
7686 {
9f689658
DD
7687 if (! is_first)
7688 vty_out (vty, ",%s", VTY_NEWLINE);
7689 else
7690 is_first = 0;
7691
7692 vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
7693 ? "Default" : bgp->name);
7694 }
7695 else
7696 {
7697 vty_out (vty, "%sInstance %s:%s",
7698 VTY_NEWLINE,
7699 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
7700 ? "Default" : bgp->name,
7701 VTY_NEWLINE);
7702 }
f186de26 7703 table = bgp->rib[afi][safi];
31303c3e
DS
7704 bgp_show_table (vty, bgp, table,
7705 bgp_show_type_normal, NULL, use_json);
9f689658 7706
f186de26 7707 }
9f689658
DD
7708
7709 if (use_json)
7710 vty_out (vty, "}%s", VTY_NEWLINE);
f186de26 7711}
7712
718e3744 7713/* Header of detailed BGP route information */
94f2b392 7714static void
718e3744 7715route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
7716 struct bgp_node *rn,
b05a1c8b
DS
7717 struct prefix_rd *prd, afi_t afi, safi_t safi,
7718 json_object *json)
718e3744 7719{
7720 struct bgp_info *ri;
7721 struct prefix *p;
7722 struct peer *peer;
1eb8ef25 7723 struct listnode *node, *nnode;
718e3744 7724 char buf1[INET6_ADDRSTRLEN];
7725 char buf2[INET6_ADDRSTRLEN];
7726 int count = 0;
7727 int best = 0;
7728 int suppress = 0;
7729 int no_export = 0;
7730 int no_advertise = 0;
7731 int local_as = 0;
adbac85e 7732 int first = 1;
ffd0c037 7733 json_object *json_adv_to = NULL;
718e3744 7734
7735 p = &rn->p;
b05a1c8b
DS
7736
7737 if (json)
7738 {
f1aa5d8a
DS
7739 json_object_string_add(json, "prefix", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN));
7740 json_object_int_add(json, "prefixlen", p->prefixlen);
b05a1c8b
DS
7741 }
7742 else
7743 {
7744 vty_out (vty, "BGP routing table entry for %s%s%s/%d%s",
3d6c0dfa 7745 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) ?
b05a1c8b 7746 prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
3d6c0dfa 7747 ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "",
b05a1c8b
DS
7748 inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN),
7749 p->prefixlen, VTY_NEWLINE);
7750 }
718e3744 7751
7752 for (ri = rn->info; ri; ri = ri->next)
7753 {
7754 count++;
7755 if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
7756 {
7757 best = count;
fb982c25 7758 if (ri->extra && ri->extra->suppress)
718e3744 7759 suppress = 1;
7760 if (ri->attr->community != NULL)
7761 {
7762 if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE))
7763 no_advertise = 1;
7764 if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT))
7765 no_export = 1;
7766 if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS))
7767 local_as = 1;
7768 }
7769 }
7770 }
7771
b05a1c8b 7772 if (!json)
718e3744 7773 {
b05a1c8b
DS
7774 vty_out (vty, "Paths: (%d available", count);
7775 if (best)
7776 {
7777 vty_out (vty, ", best #%d", best);
7778 if (safi == SAFI_UNICAST)
46827ae9
DS
7779 vty_out (vty, ", table %s",
7780 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
7781 ? "Default-IP-Routing-Table" : bgp->name);
b05a1c8b
DS
7782 }
7783 else
7784 vty_out (vty, ", no best path");
7785
7786 if (no_advertise)
7787 vty_out (vty, ", not advertised to any peer");
7788 else if (no_export)
7789 vty_out (vty, ", not advertised to EBGP peer");
7790 else if (local_as)
7791 vty_out (vty, ", not advertised outside local AS");
7792
7793 if (suppress)
7794 vty_out (vty, ", Advertisements suppressed by an aggregate.");
7795 vty_out (vty, ")%s", VTY_NEWLINE);
718e3744 7796 }
718e3744 7797
adbac85e
DW
7798 /* If we are not using addpath then we can display Advertised to and that will
7799 * show what peers we advertised the bestpath to. If we are using addpath
7800 * though then we must display Advertised to on a path-by-path basis. */
7801 if (!bgp->addpath_tx_used[afi][safi])
718e3744 7802 {
adbac85e
DW
7803 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
7804 {
7805 if (bgp_adj_out_lookup (peer, rn, 0))
b05a1c8b 7806 {
adbac85e 7807 if (json && !json_adv_to)
f1aa5d8a 7808 json_adv_to = json_object_new_object();
6410e93a 7809
adbac85e
DW
7810 route_vty_out_advertised_to(vty, peer, &first,
7811 " Advertised to non peer-group peers:\n ",
7812 json_adv_to);
b05a1c8b 7813 }
adbac85e 7814 }
036a4e7d 7815
adbac85e
DW
7816 if (json)
7817 {
7818 if (json_adv_to)
7819 {
7820 json_object_object_add(json, "advertisedTo", json_adv_to);
b05a1c8b 7821 }
adbac85e
DW
7822 }
7823 else
b05a1c8b 7824 {
adbac85e
DW
7825 if (first)
7826 vty_out (vty, " Not advertised to any peer");
7827 vty_out (vty, "%s", VTY_NEWLINE);
b05a1c8b
DS
7828 }
7829 }
718e3744 7830}
7831
7832/* Display specified route of BGP table. */
94f2b392 7833static int
fee0f4c6 7834bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
fd79ac91 7835 struct bgp_table *rib, const char *ip_str,
7836 afi_t afi, safi_t safi, struct prefix_rd *prd,
b05a1c8b
DS
7837 int prefix_check, enum bgp_path_type pathtype,
7838 u_char use_json)
718e3744 7839{
7840 int ret;
7841 int header;
7842 int display = 0;
7843 struct prefix match;
7844 struct bgp_node *rn;
7845 struct bgp_node *rm;
7846 struct bgp_info *ri;
718e3744 7847 struct bgp_table *table;
f1aa5d8a
DS
7848 json_object *json = NULL;
7849 json_object *json_paths = NULL;
718e3744 7850
718e3744 7851 /* Check IP address argument. */
7852 ret = str2prefix (ip_str, &match);
7853 if (! ret)
7854 {
7855 vty_out (vty, "address is malformed%s", VTY_NEWLINE);
7856 return CMD_WARNING;
7857 }
7858
7859 match.family = afi2family (afi);
7860
b05a1c8b
DS
7861 if (use_json)
7862 {
7863 json = json_object_new_object();
7864 json_paths = json_object_new_array();
7865 }
b05a1c8b 7866
3d6c0dfa 7867 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
718e3744 7868 {
fee0f4c6 7869 for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
718e3744 7870 {
7871 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
7872 continue;
7873
7874 if ((table = rn->info) != NULL)
7875 {
7876 header = 1;
7877
7878 if ((rm = bgp_node_match (table, &match)) != NULL)
7879 {
7880 if (prefix_check && rm->p.prefixlen != match.prefixlen)
6c88b44d
CC
7881 {
7882 bgp_unlock_node (rm);
7883 continue;
7884 }
718e3744 7885
7886 for (ri = rm->info; ri; ri = ri->next)
7887 {
7888 if (header)
7889 {
7890 route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p,
587ff0fd 7891 AFI_IP, safi, json);
718e3744 7892 header = 0;
7893 }
7894 display++;
4092b06c
DS
7895
7896 if (pathtype == BGP_PATH_ALL ||
7897 (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
7898 (pathtype == BGP_PATH_MULTIPATH &&
7899 (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
587ff0fd 7900 route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi, json_paths);
718e3744 7901 }
6c88b44d
CC
7902
7903 bgp_unlock_node (rm);
718e3744 7904 }
7905 }
7906 }
7907 }
7908 else
7909 {
7910 header = 1;
7911
fee0f4c6 7912 if ((rn = bgp_node_match (rib, &match)) != NULL)
718e3744 7913 {
7914 if (! prefix_check || rn->p.prefixlen == match.prefixlen)
7915 {
7916 for (ri = rn->info; ri; ri = ri->next)
7917 {
7918 if (header)
7919 {
b05a1c8b 7920 route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi, json);
718e3744 7921 header = 0;
7922 }
7923 display++;
4092b06c
DS
7924
7925 if (pathtype == BGP_PATH_ALL ||
7926 (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
7927 (pathtype == BGP_PATH_MULTIPATH &&
7928 (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
b05a1c8b 7929 route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, json_paths);
718e3744 7930 }
7931 }
6c88b44d
CC
7932
7933 bgp_unlock_node (rn);
718e3744 7934 }
7935 }
7936
e5eee9af 7937 if (use_json)
718e3744 7938 {
e5eee9af
DS
7939 if (display)
7940 json_object_object_add(json, "paths", json_paths);
7941
2aac5767 7942 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
f1aa5d8a 7943 json_object_free(json);
b05a1c8b
DS
7944 }
7945 else
7946 {
e5eee9af 7947 if (!display)
b05a1c8b
DS
7948 {
7949 vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
7950 return CMD_WARNING;
7951 }
7952 }
7953
718e3744 7954 return CMD_SUCCESS;
7955}
7956
fee0f4c6 7957/* Display specified route of Main RIB */
94f2b392 7958static int
c41247f5 7959bgp_show_route (struct vty *vty, struct bgp *bgp, const char *ip_str,
fee0f4c6 7960 afi_t afi, safi_t safi, struct prefix_rd *prd,
b05a1c8b
DS
7961 int prefix_check, enum bgp_path_type pathtype,
7962 u_char use_json)
fee0f4c6 7963{
41cebd7e
DS
7964 if (!bgp)
7965 bgp = bgp_get_default ();
7966
fee0f4c6 7967 return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str,
b05a1c8b
DS
7968 afi, safi, prd, prefix_check, pathtype,
7969 use_json);
fee0f4c6 7970}
fee0f4c6 7971
57d187bc
JS
7972static int
7973bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc,
2acb4ac2 7974 struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj)
57d187bc
JS
7975{
7976 struct lcommunity *lcom;
7977 struct buffer *b;
7978 int i;
7979 char *str;
7980 int first = 0;
7981
7982 b = buffer_new (1024);
7983 for (i = 0; i < argc; i++)
fee0f4c6 7984 {
57d187bc
JS
7985 if (first)
7986 buffer_putc (b, ' ');
7987 else
2acb4ac2
DL
7988 {
7989 if (strmatch (argv[i]->text, "<AA:BB:CC>"))
7990 {
7991 first = 1;
7992 buffer_putstr (b, argv[i]->arg);
7993 }
7994 }
fee0f4c6 7995 }
57d187bc
JS
7996 buffer_putc (b, '\0');
7997
7998 str = buffer_getstr (b);
7999 buffer_free (b);
8000
8001 lcom = lcommunity_str2com (str);
8002 XFREE (MTYPE_TMP, str);
8003 if (! lcom)
fee0f4c6 8004 {
57d187bc
JS
8005 vty_out (vty, "%% Large-community malformed: %s", VTY_NEWLINE);
8006 return CMD_WARNING;
fee0f4c6 8007 }
57d187bc
JS
8008
8009 return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, uj);
8010}
8011
8012static int
8013bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom,
2acb4ac2 8014 afi_t afi, safi_t safi, u_char uj)
57d187bc
JS
8015{
8016 struct community_list *list;
8017
8018 list = community_list_lookup (bgp_clist, lcom, LARGE_COMMUNITY_LIST_MASTER);
8019 if (list == NULL)
8020 {
8021 vty_out (vty, "%% %s is not a valid large-community-list name%s", lcom,
2acb4ac2 8022 VTY_NEWLINE);
57d187bc
JS
8023 return CMD_WARNING;
8024 }
8025
8026 return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_list, list, uj);
fee0f4c6 8027}
8028
52951b63
DS
8029DEFUN (show_ip_bgp_large_community_list,
8030 show_ip_bgp_large_community_list_cmd,
8031 "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] large-community-list <(1-500)|WORD> [json]",
8032 SHOW_STR
8033 IP_STR
8034 BGP_STR
8035 BGP_INSTANCE_HELP_STR
8036 "Address Family\n"
8037 "Address Family\n"
8038 "Address Family modifier\n"
8039 "Address Family modifier\n"
8040 "Address Family modifier\n"
8041 "Address Family modifier\n"
8042 "Display routes matching the large-community-list\n"
8043 "large-community-list number\n"
8044 "large-community-list name\n"
8045 JSON_STR)
8046{
8047 char *vrf = NULL;
8048 afi_t afi = AFI_IP6;
8049 safi_t safi = SAFI_UNICAST;
8050 int idx = 0;
8051
8052 if (argv_find (argv, argc, "ip", &idx))
8053 afi = AFI_IP;
8054 if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx))
8055 vrf = argv[++idx]->arg;
8056 if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx))
8057 {
8058 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
8059 if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
8060 safi = bgp_vty_safi_from_arg (argv[idx]->text);
8061 }
8062
8063 int uj = use_json (argc, argv);
8064
8065 struct bgp *bgp = bgp_lookup_by_name (vrf);
8066 if (bgp == NULL)
8067 {
8068 vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE);
8069 return CMD_WARNING;
8070 }
8071
8072 argv_find (argv, argc, "large-community-list", &idx);
8073 return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj);
8074}
8075DEFUN (show_ip_bgp_large_community,
8076 show_ip_bgp_large_community_cmd,
8077 "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] large-community [AA:BB:CC] [json]",
8078 SHOW_STR
8079 IP_STR
8080 BGP_STR
8081 BGP_INSTANCE_HELP_STR
8082 "Address Family\n"
8083 "Address Family\n"
8084 "Address Family modifier\n"
8085 "Address Family modifier\n"
8086 "Address Family modifier\n"
8087 "Address Family modifier\n"
8088 "Display routes matching the large-communities\n"
8089 "List of large-community numbers\n"
8090 JSON_STR)
8091{
8092 char *vrf = NULL;
8093 afi_t afi = AFI_IP6;
8094 safi_t safi = SAFI_UNICAST;
8095 int idx = 0;
8096
8097 if (argv_find (argv, argc, "ip", &idx))
8098 afi = AFI_IP;
8099 if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx))
8100 vrf = argv[++idx]->arg;
8101 if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx))
8102 {
8103 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
8104 if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
8105 safi = bgp_vty_safi_from_arg (argv[idx]->text);
8106 }
8107
8108 int uj = use_json (argc, argv);
8109
8110 struct bgp *bgp = bgp_lookup_by_name (vrf);
8111 if (bgp == NULL)
8112 {
8113 vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE);
8114 return CMD_WARNING;
8115 }
8116
8117 argv_find (argv, argc, "large-community", &idx);
8118 if (strmatch(argv[idx+1]->text, "AA:BB:CC"))
8119 return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj);
8120 else
8121 return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj);
8122}
8123
e01ca200
DS
8124static int bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi);
8125
718e3744 8126/* BGP route print out function. */
af462945
DS
8127DEFUN (show_ip_bgp,
8128 show_ip_bgp_cmd,
4f280b15 8129 "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]]\
ae19d7dd
QY
8130 [<\
8131 cidr-only\
8c3deaae 8132 |dampening <flap-statistics|dampened-paths|parameters>\
ae19d7dd
QY
8133 |route-map WORD\
8134 |prefix-list WORD\
8135 |filter-list WORD\
e01ca200 8136 |statistics\
0c7b1b01 8137 |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
ae19d7dd
QY
8138 |community-list <(1-500)|WORD> [exact-match]\
8139 |A.B.C.D/M longer-prefixes\
9711caf8
DS
8140 |X:X::X:X/M longer-prefixes>\
8141 ] [json]",
718e3744 8142 SHOW_STR
8143 IP_STR
8144 BGP_STR
a636c635 8145 BGP_INSTANCE_HELP_STR
4f280b15
LB
8146 BGP_AFI_HELP_STR
8147 BGP_SAFI_HELP_STR
a636c635 8148 "Display only routes with non-natural netmasks\n"
a636c635
DW
8149 "Display detailed information about dampening\n"
8150 "Display flap statistics of routes\n"
8151 "Display paths suppressed due to dampening\n"
af462945 8152 "Display detail of configured dampening parameters\n"
a636c635
DW
8153 "Display routes matching the route-map\n"
8154 "A route-map to match on\n"
8155 "Display routes conforming to the prefix-list\n"
8c3deaae 8156 "Prefix-list name\n"
a636c635
DW
8157 "Display routes conforming to the filter-list\n"
8158 "Regular expression access list name\n"
e01ca200 8159 "BGP RIB advertisement statistics\n"
a636c635
DW
8160 "Display routes matching the communities\n"
8161 COMMUNITY_AANN_STR
8162 "Do not send outside local AS (well-known community)\n"
8163 "Do not advertise to any peer (well-known community)\n"
8164 "Do not export to next AS (well-known community)\n"
8165 "Exact match of the communities\n"
8166 "Display routes matching the community-list\n"
8167 "community-list number\n"
8168 "community-list name\n"
8169 "Exact match of the communities\n"
0c7b1b01 8170 "IPv4 prefix\n"
8c3deaae 8171 "Display route and more specific routes\n"
0c7b1b01 8172 "IPv6 prefix\n"
a636c635 8173 "Display route and more specific routes\n"
9973d184 8174 JSON_STR)
718e3744 8175{
af462945 8176 vrf_id_t vrf = VRF_DEFAULT;
ae19d7dd
QY
8177 afi_t afi = AFI_IP6;
8178 safi_t safi = SAFI_UNICAST;
ef736f12 8179 int exact_match = 0;
a636c635 8180 enum bgp_show_type sh_type = bgp_show_type_normal;
af462945 8181 struct bgp *bgp = NULL;
ae19d7dd
QY
8182 int idx = 0;
8183
9317e17d 8184 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
af462945 8185 if (!idx)
c493f2d8
DS
8186 return CMD_WARNING;
8187
ae19d7dd
QY
8188 int uj = use_json (argc, argv);
8189 if (uj) argc--;
a636c635 8190
b4898a38 8191 bgp = bgp_lookup_by_vrf_id (vrf);
a636c635 8192 if (bgp == NULL)
af462945 8193 {
477be8c1
QY
8194 if (vrf == VRF_DEFAULT)
8195 vty_out (vty, "Can't find BGP instance (default)%s", VTY_NEWLINE);
8196 else
8197 vty_out (vty, "Can't find BGP instance %d%s", vrf, VTY_NEWLINE);
b4898a38 8198 return CMD_WARNING;
af462945 8199 }
718e3744 8200
af462945
DS
8201 if (argv_find(argv, argc, "cidr-only", &idx))
8202 return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj);
a636c635 8203
af462945 8204 if (argv_find(argv, argc, "dampening", &idx))
8c3deaae
QY
8205 {
8206 if (argv_find (argv, argc, "dampened-paths", &idx))
8207 return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj);
8208 else if (argv_find (argv, argc, "flap-statistics", &idx))
8209 return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj);
8210 else if (argv_find (argv, argc, "parameters", &idx))
af462945 8211 return bgp_show_dampening_parameters (vty, afi, safi);
8c3deaae 8212 }
a636c635 8213
af462945
DS
8214 if (argv_find(argv, argc, "prefix-list", &idx))
8215 return bgp_show_prefix_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list);
a636c635 8216
af462945
DS
8217 if (argv_find(argv, argc, "filter-list", &idx))
8218 return bgp_show_filter_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list);
a636c635 8219
e01ca200
DS
8220 if (argv_find(argv, argc, "statistics", &idx))
8221 return bgp_table_stats (vty, bgp, afi, safi);
a636c635 8222
af462945
DS
8223 if (argv_find(argv, argc, "route-map", &idx))
8224 return bgp_show_route_map (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map);
a636c635 8225
af462945 8226 if (argv_find(argv, argc, "community", &idx))
ae19d7dd
QY
8227 {
8228 /* show a specific community */
08435c2b
DS
8229 if (argv_find (argv, argc, "local-AS", &idx) ||
8230 argv_find (argv, argc, "no-advertise", &idx) ||
8231 argv_find (argv, argc, "no-export", &idx))
ae19d7dd 8232 {
08435c2b 8233 if (argv_find (argv, argc, "exact_match", &idx))
ae19d7dd 8234 exact_match = 1;
af462945 8235 return bgp_show_community (vty, bgp, argc, argv, exact_match, afi, safi);
ae19d7dd
QY
8236 }
8237 /* show all communities */
8238 else
8239 return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj);
8240 }
c016b6c7 8241
af462945
DS
8242 if (argv_find(argv, argc, "community-list", &idx))
8243 {
8244 const char *clist_number_or_name = argv[++idx]->arg;
0e37c258 8245 if (++idx < argc && strmatch (argv[idx]->text, "exact-match"))
af462945
DS
8246 exact_match = 1;
8247 return bgp_show_community_list (vty, bgp, clist_number_or_name, exact_match, afi, safi);
8248 }
8249 /* prefix-longer */
8250 if (argv_find(argv, argc, "A.B.C.D/M", &idx) || argv_find(argv, argc, "X:X::X:X/M", &idx))
8251 return bgp_show_prefix_longer (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_longer);
a636c635 8252
4e019978
PG
8253 if (safi == SAFI_MPLS_VPN)
8254 return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, uj);
8255 else if (safi == SAFI_ENCAP)
8256 return bgp_show_encap (vty, afi, NULL, bgp_show_type_normal, NULL, 0);
8257 else
8258 return bgp_show (vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 8259}
47fc97cc 8260
718e3744 8261DEFUN (show_ip_bgp_route,
8262 show_ip_bgp_route_cmd,
4f280b15 8263 "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]]"
ae19d7dd 8264 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 8265 SHOW_STR
8266 IP_STR
8267 BGP_STR
a636c635 8268 BGP_INSTANCE_HELP_STR
4f280b15
LB
8269 BGP_AFI_HELP_STR
8270 BGP_SAFI_HELP_STR
b05a1c8b 8271 "Network in the BGP routing table to display\n"
0c7b1b01 8272 "IPv4 prefix\n"
8c3deaae 8273 "Network in the BGP routing table to display\n"
0c7b1b01 8274 "IPv6 prefix\n"
4092b06c 8275 "Display only the bestpath\n"
b05a1c8b 8276 "Display only multipaths\n"
9973d184 8277 JSON_STR)
4092b06c 8278{
a636c635 8279 int prefix_check = 0;
ae19d7dd
QY
8280
8281 afi_t afi = AFI_IP6;
8282 safi_t safi = SAFI_UNICAST;
c41247f5 8283 vrf_id_t vrf = VRF_DEFAULT;;
ae19d7dd 8284 char *prefix = NULL;
c41247f5 8285 struct bgp *bgp = NULL;
a636c635 8286 enum bgp_path_type path_type;
db7c8528 8287 u_char uj = use_json(argc, argv);
b05a1c8b 8288
ae19d7dd
QY
8289 int idx = 0;
8290
9317e17d 8291 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
c41247f5 8292 if (!idx)
c493f2d8 8293 return CMD_WARNING;
c41247f5
DS
8294
8295 if (vrf != VRF_ALL)
8296 {
8297 bgp = bgp_lookup_by_vrf_id (vrf);
8298 if (bgp == NULL)
8299 {
8300 vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE);
8301 return CMD_WARNING;
8302 }
8303 }
8304 else
0e37c258
DS
8305 {
8306 vty_out (vty, "Specified 'all' vrf's but this command currently only works per view/vrf%s", VTY_NEWLINE);
8307 return CMD_WARNING;
8308 }
a636c635 8309
ae19d7dd
QY
8310 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8311 if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx))
a636c635 8312 prefix_check = 0;
ae19d7dd 8313 else if (argv_find (argv, argc, "A.B.C.D/M", &idx) || argv_find (argv, argc, "X:X::X:X/M", &idx))
a636c635
DW
8314 prefix_check = 1;
8315
ae19d7dd
QY
8316 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) && afi != AFI_IP6)
8317 {
8318 vty_out (vty, "%% Cannot specify IPv6 address or prefix with IPv4 AFI%s", VTY_NEWLINE);
8319 return CMD_WARNING;
8320 }
8321 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) && afi != AFI_IP)
8322 {
8323 vty_out (vty, "%% Cannot specify IPv4 address or prefix with IPv6 AFI%s", VTY_NEWLINE);
8324 return CMD_WARNING;
8325 }
a636c635 8326
ae19d7dd
QY
8327 prefix = argv[idx]->arg;
8328
8329 /* [<bestpath|multipath>] */
8330 if (argv_find (argv, argc, "bestpath", &idx))
a636c635 8331 path_type = BGP_PATH_BESTPATH;
ae19d7dd 8332 else if (argv_find (argv, argc, "multipath", &idx))
a636c635 8333 path_type = BGP_PATH_MULTIPATH;
4092b06c 8334 else
a636c635
DW
8335 path_type = BGP_PATH_ALL;
8336
c41247f5 8337 return bgp_show_route (vty, bgp, prefix, afi, safi, NULL, prefix_check, path_type, uj);
4092b06c
DS
8338}
8339
8c3deaae
QY
8340DEFUN (show_ip_bgp_regexp,
8341 show_ip_bgp_regexp_cmd,
1dc84b65 8342 "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
8343 SHOW_STR
8344 IP_STR
8345 BGP_STR
b00b230a 8346 BGP_INSTANCE_HELP_STR
4f280b15
LB
8347 BGP_AFI_HELP_STR
8348 BGP_SAFI_HELP_STR
8c3deaae
QY
8349 "Display routes matching the AS path regular expression\n"
8350 "A regular-expression to match the BGP AS paths\n")
8351{
b00b230a 8352 vrf_id_t vrf = VRF_DEFAULT;
8c3deaae
QY
8353 afi_t afi = AFI_IP6;
8354 safi_t safi = SAFI_UNICAST;
8355
8356 int idx = 0;
9317e17d 8357 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
b00b230a 8358 if (!idx)
c493f2d8 8359 return CMD_WARNING;
8c3deaae
QY
8360
8361 // get index of regex
8362 argv_find (argv, argc, "regexp", &idx);
8363 idx++;
8364
8365 char *regstr = argv_concat (argv, argc, idx);
8366 int rc = bgp_show_regexp (vty, (const char *) regstr, afi, safi, bgp_show_type_regexp);
8367 XFREE (MTYPE_TMP, regstr);
8368 return rc;
8369}
8370
a636c635
DW
8371DEFUN (show_ip_bgp_instance_all,
8372 show_ip_bgp_instance_all_cmd,
4f280b15 8373 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] [json]",
4092b06c 8374 SHOW_STR
a636c635 8375 IP_STR
4092b06c 8376 BGP_STR
a636c635 8377 BGP_INSTANCE_ALL_HELP_STR
4f280b15
LB
8378 BGP_AFI_HELP_STR
8379 BGP_SAFI_HELP_STR
9973d184 8380 JSON_STR)
4092b06c 8381{
f2a8972b 8382 vrf_id_t vrf = VRF_DEFAULT;
ae19d7dd
QY
8383 afi_t afi = AFI_IP;
8384 safi_t safi = SAFI_UNICAST;
8385
8386 int idx = 0;
9317e17d 8387 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
f2a8972b 8388 if (!idx)
c493f2d8 8389 return CMD_WARNING;
ae19d7dd 8390
f2a8972b
DS
8391 int uj = use_json (argc, argv);
8392 if (uj) argc--;
e3e29b32 8393
273f7743 8394 bgp_show_all_instances_routes_vty (vty, afi, safi, uj);
a636c635 8395 return CMD_SUCCESS;
e3e29b32
LB
8396}
8397
a636c635 8398static int
8c3deaae 8399bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi,
a636c635 8400 safi_t safi, enum bgp_show_type type)
718e3744 8401{
39e92c06 8402 return CMD_SUCCESS;
e3e29b32 8403
a636c635
DW
8404 regex_t *regex;
8405 int rc;
8406
a636c635 8407 regex = bgp_regcomp (regstr);
a636c635
DW
8408 if (! regex)
8409 {
8c3deaae 8410 vty_out (vty, "Can't compile regexp %s%s", regstr, VTY_NEWLINE);
a636c635
DW
8411 return CMD_WARNING;
8412 }
718e3744 8413
a636c635
DW
8414 rc = bgp_show (vty, NULL, afi, safi, type, regex, 0);
8415 bgp_regex_free (regex);
8416 return rc;
e3e29b32
LB
8417}
8418
a636c635 8419static int
af462945 8420bgp_show_prefix_list (struct vty *vty, struct bgp *bgp,
a636c635
DW
8421 const char *prefix_list_str, afi_t afi,
8422 safi_t safi, enum bgp_show_type type)
e3e29b32 8423{
a636c635 8424 struct prefix_list *plist;
e3e29b32 8425
a636c635
DW
8426 plist = prefix_list_lookup (afi, prefix_list_str);
8427 if (plist == NULL)
e3e29b32 8428 {
a636c635
DW
8429 vty_out (vty, "%% %s is not a valid prefix-list name%s",
8430 prefix_list_str, VTY_NEWLINE);
e3e29b32
LB
8431 return CMD_WARNING;
8432 }
a636c635
DW
8433
8434 return bgp_show (vty, bgp, afi, safi, type, plist, 0);
e3e29b32
LB
8435}
8436
a636c635 8437static int
af462945 8438bgp_show_filter_list (struct vty *vty, struct bgp *bgp,
a636c635
DW
8439 const char *filter, afi_t afi,
8440 safi_t safi, enum bgp_show_type type)
e3e29b32 8441{
a636c635 8442 struct as_list *as_list;
718e3744 8443
a636c635
DW
8444 as_list = as_list_lookup (filter);
8445 if (as_list == NULL)
718e3744 8446 {
a636c635 8447 vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE);
718e3744 8448 return CMD_WARNING;
8449 }
718e3744 8450
a636c635 8451 return bgp_show (vty, bgp, afi, safi, type, as_list, 0);
4092b06c
DS
8452}
8453
a636c635 8454static int
af462945 8455bgp_show_route_map (struct vty *vty, struct bgp *bgp,
a636c635
DW
8456 const char *rmap_str, afi_t afi,
8457 safi_t safi, enum bgp_show_type type)
4092b06c 8458{
a636c635 8459 struct route_map *rmap;
718e3744 8460
a636c635
DW
8461 rmap = route_map_lookup_by_name (rmap_str);
8462 if (! rmap)
718e3744 8463 {
a636c635
DW
8464 vty_out (vty, "%% %s is not a valid route-map name%s",
8465 rmap_str, VTY_NEWLINE);
718e3744 8466 return CMD_WARNING;
8467 }
a636c635
DW
8468
8469 return bgp_show (vty, bgp, afi, safi, type, rmap, 0);
718e3744 8470}
8471
a636c635 8472static int
af462945 8473bgp_show_community (struct vty *vty, struct bgp *bgp, int argc,
a636c635 8474 struct cmd_token **argv, int exact, afi_t afi, safi_t safi)
718e3744 8475{
a636c635
DW
8476 struct community *com;
8477 struct buffer *b;
a636c635
DW
8478 int i;
8479 char *str;
8480 int first = 0;
bb46e94f 8481
a636c635
DW
8482 b = buffer_new (1024);
8483 for (i = 0; i < argc; i++)
8484 {
8485 if (first)
8486 buffer_putc (b, ' ');
8487 else
8488 {
8489 if ((strcmp (argv[i]->arg, "unicast") == 0) || (strcmp (argv[i]->arg, "multicast") == 0))
8490 continue;
8491 first = 1;
8492 }
8493
8494 buffer_putstr (b, argv[i]->arg);
8495 }
8496 buffer_putc (b, '\0');
718e3744 8497
a636c635
DW
8498 str = buffer_getstr (b);
8499 buffer_free (b);
f186de26 8500
a636c635
DW
8501 com = community_str2com (str);
8502 XFREE (MTYPE_TMP, str);
8503 if (! com)
8504 {
8505 vty_out (vty, "%% Community malformed: %s", VTY_NEWLINE);
8506 return CMD_WARNING;
8507 }
f186de26 8508
a636c635
DW
8509 return bgp_show (vty, bgp, afi, safi,
8510 (exact ? bgp_show_type_community_exact :
8511 bgp_show_type_community), com, 0);
718e3744 8512}
8513
a636c635 8514static int
af462945 8515bgp_show_community_list (struct vty *vty, struct bgp *bgp,
a636c635
DW
8516 const char *com, int exact,
8517 afi_t afi, safi_t safi)
50ef26d4 8518{
a636c635 8519 struct community_list *list;
50ef26d4 8520
a636c635
DW
8521 list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_MASTER);
8522 if (list == NULL)
8523 {
8524 vty_out (vty, "%% %s is not a valid community-list name%s", com,
8525 VTY_NEWLINE);
8526 return CMD_WARNING;
8527 }
718e3744 8528
a636c635
DW
8529 return bgp_show (vty, bgp, afi, safi,
8530 (exact ? bgp_show_type_community_list_exact :
8531 bgp_show_type_community_list), list, 0);
50ef26d4 8532}
8533
a636c635 8534static int
af462945 8535bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp,
a636c635
DW
8536 const char *prefix, afi_t afi,
8537 safi_t safi, enum bgp_show_type type)
718e3744 8538{
a636c635
DW
8539 int ret;
8540 struct prefix *p;
718e3744 8541
a636c635 8542 p = prefix_new();
47fc97cc 8543
a636c635
DW
8544 ret = str2prefix (prefix, p);
8545 if (! ret)
8546 {
8547 vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
8548 return CMD_WARNING;
8549 }
95cbbd2a 8550
a636c635
DW
8551 ret = bgp_show (vty, bgp, afi, safi, type, p, 0);
8552 prefix_free(p);
8553 return ret;
47e9b292
DW
8554}
8555
a636c635 8556static struct peer *
30a6a167 8557peer_lookup_in_view (struct vty *vty, struct bgp *bgp,
a636c635 8558 const char *ip_str, u_char use_json)
718e3744 8559{
a636c635 8560 int ret;
a636c635
DW
8561 struct peer *peer;
8562 union sockunion su;
718e3744 8563
a636c635
DW
8564 /* Get peer sockunion. */
8565 ret = str2sockunion (ip_str, &su);
8566 if (ret < 0)
8567 {
8568 peer = peer_lookup_by_conf_if (bgp, ip_str);
8569 if (!peer)
8570 {
8571 peer = peer_lookup_by_hostname(bgp, ip_str);
8572
8573 if (!peer)
8574 {
8575 if (use_json)
8576 {
8577 json_object *json_no = NULL;
8578 json_no = json_object_new_object();
8579 json_object_string_add(json_no, "malformedAddressOrName", ip_str);
8580 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
8581 json_object_free(json_no);
8582 }
8583 else
8584 vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
8585 return NULL;
8586 }
2815e61f 8587 }
a636c635 8588 return peer;
2815e61f 8589 }
2815e61f 8590
a636c635
DW
8591 /* Peer structure lookup. */
8592 peer = peer_lookup (bgp, &su);
8593 if (! peer)
2815e61f 8594 {
a636c635 8595 if (use_json)
2815e61f 8596 {
a636c635
DW
8597 json_object *json_no = NULL;
8598 json_no = json_object_new_object();
8599 json_object_string_add(json_no, "warning","No such neighbor");
8600 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
8601 json_object_free(json_no);
2815e61f 8602 }
2815e61f 8603 else
a636c635
DW
8604 vty_out (vty, "No such neighbor%s", VTY_NEWLINE);
8605 return NULL;
2815e61f 8606 }
a636c635
DW
8607
8608 return peer;
2815e61f
PJ
8609}
8610
a636c635 8611enum bgp_stats
2815e61f 8612{
a636c635
DW
8613 BGP_STATS_MAXBITLEN = 0,
8614 BGP_STATS_RIB,
8615 BGP_STATS_PREFIXES,
8616 BGP_STATS_TOTPLEN,
8617 BGP_STATS_UNAGGREGATEABLE,
8618 BGP_STATS_MAX_AGGREGATEABLE,
8619 BGP_STATS_AGGREGATES,
8620 BGP_STATS_SPACE,
8621 BGP_STATS_ASPATH_COUNT,
8622 BGP_STATS_ASPATH_MAXHOPS,
8623 BGP_STATS_ASPATH_TOTHOPS,
8624 BGP_STATS_ASPATH_MAXSIZE,
8625 BGP_STATS_ASPATH_TOTSIZE,
8626 BGP_STATS_ASN_HIGHEST,
8627 BGP_STATS_MAX,
8628};
2815e61f 8629
a636c635 8630static const char *table_stats_strs[] =
2815e61f 8631{
a636c635
DW
8632 [BGP_STATS_PREFIXES] = "Total Prefixes",
8633 [BGP_STATS_TOTPLEN] = "Average prefix length",
8634 [BGP_STATS_RIB] = "Total Advertisements",
8635 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
8636 [BGP_STATS_MAX_AGGREGATEABLE] = "Maximum aggregateable prefixes",
8637 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
8638 [BGP_STATS_SPACE] = "Address space advertised",
8639 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
8640 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
8641 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
8642 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
8643 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
8644 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
8645 [BGP_STATS_MAX] = NULL,
8646};
2815e61f 8647
a636c635 8648struct bgp_table_stats
ff7924f6 8649{
a636c635
DW
8650 struct bgp_table *table;
8651 unsigned long long counts[BGP_STATS_MAX];
ff7924f6
PJ
8652};
8653
a636c635
DW
8654#if 0
8655#define TALLY_SIGFIG 100000
8656static unsigned long
8657ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 8658{
a636c635
DW
8659 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
8660 unsigned long res = (newtot * TALLY_SIGFIG) / count;
8661 unsigned long ret = newtot / count;
8662
8663 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
8664 return ret + 1;
8665 else
8666 return ret;
8667}
8668#endif
ff7924f6 8669
a636c635
DW
8670static int
8671bgp_table_stats_walker (struct thread *t)
2815e61f 8672{
a636c635
DW
8673 struct bgp_node *rn;
8674 struct bgp_node *top;
8675 struct bgp_table_stats *ts = THREAD_ARG (t);
8676 unsigned int space = 0;
8677
8678 if (!(top = bgp_table_top (ts->table)))
8679 return 0;
8680
8681 switch (top->p.family)
8682 {
8683 case AF_INET:
8684 space = IPV4_MAX_BITLEN;
8685 break;
8686 case AF_INET6:
8687 space = IPV6_MAX_BITLEN;
8688 break;
8689 }
8690
8691 ts->counts[BGP_STATS_MAXBITLEN] = space;
2815e61f 8692
a636c635 8693 for (rn = top; rn; rn = bgp_route_next (rn))
ff7924f6 8694 {
2815e61f 8695 struct bgp_info *ri;
a636c635
DW
8696 struct bgp_node *prn = bgp_node_parent_nolock (rn);
8697 unsigned int rinum = 0;
ff7924f6 8698
a636c635
DW
8699 if (rn == top)
8700 continue;
8701
8702 if (!rn->info)
8703 continue;
8704
8705 ts->counts[BGP_STATS_PREFIXES]++;
8706 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 8707
a636c635
DW
8708#if 0
8709 ts->counts[BGP_STATS_AVGPLEN]
8710 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
8711 ts->counts[BGP_STATS_AVGPLEN],
8712 rn->p.prefixlen);
8713#endif
8714
8715 /* check if the prefix is included by any other announcements */
8716 while (prn && !prn->info)
8717 prn = bgp_node_parent_nolock (prn);
8718
8719 if (prn == NULL || prn == top)
8720 {
8721 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
8722 /* announced address space */
8723 if (space)
8724 ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen);
8725 }
8726 else if (prn->info)
8727 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
8728
ff7924f6
PJ
8729 for (ri = rn->info; ri; ri = ri->next)
8730 {
a636c635
DW
8731 rinum++;
8732 ts->counts[BGP_STATS_RIB]++;
ff7924f6 8733
a636c635
DW
8734 if (ri->attr &&
8735 (CHECK_FLAG (ri->attr->flag,
8736 ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))))
8737 ts->counts[BGP_STATS_AGGREGATES]++;
ff7924f6 8738
a636c635
DW
8739 /* as-path stats */
8740 if (ri->attr && ri->attr->aspath)
ff7924f6 8741 {
a636c635
DW
8742 unsigned int hops = aspath_count_hops (ri->attr->aspath);
8743 unsigned int size = aspath_size (ri->attr->aspath);
8744 as_t highest = aspath_highest (ri->attr->aspath);
8745
8746 ts->counts[BGP_STATS_ASPATH_COUNT]++;
8747
8748 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
8749 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
8750
8751 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
8752 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
8753
8754 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
8755 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
8756#if 0
8757 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
8758 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
8759 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
8760 hops);
8761 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
8762 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
8763 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
8764 size);
8765#endif
8766 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
8767 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
ff7924f6
PJ
8768 }
8769 }
8770 }
2815e61f
PJ
8771 return 0;
8772}
ff7924f6 8773
2815e61f 8774static int
a636c635 8775bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
2815e61f 8776{
a636c635 8777 struct bgp_table_stats ts;
2815e61f
PJ
8778 unsigned int i;
8779
a636c635 8780 if (!bgp->rib[afi][safi])
2815e61f 8781 {
a636c635
DW
8782 vty_out (vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)%s",
8783 afi, safi, VTY_NEWLINE);
2815e61f
PJ
8784 return CMD_WARNING;
8785 }
8786
a636c635
DW
8787 memset (&ts, 0, sizeof (ts));
8788 ts.table = bgp->rib[afi][safi];
8789 thread_execute (bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 8790
a636c635
DW
8791 vty_out (vty, "BGP %s RIB statistics%s%s",
8792 afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE);
8793
8794 for (i = 0; i < BGP_STATS_MAX; i++)
ff7924f6 8795 {
a636c635
DW
8796 if (!table_stats_strs[i])
8797 continue;
8798
8799 switch (i)
856ca177 8800 {
a636c635
DW
8801#if 0
8802 case BGP_STATS_ASPATH_AVGHOPS:
8803 case BGP_STATS_ASPATH_AVGSIZE:
8804 case BGP_STATS_AVGPLEN:
8805 vty_out (vty, "%-30s: ", table_stats_strs[i]);
8806 vty_out (vty, "%12.2f",
8807 (float)ts.counts[i] / (float)TALLY_SIGFIG);
8808 break;
8809#endif
8810 case BGP_STATS_ASPATH_TOTHOPS:
8811 case BGP_STATS_ASPATH_TOTSIZE:
8812 vty_out (vty, "%-30s: ", table_stats_strs[i]);
8813 vty_out (vty, "%12.2f",
8814 ts.counts[i] ?
8815 (float)ts.counts[i] /
8816 (float)ts.counts[BGP_STATS_ASPATH_COUNT]
8817 : 0);
8818 break;
8819 case BGP_STATS_TOTPLEN:
8820 vty_out (vty, "%-30s: ", table_stats_strs[i]);
8821 vty_out (vty, "%12.2f",
8822 ts.counts[i] ?
8823 (float)ts.counts[i] /
8824 (float)ts.counts[BGP_STATS_PREFIXES]
8825 : 0);
8826 break;
8827 case BGP_STATS_SPACE:
8828 vty_out (vty, "%-30s: ", table_stats_strs[i]);
8829 vty_out (vty, "%12llu%s", ts.counts[i], VTY_NEWLINE);
8830 if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
8831 break;
8832 vty_out (vty, "%30s: ", "%% announced ");
8833 vty_out (vty, "%12.2f%s",
8834 100 * (float)ts.counts[BGP_STATS_SPACE] /
8835 (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]),
8836 VTY_NEWLINE);
8837 vty_out (vty, "%30s: ", "/8 equivalent ");
8838 vty_out (vty, "%12.2f%s",
8839 (float)ts.counts[BGP_STATS_SPACE] /
8840 (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)),
8841 VTY_NEWLINE);
8842 if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
8843 break;
8844 vty_out (vty, "%30s: ", "/24 equivalent ");
8845 vty_out (vty, "%12.2f",
8846 (float)ts.counts[BGP_STATS_SPACE] /
8847 (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24)));
8848 break;
8849 default:
8850 vty_out (vty, "%-30s: ", table_stats_strs[i]);
8851 vty_out (vty, "%12llu", ts.counts[i]);
856ca177 8852 }
a636c635
DW
8853
8854 vty_out (vty, "%s", VTY_NEWLINE);
ff7924f6 8855 }
ff7924f6
PJ
8856 return CMD_SUCCESS;
8857}
8858
a636c635
DW
8859enum bgp_pcounts
8860{
8861 PCOUNT_ADJ_IN = 0,
8862 PCOUNT_DAMPED,
8863 PCOUNT_REMOVED,
8864 PCOUNT_HISTORY,
8865 PCOUNT_STALE,
8866 PCOUNT_VALID,
8867 PCOUNT_ALL,
8868 PCOUNT_COUNTED,
8869 PCOUNT_PFCNT, /* the figure we display to users */
8870 PCOUNT_MAX,
8871};
718e3744 8872
a636c635
DW
8873static const char *pcount_strs[] =
8874{
8875 [PCOUNT_ADJ_IN] = "Adj-in",
8876 [PCOUNT_DAMPED] = "Damped",
8877 [PCOUNT_REMOVED] = "Removed",
8878 [PCOUNT_HISTORY] = "History",
8879 [PCOUNT_STALE] = "Stale",
8880 [PCOUNT_VALID] = "Valid",
8881 [PCOUNT_ALL] = "All RIB",
8882 [PCOUNT_COUNTED] = "PfxCt counted",
8883 [PCOUNT_PFCNT] = "Useable",
8884 [PCOUNT_MAX] = NULL,
8885};
718e3744 8886
a636c635
DW
8887struct peer_pcounts
8888{
8889 unsigned int count[PCOUNT_MAX];
8890 const struct peer *peer;
8891 const struct bgp_table *table;
8892};
47fc97cc 8893
a636c635
DW
8894static int
8895bgp_peer_count_walker (struct thread *t)
8896{
8897 struct bgp_node *rn;
8898 struct peer_pcounts *pc = THREAD_ARG (t);
8899 const struct peer *peer = pc->peer;
8900
8901 for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn))
718e3744 8902 {
a636c635
DW
8903 struct bgp_adj_in *ain;
8904 struct bgp_info *ri;
8905
8906 for (ain = rn->adj_in; ain; ain = ain->next)
8907 if (ain->peer == peer)
8908 pc->count[PCOUNT_ADJ_IN]++;
718e3744 8909
a636c635 8910 for (ri = rn->info; ri; ri = ri->next)
856ca177 8911 {
a636c635
DW
8912 char buf[SU_ADDRSTRLEN];
8913
8914 if (ri->peer != peer)
8915 continue;
8916
8917 pc->count[PCOUNT_ALL]++;
8918
8919 if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
8920 pc->count[PCOUNT_DAMPED]++;
8921 if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
8922 pc->count[PCOUNT_HISTORY]++;
8923 if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED))
8924 pc->count[PCOUNT_REMOVED]++;
8925 if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
8926 pc->count[PCOUNT_STALE]++;
8927 if (CHECK_FLAG (ri->flags, BGP_INFO_VALID))
8928 pc->count[PCOUNT_VALID]++;
8929 if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
8930 pc->count[PCOUNT_PFCNT]++;
8931
8932 if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
856ca177 8933 {
a636c635
DW
8934 pc->count[PCOUNT_COUNTED]++;
8935 if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
8936 zlog_warn ("%s [pcount] %s/%d is counted but flags 0x%x",
8937 peer->host,
8938 inet_ntop(rn->p.family, &rn->p.u.prefix,
8939 buf, SU_ADDRSTRLEN),
8940 rn->p.prefixlen,
8941 ri->flags);
8942 }
8943 else
8944 {
8945 if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
8946 zlog_warn ("%s [pcount] %s/%d not counted but flags 0x%x",
8947 peer->host,
8948 inet_ntop(rn->p.family, &rn->p.u.prefix,
8949 buf, SU_ADDRSTRLEN),
8950 rn->p.prefixlen,
8951 ri->flags);
856ca177
MS
8952 }
8953 }
856ca177 8954 }
a636c635 8955 return 0;
718e3744 8956}
8957
94f2b392 8958static int
a636c635 8959bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, u_char use_json)
856ca177 8960{
a636c635
DW
8961 struct peer_pcounts pcounts = { .peer = peer };
8962 unsigned int i;
856ca177 8963 json_object *json = NULL;
a636c635 8964 json_object *json_loop = NULL;
856ca177
MS
8965
8966 if (use_json)
718e3744 8967 {
a636c635
DW
8968 json = json_object_new_object();
8969 json_loop = json_object_new_object();
718e3744 8970 }
a636c635
DW
8971
8972 if (!peer || !peer->bgp || !peer->afc[afi][safi]
8973 || !peer->bgp->rib[afi][safi])
718e3744 8974 {
856ca177
MS
8975 if (use_json)
8976 {
a636c635 8977 json_object_string_add(json, "warning", "No such neighbor or address family");
856ca177
MS
8978 vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
8979 json_object_free(json);
8980 }
8981 else
a636c635 8982 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
856ca177 8983
718e3744 8984 return CMD_WARNING;
8985 }
a636c635
DW
8986
8987 memset (&pcounts, 0, sizeof(pcounts));
8988 pcounts.peer = peer;
8989 pcounts.table = peer->bgp->rib[afi][safi];
8990
8991 /* in-place call via thread subsystem so as to record execution time
8992 * * stats for the thread-walk (i.e. ensure this can't be blamed on
8993 * * on just vty_read()).
8994 * */
8995 thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0);
718e3744 8996
a636c635
DW
8997 if (use_json)
8998 {
8999 json_object_string_add(json, "prefixCountsFor", peer->host);
9000 json_object_string_add(json, "multiProtocol", afi_safi_print (afi, safi));
9001 json_object_int_add(json, "pfxCounter", peer->pcount[afi][safi]);
718e3744 9002
a636c635
DW
9003 for (i = 0; i < PCOUNT_MAX; i++)
9004 json_object_int_add(json_loop, pcount_strs[i], pcounts.count[i]);
718e3744 9005
a636c635 9006 json_object_object_add(json, "ribTableWalkCounters", json_loop);
856ca177 9007
a636c635
DW
9008 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
9009 {
9010 json_object_string_add(json, "pfxctDriftFor", peer->host);
9011 json_object_string_add(json, "recommended", "Please report this bug, with the above command output");
9012 }
9013 vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
9014 json_object_free(json);
9015 }
2a71e9ce 9016 else
a636c635 9017 {
2a71e9ce 9018
a636c635
DW
9019 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
9020 {
9021 vty_out (vty, "Prefix counts for %s/%s, %s%s",
9022 peer->hostname, peer->host, afi_safi_print (afi, safi),
9023 VTY_NEWLINE);
9024 }
9025 else
9026 {
9027 vty_out (vty, "Prefix counts for %s, %s%s",
9028 peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
9029 }
9030
9031 vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE);
9032 vty_out (vty, "%sCounts from RIB table walk:%s%s",
9033 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
9034
9035 for (i = 0; i < PCOUNT_MAX; i++)
9036 vty_out (vty, "%20s: %-10d%s", pcount_strs[i], pcounts.count[i], VTY_NEWLINE);
0b16f239 9037
a636c635
DW
9038 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
9039 {
9040 vty_out (vty, "%s [pcount] PfxCt drift!%s",
9041 peer->host, VTY_NEWLINE);
9042 vty_out (vty, "Please report this bug, with the above command output%s",
9043 VTY_NEWLINE);
9044 }
9045 }
9046
9047 return CMD_SUCCESS;
718e3744 9048}
9049
a636c635
DW
9050DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
9051 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
30a6a167
DS
9052 "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] "
9053 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 9054 SHOW_STR
9055 IP_STR
9056 BGP_STR
8386ac43 9057 BGP_INSTANCE_HELP_STR
8c3deaae 9058 "Address Family\n"
8c3deaae 9059 "Address Family\n"
a636c635
DW
9060 "Address Family modifier\n"
9061 "Address Family modifier\n"
30a6a167
DS
9062 "Address Family modifier\n"
9063 "Address Family modifier\n"
0b16f239
DS
9064 "Detailed information on TCP and BGP neighbor connections\n"
9065 "Neighbor to display information about\n"
9066 "Neighbor to display information about\n"
91d37724 9067 "Neighbor on BGP configured interface\n"
a636c635 9068 "Display detailed prefix count information\n"
9973d184 9069 JSON_STR)
0b16f239 9070{
30a6a167
DS
9071 vrf_id_t vrf = VRF_DEFAULT;
9072 afi_t afi = AFI_IP6;
9073 safi_t safi = SAFI_UNICAST;
0b16f239 9074 struct peer *peer;
30a6a167
DS
9075 int idx = 0;
9076 struct bgp *bgp = NULL;
856ca177 9077
9317e17d 9078 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
30a6a167 9079 if (!idx)
0b16f239
DS
9080 return CMD_WARNING;
9081
30a6a167
DS
9082 int uj = use_json (argc, argv);
9083 if (uj) argc--;
0b16f239 9084
30a6a167
DS
9085 if (vrf != VRF_ALL)
9086 {
9087 bgp = bgp_lookup_by_vrf_id (vrf);
9088 if (bgp == NULL)
9089 {
9090 if (uj)
9091 {
9092 json_object *json_no = NULL;
9093 json_no = json_object_new_object();
9094 json_object_string_add(json_no, "warning", "Can't find BGP view");
9095 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
9096 json_object_free(json_no);
9097 }
9098 else
9099 vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE);
9100 return CMD_WARNING;
9101 }
9102 }
9103 else
9104 bgp = NULL;
856ca177 9105
30a6a167
DS
9106 argv_find (argv, argc, "neighbors", &idx);
9107 peer = peer_lookup_in_view (vty, bgp, argv[idx+1]->arg, uj);
bb46e94f 9108 if (! peer)
9109 return CMD_WARNING;
9110
a636c635
DW
9111 return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj);
9112}
0b16f239 9113
d6902373
PG
9114#ifdef KEEP_OLD_VPN_COMMANDS
9115DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
9116 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
9117 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
9118 SHOW_STR
9119 IP_STR
9120 BGP_STR
d6902373 9121 BGP_VPNVX_HELP_STR
91d37724 9122 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
9123 "Detailed information on TCP and BGP neighbor connections\n"
9124 "Neighbor to display information about\n"
9125 "Neighbor to display information about\n"
91d37724 9126 "Neighbor on BGP configured interface\n"
a636c635 9127 "Display detailed prefix count information\n"
9973d184 9128 JSON_STR)
a636c635
DW
9129{
9130 int idx_peer = 6;
9131 struct peer *peer;
9132 u_char uj = use_json(argc, argv);
9133
9134 peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj);
9135 if (! peer)
9136 return CMD_WARNING;
9137
9138 return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
9139}
9140
d6902373
PG
9141DEFUN (show_ip_bgp_vpn_all_route_prefix,
9142 show_ip_bgp_vpn_all_route_prefix_cmd,
9143 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
9144 SHOW_STR
9145 IP_STR
9146 BGP_STR
d6902373 9147 BGP_VPNVX_HELP_STR
91d37724
QY
9148 "Display information about all VPNv4 NLRIs\n"
9149 "Network in the BGP routing table to display\n"
3a2d747c 9150 "Network in the BGP routing table to display\n"
9973d184 9151 JSON_STR)
91d37724
QY
9152{
9153 int idx = 0;
c49921c3 9154 char *network = NULL;
0e37c258
DS
9155 struct bgp *bgp = bgp_get_default();
9156 if (!bgp)
9157 {
9158 vty_out (vty, "Can't find default instance%s", VTY_NEWLINE);
9159 return CMD_WARNING;
9160 }
c49921c3
QY
9161 network = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
9162 network = argv_find (argv, argc, "A.B.C.D/M", &idx) ? argv[idx]->arg : NULL;
0e37c258 9163 return bgp_show_route (vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv));
91d37724 9164}
d6902373 9165#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 9166
a636c635
DW
9167static void
9168show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
9169 int in, const char *rmap_name, u_char use_json, json_object *json)
9170{
9171 struct bgp_table *table;
9172 struct bgp_adj_in *ain;
9173 struct bgp_adj_out *adj;
9174 unsigned long output_count;
9175 unsigned long filtered_count;
9176 struct bgp_node *rn;
9177 int header1 = 1;
9178 struct bgp *bgp;
9179 int header2 = 1;
9180 struct attr attr;
9181 struct attr_extra extra;
9182 int ret;
9183 struct update_subgroup *subgrp;
9184 json_object *json_scode = NULL;
9185 json_object *json_ocode = NULL;
9186 json_object *json_ar = NULL;
9187 struct peer_af *paf;
9188
9189 if (use_json)
9190 {
9191 json_scode = json_object_new_object();
9192 json_ocode = json_object_new_object();
9193 json_ar = json_object_new_object();
9194
9195 json_object_string_add(json_scode, "suppressed", "s");
9196 json_object_string_add(json_scode, "damped", "d");
9197 json_object_string_add(json_scode, "history", "h");
9198 json_object_string_add(json_scode, "valid", "*");
9199 json_object_string_add(json_scode, "best", ">");
9200 json_object_string_add(json_scode, "multipath", "=");
9201 json_object_string_add(json_scode, "internal", "i");
9202 json_object_string_add(json_scode, "ribFailure", "r");
9203 json_object_string_add(json_scode, "stale", "S");
9204 json_object_string_add(json_scode, "removed", "R");
9205
9206 json_object_string_add(json_ocode, "igp", "i");
9207 json_object_string_add(json_ocode, "egp", "e");
9208 json_object_string_add(json_ocode, "incomplete", "?");
9209 }
9210
9211 bgp = peer->bgp;
9212
9213 if (! bgp)
9214 {
9215 if (use_json)
9216 {
9217 json_object_string_add(json, "alert", "no BGP");
9218 vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
9219 json_object_free(json);
9220 }
9221 else
9222 vty_out (vty, "%% No bgp%s", VTY_NEWLINE);
9223 return;
9224 }
9225
9226 table = bgp->rib[afi][safi];
9227
9228 output_count = filtered_count = 0;
9229 subgrp = peer_subgroup(peer, afi, safi);
9230
9231 if (!in && subgrp && CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
9232 {
9233 if (use_json)
9234 {
9235 json_object_int_add(json, "bgpTableVersion", table->version);
9236 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
9237 json_object_object_add(json, "bgpStatusCodes", json_scode);
9238 json_object_object_add(json, "bgpOriginCodes", json_ocode);
9239 json_object_string_add(json, "bgpOriginatingDefaultNetwork", "0.0.0.0");
9240 }
9241 else
9242 {
9243 vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s%s", table->version, inet_ntoa (bgp->router_id), VTY_NEWLINE);
9244 vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
9245 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
9246
9247 vty_out (vty, "Originating default network 0.0.0.0%s%s",
9248 VTY_NEWLINE, VTY_NEWLINE);
9249 }
9250 header1 = 0;
9251 }
9252
9253 attr.extra = &extra;
9254 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
9255 {
9256 if (in)
9257 {
9258 for (ain = rn->adj_in; ain; ain = ain->next)
9259 {
9260 if (ain->peer == peer)
9261 {
9262 if (header1)
9263 {
9264 if (use_json)
9265 {
9266 json_object_int_add(json, "bgpTableVersion", 0);
9267 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
9268 json_object_object_add(json, "bgpStatusCodes", json_scode);
9269 json_object_object_add(json, "bgpOriginCodes", json_ocode);
9270 }
9271 else
9272 {
9273 vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
9274 vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
9275 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
9276 }
9277 header1 = 0;
9278 }
9279 if (header2)
9280 {
9281 if (!use_json)
9282 vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
9283 header2 = 0;
9284 }
9285 if (ain->attr)
9286 {
9287 bgp_attr_dup(&attr, ain->attr);
9288 if (bgp_input_modifier(peer, &rn->p, &attr, afi, safi, rmap_name) != RMAP_DENY)
9289 {
9290 route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar);
9291 output_count++;
9292 }
9293 else
9294 filtered_count++;
9295 }
9296 }
9297 }
9298 }
9299 else
9300 {
9301 for (adj = rn->adj_out; adj; adj = adj->next)
9302 SUBGRP_FOREACH_PEER(adj->subgroup, paf)
9303 if (paf->peer == peer)
9304 {
9305 if (header1)
9306 {
9307 if (use_json)
9308 {
9309 json_object_int_add(json, "bgpTableVersion", table->version);
9310 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
9311 json_object_object_add(json, "bgpStatusCodes", json_scode);
9312 json_object_object_add(json, "bgpOriginCodes", json_ocode);
9313 }
9314 else
9315 {
9316 vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s%s", table->version,
9317 inet_ntoa (bgp->router_id), VTY_NEWLINE);
9318 vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
9319 vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
9320 }
9321 header1 = 0;
9322 }
9323
9324 if (header2)
9325 {
9326 if (!use_json)
9327 vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
9328 header2 = 0;
9329 }
9330
9331 if (adj->attr)
9332 {
9333 bgp_attr_dup(&attr, adj->attr);
9334 ret = bgp_output_modifier(peer, &rn->p, &attr, afi, safi, rmap_name);
9335 if (ret != RMAP_DENY)
9336 {
9337 route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar);
9338 output_count++;
9339 }
9340 else
9341 filtered_count++;
9342 }
9343 }
9344 }
9345 }
9346 if (use_json)
9347 json_object_object_add(json, "advertisedRoutes", json_ar);
9348
9349 if (output_count != 0)
9350 {
9351 if (use_json)
9352 json_object_int_add(json, "totalPrefixCounter", output_count);
9353 else
9354 vty_out (vty, "%sTotal number of prefixes %ld%s",
9355 VTY_NEWLINE, output_count, VTY_NEWLINE);
9356 }
9357 if (use_json)
9358 {
9359 vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
9360 json_object_free(json);
9361 }
9362
9363}
2a71e9ce 9364
a636c635
DW
9365static int
9366peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
9367 int in, const char *rmap_name, u_char use_json)
0b16f239 9368{
a636c635 9369 json_object *json = NULL;
0b16f239 9370
a636c635
DW
9371 if (use_json)
9372 json = json_object_new_object();
0b16f239 9373
a636c635
DW
9374 if (!peer || !peer->afc[afi][safi])
9375 {
9376 if (use_json)
9377 {
9378 json_object_string_add(json, "warning", "No such neighbor or address family");
9379 vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
9380 json_object_free(json);
9381 }
9382 else
9383 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
9384
9385 return CMD_WARNING;
9386 }
0b16f239 9387
a636c635
DW
9388 if (in && !CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
9389 {
9390 if (use_json)
9391 {
9392 json_object_string_add(json, "warning", "Inbound soft reconfiguration not enabled");
9393 vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
9394 json_object_free(json);
9395 }
9396 else
9397 vty_out (vty, "%% Inbound soft reconfiguration not enabled%s", VTY_NEWLINE);
0b16f239 9398
a636c635
DW
9399 return CMD_WARNING;
9400 }
0b16f239 9401
a636c635 9402 show_adj_route (vty, peer, afi, safi, in, rmap_name, use_json, json);
0b16f239 9403
a636c635
DW
9404 return CMD_SUCCESS;
9405}
50ef26d4 9406
a636c635
DW
9407DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
9408 show_ip_bgp_instance_neighbor_advertised_route_cmd,
1dc84b65 9409 "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
1edcd642 9410 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
718e3744 9411 SHOW_STR
9412 IP_STR
9413 BGP_STR
a636c635 9414 BGP_INSTANCE_HELP_STR
7395a2c9
DS
9415 BGP_AFI_HELP_STR
9416 BGP_SAFI_HELP_STR
718e3744 9417 "Detailed information on TCP and BGP neighbor connections\n"
9418 "Neighbor to display information about\n"
9419 "Neighbor to display information about\n"
91d37724 9420 "Neighbor on BGP configured interface\n"
856ca177 9421 "Display the received routes from neighbor\n"
a636c635
DW
9422 "Display the routes advertised to a BGP neighbor\n"
9423 "Route-map to modify the attributes\n"
9424 "Name of the route map\n"
9973d184 9425 JSON_STR)
718e3744 9426{
30a6a167 9427 vrf_id_t vrf = VRF_DEFAULT;
8c3deaae
QY
9428 afi_t afi = AFI_IP6;
9429 safi_t safi = SAFI_UNICAST;
a636c635 9430 char *rmap_name = NULL;
8c3deaae 9431 char *peerstr = NULL;
c01d03a6 9432 int rcvd = 0;
30a6a167 9433 struct bgp *bgp = NULL;
bb46e94f 9434 struct peer *peer;
9435
8c3deaae 9436 int idx = 0;
718e3744 9437
9317e17d 9438 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
30a6a167 9439 if (!idx)
c493f2d8
DS
9440 return CMD_WARNING;
9441
30a6a167
DS
9442 int uj = use_json (argc, argv);
9443 if (uj) argc--;
9444
b4898a38
DS
9445 bgp = bgp_lookup_by_vrf_id (vrf);
9446 if (bgp == NULL)
30a6a167 9447 {
b4898a38
DS
9448 if (uj)
9449 {
9450 json_object *json_no = NULL;
9451 json_no = json_object_new_object();
9452 json_object_string_add(json_no, "warning", "Can't find BGP view");
9453 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
9454 json_object_free(json_no);
30a6a167 9455 }
b4898a38
DS
9456 else
9457 vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE);
9458 return CMD_WARNING;
30a6a167 9459 }
8c3deaae
QY
9460
9461 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
9462 argv_find (argv, argc, "neighbors", &idx);
9463 peerstr = argv[++idx]->arg;
9464
30a6a167 9465 peer = peer_lookup_in_view (vty, bgp, peerstr, uj);
a636c635 9466 if (! peer)
30a6a167 9467 return CMD_WARNING;
856ca177 9468
8c3deaae
QY
9469 if (argv_find (argv, argc, "received-routes", &idx))
9470 rcvd = 1;
9471 if (argv_find (argv, argc, "advertised-routes", &idx))
9472 rcvd = 0;
9473 if (argv_find (argv, argc, "route-map", &idx))
9474 rmap_name = argv[++idx]->arg;
95cbbd2a 9475
a636c635 9476 return peer_adj_routes (vty, peer, afi, safi, rcvd, rmap_name, uj);
95cbbd2a
ML
9477}
9478
718e3744 9479DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
9480 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 9481 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 9482 SHOW_STR
9483 IP_STR
9484 BGP_STR
8c3deaae
QY
9485 "Address Family\n"
9486 "Address Family\n"
718e3744 9487 "Address Family modifier\n"
9488 "Detailed information on TCP and BGP neighbor connections\n"
9489 "Neighbor to display information about\n"
9490 "Neighbor to display information about\n"
91d37724 9491 "Neighbor on BGP configured interface\n"
718e3744 9492 "Display information received from a BGP neighbor\n"
856ca177 9493 "Display the prefixlist filter\n"
9973d184 9494 JSON_STR)
718e3744 9495{
8c3deaae
QY
9496 afi_t afi = AFI_IP6;
9497 safi_t safi = SAFI_UNICAST;
9498 char *peerstr = NULL;
9499
718e3744 9500 char name[BUFSIZ];
c63b83fe 9501 union sockunion su;
718e3744 9502 struct peer *peer;
c63b83fe 9503 int count, ret;
718e3744 9504
8c3deaae 9505 int idx = 0;
718e3744 9506
8c3deaae
QY
9507 /* show [ip] bgp */
9508 if (argv_find (argv, argc, "ip", &idx))
9509 afi = AFI_IP;
9510 /* [<ipv4|ipv6> [unicast]] */
9511 if (argv_find (argv, argc, "ipv4", &idx))
9512 afi = AFI_IP;
9513 if (argv_find (argv, argc, "ipv6", &idx))
9514 afi = AFI_IP6;
9515 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
9516 argv_find (argv, argc, "neighbors", &idx);
9517 peerstr = argv[++idx]->arg;
9518
9519 u_char uj = use_json(argc, argv);
9520
9521 ret = str2sockunion (peerstr, &su);
c63b83fe
JBD
9522 if (ret < 0)
9523 {
8c3deaae 9524 peer = peer_lookup_by_conf_if (NULL, peerstr);
856ca177 9525 if (! peer)
a80beece 9526 {
db7c8528 9527 if (uj)
39573b33 9528 vty_out (vty, "{}%s", VTY_NEWLINE);
856ca177 9529 else
8c3deaae 9530 vty_out (vty, "%% Malformed address or name: %s%s", peerstr, VTY_NEWLINE);
a80beece
DS
9531 return CMD_WARNING;
9532 }
9533 }
9534 else
9535 {
9536 peer = peer_lookup (NULL, &su);
9537 if (! peer)
856ca177 9538 {
db7c8528 9539 if (uj)
39573b33 9540 vty_out (vty, "{}%s", VTY_NEWLINE);
856ca177
MS
9541 else
9542 vty_out (vty, "No peer%s", VTY_NEWLINE);
9543 return CMD_WARNING;
9544 }
c63b83fe 9545 }
718e3744 9546
39573b33
DW
9547 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
9548 count = prefix_bgp_show_prefix_list (NULL, afi, name, uj);
718e3744 9549 if (count)
9550 {
db7c8528 9551 if (!uj)
8c3deaae 9552 vty_out (vty, "Address Family: %s%s", afi_safi_print(afi, safi), VTY_NEWLINE);
39573b33 9553 prefix_bgp_show_prefix_list (vty, afi, name, uj);
856ca177
MS
9554 }
9555 else
9556 {
db7c8528 9557 if (uj)
39573b33 9558 vty_out (vty, "{}%s", VTY_NEWLINE);
856ca177
MS
9559 else
9560 vty_out (vty, "No functional output%s", VTY_NEWLINE);
718e3744 9561 }
9562
9563 return CMD_SUCCESS;
9564}
9565
94f2b392 9566static int
bb46e94f 9567bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi,
856ca177 9568 safi_t safi, enum bgp_show_type type, u_char use_json)
718e3744 9569{
718e3744 9570 if (! peer || ! peer->afc[afi][safi])
9571 {
856ca177
MS
9572 if (use_json)
9573 {
9574 json_object *json_no = NULL;
9575 json_no = json_object_new_object();
9576 json_object_string_add(json_no, "warning", "No such neighbor or address family");
9577 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
9578 json_object_free(json_no);
9579 }
9580 else
9581 vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
718e3744 9582 return CMD_WARNING;
9583 }
47fc97cc 9584
856ca177 9585 return bgp_show (vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 9586}
9587
9588DEFUN (show_ip_bgp_neighbor_routes,
9589 show_ip_bgp_neighbor_routes_cmd,
1dc84b65 9590 "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 9591 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 9592 SHOW_STR
9593 IP_STR
9594 BGP_STR
8386ac43 9595 BGP_INSTANCE_HELP_STR
4f280b15
LB
9596 BGP_AFI_HELP_STR
9597 BGP_SAFI_HELP_STR
718e3744 9598 "Detailed information on TCP and BGP neighbor connections\n"
9599 "Neighbor to display information about\n"
9600 "Neighbor to display information about\n"
91d37724 9601 "Neighbor on BGP configured interface\n"
2525cf39 9602 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
9603 "Display the dampened routes received from neighbor\n"
9604 "Display routes learned from neighbor\n"
9973d184 9605 JSON_STR)
718e3744 9606{
30a6a167 9607 vrf_id_t vrf = VRF_DEFAULT;
8c3deaae 9608 char *peerstr = NULL;
30a6a167 9609 struct bgp *bgp = NULL;
8c3deaae
QY
9610 afi_t afi = AFI_IP6;
9611 safi_t safi = SAFI_UNICAST;
bb46e94f 9612 struct peer *peer;
2525cf39 9613 enum bgp_show_type sh_type = bgp_show_type_neighbor;
856ca177 9614
8c3deaae 9615 int idx = 0;
bb46e94f 9616
9317e17d 9617 bgp_vty_find_and_parse_afi_safi_vrf (vty, argv, argc, &idx, &afi, &safi, &vrf);
30a6a167 9618 if (!idx)
c493f2d8
DS
9619 return CMD_WARNING;
9620
30a6a167
DS
9621 int uj = use_json (argc, argv);
9622 if (uj) argc--;
9623
9624 if (vrf != VRF_ALL)
9625 {
9626 bgp = bgp_lookup_by_vrf_id (vrf);
9627 if (bgp == NULL)
9628 {
9629 if (uj)
9630 {
9631 json_object *json_no = NULL;
9632 json_no = json_object_new_object();
9633 json_object_string_add(json_no, "warning", "Can't find BGP view");
9634 vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
9635 json_object_free(json_no);
9636 }
9637 else
9638 vty_out (vty, "Can't find BGP instance %s%s", argv[5]->arg, VTY_NEWLINE);
9639 return CMD_WARNING;
9640 }
9641 }
9642 else
9643 bgp = NULL;
9644
8c3deaae
QY
9645 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
9646 argv_find (argv, argc, "neighbors", &idx);
9647 peerstr = argv[++idx]->arg;
9648
30a6a167 9649 peer = peer_lookup_in_view (vty, bgp, peerstr, uj);
bb46e94f 9650 if (! peer)
2525cf39
DW
9651 {
9652 vty_out (vty, "No such neighbor%s", VTY_NEWLINE);
9653 return CMD_WARNING;
9654 }
bb46e94f 9655
8c3deaae 9656 if (argv_find (argv, argc, "flap-statistics", &idx))
2525cf39 9657 sh_type = bgp_show_type_flap_neighbor;
8c3deaae
QY
9658 else if (argv_find (argv, argc, "dampened-routes", &idx))
9659 sh_type = bgp_show_type_damp_neighbor;
9660 else if (argv_find (argv, argc, "routes", &idx))
9661 sh_type = bgp_show_type_neighbor;
2525cf39
DW
9662
9663 return bgp_show_neighbor_route (vty, peer, afi, safi, sh_type, uj);
50ef26d4 9664}
6b0655a2 9665
734b349e 9666struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 9667
9668struct bgp_distance
9669{
9670 /* Distance value for the IP source prefix. */
9671 u_char distance;
9672
9673 /* Name of the access-list to be matched. */
9674 char *access_list;
9675};
9676
4f280b15
LB
9677DEFUN (show_bgp_afi_vpn_rd_route,
9678 show_bgp_afi_vpn_rd_route_cmd,
9679 "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]",
9680 SHOW_STR
9681 BGP_STR
9682 BGP_AFI_HELP_STR
9683 "Address Family modifier\n"
9684 "Display information for a route distinguisher\n"
9685 "Route Distinguisher\n"
7395a2c9
DS
9686 "Network in the BGP routing table to display\n"
9687 "Network in the BGP routing table to display\n"
9688 JSON_STR)
4f280b15
LB
9689{
9690 int ret;
9691 struct prefix_rd prd;
9692 afi_t afi = AFI_MAX;
9693 int idx = 0;
9694
9695 argv_find_and_parse_afi (argv, argc, &idx, &afi);
9696 ret = str2prefix_rd (argv[5]->arg, &prd);
9697 if (! ret)
9698 {
9699 vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
9700 return CMD_WARNING;
9701 }
9702 return bgp_show_route (vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL, use_json (argc, argv));
9703}
9704
94f2b392 9705static struct bgp_distance *
66e5cd87 9706bgp_distance_new (void)
718e3744 9707{
393deb9b 9708 return XCALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
718e3744 9709}
9710
94f2b392 9711static void
718e3744 9712bgp_distance_free (struct bgp_distance *bdistance)
9713{
9714 XFREE (MTYPE_BGP_DISTANCE, bdistance);
9715}
9716
94f2b392 9717static int
fd79ac91 9718bgp_distance_set (struct vty *vty, const char *distance_str,
9719 const char *ip_str, const char *access_list_str)
718e3744 9720{
9721 int ret;
734b349e
MZ
9722 afi_t afi;
9723 safi_t safi;
9724 struct prefix p;
718e3744 9725 u_char distance;
9726 struct bgp_node *rn;
9727 struct bgp_distance *bdistance;
9728
734b349e
MZ
9729 afi = bgp_node_afi (vty);
9730 safi = bgp_node_safi (vty);
9731
9732 ret = str2prefix (ip_str, &p);
718e3744 9733 if (ret == 0)
9734 {
9735 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
9736 return CMD_WARNING;
9737 }
9738
9739 distance = atoi (distance_str);
9740
9741 /* Get BGP distance node. */
734b349e 9742 rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p);
718e3744 9743 if (rn->info)
9744 {
9745 bdistance = rn->info;
9746 bgp_unlock_node (rn);
9747 }
9748 else
9749 {
9750 bdistance = bgp_distance_new ();
9751 rn->info = bdistance;
9752 }
9753
9754 /* Set distance value. */
9755 bdistance->distance = distance;
9756
9757 /* Reset access-list configuration. */
9758 if (bdistance->access_list)
9759 {
6e919709 9760 XFREE(MTYPE_AS_LIST, bdistance->access_list);
718e3744 9761 bdistance->access_list = NULL;
9762 }
9763 if (access_list_str)
6e919709 9764 bdistance->access_list = XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 9765
9766 return CMD_SUCCESS;
9767}
9768
94f2b392 9769static int
fd79ac91 9770bgp_distance_unset (struct vty *vty, const char *distance_str,
9771 const char *ip_str, const char *access_list_str)
718e3744 9772{
9773 int ret;
734b349e
MZ
9774 afi_t afi;
9775 safi_t safi;
9776 struct prefix p;
1f9a9fff 9777 int distance;
718e3744 9778 struct bgp_node *rn;
9779 struct bgp_distance *bdistance;
9780
734b349e
MZ
9781 afi = bgp_node_afi (vty);
9782 safi = bgp_node_safi (vty);
9783
9784 ret = str2prefix (ip_str, &p);
718e3744 9785 if (ret == 0)
9786 {
9787 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
9788 return CMD_WARNING;
9789 }
9790
734b349e 9791 rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p);
718e3744 9792 if (! rn)
9793 {
9794 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
9795 return CMD_WARNING;
9796 }
9797
9798 bdistance = rn->info;
1f9a9fff
PJ
9799 distance = atoi(distance_str);
9800
9801 if (bdistance->distance != distance)
9802 {
9803 vty_out (vty, "Distance does not match configured%s", VTY_NEWLINE);
9804 return CMD_WARNING;
9805 }
718e3744 9806
9807 if (bdistance->access_list)
6e919709 9808 XFREE(MTYPE_AS_LIST, bdistance->access_list);
718e3744 9809 bgp_distance_free (bdistance);
9810
9811 rn->info = NULL;
9812 bgp_unlock_node (rn);
9813 bgp_unlock_node (rn);
9814
9815 return CMD_SUCCESS;
9816}
9817
718e3744 9818/* Apply BGP information to distance method. */
9819u_char
734b349e
MZ
9820bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi,
9821 safi_t safi, struct bgp *bgp)
718e3744 9822{
9823 struct bgp_node *rn;
734b349e 9824 struct prefix q;
718e3744 9825 struct peer *peer;
9826 struct bgp_distance *bdistance;
9827 struct access_list *alist;
9828 struct bgp_static *bgp_static;
9829
9830 if (! bgp)
9831 return 0;
9832
718e3744 9833 peer = rinfo->peer;
9834
718e3744 9835 /* Check source address. */
734b349e
MZ
9836 sockunion2hostprefix (&peer->su, &q);
9837 rn = bgp_node_match (bgp_distance_table[afi][safi], &q);
718e3744 9838 if (rn)
9839 {
9840 bdistance = rn->info;
9841 bgp_unlock_node (rn);
9842
9843 if (bdistance->access_list)
9844 {
734b349e 9845 alist = access_list_lookup (afi, bdistance->access_list);
718e3744 9846 if (alist && access_list_apply (alist, p) == FILTER_PERMIT)
9847 return bdistance->distance;
9848 }
9849 else
9850 return bdistance->distance;
9851 }
9852
9853 /* Backdoor check. */
734b349e 9854 rn = bgp_node_lookup (bgp->route[afi][safi], p);
718e3744 9855 if (rn)
9856 {
9857 bgp_static = rn->info;
9858 bgp_unlock_node (rn);
9859
9860 if (bgp_static->backdoor)
9861 {
734b349e
MZ
9862 if (bgp->distance_local[afi][safi])
9863 return bgp->distance_local[afi][safi];
718e3744 9864 else
9865 return ZEBRA_IBGP_DISTANCE_DEFAULT;
9866 }
9867 }
9868
6d85b15b 9869 if (peer->sort == BGP_PEER_EBGP)
718e3744 9870 {
734b349e
MZ
9871 if (bgp->distance_ebgp[afi][safi])
9872 return bgp->distance_ebgp[afi][safi];
718e3744 9873 return ZEBRA_EBGP_DISTANCE_DEFAULT;
9874 }
9875 else
9876 {
734b349e
MZ
9877 if (bgp->distance_ibgp[afi][safi])
9878 return bgp->distance_ibgp[afi][safi];
718e3744 9879 return ZEBRA_IBGP_DISTANCE_DEFAULT;
9880 }
9881}
9882
9883DEFUN (bgp_distance,
9884 bgp_distance_cmd,
6147e2c6 9885 "distance bgp (1-255) (1-255) (1-255)",
718e3744 9886 "Define an administrative distance\n"
9887 "BGP distance\n"
9888 "Distance for routes external to the AS\n"
9889 "Distance for routes internal to the AS\n"
9890 "Distance for local routes\n")
9891{
cdc2d765 9892 VTY_DECLVAR_CONTEXT(bgp, bgp);
c500ae40
DW
9893 int idx_number = 2;
9894 int idx_number_2 = 3;
9895 int idx_number_3 = 4;
734b349e
MZ
9896 afi_t afi;
9897 safi_t safi;
718e3744 9898
734b349e
MZ
9899 afi = bgp_node_afi (vty);
9900 safi = bgp_node_safi (vty);
718e3744 9901
39e92c06
QY
9902 bgp->distance_ebgp[afi][safi] = atoi (argv[idx_number]->arg);
9903 bgp->distance_ibgp[afi][safi] = atoi (argv[idx_number_2]->arg);
9904 bgp->distance_local[afi][safi] = atoi (argv[idx_number_3]->arg);
718e3744 9905 return CMD_SUCCESS;
9906}
9907
9908DEFUN (no_bgp_distance,
9909 no_bgp_distance_cmd,
a636c635 9910 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 9911 NO_STR
9912 "Define an administrative distance\n"
9913 "BGP distance\n"
9914 "Distance for routes external to the AS\n"
9915 "Distance for routes internal to the AS\n"
9916 "Distance for local routes\n")
9917{
cdc2d765 9918 VTY_DECLVAR_CONTEXT(bgp, bgp);
734b349e
MZ
9919 afi_t afi;
9920 safi_t safi;
718e3744 9921
734b349e
MZ
9922 afi = bgp_node_afi (vty);
9923 safi = bgp_node_safi (vty);
718e3744 9924
734b349e
MZ
9925 bgp->distance_ebgp[afi][safi] = 0;
9926 bgp->distance_ibgp[afi][safi] = 0;
9927 bgp->distance_local[afi][safi] = 0;
718e3744 9928 return CMD_SUCCESS;
9929}
9930
718e3744 9931
9932DEFUN (bgp_distance_source,
9933 bgp_distance_source_cmd,
6147e2c6 9934 "distance (1-255) A.B.C.D/M",
718e3744 9935 "Define an administrative distance\n"
9936 "Administrative distance\n"
9937 "IP source prefix\n")
9938{
c500ae40
DW
9939 int idx_number = 1;
9940 int idx_ipv4_prefixlen = 2;
9941 bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL);
718e3744 9942 return CMD_SUCCESS;
9943}
9944
9945DEFUN (no_bgp_distance_source,
9946 no_bgp_distance_source_cmd,
6147e2c6 9947 "no distance (1-255) A.B.C.D/M",
718e3744 9948 NO_STR
9949 "Define an administrative distance\n"
9950 "Administrative distance\n"
9951 "IP source prefix\n")
9952{
c500ae40
DW
9953 int idx_number = 2;
9954 int idx_ipv4_prefixlen = 3;
9955 bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL);
718e3744 9956 return CMD_SUCCESS;
9957}
9958
9959DEFUN (bgp_distance_source_access_list,
9960 bgp_distance_source_access_list_cmd,
6147e2c6 9961 "distance (1-255) A.B.C.D/M WORD",
718e3744 9962 "Define an administrative distance\n"
9963 "Administrative distance\n"
9964 "IP source prefix\n"
9965 "Access list name\n")
9966{
c500ae40
DW
9967 int idx_number = 1;
9968 int idx_ipv4_prefixlen = 2;
9969 int idx_word = 3;
9970 bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
718e3744 9971 return CMD_SUCCESS;
9972}
9973
9974DEFUN (no_bgp_distance_source_access_list,
9975 no_bgp_distance_source_access_list_cmd,
6147e2c6 9976 "no distance (1-255) A.B.C.D/M WORD",
718e3744 9977 NO_STR
9978 "Define an administrative distance\n"
9979 "Administrative distance\n"
9980 "IP source prefix\n"
9981 "Access list name\n")
9982{
c500ae40
DW
9983 int idx_number = 2;
9984 int idx_ipv4_prefixlen = 3;
9985 int idx_word = 4;
9986 bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
718e3744 9987 return CMD_SUCCESS;
9988}
6b0655a2 9989
734b349e
MZ
9990DEFUN (ipv6_bgp_distance_source,
9991 ipv6_bgp_distance_source_cmd,
39e92c06 9992 "distance (1-255) X:X::X:X/M",
734b349e
MZ
9993 "Define an administrative distance\n"
9994 "Administrative distance\n"
9995 "IP source prefix\n")
9996{
39e92c06 9997 bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, NULL);
734b349e
MZ
9998 return CMD_SUCCESS;
9999}
10000
10001DEFUN (no_ipv6_bgp_distance_source,
10002 no_ipv6_bgp_distance_source_cmd,
39e92c06 10003 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
10004 NO_STR
10005 "Define an administrative distance\n"
10006 "Administrative distance\n"
10007 "IP source prefix\n")
10008{
39e92c06 10009 bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, NULL);
734b349e
MZ
10010 return CMD_SUCCESS;
10011}
10012
10013DEFUN (ipv6_bgp_distance_source_access_list,
10014 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10015 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10016 "Define an administrative distance\n"
10017 "Administrative distance\n"
10018 "IP source prefix\n"
10019 "Access list name\n")
10020{
39e92c06 10021 bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
734b349e
MZ
10022 return CMD_SUCCESS;
10023}
10024
10025DEFUN (no_ipv6_bgp_distance_source_access_list,
10026 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10027 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10028 NO_STR
10029 "Define an administrative distance\n"
10030 "Administrative distance\n"
10031 "IP source prefix\n"
10032 "Access list name\n")
10033{
39e92c06 10034 bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
734b349e
MZ
10035 return CMD_SUCCESS;
10036}
10037
718e3744 10038DEFUN (bgp_damp_set,
10039 bgp_damp_set_cmd,
31500417 10040 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10041 "BGP Specific commands\n"
10042 "Enable route-flap dampening\n"
10043 "Half-life time for the penalty\n"
10044 "Value to start reusing a route\n"
10045 "Value to start suppressing a route\n"
10046 "Maximum duration to suppress a stable route\n")
10047{
cdc2d765 10048 VTY_DECLVAR_CONTEXT(bgp, bgp);
31500417
DW
10049 int idx_half_life = 2;
10050 int idx_reuse = 3;
10051 int idx_suppress = 4;
10052 int idx_max_suppress = 5;
718e3744 10053 int half = DEFAULT_HALF_LIFE * 60;
10054 int reuse = DEFAULT_REUSE;
10055 int suppress = DEFAULT_SUPPRESS;
10056 int max = 4 * half;
10057
31500417 10058 if (argc == 6)
718e3744 10059 {
31500417
DW
10060 half = atoi (argv[idx_half_life]->arg) * 60;
10061 reuse = atoi (argv[idx_reuse]->arg);
10062 suppress = atoi (argv[idx_suppress]->arg);
10063 max = atoi (argv[idx_max_suppress]->arg) * 60;
718e3744 10064 }
31500417 10065 else if (argc == 3)
718e3744 10066 {
31500417 10067 half = atoi (argv[idx_half_life]->arg) * 60;
718e3744 10068 max = 4 * half;
10069 }
10070
7ebe9748
B
10071 if (suppress < reuse)
10072 {
10073 vty_out (vty, "Suppress value cannot be less than reuse value %s",
10074 VTY_NEWLINE);
10075 return 0;
10076 }
10077
718e3744 10078 return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty),
10079 half, reuse, suppress, max);
10080}
10081
718e3744 10082DEFUN (bgp_damp_unset,
10083 bgp_damp_unset_cmd,
d04c479d 10084 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10085 NO_STR
10086 "BGP Specific commands\n"
16cedbb0
QY
10087 "Enable route-flap dampening\n"
10088 "Half-life time for the penalty\n"
10089 "Value to start reusing a route\n"
10090 "Value to start suppressing a route\n"
10091 "Maximum duration to suppress a stable route\n")
718e3744 10092{
cdc2d765 10093 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 10094 return bgp_damp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty));
10095}
10096
718e3744 10097/* Display specified route of BGP table. */
94f2b392 10098static int
fd79ac91 10099bgp_clear_damp_route (struct vty *vty, const char *view_name,
10100 const char *ip_str, afi_t afi, safi_t safi,
10101 struct prefix_rd *prd, int prefix_check)
718e3744 10102{
10103 int ret;
10104 struct prefix match;
10105 struct bgp_node *rn;
10106 struct bgp_node *rm;
10107 struct bgp_info *ri;
10108 struct bgp_info *ri_temp;
10109 struct bgp *bgp;
10110 struct bgp_table *table;
10111
10112 /* BGP structure lookup. */
10113 if (view_name)
10114 {
10115 bgp = bgp_lookup_by_name (view_name);
10116 if (bgp == NULL)
10117 {
6aeb9e78 10118 vty_out (vty, "%% Can't find BGP instance %s%s", view_name, VTY_NEWLINE);
718e3744 10119 return CMD_WARNING;
10120 }
10121 }
10122 else
10123 {
10124 bgp = bgp_get_default ();
10125 if (bgp == NULL)
10126 {
10127 vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE);
10128 return CMD_WARNING;
10129 }
10130 }
10131
10132 /* Check IP address argument. */
10133 ret = str2prefix (ip_str, &match);
10134 if (! ret)
10135 {
10136 vty_out (vty, "%% address is malformed%s", VTY_NEWLINE);
10137 return CMD_WARNING;
10138 }
10139
10140 match.family = afi2family (afi);
10141
3d6c0dfa 10142 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN))
718e3744 10143 {
587ff0fd 10144 for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn))
718e3744 10145 {
10146 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
10147 continue;
10148
10149 if ((table = rn->info) != NULL)
10150 if ((rm = bgp_node_match (table, &match)) != NULL)
6c88b44d
CC
10151 {
10152 if (! prefix_check || rm->p.prefixlen == match.prefixlen)
10153 {
10154 ri = rm->info;
10155 while (ri)
10156 {
10157 if (ri->extra && ri->extra->damp_info)
10158 {
10159 ri_temp = ri->next;
10160 bgp_damp_info_free (ri->extra->damp_info, 1);
10161 ri = ri_temp;
10162 }
10163 else
10164 ri = ri->next;
10165 }
10166 }
10167
10168 bgp_unlock_node (rm);
10169 }
718e3744 10170 }
10171 }
10172 else
10173 {
10174 if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
6c88b44d
CC
10175 {
10176 if (! prefix_check || rn->p.prefixlen == match.prefixlen)
10177 {
10178 ri = rn->info;
10179 while (ri)
10180 {
10181 if (ri->extra && ri->extra->damp_info)
10182 {
10183 ri_temp = ri->next;
10184 bgp_damp_info_free (ri->extra->damp_info, 1);
10185 ri = ri_temp;
10186 }
10187 else
10188 ri = ri->next;
10189 }
10190 }
10191
10192 bgp_unlock_node (rn);
10193 }
718e3744 10194 }
10195
10196 return CMD_SUCCESS;
10197}
10198
10199DEFUN (clear_ip_bgp_dampening,
10200 clear_ip_bgp_dampening_cmd,
10201 "clear ip bgp dampening",
10202 CLEAR_STR
10203 IP_STR
10204 BGP_STR
10205 "Clear route flap dampening information\n")
10206{
10207 bgp_damp_info_clean ();
10208 return CMD_SUCCESS;
10209}
10210
10211DEFUN (clear_ip_bgp_dampening_prefix,
10212 clear_ip_bgp_dampening_prefix_cmd,
10213 "clear ip bgp dampening A.B.C.D/M",
10214 CLEAR_STR
10215 IP_STR
10216 BGP_STR
10217 "Clear route flap dampening information\n"
0c7b1b01 10218 "IPv4 prefix\n")
718e3744 10219{
c500ae40
DW
10220 int idx_ipv4_prefixlen = 4;
10221 return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
718e3744 10222 SAFI_UNICAST, NULL, 1);
10223}
10224
10225DEFUN (clear_ip_bgp_dampening_address,
10226 clear_ip_bgp_dampening_address_cmd,
10227 "clear ip bgp dampening A.B.C.D",
10228 CLEAR_STR
10229 IP_STR
10230 BGP_STR
10231 "Clear route flap dampening information\n"
10232 "Network to clear damping information\n")
10233{
c500ae40
DW
10234 int idx_ipv4 = 4;
10235 return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
718e3744 10236 SAFI_UNICAST, NULL, 0);
10237}
10238
10239DEFUN (clear_ip_bgp_dampening_address_mask,
10240 clear_ip_bgp_dampening_address_mask_cmd,
10241 "clear ip bgp dampening A.B.C.D A.B.C.D",
10242 CLEAR_STR
10243 IP_STR
10244 BGP_STR
10245 "Clear route flap dampening information\n"
10246 "Network to clear damping information\n"
10247 "Network mask\n")
10248{
c500ae40
DW
10249 int idx_ipv4 = 4;
10250 int idx_ipv4_2 = 5;
718e3744 10251 int ret;
10252 char prefix_str[BUFSIZ];
10253
c500ae40 10254 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str);
718e3744 10255 if (! ret)
10256 {
10257 vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
10258 return CMD_WARNING;
10259 }
10260
10261 return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP,
10262 SAFI_UNICAST, NULL, 0);
10263}
6b0655a2 10264
587ff0fd 10265/* also used for encap safi */
94f2b392 10266static int
c286be96 10267bgp_config_write_network_vpn (struct vty *vty, struct bgp *bgp,
718e3744 10268 afi_t afi, safi_t safi, int *write)
10269{
10270 struct bgp_node *prn;
10271 struct bgp_node *rn;
10272 struct bgp_table *table;
10273 struct prefix *p;
10274 struct prefix_rd *prd;
10275 struct bgp_static *bgp_static;
10276 u_int32_t label;
10277 char buf[SU_ADDRSTRLEN];
10278 char rdbuf[RD_ADDRSTRLEN];
10279
10280 /* Network configuration. */
10281 for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn))
10282 if ((table = prn->info) != NULL)
10283 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
10284 if ((bgp_static = rn->info) != NULL)
10285 {
10286 p = &rn->p;
10287 prd = (struct prefix_rd *) &prn->p;
10288
10289 /* "address-family" display. */
10290 bgp_config_write_family_header (vty, afi, safi, write);
10291
10292 /* "network" configuration display. */
10293 prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
10294 label = decode_label (bgp_static->tag);
10295
0b960b4d 10296 vty_out (vty, " network %s/%d rd %s tag %d",
718e3744 10297 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
10298 p->prefixlen,
10299 rdbuf, label);
10300 vty_out (vty, "%s", VTY_NEWLINE);
10301 }
10302 return 0;
10303}
10304
10305/* Configuration of static route announcement and aggregate
10306 information. */
10307int
10308bgp_config_write_network (struct vty *vty, struct bgp *bgp,
10309 afi_t afi, safi_t safi, int *write)
10310{
10311 struct bgp_node *rn;
10312 struct prefix *p;
10313 struct bgp_static *bgp_static;
10314 struct bgp_aggregate *bgp_aggregate;
10315 char buf[SU_ADDRSTRLEN];
10316
c286be96
LX
10317 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
10318 return bgp_config_write_network_vpn (vty, bgp, afi, safi, write);
718e3744 10319
10320 /* Network configuration. */
10321 for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
10322 if ((bgp_static = rn->info) != NULL)
10323 {
10324 p = &rn->p;
10325
10326 /* "address-family" display. */
10327 bgp_config_write_family_header (vty, afi, safi, write);
10328
10329 /* "network" configuration display. */
10330 if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP)
10331 {
10332 u_int32_t destination;
10333 struct in_addr netmask;
10334
10335 destination = ntohl (p->u.prefix4.s_addr);
10336 masklen2ip (p->prefixlen, &netmask);
0b960b4d 10337 vty_out (vty, " network %s",
718e3744 10338 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN));
10339
10340 if ((IN_CLASSC (destination) && p->prefixlen == 24)
10341 || (IN_CLASSB (destination) && p->prefixlen == 16)
10342 || (IN_CLASSA (destination) && p->prefixlen == 8)
10343 || p->u.prefix4.s_addr == 0)
10344 {
10345 /* Natural mask is not display. */
10346 }
10347 else
10348 vty_out (vty, " mask %s", inet_ntoa (netmask));
10349 }
10350 else
10351 {
0b960b4d 10352 vty_out (vty, " network %s/%d",
718e3744 10353 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
10354 p->prefixlen);
10355 }
10356
10357 if (bgp_static->rmap.name)
10358 vty_out (vty, " route-map %s", bgp_static->rmap.name);
41367172
PJ
10359 else
10360 {
10361 if (bgp_static->backdoor)
10362 vty_out (vty, " backdoor");
41367172 10363 }
718e3744 10364
10365 vty_out (vty, "%s", VTY_NEWLINE);
10366 }
10367
10368 /* Aggregate-address configuration. */
10369 for (rn = bgp_table_top (bgp->aggregate[afi][safi]); rn; rn = bgp_route_next (rn))
10370 if ((bgp_aggregate = rn->info) != NULL)
10371 {
10372 p = &rn->p;
10373
10374 /* "address-family" display. */
10375 bgp_config_write_family_header (vty, afi, safi, write);
10376
10377 if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP)
10378 {
10379 struct in_addr netmask;
10380
10381 masklen2ip (p->prefixlen, &netmask);
0b960b4d 10382 vty_out (vty, " aggregate-address %s %s",
718e3744 10383 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
10384 inet_ntoa (netmask));
10385 }
10386 else
10387 {
0b960b4d 10388 vty_out (vty, " aggregate-address %s/%d",
718e3744 10389 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
10390 p->prefixlen);
10391 }
10392
10393 if (bgp_aggregate->as_set)
10394 vty_out (vty, " as-set");
10395
10396 if (bgp_aggregate->summary_only)
10397 vty_out (vty, " summary-only");
10398
10399 vty_out (vty, "%s", VTY_NEWLINE);
10400 }
10401
10402 return 0;
10403}
10404
10405int
734b349e
MZ
10406bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi,
10407 safi_t safi, int *write)
718e3744 10408{
10409 struct bgp_node *rn;
10410 struct bgp_distance *bdistance;
10411
10412 /* Distance configuration. */
734b349e
MZ
10413 if (bgp->distance_ebgp[afi][safi]
10414 && bgp->distance_ibgp[afi][safi]
10415 && bgp->distance_local[afi][safi]
10416 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
10417 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
10418 || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT))
10419 {
10420 bgp_config_write_family_header (vty, afi, safi, write);
10421 vty_out (vty, " distance bgp %d %d %d%s",
10422 bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi],
10423 bgp->distance_local[afi][safi], VTY_NEWLINE);
10424 }
10425
10426 for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn;
10427 rn = bgp_route_next (rn))
718e3744 10428 if ((bdistance = rn->info) != NULL)
10429 {
734b349e
MZ
10430 char buf[PREFIX_STRLEN];
10431
10432 bgp_config_write_family_header (vty, afi, safi, write);
10433 vty_out (vty, " distance %d %s %s%s", bdistance->distance,
10434 prefix2str (&rn->p, buf, sizeof (buf)),
718e3744 10435 bdistance->access_list ? bdistance->access_list : "",
10436 VTY_NEWLINE);
10437 }
10438
734b349e 10439 return *write;
718e3744 10440}
10441
10442/* Allocate routing table structure and install commands. */
10443void
66e5cd87 10444bgp_route_init (void)
718e3744 10445{
734b349e
MZ
10446 afi_t afi;
10447 safi_t safi;
10448
718e3744 10449 /* Init BGP distance table. */
734b349e
MZ
10450 for (afi = AFI_IP; afi < AFI_MAX; afi++)
10451 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
10452 bgp_distance_table[afi][safi] = bgp_table_init (afi, safi);
718e3744 10453
10454 /* IPv4 BGP commands. */
73ac8160 10455 install_element (BGP_NODE, &bgp_table_map_cmd);
718e3744 10456 install_element (BGP_NODE, &bgp_network_cmd);
10457 install_element (BGP_NODE, &bgp_network_mask_cmd);
10458 install_element (BGP_NODE, &bgp_network_mask_natural_cmd);
10459 install_element (BGP_NODE, &bgp_network_route_map_cmd);
10460 install_element (BGP_NODE, &bgp_network_mask_route_map_cmd);
10461 install_element (BGP_NODE, &bgp_network_mask_natural_route_map_cmd);
10462 install_element (BGP_NODE, &bgp_network_backdoor_cmd);
10463 install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd);
10464 install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
73ac8160 10465 install_element (BGP_NODE, &no_bgp_table_map_cmd);
718e3744 10466 install_element (BGP_NODE, &no_bgp_network_cmd);
10467 install_element (BGP_NODE, &no_bgp_network_mask_cmd);
10468 install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd);
718e3744 10469
10470 install_element (BGP_NODE, &aggregate_address_cmd);
10471 install_element (BGP_NODE, &aggregate_address_mask_cmd);
718e3744 10472 install_element (BGP_NODE, &no_aggregate_address_cmd);
718e3744 10473 install_element (BGP_NODE, &no_aggregate_address_mask_cmd);
718e3744 10474
10475 /* IPv4 unicast configuration. */
73ac8160 10476 install_element (BGP_IPV4_NODE, &bgp_table_map_cmd);
718e3744 10477 install_element (BGP_IPV4_NODE, &bgp_network_cmd);
10478 install_element (BGP_IPV4_NODE, &bgp_network_mask_cmd);
10479 install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_cmd);
10480 install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd);
10481 install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
10482 install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
73ac8160 10483 install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd);
c8f3fe30 10484 install_element (BGP_IPV4_NODE, &no_bgp_network_cmd);
718e3744 10485 install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
10486 install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
c8f3fe30 10487
718e3744 10488 install_element (BGP_IPV4_NODE, &aggregate_address_cmd);
10489 install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd);
718e3744 10490 install_element (BGP_IPV4_NODE, &no_aggregate_address_cmd);
718e3744 10491 install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
718e3744 10492
10493 /* IPv4 multicast configuration. */
73ac8160 10494 install_element (BGP_IPV4M_NODE, &bgp_table_map_cmd);
718e3744 10495 install_element (BGP_IPV4M_NODE, &bgp_network_cmd);
10496 install_element (BGP_IPV4M_NODE, &bgp_network_mask_cmd);
10497 install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd);
10498 install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
10499 install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
10500 install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_cmd);
73ac8160 10501 install_element (BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
718e3744 10502 install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd);
10503 install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
10504 install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
718e3744 10505 install_element (BGP_IPV4M_NODE, &aggregate_address_cmd);
10506 install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
718e3744 10507 install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd);
718e3744 10508 install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
718e3744 10509
f186de26 10510 install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd);
af462945 10511 install_element (VIEW_NODE, &show_ip_bgp_cmd);
718e3744 10512 install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
8c3deaae 10513 install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd);
57d187bc 10514
8386ac43 10515 install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd);
718e3744 10516 install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
718e3744 10517 install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373
PG
10518#ifdef KEEP_OLD_VPN_COMMANDS
10519 install_element (VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
10520#endif /* KEEP_OLD_VPN_COMMANDS */
4f280b15 10521 install_element (VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
718e3744 10522
10523 /* BGP dampening clear commands */
10524 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
10525 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
57d187bc 10526
718e3744 10527 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
10528 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
10529
ff7924f6 10530 /* prefix count */
8386ac43 10531 install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373
PG
10532#ifdef KEEP_OLD_VPN_COMMANDS
10533 install_element (ENABLE_NODE, &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
10534#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 10535
718e3744 10536 /* New config IPv6 BGP commands. */
73ac8160 10537 install_element (BGP_IPV6_NODE, &bgp_table_map_cmd);
718e3744 10538 install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
10539 install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
73ac8160 10540 install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd);
718e3744 10541 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
718e3744 10542
10543 install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
718e3744 10544 install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
73bfe0bd
B
10545
10546 install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
10547 install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
718e3744 10548
718e3744 10549 install_element (BGP_NODE, &bgp_distance_cmd);
10550 install_element (BGP_NODE, &no_bgp_distance_cmd);
718e3744 10551 install_element (BGP_NODE, &bgp_distance_source_cmd);
10552 install_element (BGP_NODE, &no_bgp_distance_source_cmd);
10553 install_element (BGP_NODE, &bgp_distance_source_access_list_cmd);
10554 install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd);
734b349e
MZ
10555 install_element (BGP_IPV4_NODE, &bgp_distance_cmd);
10556 install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd);
734b349e
MZ
10557 install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd);
10558 install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
10559 install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
10560 install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
10561 install_element (BGP_IPV4M_NODE, &bgp_distance_cmd);
10562 install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd);
734b349e
MZ
10563 install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd);
10564 install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
10565 install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
10566 install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd);
10567 install_element (BGP_IPV6_NODE, &bgp_distance_cmd);
10568 install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd);
734b349e
MZ
10569 install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
10570 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
10571 install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd);
10572 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd);
10573 install_element (BGP_IPV6M_NODE, &bgp_distance_cmd);
10574 install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd);
734b349e
MZ
10575 install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
10576 install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
10577 install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd);
10578 install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd);
718e3744 10579
10580 install_element (BGP_NODE, &bgp_damp_set_cmd);
718e3744 10581 install_element (BGP_NODE, &bgp_damp_unset_cmd);
718e3744 10582 install_element (BGP_IPV4_NODE, &bgp_damp_set_cmd);
718e3744 10583 install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
5c9e5a8d
B
10584
10585 /* IPv4 Multicast Mode */
10586 install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd);
5c9e5a8d 10587 install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
52951b63
DS
10588
10589 /* Large Communities */
10590 install_element (VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
10591 install_element (VIEW_NODE, &show_ip_bgp_large_community_cmd);
718e3744 10592}
228da428
CC
10593
10594void
10595bgp_route_finish (void)
10596{
734b349e
MZ
10597 afi_t afi;
10598 safi_t safi;
10599
10600 for (afi = AFI_IP; afi < AFI_MAX; afi++)
10601 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
10602 {
10603 bgp_table_unlock (bgp_distance_table[afi][safi]);
10604 bgp_distance_table[afi][safi] = NULL;
10605 }
228da428 10606}