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