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