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