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