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