]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_mplsvpn.c
bgpd: vpn-vrf-leaking new CLI: address Vivek's review comments + crash fix
[mirror_frr.git] / bgpd / bgp_mplsvpn.c
CommitLineData
718e3744 1/* MPLS-VPN
896014f4
DL
2 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 20
21#include <zebra.h>
22
23#include "command.h"
24#include "prefix.h"
25#include "log.h"
26#include "memory.h"
27#include "stream.h"
3f9c7369 28#include "queue.h"
039f3a34 29#include "filter.h"
ddb5b488 30#include "mpls.h"
b9c7bc5a
PZ
31#include "json.h"
32#include "zclient.h"
9bedbb1e 33
718e3744 34#include "bgpd/bgpd.h"
ddb5b488 35#include "bgpd/bgp_debug.h"
718e3744 36#include "bgpd/bgp_table.h"
37#include "bgpd/bgp_route.h"
38#include "bgpd/bgp_attr.h"
9bedbb1e 39#include "bgpd/bgp_label.h"
718e3744 40#include "bgpd/bgp_mplsvpn.h"
48a5452b 41#include "bgpd/bgp_packet.h"
3f227172 42#include "bgpd/bgp_vty.h"
784d3a42 43#include "bgpd/bgp_vpn.h"
ddb5b488
PZ
44#include "bgpd/bgp_ecommunity.h"
45#include "bgpd/bgp_zebra.h"
46#include "bgpd/bgp_nexthop.h"
718e3744 47
65efcfce 48#if ENABLE_BGP_VNC
f8b6f499 49#include "bgpd/rfapi/rfapi_backend.h"
65efcfce
LB
50#endif
51
ddb5b488
PZ
52/*
53 * Definitions and external declarations.
54 */
55extern struct zclient *zclient;
56
d62a17ae 57extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
58 int *index, afi_t *afi)
3f227172 59{
d62a17ae 60 int ret = 0;
61 if (argv_find(argv, argc, "vpnv4", index)) {
62 ret = 1;
63 if (afi)
64 *afi = AFI_IP;
65 } else if (argv_find(argv, argc, "vpnv6", index)) {
66 ret = 1;
67 if (afi)
68 *afi = AFI_IP6;
69 }
70 return ret;
3f227172
PG
71}
72
d62a17ae 73u_int32_t decode_label(mpls_label_t *label_pnt)
718e3744 74{
d62a17ae 75 u_int32_t l;
76 u_char *pnt = (u_char *)label_pnt;
718e3744 77
d62a17ae 78 l = ((u_int32_t)*pnt++ << 12);
79 l |= (u_int32_t)*pnt++ << 4;
80 l |= (u_int32_t)((*pnt & 0xf0) >> 4);
81 return l;
718e3744 82}
83
d62a17ae 84void encode_label(mpls_label_t label, mpls_label_t *label_pnt)
65efcfce 85{
d62a17ae 86 u_char *pnt = (u_char *)label_pnt;
87 if (pnt == NULL)
88 return;
89 *pnt++ = (label >> 12) & 0xff;
90 *pnt++ = (label >> 4) & 0xff;
91 *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */
65efcfce
LB
92}
93
d62a17ae 94int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
95 struct bgp_nlri *packet)
718e3744 96{
d62a17ae 97 u_char *pnt;
98 u_char *lim;
99 struct prefix p;
100 int psize = 0;
101 int prefixlen;
102 u_int16_t type;
103 struct rd_as rd_as;
104 struct rd_ip rd_ip;
105 struct prefix_rd prd;
ddb5b488 106 mpls_label_t label = {0};
d62a17ae 107 afi_t afi;
108 safi_t safi;
109 int addpath_encoded;
110 u_int32_t addpath_id;
111
112 /* Check peer status. */
113 if (peer->status != Established)
114 return 0;
115
116 /* Make prefix_rd */
117 prd.family = AF_UNSPEC;
118 prd.prefixlen = 64;
119
120 pnt = packet->nlri;
121 lim = pnt + packet->length;
122 afi = packet->afi;
123 safi = packet->safi;
124 addpath_id = 0;
125
126 addpath_encoded =
127 (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
128 && CHECK_FLAG(peer->af_cap[afi][safi],
129 PEER_CAP_ADDPATH_AF_TX_RCV));
718e3744 130
50905aa2 131#define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
d62a17ae 132 for (; pnt < lim; pnt += psize) {
133 /* Clear prefix structure. */
134 memset(&p, 0, sizeof(struct prefix));
135
136 if (addpath_encoded) {
137
138 /* When packet overflow occurs return immediately. */
139 if (pnt + BGP_ADDPATH_ID_LEN > lim)
140 return -1;
141
142 addpath_id = ntohl(*((uint32_t *)pnt));
143 pnt += BGP_ADDPATH_ID_LEN;
144 }
145
146 /* Fetch prefix length. */
147 prefixlen = *pnt++;
148 p.family = afi2family(packet->afi);
149 psize = PSIZE(prefixlen);
150
151 if (prefixlen < VPN_PREFIXLEN_MIN_BYTES * 8) {
152 zlog_err(
153 "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
154 peer->host, prefixlen);
155 return -1;
156 }
157
158 /* sanity check against packet data */
159 if ((pnt + psize) > lim) {
160 zlog_err(
161 "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
162 peer->host, prefixlen, (uint)(lim - pnt));
163 return -1;
164 }
165
166 /* sanity check against storage for the IP address portion */
167 if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t)sizeof(p.u)) {
168 zlog_err(
169 "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
170 peer->host,
171 prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
172 sizeof(p.u));
173 return -1;
174 }
175
176 /* Sanity check against max bitlen of the address family */
177 if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen(&p)) {
178 zlog_err(
179 "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
180 peer->host,
181 prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
182 p.family, prefix_blen(&p));
183 return -1;
184 }
185
186 /* Copy label to prefix. */
187 memcpy(&label, pnt, BGP_LABEL_BYTES);
188 bgp_set_valid_label(&label);
189
190 /* Copy routing distinguisher to rd. */
191 memcpy(&prd.val, pnt + BGP_LABEL_BYTES, 8);
192
193 /* Decode RD type. */
194 type = decode_rd_type(pnt + BGP_LABEL_BYTES);
195
196 switch (type) {
197 case RD_TYPE_AS:
198 decode_rd_as(pnt + 5, &rd_as);
199 break;
200
201 case RD_TYPE_AS4:
202 decode_rd_as4(pnt + 5, &rd_as);
203 break;
204
205 case RD_TYPE_IP:
206 decode_rd_ip(pnt + 5, &rd_ip);
207 break;
fe770c88 208
65efcfce 209#if ENABLE_BGP_VNC
d62a17ae 210 case RD_TYPE_VNC_ETH:
211 break;
65efcfce
LB
212#endif
213
d62a17ae 214 default:
215 zlog_err("Unknown RD type %d", type);
216 break; /* just report */
217 }
218
219 p.prefixlen =
220 prefixlen
221 - VPN_PREFIXLEN_MIN_BYTES * 8; /* exclude label & RD */
222 memcpy(&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
223 psize - VPN_PREFIXLEN_MIN_BYTES);
224
225 if (attr) {
226 bgp_update(peer, &p, addpath_id, attr, packet->afi,
227 SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
b57ba6d2 228 BGP_ROUTE_NORMAL, &prd, &label, 1, 0, NULL);
d62a17ae 229 } else {
230 bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
231 SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
b57ba6d2 232 BGP_ROUTE_NORMAL, &prd, &label, 1, NULL);
d62a17ae 233 }
234 }
235 /* Packet length consistency check. */
236 if (pnt != lim) {
237 zlog_err(
238 "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
239 peer->host, lim - pnt);
240 return -1;
241 }
242
243 return 0;
50905aa2 244#undef VPN_PREFIXLEN_MIN_BYTES
718e3744 245}
246
ddb5b488
PZ
247/*
248 * This function informs zebra of the label this vrf sets on routes
249 * leaked to VPN. Zebra should install this label in the kernel with
250 * an action of "pop label and then use this vrf's IP FIB to route the PDU."
251 *
252 * Sending this vrf-label association is qualified by a) whether vrf->vpn
253 * exporting is active ("export vpn" is enabled, vpn-policy RD and RT list
254 * are set) and b) whether vpn-policy label is set.
255 *
256 * If any of these conditions do not hold, then we send MPLS_LABEL_NONE
257 * for this vrf, which zebra interprets to mean "delete this vrf-label
258 * association."
259 */
260void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
261{
262 mpls_label_t label = MPLS_LABEL_NONE;
263 const char *name = "default";
264 int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
265
266 if (debug && (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)) {
267 name = bgp->name;
268 }
269
270 if (bgp->vrf_id == VRF_UNKNOWN) {
271 if (debug) {
272 zlog_debug(
273 "%s: vrf %s: afi %s: vrf_id not set, "
274 "can't set zebra vrf label",
275 __func__, name, afi2str(afi));
276 }
277 return;
278 }
279
280 if (vpn_leak_to_vpn_active(bgp, afi, NULL)) {
281 label = bgp->vpn_policy[afi].tovpn_label;
282 }
283
284 if (debug) {
285 zlog_debug("%s: vrf %s: afi %s: setting label %d for vrf id %d",
286 __func__, name, afi2str(afi), label, bgp->vrf_id);
287 }
288
289 zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
290 bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
291}
292
293/*
294 * If zebra tells us vrf has become unconfigured, tell zebra not to
295 * use this label to forward to the vrf anymore
296 */
297void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi)
298{
299 mpls_label_t label = MPLS_LABEL_NONE;
300 int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
301
302 if (bgp->vrf_id == VRF_UNKNOWN) {
303 if (debug) {
304 zlog_debug(
305 "%s: vrf_id not set, can't delete zebra vrf label",
306 __func__);
307 }
308 return;
309 }
310
311 if (debug) {
312 zlog_debug("%s: deleting label for vrf %s (id=%d)", __func__,
313 (bgp->name ? bgp->name : "default"), bgp->vrf_id);
314 }
315
316 zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
317 bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
318}
319
320static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
321{
322 int i;
323 int j;
324
325 if (!e1 || !e2)
326 return 0;
327
328 for (i = 0; i < e1->size; ++i) {
329 for (j = 0; j < e2->size; ++j) {
330 if (!memcmp(e1->val + (i * ECOMMUNITY_SIZE),
331 e2->val + (j * ECOMMUNITY_SIZE),
332 ECOMMUNITY_SIZE)) {
333
334 return 1;
335 }
336 }
337 }
338 return 0;
339}
340
341/*
342 * returns pointer to new bgp_info upon success
343 */
344static struct bgp_info *
345leak_update(struct bgp *bgp, /* destination bgp instance */
346 struct bgp_node *bn, struct attr *new_attr, /* already interned */
347 afi_t afi, safi_t safi, struct bgp_info *source_bi, u_char type,
348 u_char sub_type, mpls_label_t *label, int num_labels, void *parent,
349 struct bgp *bgp_orig, struct prefix *nexthop_orig, int debug)
350{
351 struct prefix *p = &bn->p;
352 struct bgp_info *bi;
353 struct bgp_info *new;
354 char buf_prefix[PREFIX_STRLEN];
355 const char *pDestInstanceName = "default";
356
357 if (debug) {
358 prefix2str(&bn->p, buf_prefix, sizeof(buf_prefix));
359 if (bgp->name)
360 pDestInstanceName = bgp->name;
361 }
362
363 /*
364 * match parent
365 */
366 for (bi = bn->info; bi; bi = bi->next) {
367 if (bi->extra && bi->extra->parent == parent)
368 break;
369 }
370
371 if (bi) {
372 if (attrhash_cmp(bi->attr, new_attr)
373 && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
374
375 bgp_attr_unintern(&new_attr);
376 if (debug)
377 zlog_debug(
378 "%s: ->%s: %s: Found route, no change",
379 __func__, pDestInstanceName,
380 buf_prefix);
381 return NULL;
382 }
383
384 /* attr is changed */
385 bgp_info_set_flag(bn, bi, BGP_INFO_ATTR_CHANGED);
386
387 /* Rewrite BGP route information. */
388 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
389 bgp_info_restore(bn, bi);
390 else
391 bgp_aggregate_decrement(bgp, p, bi, afi, safi);
392 bgp_attr_unintern(&bi->attr);
393 bi->attr = new_attr;
394 bi->uptime = bgp_clock();
395
396 /* Process change. */
397 bgp_aggregate_increment(bgp, p, bi, afi, safi);
398 bgp_process(bgp, bn, afi, safi);
399 bgp_unlock_node(bn);
400
401 if (debug)
402 zlog_debug("%s: ->%s: %s Found route, changed attr",
403 __func__, pDestInstanceName, buf_prefix);
404
405 return NULL;
406 }
407
408 new = info_make(type, sub_type, 0, bgp->peer_self, new_attr, bn);
409 SET_FLAG(new->flags, BGP_INFO_VALID);
410
411 bgp_info_extra_get(new);
412 if (label) {
413 int i;
414
415 for (i = 0; i < num_labels; ++i) {
416 new->extra->label[i] = label[i];
417 if (!bgp_is_valid_label(&label[i])) {
418 if (debug) {
419 zlog_debug(
420 "%s: %s: marking label %d valid",
421 __func__, buf_prefix, i);
422 }
423 bgp_set_valid_label(&new->extra->label[i]);
424 }
425 }
426 new->extra->num_labels = num_labels;
427 }
428 new->extra->parent = parent;
429
430 if (bgp_orig)
431 new->extra->bgp_orig = bgp_orig;
432 if (nexthop_orig)
433 new->extra->nexthop_orig = *nexthop_orig;
434
435 bgp_aggregate_increment(bgp, p, new, afi, safi);
436 bgp_info_add(bn, new);
437
438 bgp_unlock_node(bn);
439 bgp_process(bgp, bn, afi, safi);
440
441 if (debug)
442 zlog_debug("%s: ->%s: %s: Added new route", __func__,
443 pDestInstanceName, buf_prefix);
444
445 return new;
446}
447
448/* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
449void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
450 struct bgp *bgp_vrf, /* from */
451 struct bgp_info *info_vrf) /* route */
452{
453 int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
454 struct prefix *p = &info_vrf->net->p;
455 afi_t afi = family2afi(p->family);
456 struct attr static_attr = {0};
457 struct attr *new_attr = NULL;
458 safi_t safi = SAFI_MPLS_VPN;
459 mpls_label_t label_val;
460 mpls_label_t label;
461 struct bgp_node *bn;
462 const char *debugmsg;
463
464 if (debug) {
465 const char *s = "";
466
467 if (info_vrf->attr && info_vrf->attr->ecommunity) {
468 s = ecommunity_ecom2str(info_vrf->attr->ecommunity,
469 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
470 }
471
472 zlog_debug("%s: info_vrf->type=%d, EC{%s}", __func__,
473 info_vrf->type, s);
474 }
475
476 if (!bgp_vpn)
477 return;
478
479 if (!afi) {
480 if (debug)
481 zlog_debug("%s: can't get afi of prefix", __func__);
482 return;
483 }
484
485 /* loop check */
486 if (info_vrf->extra && info_vrf->extra->bgp_orig == bgp_vpn)
487 return;
488
489
490 if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) {
491 if (debug)
492 zlog_debug("%s: skipping: %s", __func__, debugmsg);
493 return;
494 }
495
496 bgp_attr_dup(&static_attr, info_vrf->attr); /* shallow copy */
497
498 /*
499 * route map handling
500 */
501 if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
502 struct bgp_info info;
503 route_map_result_t ret;
504
505 memset(&info, 0, sizeof(info));
506 info.peer = bgp_vpn->peer_self;
507 info.attr = &static_attr;
508 ret = route_map_apply(
509 bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN],
510 p, RMAP_BGP, &info);
511 if (RMAP_DENYMATCH == ret) {
512 bgp_attr_flush(&static_attr); /* free any added parts */
513 if (debug)
514 zlog_debug(
515 "%s: vrf %s route map \"%s\" says DENY, returning",
516 __func__, bgp_vrf->name,
517 bgp_vrf->vpn_policy[afi]
518 .rmap[BGP_VPN_POLICY_DIR_TOVPN]
519 ->name);
520 return;
521 }
522 }
523
524 if (debug) {
525 const char *s = "";
526
527 if (static_attr.ecommunity) {
528 s = ecommunity_ecom2str(static_attr.ecommunity,
529 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
530 }
531 zlog_debug("%s: post route map static_attr.ecommunity{%s}",
532 __func__, s);
533 }
534
535 /*
536 * Add the vpn-policy rt-list
537 */
538 struct ecommunity *old_ecom;
539 struct ecommunity *new_ecom;
540
541 old_ecom = static_attr.ecommunity;
542 if (old_ecom) {
543 new_ecom = ecommunity_merge(
544 ecommunity_dup(old_ecom),
545 bgp_vrf->vpn_policy[afi]
546 .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
547 if (!old_ecom->refcnt)
548 ecommunity_free(&old_ecom);
549 } else {
550 new_ecom = ecommunity_dup(
551 bgp_vrf->vpn_policy[afi]
552 .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
553 }
554 static_attr.ecommunity = new_ecom;
555 SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
556
557 if (debug) {
558 const char *s = "";
559
560 if (static_attr.ecommunity) {
561 s = ecommunity_ecom2str(static_attr.ecommunity,
562 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
563 }
564 zlog_debug("%s: post merge static_attr.ecommunity{%s}",
565 __func__, s);
566 }
567
568 /* Nexthop */
569 /* if policy nexthop not set, use 0 */
570 if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
571 BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
572
573 struct prefix *nexthop =
574 &bgp_vrf->vpn_policy[afi].tovpn_nexthop;
575 switch (nexthop->family) {
576 case AF_INET:
577 /* prevent mp_nexthop_global_in <- self in bgp_route.c
578 */
579 static_attr.nexthop.s_addr = nexthop->u.prefix4.s_addr;
580
581 static_attr.mp_nexthop_global_in = nexthop->u.prefix4;
582 static_attr.mp_nexthop_len = 4;
583 break;
584
585 case AF_INET6:
586 static_attr.mp_nexthop_global = nexthop->u.prefix6;
587 static_attr.mp_nexthop_len = 16;
588 break;
589
590 default:
591 assert(0);
592 }
593 } else {
594 switch (afi) {
595 case AFI_IP:
596 default:
597 /* Clear ipv4 */
598 static_attr.mp_nexthop_global_in.s_addr = 0;
599 static_attr.mp_nexthop_len = 4;
600 static_attr.nexthop.s_addr = 0; /* self */
601 static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
602 break;
603
604 case AFI_IP6:
605 /* Clear ipv6 */
606 memset(&static_attr.mp_nexthop_global, 0,
607 sizeof(static_attr.mp_nexthop_global));
608 static_attr.mp_nexthop_len = 16; /* bytes */
609 break;
610 }
611 }
612
613 label_val = bgp_vrf->vpn_policy[afi].tovpn_label;
614 if (label_val == MPLS_LABEL_NONE) {
615 /* TBD get from label manager */
616 label = MPLS_LABEL_IMPLICIT_NULL;
617 } else {
618 encode_label(label_val, &label);
619 }
620
621 /* Set originator ID to "me" */
622 SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID));
623 static_attr.originator_id = bgp_vpn->router_id;
624
625
626 new_attr = bgp_attr_intern(
627 &static_attr); /* hashed refcounted everything */
628 bgp_attr_flush(&static_attr); /* free locally-allocated parts */
629
630 if (debug) {
631 const char *s = "";
632
633 if (new_attr->ecommunity) {
634 s = ecommunity_ecom2str(new_attr->ecommunity,
635 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
636 }
637 zlog_debug("%s: new_attr->ecommunity{%s}", __func__, s);
638 }
639
640 /* Now new_attr is an allocated interned attr */
641
642 bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p,
643 &(bgp_vrf->vpn_policy[afi].tovpn_rd));
644
645 struct bgp_info *new_info;
646
647 new_info = leak_update(bgp_vpn, bn, new_attr, afi, safi, info_vrf,
648 ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, &label, 1,
649 info_vrf, bgp_vrf, NULL, debug);
650
651 /*
652 * Routes actually installed in the vpn RIB must also be
653 * offered to all vrfs (because now they originate from
654 * the vpn RIB).
655 *
656 * Acceptance into other vrfs depends on rt-lists.
657 * Originating vrf will not accept the looped back route
658 * because of loop checking.
659 */
660 if (new_info)
661 vpn_leak_to_vrf_update(bgp_vrf, new_info);
662}
663
664void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */
665 struct bgp *bgp_vrf, /* from */
666 struct bgp_info *info_vrf) /* route */
667{
668 int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
669 struct prefix *p = &info_vrf->net->p;
670 afi_t afi = family2afi(p->family);
671 safi_t safi = SAFI_MPLS_VPN;
672 struct bgp_info *bi;
673 struct bgp_node *bn;
674 const char *debugmsg;
675
676 if (info_vrf->type != ZEBRA_ROUTE_BGP) {
677 if (debug)
678 zlog_debug("%s: wrong type %d", __func__,
679 info_vrf->type);
680 return;
681 }
682 if (info_vrf->sub_type != BGP_ROUTE_NORMAL
683 && info_vrf->sub_type != BGP_ROUTE_STATIC) {
684
685 if (debug)
686 zlog_debug("%s: wrong sub_type %d", __func__,
687 info_vrf->sub_type);
688 return;
689 }
690 if (!bgp_vpn)
691 return;
692
693 if (!afi) {
694 if (debug)
695 zlog_debug("%s: can't get afi of prefix", __func__);
696 return;
697 }
698
699 if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) {
700 if (debug)
701 zlog_debug("%s: skipping: %s", __func__, debugmsg);
702 return;
703 }
704
705 if (debug)
706 zlog_debug("%s: withdrawing (info_vrf=%p)", __func__, info_vrf);
707
708 bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p,
709 &(bgp_vrf->vpn_policy[afi].tovpn_rd));
710
711 /*
712 * vrf -> vpn
713 * match original bi imported from
714 */
715 for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) {
716 if (bi->extra && bi->extra->parent == info_vrf) {
717 break;
718 }
719 }
720
721 if (bi) {
722 /* withdraw from looped vrfs as well */
723 vpn_leak_to_vrf_withdraw(bgp_vpn, bi);
724
725 bgp_aggregate_decrement(bgp_vpn, p, bi, afi, safi);
726 bgp_info_delete(bn, bi);
727 bgp_process(bgp_vpn, bn, afi, safi);
728 }
729 bgp_unlock_node(bn);
730}
731
732void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
733 struct bgp *bgp_vrf, /* from */
734 afi_t afi)
735{
736 int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
737 struct bgp_node *prn;
738 safi_t safi = SAFI_MPLS_VPN;
739
740 /*
ddb5b488
PZ
741 * Walk vpn table, delete bi with bgp_orig == bgp_vrf
742 */
743 for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn;
744 prn = bgp_route_next(prn)) {
745
746 struct bgp_table *table;
747 struct bgp_node *bn;
748 struct bgp_info *bi;
749
750 /* This is the per-RD table of prefixes */
751 table = prn->info;
752
753 if (!table)
754 continue;
755
756 for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
757
758 char buf[PREFIX2STR_BUFFER];
759
760 if (debug && bn->info) {
761 zlog_debug(
762 "%s: looking at prefix %s", __func__,
763 prefix2str(&bn->p, buf, sizeof(buf)));
764 }
765
766 for (bi = bn->info; bi; bi = bi->next) {
767 if (debug)
768 zlog_debug("%s: type %d, sub_type %d",
769 __func__, bi->type,
770 bi->sub_type);
771 if (bi->sub_type != BGP_ROUTE_IMPORTED)
772 continue;
773 if (!bi->extra)
774 continue;
775 if ((struct bgp *)bi->extra->bgp_orig
776 == bgp_vrf) {
777 /* delete route */
778 if (debug)
779 zlog_debug("%s: deleting it\n",
780 __func__);
781 bgp_aggregate_decrement(bgp_vpn, &bn->p,
782 bi, afi, safi);
783 bgp_info_delete(bn, bi);
784 bgp_process(bgp_vpn, bn, afi, safi);
785 }
786 }
787 }
788 }
789}
790
791void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */
792 struct bgp *bgp_vrf, /* from */
793 afi_t afi)
794{
795 struct bgp_node *bn;
796 struct bgp_info *bi;
797 int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
798
799 if (debug)
800 zlog_debug("%s: entry, afi=%d, vrf=%s", __func__, afi,
801 bgp_vrf->name);
802
803 for (bn = bgp_table_top(bgp_vrf->rib[afi][SAFI_UNICAST]); bn;
804 bn = bgp_route_next(bn)) {
805
806 if (debug)
807 zlog_debug("%s: node=%p", __func__, bn);
808
809 for (bi = bn->info; bi; bi = bi->next) {
810 if (debug)
811 zlog_debug(
812 "%s: calling vpn_leak_from_vrf_update",
813 __func__);
814 vpn_leak_from_vrf_update(bgp_vpn, bgp_vrf, bi);
815 }
816 }
817}
818
819static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
820 struct bgp *bgp_vpn, /* from */
821 struct bgp_info *info_vpn) /* route */
822{
823 struct prefix *p = &info_vpn->net->p;
824 afi_t afi = family2afi(p->family);
825
ddb5b488
PZ
826 struct attr static_attr = {0};
827 struct attr *new_attr = NULL;
828 struct bgp_node *bn;
829 safi_t safi = SAFI_UNICAST;
830 const char *debugmsg;
831 struct prefix nexthop_orig;
832 mpls_label_t *pLabels = NULL;
833 int num_labels = 0;
834
835 int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
836
b9c7bc5a 837 if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg)) {
ddb5b488
PZ
838 if (debug)
839 zlog_debug("%s: skipping: %s", __func__, debugmsg);
840 return;
841 }
842
843 /* Check for intersection of route targets */
844 if (!ecom_intersect(
845 bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
846 info_vpn->attr->ecommunity)) {
847
848 return;
849 }
850
851 if (debug)
852 zlog_debug("%s: updating to vrf %s", __func__, bgp_vrf->name);
853
854 bgp_attr_dup(&static_attr, info_vpn->attr); /* shallow copy */
855
856 /*
857 * Nexthop: stash and clear
858 *
859 * Nexthop is valid in context of VPN core, but not in destination vrf.
860 * Stash it for later label resolution by vrf ingress path and then
861 * overwrite with 0, i.e., "me", for the sake of vrf advertisement.
862 */
863 uint8_t nhfamily = NEXTHOP_FAMILY(info_vpn->attr->mp_nexthop_len);
864
865 memset(&nexthop_orig, 0, sizeof(nexthop_orig));
866 nexthop_orig.family = nhfamily;
867
868 switch (nhfamily) {
869
870 case AF_INET:
871 /* save */
872 nexthop_orig.u.prefix4 = info_vpn->attr->mp_nexthop_global_in;
873 nexthop_orig.prefixlen = 32;
874
875 static_attr.nexthop.s_addr = 0; /* self */
876 static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
877
878 break;
879
880 case AF_INET6:
881 /* save */
882 nexthop_orig.u.prefix6 = info_vpn->attr->mp_nexthop_global;
883 nexthop_orig.prefixlen = 128;
884
885 memset(&static_attr.mp_nexthop_global, 0,
886 sizeof(static_attr.mp_nexthop_global)); /* clear */
887 static_attr.mp_nexthop_len = 16; /* bytes */
888 break;
889 }
890
891
892 /*
893 * route map handling
ddb5b488 894 */
ddb5b488
PZ
895 if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
896 struct bgp_info info;
897 route_map_result_t ret;
898
899 memset(&info, 0, sizeof(info));
900 info.peer = bgp_vrf->peer_self;
901 info.attr = &static_attr;
902 ret = route_map_apply(bgp_vrf->vpn_policy[afi]
903 .rmap[BGP_VPN_POLICY_DIR_FROMVPN],
904 p, RMAP_BGP, &info);
905 if (RMAP_DENYMATCH == ret) {
906 bgp_attr_flush(&static_attr); /* free any added parts */
907 if (debug)
908 zlog_debug(
909 "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning",
910 __func__, bgp_vrf->name,
911 bgp_vrf->vpn_policy[afi]
912 .rmap[BGP_VPN_POLICY_DIR_FROMVPN]
913 ->name);
914 return;
915 }
916 }
917
918 new_attr = bgp_attr_intern(&static_attr);
919 bgp_attr_flush(&static_attr);
920
921 bn = bgp_afi_node_get(bgp_vrf->rib[afi][safi], afi, safi, p, NULL);
922
923 /*
924 * ensure labels are copied
925 */
926 if (info_vpn->extra && info_vpn->extra->num_labels) {
927 num_labels = info_vpn->extra->num_labels;
928 if (num_labels > BGP_MAX_LABELS)
929 num_labels = BGP_MAX_LABELS;
930 pLabels = info_vpn->extra->label;
931 }
932 if (debug) {
933 char buf_prefix[PREFIX_STRLEN];
934 prefix2str(p, buf_prefix, sizeof(buf_prefix));
935 zlog_debug("%s: pfx %s: num_labels %d", __func__, buf_prefix,
936 num_labels);
937 }
938
939 leak_update(bgp_vrf, bn, new_attr, afi, safi, info_vpn, ZEBRA_ROUTE_BGP,
940 BGP_ROUTE_IMPORTED, pLabels, num_labels,
941 info_vpn, /* parent */
942 bgp_vpn, &nexthop_orig, debug);
943}
944
945void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */
946 struct bgp_info *info_vpn) /* route */
947{
948 struct listnode *mnode, *mnnode;
949 struct bgp *bgp;
950
951 int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
952
953 if (debug)
954 zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn);
955
956 /* Loop over VRFs */
957 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
958
959 if (!info_vpn->extra
960 || info_vpn->extra->bgp_orig != bgp) { /* no loop */
961 vpn_leak_to_vrf_update_onevrf(bgp, bgp_vpn, info_vpn);
962 }
963 }
964}
965
966void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */
967 struct bgp_info *info_vpn) /* route */
968{
969 struct prefix *p = &info_vpn->net->p;
970 afi_t afi = family2afi(p->family);
971 safi_t safi = SAFI_UNICAST;
972 struct bgp *bgp;
973 struct listnode *mnode, *mnnode;
ddb5b488
PZ
974 struct bgp_node *bn;
975 struct bgp_info *bi;
976 const char *debugmsg;
977
978 int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
979
980 if (debug)
981 zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn);
982
983
984 /* Loop over VRFs */
985 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
b9c7bc5a 986 if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg)) {
ddb5b488
PZ
987 if (debug)
988 zlog_debug("%s: skipping: %s", __func__,
989 debugmsg);
990 continue;
991 }
992
993 /* Check for intersection of route targets */
994 if (!ecom_intersect(bgp->vpn_policy[afi]
995 .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
996 info_vpn->attr->ecommunity)) {
997
998 continue;
999 }
1000
1001 if (debug)
1002 zlog_debug("%s: withdrawing from vrf %s", __func__,
1003 bgp->name);
1004
1005 bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
1006 for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) {
1007 if (bi->extra
1008 && (struct bgp_info *)bi->extra->parent
1009 == info_vpn) {
1010 break;
1011 }
1012 }
1013
1014 if (bi) {
1015 if (debug)
1016 zlog_debug("%s: deleting bi %p", __func__, bi);
1017 bgp_aggregate_decrement(bgp, p, bi, afi, safi);
1018 bgp_info_delete(bn, bi);
1019 bgp_process(bgp, bn, afi, safi);
1020 }
1021 bgp_unlock_node(bn);
1022 }
1023}
1024
1025void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */
1026 afi_t afi)
1027{
1028 struct bgp_node *bn;
1029 struct bgp_info *bi;
1030 safi_t safi = SAFI_UNICAST;
1031 int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
1032 struct bgp *bgp_vpn = bgp_get_default();
1033
1034 if (debug)
1035 zlog_debug("%s: entry", __func__);
1036 /*
1037 * Walk vrf table, delete bi with bgp_orig == bgp_vpn
1038 */
1039 for (bn = bgp_table_top(bgp_vrf->rib[afi][safi]); bn;
1040 bn = bgp_route_next(bn)) {
1041
1042 for (bi = bn->info; bi; bi = bi->next) {
1043 if (bi->extra && bi->extra->bgp_orig == bgp_vpn) {
1044
1045 /* delete route */
1046 bgp_aggregate_decrement(bgp_vrf, &bn->p, bi,
1047 afi, safi);
1048 bgp_info_delete(bn, bi);
1049 bgp_process(bgp_vrf, bn, afi, safi);
1050 }
1051 }
1052 }
1053}
1054
1055void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */
1056 struct bgp *bgp_vpn, /* from */
1057 afi_t afi)
1058{
1059 struct prefix_rd prd;
1060 struct bgp_node *prn;
1061 safi_t safi = SAFI_MPLS_VPN;
1062
1063 /*
1064 * Walk vpn table
1065 */
1066 for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn;
1067 prn = bgp_route_next(prn)) {
1068
1069 struct bgp_table *table;
1070 struct bgp_node *bn;
1071 struct bgp_info *bi;
1072
1073 memset(&prd, 0, sizeof(prd));
1074 prd.family = AF_UNSPEC;
1075 prd.prefixlen = 64;
1076 memcpy(prd.val, prn->p.u.val, 8);
1077
1078 /* This is the per-RD table of prefixes */
1079 table = prn->info;
1080
1081 if (!table)
1082 continue;
1083
1084 for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
1085
1086 for (bi = bn->info; bi; bi = bi->next) {
1087
1088 if (bi->extra && bi->extra->bgp_orig == bgp_vrf)
1089 continue;
1090
1091 vpn_leak_to_vrf_update_onevrf(bgp_vrf, bgp_vpn,
1092 bi);
1093 }
1094 }
1095 }
1096}
1097
1098static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name)
1099{
1100 int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
1101 afi_t afi;
1102 struct route_map *rmap;
1103
1104 if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
1105 && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) {
1106
1107 return;
1108 }
1109
1110 rmap = route_map_lookup_by_name(rmap_name); /* NULL if deleted */
1111
1112 for (afi = 0; afi < AFI_MAX; ++afi) {
1113
1114 if (vpn_leak_to_vpn_active(bgp, afi, NULL)
1115 && bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]
1116 && !strcmp(rmap_name,
1117 bgp->vpn_policy[afi]
1118 .rmap_name[BGP_VPN_POLICY_DIR_TOVPN])) {
1119
1120 if (debug)
1121 zlog_debug(
1122 "%s: rmap \"%s\" matches vrf-policy tovpn for as %d afi %s",
1123 __func__, rmap_name, bgp->as,
1124 afi2str(afi));
1125
1126 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
1127 bgp_get_default(), bgp);
1128 if (debug)
1129 zlog_debug("%s: after vpn_leak_prechange",
1130 __func__);
1131
1132 if (!rmap)
1133 bgp->vpn_policy[afi]
1134 .rmap[BGP_VPN_POLICY_DIR_TOVPN] = NULL;
1135
1136 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
1137 bgp_get_default(), bgp);
1138 if (debug)
1139 zlog_debug("%s: after vpn_leak_postchange",
1140 __func__);
1141 }
1142
b9c7bc5a
PZ
1143 char *mapname = bgp->vpn_policy[afi]
1144 .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN];
ddb5b488 1145
d555f3e9 1146 if (vpn_leak_from_vpn_active(bgp, afi, NULL) &&
b9c7bc5a
PZ
1147 mapname &&
1148 !strcmp(rmap_name, mapname)) {
1149
1150 if (debug) {
1151 zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
ddb5b488
PZ
1152 __func__, rmap_name, bgp->as,
1153 afi2str(afi));
b9c7bc5a 1154 }
ddb5b488
PZ
1155
1156 vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
1157 bgp_get_default(), bgp);
1158
b9c7bc5a 1159 if (!rmap) {
ddb5b488
PZ
1160 bgp->vpn_policy[afi]
1161 .rmap[BGP_VPN_POLICY_DIR_FROMVPN] =
1162 NULL;
b9c7bc5a 1163 }
ddb5b488
PZ
1164
1165 vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
1166 bgp_get_default(), bgp);
1167 }
1168 }
1169}
1170
1171void vpn_policy_routemap_event(const char *rmap_name)
1172{
1173 int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
1174 struct listnode *mnode, *mnnode;
1175 struct bgp *bgp;
1176
1177 if (debug)
1178 zlog_debug("%s: entry", __func__);
1179
1180 if (bm->bgp == NULL) /* may be called during cleanup */
1181 return;
1182
1183 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
1184 vpn_policy_routemap_update(bgp, rmap_name);
1185}
1186
718e3744 1187/* For testing purpose, static route of MPLS-VPN. */
1188DEFUN (vpnv4_network,
1189 vpnv4_network_cmd,
d114b977 1190 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
718e3744 1191 "Specify a network to announce via BGP\n"
0c7b1b01 1192 "IPv4 prefix\n"
718e3744 1193 "Specify Route Distinguisher\n"
1194 "VPN Route Distinguisher\n"
fb1d2a2d
LB
1195 "VPN NLRI label (tag)\n"
1196 "VPN NLRI label (tag)\n"
1197 "Label value\n")
718e3744 1198{
d62a17ae 1199 int idx_ipv4_prefixlen = 1;
1200 int idx_ext_community = 3;
1201 int idx_label = 5;
1202 return bgp_static_set_safi(
1203 AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
1204 argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0,
1205 NULL, NULL, NULL, NULL);
137446f9
LB
1206}
1207
1208DEFUN (vpnv4_network_route_map,
1209 vpnv4_network_route_map_cmd,
d114b977 1210 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map WORD",
137446f9 1211 "Specify a network to announce via BGP\n"
0c7b1b01 1212 "IPv4 prefix\n"
137446f9
LB
1213 "Specify Route Distinguisher\n"
1214 "VPN Route Distinguisher\n"
fb1d2a2d
LB
1215 "VPN NLRI label (tag)\n"
1216 "VPN NLRI label (tag)\n"
1217 "Label value\n"
137446f9
LB
1218 "route map\n"
1219 "route map name\n")
1220{
d62a17ae 1221 int idx_ipv4_prefixlen = 1;
1222 int idx_ext_community = 3;
1223 int idx_label = 5;
1224 int idx_word_2 = 7;
1225 return bgp_static_set_safi(
1226 AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
1227 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1228 argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
718e3744 1229}
1230
1231/* For testing purpose, static route of MPLS-VPN. */
1232DEFUN (no_vpnv4_network,
1233 no_vpnv4_network_cmd,
d114b977 1234 "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
718e3744 1235 NO_STR
1236 "Specify a network to announce via BGP\n"
0c7b1b01 1237 "IPv4 prefix\n"
718e3744 1238 "Specify Route Distinguisher\n"
1239 "VPN Route Distinguisher\n"
fb1d2a2d
LB
1240 "VPN NLRI label (tag)\n"
1241 "VPN NLRI label (tag)\n"
1242 "Label value\n")
718e3744 1243{
d62a17ae 1244 int idx_ipv4_prefixlen = 2;
1245 int idx_ext_community = 4;
1246 int idx_label = 6;
1247 return bgp_static_unset_safi(AFI_IP, SAFI_MPLS_VPN, vty,
1248 argv[idx_ipv4_prefixlen]->arg,
1249 argv[idx_ext_community]->arg,
1250 argv[idx_label]->arg, 0, NULL, NULL, NULL);
718e3744 1251}
1252
c286be96
LX
1253DEFUN (vpnv6_network,
1254 vpnv6_network_cmd,
d114b977 1255 "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map WORD]",
c286be96
LX
1256 "Specify a network to announce via BGP\n"
1257 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1258 "Specify Route Distinguisher\n"
1259 "VPN Route Distinguisher\n"
fb1d2a2d
LB
1260 "VPN NLRI label (tag)\n"
1261 "VPN NLRI label (tag)\n"
1262 "Label value\n"
11daee81
DS
1263 "route map\n"
1264 "route map name\n")
c286be96 1265{
d62a17ae 1266 int idx_ipv6_prefix = 1;
1267 int idx_ext_community = 3;
1268 int idx_label = 5;
1269 int idx_word_2 = 7;
1270 if (argc == 8)
1271 return bgp_static_set_safi(
1272 AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
1273 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1274 argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
1275 else
1276 return bgp_static_set_safi(
1277 AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
1278 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1279 NULL, 0, NULL, NULL, NULL, NULL);
c286be96
LX
1280}
1281
1282/* For testing purpose, static route of MPLS-VPN. */
1283DEFUN (no_vpnv6_network,
1284 no_vpnv6_network_cmd,
d114b977 1285 "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
c286be96
LX
1286 NO_STR
1287 "Specify a network to announce via BGP\n"
1288 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1289 "Specify Route Distinguisher\n"
1290 "VPN Route Distinguisher\n"
fb1d2a2d
LB
1291 "VPN NLRI label (tag)\n"
1292 "VPN NLRI label (tag)\n"
1293 "Label value\n")
c286be96 1294{
d62a17ae 1295 int idx_ipv6_prefix = 2;
1296 int idx_ext_community = 4;
1297 int idx_label = 6;
1298 return bgp_static_unset_safi(AFI_IP6, SAFI_MPLS_VPN, vty,
1299 argv[idx_ipv6_prefix]->arg,
1300 argv[idx_ext_community]->arg,
1301 argv[idx_label]->arg, 0, NULL, NULL, NULL);
c286be96
LX
1302}
1303
d62a17ae 1304int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
1305 enum bgp_show_type type, void *output_arg, int tags,
1306 u_char use_json)
718e3744 1307{
d62a17ae 1308 struct bgp *bgp;
1309 struct bgp_table *table;
d62a17ae 1310
1311 bgp = bgp_get_default();
1312 if (bgp == NULL) {
1313 if (!use_json)
1314 vty_out(vty, "No BGP process is configured\n");
16307668
RW
1315 else
1316 vty_out(vty, "{}\n");
d62a17ae 1317 return CMD_WARNING;
1318 }
1ae44dfc 1319 table = bgp->rib[afi][SAFI_MPLS_VPN];
a4d82a8a
PZ
1320 return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, table, prd, type,
1321 output_arg, use_json);
718e3744 1322}
1323
4f280b15
LB
1324DEFUN (show_bgp_ip_vpn_all_rd,
1325 show_bgp_ip_vpn_all_rd_cmd,
d114b977 1326 "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:NN_OR_IP-ADDRESS:NN] [json]",
e3e29b32
LB
1327 SHOW_STR
1328 BGP_STR
05e588f4 1329 BGP_VPNVX_HELP_STR
e3e29b32 1330 "Display VPN NLRI specific information\n"
af8528fa 1331 "Display VPN NLRI specific information\n"
e3e29b32
LB
1332 "Display information for a route distinguisher\n"
1333 "VPN Route Distinguisher\n"
1334 JSON_STR)
1335{
d62a17ae 1336 int ret;
1337 struct prefix_rd prd;
1338 afi_t afi;
1339 int idx = 0;
1340
1341 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
3d7c4cd7 1342 if (argv_find(argv, argc, "rd", &idx)) {
a4d82a8a 1343 ret = str2prefix_rd(argv[idx + 1]->arg, &prd);
d62a17ae 1344 if (!ret) {
1345 vty_out(vty,
1346 "%% Malformed Route Distinguisher\n");
1347 return CMD_WARNING;
1348 }
1349 return bgp_show_mpls_vpn(vty, afi, &prd,
1350 bgp_show_type_normal, NULL, 0,
1351 use_json(argc, argv));
1352 } else {
1353 return bgp_show_mpls_vpn(vty, afi, NULL,
1354 bgp_show_type_normal, NULL, 0,
1355 use_json(argc, argv));
1356 }
1357 }
1358 return CMD_SUCCESS;
718e3744 1359}
1360
af8528fa
LB
1361ALIAS(show_bgp_ip_vpn_all_rd,
1362 show_bgp_ip_vpn_rd_cmd,
1363 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1364 SHOW_STR
1365 BGP_STR
1366 BGP_VPNVX_HELP_STR
1367 "Display VPN NLRI specific information\n"
1368 "Display information for a route distinguisher\n"
1369 "VPN Route Distinguisher\n"
1370 JSON_STR)
1371
1372#ifdef KEEP_OLD_VPN_COMMANDS
3f227172
PG
1373DEFUN (show_ip_bgp_vpn_rd,
1374 show_ip_bgp_vpn_rd_cmd,
af8528fa 1375 "show ip bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN",
718e3744 1376 SHOW_STR
1377 IP_STR
1378 BGP_STR
4f280b15 1379 BGP_AFI_HELP_STR
3517059b 1380 "Address Family modifier\n"
718e3744 1381 "Display information for a route distinguisher\n"
1382 "VPN Route Distinguisher\n")
1383{
d62a17ae 1384 int idx_ext_community = argc - 1;
1385 int ret;
1386 struct prefix_rd prd;
1387 afi_t afi;
1388 int idx = 0;
1389
1390 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1391 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1392 if (!ret) {
1393 vty_out(vty, "%% Malformed Route Distinguisher\n");
1394 return CMD_WARNING;
1395 }
1396 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
1397 NULL, 0, 0);
1398 }
1399 return CMD_SUCCESS;
1400}
718e3744 1401
4f280b15
LB
1402DEFUN (show_ip_bgp_vpn_all,
1403 show_ip_bgp_vpn_all_cmd,
1404 "show [ip] bgp <vpnv4|vpnv6>",
1405 SHOW_STR
1406 IP_STR
1407 BGP_STR
1408 BGP_VPNVX_HELP_STR)
1409{
d62a17ae 1410 afi_t afi;
1411 int idx = 0;
4f280b15 1412
d62a17ae 1413 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
1414 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
1415 NULL, 0, 0);
1416 return CMD_SUCCESS;
4f280b15
LB
1417}
1418
3f227172
PG
1419DEFUN (show_ip_bgp_vpn_all_tags,
1420 show_ip_bgp_vpn_all_tags_cmd,
1421 "show [ip] bgp <vpnv4|vpnv6> all tags",
718e3744 1422 SHOW_STR
1423 IP_STR
1424 BGP_STR
3f227172
PG
1425 BGP_VPNVX_HELP_STR
1426 "Display information about all VPNv4/VPNV6 NLRIs\n"
718e3744 1427 "Display BGP tags for prefixes\n")
1428{
d62a17ae 1429 afi_t afi;
1430 int idx = 0;
3f227172 1431
d62a17ae 1432 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
1433 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
1434 NULL, 1, 0);
1435 return CMD_SUCCESS;
718e3744 1436}
1437
3f227172
PG
1438DEFUN (show_ip_bgp_vpn_rd_tags,
1439 show_ip_bgp_vpn_rd_tags_cmd,
d114b977 1440 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN tags",
718e3744 1441 SHOW_STR
1442 IP_STR
1443 BGP_STR
3f227172 1444 BGP_VPNVX_HELP_STR
718e3744 1445 "Display information for a route distinguisher\n"
1446 "VPN Route Distinguisher\n"
1447 "Display BGP tags for prefixes\n")
1448{
d62a17ae 1449 int idx_ext_community = 5;
1450 int ret;
1451 struct prefix_rd prd;
1452 afi_t afi;
1453 int idx = 0;
1454
1455 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1456 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1457 if (!ret) {
1458 vty_out(vty, "%% Malformed Route Distinguisher\n");
1459 return CMD_WARNING;
1460 }
1461 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
1462 NULL, 1, 0);
1463 }
1464 return CMD_SUCCESS;
718e3744 1465}
1466
3f227172
PG
1467DEFUN (show_ip_bgp_vpn_all_neighbor_routes,
1468 show_ip_bgp_vpn_all_neighbor_routes_cmd,
1469 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
718e3744 1470 SHOW_STR
1471 IP_STR
1472 BGP_STR
3f227172
PG
1473 BGP_VPNVX_HELP_STR
1474 "Display information about all VPNv4/VPNv6 NLRIs\n"
718e3744 1475 "Detailed information on TCP and BGP neighbor connections\n"
1476 "Neighbor to display information about\n"
856ca177 1477 "Display routes learned from neighbor\n"
9973d184 1478 JSON_STR)
718e3744 1479{
d62a17ae 1480 int idx_ipv4 = 6;
1481 union sockunion su;
1482 struct peer *peer;
1483 int ret;
1484 u_char uj = use_json(argc, argv);
1485 afi_t afi;
1486 int idx = 0;
1487
1488 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1489 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1490 if (ret < 0) {
1491 if (uj) {
1492 json_object *json_no = NULL;
1493 json_no = json_object_new_object();
1494 json_object_string_add(json_no, "warning",
1495 "Malformed address");
1496 vty_out(vty, "%s\n",
1497 json_object_to_json_string(json_no));
1498 json_object_free(json_no);
1499 } else
1500 vty_out(vty, "Malformed address: %s\n",
1501 argv[idx_ipv4]->arg);
1502 return CMD_WARNING;
1503 }
1504
1505 peer = peer_lookup(NULL, &su);
1506 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1507 if (uj) {
1508 json_object *json_no = NULL;
1509 json_no = json_object_new_object();
1510 json_object_string_add(
1511 json_no, "warning",
1512 "No such neighbor or address family");
1513 vty_out(vty, "%s\n",
1514 json_object_to_json_string(json_no));
1515 json_object_free(json_no);
1516 } else
1517 vty_out(vty,
1518 "%% No such neighbor or address family\n");
1519 return CMD_WARNING;
1520 }
1521
1522 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor,
1523 &su, 0, uj);
1524 }
1525 return CMD_SUCCESS;
718e3744 1526}
1527
3f227172
PG
1528DEFUN (show_ip_bgp_vpn_rd_neighbor_routes,
1529 show_ip_bgp_vpn_rd_neighbor_routes_cmd,
d114b977 1530 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
718e3744 1531 SHOW_STR
1532 IP_STR
1533 BGP_STR
3f227172 1534 BGP_VPNVX_HELP_STR
718e3744 1535 "Display information for a route distinguisher\n"
1536 "VPN Route Distinguisher\n"
1537 "Detailed information on TCP and BGP neighbor connections\n"
1538 "Neighbor to display information about\n"
856ca177 1539 "Display routes learned from neighbor\n"
9973d184 1540 JSON_STR)
718e3744 1541{
d62a17ae 1542 int idx_ext_community = 5;
1543 int idx_ipv4 = 7;
1544 int ret;
1545 union sockunion su;
1546 struct peer *peer;
1547 struct prefix_rd prd;
1548 u_char uj = use_json(argc, argv);
1549 afi_t afi;
1550 int idx = 0;
1551
1552 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1553 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1554 if (!ret) {
1555 if (uj) {
1556 json_object *json_no = NULL;
1557 json_no = json_object_new_object();
1558 json_object_string_add(
1559 json_no, "warning",
1560 "Malformed Route Distinguisher");
1561 vty_out(vty, "%s\n",
1562 json_object_to_json_string(json_no));
1563 json_object_free(json_no);
1564 } else
1565 vty_out(vty,
1566 "%% Malformed Route Distinguisher\n");
1567 return CMD_WARNING;
1568 }
1569
1570 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1571 if (ret < 0) {
1572 if (uj) {
1573 json_object *json_no = NULL;
1574 json_no = json_object_new_object();
1575 json_object_string_add(json_no, "warning",
1576 "Malformed address");
1577 vty_out(vty, "%s\n",
1578 json_object_to_json_string(json_no));
1579 json_object_free(json_no);
1580 } else
1581 vty_out(vty, "Malformed address: %s\n",
1582 argv[idx_ext_community]->arg);
1583 return CMD_WARNING;
1584 }
1585
1586 peer = peer_lookup(NULL, &su);
1587 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1588 if (uj) {
1589 json_object *json_no = NULL;
1590 json_no = json_object_new_object();
1591 json_object_string_add(
1592 json_no, "warning",
1593 "No such neighbor or address family");
1594 vty_out(vty, "%s\n",
1595 json_object_to_json_string(json_no));
1596 json_object_free(json_no);
1597 } else
1598 vty_out(vty,
1599 "%% No such neighbor or address family\n");
1600 return CMD_WARNING;
1601 }
1602
1603 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_neighbor,
1604 &su, 0, uj);
1605 }
1606 return CMD_SUCCESS;
718e3744 1607}
1608
3f227172
PG
1609DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes,
1610 show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd,
1611 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
718e3744 1612 SHOW_STR
1613 IP_STR
1614 BGP_STR
3f227172
PG
1615 BGP_VPNVX_HELP_STR
1616 "Display information about all VPNv4/VPNv6 NLRIs\n"
718e3744 1617 "Detailed information on TCP and BGP neighbor connections\n"
1618 "Neighbor to display information about\n"
856ca177 1619 "Display the routes advertised to a BGP neighbor\n"
9973d184 1620 JSON_STR)
718e3744 1621{
d62a17ae 1622 int idx_ipv4 = 6;
1623 int ret;
1624 struct peer *peer;
1625 union sockunion su;
1626 u_char uj = use_json(argc, argv);
1627 afi_t afi;
1628 int idx = 0;
1629
1630 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1631 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1632 if (ret < 0) {
1633 if (uj) {
1634 json_object *json_no = NULL;
1635 json_no = json_object_new_object();
1636 json_object_string_add(json_no, "warning",
1637 "Malformed address");
1638 vty_out(vty, "%s\n",
1639 json_object_to_json_string(json_no));
1640 json_object_free(json_no);
1641 } else
1642 vty_out(vty, "Malformed address: %s\n",
1643 argv[idx_ipv4]->arg);
1644 return CMD_WARNING;
1645 }
1646 peer = peer_lookup(NULL, &su);
1647 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1648 if (uj) {
1649 json_object *json_no = NULL;
1650 json_no = json_object_new_object();
1651 json_object_string_add(
1652 json_no, "warning",
1653 "No such neighbor or address family");
1654 vty_out(vty, "%s\n",
1655 json_object_to_json_string(json_no));
1656 json_object_free(json_no);
1657 } else
1658 vty_out(vty,
1659 "%% No such neighbor or address family\n");
1660 return CMD_WARNING;
1661 }
1662 return show_adj_route_vpn(vty, peer, NULL, AFI_IP,
1663 SAFI_MPLS_VPN, uj);
1664 }
1665 return CMD_SUCCESS;
718e3744 1666}
1667
3f227172
PG
1668DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes,
1669 show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd,
d114b977 1670 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
718e3744 1671 SHOW_STR
1672 IP_STR
1673 BGP_STR
3f227172 1674 BGP_VPNVX_HELP_STR
718e3744 1675 "Display information for a route distinguisher\n"
1676 "VPN Route Distinguisher\n"
1677 "Detailed information on TCP and BGP neighbor connections\n"
1678 "Neighbor to display information about\n"
856ca177 1679 "Display the routes advertised to a BGP neighbor\n"
9973d184 1680 JSON_STR)
718e3744 1681{
d62a17ae 1682 int idx_ext_community = 5;
1683 int idx_ipv4 = 7;
1684 int ret;
1685 struct peer *peer;
1686 struct prefix_rd prd;
1687 union sockunion su;
1688 u_char uj = use_json(argc, argv);
1689 afi_t afi;
1690 int idx = 0;
1691
1692 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
1693 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1694 if (ret < 0) {
1695 if (uj) {
1696 json_object *json_no = NULL;
1697 json_no = json_object_new_object();
1698 json_object_string_add(json_no, "warning",
1699 "Malformed address");
1700 vty_out(vty, "%s\n",
1701 json_object_to_json_string(json_no));
1702 json_object_free(json_no);
1703 } else
1704 vty_out(vty, "Malformed address: %s\n",
1705 argv[idx_ext_community]->arg);
1706 return CMD_WARNING;
1707 }
1708 peer = peer_lookup(NULL, &su);
1709 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
1710 if (uj) {
1711 json_object *json_no = NULL;
1712 json_no = json_object_new_object();
1713 json_object_string_add(
1714 json_no, "warning",
1715 "No such neighbor or address family");
1716 vty_out(vty, "%s\n",
1717 json_object_to_json_string(json_no));
1718 json_object_free(json_no);
1719 } else
1720 vty_out(vty,
1721 "%% No such neighbor or address family\n");
1722 return CMD_WARNING;
1723 }
1724
1725 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1726 if (!ret) {
1727 if (uj) {
1728 json_object *json_no = NULL;
1729 json_no = json_object_new_object();
1730 json_object_string_add(
1731 json_no, "warning",
1732 "Malformed Route Distinguisher");
1733 vty_out(vty, "%s\n",
1734 json_object_to_json_string(json_no));
1735 json_object_free(json_no);
1736 } else
1737 vty_out(vty,
1738 "%% Malformed Route Distinguisher\n");
1739 return CMD_WARNING;
1740 }
1741
1742 return show_adj_route_vpn(vty, peer, &prd, AFI_IP,
1743 SAFI_MPLS_VPN, uj);
1744 }
1745 return CMD_SUCCESS;
718e3744 1746}
d6902373 1747#endif /* KEEP_OLD_VPN_COMMANDS */
718e3744 1748
d62a17ae 1749void bgp_mplsvpn_init(void)
718e3744 1750{
d62a17ae 1751 install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd);
1752 install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
1753 install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
718e3744 1754
d62a17ae 1755 install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd);
1756 install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd);
c286be96 1757
d62a17ae 1758 install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd);
af8528fa 1759 install_element(VIEW_NODE, &show_bgp_ip_vpn_rd_cmd);
d6902373 1760#ifdef KEEP_OLD_VPN_COMMANDS
af8528fa 1761 install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd);
d62a17ae 1762 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd);
1763 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd);
1764 install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd);
1765 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd);
1766 install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd);
1767 install_element(VIEW_NODE,
1768 &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd);
1769 install_element(VIEW_NODE,
1770 &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd);
d6902373 1771#endif /* KEEP_OLD_VPN_COMMANDS */
718e3744 1772}