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