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