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