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
;
112 /* Check peer status. */
113 if (peer
->status
!= Established
)
117 prd
.family
= AF_UNSPEC
;
121 lim
= pnt
+ packet
->length
;
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
));
131 #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
132 for (; pnt
< lim
; pnt
+= psize
) {
133 /* Clear prefix structure. */
134 memset(&p
, 0, sizeof(struct prefix
));
136 if (addpath_encoded
) {
138 /* When packet overflow occurs return immediately. */
139 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
142 addpath_id
= ntohl(*((uint32_t *)pnt
));
143 pnt
+= BGP_ADDPATH_ID_LEN
;
146 /* Fetch prefix length. */
148 p
.family
= afi2family(packet
->afi
);
149 psize
= PSIZE(prefixlen
);
151 if (prefixlen
< VPN_PREFIXLEN_MIN_BYTES
* 8) {
153 "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
154 peer
->host
, prefixlen
);
158 /* sanity check against packet data */
159 if ((pnt
+ psize
) > lim
) {
161 "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
162 peer
->host
, prefixlen
, (uint
)(lim
- pnt
));
166 /* sanity check against storage for the IP address portion */
167 if ((psize
- VPN_PREFIXLEN_MIN_BYTES
) > (ssize_t
)sizeof(p
.u
)) {
169 "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
171 prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8,
176 /* Sanity check against max bitlen of the address family */
177 if ((psize
- VPN_PREFIXLEN_MIN_BYTES
) > prefix_blen(&p
)) {
179 "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
181 prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8,
182 p
.family
, prefix_blen(&p
));
186 /* Copy label to prefix. */
187 memcpy(&label
, pnt
, BGP_LABEL_BYTES
);
188 bgp_set_valid_label(&label
);
190 /* Copy routing distinguisher to rd. */
191 memcpy(&prd
.val
, pnt
+ BGP_LABEL_BYTES
, 8);
193 /* Decode RD type. */
194 type
= decode_rd_type(pnt
+ BGP_LABEL_BYTES
);
198 decode_rd_as(pnt
+ 5, &rd_as
);
202 decode_rd_as4(pnt
+ 5, &rd_as
);
206 decode_rd_ip(pnt
+ 5, &rd_ip
);
210 case RD_TYPE_VNC_ETH
:
215 zlog_err("Unknown RD type %d", type
);
216 break; /* just report */
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
);
226 bgp_update(peer
, &p
, addpath_id
, attr
, packet
->afi
,
227 SAFI_MPLS_VPN
, ZEBRA_ROUTE_BGP
,
228 BGP_ROUTE_NORMAL
, &prd
, &label
, 1, 0, NULL
);
230 bgp_withdraw(peer
, &p
, addpath_id
, attr
, packet
->afi
,
231 SAFI_MPLS_VPN
, ZEBRA_ROUTE_BGP
,
232 BGP_ROUTE_NORMAL
, &prd
, &label
, 1, NULL
);
235 /* Packet length consistency check. */
238 "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
239 peer
->host
, lim
- pnt
);
244 #undef VPN_PREFIXLEN_MIN_BYTES
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."
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.
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
260 void vpn_leak_zebra_vrf_label_update(struct bgp
*bgp
, afi_t afi
)
262 mpls_label_t label
= MPLS_LABEL_NONE
;
263 const char *name
= "default";
264 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
266 if (debug
&& (bgp
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
)) {
270 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
273 "%s: vrf %s: afi %s: vrf_id not set, "
274 "can't set zebra vrf label",
275 __func__
, name
, afi2str(afi
));
280 if (vpn_leak_to_vpn_active(bgp
, afi
, NULL
)) {
281 label
= bgp
->vpn_policy
[afi
].tovpn_label
;
285 zlog_debug("%s: vrf %s: afi %s: setting label %d for vrf id %d",
286 __func__
, name
, afi2str(afi
), label
, bgp
->vrf_id
);
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
;
294 * If zebra tells us vrf has become unconfigured, tell zebra not to
295 * use this label to forward to the vrf anymore
297 void vpn_leak_zebra_vrf_label_withdraw(struct bgp
*bgp
, afi_t afi
)
299 mpls_label_t label
= MPLS_LABEL_NONE
;
300 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
302 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
305 "%s: vrf_id not set, can't delete zebra vrf label",
312 zlog_debug("%s: deleting label for vrf %s (id=%d)", __func__
,
313 (bgp
->name
? bgp
->name
: "default"), bgp
->vrf_id
);
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
;
320 static int ecom_intersect(struct ecommunity
*e1
, struct ecommunity
*e2
)
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
),
342 * returns pointer to new bgp_info upon success
344 static struct bgp_info
*
345 leak_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
)
351 struct prefix
*p
= &bn
->p
;
353 struct bgp_info
*new;
354 char buf_prefix
[PREFIX_STRLEN
];
355 const char *pDestInstanceName
= "default";
358 prefix2str(&bn
->p
, buf_prefix
, sizeof(buf_prefix
));
360 pDestInstanceName
= bgp
->name
;
366 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
367 if (bi
->extra
&& bi
->extra
->parent
== parent
)
372 if (attrhash_cmp(bi
->attr
, new_attr
)
373 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
375 bgp_attr_unintern(&new_attr
);
378 "%s: ->%s: %s: Found route, no change",
379 __func__
, pDestInstanceName
,
384 /* attr is changed */
385 bgp_info_set_flag(bn
, bi
, BGP_INFO_ATTR_CHANGED
);
387 /* Rewrite BGP route information. */
388 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
389 bgp_info_restore(bn
, bi
);
391 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
392 bgp_attr_unintern(&bi
->attr
);
394 bi
->uptime
= bgp_clock();
396 /* Process change. */
397 bgp_aggregate_increment(bgp
, p
, bi
, afi
, safi
);
398 bgp_process(bgp
, bn
, afi
, safi
);
402 zlog_debug("%s: ->%s: %s Found route, changed attr",
403 __func__
, pDestInstanceName
, buf_prefix
);
408 new = info_make(type
, sub_type
, 0, bgp
->peer_self
, new_attr
, bn
);
409 SET_FLAG(new->flags
, BGP_INFO_VALID
);
411 bgp_info_extra_get(new);
415 for (i
= 0; i
< num_labels
; ++i
) {
416 new->extra
->label
[i
] = label
[i
];
417 if (!bgp_is_valid_label(&label
[i
])) {
420 "%s: %s: marking label %d valid",
421 __func__
, buf_prefix
, i
);
423 bgp_set_valid_label(&new->extra
->label
[i
]);
426 new->extra
->num_labels
= num_labels
;
428 new->extra
->parent
= parent
;
431 new->extra
->bgp_orig
= bgp_orig
;
433 new->extra
->nexthop_orig
= *nexthop_orig
;
435 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
436 bgp_info_add(bn
, new);
439 bgp_process(bgp
, bn
, afi
, safi
);
442 zlog_debug("%s: ->%s: %s: Added new route", __func__
,
443 pDestInstanceName
, buf_prefix
);
448 /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
449 void vpn_leak_from_vrf_update(struct bgp
*bgp_vpn
, /* to */
450 struct bgp
*bgp_vrf
, /* from */
451 struct bgp_info
*info_vrf
) /* route */
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
;
462 const char *debugmsg
;
467 if (info_vrf
->attr
&& info_vrf
->attr
->ecommunity
) {
468 s
= ecommunity_ecom2str(info_vrf
->attr
->ecommunity
,
469 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
472 zlog_debug("%s: info_vrf->type=%d, EC{%s}", __func__
,
481 zlog_debug("%s: can't get afi of prefix", __func__
);
486 if (info_vrf
->extra
&& info_vrf
->extra
->bgp_orig
== bgp_vpn
)
490 if (!vpn_leak_to_vpn_active(bgp_vrf
, afi
, &debugmsg
)) {
492 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
496 bgp_attr_dup(&static_attr
, info_vrf
->attr
); /* shallow copy */
501 if (bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
]) {
502 struct bgp_info info
;
503 route_map_result_t ret
;
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
],
511 if (RMAP_DENYMATCH
== ret
) {
512 bgp_attr_flush(&static_attr
); /* free any added parts */
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
]
527 if (static_attr
.ecommunity
) {
528 s
= ecommunity_ecom2str(static_attr
.ecommunity
,
529 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
531 zlog_debug("%s: post route map static_attr.ecommunity{%s}",
536 * Add the vpn-policy rt-list
538 struct ecommunity
*old_ecom
;
539 struct ecommunity
*new_ecom
;
541 old_ecom
= static_attr
.ecommunity
;
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
);
550 new_ecom
= ecommunity_dup(
551 bgp_vrf
->vpn_policy
[afi
]
552 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]);
554 static_attr
.ecommunity
= new_ecom
;
555 SET_FLAG(static_attr
.flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
560 if (static_attr
.ecommunity
) {
561 s
= ecommunity_ecom2str(static_attr
.ecommunity
,
562 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
564 zlog_debug("%s: post merge static_attr.ecommunity{%s}",
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
)) {
573 struct prefix
*nexthop
=
574 &bgp_vrf
->vpn_policy
[afi
].tovpn_nexthop
;
575 switch (nexthop
->family
) {
577 /* prevent mp_nexthop_global_in <- self in bgp_route.c
579 static_attr
.nexthop
.s_addr
= nexthop
->u
.prefix4
.s_addr
;
581 static_attr
.mp_nexthop_global_in
= nexthop
->u
.prefix4
;
582 static_attr
.mp_nexthop_len
= 4;
586 static_attr
.mp_nexthop_global
= nexthop
->u
.prefix6
;
587 static_attr
.mp_nexthop_len
= 16;
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
);
606 memset(&static_attr
.mp_nexthop_global
, 0,
607 sizeof(static_attr
.mp_nexthop_global
));
608 static_attr
.mp_nexthop_len
= 16; /* bytes */
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
;
618 encode_label(label_val
, &label
);
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
;
626 new_attr
= bgp_attr_intern(
627 &static_attr
); /* hashed refcounted everything */
628 bgp_attr_flush(&static_attr
); /* free locally-allocated parts */
633 if (new_attr
->ecommunity
) {
634 s
= ecommunity_ecom2str(new_attr
->ecommunity
,
635 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
637 zlog_debug("%s: new_attr->ecommunity{%s}", __func__
, s
);
640 /* Now new_attr is an allocated interned attr */
642 bn
= bgp_afi_node_get(bgp_vpn
->rib
[afi
][safi
], afi
, safi
, p
,
643 &(bgp_vrf
->vpn_policy
[afi
].tovpn_rd
));
645 struct bgp_info
*new_info
;
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
);
652 * Routes actually installed in the vpn RIB must also be
653 * offered to all vrfs (because now they originate from
656 * Acceptance into other vrfs depends on rt-lists.
657 * Originating vrf will not accept the looped back route
658 * because of loop checking.
661 vpn_leak_to_vrf_update(bgp_vrf
, new_info
);
664 void vpn_leak_from_vrf_withdraw(struct bgp
*bgp_vpn
, /* to */
665 struct bgp
*bgp_vrf
, /* from */
666 struct bgp_info
*info_vrf
) /* route */
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
;
674 const char *debugmsg
;
676 if (info_vrf
->type
!= ZEBRA_ROUTE_BGP
) {
678 zlog_debug("%s: wrong type %d", __func__
,
682 if (info_vrf
->sub_type
!= BGP_ROUTE_NORMAL
683 && info_vrf
->sub_type
!= BGP_ROUTE_STATIC
) {
686 zlog_debug("%s: wrong sub_type %d", __func__
,
695 zlog_debug("%s: can't get afi of prefix", __func__
);
699 if (!vpn_leak_to_vpn_active(bgp_vrf
, afi
, &debugmsg
)) {
701 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
706 zlog_debug("%s: withdrawing (info_vrf=%p)", __func__
, info_vrf
);
708 bn
= bgp_afi_node_get(bgp_vpn
->rib
[afi
][safi
], afi
, safi
, p
,
709 &(bgp_vrf
->vpn_policy
[afi
].tovpn_rd
));
713 * match original bi imported from
715 for (bi
= (bn
? bn
->info
: NULL
); bi
; bi
= bi
->next
) {
716 if (bi
->extra
&& bi
->extra
->parent
== info_vrf
) {
722 /* withdraw from looped vrfs as well */
723 vpn_leak_to_vrf_withdraw(bgp_vpn
, bi
);
725 bgp_aggregate_decrement(bgp_vpn
, p
, bi
, afi
, safi
);
726 bgp_info_delete(bn
, bi
);
727 bgp_process(bgp_vpn
, bn
, afi
, safi
);
732 void vpn_leak_from_vrf_withdraw_all(struct bgp
*bgp_vpn
, /* to */
733 struct bgp
*bgp_vrf
, /* from */
736 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
737 struct bgp_node
*prn
;
738 safi_t safi
= SAFI_MPLS_VPN
;
741 * Walk vpn table, delete bi with parent == bgp_vrf
742 * Walk vpn table, delete bi with bgp_orig == bgp_vrf
744 for (prn
= bgp_table_top(bgp_vpn
->rib
[afi
][safi
]); prn
;
745 prn
= bgp_route_next(prn
)) {
747 struct bgp_table
*table
;
751 /* This is the per-RD table of prefixes */
757 for (bn
= bgp_table_top(table
); bn
; bn
= bgp_route_next(bn
)) {
759 char buf
[PREFIX2STR_BUFFER
];
761 if (debug
&& bn
->info
) {
763 "%s: looking at prefix %s", __func__
,
764 prefix2str(&bn
->p
, buf
, sizeof(buf
)));
767 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
769 zlog_debug("%s: type %d, sub_type %d",
772 if (bi
->sub_type
!= BGP_ROUTE_IMPORTED
)
776 if ((struct bgp
*)bi
->extra
->bgp_orig
780 zlog_debug("%s: deleting it\n",
782 bgp_aggregate_decrement(bgp_vpn
, &bn
->p
,
784 bgp_info_delete(bn
, bi
);
785 bgp_process(bgp_vpn
, bn
, afi
, safi
);
792 void vpn_leak_from_vrf_update_all(struct bgp
*bgp_vpn
, /* to */
793 struct bgp
*bgp_vrf
, /* from */
798 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
801 zlog_debug("%s: entry, afi=%d, vrf=%s", __func__
, afi
,
804 for (bn
= bgp_table_top(bgp_vrf
->rib
[afi
][SAFI_UNICAST
]); bn
;
805 bn
= bgp_route_next(bn
)) {
808 zlog_debug("%s: node=%p", __func__
, bn
);
810 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
813 "%s: calling vpn_leak_from_vrf_update",
815 vpn_leak_from_vrf_update(bgp_vpn
, bgp_vrf
, bi
);
820 static void vpn_leak_to_vrf_update_onevrf(struct bgp
*bgp_vrf
, /* to */
821 struct bgp
*bgp_vpn
, /* from */
822 struct bgp_info
*info_vpn
) /* route */
824 struct prefix
*p
= &info_vpn
->net
->p
;
825 afi_t afi
= family2afi(p
->family
);
827 struct attr static_attr
= {0};
828 struct attr
*new_attr
= NULL
;
830 safi_t safi
= SAFI_UNICAST
;
831 const char *debugmsg
;
832 struct prefix nexthop_orig
;
833 mpls_label_t
*pLabels
= NULL
;
836 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
838 if (!vpn_leak_from_vpn_active(bgp_vrf
, afi
, &debugmsg
)) {
840 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
844 /* Check for intersection of route targets */
846 bgp_vrf
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
847 info_vpn
->attr
->ecommunity
)) {
853 zlog_debug("%s: updating to vrf %s", __func__
, bgp_vrf
->name
);
855 bgp_attr_dup(&static_attr
, info_vpn
->attr
); /* shallow copy */
858 * Nexthop: stash and clear
860 * Nexthop is valid in context of VPN core, but not in destination vrf.
861 * Stash it for later label resolution by vrf ingress path and then
862 * overwrite with 0, i.e., "me", for the sake of vrf advertisement.
864 uint8_t nhfamily
= NEXTHOP_FAMILY(info_vpn
->attr
->mp_nexthop_len
);
866 memset(&nexthop_orig
, 0, sizeof(nexthop_orig
));
867 nexthop_orig
.family
= nhfamily
;
873 nexthop_orig
.u
.prefix4
= info_vpn
->attr
->mp_nexthop_global_in
;
874 nexthop_orig
.prefixlen
= 32;
876 static_attr
.nexthop
.s_addr
= 0; /* self */
877 static_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
883 nexthop_orig
.u
.prefix6
= info_vpn
->attr
->mp_nexthop_global
;
884 nexthop_orig
.prefixlen
= 128;
886 memset(&static_attr
.mp_nexthop_global
, 0,
887 sizeof(static_attr
.mp_nexthop_global
)); /* clear */
888 static_attr
.mp_nexthop_len
= 16; /* bytes */
896 if (bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
897 struct bgp_info info
;
898 route_map_result_t ret
;
900 memset(&info
, 0, sizeof(info
));
901 info
.peer
= bgp_vrf
->peer_self
;
902 info
.attr
= &static_attr
;
903 ret
= route_map_apply(bgp_vrf
->vpn_policy
[afi
]
904 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
],
906 if (RMAP_DENYMATCH
== ret
) {
907 bgp_attr_flush(&static_attr
); /* free any added parts */
910 "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning",
911 __func__
, bgp_vrf
->name
,
912 bgp_vrf
->vpn_policy
[afi
]
913 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]
919 new_attr
= bgp_attr_intern(&static_attr
);
920 bgp_attr_flush(&static_attr
);
922 bn
= bgp_afi_node_get(bgp_vrf
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
925 * ensure labels are copied
927 if (info_vpn
->extra
&& info_vpn
->extra
->num_labels
) {
928 num_labels
= info_vpn
->extra
->num_labels
;
929 if (num_labels
> BGP_MAX_LABELS
)
930 num_labels
= BGP_MAX_LABELS
;
931 pLabels
= info_vpn
->extra
->label
;
934 char buf_prefix
[PREFIX_STRLEN
];
935 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
936 zlog_debug("%s: pfx %s: num_labels %d", __func__
, buf_prefix
,
940 leak_update(bgp_vrf
, bn
, new_attr
, afi
, safi
, info_vpn
, ZEBRA_ROUTE_BGP
,
941 BGP_ROUTE_IMPORTED
, pLabels
, num_labels
,
942 info_vpn
, /* parent */
943 bgp_vpn
, &nexthop_orig
, debug
);
946 void vpn_leak_to_vrf_update(struct bgp
*bgp_vpn
, /* from */
947 struct bgp_info
*info_vpn
) /* route */
949 struct listnode
*mnode
, *mnnode
;
952 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
955 zlog_debug("%s: start (info_vpn=%p)", __func__
, info_vpn
);
958 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
961 || info_vpn
->extra
->bgp_orig
!= bgp
) { /* no loop */
962 vpn_leak_to_vrf_update_onevrf(bgp
, bgp_vpn
, info_vpn
);
967 void vpn_leak_to_vrf_withdraw(struct bgp
*bgp_vpn
, /* from */
968 struct bgp_info
*info_vpn
) /* route */
970 struct prefix
*p
= &info_vpn
->net
->p
;
971 afi_t afi
= family2afi(p
->family
);
972 safi_t safi
= SAFI_UNICAST
;
974 struct listnode
*mnode
, *mnnode
;
977 const char *debugmsg
;
979 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
982 zlog_debug("%s: start (info_vpn=%p)", __func__
, info_vpn
);
986 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
987 if (!vpn_leak_from_vpn_active(bgp
, afi
, &debugmsg
)) {
989 zlog_debug("%s: skipping: %s", __func__
,
994 /* Check for intersection of route targets */
995 if (!ecom_intersect(bgp
->vpn_policy
[afi
]
996 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
997 info_vpn
->attr
->ecommunity
)) {
1003 zlog_debug("%s: withdrawing from vrf %s", __func__
,
1006 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
1007 for (bi
= (bn
? bn
->info
: NULL
); bi
; bi
= bi
->next
) {
1009 && (struct bgp_info
*)bi
->extra
->parent
1017 zlog_debug("%s: deleting bi %p", __func__
, bi
);
1018 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
1019 bgp_info_delete(bn
, bi
);
1020 bgp_process(bgp
, bn
, afi
, safi
);
1022 bgp_unlock_node(bn
);
1026 void vpn_leak_to_vrf_withdraw_all(struct bgp
*bgp_vrf
, /* to */
1029 struct bgp_node
*bn
;
1030 struct bgp_info
*bi
;
1031 safi_t safi
= SAFI_UNICAST
;
1032 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
1033 struct bgp
*bgp_vpn
= bgp_get_default();
1036 zlog_debug("%s: entry", __func__
);
1038 * Walk vrf table, delete bi with bgp_orig == bgp_vpn
1040 for (bn
= bgp_table_top(bgp_vrf
->rib
[afi
][safi
]); bn
;
1041 bn
= bgp_route_next(bn
)) {
1043 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
1044 if (bi
->extra
&& bi
->extra
->bgp_orig
== bgp_vpn
) {
1047 bgp_aggregate_decrement(bgp_vrf
, &bn
->p
, bi
,
1049 bgp_info_delete(bn
, bi
);
1050 bgp_process(bgp_vrf
, bn
, afi
, safi
);
1056 void vpn_leak_to_vrf_update_all(struct bgp
*bgp_vrf
, /* to */
1057 struct bgp
*bgp_vpn
, /* from */
1060 struct prefix_rd prd
;
1061 struct bgp_node
*prn
;
1062 safi_t safi
= SAFI_MPLS_VPN
;
1067 for (prn
= bgp_table_top(bgp_vpn
->rib
[afi
][safi
]); prn
;
1068 prn
= bgp_route_next(prn
)) {
1070 struct bgp_table
*table
;
1071 struct bgp_node
*bn
;
1072 struct bgp_info
*bi
;
1074 memset(&prd
, 0, sizeof(prd
));
1075 prd
.family
= AF_UNSPEC
;
1077 memcpy(prd
.val
, prn
->p
.u
.val
, 8);
1079 /* This is the per-RD table of prefixes */
1085 for (bn
= bgp_table_top(table
); bn
; bn
= bgp_route_next(bn
)) {
1087 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
1089 if (bi
->extra
&& bi
->extra
->bgp_orig
== bgp_vrf
)
1092 vpn_leak_to_vrf_update_onevrf(bgp_vrf
, bgp_vpn
,
1099 static void vpn_policy_routemap_update(struct bgp
*bgp
, const char *rmap_name
)
1101 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_RMAP_EVENT
);
1103 struct route_map
*rmap
;
1105 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
1106 && bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
) {
1111 rmap
= route_map_lookup_by_name(rmap_name
); /* NULL if deleted */
1113 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
1115 if (vpn_leak_to_vpn_active(bgp
, afi
, NULL
)
1116 && bgp
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
]
1117 && !strcmp(rmap_name
,
1118 bgp
->vpn_policy
[afi
]
1119 .rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
])) {
1123 "%s: rmap \"%s\" matches vrf-policy tovpn for as %d afi %s",
1124 __func__
, rmap_name
, bgp
->as
,
1127 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN
, afi
,
1128 bgp_get_default(), bgp
);
1130 zlog_debug("%s: after vpn_leak_prechange",
1134 bgp
->vpn_policy
[afi
]
1135 .rmap
[BGP_VPN_POLICY_DIR_TOVPN
] = NULL
;
1137 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN
, afi
,
1138 bgp_get_default(), bgp
);
1140 zlog_debug("%s: after vpn_leak_postchange",
1144 char *mapname
= bgp
->vpn_policy
[afi
]
1145 .rmap_name
[BGP_VPN_POLICY_DIR_FROMVPN
];
1147 if (vpn_leak_from_vpn_active(bgp
, afi
, NULL
) &&
1149 !strcmp(rmap_name
, mapname
)) {
1152 zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
1153 __func__
, rmap_name
, bgp
->as
,
1157 vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN
, afi
,
1158 bgp_get_default(), bgp
);
1161 bgp
->vpn_policy
[afi
]
1162 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
] =
1166 vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN
, afi
,
1167 bgp_get_default(), bgp
);
1172 void vpn_policy_routemap_event(const char *rmap_name
)
1174 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_RMAP_EVENT
);
1175 struct listnode
*mnode
, *mnnode
;
1179 zlog_debug("%s: entry", __func__
);
1181 if (bm
->bgp
== NULL
) /* may be called during cleanup */
1184 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
))
1185 vpn_policy_routemap_update(bgp
, rmap_name
);
1188 /* For testing purpose, static route of MPLS-VPN. */
1189 DEFUN (vpnv4_network
,
1191 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
1192 "Specify a network to announce via BGP\n"
1194 "Specify Route Distinguisher\n"
1195 "VPN Route Distinguisher\n"
1196 "VPN NLRI label (tag)\n"
1197 "VPN NLRI label (tag)\n"
1200 int idx_ipv4_prefixlen
= 1;
1201 int idx_ext_community
= 3;
1203 return bgp_static_set_safi(
1204 AFI_IP
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1205 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
, NULL
, 0,
1206 NULL
, NULL
, NULL
, NULL
);
1209 DEFUN (vpnv4_network_route_map
,
1210 vpnv4_network_route_map_cmd
,
1211 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map WORD",
1212 "Specify a network to announce via BGP\n"
1214 "Specify Route Distinguisher\n"
1215 "VPN Route Distinguisher\n"
1216 "VPN NLRI label (tag)\n"
1217 "VPN NLRI label (tag)\n"
1222 int idx_ipv4_prefixlen
= 1;
1223 int idx_ext_community
= 3;
1226 return bgp_static_set_safi(
1227 AFI_IP
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1228 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1229 argv
[idx_word_2
]->arg
, 0, NULL
, NULL
, NULL
, NULL
);
1232 /* For testing purpose, static route of MPLS-VPN. */
1233 DEFUN (no_vpnv4_network
,
1234 no_vpnv4_network_cmd
,
1235 "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
1237 "Specify a network to announce via BGP\n"
1239 "Specify Route Distinguisher\n"
1240 "VPN Route Distinguisher\n"
1241 "VPN NLRI label (tag)\n"
1242 "VPN NLRI label (tag)\n"
1245 int idx_ipv4_prefixlen
= 2;
1246 int idx_ext_community
= 4;
1248 return bgp_static_unset_safi(AFI_IP
, SAFI_MPLS_VPN
, vty
,
1249 argv
[idx_ipv4_prefixlen
]->arg
,
1250 argv
[idx_ext_community
]->arg
,
1251 argv
[idx_label
]->arg
, 0, NULL
, NULL
, NULL
);
1254 DEFUN (vpnv6_network
,
1256 "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map WORD]",
1257 "Specify a network to announce via BGP\n"
1258 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1259 "Specify Route Distinguisher\n"
1260 "VPN Route Distinguisher\n"
1261 "VPN NLRI label (tag)\n"
1262 "VPN NLRI label (tag)\n"
1267 int idx_ipv6_prefix
= 1;
1268 int idx_ext_community
= 3;
1272 return bgp_static_set_safi(
1273 AFI_IP6
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv6_prefix
]->arg
,
1274 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1275 argv
[idx_word_2
]->arg
, 0, NULL
, NULL
, NULL
, NULL
);
1277 return bgp_static_set_safi(
1278 AFI_IP6
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv6_prefix
]->arg
,
1279 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1280 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1283 /* For testing purpose, static route of MPLS-VPN. */
1284 DEFUN (no_vpnv6_network
,
1285 no_vpnv6_network_cmd
,
1286 "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
1288 "Specify a network to announce via BGP\n"
1289 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1290 "Specify Route Distinguisher\n"
1291 "VPN Route Distinguisher\n"
1292 "VPN NLRI label (tag)\n"
1293 "VPN NLRI label (tag)\n"
1296 int idx_ipv6_prefix
= 2;
1297 int idx_ext_community
= 4;
1299 return bgp_static_unset_safi(AFI_IP6
, SAFI_MPLS_VPN
, vty
,
1300 argv
[idx_ipv6_prefix
]->arg
,
1301 argv
[idx_ext_community
]->arg
,
1302 argv
[idx_label
]->arg
, 0, NULL
, NULL
, NULL
);
1305 int bgp_show_mpls_vpn(struct vty
*vty
, afi_t afi
, struct prefix_rd
*prd
,
1306 enum bgp_show_type type
, void *output_arg
, int tags
,
1310 struct bgp_table
*table
;
1312 bgp
= bgp_get_default();
1315 vty_out(vty
, "No BGP process is configured\n");
1317 vty_out(vty
, "{}\n");
1320 table
= bgp
->rib
[afi
][SAFI_MPLS_VPN
];
1321 return bgp_show_table_rd(vty
, bgp
, SAFI_MPLS_VPN
, table
, prd
, type
,
1322 output_arg
, use_json
);
1325 DEFUN (show_bgp_ip_vpn_all_rd
,
1326 show_bgp_ip_vpn_all_rd_cmd
,
1327 "show bgp "BGP_AFI_CMD_STR
" vpn all [rd ASN:NN_OR_IP-ADDRESS:NN] [json]",
1331 "Display VPN NLRI specific information\n"
1332 "Display VPN NLRI specific information\n"
1333 "Display information for a route distinguisher\n"
1334 "VPN Route Distinguisher\n"
1338 struct prefix_rd prd
;
1342 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
1343 if (argv_find(argv
, argc
, "rd", &idx
)) {
1344 ret
= str2prefix_rd(argv
[idx
+ 1]->arg
, &prd
);
1347 "%% Malformed Route Distinguisher\n");
1350 return bgp_show_mpls_vpn(vty
, afi
, &prd
,
1351 bgp_show_type_normal
, NULL
, 0,
1352 use_json(argc
, argv
));
1354 return bgp_show_mpls_vpn(vty
, afi
, NULL
,
1355 bgp_show_type_normal
, NULL
, 0,
1356 use_json(argc
, argv
));
1362 ALIAS(show_bgp_ip_vpn_all_rd
,
1363 show_bgp_ip_vpn_rd_cmd
,
1364 "show bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1368 "Display VPN NLRI specific information\n"
1369 "Display information for a route distinguisher\n"
1370 "VPN Route Distinguisher\n"
1373 #ifdef KEEP_OLD_VPN_COMMANDS
1374 DEFUN (show_ip_bgp_vpn_rd
,
1375 show_ip_bgp_vpn_rd_cmd
,
1376 "show ip bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN",
1381 "Address Family modifier\n"
1382 "Display information for a route distinguisher\n"
1383 "VPN Route Distinguisher\n")
1385 int idx_ext_community
= argc
- 1;
1387 struct prefix_rd prd
;
1391 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1392 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1394 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1397 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_normal
,
1403 DEFUN (show_ip_bgp_vpn_all
,
1404 show_ip_bgp_vpn_all_cmd
,
1405 "show [ip] bgp <vpnv4|vpnv6>",
1414 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
))
1415 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
1420 DEFUN (show_ip_bgp_vpn_all_tags
,
1421 show_ip_bgp_vpn_all_tags_cmd
,
1422 "show [ip] bgp <vpnv4|vpnv6> all tags",
1427 "Display information about all VPNv4/VPNV6 NLRIs\n"
1428 "Display BGP tags for prefixes\n")
1433 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
))
1434 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
1439 DEFUN (show_ip_bgp_vpn_rd_tags
,
1440 show_ip_bgp_vpn_rd_tags_cmd
,
1441 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN tags",
1446 "Display information for a route distinguisher\n"
1447 "VPN Route Distinguisher\n"
1448 "Display BGP tags for prefixes\n")
1450 int idx_ext_community
= 5;
1452 struct prefix_rd prd
;
1456 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1457 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1459 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1462 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_normal
,
1468 DEFUN (show_ip_bgp_vpn_all_neighbor_routes
,
1469 show_ip_bgp_vpn_all_neighbor_routes_cmd
,
1470 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
1475 "Display information about all VPNv4/VPNv6 NLRIs\n"
1476 "Detailed information on TCP and BGP neighbor connections\n"
1477 "Neighbor to display information about\n"
1478 "Display routes learned from neighbor\n"
1485 u_char uj
= use_json(argc
, argv
);
1489 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1490 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1493 json_object
*json_no
= NULL
;
1494 json_no
= json_object_new_object();
1495 json_object_string_add(json_no
, "warning",
1496 "Malformed address");
1497 vty_out(vty
, "%s\n",
1498 json_object_to_json_string(json_no
));
1499 json_object_free(json_no
);
1501 vty_out(vty
, "Malformed address: %s\n",
1502 argv
[idx_ipv4
]->arg
);
1506 peer
= peer_lookup(NULL
, &su
);
1507 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1509 json_object
*json_no
= NULL
;
1510 json_no
= json_object_new_object();
1511 json_object_string_add(
1513 "No such neighbor or address family");
1514 vty_out(vty
, "%s\n",
1515 json_object_to_json_string(json_no
));
1516 json_object_free(json_no
);
1519 "%% No such neighbor or address family\n");
1523 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_neighbor
,
1529 DEFUN (show_ip_bgp_vpn_rd_neighbor_routes
,
1530 show_ip_bgp_vpn_rd_neighbor_routes_cmd
,
1531 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1536 "Display information for a route distinguisher\n"
1537 "VPN Route Distinguisher\n"
1538 "Detailed information on TCP and BGP neighbor connections\n"
1539 "Neighbor to display information about\n"
1540 "Display routes learned from neighbor\n"
1543 int idx_ext_community
= 5;
1548 struct prefix_rd prd
;
1549 u_char uj
= use_json(argc
, argv
);
1553 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1554 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1557 json_object
*json_no
= NULL
;
1558 json_no
= json_object_new_object();
1559 json_object_string_add(
1561 "Malformed Route Distinguisher");
1562 vty_out(vty
, "%s\n",
1563 json_object_to_json_string(json_no
));
1564 json_object_free(json_no
);
1567 "%% Malformed Route Distinguisher\n");
1571 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1574 json_object
*json_no
= NULL
;
1575 json_no
= json_object_new_object();
1576 json_object_string_add(json_no
, "warning",
1577 "Malformed address");
1578 vty_out(vty
, "%s\n",
1579 json_object_to_json_string(json_no
));
1580 json_object_free(json_no
);
1582 vty_out(vty
, "Malformed address: %s\n",
1583 argv
[idx_ext_community
]->arg
);
1587 peer
= peer_lookup(NULL
, &su
);
1588 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1590 json_object
*json_no
= NULL
;
1591 json_no
= json_object_new_object();
1592 json_object_string_add(
1594 "No such neighbor or address family");
1595 vty_out(vty
, "%s\n",
1596 json_object_to_json_string(json_no
));
1597 json_object_free(json_no
);
1600 "%% No such neighbor or address family\n");
1604 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_neighbor
,
1610 DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes
,
1611 show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd
,
1612 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
1617 "Display information about all VPNv4/VPNv6 NLRIs\n"
1618 "Detailed information on TCP and BGP neighbor connections\n"
1619 "Neighbor to display information about\n"
1620 "Display the routes advertised to a BGP neighbor\n"
1627 u_char uj
= use_json(argc
, argv
);
1631 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1632 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1635 json_object
*json_no
= NULL
;
1636 json_no
= json_object_new_object();
1637 json_object_string_add(json_no
, "warning",
1638 "Malformed address");
1639 vty_out(vty
, "%s\n",
1640 json_object_to_json_string(json_no
));
1641 json_object_free(json_no
);
1643 vty_out(vty
, "Malformed address: %s\n",
1644 argv
[idx_ipv4
]->arg
);
1647 peer
= peer_lookup(NULL
, &su
);
1648 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1650 json_object
*json_no
= NULL
;
1651 json_no
= json_object_new_object();
1652 json_object_string_add(
1654 "No such neighbor or address family");
1655 vty_out(vty
, "%s\n",
1656 json_object_to_json_string(json_no
));
1657 json_object_free(json_no
);
1660 "%% No such neighbor or address family\n");
1663 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_IP
,
1669 DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes
,
1670 show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd
,
1671 "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1676 "Display information for a route distinguisher\n"
1677 "VPN Route Distinguisher\n"
1678 "Detailed information on TCP and BGP neighbor connections\n"
1679 "Neighbor to display information about\n"
1680 "Display the routes advertised to a BGP neighbor\n"
1683 int idx_ext_community
= 5;
1687 struct prefix_rd prd
;
1689 u_char uj
= use_json(argc
, argv
);
1693 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
1694 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1697 json_object
*json_no
= NULL
;
1698 json_no
= json_object_new_object();
1699 json_object_string_add(json_no
, "warning",
1700 "Malformed address");
1701 vty_out(vty
, "%s\n",
1702 json_object_to_json_string(json_no
));
1703 json_object_free(json_no
);
1705 vty_out(vty
, "Malformed address: %s\n",
1706 argv
[idx_ext_community
]->arg
);
1709 peer
= peer_lookup(NULL
, &su
);
1710 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
1712 json_object
*json_no
= NULL
;
1713 json_no
= json_object_new_object();
1714 json_object_string_add(
1716 "No such neighbor or address family");
1717 vty_out(vty
, "%s\n",
1718 json_object_to_json_string(json_no
));
1719 json_object_free(json_no
);
1722 "%% No such neighbor or address family\n");
1726 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1729 json_object
*json_no
= NULL
;
1730 json_no
= json_object_new_object();
1731 json_object_string_add(
1733 "Malformed Route Distinguisher");
1734 vty_out(vty
, "%s\n",
1735 json_object_to_json_string(json_no
));
1736 json_object_free(json_no
);
1739 "%% Malformed Route Distinguisher\n");
1743 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_IP
,
1748 #endif /* KEEP_OLD_VPN_COMMANDS */
1750 void bgp_mplsvpn_init(void)
1752 install_element(BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
1753 install_element(BGP_VPNV4_NODE
, &vpnv4_network_route_map_cmd
);
1754 install_element(BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
1756 install_element(BGP_VPNV6_NODE
, &vpnv6_network_cmd
);
1757 install_element(BGP_VPNV6_NODE
, &no_vpnv6_network_cmd
);
1759 install_element(VIEW_NODE
, &show_bgp_ip_vpn_all_rd_cmd
);
1760 install_element(VIEW_NODE
, &show_bgp_ip_vpn_rd_cmd
);
1761 #ifdef KEEP_OLD_VPN_COMMANDS
1762 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_cmd
);
1763 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_cmd
);
1764 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_tags_cmd
);
1765 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_tags_cmd
);
1766 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_neighbor_routes_cmd
);
1767 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_neighbor_routes_cmd
);
1768 install_element(VIEW_NODE
,
1769 &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd
);
1770 install_element(VIEW_NODE
,
1771 &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd
);
1772 #endif /* KEEP_OLD_VPN_COMMANDS */