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