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