]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Refactor 'struct attr_extra' into 'struct attr'
[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 {
96ade3ed 4415 vty_outln (vty, "%% Malformed prefix");
718e3744 4416 return CMD_WARNING;
4417 }
718e3744 4418 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
4419 {
96ade3ed 4420 vty_outln (vty,"%% Malformed prefix (link-local address)");
718e3744 4421 return CMD_WARNING;
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 {
96ade3ed 4437 vty_outln (vty, "%% Label index cannot be changed");
1b6d5c7e
VV
4438 return CMD_WARNING;
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 {
96ade3ed 4509 vty_outln (vty, "%% Malformed prefix");
718e3744 4510 return CMD_WARNING;
4511 }
718e3744 4512 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
4513 {
96ade3ed 4514 vty_outln (vty,"%% Malformed prefix (link-local address)");
718e3744 4515 return CMD_WARNING;
4516 }
718e3744 4517
4518 apply_mask (&p);
4519
4520 rn = bgp_node_lookup (bgp->route[afi][safi], &p);
4521 if (! rn)
4522 {
96ade3ed 4523 vty_outln (vty,"%% Can't find specified static route configuration.");
718e3744 4524 return CMD_WARNING;
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 {
96ade3ed 4721 vty_outln (vty, "%% Malformed prefix");
718e3744 4722 return CMD_WARNING;
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 {
96ade3ed 4728 vty_outln (vty, "%% L2VPN prefix could not be forged");
3da6fcd5
PG
4729 return CMD_WARNING;
4730 }
718e3744 4731
4732 ret = str2prefix_rd (rd_str, &prd);
4733 if (! ret)
4734 {
96ade3ed 4735 vty_outln (vty, "%% Malformed rd");
718e3744 4736 return CMD_WARNING;
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 {
96ade3ed 4750 vty_outln (vty, "%% Malformed ESI");
3da6fcd5
PG
4751 return CMD_WARNING;
4752 }
7acff3e7 4753 if( routermac && prefix_str2mac (routermac, NULL) == 0)
3da6fcd5 4754 {
96ade3ed 4755 vty_outln (vty, "%% Malformed Router MAC");
3da6fcd5
PG
4756 return CMD_WARNING;
4757 }
4758 if (gwip)
4759 {
4760 memset (&gw_ip, 0, sizeof (struct prefix));
4761 ret = str2prefix (gwip, &gw_ip);
4762 if (! ret)
4763 {
96ade3ed 4764 vty_outln (vty, "%% Malformed GatewayIp");
3da6fcd5
PG
4765 return CMD_WARNING;
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 {
96ade3ed 4772 vty_outln (vty, "%% GatewayIp family differs with IP prefix");
3da6fcd5
PG
4773 return CMD_WARNING;
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 {
96ade3ed 4789 vty_outln (vty, "%% Same network configuration exists");
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 {
96ade3ed 4855 vty_outln (vty, "%% Malformed prefix");
718e3744 4856 return CMD_WARNING;
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 {
96ade3ed 4862 vty_outln (vty, "%% L2VPN prefix could not be forged");
3da6fcd5
PG
4863 return CMD_WARNING;
4864 }
718e3744 4865 ret = str2prefix_rd (rd_str, &prd);
4866 if (! ret)
4867 {
96ade3ed 4868 vty_outln (vty, "%% Malformed rd");
718e3744 4869 return CMD_WARNING;
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
96ade3ed 4900 vty_outln (vty, "%% Can't find the route");
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);
96ade3ed
QY
4960 vty_outln (vty, " table-map %s",
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 {
96ade3ed 5044 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5045 return CMD_WARNING;
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 {
96ade3ed 5071 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5072 return CMD_WARNING;
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 {
96ade3ed 5096 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5097 return CMD_WARNING;
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 {
96ade3ed 5118 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5119 return CMD_WARNING;
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 {
96ade3ed 5143 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5144 return CMD_WARNING;
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 {
96ade3ed 5166 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5167 return CMD_WARNING;
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 {
96ade3ed 5241 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5242 return CMD_WARNING;
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 {
96ade3ed 5266 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 5267 return CMD_WARNING;
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 {
96ade3ed 5900 vty_outln (vty, "Malformed prefix");
718e3744 5901 return CMD_WARNING;
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 {
96ade3ed 5909 vty_outln (vty,"%% There is no aggregate-address configuration.");
718e3744 5910 return CMD_WARNING;
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 {
96ade3ed 5945 vty_outln (vty, "Malformed prefix");
718e3744 5946 return CMD_WARNING;
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 {
96ade3ed 5955 vty_outln (vty, "There is already same aggregate network.");
368473f6 5956 /* try to remove the old entry */
f6269b4f
RB
5957 ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
5958 if (ret)
5959 {
96ade3ed 5960 vty_outln (vty, "Error deleting aggregate.");
368473f6 5961 bgp_unlock_node (rn);
f6269b4f
RB
5962 return CMD_WARNING;
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 {
96ade3ed 6028 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 6029 return CMD_WARNING;
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 {
96ade3ed 6074 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 6075 return CMD_WARNING;
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)
1318e7c8 6333 vty_out (vty, "%s%*s", VTYNL, 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)
1318e7c8 6566 vty_out (vty, "%s%*s", VTYNL, 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)
1318e7c8 6579 vty_out (vty, "%s%*s", VTYNL, 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)
1318e7c8 6593 vty_out (vty, "%s%*s", VTYNL, 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
96ade3ed 6650 vty_outln (vty, "No attributes to print");
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 {
e31b6333 6672 vty_out (vty, VTYNL);
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)
1318e7c8 6771 vty_out (vty, "%s%*s", VTYNL, 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
e31b6333 6804 vty_out (vty, VTYNL);
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
DW
6906 vty_out (vty, "notag/%d", label);
6907 vty_out (vty, VTYNL);
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 }
e31b6333 6987 vty_out (vty, VTYNL);
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)
1318e7c8 7016 vty_out (vty, "%s%*s", VTYNL, 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)
e31b6333 7051 vty_out (vty, VTYNL);
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)
1318e7c8 7086 vty_out (vty, "%s%*s", VTYNL, 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)
e31b6333 7151 vty_out (vty, VTYNL);
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];
520d5d76 7212 char buf2[EVPN_ROUTE_STRLEN];
718e3744 7213 struct attr *attr;
7214 int sockunion_vty_out (struct vty *, union sockunion *);
30b00176 7215 time_t tbuf;
f1aa5d8a 7216 json_object *json_bestpath = NULL;
ffd0c037 7217 json_object *json_cluster_list = NULL;
f1aa5d8a
DS
7218 json_object *json_cluster_list_list = NULL;
7219 json_object *json_ext_community = NULL;
7220 json_object *json_last_update = NULL;
7221 json_object *json_nexthop_global = NULL;
7222 json_object *json_nexthop_ll = NULL;
7223 json_object *json_nexthops = NULL;
7224 json_object *json_path = NULL;
7225 json_object *json_peer = NULL;
7226 json_object *json_string = NULL;
adbac85e
DW
7227 json_object *json_adv_to = NULL;
7228 int first = 0;
7229 struct listnode *node, *nnode;
7230 struct peer *peer;
7231 int addpath_capable;
7232 int has_adj;
aac9ef6c 7233 unsigned int first_as;
b05a1c8b
DS
7234
7235 if (json_paths)
7236 {
7237 json_path = json_object_new_object();
f1aa5d8a
DS
7238 json_peer = json_object_new_object();
7239 json_nexthop_global = json_object_new_object();
b05a1c8b
DS
7240 }
7241
520d5d76 7242#if defined (HAVE_CUMULUS)
7243 if (!json_paths && safi == SAFI_EVPN)
7244 {
7245 char tag_buf[20];
7246
7247 bgp_evpn_route2str ((struct prefix_evpn *)p, buf2, sizeof (buf2));
7248 vty_out (vty, " Route %s", buf2);
7249 tag_buf[0] = '\0';
7250 if (binfo->extra)
7251 {
7252 bgp_evpn_label2str (&binfo->extra->label, tag_buf, sizeof (tag_buf));
7253 vty_out (vty, " VNI %s", tag_buf);
7254 }
7255 vty_out (vty, "%s", VTY_NEWLINE);
7256 if (binfo->extra && binfo->extra->parent)
7257 {
7258 struct bgp_info *parent_ri;
7259 struct bgp_node *rn, *prn;
7260
7261 parent_ri = (struct bgp_info *)binfo->extra->parent;
7262 rn = parent_ri->net;
7263 if (rn && rn->prn)
7264 {
7265 prn = rn->prn;
7266 vty_out (vty, " Imported from %s:%s%s",
7267 prefix_rd2str ((struct prefix_rd *)&prn->p,
7268 buf1, RD_ADDRSTRLEN),
7269 buf2, VTY_NEWLINE);
7270 }
7271 }
7272 }
7273#endif
7274
718e3744 7275 attr = binfo->attr;
7276
7277 if (attr)
7278 {
7279 /* Line1 display AS-path, Aggregator */
7280 if (attr->aspath)
7281 {
f1aa5d8a
DS
7282 if (json_paths)
7283 {
7284 json_object_lock(attr->aspath->json);
7285 json_object_object_add(json_path, "aspath", attr->aspath->json);
7286 }
7287 else
b05a1c8b 7288 {
f1aa5d8a
DS
7289 if (attr->aspath->segments)
7290 aspath_print_vty (vty, " %s", attr->aspath, "");
b05a1c8b 7291 else
f1aa5d8a 7292 vty_out (vty, " Local");
b05a1c8b 7293 }
718e3744 7294 }
7295
b40d939b 7296 if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
b05a1c8b
DS
7297 {
7298 if (json_paths)
f1aa5d8a 7299 json_object_boolean_true_add(json_path, "removed");
b05a1c8b
DS
7300 else
7301 vty_out (vty, ", (removed)");
7302 }
7303
93406d87 7304 if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
b05a1c8b
DS
7305 {
7306 if (json_paths)
f1aa5d8a 7307 json_object_boolean_true_add(json_path, "stale");
b05a1c8b
DS
7308 else
7309 vty_out (vty, ", (stale)");
7310 }
7311
93406d87 7312 if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
b05a1c8b
DS
7313 {
7314 if (json_paths)
7315 {
aadc0905
DS
7316 json_object_int_add(json_path, "aggregatorAs", attr->aggregator_as);
7317 json_object_string_add(json_path, "aggregatorId", inet_ntoa (attr->aggregator_addr));
b05a1c8b
DS
7318 }
7319 else
7320 {
7321 vty_out (vty, ", (aggregated by %u %s)",
aadc0905
DS
7322 attr->aggregator_as,
7323 inet_ntoa (attr->aggregator_addr));
b05a1c8b
DS
7324 }
7325 }
7326
93406d87 7327 if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
b05a1c8b
DS
7328 {
7329 if (json_paths)
62d6dca0 7330 json_object_boolean_true_add(json_path, "rxedFromRrClient");
b05a1c8b
DS
7331 else
7332 vty_out (vty, ", (Received from a RR-client)");
7333 }
7334
93406d87 7335 if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
b05a1c8b
DS
7336 {
7337 if (json_paths)
62d6dca0 7338 json_object_boolean_true_add(json_path, "rxedFromRsClient");
b05a1c8b
DS
7339 else
7340 vty_out (vty, ", (Received from a RS-client)");
7341 }
7342
93406d87 7343 if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
b05a1c8b
DS
7344 {
7345 if (json_paths)
62d6dca0 7346 json_object_boolean_true_add(json_path, "dampeningHistoryEntry");
b05a1c8b
DS
7347 else
7348 vty_out (vty, ", (history entry)");
7349 }
93406d87 7350 else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
b05a1c8b
DS
7351 {
7352 if (json_paths)
62d6dca0 7353 json_object_boolean_true_add(json_path, "dampeningSuppressed");
b05a1c8b
DS
7354 else
7355 vty_out (vty, ", (suppressed due to dampening)");
7356 }
7357
7358 if (!json_paths)
e31b6333 7359 vty_out (vty, VTYNL);
718e3744 7360
7361 /* Line2 display Next-hop, Neighbor, Router-id */
f1aa5d8a 7362 /* Display the nexthop */
ea2e4889 7363 if ((p->family == AF_INET ||
7364 p->family == AF_ETHERNET) &&
587ff0fd
LB
7365 (safi == SAFI_MPLS_VPN ||
7366 safi == SAFI_ENCAP ||
3d6c0dfa 7367 safi == SAFI_EVPN ||
587ff0fd 7368 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
718e3744 7369 {
3d6c0dfa 7370 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
b05a1c8b
DS
7371 {
7372 if (json_paths)
aadc0905 7373 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->mp_nexthop_global_in));
b05a1c8b 7374 else
aadc0905 7375 vty_out (vty, " %s", inet_ntoa (attr->mp_nexthop_global_in));
b05a1c8b
DS
7376 }
7377 else
7378 {
7379 if (json_paths)
f1aa5d8a 7380 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop));
b05a1c8b
DS
7381 else
7382 vty_out (vty, " %s", inet_ntoa (attr->nexthop));
7383 }
7384
7385 if (json_paths)
f1aa5d8a 7386 json_object_string_add(json_nexthop_global, "afi", "ipv4");
718e3744 7387 }
718e3744 7388 else
7389 {
b05a1c8b
DS
7390 if (json_paths)
7391 {
f1aa5d8a 7392 json_object_string_add(json_nexthop_global, "ip",
aadc0905 7393 inet_ntop (AF_INET6, &attr->mp_nexthop_global,
f1aa5d8a
DS
7394 buf, INET6_ADDRSTRLEN));
7395 json_object_string_add(json_nexthop_global, "afi", "ipv6");
7396 json_object_string_add(json_nexthop_global, "scope", "global");
b05a1c8b
DS
7397 }
7398 else
7399 {
7400 vty_out (vty, " %s",
aadc0905 7401 inet_ntop (AF_INET6, &attr->mp_nexthop_global,
b05a1c8b
DS
7402 buf, INET6_ADDRSTRLEN));
7403 }
718e3744 7404 }
b05a1c8b 7405
f1aa5d8a
DS
7406 /* Display the IGP cost or 'inaccessible' */
7407 if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
7408 {
7409 if (json_paths)
7410 json_object_boolean_false_add(json_nexthop_global, "accessible");
7411 else
7412 vty_out (vty, " (inaccessible)");
7413 }
7414 else
7415 {
7416 if (binfo->extra && binfo->extra->igpmetric)
b05a1c8b
DS
7417 {
7418 if (json_paths)
f1aa5d8a 7419 json_object_int_add(json_nexthop_global, "metric", binfo->extra->igpmetric);
b05a1c8b 7420 else
f1aa5d8a 7421 vty_out (vty, " (metric %u)", binfo->extra->igpmetric);
b05a1c8b 7422 }
f1aa5d8a
DS
7423
7424 /* IGP cost is 0, display this only for json */
b05a1c8b
DS
7425 else
7426 {
7427 if (json_paths)
f1aa5d8a 7428 json_object_int_add(json_nexthop_global, "metric", 0);
b05a1c8b
DS
7429 }
7430
7431 if (json_paths)
f1aa5d8a
DS
7432 json_object_boolean_true_add(json_nexthop_global, "accessible");
7433 }
7434
7435 /* Display peer "from" output */
7436 /* This path was originated locally */
7437 if (binfo->peer == bgp->peer_self)
718e3744 7438 {
f1aa5d8a 7439
520d5d76 7440 if (safi == SAFI_EVPN ||
7441 (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
b05a1c8b
DS
7442 {
7443 if (json_paths)
62d6dca0 7444 json_object_string_add(json_peer, "peerId", "0.0.0.0");
b05a1c8b 7445 else
f1aa5d8a 7446 vty_out (vty, " from 0.0.0.0 ");
b05a1c8b 7447 }
f1aa5d8a 7448 else
b05a1c8b
DS
7449 {
7450 if (json_paths)
62d6dca0 7451 json_object_string_add(json_peer, "peerId", "::");
b05a1c8b 7452 else
f1aa5d8a 7453 vty_out (vty, " from :: ");
b05a1c8b
DS
7454 }
7455
f1aa5d8a 7456 if (json_paths)
62d6dca0 7457 json_object_string_add(json_peer, "routerId", inet_ntoa(bgp->router_id));
b05a1c8b 7458 else
f1aa5d8a
DS
7459 vty_out (vty, "(%s)", inet_ntoa(bgp->router_id));
7460 }
7461
7462 /* We RXed this path from one of our peers */
7463 else
7464 {
b05a1c8b
DS
7465
7466 if (json_paths)
7467 {
62d6dca0
DS
7468 json_object_string_add(json_peer, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
7469 json_object_string_add(json_peer, "routerId", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
f1aa5d8a 7470
04b6bdc0
DW
7471 if (binfo->peer->hostname)
7472 json_object_string_add(json_peer, "hostname", binfo->peer->hostname);
7473
7474 if (binfo->peer->domainname)
7475 json_object_string_add(json_peer, "domainname", binfo->peer->domainname);
7476
036a4e7d 7477 if (binfo->peer->conf_if)
f1aa5d8a 7478 json_object_string_add(json_peer, "interface", binfo->peer->conf_if);
b05a1c8b
DS
7479 }
7480 else
7481 {
036a4e7d 7482 if (binfo->peer->conf_if)
04b6bdc0
DW
7483 {
7484 if (binfo->peer->hostname &&
7485 bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
7486 vty_out (vty, " from %s(%s)", binfo->peer->hostname,
7487 binfo->peer->conf_if);
7488 else
7489 vty_out (vty, " from %s", binfo->peer->conf_if);
7490 }
036a4e7d 7491 else
04b6bdc0
DW
7492 {
7493 if (binfo->peer->hostname &&
7494 bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
7495 vty_out (vty, " from %s(%s)", binfo->peer->hostname,
7496 binfo->peer->host);
7497 else
7498 vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
7499 }
b05a1c8b 7500
f1aa5d8a 7501 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
aadc0905 7502 vty_out (vty, " (%s)", inet_ntoa (attr->originator_id));
f1aa5d8a
DS
7503 else
7504 vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
b05a1c8b 7505 }
718e3744 7506 }
b05a1c8b
DS
7507
7508 if (!json_paths)
e31b6333 7509 vty_out (vty, VTYNL);
718e3744 7510
f1aa5d8a 7511 /* display the link-local nexthop */
aadc0905 7512 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
718e3744 7513 {
b05a1c8b
DS
7514 if (json_paths)
7515 {
f1aa5d8a
DS
7516 json_nexthop_ll = json_object_new_object();
7517 json_object_string_add(json_nexthop_ll, "ip",
aadc0905 7518 inet_ntop (AF_INET6, &attr->mp_nexthop_local,
f1aa5d8a
DS
7519 buf, INET6_ADDRSTRLEN));
7520 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
7521 json_object_string_add(json_nexthop_ll, "scope", "link-local");
7522
7523 json_object_boolean_true_add(json_nexthop_ll, "accessible");
161995ea 7524
aadc0905 7525 if (!attr->mp_nexthop_prefer_global)
161995ea
DS
7526 json_object_boolean_true_add(json_nexthop_ll, "used");
7527 else
7528 json_object_boolean_true_add(json_nexthop_global, "used");
b05a1c8b
DS
7529 }
7530 else
7531 {
96ade3ed 7532 vty_outln (vty, " (%s) %s",
aadc0905 7533 inet_ntop (AF_INET6, &attr->mp_nexthop_local,
b05a1c8b 7534 buf, INET6_ADDRSTRLEN),
aadc0905 7535 attr->mp_nexthop_prefer_global ? "(prefer-global)" : "(used)");
b05a1c8b 7536 }
718e3744 7537 }
f1aa5d8a
DS
7538 /* If we do not have a link-local nexthop then we must flag the global as "used" */
7539 else
7540 {
7541 if (json_paths)
7542 json_object_boolean_true_add(json_nexthop_global, "used");
7543 }
718e3744 7544
0d9551dc 7545 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */
b05a1c8b 7546 if (json_paths)
f1aa5d8a 7547 json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]);
b05a1c8b 7548 else
f1aa5d8a 7549 vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]);
718e3744 7550
7551 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
b05a1c8b
DS
7552 {
7553 if (json_paths)
f1aa5d8a 7554 json_object_int_add(json_path, "med", attr->med);
b05a1c8b 7555 else
f1aa5d8a 7556 vty_out (vty, ", metric %u", attr->med);
b05a1c8b 7557 }
718e3744 7558
7559 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
b05a1c8b
DS
7560 {
7561 if (json_paths)
f1aa5d8a 7562 json_object_int_add(json_path, "localpref", attr->local_pref);
b05a1c8b 7563 else
f1aa5d8a 7564 vty_out (vty, ", localpref %u", attr->local_pref);
b05a1c8b 7565 }
718e3744 7566 else
b05a1c8b
DS
7567 {
7568 if (json_paths)
f1aa5d8a 7569 json_object_int_add(json_path, "localpref", bgp->default_local_pref);
b05a1c8b 7570 else
f1aa5d8a 7571 vty_out (vty, ", localpref %u", bgp->default_local_pref);
b05a1c8b 7572 }
718e3744 7573
aadc0905 7574 if (attr->weight != 0)
b05a1c8b
DS
7575 {
7576 if (json_paths)
aadc0905 7577 json_object_int_add(json_path, "weight", attr->weight);
b05a1c8b 7578 else
aadc0905 7579 vty_out (vty, ", weight %u", attr->weight);
b05a1c8b 7580 }
0d9551dc 7581
aadc0905 7582 if (attr->tag != 0)
b05a1c8b
DS
7583 {
7584 if (json_paths)
aadc0905 7585 json_object_int_add(json_path, "tag", attr->tag);
b05a1c8b 7586 else
aadc0905 7587 vty_out (vty, ", tag %"ROUTE_TAG_PRI, attr->tag);
b05a1c8b 7588 }
718e3744 7589
31eba040 7590 if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
b05a1c8b
DS
7591 {
7592 if (json_paths)
f1aa5d8a 7593 json_object_boolean_false_add(json_path, "valid");
b05a1c8b
DS
7594 else
7595 vty_out (vty, ", invalid");
7596 }
31eba040 7597 else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
b05a1c8b
DS
7598 {
7599 if (json_paths)
f1aa5d8a 7600 json_object_boolean_true_add(json_path, "valid");
b05a1c8b
DS
7601 else
7602 vty_out (vty, ", valid");
7603 }
718e3744 7604
7605 if (binfo->peer != bgp->peer_self)
7606 {
f1aa5d8a 7607 if (binfo->peer->as == binfo->peer->local_as)
b05a1c8b 7608 {
66b199b2
DS
7609 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
7610 {
7611 if (json_paths)
f1aa5d8a 7612 json_object_string_add(json_peer, "type", "confed-internal");
66b199b2 7613 else
f1aa5d8a 7614 vty_out (vty, ", confed-internal");
66b199b2 7615 }
b05a1c8b 7616 else
66b199b2
DS
7617 {
7618 if (json_paths)
f1aa5d8a 7619 json_object_string_add(json_peer, "type", "internal");
66b199b2 7620 else
f1aa5d8a 7621 vty_out (vty, ", internal");
66b199b2 7622 }
b05a1c8b 7623 }
f1aa5d8a 7624 else
b05a1c8b
DS
7625 {
7626 if (bgp_confederation_peers_check(bgp, binfo->peer->as))
7627 {
7628 if (json_paths)
f1aa5d8a 7629 json_object_string_add(json_peer, "type", "confed-external");
b05a1c8b 7630 else
f1aa5d8a 7631 vty_out (vty, ", confed-external");
b05a1c8b
DS
7632 }
7633 else
7634 {
7635 if (json_paths)
f1aa5d8a 7636 json_object_string_add(json_peer, "type", "external");
b05a1c8b 7637 else
f1aa5d8a 7638 vty_out (vty, ", external");
b05a1c8b
DS
7639 }
7640 }
718e3744 7641 }
7642 else if (binfo->sub_type == BGP_ROUTE_AGGREGATE)
b05a1c8b
DS
7643 {
7644 if (json_paths)
7645 {
f1aa5d8a
DS
7646 json_object_boolean_true_add(json_path, "aggregated");
7647 json_object_boolean_true_add(json_path, "local");
b05a1c8b
DS
7648 }
7649 else
7650 {
7651 vty_out (vty, ", aggregated, local");
7652 }
7653 }
718e3744 7654 else if (binfo->type != ZEBRA_ROUTE_BGP)
b05a1c8b
DS
7655 {
7656 if (json_paths)
f1aa5d8a 7657 json_object_boolean_true_add(json_path, "sourced");
b05a1c8b
DS
7658 else
7659 vty_out (vty, ", sourced");
7660 }
718e3744 7661 else
b05a1c8b
DS
7662 {
7663 if (json_paths)
7664 {
f1aa5d8a
DS
7665 json_object_boolean_true_add(json_path, "sourced");
7666 json_object_boolean_true_add(json_path, "local");
b05a1c8b
DS
7667 }
7668 else
7669 {
7670 vty_out (vty, ", sourced, local");
7671 }
7672 }
718e3744 7673
7674 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
b05a1c8b
DS
7675 {
7676 if (json_paths)
62d6dca0 7677 json_object_boolean_true_add(json_path, "atomicAggregate");
b05a1c8b
DS
7678 else
7679 vty_out (vty, ", atomic-aggregate");
7680 }
718e3744 7681
de8d5dff
JB
7682 if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) ||
7683 (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) &&
7684 bgp_info_mpath_count (binfo)))
b05a1c8b
DS
7685 {
7686 if (json_paths)
f1aa5d8a 7687 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b
DS
7688 else
7689 vty_out (vty, ", multipath");
7690 }
de8d5dff 7691
06370dac
DW
7692 // Mark the bestpath(s)
7693 if (CHECK_FLAG (binfo->flags, BGP_INFO_DMED_SELECTED))
7694 {
aac9ef6c 7695 first_as = aspath_get_first_as(attr->aspath);
06370dac
DW
7696
7697 if (json_paths)
7698 {
7699 if (!json_bestpath)
7700 json_bestpath = json_object_new_object();
7701 json_object_int_add(json_bestpath, "bestpathFromAs", first_as);
7702 }
7703 else
7704 {
7705 if (first_as)
7706 vty_out (vty, ", bestpath-from-AS %d", first_as);
7707 else
7708 vty_out (vty, ", bestpath-from-AS Local");
7709 }
7710 }
7711
718e3744 7712 if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
b05a1c8b
DS
7713 {
7714 if (json_paths)
f1aa5d8a 7715 {
06370dac
DW
7716 if (!json_bestpath)
7717 json_bestpath = json_object_new_object();
f1aa5d8a 7718 json_object_boolean_true_add(json_bestpath, "overall");
f1aa5d8a 7719 }
b05a1c8b
DS
7720 else
7721 vty_out (vty, ", best");
7722 }
718e3744 7723
06370dac
DW
7724 if (json_bestpath)
7725 json_object_object_add(json_path, "bestpath", json_bestpath);
7726
b05a1c8b 7727 if (!json_paths)
e31b6333 7728 vty_out (vty, VTYNL);
718e3744 7729
7730 /* Line 4 display Community */
7731 if (attr->community)
b05a1c8b
DS
7732 {
7733 if (json_paths)
7734 {
f1aa5d8a
DS
7735 json_object_lock(attr->community->json);
7736 json_object_object_add(json_path, "community", attr->community->json);
b05a1c8b
DS
7737 }
7738 else
7739 {
96ade3ed 7740 vty_outln (vty, " Community: %s",attr->community->str);
b05a1c8b
DS
7741 }
7742 }
718e3744 7743
7744 /* Line 5 display Extended-community */
7745 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
b05a1c8b
DS
7746 {
7747 if (json_paths)
7748 {
f1aa5d8a 7749 json_ext_community = json_object_new_object();
aadc0905 7750 json_object_string_add(json_ext_community, "string", attr->ecommunity->str);
62d6dca0 7751 json_object_object_add(json_path, "extendedCommunity", json_ext_community);
b05a1c8b
DS
7752 }
7753 else
7754 {
96ade3ed 7755 vty_outln (vty, " Extended Community: %s",
aadc0905 7756 attr->ecommunity->str);
b05a1c8b
DS
7757 }
7758 }
7759
57d187bc
JS
7760 /* Line 6 display Large community */
7761 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))
96ade3ed 7762 vty_outln (vty, " Large Community: %s",
aadc0905 7763 attr->lcommunity->str);
57d187bc
JS
7764
7765 /* Line 7 display Originator, Cluster-id */
718e3744 7766 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) ||
7767 (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)))
7768 {
7769 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
b05a1c8b
DS
7770 {
7771 if (json_paths)
aadc0905 7772 json_object_string_add(json_path, "originatorId", inet_ntoa (attr->originator_id));
b05a1c8b 7773 else
f1aa5d8a 7774 vty_out (vty, " Originator: %s",
aadc0905 7775 inet_ntoa (attr->originator_id));
b05a1c8b 7776 }
718e3744 7777
7778 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
7779 {
7780 int i;
b05a1c8b
DS
7781
7782 if (json_paths)
7783 {
f1aa5d8a
DS
7784 json_cluster_list = json_object_new_object();
7785 json_cluster_list_list = json_object_new_array();
7786
aadc0905 7787 for (i = 0; i < attr->cluster->length / 4; i++)
b05a1c8b 7788 {
aadc0905 7789 json_string = json_object_new_string(inet_ntoa (attr->cluster->list[i]));
f1aa5d8a 7790 json_object_array_add(json_cluster_list_list, json_string);
b05a1c8b 7791 }
f1aa5d8a
DS
7792
7793 /* struct cluster_list does not have "str" variable like
7794 * aspath and community do. Add this someday if someone
7795 * asks for it.
aadc0905 7796 json_object_string_add(json_cluster_list, "string", attr->cluster->str);
f1aa5d8a
DS
7797 */
7798 json_object_object_add(json_cluster_list, "list", json_cluster_list_list);
62d6dca0 7799 json_object_object_add(json_path, "clusterList", json_cluster_list);
b05a1c8b
DS
7800 }
7801 else
7802 {
7803 vty_out (vty, ", Cluster list: ");
7804
aadc0905 7805 for (i = 0; i < attr->cluster->length / 4; i++)
b05a1c8b
DS
7806 {
7807 vty_out (vty, "%s ",
aadc0905 7808 inet_ntoa (attr->cluster->list[i]));
b05a1c8b
DS
7809 }
7810 }
718e3744 7811 }
b05a1c8b
DS
7812
7813 if (!json_paths)
e31b6333 7814 vty_out (vty, VTYNL);
718e3744 7815 }
b05a1c8b 7816
fb982c25 7817 if (binfo->extra && binfo->extra->damp_info)
b05a1c8b 7818 bgp_damp_info_vty (vty, binfo, json_path);
718e3744 7819
9bedbb1e 7820 /* Remote Label */
520d5d76 7821#if defined (HAVE_CUMULUS)
7822 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label) && safi != SAFI_EVPN)
7823#else
9bedbb1e 7824 if (binfo->extra && bgp_is_valid_label(&binfo->extra->label))
520d5d76 7825#endif
cd1964ff 7826 {
9bedbb1e 7827 mpls_label_t label = label_pton(&binfo->extra->label);
c5a543b4
DW
7828 if (json_paths)
7829 json_object_int_add(json_path, "remoteLabel", label);
7830 else
96ade3ed 7831 vty_outln (vty, " Remote label: %d", label);
c5a543b4 7832 }
9fbea8d5 7833
c5a543b4 7834 /* Label Index */
aadc0905 7835 if (attr->label_index != BGP_INVALID_LABEL_INDEX)
c5a543b4
DW
7836 {
7837 if (json_paths)
aadc0905 7838 json_object_int_add(json_path, "labelIndex", attr->label_index);
c5a543b4 7839 else
96ade3ed 7840 vty_outln (vty, " Label Index: %d",
aadc0905 7841 attr->label_index);
6cf48acc
VV
7842 }
7843
57d187bc 7844 /* Line 8 display Addpath IDs */
a82478b9 7845 if (binfo->addpath_rx_id || binfo->addpath_tx_id)
b05a1c8b
DS
7846 {
7847 if (json_paths)
7848 {
62d6dca0
DS
7849 json_object_int_add(json_path, "addpathRxId", binfo->addpath_rx_id);
7850 json_object_int_add(json_path, "addpathTxId", binfo->addpath_tx_id);
b05a1c8b
DS
7851 }
7852 else
7853 {
96ade3ed
QY
7854 vty_outln (vty, " AddPath ID: RX %u, TX %u",
7855 binfo->addpath_rx_id,binfo->addpath_tx_id);
b05a1c8b
DS
7856 }
7857 }
a82478b9 7858
adbac85e
DW
7859 /* If we used addpath to TX a non-bestpath we need to display
7860 * "Advertised to" on a path-by-path basis */
7861 if (bgp->addpath_tx_used[afi][safi])
7862 {
7863 first = 1;
7864
7865 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
7866 {
7867 addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
7868 has_adj = bgp_adj_out_lookup (peer, binfo->net, binfo->addpath_tx_id);
7869
7870 if ((addpath_capable && has_adj) ||
7871 (!addpath_capable && has_adj && CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)))
7872 {
7873 if (json_path && !json_adv_to)
7874 json_adv_to = json_object_new_object();
7875
7876 route_vty_out_advertised_to(vty, peer, &first,
7877 " Advertised to:",
7878 json_adv_to);
7879 }
7880 }
7881
7882 if (json_path)
7883 {
7884 if (json_adv_to)
7885 {
7886 json_object_object_add(json_path, "advertisedTo", json_adv_to);
7887 }
7888 }
7889 else
7890 {
7891 if (!first)
7892 {
e31b6333 7893 vty_out (vty, VTYNL);
adbac85e
DW
7894 }
7895 }
7896 }
7897
57d187bc 7898 /* Line 9 display Uptime */
30b00176 7899 tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
b05a1c8b 7900 if (json_paths)
f1aa5d8a
DS
7901 {
7902 json_last_update = json_object_new_object();
7903 json_object_int_add(json_last_update, "epoch", tbuf);
7904 json_object_string_add(json_last_update, "string", ctime(&tbuf));
62d6dca0 7905 json_object_object_add(json_path, "lastUpdate", json_last_update);
f1aa5d8a 7906 }
b05a1c8b
DS
7907 else
7908 vty_out (vty, " Last update: %s", ctime(&tbuf));
718e3744 7909 }
b05a1c8b
DS
7910
7911 /* We've constructed the json object for this path, add it to the json
7912 * array of paths
7913 */
7914 if (json_paths)
f1aa5d8a
DS
7915 {
7916 if (json_nexthop_global || json_nexthop_ll)
7917 {
7918 json_nexthops = json_object_new_array();
7919
7920 if (json_nexthop_global)
7921 json_object_array_add(json_nexthops, json_nexthop_global);
7922
7923 if (json_nexthop_ll)
7924 json_object_array_add(json_nexthops, json_nexthop_ll);
7925
7926 json_object_object_add(json_path, "nexthops", json_nexthops);
7927 }
7928
7929 json_object_object_add(json_path, "peer", json_peer);
7930 json_object_array_add(json_paths, json_path);
7931 }
b05a1c8b 7932 else
e31b6333 7933 vty_out (vty, VTYNL);
b366b518
BB
7934}
7935
96ade3ed
QY
7936#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
7937#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path"
7938#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path"
718e3744 7939
50ef26d4 7940static int
af462945 7941bgp_show_prefix_list (struct vty *vty, struct bgp *bgp,
50ef26d4 7942 const char *prefix_list_str, afi_t afi,
7943 safi_t safi, enum bgp_show_type type);
7944static int
af462945 7945bgp_show_filter_list (struct vty *vty, struct bgp *bgp,
50ef26d4 7946 const char *filter, afi_t afi,
7947 safi_t safi, enum bgp_show_type type);
7948static int
af462945 7949bgp_show_route_map (struct vty *vty, struct bgp *bgp,
50ef26d4 7950 const char *rmap_str, afi_t afi,
7951 safi_t safi, enum bgp_show_type type);
7952static int
af462945 7953bgp_show_community_list (struct vty *vty, struct bgp *bgp,
50ef26d4 7954 const char *com, int exact,
7955 afi_t afi, safi_t safi);
7956static int
af462945 7957bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp,
50ef26d4 7958 const char *prefix, afi_t afi,
7959 safi_t safi, enum bgp_show_type type);
a636c635 7960static int
8c3deaae 7961bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi,
a636c635
DW
7962 safi_t safi, enum bgp_show_type type);
7963static int
af462945 7964bgp_show_community (struct vty *vty, struct bgp *bgp, int argc,
a636c635 7965 struct cmd_token **argv, int exact, afi_t afi, safi_t safi);
50ef26d4 7966
5a646650 7967static int
31303c3e
DS
7968bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table,
7969 enum bgp_show_type type, void *output_arg, u_char use_json)
718e3744 7970{
718e3744 7971 struct bgp_info *ri;
7972 struct bgp_node *rn;
718e3744 7973 int header = 1;
718e3744 7974 int display;
5a646650 7975 unsigned long output_count;
18200902 7976 unsigned long total_count;
b05a1c8b
DS
7977 struct prefix *p;
7978 char buf[BUFSIZ];
7979 char buf2[BUFSIZ];
f1aa5d8a 7980 json_object *json_paths = NULL;
31303c3e 7981 int first = 1;
b05a1c8b
DS
7982
7983 if (use_json)
7984 {
31303c3e
DS
7985 vty_out (vty, "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 ", \"routerId\": \"%s\", \"routes\": { ",
7986 bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id,
7987 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" : bgp->name,
7988 table->version, inet_ntoa (bgp->router_id));
7989 json_paths = json_object_new_object();
b05a1c8b 7990 }
718e3744 7991
7992 /* This is first entry point, so reset total line. */
5a646650 7993 output_count = 0;
18200902 7994 total_count = 0;
718e3744 7995
718e3744 7996 /* Start processing of routes. */
7997 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
7998 if (rn->info != NULL)
7999 {
856ca177 8000 display = 0;
31303c3e
DS
8001 if (!first && use_json)
8002 {
8003 vty_out (vty, ",");
8004 }
b05a1c8b
DS
8005 if (use_json)
8006 json_paths = json_object_new_array();
8007 else
8008 json_paths = NULL;
8009
856ca177
MS
8010 for (ri = rn->info; ri; ri = ri->next)
8011 {
18200902 8012 total_count++;
856ca177 8013 if (type == bgp_show_type_flap_statistics
856ca177
MS
8014 || type == bgp_show_type_flap_neighbor
8015 || type == bgp_show_type_dampend_paths
8016 || type == bgp_show_type_damp_neighbor)
8017 {
8018 if (!(ri->extra && ri->extra->damp_info))
8019 continue;
8020 }
a636c635 8021 if (type == bgp_show_type_regexp)
856ca177
MS
8022 {
8023 regex_t *regex = output_arg;
718e3744 8024
856ca177
MS
8025 if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH)
8026 continue;
8027 }
a636c635 8028 if (type == bgp_show_type_prefix_list)
856ca177
MS
8029 {
8030 struct prefix_list *plist = output_arg;
718e3744 8031
856ca177
MS
8032 if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT)
8033 continue;
8034 }
a636c635 8035 if (type == bgp_show_type_filter_list)
856ca177
MS
8036 {
8037 struct as_list *as_list = output_arg;
558d1fec 8038
856ca177
MS
8039 if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT)
8040 continue;
8041 }
a636c635 8042 if (type == bgp_show_type_route_map)
856ca177
MS
8043 {
8044 struct route_map *rmap = output_arg;
8045 struct bgp_info binfo;
8046 struct attr dummy_attr;
856ca177 8047 int ret;
718e3744 8048
856ca177 8049 bgp_attr_dup (&dummy_attr, ri->attr);
718e3744 8050
856ca177
MS
8051 binfo.peer = ri->peer;
8052 binfo.attr = &dummy_attr;
718e3744 8053
856ca177
MS
8054 ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo);
8055 if (ret == RMAP_DENYMATCH)
8056 continue;
8057 }
8058 if (type == bgp_show_type_neighbor
8059 || type == bgp_show_type_flap_neighbor
8060 || type == bgp_show_type_damp_neighbor)
8061 {
8062 union sockunion *su = output_arg;
718e3744 8063
4f280b15
LB
8064 if (ri->peer == NULL ||
8065 ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
856ca177
MS
8066 continue;
8067 }
a636c635 8068 if (type == bgp_show_type_cidr_only)
856ca177
MS
8069 {
8070 u_int32_t destination;
718e3744 8071
856ca177
MS
8072 destination = ntohl (rn->p.u.prefix4.s_addr);
8073 if (IN_CLASSC (destination) && rn->p.prefixlen == 24)
8074 continue;
8075 if (IN_CLASSB (destination) && rn->p.prefixlen == 16)
8076 continue;
8077 if (IN_CLASSA (destination) && rn->p.prefixlen == 8)
8078 continue;
8079 }
a636c635 8080 if (type == bgp_show_type_prefix_longer)
856ca177
MS
8081 {
8082 struct prefix *p = output_arg;
718e3744 8083
856ca177
MS
8084 if (! prefix_match (p, &rn->p))
8085 continue;
8086 }
8087 if (type == bgp_show_type_community_all)
8088 {
8089 if (! ri->attr->community)
8090 continue;
8091 }
8092 if (type == bgp_show_type_community)
8093 {
8094 struct community *com = output_arg;
718e3744 8095
856ca177
MS
8096 if (! ri->attr->community ||
8097 ! community_match (ri->attr->community, com))
8098 continue;
8099 }
8100 if (type == bgp_show_type_community_exact)
8101 {
8102 struct community *com = output_arg;
718e3744 8103
856ca177
MS
8104 if (! ri->attr->community ||
8105 ! community_cmp (ri->attr->community, com))
8106 continue;
8107 }
8108 if (type == bgp_show_type_community_list)
8109 {
8110 struct community_list *list = output_arg;
718e3744 8111
856ca177
MS
8112 if (! community_list_match (ri->attr->community, list))
8113 continue;
8114 }
8115 if (type == bgp_show_type_community_list_exact)
8116 {
8117 struct community_list *list = output_arg;
718e3744 8118
856ca177
MS
8119 if (! community_list_exact_match (ri->attr->community, list))
8120 continue;
8121 }
2acb4ac2
DL
8122 if (type == bgp_show_type_lcommunity)
8123 {
8124 struct lcommunity *lcom = output_arg;
57d187bc 8125
aadc0905
DS
8126 if (! ri->attr->lcommunity ||
8127 ! lcommunity_match (ri->attr->lcommunity, lcom))
2acb4ac2
DL
8128 continue;
8129 }
8130 if (type == bgp_show_type_lcommunity_list)
8131 {
8132 struct community_list *list = output_arg;
57d187bc 8133
aadc0905 8134 if (! lcommunity_list_match (ri->attr->lcommunity, list))
2acb4ac2
DL
8135 continue;
8136 }
8137 if (type == bgp_show_type_lcommunity_all)
8138 {
aadc0905 8139 if (! ri->attr->lcommunity)
2acb4ac2
DL
8140 continue;
8141 }
856ca177
MS
8142 if (type == bgp_show_type_dampend_paths
8143 || type == bgp_show_type_damp_neighbor)
8144 {
8145 if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)
8146 || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
8147 continue;
8148 }
8149
8150 if (!use_json && header)
8151 {
96ade3ed
QY
8152 vty_outln (vty, "BGP table version is %" PRIu64 ", local router ID is %s", table->version,
8153 inet_ntoa(bgp->router_id));
1318e7c8
QY
8154 vty_outln (vty, BGP_SHOW_SCODE_HEADER, VTYNL);
8155 vty_outln (vty, BGP_SHOW_OCODE_HEADER, VTYNL);
856ca177
MS
8156 if (type == bgp_show_type_dampend_paths
8157 || type == bgp_show_type_damp_neighbor)
96ade3ed 8158 vty_outln (vty, BGP_SHOW_DAMP_HEADER);
856ca177 8159 else if (type == bgp_show_type_flap_statistics
856ca177 8160 || type == bgp_show_type_flap_neighbor)
96ade3ed 8161 vty_outln (vty, BGP_SHOW_FLAP_HEADER);
856ca177 8162 else
96ade3ed 8163 vty_outln (vty, BGP_SHOW_HEADER);
856ca177
MS
8164 header = 0;
8165 }
8166
8167 if (type == bgp_show_type_dampend_paths
8168 || type == bgp_show_type_damp_neighbor)
8169 damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths);
8170 else if (type == bgp_show_type_flap_statistics
856ca177
MS
8171 || type == bgp_show_type_flap_neighbor)
8172 flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths);
8173 else
8174 route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, json_paths);
8175 display++;
b05a1c8b
DS
8176 }
8177
856ca177
MS
8178 if (display)
8179 {
8180 output_count++;
8181 if (use_json)
8182 {
8183 p = &rn->p;
8184 sprintf(buf2, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
31303c3e
DS
8185 vty_out (vty, "\"%s\": ", buf2);
8186 vty_out (vty, "%s", json_object_to_json_string (json_paths));
8187 json_object_free (json_paths);
8188 first = 0;
8189
856ca177
MS
8190 }
8191 }
9f689658 8192 }
718e3744 8193
b05a1c8b 8194 if (use_json)
718e3744 8195 {
31303c3e 8196 json_object_free (json_paths);
96ade3ed 8197 vty_outln (vty, " } }");
718e3744 8198 }
8199 else
b05a1c8b
DS
8200 {
8201 /* No route is displayed */
8202 if (output_count == 0)
8203 {
8204 if (type == bgp_show_type_normal)
96ade3ed
QY
8205 vty_outln (vty, "No BGP prefixes displayed, %ld exist",
8206 total_count);
b05a1c8b
DS
8207 }
8208 else
96ade3ed 8209 vty_outln (vty, "%sDisplayed %ld routes and %ld total paths",
1318e7c8 8210 VTYNL, output_count, total_count);
b05a1c8b 8211 }
718e3744 8212
8213 return CMD_SUCCESS;
8214}
8215
5a646650 8216static int
fee0f4c6 8217bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
856ca177 8218 enum bgp_show_type type, void *output_arg, u_char use_json)
fee0f4c6 8219{
8220 struct bgp_table *table;
8221
856ca177
MS
8222 if (bgp == NULL)
8223 {
8224 bgp = bgp_get_default ();
8225 }
fee0f4c6 8226
8227 if (bgp == NULL)
8228 {
856ca177 8229 if (!use_json)
96ade3ed 8230 vty_outln (vty, "No BGP process is configured");
fee0f4c6 8231 return CMD_WARNING;
8232 }
4f280b15
LB
8233 /* use MPLS and ENCAP specific shows until they are merged */
8234 if (safi == SAFI_MPLS_VPN)
8235 {
8236 return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg,
8237 0, use_json);
8238 }
fee0f4c6 8239
fee0f4c6 8240 table = bgp->rib[afi][safi];
8241
31303c3e
DS
8242 return bgp_show_table (vty, bgp, table, type, output_arg,
8243 use_json);
fee0f4c6 8244}
8245
f186de26 8246static void
8247bgp_show_all_instances_routes_vty (struct vty *vty, afi_t afi, safi_t safi,
8248 u_char use_json)
8249{
8250 struct listnode *node, *nnode;
8251 struct bgp *bgp;
9f689658
DD
8252 int is_first = 1;
8253
8254 if (use_json)
96ade3ed 8255 vty_outln (vty, "{");
f186de26 8256
8257 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
8258 {
9f689658
DD
8259 if (use_json)
8260 {
9f689658 8261 if (! is_first)
96ade3ed 8262 vty_outln (vty, ",");
9f689658
DD
8263 else
8264 is_first = 0;
8265
8266 vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8267 ? "Default" : bgp->name);
8268 }
8269 else
8270 {
96ade3ed 8271 vty_outln (vty, "%sInstance %s:",
1318e7c8 8272 VTYNL,
96ade3ed 8273 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name);
9f689658 8274 }
8282ecff 8275 bgp_show (vty, bgp, afi, safi, bgp_show_type_normal, NULL, use_json);
9f689658 8276
f186de26 8277 }
9f689658
DD
8278
8279 if (use_json)
96ade3ed 8280 vty_outln (vty, "}");
f186de26 8281}
8282
718e3744 8283/* Header of detailed BGP route information */
520d5d76 8284void
718e3744 8285route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
8286 struct bgp_node *rn,
b05a1c8b
DS
8287 struct prefix_rd *prd, afi_t afi, safi_t safi,
8288 json_object *json)
718e3744 8289{
8290 struct bgp_info *ri;
8291 struct prefix *p;
8292 struct peer *peer;
1eb8ef25 8293 struct listnode *node, *nnode;
718e3744 8294 char buf1[INET6_ADDRSTRLEN];
8295 char buf2[INET6_ADDRSTRLEN];
520d5d76 8296 char buf3[EVPN_ROUTE_STRLEN];
718e3744 8297 int count = 0;
8298 int best = 0;
8299 int suppress = 0;
8300 int no_export = 0;
8301 int no_advertise = 0;
8302 int local_as = 0;
adbac85e 8303 int first = 1;
9bedbb1e 8304 int has_valid_label = 0;
0826e83c 8305 mpls_label_t label;
ffd0c037 8306 json_object *json_adv_to = NULL;
718e3744 8307
8308 p = &rn->p;
9bedbb1e
DW
8309 has_valid_label = bgp_is_valid_label(&rn->local_label);
8310
8311 if (has_valid_label)
8312 label = label_pton(&rn->local_label);
b05a1c8b
DS
8313
8314 if (json)
8315 {
9bedbb1e
DW
8316 if (has_valid_label)
8317 json_object_int_add(json, "localLabel", label);
8318
f1aa5d8a
DS
8319 json_object_string_add(json, "prefix", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN));
8320 json_object_int_add(json, "prefixlen", p->prefixlen);
b05a1c8b
DS
8321 }
8322 else
8323 {
520d5d76 8324#if defined (HAVE_CUMULUS)
8325 if (safi == SAFI_EVPN)
8326 vty_out (vty, "BGP routing table entry for %s%s%s%s",
8327 prd ? prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : "",
8328 prd ? ":" : "",
8329 bgp_evpn_route2str ((struct prefix_evpn *)p,
8330 buf3, sizeof (buf3)),
8331 VTY_NEWLINE);
8332 else
8333 vty_out (vty, "BGP routing table entry for %s%s%s/%d%s",
8334 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) ?
8335 prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
8336 safi == SAFI_MPLS_VPN ? ":" : "",
8337 inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN),
8338 p->prefixlen, VTY_NEWLINE);
8339#else
dc49391e
JC
8340 if (p->family == AF_ETHERNET)
8341 prefix2str (p, buf2, INET6_ADDRSTRLEN);
8342 else
8343 inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN);
96ade3ed 8344 vty_outln (vty, "BGP routing table entry for %s%s%s/%d",
3d6c0dfa 8345 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) ?
b05a1c8b 8346 prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
3d6c0dfa 8347 ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "",
dc49391e 8348 buf2,
96ade3ed 8349 p->prefixlen);
520d5d76 8350#endif
cd1964ff 8351
9bedbb1e 8352 if (has_valid_label)
b738b1ac 8353 vty_outln (vty, "Local label: %d", label);
520d5d76 8354#if defined (HAVE_CUMULUS)
8355 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
8356#else
8357 if (bgp_labeled_safi(safi))
8358#endif
8359 vty_out(vty, "not allocated%s", VTY_NEWLINE);
b05a1c8b 8360 }
718e3744 8361
8362 for (ri = rn->info; ri; ri = ri->next)
8363 {
8364 count++;
8365 if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
8366 {
8367 best = count;
fb982c25 8368 if (ri->extra && ri->extra->suppress)
718e3744 8369 suppress = 1;
8370 if (ri->attr->community != NULL)
8371 {
8372 if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE))
8373 no_advertise = 1;
8374 if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT))
8375 no_export = 1;
8376 if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS))
8377 local_as = 1;
8378 }
8379 }
8380 }
8381
b05a1c8b 8382 if (!json)
718e3744 8383 {
b05a1c8b
DS
8384 vty_out (vty, "Paths: (%d available", count);
8385 if (best)
8386 {
8387 vty_out (vty, ", best #%d", best);
8388 if (safi == SAFI_UNICAST)
46827ae9
DS
8389 vty_out (vty, ", table %s",
8390 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
8391 ? "Default-IP-Routing-Table" : bgp->name);
b05a1c8b
DS
8392 }
8393 else
8394 vty_out (vty, ", no best path");
8395
8396 if (no_advertise)
8397 vty_out (vty, ", not advertised to any peer");
8398 else if (no_export)
8399 vty_out (vty, ", not advertised to EBGP peer");
8400 else if (local_as)
8401 vty_out (vty, ", not advertised outside local AS");
8402
8403 if (suppress)
8404 vty_out (vty, ", Advertisements suppressed by an aggregate.");
96ade3ed 8405 vty_outln (vty, ")");
718e3744 8406 }
718e3744 8407
adbac85e
DW
8408 /* If we are not using addpath then we can display Advertised to and that will
8409 * show what peers we advertised the bestpath to. If we are using addpath
8410 * though then we must display Advertised to on a path-by-path basis. */
8411 if (!bgp->addpath_tx_used[afi][safi])
718e3744 8412 {
adbac85e
DW
8413 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
8414 {
8415 if (bgp_adj_out_lookup (peer, rn, 0))
b05a1c8b 8416 {
adbac85e 8417 if (json && !json_adv_to)
f1aa5d8a 8418 json_adv_to = json_object_new_object();
6410e93a 8419
adbac85e
DW
8420 route_vty_out_advertised_to(vty, peer, &first,
8421 " Advertised to non peer-group peers:\n ",
8422 json_adv_to);
b05a1c8b 8423 }
adbac85e 8424 }
036a4e7d 8425
adbac85e
DW
8426 if (json)
8427 {
8428 if (json_adv_to)
8429 {
8430 json_object_object_add(json, "advertisedTo", json_adv_to);
b05a1c8b 8431 }
adbac85e
DW
8432 }
8433 else
b05a1c8b 8434 {
adbac85e
DW
8435 if (first)
8436 vty_out (vty, " Not advertised to any peer");
e31b6333 8437 vty_out (vty, VTYNL);
b05a1c8b
DS
8438 }
8439 }
718e3744 8440}
8441
8442/* Display specified route of BGP table. */
94f2b392 8443static int
fee0f4c6 8444bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
fd79ac91 8445 struct bgp_table *rib, const char *ip_str,
8446 afi_t afi, safi_t safi, struct prefix_rd *prd,
b05a1c8b
DS
8447 int prefix_check, enum bgp_path_type pathtype,
8448 u_char use_json)
718e3744 8449{
8450 int ret;
8451 int header;
8452 int display = 0;
8453 struct prefix match;
8454 struct bgp_node *rn;
8455 struct bgp_node *rm;
8456 struct bgp_info *ri;
718e3744 8457 struct bgp_table *table;
f1aa5d8a
DS
8458 json_object *json = NULL;
8459 json_object *json_paths = NULL;
718e3744 8460
718e3744 8461 /* Check IP address argument. */
8462 ret = str2prefix (ip_str, &match);
8463 if (! ret)
8464 {
96ade3ed 8465 vty_outln (vty, "address is malformed");
718e3744 8466 return CMD_WARNING;
8467 }
8468
8469 match.family = afi2family (afi);
8470
b05a1c8b
DS
8471 if (use_json)
8472 {
8473 json = json_object_new_object();
8474 json_paths = json_object_new_array();
8475 }
b05a1c8b 8476
3d6c0dfa 8477 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
718e3744 8478 {
fee0f4c6 8479 for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
718e3744 8480 {
8481 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
8482 continue;
8483
8484 if ((table = rn->info) != NULL)
8485 {
8486 header = 1;
8487
8488 if ((rm = bgp_node_match (table, &match)) != NULL)
8489 {
8490 if (prefix_check && rm->p.prefixlen != match.prefixlen)
6c88b44d
CC
8491 {
8492 bgp_unlock_node (rm);
8493 continue;
8494 }
718e3744 8495
8496 for (ri = rm->info; ri; ri = ri->next)
8497 {
8498 if (header)
8499 {
8500 route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p,
587ff0fd 8501 AFI_IP, safi, json);
718e3744 8502 header = 0;
8503 }
8504 display++;
4092b06c
DS
8505
8506 if (pathtype == BGP_PATH_ALL ||
8507 (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
8508 (pathtype == BGP_PATH_MULTIPATH &&
8509 (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
587ff0fd 8510 route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi, json_paths);
718e3744 8511 }
6c88b44d
CC
8512
8513 bgp_unlock_node (rm);
718e3744 8514 }
8515 }
8516 }
8517 }
8518 else
8519 {
8520 header = 1;
8521
fee0f4c6 8522 if ((rn = bgp_node_match (rib, &match)) != NULL)
718e3744 8523 {
8524 if (! prefix_check || rn->p.prefixlen == match.prefixlen)
8525 {
8526 for (ri = rn->info; ri; ri = ri->next)
8527 {
8528 if (header)
8529 {
b05a1c8b 8530 route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi, json);
718e3744 8531 header = 0;
8532 }
8533 display++;
4092b06c
DS
8534
8535 if (pathtype == BGP_PATH_ALL ||
8536 (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
8537 (pathtype == BGP_PATH_MULTIPATH &&
8538 (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
b05a1c8b 8539 route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, json_paths);
718e3744 8540 }
8541 }
6c88b44d
CC
8542
8543 bgp_unlock_node (rn);
718e3744 8544 }
8545 }
8546
e5eee9af 8547 if (use_json)
718e3744 8548 {
e5eee9af
DS
8549 if (display)
8550 json_object_object_add(json, "paths", json_paths);
8551
96ade3ed
QY
8552 vty_outln (vty, "%s",
8553 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
f1aa5d8a 8554 json_object_free(json);
b05a1c8b
DS
8555 }
8556 else
8557 {
e5eee9af 8558 if (!display)
b05a1c8b 8559 {
96ade3ed 8560 vty_outln (vty, "%% Network not in table");
b05a1c8b
DS
8561 return CMD_WARNING;
8562 }
8563 }
8564
718e3744 8565 return CMD_SUCCESS;
8566}
8567
fee0f4c6 8568/* Display specified route of Main RIB */
94f2b392 8569static int
c41247f5 8570bgp_show_route (struct vty *vty, struct bgp *bgp, const char *ip_str,
fee0f4c6 8571 afi_t afi, safi_t safi, struct prefix_rd *prd,
b05a1c8b
DS
8572 int prefix_check, enum bgp_path_type pathtype,
8573 u_char use_json)
fee0f4c6 8574{
41cebd7e
DS
8575 if (!bgp)
8576 bgp = bgp_get_default ();
8577
fee0f4c6 8578 return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str,
b05a1c8b
DS
8579 afi, safi, prd, prefix_check, pathtype,
8580 use_json);
fee0f4c6 8581}
fee0f4c6 8582
57d187bc
JS
8583static int
8584bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc,
2acb4ac2 8585 struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj)
57d187bc
JS
8586{
8587 struct lcommunity *lcom;
8588 struct buffer *b;
8589 int i;
8590 char *str;
8591 int first = 0;
8592
8593 b = buffer_new (1024);
8594 for (i = 0; i < argc; i++)
fee0f4c6 8595 {
57d187bc
JS
8596 if (first)
8597 buffer_putc (b, ' ');
8598 else
2acb4ac2 8599 {
d536095f 8600 if (strmatch (argv[i]->text, "AA:BB:CC"))
2acb4ac2
DL
8601 {
8602 first = 1;
8603 buffer_putstr (b, argv[i]->arg);
8604 }
8605 }
fee0f4c6 8606 }
57d187bc
JS
8607 buffer_putc (b, '\0');
8608
8609 str = buffer_getstr (b);
8610 buffer_free (b);
8611
8612 lcom = lcommunity_str2com (str);
8613 XFREE (MTYPE_TMP, str);
8614 if (! lcom)
fee0f4c6 8615 {
96ade3ed 8616 vty_outln (vty, "%% Large-community malformed");
57d187bc 8617 return CMD_WARNING;
fee0f4c6 8618 }
57d187bc
JS
8619
8620 return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, uj);
8621}
8622
8623static int
8624bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom,
2acb4ac2 8625 afi_t afi, safi_t safi, u_char uj)
57d187bc
JS
8626{
8627 struct community_list *list;
8628
8629 list = community_list_lookup (bgp_clist, lcom, LARGE_COMMUNITY_LIST_MASTER);
8630 if (list == NULL)
8631 {
96ade3ed 8632 vty_outln (vty, "%% %s is not a valid large-community-list name",lcom);
57d187bc
JS
8633 return CMD_WARNING;
8634 }
8635
8636 return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_list, list, uj);
fee0f4c6 8637}
8638
52951b63
DS
8639DEFUN (show_ip_bgp_large_community_list,
8640 show_ip_bgp_large_community_list_cmd,
c1a44e43 8641 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
52951b63
DS
8642 SHOW_STR
8643 IP_STR
8644 BGP_STR
8645 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
8646 BGP_AFI_HELP_STR
8647 BGP_SAFI_HELP_STR
52951b63
DS
8648 "Display routes matching the large-community-list\n"
8649 "large-community-list number\n"
8650 "large-community-list name\n"
8651 JSON_STR)
8652{
8653 char *vrf = NULL;
8654 afi_t afi = AFI_IP6;
8655 safi_t safi = SAFI_UNICAST;
8656 int idx = 0;
8657
8658 if (argv_find (argv, argc, "ip", &idx))
8659 afi = AFI_IP;
8660 if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx))
8661 vrf = argv[++idx]->arg;
8662 if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx))
8663 {
8664 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
8665 if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
55f91488 8666 safi = bgp_vty_safi_from_str (argv[idx]->text);
52951b63
DS
8667 }
8668
8669 int uj = use_json (argc, argv);
8670
8671 struct bgp *bgp = bgp_lookup_by_name (vrf);
8672 if (bgp == NULL)
8673 {
96ade3ed 8674 vty_outln (vty, "Can't find BGP instance %s", vrf);
52951b63
DS
8675 return CMD_WARNING;
8676 }
8677
8678 argv_find (argv, argc, "large-community-list", &idx);
8679 return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj);
8680}
8681DEFUN (show_ip_bgp_large_community,
8682 show_ip_bgp_large_community_cmd,
c1a44e43 8683 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] large-community [AA:BB:CC] [json]",
52951b63
DS
8684 SHOW_STR
8685 IP_STR
8686 BGP_STR
8687 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
8688 BGP_AFI_HELP_STR
8689 BGP_SAFI_HELP_STR
52951b63
DS
8690 "Display routes matching the large-communities\n"
8691 "List of large-community numbers\n"
8692 JSON_STR)
8693{
8694 char *vrf = NULL;
8695 afi_t afi = AFI_IP6;
8696 safi_t safi = SAFI_UNICAST;
8697 int idx = 0;
8698
8699 if (argv_find (argv, argc, "ip", &idx))
8700 afi = AFI_IP;
8701 if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx))
8702 vrf = argv[++idx]->arg;
8703 if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx))
8704 {
8705 afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
8706 if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx))
55f91488 8707 safi = bgp_vty_safi_from_str (argv[idx]->text);
52951b63
DS
8708 }
8709
8710 int uj = use_json (argc, argv);
8711
8712 struct bgp *bgp = bgp_lookup_by_name (vrf);
8713 if (bgp == NULL)
8714 {
96ade3ed 8715 vty_outln (vty, "Can't find BGP instance %s", vrf);
52951b63
DS
8716 return CMD_WARNING;
8717 }
8718
d536095f 8719 if (argv_find (argv, argc, "AA:BB:CC", &idx))
52951b63
DS
8720 return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj);
8721 else
8722 return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj);
8723}
8724
e01ca200
DS
8725static int bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi);
8726
718e3744 8727/* BGP route print out function. */
af462945
DS
8728DEFUN (show_ip_bgp,
8729 show_ip_bgp_cmd,
18c57037 8730 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]]\
ae19d7dd
QY
8731 [<\
8732 cidr-only\
8c3deaae 8733 |dampening <flap-statistics|dampened-paths|parameters>\
ae19d7dd
QY
8734 |route-map WORD\
8735 |prefix-list WORD\
8736 |filter-list WORD\
e01ca200 8737 |statistics\
0c7b1b01 8738 |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
ae19d7dd
QY
8739 |community-list <(1-500)|WORD> [exact-match]\
8740 |A.B.C.D/M longer-prefixes\
9711caf8
DS
8741 |X:X::X:X/M longer-prefixes>\
8742 ] [json]",
718e3744 8743 SHOW_STR
8744 IP_STR
8745 BGP_STR
a636c635 8746 BGP_INSTANCE_HELP_STR
4f280b15
LB
8747 BGP_AFI_HELP_STR
8748 BGP_SAFI_HELP_STR
a636c635 8749 "Display only routes with non-natural netmasks\n"
a636c635
DW
8750 "Display detailed information about dampening\n"
8751 "Display flap statistics of routes\n"
8752 "Display paths suppressed due to dampening\n"
af462945 8753 "Display detail of configured dampening parameters\n"
a636c635
DW
8754 "Display routes matching the route-map\n"
8755 "A route-map to match on\n"
8756 "Display routes conforming to the prefix-list\n"
8c3deaae 8757 "Prefix-list name\n"
a636c635
DW
8758 "Display routes conforming to the filter-list\n"
8759 "Regular expression access list name\n"
e01ca200 8760 "BGP RIB advertisement statistics\n"
a636c635
DW
8761 "Display routes matching the communities\n"
8762 COMMUNITY_AANN_STR
8763 "Do not send outside local AS (well-known community)\n"
8764 "Do not advertise to any peer (well-known community)\n"
8765 "Do not export to next AS (well-known community)\n"
8766 "Exact match of the communities\n"
8767 "Display routes matching the community-list\n"
8768 "community-list number\n"
8769 "community-list name\n"
8770 "Exact match of the communities\n"
0c7b1b01 8771 "IPv4 prefix\n"
8c3deaae 8772 "Display route and more specific routes\n"
0c7b1b01 8773 "IPv6 prefix\n"
a636c635 8774 "Display route and more specific routes\n"
9973d184 8775 JSON_STR)
718e3744 8776{
ae19d7dd
QY
8777 afi_t afi = AFI_IP6;
8778 safi_t safi = SAFI_UNICAST;
ef736f12 8779 int exact_match = 0;
a636c635 8780 enum bgp_show_type sh_type = bgp_show_type_normal;
af462945 8781 struct bgp *bgp = NULL;
ae19d7dd
QY
8782 int idx = 0;
8783
f212a857 8784 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
af462945 8785 if (!idx)
c493f2d8
DS
8786 return CMD_WARNING;
8787
ae19d7dd
QY
8788 int uj = use_json (argc, argv);
8789 if (uj) argc--;
a636c635 8790
af462945
DS
8791 if (argv_find(argv, argc, "cidr-only", &idx))
8792 return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj);
a636c635 8793
af462945 8794 if (argv_find(argv, argc, "dampening", &idx))
8c3deaae
QY
8795 {
8796 if (argv_find (argv, argc, "dampened-paths", &idx))
8797 return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj);
8798 else if (argv_find (argv, argc, "flap-statistics", &idx))
8799 return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj);
8800 else if (argv_find (argv, argc, "parameters", &idx))
af462945 8801 return bgp_show_dampening_parameters (vty, afi, safi);
8c3deaae 8802 }
a636c635 8803
af462945
DS
8804 if (argv_find(argv, argc, "prefix-list", &idx))
8805 return bgp_show_prefix_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list);
a636c635 8806
af462945
DS
8807 if (argv_find(argv, argc, "filter-list", &idx))
8808 return bgp_show_filter_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list);
a636c635 8809
e01ca200
DS
8810 if (argv_find(argv, argc, "statistics", &idx))
8811 return bgp_table_stats (vty, bgp, afi, safi);
a636c635 8812
af462945
DS
8813 if (argv_find(argv, argc, "route-map", &idx))
8814 return bgp_show_route_map (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map);
a636c635 8815
af462945 8816 if (argv_find(argv, argc, "community", &idx))
ae19d7dd
QY
8817 {
8818 /* show a specific community */
08435c2b
DS
8819 if (argv_find (argv, argc, "local-AS", &idx) ||
8820 argv_find (argv, argc, "no-advertise", &idx) ||
8821 argv_find (argv, argc, "no-export", &idx))
ae19d7dd 8822 {
08435c2b 8823 if (argv_find (argv, argc, "exact_match", &idx))
ae19d7dd 8824 exact_match = 1;
af462945 8825 return bgp_show_community (vty, bgp, argc, argv, exact_match, afi, safi);
ae19d7dd
QY
8826 }
8827 /* show all communities */
8828 else
8829 return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj);
8830 }
c016b6c7 8831
af462945
DS
8832 if (argv_find(argv, argc, "community-list", &idx))
8833 {
8834 const char *clist_number_or_name = argv[++idx]->arg;
0e37c258 8835 if (++idx < argc && strmatch (argv[idx]->text, "exact-match"))
af462945
DS
8836 exact_match = 1;
8837 return bgp_show_community_list (vty, bgp, clist_number_or_name, exact_match, afi, safi);
8838 }
8839 /* prefix-longer */
8840 if (argv_find(argv, argc, "A.B.C.D/M", &idx) || argv_find(argv, argc, "X:X::X:X/M", &idx))
ff595214 8841 return bgp_show_prefix_longer (vty, bgp, argv[idx]->arg, afi, safi, bgp_show_type_prefix_longer);
a636c635 8842
4e019978
PG
8843 if (safi == SAFI_MPLS_VPN)
8844 return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, uj);
4e019978
PG
8845 else
8846 return bgp_show (vty, bgp, afi, safi, sh_type, NULL, uj);
a636c635 8847}
47fc97cc 8848
718e3744 8849DEFUN (show_ip_bgp_route,
8850 show_ip_bgp_route_cmd,
18c57037 8851 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]]"
ae19d7dd 8852 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
718e3744 8853 SHOW_STR
8854 IP_STR
8855 BGP_STR
a636c635 8856 BGP_INSTANCE_HELP_STR
4f280b15
LB
8857 BGP_AFI_HELP_STR
8858 BGP_SAFI_HELP_STR
b05a1c8b 8859 "Network in the BGP routing table to display\n"
0c7b1b01 8860 "IPv4 prefix\n"
8c3deaae 8861 "Network in the BGP routing table to display\n"
0c7b1b01 8862 "IPv6 prefix\n"
4092b06c 8863 "Display only the bestpath\n"
b05a1c8b 8864 "Display only multipaths\n"
9973d184 8865 JSON_STR)
4092b06c 8866{
a636c635 8867 int prefix_check = 0;
ae19d7dd
QY
8868
8869 afi_t afi = AFI_IP6;
8870 safi_t safi = SAFI_UNICAST;
ae19d7dd 8871 char *prefix = NULL;
c41247f5 8872 struct bgp *bgp = NULL;
a636c635 8873 enum bgp_path_type path_type;
db7c8528 8874 u_char uj = use_json(argc, argv);
b05a1c8b 8875
ae19d7dd
QY
8876 int idx = 0;
8877
f212a857 8878 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
c41247f5 8879 if (!idx)
c493f2d8 8880 return CMD_WARNING;
c41247f5 8881
f212a857 8882 if (!bgp)
0e37c258 8883 {
96ade3ed
QY
8884 vty_outln (vty,
8885 "Specified 'all' vrf's but this command currently only works per view/vrf");
0e37c258
DS
8886 return CMD_WARNING;
8887 }
a636c635 8888
ae19d7dd
QY
8889 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8890 if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx))
a636c635 8891 prefix_check = 0;
ae19d7dd 8892 else if (argv_find (argv, argc, "A.B.C.D/M", &idx) || argv_find (argv, argc, "X:X::X:X/M", &idx))
a636c635
DW
8893 prefix_check = 1;
8894
ae19d7dd
QY
8895 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) && afi != AFI_IP6)
8896 {
96ade3ed
QY
8897 vty_outln (vty,
8898 "%% Cannot specify IPv6 address or prefix with IPv4 AFI");
ae19d7dd
QY
8899 return CMD_WARNING;
8900 }
8901 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) && afi != AFI_IP)
8902 {
96ade3ed
QY
8903 vty_outln (vty,
8904 "%% Cannot specify IPv4 address or prefix with IPv6 AFI");
ae19d7dd
QY
8905 return CMD_WARNING;
8906 }
a636c635 8907
ae19d7dd
QY
8908 prefix = argv[idx]->arg;
8909
8910 /* [<bestpath|multipath>] */
8911 if (argv_find (argv, argc, "bestpath", &idx))
a636c635 8912 path_type = BGP_PATH_BESTPATH;
ae19d7dd 8913 else if (argv_find (argv, argc, "multipath", &idx))
a636c635 8914 path_type = BGP_PATH_MULTIPATH;
4092b06c 8915 else
a636c635
DW
8916 path_type = BGP_PATH_ALL;
8917
c41247f5 8918 return bgp_show_route (vty, bgp, prefix, afi, safi, NULL, prefix_check, path_type, uj);
4092b06c
DS
8919}
8920
8c3deaae
QY
8921DEFUN (show_ip_bgp_regexp,
8922 show_ip_bgp_regexp_cmd,
18c57037 8923 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] regexp REGEX...",
8c3deaae
QY
8924 SHOW_STR
8925 IP_STR
8926 BGP_STR
b00b230a 8927 BGP_INSTANCE_HELP_STR
4f280b15
LB
8928 BGP_AFI_HELP_STR
8929 BGP_SAFI_HELP_STR
8c3deaae
QY
8930 "Display routes matching the AS path regular expression\n"
8931 "A regular-expression to match the BGP AS paths\n")
8932{
8933 afi_t afi = AFI_IP6;
8934 safi_t safi = SAFI_UNICAST;
f212a857 8935 struct bgp *bgp = NULL;
8c3deaae
QY
8936
8937 int idx = 0;
f212a857 8938 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
b00b230a 8939 if (!idx)
c493f2d8 8940 return CMD_WARNING;
8c3deaae
QY
8941
8942 // get index of regex
8943 argv_find (argv, argc, "regexp", &idx);
8944 idx++;
8945
8946 char *regstr = argv_concat (argv, argc, idx);
8947 int rc = bgp_show_regexp (vty, (const char *) regstr, afi, safi, bgp_show_type_regexp);
8948 XFREE (MTYPE_TMP, regstr);
8949 return rc;
8950}
8951
a636c635
DW
8952DEFUN (show_ip_bgp_instance_all,
8953 show_ip_bgp_instance_all_cmd,
4f280b15 8954 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] [json]",
4092b06c 8955 SHOW_STR
a636c635 8956 IP_STR
4092b06c 8957 BGP_STR
a636c635 8958 BGP_INSTANCE_ALL_HELP_STR
4f280b15
LB
8959 BGP_AFI_HELP_STR
8960 BGP_SAFI_HELP_STR
9973d184 8961 JSON_STR)
4092b06c 8962{
ae19d7dd
QY
8963 afi_t afi = AFI_IP;
8964 safi_t safi = SAFI_UNICAST;
f212a857 8965 struct bgp *bgp = NULL;
ae19d7dd
QY
8966
8967 int idx = 0;
f212a857 8968 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
f2a8972b 8969 if (!idx)
c493f2d8 8970 return CMD_WARNING;
ae19d7dd 8971
f2a8972b
DS
8972 int uj = use_json (argc, argv);
8973 if (uj) argc--;
e3e29b32 8974
273f7743 8975 bgp_show_all_instances_routes_vty (vty, afi, safi, uj);
a636c635 8976 return CMD_SUCCESS;
e3e29b32
LB
8977}
8978
a636c635 8979static int
8c3deaae 8980bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi,
a636c635 8981 safi_t safi, enum bgp_show_type type)
718e3744 8982{
a636c635
DW
8983 regex_t *regex;
8984 int rc;
8985
a636c635 8986 regex = bgp_regcomp (regstr);
a636c635
DW
8987 if (! regex)
8988 {
96ade3ed 8989 vty_outln (vty, "Can't compile regexp %s", regstr);
a636c635
DW
8990 return CMD_WARNING;
8991 }
718e3744 8992
a636c635
DW
8993 rc = bgp_show (vty, NULL, afi, safi, type, regex, 0);
8994 bgp_regex_free (regex);
8995 return rc;
e3e29b32
LB
8996}
8997
a636c635 8998static int
af462945 8999bgp_show_prefix_list (struct vty *vty, struct bgp *bgp,
a636c635
DW
9000 const char *prefix_list_str, afi_t afi,
9001 safi_t safi, enum bgp_show_type type)
e3e29b32 9002{
a636c635 9003 struct prefix_list *plist;
e3e29b32 9004
a636c635
DW
9005 plist = prefix_list_lookup (afi, prefix_list_str);
9006 if (plist == NULL)
e3e29b32 9007 {
96ade3ed
QY
9008 vty_outln (vty, "%% %s is not a valid prefix-list name",
9009 prefix_list_str);
e3e29b32
LB
9010 return CMD_WARNING;
9011 }
a636c635
DW
9012
9013 return bgp_show (vty, bgp, afi, safi, type, plist, 0);
e3e29b32
LB
9014}
9015
a636c635 9016static int
af462945 9017bgp_show_filter_list (struct vty *vty, struct bgp *bgp,
a636c635
DW
9018 const char *filter, afi_t afi,
9019 safi_t safi, enum bgp_show_type type)
e3e29b32 9020{
a636c635 9021 struct as_list *as_list;
718e3744 9022
a636c635
DW
9023 as_list = as_list_lookup (filter);
9024 if (as_list == NULL)
718e3744 9025 {
96ade3ed
QY
9026 vty_outln (vty, "%% %s is not a valid AS-path access-list name",
9027 filter);
718e3744 9028 return CMD_WARNING;
9029 }
718e3744 9030
a636c635 9031 return bgp_show (vty, bgp, afi, safi, type, as_list, 0);
4092b06c
DS
9032}
9033
a636c635 9034static int
af462945 9035bgp_show_route_map (struct vty *vty, struct bgp *bgp,
a636c635
DW
9036 const char *rmap_str, afi_t afi,
9037 safi_t safi, enum bgp_show_type type)
4092b06c 9038{
a636c635 9039 struct route_map *rmap;
718e3744 9040
a636c635
DW
9041 rmap = route_map_lookup_by_name (rmap_str);
9042 if (! rmap)
718e3744 9043 {
96ade3ed
QY
9044 vty_outln (vty, "%% %s is not a valid route-map name",
9045 rmap_str);
718e3744 9046 return CMD_WARNING;
9047 }
a636c635
DW
9048
9049 return bgp_show (vty, bgp, afi, safi, type, rmap, 0);
718e3744 9050}
9051
a636c635 9052static int
af462945 9053bgp_show_community (struct vty *vty, struct bgp *bgp, int argc,
a636c635 9054 struct cmd_token **argv, int exact, afi_t afi, safi_t safi)
718e3744 9055{
a636c635
DW
9056 struct community *com;
9057 struct buffer *b;
a636c635
DW
9058 int i;
9059 char *str;
9060 int first = 0;
46c3ce83 9061 int ret = 0;
bb46e94f 9062
a636c635
DW
9063 b = buffer_new (1024);
9064 for (i = 0; i < argc; i++)
9065 {
9066 if (first)
9067 buffer_putc (b, ' ');
9068 else
9069 {
7e045c3d 9070 if (strmatch(argv[i]->text, "unicast") || strmatch(argv[i]->text, "multicast"))
a636c635
DW
9071 continue;
9072 first = 1;
9073 }
9074
9075 buffer_putstr (b, argv[i]->arg);
9076 }
9077 buffer_putc (b, '\0');
718e3744 9078
a636c635
DW
9079 str = buffer_getstr (b);
9080 buffer_free (b);
f186de26 9081
a636c635
DW
9082 com = community_str2com (str);
9083 XFREE (MTYPE_TMP, str);
9084 if (! com)
9085 {
96ade3ed 9086 vty_outln (vty, "%% Community malformed: ");
a636c635
DW
9087 return CMD_WARNING;
9088 }
f186de26 9089
46c3ce83
DS
9090 ret = bgp_show (vty, bgp, afi, safi,
9091 (exact ? bgp_show_type_community_exact :
9092 bgp_show_type_community), com, 0);
9093 community_free (com);
9094
9095 return ret;
718e3744 9096}
9097
a636c635 9098static int
af462945 9099bgp_show_community_list (struct vty *vty, struct bgp *bgp,
a636c635
DW
9100 const char *com, int exact,
9101 afi_t afi, safi_t safi)
50ef26d4 9102{
a636c635 9103 struct community_list *list;
50ef26d4 9104
a636c635
DW
9105 list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_MASTER);
9106 if (list == NULL)
9107 {
96ade3ed 9108 vty_outln (vty, "%% %s is not a valid community-list name",com);
a636c635
DW
9109 return CMD_WARNING;
9110 }
718e3744 9111
a636c635
DW
9112 return bgp_show (vty, bgp, afi, safi,
9113 (exact ? bgp_show_type_community_list_exact :
9114 bgp_show_type_community_list), list, 0);
50ef26d4 9115}
9116
a636c635 9117static int
af462945 9118bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp,
a636c635
DW
9119 const char *prefix, afi_t afi,
9120 safi_t safi, enum bgp_show_type type)
718e3744 9121{
a636c635
DW
9122 int ret;
9123 struct prefix *p;
718e3744 9124
a636c635 9125 p = prefix_new();
47fc97cc 9126
a636c635
DW
9127 ret = str2prefix (prefix, p);
9128 if (! ret)
9129 {
96ade3ed 9130 vty_outln (vty, "%% Malformed Prefix");
a636c635
DW
9131 return CMD_WARNING;
9132 }
95cbbd2a 9133
a636c635
DW
9134 ret = bgp_show (vty, bgp, afi, safi, type, p, 0);
9135 prefix_free(p);
9136 return ret;
47e9b292
DW
9137}
9138
a636c635 9139static struct peer *
30a6a167 9140peer_lookup_in_view (struct vty *vty, struct bgp *bgp,
a636c635 9141 const char *ip_str, u_char use_json)
718e3744 9142{
a636c635 9143 int ret;
a636c635
DW
9144 struct peer *peer;
9145 union sockunion su;
718e3744 9146
a636c635
DW
9147 /* Get peer sockunion. */
9148 ret = str2sockunion (ip_str, &su);
9149 if (ret < 0)
9150 {
9151 peer = peer_lookup_by_conf_if (bgp, ip_str);
9152 if (!peer)
9153 {
9154 peer = peer_lookup_by_hostname(bgp, ip_str);
9155
9156 if (!peer)
9157 {
9158 if (use_json)
9159 {
9160 json_object *json_no = NULL;
9161 json_no = json_object_new_object();
9162 json_object_string_add(json_no, "malformedAddressOrName", ip_str);
96ade3ed 9163 vty_outln (vty, "%s", json_object_to_json_string(json_no));
a636c635
DW
9164 json_object_free(json_no);
9165 }
9166 else
96ade3ed 9167 vty_outln (vty, "%% Malformed address or name: %s", ip_str);
a636c635
DW
9168 return NULL;
9169 }
2815e61f 9170 }
a636c635 9171 return peer;
2815e61f 9172 }
2815e61f 9173
a636c635
DW
9174 /* Peer structure lookup. */
9175 peer = peer_lookup (bgp, &su);
9176 if (! peer)
2815e61f 9177 {
a636c635 9178 if (use_json)
2815e61f 9179 {
a636c635
DW
9180 json_object *json_no = NULL;
9181 json_no = json_object_new_object();
9182 json_object_string_add(json_no, "warning","No such neighbor");
96ade3ed 9183 vty_outln (vty, "%s", json_object_to_json_string(json_no));
a636c635 9184 json_object_free(json_no);
2815e61f 9185 }
2815e61f 9186 else
96ade3ed 9187 vty_outln (vty, "No such neighbor");
a636c635 9188 return NULL;
2815e61f 9189 }
a636c635
DW
9190
9191 return peer;
2815e61f
PJ
9192}
9193
a636c635 9194enum bgp_stats
2815e61f 9195{
a636c635
DW
9196 BGP_STATS_MAXBITLEN = 0,
9197 BGP_STATS_RIB,
9198 BGP_STATS_PREFIXES,
9199 BGP_STATS_TOTPLEN,
9200 BGP_STATS_UNAGGREGATEABLE,
9201 BGP_STATS_MAX_AGGREGATEABLE,
9202 BGP_STATS_AGGREGATES,
9203 BGP_STATS_SPACE,
9204 BGP_STATS_ASPATH_COUNT,
9205 BGP_STATS_ASPATH_MAXHOPS,
9206 BGP_STATS_ASPATH_TOTHOPS,
9207 BGP_STATS_ASPATH_MAXSIZE,
9208 BGP_STATS_ASPATH_TOTSIZE,
9209 BGP_STATS_ASN_HIGHEST,
9210 BGP_STATS_MAX,
9211};
2815e61f 9212
a636c635 9213static const char *table_stats_strs[] =
2815e61f 9214{
a636c635
DW
9215 [BGP_STATS_PREFIXES] = "Total Prefixes",
9216 [BGP_STATS_TOTPLEN] = "Average prefix length",
9217 [BGP_STATS_RIB] = "Total Advertisements",
9218 [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
9219 [BGP_STATS_MAX_AGGREGATEABLE] = "Maximum aggregateable prefixes",
9220 [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
9221 [BGP_STATS_SPACE] = "Address space advertised",
9222 [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
9223 [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
9224 [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
9225 [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
9226 [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
9227 [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
9228 [BGP_STATS_MAX] = NULL,
9229};
2815e61f 9230
a636c635 9231struct bgp_table_stats
ff7924f6 9232{
a636c635
DW
9233 struct bgp_table *table;
9234 unsigned long long counts[BGP_STATS_MAX];
ff7924f6
PJ
9235};
9236
a636c635
DW
9237#if 0
9238#define TALLY_SIGFIG 100000
9239static unsigned long
9240ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 9241{
a636c635
DW
9242 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
9243 unsigned long res = (newtot * TALLY_SIGFIG) / count;
9244 unsigned long ret = newtot / count;
9245
9246 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
9247 return ret + 1;
9248 else
9249 return ret;
9250}
9251#endif
ff7924f6 9252
a636c635
DW
9253static int
9254bgp_table_stats_walker (struct thread *t)
2815e61f 9255{
a636c635
DW
9256 struct bgp_node *rn;
9257 struct bgp_node *top;
9258 struct bgp_table_stats *ts = THREAD_ARG (t);
9259 unsigned int space = 0;
9260
9261 if (!(top = bgp_table_top (ts->table)))
9262 return 0;
9263
9264 switch (top->p.family)
9265 {
9266 case AF_INET:
9267 space = IPV4_MAX_BITLEN;
9268 break;
9269 case AF_INET6:
9270 space = IPV6_MAX_BITLEN;
9271 break;
9272 }
9273
9274 ts->counts[BGP_STATS_MAXBITLEN] = space;
2815e61f 9275
a636c635 9276 for (rn = top; rn; rn = bgp_route_next (rn))
ff7924f6 9277 {
2815e61f 9278 struct bgp_info *ri;
a636c635
DW
9279 struct bgp_node *prn = bgp_node_parent_nolock (rn);
9280 unsigned int rinum = 0;
ff7924f6 9281
a636c635
DW
9282 if (rn == top)
9283 continue;
9284
9285 if (!rn->info)
9286 continue;
9287
9288 ts->counts[BGP_STATS_PREFIXES]++;
9289 ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
ff7924f6 9290
a636c635
DW
9291#if 0
9292 ts->counts[BGP_STATS_AVGPLEN]
9293 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
9294 ts->counts[BGP_STATS_AVGPLEN],
9295 rn->p.prefixlen);
9296#endif
9297
9298 /* check if the prefix is included by any other announcements */
9299 while (prn && !prn->info)
9300 prn = bgp_node_parent_nolock (prn);
9301
9302 if (prn == NULL || prn == top)
9303 {
9304 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
9305 /* announced address space */
9306 if (space)
9307 ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen);
9308 }
9309 else if (prn->info)
9310 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
9311
ff7924f6
PJ
9312 for (ri = rn->info; ri; ri = ri->next)
9313 {
a636c635
DW
9314 rinum++;
9315 ts->counts[BGP_STATS_RIB]++;
ff7924f6 9316
a636c635
DW
9317 if (ri->attr &&
9318 (CHECK_FLAG (ri->attr->flag,
9319 ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))))
9320 ts->counts[BGP_STATS_AGGREGATES]++;
ff7924f6 9321
a636c635
DW
9322 /* as-path stats */
9323 if (ri->attr && ri->attr->aspath)
ff7924f6 9324 {
a636c635
DW
9325 unsigned int hops = aspath_count_hops (ri->attr->aspath);
9326 unsigned int size = aspath_size (ri->attr->aspath);
9327 as_t highest = aspath_highest (ri->attr->aspath);
9328
9329 ts->counts[BGP_STATS_ASPATH_COUNT]++;
9330
9331 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
9332 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
9333
9334 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
9335 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
9336
9337 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
9338 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9339#if 0
9340 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
9341 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9342 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
9343 hops);
9344 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
9345 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
9346 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
9347 size);
9348#endif
9349 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
9350 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
ff7924f6
PJ
9351 }
9352 }
9353 }
2815e61f
PJ
9354 return 0;
9355}
ff7924f6 9356
2815e61f 9357static int
a636c635 9358bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
2815e61f 9359{
a636c635 9360 struct bgp_table_stats ts;
2815e61f
PJ
9361 unsigned int i;
9362
a636c635 9363 if (!bgp->rib[afi][safi])
2815e61f 9364 {
96ade3ed
QY
9365 vty_outln (vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)",
9366 afi, safi);
2815e61f
PJ
9367 return CMD_WARNING;
9368 }
9369
a636c635
DW
9370 memset (&ts, 0, sizeof (ts));
9371 ts.table = bgp->rib[afi][safi];
9372 thread_execute (bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 9373
96ade3ed 9374 vty_outln (vty, "BGP %s RIB statistics%s",
1318e7c8 9375 afi_safi_print (afi, safi), VTYNL);
a636c635
DW
9376
9377 for (i = 0; i < BGP_STATS_MAX; i++)
ff7924f6 9378 {
a636c635
DW
9379 if (!table_stats_strs[i])
9380 continue;
9381
9382 switch (i)
856ca177 9383 {
a636c635
DW
9384#if 0
9385 case BGP_STATS_ASPATH_AVGHOPS:
9386 case BGP_STATS_ASPATH_AVGSIZE:
9387 case BGP_STATS_AVGPLEN:
9388 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9389 vty_out (vty, "%12.2f",
9390 (float)ts.counts[i] / (float)TALLY_SIGFIG);
9391 break;
9392#endif
9393 case BGP_STATS_ASPATH_TOTHOPS:
9394 case BGP_STATS_ASPATH_TOTSIZE:
9395 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9396 vty_out (vty, "%12.2f",
9397 ts.counts[i] ?
9398 (float)ts.counts[i] /
9399 (float)ts.counts[BGP_STATS_ASPATH_COUNT]
9400 : 0);
9401 break;
9402 case BGP_STATS_TOTPLEN:
9403 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9404 vty_out (vty, "%12.2f",
9405 ts.counts[i] ?
9406 (float)ts.counts[i] /
9407 (float)ts.counts[BGP_STATS_PREFIXES]
9408 : 0);
9409 break;
9410 case BGP_STATS_SPACE:
9411 vty_out (vty, "%-30s: ", table_stats_strs[i]);
96ade3ed 9412 vty_outln (vty, "%12llu", ts.counts[i]);
a636c635
DW
9413 if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
9414 break;
9415 vty_out (vty, "%30s: ", "%% announced ");
96ade3ed
QY
9416 vty_outln (vty, "%12.2f",
9417 100 * (float)ts.counts[BGP_STATS_SPACE] / (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]));
a636c635 9418 vty_out (vty, "%30s: ", "/8 equivalent ");
96ade3ed
QY
9419 vty_outln (vty, "%12.2f",
9420 (float)ts.counts[BGP_STATS_SPACE] / (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)));
a636c635
DW
9421 if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
9422 break;
9423 vty_out (vty, "%30s: ", "/24 equivalent ");
9424 vty_out (vty, "%12.2f",
9425 (float)ts.counts[BGP_STATS_SPACE] /
9426 (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24)));
9427 break;
9428 default:
9429 vty_out (vty, "%-30s: ", table_stats_strs[i]);
9430 vty_out (vty, "%12llu", ts.counts[i]);
856ca177 9431 }
a636c635 9432
e31b6333 9433 vty_out (vty, VTYNL);
ff7924f6 9434 }
ff7924f6
PJ
9435 return CMD_SUCCESS;
9436}
9437
a636c635
DW
9438enum bgp_pcounts
9439{
9440 PCOUNT_ADJ_IN = 0,
9441 PCOUNT_DAMPED,
9442 PCOUNT_REMOVED,
9443 PCOUNT_HISTORY,
9444 PCOUNT_STALE,
9445 PCOUNT_VALID,
9446 PCOUNT_ALL,
9447 PCOUNT_COUNTED,
9448 PCOUNT_PFCNT, /* the figure we display to users */
9449 PCOUNT_MAX,
9450};
718e3744 9451
a636c635
DW
9452static const char *pcount_strs[] =
9453{
9454 [PCOUNT_ADJ_IN] = "Adj-in",
9455 [PCOUNT_DAMPED] = "Damped",
9456 [PCOUNT_REMOVED] = "Removed",
9457 [PCOUNT_HISTORY] = "History",
9458 [PCOUNT_STALE] = "Stale",
9459 [PCOUNT_VALID] = "Valid",
9460 [PCOUNT_ALL] = "All RIB",
9461 [PCOUNT_COUNTED] = "PfxCt counted",
9462 [PCOUNT_PFCNT] = "Useable",
9463 [PCOUNT_MAX] = NULL,
9464};
718e3744 9465
a636c635
DW
9466struct peer_pcounts
9467{
9468 unsigned int count[PCOUNT_MAX];
9469 const struct peer *peer;
9470 const struct bgp_table *table;
9471};
47fc97cc 9472
a636c635
DW
9473static int
9474bgp_peer_count_walker (struct thread *t)
9475{
9476 struct bgp_node *rn;
9477 struct peer_pcounts *pc = THREAD_ARG (t);
9478 const struct peer *peer = pc->peer;
9479
9480 for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn))
718e3744 9481 {
a636c635
DW
9482 struct bgp_adj_in *ain;
9483 struct bgp_info *ri;
9484
9485 for (ain = rn->adj_in; ain; ain = ain->next)
9486 if (ain->peer == peer)
9487 pc->count[PCOUNT_ADJ_IN]++;
718e3744 9488
a636c635 9489 for (ri = rn->info; ri; ri = ri->next)
856ca177 9490 {
a636c635
DW
9491 char buf[SU_ADDRSTRLEN];
9492
9493 if (ri->peer != peer)
9494 continue;
9495
9496 pc->count[PCOUNT_ALL]++;
9497
9498 if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
9499 pc->count[PCOUNT_DAMPED]++;
9500 if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
9501 pc->count[PCOUNT_HISTORY]++;
9502 if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED))
9503 pc->count[PCOUNT_REMOVED]++;
9504 if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
9505 pc->count[PCOUNT_STALE]++;
9506 if (CHECK_FLAG (ri->flags, BGP_INFO_VALID))
9507 pc->count[PCOUNT_VALID]++;
9508 if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
9509 pc->count[PCOUNT_PFCNT]++;
9510
9511 if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
856ca177 9512 {
a636c635
DW
9513 pc->count[PCOUNT_COUNTED]++;
9514 if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
9515 zlog_warn ("%s [pcount] %s/%d is counted but flags 0x%x",
9516 peer->host,
9517 inet_ntop(rn->p.family, &rn->p.u.prefix,
9518 buf, SU_ADDRSTRLEN),
9519 rn->p.prefixlen,
9520 ri->flags);
9521 }
9522 else
9523 {
9524 if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
9525 zlog_warn ("%s [pcount] %s/%d not counted but flags 0x%x",
9526 peer->host,
9527 inet_ntop(rn->p.family, &rn->p.u.prefix,
9528 buf, SU_ADDRSTRLEN),
9529 rn->p.prefixlen,
9530 ri->flags);
856ca177
MS
9531 }
9532 }
856ca177 9533 }
a636c635 9534 return 0;
718e3744 9535}
9536
94f2b392 9537static int
a636c635 9538bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, u_char use_json)
856ca177 9539{
a636c635
DW
9540 struct peer_pcounts pcounts = { .peer = peer };
9541 unsigned int i;
856ca177 9542 json_object *json = NULL;
a636c635 9543 json_object *json_loop = NULL;
856ca177
MS
9544
9545 if (use_json)
718e3744 9546 {
a636c635
DW
9547 json = json_object_new_object();
9548 json_loop = json_object_new_object();
718e3744 9549 }
a636c635
DW
9550
9551 if (!peer || !peer->bgp || !peer->afc[afi][safi]
9552 || !peer->bgp->rib[afi][safi])
718e3744 9553 {
856ca177
MS
9554 if (use_json)
9555 {
a636c635 9556 json_object_string_add(json, "warning", "No such neighbor or address family");
96ade3ed 9557 vty_outln (vty, "%s", json_object_to_json_string(json));
856ca177
MS
9558 json_object_free(json);
9559 }
9560 else
96ade3ed 9561 vty_outln (vty, "%% No such neighbor or address family");
856ca177 9562
718e3744 9563 return CMD_WARNING;
9564 }
a636c635
DW
9565
9566 memset (&pcounts, 0, sizeof(pcounts));
9567 pcounts.peer = peer;
9568 pcounts.table = peer->bgp->rib[afi][safi];
9569
9570 /* in-place call via thread subsystem so as to record execution time
9571 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9572 * * on just vty_read()).
9573 * */
9574 thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0);
718e3744 9575
a636c635
DW
9576 if (use_json)
9577 {
9578 json_object_string_add(json, "prefixCountsFor", peer->host);
9579 json_object_string_add(json, "multiProtocol", afi_safi_print (afi, safi));
9580 json_object_int_add(json, "pfxCounter", peer->pcount[afi][safi]);
718e3744 9581
a636c635
DW
9582 for (i = 0; i < PCOUNT_MAX; i++)
9583 json_object_int_add(json_loop, pcount_strs[i], pcounts.count[i]);
718e3744 9584
a636c635 9585 json_object_object_add(json, "ribTableWalkCounters", json_loop);
856ca177 9586
a636c635
DW
9587 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
9588 {
9589 json_object_string_add(json, "pfxctDriftFor", peer->host);
9590 json_object_string_add(json, "recommended", "Please report this bug, with the above command output");
9591 }
96ade3ed 9592 vty_outln (vty, "%s", json_object_to_json_string(json));
a636c635
DW
9593 json_object_free(json);
9594 }
2a71e9ce 9595 else
a636c635 9596 {
2a71e9ce 9597
a636c635
DW
9598 if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
9599 {
96ade3ed
QY
9600 vty_outln (vty, "Prefix counts for %s/%s, %s",
9601 peer->hostname, peer->host,afi_safi_print(afi, safi));
a636c635
DW
9602 }
9603 else
9604 {
96ade3ed
QY
9605 vty_outln (vty, "Prefix counts for %s, %s",
9606 peer->host, afi_safi_print(afi, safi));
a636c635
DW
9607 }
9608
96ade3ed
QY
9609 vty_outln (vty, "PfxCt: %ld", peer->pcount[afi][safi]);
9610 vty_outln (vty, "%sCounts from RIB table walk:%s",
1318e7c8 9611 VTYNL, VTYNL);
a636c635
DW
9612
9613 for (i = 0; i < PCOUNT_MAX; i++)
96ade3ed 9614 vty_outln (vty, "%20s: %-10d", pcount_strs[i], pcounts.count[i]);
0b16f239 9615
a636c635
DW
9616 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
9617 {
96ade3ed
QY
9618 vty_outln (vty, "%s [pcount] PfxCt drift!",
9619 peer->host);
9620 vty_outln (vty,
9621 "Please report this bug, with the above command output");
a636c635
DW
9622 }
9623 }
9624
9625 return CMD_SUCCESS;
718e3744 9626}
9627
a636c635
DW
9628DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
9629 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
c1a44e43 9630 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 9631 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
718e3744 9632 SHOW_STR
9633 IP_STR
9634 BGP_STR
8386ac43 9635 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
9636 BGP_AFI_HELP_STR
9637 BGP_SAFI_HELP_STR
0b16f239
DS
9638 "Detailed information on TCP and BGP neighbor connections\n"
9639 "Neighbor to display information about\n"
9640 "Neighbor to display information about\n"
91d37724 9641 "Neighbor on BGP configured interface\n"
a636c635 9642 "Display detailed prefix count information\n"
9973d184 9643 JSON_STR)
0b16f239 9644{
30a6a167
DS
9645 afi_t afi = AFI_IP6;
9646 safi_t safi = SAFI_UNICAST;
0b16f239 9647 struct peer *peer;
30a6a167
DS
9648 int idx = 0;
9649 struct bgp *bgp = NULL;
856ca177 9650
f212a857 9651 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
30a6a167 9652 if (!idx)
0b16f239
DS
9653 return CMD_WARNING;
9654
30a6a167
DS
9655 int uj = use_json (argc, argv);
9656 if (uj) argc--;
0b16f239 9657
30a6a167
DS
9658 argv_find (argv, argc, "neighbors", &idx);
9659 peer = peer_lookup_in_view (vty, bgp, argv[idx+1]->arg, uj);
bb46e94f 9660 if (! peer)
9661 return CMD_WARNING;
9662
a636c635
DW
9663 return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj);
9664}
0b16f239 9665
d6902373
PG
9666#ifdef KEEP_OLD_VPN_COMMANDS
9667DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
9668 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
9669 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
9670 SHOW_STR
9671 IP_STR
9672 BGP_STR
d6902373 9673 BGP_VPNVX_HELP_STR
91d37724 9674 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
9675 "Detailed information on TCP and BGP neighbor connections\n"
9676 "Neighbor to display information about\n"
9677 "Neighbor to display information about\n"
91d37724 9678 "Neighbor on BGP configured interface\n"
a636c635 9679 "Display detailed prefix count information\n"
9973d184 9680 JSON_STR)
a636c635
DW
9681{
9682 int idx_peer = 6;
9683 struct peer *peer;
9684 u_char uj = use_json(argc, argv);
9685
9686 peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj);
9687 if (! peer)
9688 return CMD_WARNING;
9689
9690 return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
9691}
9692
d6902373
PG
9693DEFUN (show_ip_bgp_vpn_all_route_prefix,
9694 show_ip_bgp_vpn_all_route_prefix_cmd,
9695 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
9696 SHOW_STR
9697 IP_STR
9698 BGP_STR
d6902373 9699 BGP_VPNVX_HELP_STR
91d37724
QY
9700 "Display information about all VPNv4 NLRIs\n"
9701 "Network in the BGP routing table to display\n"
3a2d747c 9702 "Network in the BGP routing table to display\n"
9973d184 9703 JSON_STR)
91d37724
QY
9704{
9705 int idx = 0;
c49921c3 9706 char *network = NULL;
0e37c258
DS
9707 struct bgp *bgp = bgp_get_default();
9708 if (!bgp)
9709 {
96ade3ed 9710 vty_outln (vty, "Can't find default instance");
0e37c258
DS
9711 return CMD_WARNING;
9712 }
87e34b58
DS
9713
9714 if (argv_find (argv, argc, "A.B.C.D", &idx))
9715 network = argv[idx]->arg;
9716 else if (argv_find (argv, argc, "A.B.C.D/M", &idx))
9717 network = argv[idx]->arg;
9718 else
9719 {
96ade3ed 9720 vty_outln (vty, "Unable to figure out Network");
87e34b58
DS
9721 return CMD_WARNING;
9722 }
9723
0e37c258 9724 return bgp_show_route (vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv));
91d37724 9725}
d6902373 9726#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 9727
4c63a661
PG
9728DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
9729 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
9730 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9731 SHOW_STR
9732 IP_STR
9733 BGP_STR
9734 L2VPN_HELP_STR
9735 EVPN_HELP_STR
9736 "Display information about all EVPN NLRIs\n"
9737 "Network in the BGP routing table to display\n"
9738 "Network in the BGP routing table to display\n"
9739 JSON_STR)
9740{
9741 int idx = 0;
9742 char *network = NULL;
87e34b58
DS
9743
9744 if (argv_find (argv, argc, "A.B.C.D", &idx))
9745 network = argv[idx]->arg;
9746 else if (argv_find (argv, argc, "A.B.C.D/M", &idx))
9747 network = argv[idx]->arg;
9748 else
9749 {
96ade3ed 9750 vty_outln (vty, "Unable to figure out Network");
87e34b58
DS
9751 return CMD_WARNING;
9752 }
4c63a661
PG
9753 return bgp_show_route (vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv));
9754}
9755
9756 static void
a636c635
DW
9757show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
9758 int in, const char *rmap_name, u_char use_json, json_object *json)
9759{
9760 struct bgp_table *table;
9761 struct bgp_adj_in *ain;
9762 struct bgp_adj_out *adj;
9763 unsigned long output_count;
9764 unsigned long filtered_count;
9765 struct bgp_node *rn;
9766 int header1 = 1;
9767 struct bgp *bgp;
9768 int header2 = 1;
9769 struct attr attr;
a636c635
DW
9770 int ret;
9771 struct update_subgroup *subgrp;
9772 json_object *json_scode = NULL;
9773 json_object *json_ocode = NULL;
9774 json_object *json_ar = NULL;
9775 struct peer_af *paf;
9776
9777 if (use_json)
9778 {
9779 json_scode = json_object_new_object();
9780 json_ocode = json_object_new_object();
9781 json_ar = json_object_new_object();
9782
9783 json_object_string_add(json_scode, "suppressed", "s");
9784 json_object_string_add(json_scode, "damped", "d");
9785 json_object_string_add(json_scode, "history", "h");
9786 json_object_string_add(json_scode, "valid", "*");
9787 json_object_string_add(json_scode, "best", ">");
9788 json_object_string_add(json_scode, "multipath", "=");
9789 json_object_string_add(json_scode, "internal", "i");
9790 json_object_string_add(json_scode, "ribFailure", "r");
9791 json_object_string_add(json_scode, "stale", "S");
9792 json_object_string_add(json_scode, "removed", "R");
9793
9794 json_object_string_add(json_ocode, "igp", "i");
9795 json_object_string_add(json_ocode, "egp", "e");
9796 json_object_string_add(json_ocode, "incomplete", "?");
9797 }
9798
9799 bgp = peer->bgp;
9800
9801 if (! bgp)
9802 {
9803 if (use_json)
9804 {
9805 json_object_string_add(json, "alert", "no BGP");
96ade3ed 9806 vty_outln (vty, "%s", json_object_to_json_string(json));
a636c635
DW
9807 json_object_free(json);
9808 }
9809 else
96ade3ed 9810 vty_outln (vty, "%% No bgp");
a636c635
DW
9811 return;
9812 }
9813
9814 table = bgp->rib[afi][safi];
9815
9816 output_count = filtered_count = 0;
9817 subgrp = peer_subgroup(peer, afi, safi);
9818
9819 if (!in && subgrp && CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
9820 {
9821 if (use_json)
9822 {
9823 json_object_int_add(json, "bgpTableVersion", table->version);
9824 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
9825 json_object_object_add(json, "bgpStatusCodes", json_scode);
9826 json_object_object_add(json, "bgpOriginCodes", json_ocode);
9827 json_object_string_add(json, "bgpOriginatingDefaultNetwork", "0.0.0.0");
9828 }
9829 else
9830 {
96ade3ed
QY
9831 vty_outln (vty, "BGP table version is %" PRIu64 ", local router ID is %s", table->version,
9832 inet_ntoa(bgp->router_id));
1318e7c8
QY
9833 vty_outln (vty, BGP_SHOW_SCODE_HEADER, VTYNL);
9834 vty_outln (vty, BGP_SHOW_OCODE_HEADER, VTYNL);
a636c635 9835
96ade3ed 9836 vty_outln (vty, "Originating default network 0.0.0.0%s",
1318e7c8 9837 VTYNL);
a636c635
DW
9838 }
9839 header1 = 0;
9840 }
9841
a636c635
DW
9842 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
9843 {
9844 if (in)
9845 {
9846 for (ain = rn->adj_in; ain; ain = ain->next)
9847 {
9848 if (ain->peer == peer)
9849 {
9850 if (header1)
9851 {
9852 if (use_json)
9853 {
9854 json_object_int_add(json, "bgpTableVersion", 0);
9855 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
9856 json_object_object_add(json, "bgpStatusCodes", json_scode);
9857 json_object_object_add(json, "bgpOriginCodes", json_ocode);
9858 }
9859 else
9860 {
96ade3ed
QY
9861 vty_outln (vty, "BGP table version is 0, local router ID is %s",
9862 inet_ntoa(bgp->router_id));
1318e7c8
QY
9863 vty_outln (vty, BGP_SHOW_SCODE_HEADER, VTYNL);
9864 vty_outln (vty, BGP_SHOW_OCODE_HEADER, VTYNL);
a636c635
DW
9865 }
9866 header1 = 0;
9867 }
9868 if (header2)
9869 {
9870 if (!use_json)
96ade3ed 9871 vty_outln (vty, BGP_SHOW_HEADER);
a636c635
DW
9872 header2 = 0;
9873 }
9874 if (ain->attr)
9875 {
9876 bgp_attr_dup(&attr, ain->attr);
9877 if (bgp_input_modifier(peer, &rn->p, &attr, afi, safi, rmap_name) != RMAP_DENY)
9878 {
9879 route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar);
9880 output_count++;
9881 }
9882 else
9883 filtered_count++;
9884 }
9885 }
9886 }
9887 }
9888 else
9889 {
9890 for (adj = rn->adj_out; adj; adj = adj->next)
9891 SUBGRP_FOREACH_PEER(adj->subgroup, paf)
9892 if (paf->peer == peer)
9893 {
9894 if (header1)
9895 {
9896 if (use_json)
9897 {
9898 json_object_int_add(json, "bgpTableVersion", table->version);
9899 json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
9900 json_object_object_add(json, "bgpStatusCodes", json_scode);
9901 json_object_object_add(json, "bgpOriginCodes", json_ocode);
9902 }
9903 else
9904 {
96ade3ed
QY
9905 vty_outln (vty, "BGP table version is %" PRIu64 ", local router ID is %s", table->version,
9906 inet_ntoa(bgp->router_id));
1318e7c8
QY
9907 vty_outln (vty, BGP_SHOW_SCODE_HEADER, VTYNL);
9908 vty_outln (vty, BGP_SHOW_OCODE_HEADER, VTYNL);
a636c635
DW
9909 }
9910 header1 = 0;
9911 }
9912
9913 if (header2)
9914 {
9915 if (!use_json)
96ade3ed 9916 vty_outln (vty, BGP_SHOW_HEADER);
a636c635
DW
9917 header2 = 0;
9918 }
9919
9920 if (adj->attr)
9921 {
9922 bgp_attr_dup(&attr, adj->attr);
9923 ret = bgp_output_modifier(peer, &rn->p, &attr, afi, safi, rmap_name);
9924 if (ret != RMAP_DENY)
9925 {
9926 route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar);
9927 output_count++;
9928 }
9929 else
9930 filtered_count++;
9931 }
9932 }
9933 }
9934 }
9935 if (use_json)
9936 json_object_object_add(json, "advertisedRoutes", json_ar);
9937
9938 if (output_count != 0)
9939 {
9940 if (use_json)
9941 json_object_int_add(json, "totalPrefixCounter", output_count);
9942 else
96ade3ed 9943 vty_outln (vty, "%sTotal number of prefixes %ld",
1318e7c8 9944 VTYNL, output_count);
a636c635
DW
9945 }
9946 if (use_json)
9947 {
96ade3ed 9948 vty_outln (vty, "%s", json_object_to_json_string(json));
a636c635
DW
9949 json_object_free(json);
9950 }
9951
9952}
2a71e9ce 9953
a636c635
DW
9954static int
9955peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
9956 int in, const char *rmap_name, u_char use_json)
0b16f239 9957{
a636c635 9958 json_object *json = NULL;
0b16f239 9959
a636c635
DW
9960 if (use_json)
9961 json = json_object_new_object();
0b16f239 9962
a636c635
DW
9963 if (!peer || !peer->afc[afi][safi])
9964 {
9965 if (use_json)
9966 {
9967 json_object_string_add(json, "warning", "No such neighbor or address family");
96ade3ed 9968 vty_outln (vty, "%s", json_object_to_json_string(json));
a636c635
DW
9969 json_object_free(json);
9970 }
9971 else
96ade3ed 9972 vty_outln (vty, "%% No such neighbor or address family");
a636c635
DW
9973
9974 return CMD_WARNING;
9975 }
0b16f239 9976
a636c635
DW
9977 if (in && !CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
9978 {
9979 if (use_json)
9980 {
9981 json_object_string_add(json, "warning", "Inbound soft reconfiguration not enabled");
96ade3ed 9982 vty_outln (vty, "%s", json_object_to_json_string(json));
a636c635
DW
9983 json_object_free(json);
9984 }
9985 else
96ade3ed 9986 vty_outln (vty, "%% Inbound soft reconfiguration not enabled");
0b16f239 9987
a636c635
DW
9988 return CMD_WARNING;
9989 }
0b16f239 9990
a636c635 9991 show_adj_route (vty, peer, afi, safi, in, rmap_name, use_json, json);
0b16f239 9992
a636c635
DW
9993 return CMD_SUCCESS;
9994}
50ef26d4 9995
a636c635
DW
9996DEFUN (show_ip_bgp_instance_neighbor_advertised_route,
9997 show_ip_bgp_instance_neighbor_advertised_route_cmd,
18c57037 9998 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
1edcd642 9999 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
718e3744 10000 SHOW_STR
10001 IP_STR
10002 BGP_STR
a636c635 10003 BGP_INSTANCE_HELP_STR
7395a2c9
DS
10004 BGP_AFI_HELP_STR
10005 BGP_SAFI_HELP_STR
718e3744 10006 "Detailed information on TCP and BGP neighbor connections\n"
10007 "Neighbor to display information about\n"
10008 "Neighbor to display information about\n"
91d37724 10009 "Neighbor on BGP configured interface\n"
856ca177 10010 "Display the received routes from neighbor\n"
a636c635
DW
10011 "Display the routes advertised to a BGP neighbor\n"
10012 "Route-map to modify the attributes\n"
10013 "Name of the route map\n"
9973d184 10014 JSON_STR)
718e3744 10015{
8c3deaae
QY
10016 afi_t afi = AFI_IP6;
10017 safi_t safi = SAFI_UNICAST;
a636c635 10018 char *rmap_name = NULL;
8c3deaae 10019 char *peerstr = NULL;
c01d03a6 10020 int rcvd = 0;
30a6a167 10021 struct bgp *bgp = NULL;
bb46e94f 10022 struct peer *peer;
10023
8c3deaae 10024 int idx = 0;
718e3744 10025
f212a857 10026 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
30a6a167 10027 if (!idx)
c493f2d8
DS
10028 return CMD_WARNING;
10029
30a6a167
DS
10030 int uj = use_json (argc, argv);
10031 if (uj) argc--;
10032
8c3deaae
QY
10033 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10034 argv_find (argv, argc, "neighbors", &idx);
10035 peerstr = argv[++idx]->arg;
10036
30a6a167 10037 peer = peer_lookup_in_view (vty, bgp, peerstr, uj);
a636c635 10038 if (! peer)
30a6a167 10039 return CMD_WARNING;
856ca177 10040
8c3deaae
QY
10041 if (argv_find (argv, argc, "received-routes", &idx))
10042 rcvd = 1;
10043 if (argv_find (argv, argc, "advertised-routes", &idx))
10044 rcvd = 0;
10045 if (argv_find (argv, argc, "route-map", &idx))
10046 rmap_name = argv[++idx]->arg;
95cbbd2a 10047
a636c635 10048 return peer_adj_routes (vty, peer, afi, safi, rcvd, rmap_name, uj);
95cbbd2a
ML
10049}
10050
718e3744 10051DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
10052 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 10053 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 10054 SHOW_STR
10055 IP_STR
10056 BGP_STR
8c3deaae
QY
10057 "Address Family\n"
10058 "Address Family\n"
718e3744 10059 "Address Family modifier\n"
10060 "Detailed information on TCP and BGP neighbor connections\n"
10061 "Neighbor to display information about\n"
10062 "Neighbor to display information about\n"
91d37724 10063 "Neighbor on BGP configured interface\n"
718e3744 10064 "Display information received from a BGP neighbor\n"
856ca177 10065 "Display the prefixlist filter\n"
9973d184 10066 JSON_STR)
718e3744 10067{
8c3deaae
QY
10068 afi_t afi = AFI_IP6;
10069 safi_t safi = SAFI_UNICAST;
10070 char *peerstr = NULL;
10071
718e3744 10072 char name[BUFSIZ];
c63b83fe 10073 union sockunion su;
718e3744 10074 struct peer *peer;
c63b83fe 10075 int count, ret;
718e3744 10076
8c3deaae 10077 int idx = 0;
718e3744 10078
8c3deaae
QY
10079 /* show [ip] bgp */
10080 if (argv_find (argv, argc, "ip", &idx))
10081 afi = AFI_IP;
10082 /* [<ipv4|ipv6> [unicast]] */
10083 if (argv_find (argv, argc, "ipv4", &idx))
10084 afi = AFI_IP;
10085 if (argv_find (argv, argc, "ipv6", &idx))
10086 afi = AFI_IP6;
10087 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10088 argv_find (argv, argc, "neighbors", &idx);
10089 peerstr = argv[++idx]->arg;
10090
10091 u_char uj = use_json(argc, argv);
10092
10093 ret = str2sockunion (peerstr, &su);
c63b83fe
JBD
10094 if (ret < 0)
10095 {
8c3deaae 10096 peer = peer_lookup_by_conf_if (NULL, peerstr);
856ca177 10097 if (! peer)
a80beece 10098 {
db7c8528 10099 if (uj)
96ade3ed 10100 vty_outln (vty, "{}");
856ca177 10101 else
96ade3ed 10102 vty_outln (vty, "%% Malformed address or name: %s", peerstr);
a80beece
DS
10103 return CMD_WARNING;
10104 }
10105 }
10106 else
10107 {
10108 peer = peer_lookup (NULL, &su);
10109 if (! peer)
856ca177 10110 {
db7c8528 10111 if (uj)
96ade3ed 10112 vty_outln (vty, "{}");
856ca177 10113 else
96ade3ed 10114 vty_outln (vty, "No peer");
856ca177
MS
10115 return CMD_WARNING;
10116 }
c63b83fe 10117 }
718e3744 10118
39573b33
DW
10119 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
10120 count = prefix_bgp_show_prefix_list (NULL, afi, name, uj);
718e3744 10121 if (count)
10122 {
db7c8528 10123 if (!uj)
96ade3ed 10124 vty_outln (vty, "Address Family: %s", afi_safi_print(afi, safi));
39573b33 10125 prefix_bgp_show_prefix_list (vty, afi, name, uj);
856ca177
MS
10126 }
10127 else
10128 {
db7c8528 10129 if (uj)
96ade3ed 10130 vty_outln (vty, "{}");
856ca177 10131 else
96ade3ed 10132 vty_outln (vty, "No functional output");
718e3744 10133 }
10134
10135 return CMD_SUCCESS;
10136}
10137
94f2b392 10138static int
bb46e94f 10139bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi,
856ca177 10140 safi_t safi, enum bgp_show_type type, u_char use_json)
718e3744 10141{
718e3744 10142 if (! peer || ! peer->afc[afi][safi])
10143 {
856ca177
MS
10144 if (use_json)
10145 {
10146 json_object *json_no = NULL;
10147 json_no = json_object_new_object();
10148 json_object_string_add(json_no, "warning", "No such neighbor or address family");
96ade3ed 10149 vty_outln (vty, "%s", json_object_to_json_string(json_no));
856ca177
MS
10150 json_object_free(json_no);
10151 }
10152 else
96ade3ed 10153 vty_outln (vty, "%% No such neighbor or address family");
718e3744 10154 return CMD_WARNING;
10155 }
47fc97cc 10156
856ca177 10157 return bgp_show (vty, peer->bgp, afi, safi, type, &peer->su, use_json);
718e3744 10158}
10159
10160DEFUN (show_ip_bgp_neighbor_routes,
10161 show_ip_bgp_neighbor_routes_cmd,
18c57037 10162 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
30a6a167 10163 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
50ef26d4 10164 SHOW_STR
10165 IP_STR
10166 BGP_STR
8386ac43 10167 BGP_INSTANCE_HELP_STR
4f280b15
LB
10168 BGP_AFI_HELP_STR
10169 BGP_SAFI_HELP_STR
718e3744 10170 "Detailed information on TCP and BGP neighbor connections\n"
10171 "Neighbor to display information about\n"
10172 "Neighbor to display information about\n"
91d37724 10173 "Neighbor on BGP configured interface\n"
2525cf39 10174 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
10175 "Display the dampened routes received from neighbor\n"
10176 "Display routes learned from neighbor\n"
9973d184 10177 JSON_STR)
718e3744 10178{
8c3deaae 10179 char *peerstr = NULL;
30a6a167 10180 struct bgp *bgp = NULL;
8c3deaae
QY
10181 afi_t afi = AFI_IP6;
10182 safi_t safi = SAFI_UNICAST;
bb46e94f 10183 struct peer *peer;
2525cf39 10184 enum bgp_show_type sh_type = bgp_show_type_neighbor;
856ca177 10185
8c3deaae 10186 int idx = 0;
bb46e94f 10187
f212a857 10188 bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp);
30a6a167 10189 if (!idx)
c493f2d8
DS
10190 return CMD_WARNING;
10191
30a6a167
DS
10192 int uj = use_json (argc, argv);
10193 if (uj) argc--;
10194
8c3deaae
QY
10195 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10196 argv_find (argv, argc, "neighbors", &idx);
10197 peerstr = argv[++idx]->arg;
10198
30a6a167 10199 peer = peer_lookup_in_view (vty, bgp, peerstr, uj);
bb46e94f 10200 if (! peer)
2525cf39 10201 {
96ade3ed 10202 vty_outln (vty, "No such neighbor");
2525cf39
DW
10203 return CMD_WARNING;
10204 }
bb46e94f 10205
8c3deaae 10206 if (argv_find (argv, argc, "flap-statistics", &idx))
2525cf39 10207 sh_type = bgp_show_type_flap_neighbor;
8c3deaae
QY
10208 else if (argv_find (argv, argc, "dampened-routes", &idx))
10209 sh_type = bgp_show_type_damp_neighbor;
10210 else if (argv_find (argv, argc, "routes", &idx))
10211 sh_type = bgp_show_type_neighbor;
2525cf39
DW
10212
10213 return bgp_show_neighbor_route (vty, peer, afi, safi, sh_type, uj);
50ef26d4 10214}
6b0655a2 10215
734b349e 10216struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 10217
10218struct bgp_distance
10219{
10220 /* Distance value for the IP source prefix. */
10221 u_char distance;
10222
10223 /* Name of the access-list to be matched. */
10224 char *access_list;
10225};
10226
4f280b15
LB
10227DEFUN (show_bgp_afi_vpn_rd_route,
10228 show_bgp_afi_vpn_rd_route_cmd,
10229 "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]",
10230 SHOW_STR
10231 BGP_STR
10232 BGP_AFI_HELP_STR
10233 "Address Family modifier\n"
10234 "Display information for a route distinguisher\n"
10235 "Route Distinguisher\n"
7395a2c9
DS
10236 "Network in the BGP routing table to display\n"
10237 "Network in the BGP routing table to display\n"
10238 JSON_STR)
4f280b15
LB
10239{
10240 int ret;
10241 struct prefix_rd prd;
10242 afi_t afi = AFI_MAX;
10243 int idx = 0;
10244
10245 argv_find_and_parse_afi (argv, argc, &idx, &afi);
10246 ret = str2prefix_rd (argv[5]->arg, &prd);
10247 if (! ret)
10248 {
96ade3ed 10249 vty_outln (vty, "%% Malformed Route Distinguisher");
4f280b15
LB
10250 return CMD_WARNING;
10251 }
10252 return bgp_show_route (vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL, use_json (argc, argv));
10253}
10254
94f2b392 10255static struct bgp_distance *
66e5cd87 10256bgp_distance_new (void)
718e3744 10257{
393deb9b 10258 return XCALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
718e3744 10259}
10260
94f2b392 10261static void
718e3744 10262bgp_distance_free (struct bgp_distance *bdistance)
10263{
10264 XFREE (MTYPE_BGP_DISTANCE, bdistance);
10265}
10266
94f2b392 10267static int
fd79ac91 10268bgp_distance_set (struct vty *vty, const char *distance_str,
10269 const char *ip_str, const char *access_list_str)
718e3744 10270{
10271 int ret;
734b349e
MZ
10272 afi_t afi;
10273 safi_t safi;
10274 struct prefix p;
718e3744 10275 u_char distance;
10276 struct bgp_node *rn;
10277 struct bgp_distance *bdistance;
10278
734b349e
MZ
10279 afi = bgp_node_afi (vty);
10280 safi = bgp_node_safi (vty);
10281
10282 ret = str2prefix (ip_str, &p);
718e3744 10283 if (ret == 0)
10284 {
96ade3ed 10285 vty_outln (vty, "Malformed prefix");
718e3744 10286 return CMD_WARNING;
10287 }
10288
10289 distance = atoi (distance_str);
10290
10291 /* Get BGP distance node. */
734b349e 10292 rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p);
718e3744 10293 if (rn->info)
10294 {
10295 bdistance = rn->info;
10296 bgp_unlock_node (rn);
10297 }
10298 else
10299 {
10300 bdistance = bgp_distance_new ();
10301 rn->info = bdistance;
10302 }
10303
10304 /* Set distance value. */
10305 bdistance->distance = distance;
10306
10307 /* Reset access-list configuration. */
10308 if (bdistance->access_list)
10309 {
6e919709 10310 XFREE(MTYPE_AS_LIST, bdistance->access_list);
718e3744 10311 bdistance->access_list = NULL;
10312 }
10313 if (access_list_str)
6e919709 10314 bdistance->access_list = XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 10315
10316 return CMD_SUCCESS;
10317}
10318
94f2b392 10319static int
fd79ac91 10320bgp_distance_unset (struct vty *vty, const char *distance_str,
10321 const char *ip_str, const char *access_list_str)
718e3744 10322{
10323 int ret;
734b349e
MZ
10324 afi_t afi;
10325 safi_t safi;
10326 struct prefix p;
1f9a9fff 10327 int distance;
718e3744 10328 struct bgp_node *rn;
10329 struct bgp_distance *bdistance;
10330
734b349e
MZ
10331 afi = bgp_node_afi (vty);
10332 safi = bgp_node_safi (vty);
10333
10334 ret = str2prefix (ip_str, &p);
718e3744 10335 if (ret == 0)
10336 {
96ade3ed 10337 vty_outln (vty, "Malformed prefix");
718e3744 10338 return CMD_WARNING;
10339 }
10340
734b349e 10341 rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p);
718e3744 10342 if (! rn)
10343 {
96ade3ed 10344 vty_outln (vty, "Can't find specified prefix");
718e3744 10345 return CMD_WARNING;
10346 }
10347
10348 bdistance = rn->info;
1f9a9fff
PJ
10349 distance = atoi(distance_str);
10350
10351 if (bdistance->distance != distance)
10352 {
96ade3ed 10353 vty_outln (vty, "Distance does not match configured");
1f9a9fff
PJ
10354 return CMD_WARNING;
10355 }
718e3744 10356
10357 if (bdistance->access_list)
6e919709 10358 XFREE(MTYPE_AS_LIST, bdistance->access_list);
718e3744 10359 bgp_distance_free (bdistance);
10360
10361 rn->info = NULL;
10362 bgp_unlock_node (rn);
10363 bgp_unlock_node (rn);
10364
10365 return CMD_SUCCESS;
10366}
10367
718e3744 10368/* Apply BGP information to distance method. */
10369u_char
734b349e
MZ
10370bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi,
10371 safi_t safi, struct bgp *bgp)
718e3744 10372{
10373 struct bgp_node *rn;
734b349e 10374 struct prefix q;
718e3744 10375 struct peer *peer;
10376 struct bgp_distance *bdistance;
10377 struct access_list *alist;
10378 struct bgp_static *bgp_static;
10379
10380 if (! bgp)
10381 return 0;
10382
718e3744 10383 peer = rinfo->peer;
10384
718e3744 10385 /* Check source address. */
734b349e
MZ
10386 sockunion2hostprefix (&peer->su, &q);
10387 rn = bgp_node_match (bgp_distance_table[afi][safi], &q);
718e3744 10388 if (rn)
10389 {
10390 bdistance = rn->info;
10391 bgp_unlock_node (rn);
10392
10393 if (bdistance->access_list)
10394 {
734b349e 10395 alist = access_list_lookup (afi, bdistance->access_list);
718e3744 10396 if (alist && access_list_apply (alist, p) == FILTER_PERMIT)
10397 return bdistance->distance;
10398 }
10399 else
10400 return bdistance->distance;
10401 }
10402
10403 /* Backdoor check. */
734b349e 10404 rn = bgp_node_lookup (bgp->route[afi][safi], p);
718e3744 10405 if (rn)
10406 {
10407 bgp_static = rn->info;
10408 bgp_unlock_node (rn);
10409
10410 if (bgp_static->backdoor)
10411 {
734b349e
MZ
10412 if (bgp->distance_local[afi][safi])
10413 return bgp->distance_local[afi][safi];
718e3744 10414 else
10415 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10416 }
10417 }
10418
6d85b15b 10419 if (peer->sort == BGP_PEER_EBGP)
718e3744 10420 {
734b349e
MZ
10421 if (bgp->distance_ebgp[afi][safi])
10422 return bgp->distance_ebgp[afi][safi];
718e3744 10423 return ZEBRA_EBGP_DISTANCE_DEFAULT;
10424 }
10425 else
10426 {
734b349e
MZ
10427 if (bgp->distance_ibgp[afi][safi])
10428 return bgp->distance_ibgp[afi][safi];
718e3744 10429 return ZEBRA_IBGP_DISTANCE_DEFAULT;
10430 }
10431}
10432
10433DEFUN (bgp_distance,
10434 bgp_distance_cmd,
6147e2c6 10435 "distance bgp (1-255) (1-255) (1-255)",
718e3744 10436 "Define an administrative distance\n"
10437 "BGP distance\n"
10438 "Distance for routes external to the AS\n"
10439 "Distance for routes internal to the AS\n"
10440 "Distance for local routes\n")
10441{
cdc2d765 10442 VTY_DECLVAR_CONTEXT(bgp, bgp);
c500ae40
DW
10443 int idx_number = 2;
10444 int idx_number_2 = 3;
10445 int idx_number_3 = 4;
734b349e
MZ
10446 afi_t afi;
10447 safi_t safi;
718e3744 10448
734b349e
MZ
10449 afi = bgp_node_afi (vty);
10450 safi = bgp_node_safi (vty);
718e3744 10451
39e92c06
QY
10452 bgp->distance_ebgp[afi][safi] = atoi (argv[idx_number]->arg);
10453 bgp->distance_ibgp[afi][safi] = atoi (argv[idx_number_2]->arg);
10454 bgp->distance_local[afi][safi] = atoi (argv[idx_number_3]->arg);
718e3744 10455 return CMD_SUCCESS;
10456}
10457
10458DEFUN (no_bgp_distance,
10459 no_bgp_distance_cmd,
a636c635 10460 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 10461 NO_STR
10462 "Define an administrative distance\n"
10463 "BGP distance\n"
10464 "Distance for routes external to the AS\n"
10465 "Distance for routes internal to the AS\n"
10466 "Distance for local routes\n")
10467{
cdc2d765 10468 VTY_DECLVAR_CONTEXT(bgp, bgp);
734b349e
MZ
10469 afi_t afi;
10470 safi_t safi;
718e3744 10471
734b349e
MZ
10472 afi = bgp_node_afi (vty);
10473 safi = bgp_node_safi (vty);
718e3744 10474
734b349e
MZ
10475 bgp->distance_ebgp[afi][safi] = 0;
10476 bgp->distance_ibgp[afi][safi] = 0;
10477 bgp->distance_local[afi][safi] = 0;
718e3744 10478 return CMD_SUCCESS;
10479}
10480
718e3744 10481
10482DEFUN (bgp_distance_source,
10483 bgp_distance_source_cmd,
6147e2c6 10484 "distance (1-255) A.B.C.D/M",
718e3744 10485 "Define an administrative distance\n"
10486 "Administrative distance\n"
10487 "IP source prefix\n")
10488{
c500ae40
DW
10489 int idx_number = 1;
10490 int idx_ipv4_prefixlen = 2;
10491 bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL);
718e3744 10492 return CMD_SUCCESS;
10493}
10494
10495DEFUN (no_bgp_distance_source,
10496 no_bgp_distance_source_cmd,
6147e2c6 10497 "no distance (1-255) A.B.C.D/M",
718e3744 10498 NO_STR
10499 "Define an administrative distance\n"
10500 "Administrative distance\n"
10501 "IP source prefix\n")
10502{
c500ae40
DW
10503 int idx_number = 2;
10504 int idx_ipv4_prefixlen = 3;
10505 bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL);
718e3744 10506 return CMD_SUCCESS;
10507}
10508
10509DEFUN (bgp_distance_source_access_list,
10510 bgp_distance_source_access_list_cmd,
6147e2c6 10511 "distance (1-255) A.B.C.D/M WORD",
718e3744 10512 "Define an administrative distance\n"
10513 "Administrative distance\n"
10514 "IP source prefix\n"
10515 "Access list name\n")
10516{
c500ae40
DW
10517 int idx_number = 1;
10518 int idx_ipv4_prefixlen = 2;
10519 int idx_word = 3;
10520 bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
718e3744 10521 return CMD_SUCCESS;
10522}
10523
10524DEFUN (no_bgp_distance_source_access_list,
10525 no_bgp_distance_source_access_list_cmd,
6147e2c6 10526 "no distance (1-255) A.B.C.D/M WORD",
718e3744 10527 NO_STR
10528 "Define an administrative distance\n"
10529 "Administrative distance\n"
10530 "IP source prefix\n"
10531 "Access list name\n")
10532{
c500ae40
DW
10533 int idx_number = 2;
10534 int idx_ipv4_prefixlen = 3;
10535 int idx_word = 4;
10536 bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
718e3744 10537 return CMD_SUCCESS;
10538}
6b0655a2 10539
734b349e
MZ
10540DEFUN (ipv6_bgp_distance_source,
10541 ipv6_bgp_distance_source_cmd,
39e92c06 10542 "distance (1-255) X:X::X:X/M",
734b349e
MZ
10543 "Define an administrative distance\n"
10544 "Administrative distance\n"
10545 "IP source prefix\n")
10546{
39e92c06 10547 bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, NULL);
734b349e
MZ
10548 return CMD_SUCCESS;
10549}
10550
10551DEFUN (no_ipv6_bgp_distance_source,
10552 no_ipv6_bgp_distance_source_cmd,
39e92c06 10553 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
10554 NO_STR
10555 "Define an administrative distance\n"
10556 "Administrative distance\n"
10557 "IP source prefix\n")
10558{
39e92c06 10559 bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, NULL);
734b349e
MZ
10560 return CMD_SUCCESS;
10561}
10562
10563DEFUN (ipv6_bgp_distance_source_access_list,
10564 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10565 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10566 "Define an administrative distance\n"
10567 "Administrative distance\n"
10568 "IP source prefix\n"
10569 "Access list name\n")
10570{
39e92c06 10571 bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
734b349e
MZ
10572 return CMD_SUCCESS;
10573}
10574
10575DEFUN (no_ipv6_bgp_distance_source_access_list,
10576 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 10577 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
10578 NO_STR
10579 "Define an administrative distance\n"
10580 "Administrative distance\n"
10581 "IP source prefix\n"
10582 "Access list name\n")
10583{
39e92c06 10584 bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
734b349e
MZ
10585 return CMD_SUCCESS;
10586}
10587
718e3744 10588DEFUN (bgp_damp_set,
10589 bgp_damp_set_cmd,
31500417 10590 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10591 "BGP Specific commands\n"
10592 "Enable route-flap dampening\n"
10593 "Half-life time for the penalty\n"
10594 "Value to start reusing a route\n"
10595 "Value to start suppressing a route\n"
10596 "Maximum duration to suppress a stable route\n")
10597{
cdc2d765 10598 VTY_DECLVAR_CONTEXT(bgp, bgp);
31500417
DW
10599 int idx_half_life = 2;
10600 int idx_reuse = 3;
10601 int idx_suppress = 4;
10602 int idx_max_suppress = 5;
718e3744 10603 int half = DEFAULT_HALF_LIFE * 60;
10604 int reuse = DEFAULT_REUSE;
10605 int suppress = DEFAULT_SUPPRESS;
10606 int max = 4 * half;
10607
31500417 10608 if (argc == 6)
718e3744 10609 {
31500417
DW
10610 half = atoi (argv[idx_half_life]->arg) * 60;
10611 reuse = atoi (argv[idx_reuse]->arg);
10612 suppress = atoi (argv[idx_suppress]->arg);
10613 max = atoi (argv[idx_max_suppress]->arg) * 60;
718e3744 10614 }
31500417 10615 else if (argc == 3)
718e3744 10616 {
31500417 10617 half = atoi (argv[idx_half_life]->arg) * 60;
718e3744 10618 max = 4 * half;
10619 }
10620
7ebe9748
B
10621 if (suppress < reuse)
10622 {
96ade3ed 10623 vty_outln (vty,"Suppress value cannot be less than reuse value ");
7ebe9748
B
10624 return 0;
10625 }
10626
718e3744 10627 return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty),
10628 half, reuse, suppress, max);
10629}
10630
718e3744 10631DEFUN (bgp_damp_unset,
10632 bgp_damp_unset_cmd,
d04c479d 10633 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 10634 NO_STR
10635 "BGP Specific commands\n"
16cedbb0
QY
10636 "Enable route-flap dampening\n"
10637 "Half-life time for the penalty\n"
10638 "Value to start reusing a route\n"
10639 "Value to start suppressing a route\n"
10640 "Maximum duration to suppress a stable route\n")
718e3744 10641{
cdc2d765 10642 VTY_DECLVAR_CONTEXT(bgp, bgp);
718e3744 10643 return bgp_damp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty));
10644}
10645
718e3744 10646/* Display specified route of BGP table. */
94f2b392 10647static int
fd79ac91 10648bgp_clear_damp_route (struct vty *vty, const char *view_name,
10649 const char *ip_str, afi_t afi, safi_t safi,
10650 struct prefix_rd *prd, int prefix_check)
718e3744 10651{
10652 int ret;
10653 struct prefix match;
10654 struct bgp_node *rn;
10655 struct bgp_node *rm;
10656 struct bgp_info *ri;
10657 struct bgp_info *ri_temp;
10658 struct bgp *bgp;
10659 struct bgp_table *table;
10660
10661 /* BGP structure lookup. */
10662 if (view_name)
10663 {
10664 bgp = bgp_lookup_by_name (view_name);
10665 if (bgp == NULL)
10666 {
96ade3ed 10667 vty_outln (vty, "%% Can't find BGP instance %s", view_name);
718e3744 10668 return CMD_WARNING;
10669 }
10670 }
10671 else
10672 {
10673 bgp = bgp_get_default ();
10674 if (bgp == NULL)
10675 {
96ade3ed 10676 vty_outln (vty, "%% No BGP process is configured");
718e3744 10677 return CMD_WARNING;
10678 }
10679 }
10680
10681 /* Check IP address argument. */
10682 ret = str2prefix (ip_str, &match);
10683 if (! ret)
10684 {
96ade3ed 10685 vty_outln (vty, "%% address is malformed");
718e3744 10686 return CMD_WARNING;
10687 }
10688
10689 match.family = afi2family (afi);
10690
3d6c0dfa 10691 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN))
718e3744 10692 {
587ff0fd 10693 for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn))
718e3744 10694 {
10695 if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
10696 continue;
10697
10698 if ((table = rn->info) != NULL)
10699 if ((rm = bgp_node_match (table, &match)) != NULL)
6c88b44d
CC
10700 {
10701 if (! prefix_check || rm->p.prefixlen == match.prefixlen)
10702 {
10703 ri = rm->info;
10704 while (ri)
10705 {
10706 if (ri->extra && ri->extra->damp_info)
10707 {
10708 ri_temp = ri->next;
10709 bgp_damp_info_free (ri->extra->damp_info, 1);
10710 ri = ri_temp;
10711 }
10712 else
10713 ri = ri->next;
10714 }
10715 }
10716
10717 bgp_unlock_node (rm);
10718 }
718e3744 10719 }
10720 }
10721 else
10722 {
10723 if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
6c88b44d
CC
10724 {
10725 if (! prefix_check || rn->p.prefixlen == match.prefixlen)
10726 {
10727 ri = rn->info;
10728 while (ri)
10729 {
10730 if (ri->extra && ri->extra->damp_info)
10731 {
10732 ri_temp = ri->next;
10733 bgp_damp_info_free (ri->extra->damp_info, 1);
10734 ri = ri_temp;
10735 }
10736 else
10737 ri = ri->next;
10738 }
10739 }
10740
10741 bgp_unlock_node (rn);
10742 }
718e3744 10743 }
10744
10745 return CMD_SUCCESS;
10746}
10747
10748DEFUN (clear_ip_bgp_dampening,
10749 clear_ip_bgp_dampening_cmd,
10750 "clear ip bgp dampening",
10751 CLEAR_STR
10752 IP_STR
10753 BGP_STR
10754 "Clear route flap dampening information\n")
10755{
10756 bgp_damp_info_clean ();
10757 return CMD_SUCCESS;
10758}
10759
10760DEFUN (clear_ip_bgp_dampening_prefix,
10761 clear_ip_bgp_dampening_prefix_cmd,
10762 "clear ip bgp dampening A.B.C.D/M",
10763 CLEAR_STR
10764 IP_STR
10765 BGP_STR
10766 "Clear route flap dampening information\n"
0c7b1b01 10767 "IPv4 prefix\n")
718e3744 10768{
c500ae40
DW
10769 int idx_ipv4_prefixlen = 4;
10770 return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
718e3744 10771 SAFI_UNICAST, NULL, 1);
10772}
10773
10774DEFUN (clear_ip_bgp_dampening_address,
10775 clear_ip_bgp_dampening_address_cmd,
10776 "clear ip bgp dampening A.B.C.D",
10777 CLEAR_STR
10778 IP_STR
10779 BGP_STR
10780 "Clear route flap dampening information\n"
10781 "Network to clear damping information\n")
10782{
c500ae40
DW
10783 int idx_ipv4 = 4;
10784 return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
718e3744 10785 SAFI_UNICAST, NULL, 0);
10786}
10787
10788DEFUN (clear_ip_bgp_dampening_address_mask,
10789 clear_ip_bgp_dampening_address_mask_cmd,
10790 "clear ip bgp dampening A.B.C.D A.B.C.D",
10791 CLEAR_STR
10792 IP_STR
10793 BGP_STR
10794 "Clear route flap dampening information\n"
10795 "Network to clear damping information\n"
10796 "Network mask\n")
10797{
c500ae40
DW
10798 int idx_ipv4 = 4;
10799 int idx_ipv4_2 = 5;
718e3744 10800 int ret;
10801 char prefix_str[BUFSIZ];
10802
c500ae40 10803 ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str);
718e3744 10804 if (! ret)
10805 {
96ade3ed 10806 vty_outln (vty, "%% Inconsistent address and mask");
718e3744 10807 return CMD_WARNING;
10808 }
10809
10810 return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP,
10811 SAFI_UNICAST, NULL, 0);
10812}
6b0655a2 10813
587ff0fd 10814/* also used for encap safi */
94f2b392 10815static int
c286be96 10816bgp_config_write_network_vpn (struct vty *vty, struct bgp *bgp,
718e3744 10817 afi_t afi, safi_t safi, int *write)
10818{
10819 struct bgp_node *prn;
10820 struct bgp_node *rn;
10821 struct bgp_table *table;
10822 struct prefix *p;
10823 struct prefix_rd *prd;
10824 struct bgp_static *bgp_static;
9bedbb1e 10825 mpls_label_t label;
718e3744 10826 char buf[SU_ADDRSTRLEN];
10827 char rdbuf[RD_ADDRSTRLEN];
10828
10829 /* Network configuration. */
10830 for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn))
10831 if ((table = prn->info) != NULL)
10832 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
10833 if ((bgp_static = rn->info) != NULL)
10834 {
10835 p = &rn->p;
10836 prd = (struct prefix_rd *) &prn->p;
10837
10838 /* "address-family" display. */
10839 bgp_config_write_family_header (vty, afi, safi, write);
10840
10841 /* "network" configuration display. */
10842 prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
9bedbb1e 10843 label = decode_label (&bgp_static->label);
718e3744 10844
ebb0c02a 10845 vty_out (vty, " network %s/%d rd %s",
718e3744 10846 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
ebb0c02a
RW
10847 p->prefixlen, rdbuf);
10848 if (safi == SAFI_MPLS_VPN)
10849 vty_out (vty, " label %u", label);
10850
60566995
LB
10851 if (bgp_static->rmap.name)
10852 vty_out (vty, " route-map %s", bgp_static->rmap.name);
10853 else
10854 {
10855 if (bgp_static->backdoor)
10856 vty_out (vty, " backdoor");
10857 }
e31b6333 10858 vty_out (vty, VTYNL);
718e3744 10859 }
10860 return 0;
10861}
10862
3da6fcd5
PG
10863static int
10864bgp_config_write_network_evpn (struct vty *vty, struct bgp *bgp,
10865 afi_t afi, safi_t safi, int *write)
10866{
10867 struct bgp_node *prn;
10868 struct bgp_node *rn;
10869 struct bgp_table *table;
10870 struct prefix *p;
10871 struct prefix_rd *prd;
10872 struct bgp_static *bgp_static;
10873 char buf[PREFIX_STRLEN];
10874 char buf2[SU_ADDRSTRLEN];
10875 char rdbuf[RD_ADDRSTRLEN];
10876
10877 /* Network configuration. */
10878 for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn))
10879 if ((table = prn->info) != NULL)
10880 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
10881 if ((bgp_static = rn->info) != NULL)
10882 {
10883 char *macrouter = NULL;
10884 char *esi = NULL;
10885
10886 if(bgp_static->router_mac)
7acff3e7 10887 macrouter = prefix_mac2str(bgp_static->router_mac, NULL, 0);
3da6fcd5
PG
10888 if(bgp_static->eth_s_id)
10889 esi = esi2str(bgp_static->eth_s_id);
10890 p = &rn->p;
10891 prd = (struct prefix_rd *) &prn->p;
10892
10893 /* "address-family" display. */
10894 bgp_config_write_family_header (vty, afi, safi, write);
10895
10896 /* "network" configuration display. */
10897 prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
10898
10899 inet_ntop (AF_INET, &bgp_static->igpnexthop, buf2, SU_ADDRSTRLEN);
10900
10901 prefix2str (p, buf, sizeof (buf)),
10902 vty_out (vty, " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
10903 buf, rdbuf, p->u.prefix_evpn.eth_tag,
9bedbb1e 10904 decode_label (&bgp_static->label), esi, buf2 , macrouter);
e31b6333 10905 vty_out (vty, VTYNL);
0bee00f9
PG
10906 if (macrouter)
10907 XFREE (MTYPE_TMP, macrouter);
ffd28f0e
PG
10908 if (esi)
10909 XFREE (MTYPE_TMP, esi);
3da6fcd5
PG
10910 }
10911 return 0;
10912}
10913
718e3744 10914/* Configuration of static route announcement and aggregate
10915 information. */
10916int
10917bgp_config_write_network (struct vty *vty, struct bgp *bgp,
10918 afi_t afi, safi_t safi, int *write)
10919{
10920 struct bgp_node *rn;
10921 struct prefix *p;
10922 struct bgp_static *bgp_static;
10923 struct bgp_aggregate *bgp_aggregate;
10924 char buf[SU_ADDRSTRLEN];
10925
c286be96
LX
10926 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
10927 return bgp_config_write_network_vpn (vty, bgp, afi, safi, write);
718e3744 10928
3da6fcd5
PG
10929 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
10930 return bgp_config_write_network_evpn (vty, bgp, afi, safi, write);
10931
718e3744 10932 /* Network configuration. */
10933 for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
10934 if ((bgp_static = rn->info) != NULL)
10935 {
10936 p = &rn->p;
10937
10938 /* "address-family" display. */
10939 bgp_config_write_family_header (vty, afi, safi, write);
10940
10941 /* "network" configuration display. */
10942 if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP)
10943 {
10944 u_int32_t destination;
10945 struct in_addr netmask;
10946
10947 destination = ntohl (p->u.prefix4.s_addr);
10948 masklen2ip (p->prefixlen, &netmask);
0b960b4d 10949 vty_out (vty, " network %s",
718e3744 10950 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN));
10951
10952 if ((IN_CLASSC (destination) && p->prefixlen == 24)
10953 || (IN_CLASSB (destination) && p->prefixlen == 16)
10954 || (IN_CLASSA (destination) && p->prefixlen == 8)
10955 || p->u.prefix4.s_addr == 0)
10956 {
10957 /* Natural mask is not display. */
10958 }
10959 else
10960 vty_out (vty, " mask %s", inet_ntoa (netmask));
10961 }
10962 else
10963 {
0b960b4d 10964 vty_out (vty, " network %s/%d",
718e3744 10965 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
10966 p->prefixlen);
10967 }
10968
1b6d5c7e
VV
10969 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
10970 vty_out (vty, " label-index %u", bgp_static->label_index);
10971
718e3744 10972 if (bgp_static->rmap.name)
10973 vty_out (vty, " route-map %s", bgp_static->rmap.name);
41367172
PJ
10974 else
10975 {
10976 if (bgp_static->backdoor)
10977 vty_out (vty, " backdoor");
41367172 10978 }
718e3744 10979
e31b6333 10980 vty_out (vty, VTYNL);
718e3744 10981 }
10982
10983 /* Aggregate-address configuration. */
10984 for (rn = bgp_table_top (bgp->aggregate[afi][safi]); rn; rn = bgp_route_next (rn))
10985 if ((bgp_aggregate = rn->info) != NULL)
10986 {
10987 p = &rn->p;
10988
10989 /* "address-family" display. */
10990 bgp_config_write_family_header (vty, afi, safi, write);
10991
10992 if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP)
10993 {
10994 struct in_addr netmask;
10995
10996 masklen2ip (p->prefixlen, &netmask);
0b960b4d 10997 vty_out (vty, " aggregate-address %s %s",
718e3744 10998 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
10999 inet_ntoa (netmask));
11000 }
11001 else
11002 {
0b960b4d 11003 vty_out (vty, " aggregate-address %s/%d",
718e3744 11004 inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
11005 p->prefixlen);
11006 }
11007
11008 if (bgp_aggregate->as_set)
11009 vty_out (vty, " as-set");
11010
11011 if (bgp_aggregate->summary_only)
11012 vty_out (vty, " summary-only");
11013
e31b6333 11014 vty_out (vty, VTYNL);
718e3744 11015 }
11016
11017 return 0;
11018}
11019
11020int
734b349e
MZ
11021bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi,
11022 safi_t safi, int *write)
718e3744 11023{
11024 struct bgp_node *rn;
11025 struct bgp_distance *bdistance;
11026
11027 /* Distance configuration. */
734b349e
MZ
11028 if (bgp->distance_ebgp[afi][safi]
11029 && bgp->distance_ibgp[afi][safi]
11030 && bgp->distance_local[afi][safi]
11031 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
11032 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
11033 || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT))
11034 {
11035 bgp_config_write_family_header (vty, afi, safi, write);
96ade3ed 11036 vty_outln (vty, " distance bgp %d %d %d",
734b349e 11037 bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi],
96ade3ed 11038 bgp->distance_local[afi][safi]);
734b349e
MZ
11039 }
11040
11041 for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn;
11042 rn = bgp_route_next (rn))
718e3744 11043 if ((bdistance = rn->info) != NULL)
11044 {
734b349e
MZ
11045 char buf[PREFIX_STRLEN];
11046
11047 bgp_config_write_family_header (vty, afi, safi, write);
96ade3ed 11048 vty_outln (vty, " distance %d %s %s", bdistance->distance,
734b349e 11049 prefix2str (&rn->p, buf, sizeof (buf)),
96ade3ed 11050 bdistance->access_list ? bdistance->access_list : "");
718e3744 11051 }
11052
734b349e 11053 return *write;
718e3744 11054}
11055
11056/* Allocate routing table structure and install commands. */
11057void
66e5cd87 11058bgp_route_init (void)
718e3744 11059{
734b349e
MZ
11060 afi_t afi;
11061 safi_t safi;
11062
718e3744 11063 /* Init BGP distance table. */
734b349e
MZ
11064 for (afi = AFI_IP; afi < AFI_MAX; afi++)
11065 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
11066 bgp_distance_table[afi][safi] = bgp_table_init (afi, safi);
718e3744 11067
11068 /* IPv4 BGP commands. */
73ac8160 11069 install_element (BGP_NODE, &bgp_table_map_cmd);
718e3744 11070 install_element (BGP_NODE, &bgp_network_cmd);
11071 install_element (BGP_NODE, &bgp_network_mask_cmd);
11072 install_element (BGP_NODE, &bgp_network_mask_natural_cmd);
11073 install_element (BGP_NODE, &bgp_network_route_map_cmd);
11074 install_element (BGP_NODE, &bgp_network_mask_route_map_cmd);
11075 install_element (BGP_NODE, &bgp_network_mask_natural_route_map_cmd);
11076 install_element (BGP_NODE, &bgp_network_backdoor_cmd);
11077 install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd);
11078 install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
73ac8160 11079 install_element (BGP_NODE, &no_bgp_table_map_cmd);
718e3744 11080 install_element (BGP_NODE, &no_bgp_network_cmd);
11081 install_element (BGP_NODE, &no_bgp_network_mask_cmd);
11082 install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd);
718e3744 11083
11084 install_element (BGP_NODE, &aggregate_address_cmd);
11085 install_element (BGP_NODE, &aggregate_address_mask_cmd);
718e3744 11086 install_element (BGP_NODE, &no_aggregate_address_cmd);
718e3744 11087 install_element (BGP_NODE, &no_aggregate_address_mask_cmd);
718e3744 11088
11089 /* IPv4 unicast configuration. */
73ac8160 11090 install_element (BGP_IPV4_NODE, &bgp_table_map_cmd);
718e3744 11091 install_element (BGP_IPV4_NODE, &bgp_network_cmd);
11092 install_element (BGP_IPV4_NODE, &bgp_network_mask_cmd);
11093 install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_cmd);
11094 install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd);
11095 install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
11096 install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
9bedbb1e
DW
11097 install_element (BGP_IPV4_NODE, &bgp_network_label_index_cmd);
11098 install_element (BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd);
11099 install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_cmd);
11100 install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_route_map_cmd);
73ac8160 11101 install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd);
c8f3fe30 11102 install_element (BGP_IPV4_NODE, &no_bgp_network_cmd);
718e3744 11103 install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
11104 install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
c8f3fe30 11105
718e3744 11106 install_element (BGP_IPV4_NODE, &aggregate_address_cmd);
11107 install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd);
718e3744 11108 install_element (BGP_IPV4_NODE, &no_aggregate_address_cmd);
718e3744 11109 install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
718e3744 11110
11111 /* IPv4 multicast configuration. */
73ac8160 11112 install_element (BGP_IPV4M_NODE, &bgp_table_map_cmd);
718e3744 11113 install_element (BGP_IPV4M_NODE, &bgp_network_cmd);
11114 install_element (BGP_IPV4M_NODE, &bgp_network_mask_cmd);
11115 install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd);
11116 install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
11117 install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
11118 install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_cmd);
73ac8160 11119 install_element (BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
718e3744 11120 install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd);
11121 install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
11122 install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
718e3744 11123 install_element (BGP_IPV4M_NODE, &aggregate_address_cmd);
11124 install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
718e3744 11125 install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd);
718e3744 11126 install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
718e3744 11127
f51bae9c 11128 /* IPv4 labeled-unicast configuration. */
f186de26 11129 install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd);
af462945 11130 install_element (VIEW_NODE, &show_ip_bgp_cmd);
718e3744 11131 install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
8c3deaae 11132 install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd);
57d187bc 11133
8386ac43 11134 install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd);
718e3744 11135 install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
718e3744 11136 install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373
PG
11137#ifdef KEEP_OLD_VPN_COMMANDS
11138 install_element (VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
11139#endif /* KEEP_OLD_VPN_COMMANDS */
4f280b15 11140 install_element (VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
4c63a661
PG
11141 install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
11142
718e3744 11143 /* BGP dampening clear commands */
11144 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
11145 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
57d187bc 11146
718e3744 11147 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
11148 install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
11149
ff7924f6 11150 /* prefix count */
8386ac43 11151 install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373
PG
11152#ifdef KEEP_OLD_VPN_COMMANDS
11153 install_element (ENABLE_NODE, &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
11154#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 11155
718e3744 11156 /* New config IPv6 BGP commands. */
73ac8160 11157 install_element (BGP_IPV6_NODE, &bgp_table_map_cmd);
718e3744 11158 install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
11159 install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
73ac8160 11160 install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd);
718e3744 11161 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
292caba3
DW
11162 install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd);
11163 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd);
11164 install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_route_map_cmd);
11165 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_route_map_cmd);
718e3744 11166
11167 install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
718e3744 11168 install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
73bfe0bd
B
11169
11170 install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
11171 install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
718e3744 11172
f51bae9c
DS
11173 install_element (BGP_IPV6L_NODE, &bgp_table_map_cmd);
11174 install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
11175 install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_route_map_cmd);
11176 install_element (BGP_IPV6L_NODE, &no_bgp_table_map_cmd);
11177 install_element (BGP_IPV6L_NODE, &no_ipv6_bgp_network_cmd);
11178
718e3744 11179 install_element (BGP_NODE, &bgp_distance_cmd);
11180 install_element (BGP_NODE, &no_bgp_distance_cmd);
718e3744 11181 install_element (BGP_NODE, &bgp_distance_source_cmd);
11182 install_element (BGP_NODE, &no_bgp_distance_source_cmd);
11183 install_element (BGP_NODE, &bgp_distance_source_access_list_cmd);
11184 install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd);
734b349e
MZ
11185 install_element (BGP_IPV4_NODE, &bgp_distance_cmd);
11186 install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd);
734b349e
MZ
11187 install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd);
11188 install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
11189 install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
11190 install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
11191 install_element (BGP_IPV4M_NODE, &bgp_distance_cmd);
11192 install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd);
734b349e
MZ
11193 install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd);
11194 install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
11195 install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
11196 install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd);
11197 install_element (BGP_IPV6_NODE, &bgp_distance_cmd);
11198 install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd);
734b349e
MZ
11199 install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
11200 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
11201 install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd);
11202 install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd);
11203 install_element (BGP_IPV6M_NODE, &bgp_distance_cmd);
11204 install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd);
734b349e
MZ
11205 install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
11206 install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
11207 install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd);
11208 install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd);
718e3744 11209
11210 install_element (BGP_NODE, &bgp_damp_set_cmd);
718e3744 11211 install_element (BGP_NODE, &bgp_damp_unset_cmd);
718e3744 11212 install_element (BGP_IPV4_NODE, &bgp_damp_set_cmd);
718e3744 11213 install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
5c9e5a8d
B
11214
11215 /* IPv4 Multicast Mode */
11216 install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd);
5c9e5a8d 11217 install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
52951b63
DS
11218
11219 /* Large Communities */
11220 install_element (VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
11221 install_element (VIEW_NODE, &show_ip_bgp_large_community_cmd);
718e3744 11222}
228da428
CC
11223
11224void
11225bgp_route_finish (void)
11226{
734b349e
MZ
11227 afi_t afi;
11228 safi_t safi;
11229
11230 for (afi = AFI_IP; afi < AFI_MAX; afi++)
11231 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
11232 {
11233 bgp_table_unlock (bgp_distance_table[afi][safi]);
11234 bgp_distance_table[afi][safi] = NULL;
11235 }
228da428 11236}