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