2 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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
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.
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
34 #include "bgpd/bgpd.h"
35 #include "bgpd/bgp_debug.h"
36 #include "bgpd/bgp_table.h"
37 #include "bgpd/bgp_route.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_label.h"
40 #include "bgpd/bgp_mplsvpn.h"
41 #include "bgpd/bgp_packet.h"
42 #include "bgpd/bgp_vty.h"
43 #include "bgpd/bgp_vpn.h"
44 #include "bgpd/bgp_ecommunity.h"
45 #include "bgpd/bgp_zebra.h"
46 #include "bgpd/bgp_nexthop.h"
49 #include "bgpd/rfapi/rfapi_backend.h"
53 * Definitions and external declarations.
55 extern struct zclient
*zclient
;
57 extern int argv_find_and_parse_vpnvx(struct cmd_token
**argv
, int argc
,
58 int *index
, afi_t
*afi
)
61 if (argv_find(argv
, argc
, "vpnv4", index
)) {
65 } else if (argv_find(argv
, argc
, "vpnv6", index
)) {
73 u_int32_t
decode_label(mpls_label_t
*label_pnt
)
76 u_char
*pnt
= (u_char
*)label_pnt
;
78 l
= ((u_int32_t
)*pnt
++ << 12);
79 l
|= (u_int32_t
)*pnt
++ << 4;
80 l
|= (u_int32_t
)((*pnt
& 0xf0) >> 4);
84 void encode_label(mpls_label_t label
, mpls_label_t
*label_pnt
)
86 u_char
*pnt
= (u_char
*)label_pnt
;
89 *pnt
++ = (label
>> 12) & 0xff;
90 *pnt
++ = (label
>> 4) & 0xff;
91 *pnt
++ = ((label
<< 4) + 1) & 0xff; /* S=1 */
94 int bgp_nlri_parse_vpn(struct peer
*peer
, struct attr
*attr
,
95 struct bgp_nlri
*packet
)
105 struct prefix_rd prd
;
106 mpls_label_t label
= {0};
110 u_int32_t addpath_id
;
113 prd
.family
= AF_UNSPEC
;
117 lim
= pnt
+ packet
->length
;
123 (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
124 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
125 PEER_CAP_ADDPATH_AF_TX_RCV
));
127 #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
128 for (; pnt
< lim
; pnt
+= psize
) {
129 /* Clear prefix structure. */
130 memset(&p
, 0, sizeof(struct prefix
));
132 if (addpath_encoded
) {
134 /* When packet overflow occurs return immediately. */
135 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
138 addpath_id
= ntohl(*((uint32_t *)pnt
));
139 pnt
+= BGP_ADDPATH_ID_LEN
;
142 /* Fetch prefix length. */
144 p
.family
= afi2family(packet
->afi
);
145 psize
= PSIZE(prefixlen
);
147 if (prefixlen
< VPN_PREFIXLEN_MIN_BYTES
* 8) {
149 "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
150 peer
->host
, prefixlen
);
154 /* sanity check against packet data */
155 if ((pnt
+ psize
) > lim
) {
157 "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
158 peer
->host
, prefixlen
, (uint
)(lim
- pnt
));
162 /* sanity check against storage for the IP address portion */
163 if ((psize
- VPN_PREFIXLEN_MIN_BYTES
) > (ssize_t
)sizeof(p
.u
)) {
165 "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
167 prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8,
172 /* Sanity check against max bitlen of the address family */
173 if ((psize
- VPN_PREFIXLEN_MIN_BYTES
) > prefix_blen(&p
)) {
175 "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
177 prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8,
178 p
.family
, prefix_blen(&p
));
182 /* Copy label to prefix. */
183 memcpy(&label
, pnt
, BGP_LABEL_BYTES
);
184 bgp_set_valid_label(&label
);
186 /* Copy routing distinguisher to rd. */
187 memcpy(&prd
.val
, pnt
+ BGP_LABEL_BYTES
, 8);
189 /* Decode RD type. */
190 type
= decode_rd_type(pnt
+ BGP_LABEL_BYTES
);
194 decode_rd_as(pnt
+ 5, &rd_as
);
198 decode_rd_as4(pnt
+ 5, &rd_as
);
202 decode_rd_ip(pnt
+ 5, &rd_ip
);
206 case RD_TYPE_VNC_ETH
:
211 zlog_err("Unknown RD type %d", type
);
212 break; /* just report */
217 - VPN_PREFIXLEN_MIN_BYTES
* 8; /* exclude label & RD */
218 memcpy(&p
.u
.prefix
, pnt
+ VPN_PREFIXLEN_MIN_BYTES
,
219 psize
- VPN_PREFIXLEN_MIN_BYTES
);
222 bgp_update(peer
, &p
, addpath_id
, attr
, packet
->afi
,
223 SAFI_MPLS_VPN
, ZEBRA_ROUTE_BGP
,
224 BGP_ROUTE_NORMAL
, &prd
, &label
, 1, 0, NULL
);
226 bgp_withdraw(peer
, &p
, addpath_id
, attr
, packet
->afi
,
227 SAFI_MPLS_VPN
, ZEBRA_ROUTE_BGP
,
228 BGP_ROUTE_NORMAL
, &prd
, &label
, 1, NULL
);
231 /* Packet length consistency check. */
234 "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
235 peer
->host
, lim
- pnt
);
240 #undef VPN_PREFIXLEN_MIN_BYTES
244 * This function informs zebra of the label this vrf sets on routes
245 * leaked to VPN. Zebra should install this label in the kernel with
246 * an action of "pop label and then use this vrf's IP FIB to route the PDU."
248 * Sending this vrf-label association is qualified by a) whether vrf->vpn
249 * exporting is active ("export vpn" is enabled, vpn-policy RD and RT list
250 * are set) and b) whether vpn-policy label is set.
252 * If any of these conditions do not hold, then we send MPLS_LABEL_NONE
253 * for this vrf, which zebra interprets to mean "delete this vrf-label
256 void vpn_leak_zebra_vrf_label_update(struct bgp
*bgp
, afi_t afi
)
258 mpls_label_t label
= MPLS_LABEL_NONE
;
259 const char *name
= "default";
260 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
262 if (debug
&& (bgp
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
)) {
266 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
269 "%s: vrf %s: afi %s: vrf_id not set, "
270 "can't set zebra vrf label",
271 __func__
, name
, afi2str(afi
));
276 if (vpn_leak_to_vpn_active(bgp
, afi
, NULL
)) {
277 label
= bgp
->vpn_policy
[afi
].tovpn_label
;
281 zlog_debug("%s: vrf %s: afi %s: setting label %d for vrf id %d",
282 __func__
, name
, afi2str(afi
), label
, bgp
->vrf_id
);
285 zclient_send_vrf_label(zclient
, bgp
->vrf_id
, afi
, label
, ZEBRA_LSP_BGP
);
286 bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_label_last_sent
= label
;
290 * If zebra tells us vrf has become unconfigured, tell zebra not to
291 * use this label to forward to the vrf anymore
293 void vpn_leak_zebra_vrf_label_withdraw(struct bgp
*bgp
, afi_t afi
)
295 mpls_label_t label
= MPLS_LABEL_NONE
;
296 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
298 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
301 "%s: vrf_id not set, can't delete zebra vrf label",
308 zlog_debug("%s: deleting label for vrf %s (id=%d)", __func__
,
309 (bgp
->name
? bgp
->name
: "default"), bgp
->vrf_id
);
312 zclient_send_vrf_label(zclient
, bgp
->vrf_id
, afi
, label
, ZEBRA_LSP_BGP
);
313 bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_label_last_sent
= label
;
316 static int ecom_intersect(struct ecommunity
*e1
, struct ecommunity
*e2
)
324 for (i
= 0; i
< e1
->size
; ++i
) {
325 for (j
= 0; j
< e2
->size
; ++j
) {
326 if (!memcmp(e1
->val
+ (i
* ECOMMUNITY_SIZE
),
327 e2
->val
+ (j
* ECOMMUNITY_SIZE
),
338 * returns pointer to new bgp_info upon success
340 static struct bgp_info
*
341 leak_update(struct bgp
*bgp
, /* destination bgp instance */
342 struct bgp_node
*bn
, struct attr
*new_attr
, /* already interned */
343 afi_t afi
, safi_t safi
, struct bgp_info
*source_bi
, u_char type
,
344 u_char sub_type
, mpls_label_t
*label
, int num_labels
, void *parent
,
345 struct bgp
*bgp_orig
, struct prefix
*nexthop_orig
, int debug
)
347 struct prefix
*p
= &bn
->p
;
349 struct bgp_info
*new;
350 char buf_prefix
[PREFIX_STRLEN
];
351 const char *pDestInstanceName
= "default";
354 prefix2str(&bn
->p
, buf_prefix
, sizeof(buf_prefix
));
356 pDestInstanceName
= bgp
->name
;
362 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
363 if (bi
->extra
&& bi
->extra
->parent
== parent
)
368 if (attrhash_cmp(bi
->attr
, new_attr
)
369 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
371 bgp_attr_unintern(&new_attr
);
374 "%s: ->%s: %s: Found route, no change",
375 __func__
, pDestInstanceName
,
380 /* attr is changed */
381 bgp_info_set_flag(bn
, bi
, BGP_INFO_ATTR_CHANGED
);
383 /* Rewrite BGP route information. */
384 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
385 bgp_info_restore(bn
, bi
);
387 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
388 bgp_attr_unintern(&bi
->attr
);
390 bi
->uptime
= bgp_clock();
392 /* Process change. */
393 bgp_aggregate_increment(bgp
, p
, bi
, afi
, safi
);
394 bgp_process(bgp
, bn
, afi
, safi
);
398 zlog_debug("%s: ->%s: %s Found route, changed attr",
399 __func__
, pDestInstanceName
, buf_prefix
);
404 new = info_make(type
, sub_type
, 0, bgp
->peer_self
, new_attr
, bn
);
405 SET_FLAG(new->flags
, BGP_INFO_VALID
);
407 bgp_info_extra_get(new);
411 for (i
= 0; i
< num_labels
; ++i
) {
412 new->extra
->label
[i
] = label
[i
];
413 if (!bgp_is_valid_label(&label
[i
])) {
416 "%s: %s: marking label %d valid",
417 __func__
, buf_prefix
, i
);
419 bgp_set_valid_label(&new->extra
->label
[i
]);
422 new->extra
->num_labels
= num_labels
;
424 new->extra
->parent
= parent
;
427 new->extra
->bgp_orig
= bgp_orig
;
429 new->extra
->nexthop_orig
= *nexthop_orig
;
431 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
432 bgp_info_add(bn
, new);
435 bgp_process(bgp
, bn
, afi
, safi
);
438 zlog_debug("%s: ->%s: %s: Added new route", __func__
,
439 pDestInstanceName
, buf_prefix
);
444 /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
445 void vpn_leak_from_vrf_update(struct bgp
*bgp_vpn
, /* to */
446 struct bgp
*bgp_vrf
, /* from */
447 struct bgp_info
*info_vrf
) /* route */
449 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
450 struct prefix
*p
= &info_vrf
->net
->p
;
451 afi_t afi
= family2afi(p
->family
);
452 struct attr static_attr
= {0};
453 struct attr
*new_attr
= NULL
;
454 safi_t safi
= SAFI_MPLS_VPN
;
455 mpls_label_t label_val
;
458 const char *debugmsg
;
463 if (info_vrf
->attr
&& info_vrf
->attr
->ecommunity
) {
464 s
= ecommunity_ecom2str(info_vrf
->attr
->ecommunity
,
465 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
468 zlog_debug("%s: info_vrf->type=%d, EC{%s}", __func__
,
477 zlog_debug("%s: can't get afi of prefix", __func__
);
482 if (info_vrf
->extra
&& info_vrf
->extra
->bgp_orig
== bgp_vpn
)
486 if (!vpn_leak_to_vpn_active(bgp_vrf
, afi
, &debugmsg
)) {
488 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
492 bgp_attr_dup(&static_attr
, info_vrf
->attr
); /* shallow copy */
497 if (bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
]) {
498 struct bgp_info info
;
499 route_map_result_t ret
;
501 memset(&info
, 0, sizeof(info
));
502 info
.peer
= bgp_vpn
->peer_self
;
503 info
.attr
= &static_attr
;
504 ret
= route_map_apply(
505 bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
],
507 if (RMAP_DENYMATCH
== ret
) {
508 bgp_attr_flush(&static_attr
); /* free any added parts */
511 "%s: vrf %s route map \"%s\" says DENY, returning",
512 __func__
, bgp_vrf
->name
,
513 bgp_vrf
->vpn_policy
[afi
]
514 .rmap
[BGP_VPN_POLICY_DIR_TOVPN
]
523 if (static_attr
.ecommunity
) {
524 s
= ecommunity_ecom2str(static_attr
.ecommunity
,
525 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
527 zlog_debug("%s: post route map static_attr.ecommunity{%s}",
532 * Add the vpn-policy rt-list
534 struct ecommunity
*old_ecom
;
535 struct ecommunity
*new_ecom
;
537 old_ecom
= static_attr
.ecommunity
;
539 new_ecom
= ecommunity_merge(
540 ecommunity_dup(old_ecom
),
541 bgp_vrf
->vpn_policy
[afi
]
542 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]);
543 if (!old_ecom
->refcnt
)
544 ecommunity_free(&old_ecom
);
546 new_ecom
= ecommunity_dup(
547 bgp_vrf
->vpn_policy
[afi
]
548 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]);
550 static_attr
.ecommunity
= new_ecom
;
551 SET_FLAG(static_attr
.flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
556 if (static_attr
.ecommunity
) {
557 s
= ecommunity_ecom2str(static_attr
.ecommunity
,
558 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
560 zlog_debug("%s: post merge static_attr.ecommunity{%s}",
565 /* if policy nexthop not set, use 0 */
566 if (CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
567 BGP_VPN_POLICY_TOVPN_NEXTHOP_SET
)) {
569 struct prefix
*nexthop
=
570 &bgp_vrf
->vpn_policy
[afi
].tovpn_nexthop
;
571 switch (nexthop
->family
) {
573 /* prevent mp_nexthop_global_in <- self in bgp_route.c
575 static_attr
.nexthop
.s_addr
= nexthop
->u
.prefix4
.s_addr
;
577 static_attr
.mp_nexthop_global_in
= nexthop
->u
.prefix4
;
578 static_attr
.mp_nexthop_len
= 4;
582 static_attr
.mp_nexthop_global
= nexthop
->u
.prefix6
;
583 static_attr
.mp_nexthop_len
= 16;
594 static_attr
.mp_nexthop_global_in
.s_addr
= 0;
595 static_attr
.mp_nexthop_len
= 4;
596 static_attr
.nexthop
.s_addr
= 0; /* self */
597 static_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
602 memset(&static_attr
.mp_nexthop_global
, 0,
603 sizeof(static_attr
.mp_nexthop_global
));
604 static_attr
.mp_nexthop_len
= 16; /* bytes */
609 label_val
= bgp_vrf
->vpn_policy
[afi
].tovpn_label
;
610 if (label_val
== MPLS_LABEL_NONE
) {
611 /* TBD get from label manager */
612 label
= MPLS_LABEL_IMPLICIT_NULL
;
614 encode_label(label_val
, &label
);
617 /* Set originator ID to "me" */
618 SET_FLAG(static_attr
.flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
));
619 static_attr
.originator_id
= bgp_vpn
->router_id
;
622 new_attr
= bgp_attr_intern(
623 &static_attr
); /* hashed refcounted everything */
624 bgp_attr_flush(&static_attr
); /* free locally-allocated parts */
626 if (debug
&& new_attr
->ecommunity
) {
627 char *s
= ecommunity_ecom2str(new_attr
->ecommunity
,
628 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
630 zlog_debug("%s: new_attr->ecommunity{%s}", __func__
, s
);
631 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
634 /* Now new_attr is an allocated interned attr */
636 bn
= bgp_afi_node_get(bgp_vpn
->rib
[afi
][safi
], afi
, safi
, p
,
637 &(bgp_vrf
->vpn_policy
[afi
].tovpn_rd
));
639 struct bgp_info
*new_info
;
641 new_info
= leak_update(bgp_vpn
, bn
, new_attr
, afi
, safi
, info_vrf
,
642 ZEBRA_ROUTE_BGP
, BGP_ROUTE_IMPORTED
, &label
, 1,
643 info_vrf
, bgp_vrf
, NULL
, debug
);
646 * Routes actually installed in the vpn RIB must also be
647 * offered to all vrfs (because now they originate from
650 * Acceptance into other vrfs depends on rt-lists.
651 * Originating vrf will not accept the looped back route
652 * because of loop checking.
655 vpn_leak_to_vrf_update(bgp_vrf
, new_info
);
658 void vpn_leak_from_vrf_withdraw(struct bgp
*bgp_vpn
, /* to */
659 struct bgp
*bgp_vrf
, /* from */
660 struct bgp_info
*info_vrf
) /* route */
662 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
663 struct prefix
*p
= &info_vrf
->net
->p
;
664 afi_t afi
= family2afi(p
->family
);
665 safi_t safi
= SAFI_MPLS_VPN
;
668 const char *debugmsg
;
670 if (info_vrf
->type
!= ZEBRA_ROUTE_BGP
) {
672 zlog_debug("%s: wrong type %d", __func__
,
676 if (info_vrf
->sub_type
!= BGP_ROUTE_NORMAL
677 && info_vrf
->sub_type
!= BGP_ROUTE_STATIC
) {
680 zlog_debug("%s: wrong sub_type %d", __func__
,
689 zlog_debug("%s: can't get afi of prefix", __func__
);
693 if (!vpn_leak_to_vpn_active(bgp_vrf
, afi
, &debugmsg
)) {
695 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
700 zlog_debug("%s: withdrawing (info_vrf=%p)", __func__
, info_vrf
);
702 bn
= bgp_afi_node_get(bgp_vpn
->rib
[afi
][safi
], afi
, safi
, p
,
703 &(bgp_vrf
->vpn_policy
[afi
].tovpn_rd
));
707 * match original bi imported from
709 for (bi
= (bn
? bn
->info
: NULL
); bi
; bi
= bi
->next
) {
710 if (bi
->extra
&& bi
->extra
->parent
== info_vrf
) {
716 /* withdraw from looped vrfs as well */
717 vpn_leak_to_vrf_withdraw(bgp_vpn
, bi
);
719 bgp_aggregate_decrement(bgp_vpn
, p
, bi
, afi
, safi
);
720 bgp_info_delete(bn
, bi
);
721 bgp_process(bgp_vpn
, bn
, afi
, safi
);
726 void vpn_leak_from_vrf_withdraw_all(struct bgp
*bgp_vpn
, /* to */
727 struct bgp
*bgp_vrf
, /* from */
730 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
731 struct bgp_node
*prn
;
732 safi_t safi
= SAFI_MPLS_VPN
;
735 * Walk vpn table, delete bi with bgp_orig == bgp_vrf
737 for (prn
= bgp_table_top(bgp_vpn
->rib
[afi
][safi
]); prn
;
738 prn
= bgp_route_next(prn
)) {
740 struct bgp_table
*table
;
744 /* This is the per-RD table of prefixes */
750 for (bn
= bgp_table_top(table
); bn
; bn
= bgp_route_next(bn
)) {
752 char buf
[PREFIX2STR_BUFFER
];
754 if (debug
&& bn
->info
) {
756 "%s: looking at prefix %s", __func__
,
757 prefix2str(&bn
->p
, buf
, sizeof(buf
)));
760 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
762 zlog_debug("%s: type %d, sub_type %d",
765 if (bi
->sub_type
!= BGP_ROUTE_IMPORTED
)
769 if ((struct bgp
*)bi
->extra
->bgp_orig
773 zlog_debug("%s: deleting it\n",
775 bgp_aggregate_decrement(bgp_vpn
, &bn
->p
,
777 bgp_info_delete(bn
, bi
);
778 bgp_process(bgp_vpn
, bn
, afi
, safi
);
785 void vpn_leak_from_vrf_update_all(struct bgp
*bgp_vpn
, /* to */
786 struct bgp
*bgp_vrf
, /* from */
791 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
794 zlog_debug("%s: entry, afi=%d, vrf=%s", __func__
, afi
,
797 for (bn
= bgp_table_top(bgp_vrf
->rib
[afi
][SAFI_UNICAST
]); bn
;
798 bn
= bgp_route_next(bn
)) {
801 zlog_debug("%s: node=%p", __func__
, bn
);
803 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
806 "%s: calling vpn_leak_from_vrf_update",
808 vpn_leak_from_vrf_update(bgp_vpn
, bgp_vrf
, bi
);
813 static void vpn_leak_to_vrf_update_onevrf(struct bgp
*bgp_vrf
, /* to */
814 struct bgp
*bgp_vpn
, /* from */
815 struct bgp_info
*info_vpn
) /* route */
817 struct prefix
*p
= &info_vpn
->net
->p
;
818 afi_t afi
= family2afi(p
->family
);
820 struct attr static_attr
= {0};
821 struct attr
*new_attr
= NULL
;
823 safi_t safi
= SAFI_UNICAST
;
824 const char *debugmsg
;
825 struct prefix nexthop_orig
;
826 mpls_label_t
*pLabels
= NULL
;
829 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
831 if (!vpn_leak_from_vpn_active(bgp_vrf
, afi
, &debugmsg
)) {
833 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
837 /* Check for intersection of route targets */
839 bgp_vrf
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
840 info_vpn
->attr
->ecommunity
)) {
846 zlog_debug("%s: updating to vrf %s", __func__
, bgp_vrf
->name
);
848 bgp_attr_dup(&static_attr
, info_vpn
->attr
); /* shallow copy */
851 * Nexthop: stash and clear
853 * Nexthop is valid in context of VPN core, but not in destination vrf.
854 * Stash it for later label resolution by vrf ingress path and then
855 * overwrite with 0, i.e., "me", for the sake of vrf advertisement.
857 uint8_t nhfamily
= NEXTHOP_FAMILY(info_vpn
->attr
->mp_nexthop_len
);
859 memset(&nexthop_orig
, 0, sizeof(nexthop_orig
));
860 nexthop_orig
.family
= nhfamily
;
866 nexthop_orig
.u
.prefix4
= info_vpn
->attr
->mp_nexthop_global_in
;
867 nexthop_orig
.prefixlen
= 32;
869 static_attr
.nexthop
.s_addr
= 0; /* self */
870 static_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
876 nexthop_orig
.u
.prefix6
= info_vpn
->attr
->mp_nexthop_global
;
877 nexthop_orig
.prefixlen
= 128;
879 memset(&static_attr
.mp_nexthop_global
, 0,
880 sizeof(static_attr
.mp_nexthop_global
)); /* clear */
881 static_attr
.mp_nexthop_len
= 16; /* bytes */
889 if (bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
890 struct bgp_info info
;
891 route_map_result_t ret
;
893 memset(&info
, 0, sizeof(info
));
894 info
.peer
= bgp_vrf
->peer_self
;
895 info
.attr
= &static_attr
;
896 ret
= route_map_apply(bgp_vrf
->vpn_policy
[afi
]
897 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
],
899 if (RMAP_DENYMATCH
== ret
) {
900 bgp_attr_flush(&static_attr
); /* free any added parts */
903 "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning",
904 __func__
, bgp_vrf
->name
,
905 bgp_vrf
->vpn_policy
[afi
]
906 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]
912 new_attr
= bgp_attr_intern(&static_attr
);
913 bgp_attr_flush(&static_attr
);
915 bn
= bgp_afi_node_get(bgp_vrf
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
918 * ensure labels are copied
920 if (info_vpn
->extra
&& info_vpn
->extra
->num_labels
) {
921 num_labels
= info_vpn
->extra
->num_labels
;
922 if (num_labels
> BGP_MAX_LABELS
)
923 num_labels
= BGP_MAX_LABELS
;
924 pLabels
= info_vpn
->extra
->label
;
927 char buf_prefix
[PREFIX_STRLEN
];
928 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
929 zlog_debug("%s: pfx %s: num_labels %d", __func__
, buf_prefix
,
933 leak_update(bgp_vrf
, bn
, new_attr
, afi
, safi
, info_vpn
, ZEBRA_ROUTE_BGP
,
934 BGP_ROUTE_IMPORTED
, pLabels
, num_labels
,
935 info_vpn
, /* parent */
936 bgp_vpn
, &nexthop_orig
, debug
);
939 void vpn_leak_to_vrf_update(struct bgp
*bgp_vpn
, /* from */
940 struct bgp_info
*info_vpn
) /* route */
942 struct listnode
*mnode
, *mnnode
;
945 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
948 zlog_debug("%s: start (info_vpn=%p)", __func__
, info_vpn
);
951 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
954 || info_vpn
->extra
->bgp_orig
!= bgp
) { /* no loop */
955 vpn_leak_to_vrf_update_onevrf(bgp
, bgp_vpn
, info_vpn
);
960 void vpn_leak_to_vrf_withdraw(struct bgp
*bgp_vpn
, /* from */
961 struct bgp_info
*info_vpn
) /* route */
963 struct prefix
*p
= &info_vpn
->net
->p
;
964 afi_t afi
= family2afi(p
->family
);
965 safi_t safi
= SAFI_UNICAST
;
967 struct listnode
*mnode
, *mnnode
;
970 const char *debugmsg
;
972 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
975 zlog_debug("%s: start (info_vpn=%p)", __func__
, info_vpn
);
979 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
980 if (!vpn_leak_from_vpn_active(bgp
, afi
, &debugmsg
)) {
982 zlog_debug("%s: skipping: %s", __func__
,
987 /* Check for intersection of route targets */
988 if (!ecom_intersect(bgp
->vpn_policy
[afi
]
989 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
990 info_vpn
->attr
->ecommunity
)) {
996 zlog_debug("%s: withdrawing from vrf %s", __func__
,
999 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
1000 for (bi
= (bn
? bn
->info
: NULL
); bi
; bi
= bi
->next
) {
1002 && (struct bgp_info
*)bi
->extra
->parent
1010 zlog_debug("%s: deleting bi %p", __func__
, bi
);
1011 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
1012 bgp_info_delete(bn
, bi
);
1013 bgp_process(bgp
, bn
, afi
, safi
);
1015 bgp_unlock_node(bn
);
1019 void vpn_leak_to_vrf_withdraw_all(struct bgp
*bgp_vrf
, /* to */
1022 struct bgp_node
*bn
;
1023 struct bgp_info
*bi
;
1024 safi_t safi
= SAFI_UNICAST
;
1025 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
1026 struct bgp
*bgp_vpn
= bgp_get_default();
1029 zlog_debug("%s: entry", __func__
);
1031 * Walk vrf table, delete bi with bgp_orig == bgp_vpn
1033 for (bn
= bgp_table_top(bgp_vrf
->rib
[afi
][safi
]); bn
;
1034 bn
= bgp_route_next(bn
)) {
1036 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
1037 if (bi
->extra
&& bi
->extra
->bgp_orig
== bgp_vpn
) {
1040 bgp_aggregate_decrement(bgp_vrf
, &bn
->p
, bi
,
1042 bgp_info_delete(bn
, bi
);
1043 bgp_process(bgp_vrf
, bn
, afi
, safi
);
1049 void vpn_leak_to_vrf_update_all(struct bgp
*bgp_vrf
, /* to */
1050 struct bgp
*bgp_vpn
, /* from */
1053 struct prefix_rd prd
;
1054 struct bgp_node
*prn
;
1055 safi_t safi
= SAFI_MPLS_VPN
;
1060 for (prn
= bgp_table_top(bgp_vpn
->rib
[afi
][safi
]); prn
;
1061 prn
= bgp_route_next(prn
)) {
1063 struct bgp_table
*table
;
1064 struct bgp_node
*bn
;
1065 struct bgp_info
*bi
;
1067 memset(&prd
, 0, sizeof(prd
));
1068 prd
.family
= AF_UNSPEC
;
1070 memcpy(prd
.val
, prn
->p
.u
.val
, 8);
1072 /* This is the per-RD table of prefixes */
1078 for (bn
= bgp_table_top(table
); bn
; bn
= bgp_route_next(bn
)) {
1080 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
1082 if (bi
->extra
&& bi
->extra
->bgp_orig
== bgp_vrf
)
1085 vpn_leak_to_vrf_update_onevrf(bgp_vrf
, bgp_vpn
,
1092 static void vpn_policy_routemap_update(struct bgp
*bgp
, const char *rmap_name
)
1094 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_RMAP_EVENT
);
1096 struct route_map
*rmap
;
1098 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
1099 && bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
) {
1104 rmap
= route_map_lookup_by_name(rmap_name
); /* NULL if deleted */
1106 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
1108 if (vpn_leak_to_vpn_active(bgp
, afi
, NULL
)
1109 && bgp
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
]
1110 && !strcmp(rmap_name
,
1111 bgp
->vpn_policy
[afi
]
1112 .rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
])) {
1116 "%s: rmap \"%s\" matches vrf-policy tovpn for as %d afi %s",
1117 __func__
, rmap_name
, bgp
->as
,
1120 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN
, afi
,
1121 bgp_get_default(), bgp
);
1123 zlog_debug("%s: after vpn_leak_prechange",
1127 bgp
->vpn_policy
[afi
]
1128 .rmap
[BGP_VPN_POLICY_DIR_TOVPN
] = NULL
;
1130 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN
, afi
,
1131 bgp_get_default(), bgp
);
1133 zlog_debug("%s: after vpn_leak_postchange",
1137 char *mapname
= bgp
->vpn_policy
[afi
]
1138 .rmap_name
[BGP_VPN_POLICY_DIR_FROMVPN
];
1140 if (vpn_leak_from_vpn_active(bgp
, afi
, NULL
) &&
1142 !strcmp(rmap_name
, mapname
)) {
1145 zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
1146 __func__
, rmap_name
, bgp
->as
,
1150 vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN
, afi
,
1151 bgp_get_default(), bgp
);
1154 bgp
->vpn_policy
[afi
]
1155 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
] =
1159 vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN
, afi
,
1160 bgp_get_default(), bgp
);
1165 void vpn_policy_routemap_event(const char *rmap_name
)
1167 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_RMAP_EVENT
);
1168 struct listnode
*mnode
, *mnnode
;
1172 zlog_debug("%s: entry", __func__
);
1174 if (bm
->bgp
== NULL
) /* may be called during cleanup */
1177 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
))
1178 vpn_policy_routemap_update(bgp
, rmap_name
);
1181 /* For testing purpose, static route of MPLS-VPN. */
1182 DEFUN (vpnv4_network
,
1184 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
1185 "Specify a network to announce via BGP\n"
1187 "Specify Route Distinguisher\n"
1188 "VPN Route Distinguisher\n"
1189 "VPN NLRI label (tag)\n"
1190 "VPN NLRI label (tag)\n"
1193 int idx_ipv4_prefixlen
= 1;
1194 int idx_ext_community
= 3;
1196 return bgp_static_set_safi(
1197 AFI_IP
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1198 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
, NULL
, 0,
1199 NULL
, NULL
, NULL
, NULL
);
1202 DEFUN (vpnv4_network_route_map
,
1203 vpnv4_network_route_map_cmd
,
1204 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map WORD",
1205 "Specify a network to announce via BGP\n"
1207 "Specify Route Distinguisher\n"
1208 "VPN Route Distinguisher\n"
1209 "VPN NLRI label (tag)\n"
1210 "VPN NLRI label (tag)\n"
1215 int idx_ipv4_prefixlen
= 1;
1216 int idx_ext_community
= 3;
1219 return bgp_static_set_safi(
1220 AFI_IP
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1221 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1222 argv
[idx_word_2
]->arg
, 0, NULL
, NULL
, NULL
, NULL
);
1225 /* For testing purpose, static route of MPLS-VPN. */
1226 DEFUN (no_vpnv4_network
,
1227 no_vpnv4_network_cmd
,
1228 "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
1230 "Specify a network to announce via BGP\n"
1232 "Specify Route Distinguisher\n"
1233 "VPN Route Distinguisher\n"
1234 "VPN NLRI label (tag)\n"
1235 "VPN NLRI label (tag)\n"
1238 int idx_ipv4_prefixlen
= 2;
1239 int idx_ext_community
= 4;
1241 return bgp_static_unset_safi(AFI_IP
, SAFI_MPLS_VPN
, vty
,
1242 argv
[idx_ipv4_prefixlen
]->arg
,
1243 argv
[idx_ext_community
]->arg
,
1244 argv
[idx_label
]->arg
, 0, NULL
, NULL
, NULL
);
1247 DEFUN (vpnv6_network
,
1249 "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map WORD]",
1250 "Specify a network to announce via BGP\n"
1251 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1252 "Specify Route Distinguisher\n"
1253 "VPN Route Distinguisher\n"
1254 "VPN NLRI label (tag)\n"
1255 "VPN NLRI label (tag)\n"
1260 int idx_ipv6_prefix
= 1;
1261 int idx_ext_community
= 3;
1265 return bgp_static_set_safi(
1266 AFI_IP6
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv6_prefix
]->arg
,
1267 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1268 argv
[idx_word_2
]->arg
, 0, NULL
, NULL
, NULL
, NULL
);
1270 return bgp_static_set_safi(
1271 AFI_IP6
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv6_prefix
]->arg
,
1272 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1273 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1276 /* For testing purpose, static route of MPLS-VPN. */
1277 DEFUN (no_vpnv6_network
,
1278 no_vpnv6_network_cmd
,
1279 "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
1281 "Specify a network to announce via BGP\n"
1282 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1283 "Specify Route Distinguisher\n"
1284 "VPN Route Distinguisher\n"
1285 "VPN NLRI label (tag)\n"
1286 "VPN NLRI label (tag)\n"
1289 int idx_ipv6_prefix
= 2;
1290 int idx_ext_community
= 4;
1292 return bgp_static_unset_safi(AFI_IP6
, SAFI_MPLS_VPN
, vty
,
1293 argv
[idx_ipv6_prefix
]->arg
,
1294 argv
[idx_ext_community
]->arg
,
1295 argv
[idx_label
]->arg
, 0, NULL
, NULL
, NULL
);
1298 int bgp_show_mpls_vpn(struct vty
*vty
, afi_t afi
, struct prefix_rd
*prd
,
1299 enum bgp_show_type type
, void *output_arg
, int tags
,
1303 struct bgp_table
*table
;
1305 bgp
= bgp_get_default();
1308 vty_out(vty
, "No BGP process is configured\n");
1310 vty_out(vty
, "{}\n");
1313 table
= bgp
->rib
[afi
][SAFI_MPLS_VPN
];
1314 return bgp_show_table_rd(vty
, bgp
, SAFI_MPLS_VPN
, table
, prd
, type
,
1315 output_arg
, use_json
);
1318 DEFUN (show_bgp_ip_vpn_all_rd
,
1319 show_bgp_ip_vpn_all_rd_cmd
,
1320 "show bgp "BGP_AFI_CMD_STR
" vpn all [rd ASN:NN_OR_IP-ADDRESS:NN] [json]",
1324 "Display VPN NLRI specific information\n"
1325 "Display VPN NLRI specific information\n"
1326 "Display information for a route distinguisher\n"
1327 "VPN Route Distinguisher\n"
1331 struct prefix_rd prd
;
1335 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
1336 if (argv_find(argv
, argc
, "rd", &idx
)) {
1337 ret
= str2prefix_rd(argv
[idx
+ 1]->arg
, &prd
);
1340 "%% Malformed Route Distinguisher\n");
1343 return bgp_show_mpls_vpn(vty
, afi
, &prd
,
1344 bgp_show_type_normal
, NULL
, 0,
1345 use_json(argc
, argv
));
1347 return bgp_show_mpls_vpn(vty
, afi
, NULL
,
1348 bgp_show_type_normal
, NULL
, 0,
1349 use_json(argc
, argv
));
1355 ALIAS(show_bgp_ip_vpn_all_rd
,
1356 show_bgp_ip_vpn_rd_cmd
,
1357 "show bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1361 "Display VPN NLRI specific information\n"
1362 "Display information for a route distinguisher\n"
1363 "VPN Route Distinguisher\n"
1366 #ifdef KEEP_OLD_VPN_COMMANDS
1367 DEFUN (show_ip_bgp_vpn_rd
,
1368 show_ip_bgp_vpn_rd_cmd
,
1369 "show ip bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN",
1374 "Address Family modifier\n"
1375 "Display information for a route distinguisher\n"
1376 "VPN Route Distinguisher\n")
1378 int idx_ext_community
= argc
- 1;
1380 struct prefix_rd prd
;
1384 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1385 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1387 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1390 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_normal
,
1396 DEFUN (show_ip_bgp_vpn_all
,
1397 show_ip_bgp_vpn_all_cmd
,
1398 "show [ip] bgp <vpnv4|vpnv6>",
1407 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
))
1408 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
1413 DEFUN (show_ip_bgp_vpn_all_tags
,
1414 show_ip_bgp_vpn_all_tags_cmd
,
1415 "show [ip] bgp <vpnv4|vpnv6> all tags",
1420 "Display information about all VPNv4/VPNV6 NLRIs\n"
1421 "Display BGP tags for prefixes\n")
1426 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
))
1427 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
1432 DEFUN (show_ip_bgp_vpn_rd_tags
,
1433 show_ip_bgp_vpn_rd_tags_cmd
,
1434 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN tags",
1439 "Display information for a route distinguisher\n"
1440 "VPN Route Distinguisher\n"
1441 "Display BGP tags for prefixes\n")
1443 int idx_ext_community
= 5;
1445 struct prefix_rd prd
;
1449 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1450 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1452 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1455 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_normal
,
1461 DEFUN (show_ip_bgp_vpn_all_neighbor_routes
,
1462 show_ip_bgp_vpn_all_neighbor_routes_cmd
,
1463 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
1468 "Display information about all VPNv4/VPNv6 NLRIs\n"
1469 "Detailed information on TCP and BGP neighbor connections\n"
1470 "Neighbor to display information about\n"
1471 "Display routes learned from neighbor\n"
1478 u_char uj
= use_json(argc
, argv
);
1482 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1483 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1486 json_object
*json_no
= NULL
;
1487 json_no
= json_object_new_object();
1488 json_object_string_add(json_no
, "warning",
1489 "Malformed address");
1490 vty_out(vty
, "%s\n",
1491 json_object_to_json_string(json_no
));
1492 json_object_free(json_no
);
1494 vty_out(vty
, "Malformed address: %s\n",
1495 argv
[idx_ipv4
]->arg
);
1499 peer
= peer_lookup(NULL
, &su
);
1500 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1502 json_object
*json_no
= NULL
;
1503 json_no
= json_object_new_object();
1504 json_object_string_add(
1506 "No such neighbor or address family");
1507 vty_out(vty
, "%s\n",
1508 json_object_to_json_string(json_no
));
1509 json_object_free(json_no
);
1512 "%% No such neighbor or address family\n");
1516 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_neighbor
,
1522 DEFUN (show_ip_bgp_vpn_rd_neighbor_routes
,
1523 show_ip_bgp_vpn_rd_neighbor_routes_cmd
,
1524 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1529 "Display information for a route distinguisher\n"
1530 "VPN Route Distinguisher\n"
1531 "Detailed information on TCP and BGP neighbor connections\n"
1532 "Neighbor to display information about\n"
1533 "Display routes learned from neighbor\n"
1536 int idx_ext_community
= 5;
1541 struct prefix_rd prd
;
1542 u_char uj
= use_json(argc
, argv
);
1546 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1547 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1550 json_object
*json_no
= NULL
;
1551 json_no
= json_object_new_object();
1552 json_object_string_add(
1554 "Malformed Route Distinguisher");
1555 vty_out(vty
, "%s\n",
1556 json_object_to_json_string(json_no
));
1557 json_object_free(json_no
);
1560 "%% Malformed Route Distinguisher\n");
1564 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1567 json_object
*json_no
= NULL
;
1568 json_no
= json_object_new_object();
1569 json_object_string_add(json_no
, "warning",
1570 "Malformed address");
1571 vty_out(vty
, "%s\n",
1572 json_object_to_json_string(json_no
));
1573 json_object_free(json_no
);
1575 vty_out(vty
, "Malformed address: %s\n",
1576 argv
[idx_ext_community
]->arg
);
1580 peer
= peer_lookup(NULL
, &su
);
1581 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1583 json_object
*json_no
= NULL
;
1584 json_no
= json_object_new_object();
1585 json_object_string_add(
1587 "No such neighbor or address family");
1588 vty_out(vty
, "%s\n",
1589 json_object_to_json_string(json_no
));
1590 json_object_free(json_no
);
1593 "%% No such neighbor or address family\n");
1597 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_neighbor
,
1603 DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes
,
1604 show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd
,
1605 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
1610 "Display information about all VPNv4/VPNv6 NLRIs\n"
1611 "Detailed information on TCP and BGP neighbor connections\n"
1612 "Neighbor to display information about\n"
1613 "Display the routes advertised to a BGP neighbor\n"
1620 u_char uj
= use_json(argc
, argv
);
1624 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1625 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1628 json_object
*json_no
= NULL
;
1629 json_no
= json_object_new_object();
1630 json_object_string_add(json_no
, "warning",
1631 "Malformed address");
1632 vty_out(vty
, "%s\n",
1633 json_object_to_json_string(json_no
));
1634 json_object_free(json_no
);
1636 vty_out(vty
, "Malformed address: %s\n",
1637 argv
[idx_ipv4
]->arg
);
1640 peer
= peer_lookup(NULL
, &su
);
1641 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1643 json_object
*json_no
= NULL
;
1644 json_no
= json_object_new_object();
1645 json_object_string_add(
1647 "No such neighbor or address family");
1648 vty_out(vty
, "%s\n",
1649 json_object_to_json_string(json_no
));
1650 json_object_free(json_no
);
1653 "%% No such neighbor or address family\n");
1656 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_IP
,
1662 DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes
,
1663 show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd
,
1664 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1669 "Display information for a route distinguisher\n"
1670 "VPN Route Distinguisher\n"
1671 "Detailed information on TCP and BGP neighbor connections\n"
1672 "Neighbor to display information about\n"
1673 "Display the routes advertised to a BGP neighbor\n"
1676 int idx_ext_community
= 5;
1680 struct prefix_rd prd
;
1682 u_char uj
= use_json(argc
, argv
);
1686 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1687 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1690 json_object
*json_no
= NULL
;
1691 json_no
= json_object_new_object();
1692 json_object_string_add(json_no
, "warning",
1693 "Malformed address");
1694 vty_out(vty
, "%s\n",
1695 json_object_to_json_string(json_no
));
1696 json_object_free(json_no
);
1698 vty_out(vty
, "Malformed address: %s\n",
1699 argv
[idx_ext_community
]->arg
);
1702 peer
= peer_lookup(NULL
, &su
);
1703 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1705 json_object
*json_no
= NULL
;
1706 json_no
= json_object_new_object();
1707 json_object_string_add(
1709 "No such neighbor or address family");
1710 vty_out(vty
, "%s\n",
1711 json_object_to_json_string(json_no
));
1712 json_object_free(json_no
);
1715 "%% No such neighbor or address family\n");
1719 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1722 json_object
*json_no
= NULL
;
1723 json_no
= json_object_new_object();
1724 json_object_string_add(
1726 "Malformed Route Distinguisher");
1727 vty_out(vty
, "%s\n",
1728 json_object_to_json_string(json_no
));
1729 json_object_free(json_no
);
1732 "%% Malformed Route Distinguisher\n");
1736 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_IP
,
1741 #endif /* KEEP_OLD_VPN_COMMANDS */
1743 void bgp_mplsvpn_init(void)
1745 install_element(BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
1746 install_element(BGP_VPNV4_NODE
, &vpnv4_network_route_map_cmd
);
1747 install_element(BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
1749 install_element(BGP_VPNV6_NODE
, &vpnv6_network_cmd
);
1750 install_element(BGP_VPNV6_NODE
, &no_vpnv6_network_cmd
);
1752 install_element(VIEW_NODE
, &show_bgp_ip_vpn_all_rd_cmd
);
1753 install_element(VIEW_NODE
, &show_bgp_ip_vpn_rd_cmd
);
1754 #ifdef KEEP_OLD_VPN_COMMANDS
1755 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_cmd
);
1756 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_cmd
);
1757 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_tags_cmd
);
1758 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_tags_cmd
);
1759 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_neighbor_routes_cmd
);
1760 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_neighbor_routes_cmd
);
1761 install_element(VIEW_NODE
,
1762 &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd
);
1763 install_element(VIEW_NODE
,
1764 &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd
);
1765 #endif /* KEEP_OLD_VPN_COMMANDS */