1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
19 #include "bgpd/bgpd.h"
20 #include "bgpd/bgp_debug.h"
21 #include "bgpd/bgp_errors.h"
22 #include "bgpd/bgp_table.h"
23 #include "bgpd/bgp_route.h"
24 #include "bgpd/bgp_attr.h"
25 #include "bgpd/bgp_label.h"
26 #include "bgpd/bgp_mplsvpn.h"
27 #include "bgpd/bgp_packet.h"
28 #include "bgpd/bgp_vty.h"
29 #include "bgpd/bgp_vpn.h"
30 #include "bgpd/bgp_community.h"
31 #include "bgpd/bgp_ecommunity.h"
32 #include "bgpd/bgp_zebra.h"
33 #include "bgpd/bgp_nexthop.h"
34 #include "bgpd/bgp_nht.h"
35 #include "bgpd/bgp_evpn.h"
36 #include "bgpd/bgp_memory.h"
39 #include "bgpd/rfapi/rfapi_backend.h"
43 * Definitions and external declarations.
45 extern struct zclient
*zclient
;
47 extern int argv_find_and_parse_vpnvx(struct cmd_token
**argv
, int argc
,
48 int *index
, afi_t
*afi
)
51 if (argv_find(argv
, argc
, "vpnv4", index
)) {
55 } else if (argv_find(argv
, argc
, "vpnv6", index
)) {
63 uint32_t decode_label(mpls_label_t
*label_pnt
)
66 uint8_t *pnt
= (uint8_t *)label_pnt
;
68 l
= ((uint32_t)*pnt
++ << 12);
69 l
|= (uint32_t)*pnt
++ << 4;
70 l
|= (uint32_t)((*pnt
& 0xf0) >> 4);
74 void encode_label(mpls_label_t label
, mpls_label_t
*label_pnt
)
76 uint8_t *pnt
= (uint8_t *)label_pnt
;
79 if (label
== BGP_PREVENT_VRF_2_VRF_LEAK
) {
83 *pnt
++ = (label
>> 12) & 0xff;
84 *pnt
++ = (label
>> 4) & 0xff;
85 *pnt
++ = ((label
<< 4) + 1) & 0xff; /* S=1 */
88 int bgp_nlri_parse_vpn(struct peer
*peer
, struct attr
*attr
,
89 struct bgp_nlri
*packet
)
97 struct prefix_rd prd
= {0};
98 mpls_label_t label
= {0};
101 bool addpath_capable
;
106 prd
.family
= AF_UNSPEC
;
109 struct stream
*data
= stream_new(packet
->length
);
110 stream_put(data
, packet
->nlri
, packet
->length
);
115 addpath_capable
= bgp_addpath_encode_rx(peer
, afi
, safi
);
117 #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
118 while (STREAM_READABLE(data
) > 0) {
119 /* Clear prefix structure. */
120 memset(&p
, 0, sizeof(p
));
122 if (addpath_capable
) {
123 STREAM_GET(&addpath_id
, data
, BGP_ADDPATH_ID_LEN
);
124 addpath_id
= ntohl(addpath_id
);
127 if (STREAM_READABLE(data
) < 1) {
130 "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no prefix length)",
131 peer
->host
, packet
->length
);
132 ret
= BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
136 /* Fetch prefix length. */
137 STREAM_GETC(data
, prefixlen
);
138 p
.family
= afi2family(packet
->afi
);
139 psize
= PSIZE(prefixlen
);
141 if (prefixlen
< VPN_PREFIXLEN_MIN_BYTES
* 8) {
144 "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
145 peer
->host
, prefixlen
);
146 ret
= BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
150 /* sanity check against packet data */
151 if (STREAM_READABLE(data
) < psize
) {
154 "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
155 peer
->host
, prefixlen
, packet
->length
);
156 ret
= BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
160 /* sanity check against storage for the IP address portion */
161 if ((psize
- VPN_PREFIXLEN_MIN_BYTES
) > (ssize_t
)sizeof(p
.u
)) {
164 "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
166 prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8,
168 ret
= BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
172 /* Sanity check against max bitlen of the address family */
173 if ((psize
- VPN_PREFIXLEN_MIN_BYTES
) > prefix_blen(&p
)) {
176 "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
178 prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8,
179 p
.family
, prefix_blen(&p
));
180 ret
= BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
184 /* Copy label to prefix. */
185 if (STREAM_READABLE(data
) < BGP_LABEL_BYTES
) {
188 "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no label)",
189 peer
->host
, packet
->length
);
190 ret
= BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
194 STREAM_GET(&label
, data
, BGP_LABEL_BYTES
);
195 bgp_set_valid_label(&label
);
197 /* Copy routing distinguisher to rd. */
198 if (STREAM_READABLE(data
) < 8) {
201 "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no RD)",
202 peer
->host
, packet
->length
);
203 ret
= BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
206 STREAM_GET(&prd
.val
, data
, 8);
208 /* Decode RD type. */
209 type
= decode_rd_type(prd
.val
);
213 decode_rd_as(&prd
.val
[2], &rd_as
);
217 decode_rd_as4(&prd
.val
[2], &rd_as
);
221 decode_rd_ip(&prd
.val
[2], &rd_ip
);
224 #ifdef ENABLE_BGP_VNC
225 case RD_TYPE_VNC_ETH
:
230 flog_err(EC_BGP_UPDATE_RCV
, "Unknown RD type %d", type
);
231 break; /* just report */
234 /* exclude label & RD */
235 p
.prefixlen
= prefixlen
- VPN_PREFIXLEN_MIN_BYTES
* 8;
236 STREAM_GET(p
.u
.val
, data
, psize
- VPN_PREFIXLEN_MIN_BYTES
);
239 bgp_update(peer
, &p
, addpath_id
, attr
, packet
->afi
,
240 SAFI_MPLS_VPN
, ZEBRA_ROUTE_BGP
,
241 BGP_ROUTE_NORMAL
, &prd
, &label
, 1, 0, NULL
);
243 bgp_withdraw(peer
, &p
, addpath_id
, packet
->afi
,
244 SAFI_MPLS_VPN
, ZEBRA_ROUTE_BGP
,
245 BGP_ROUTE_NORMAL
, &prd
, &label
, 1, NULL
);
248 /* Packet length consistency check. */
249 if (STREAM_READABLE(data
) != 0) {
252 "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
253 peer
->host
, STREAM_READABLE(data
));
254 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
262 "%s [Error] Update packet error / VPN (NLRI of size %u - length error)",
263 peer
->host
, packet
->length
);
264 ret
= BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
270 #undef VPN_PREFIXLEN_MIN_BYTES
274 * This function informs zebra of the label this vrf sets on routes
275 * leaked to VPN. Zebra should install this label in the kernel with
276 * an action of "pop label and then use this vrf's IP FIB to route the PDU."
278 * Sending this vrf-label association is qualified by a) whether vrf->vpn
279 * exporting is active ("export vpn" is enabled, vpn-policy RD and RT list
280 * are set) and b) whether vpn-policy label is set.
282 * If any of these conditions do not hold, then we send MPLS_LABEL_NONE
283 * for this vrf, which zebra interprets to mean "delete this vrf-label
286 void vpn_leak_zebra_vrf_label_update(struct bgp
*bgp
, afi_t afi
)
288 mpls_label_t label
= MPLS_LABEL_NONE
;
289 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
291 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
294 "%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
295 __func__
, bgp
->name_pretty
, afi2str(afi
));
300 if (vpn_leak_to_vpn_active(bgp
, afi
, NULL
)) {
301 label
= bgp
->vpn_policy
[afi
].tovpn_label
;
305 zlog_debug("%s: vrf %s: afi %s: setting label %d for vrf id %d",
306 __func__
, bgp
->name_pretty
, afi2str(afi
), label
,
310 if (label
== BGP_PREVENT_VRF_2_VRF_LEAK
)
311 label
= MPLS_LABEL_NONE
;
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
;
317 * If zebra tells us vrf has become unconfigured, tell zebra not to
318 * use this label to forward to the vrf anymore
320 void vpn_leak_zebra_vrf_label_withdraw(struct bgp
*bgp
, afi_t afi
)
322 mpls_label_t label
= MPLS_LABEL_NONE
;
323 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
325 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
328 "%s: vrf_id not set, can't delete zebra vrf label",
335 zlog_debug("%s: deleting label for vrf %s (id=%d)", __func__
,
336 bgp
->name_pretty
, bgp
->vrf_id
);
339 zclient_send_vrf_label(zclient
, bgp
->vrf_id
, afi
, label
, ZEBRA_LSP_BGP
);
340 bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_label_last_sent
= label
;
344 * This function informs zebra of the srv6-function this vrf sets on routes
345 * leaked to VPN. Zebra should install this srv6-function in the kernel with
346 * an action of "End.DT4/6's IP FIB to route the PDU."
348 void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp
*bgp
, afi_t afi
)
350 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
351 enum seg6local_action_t act
;
352 struct seg6local_context ctx
= {};
353 struct in6_addr
*tovpn_sid
= NULL
;
354 struct in6_addr
*tovpn_sid_ls
= NULL
;
357 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
359 zlog_debug("%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
360 __func__
, bgp
->name_pretty
, afi2str(afi
));
364 tovpn_sid
= bgp
->vpn_policy
[afi
].tovpn_sid
;
367 zlog_debug("%s: vrf %s: afi %s: sid not set", __func__
,
368 bgp
->name_pretty
, afi2str(afi
));
373 zlog_debug("%s: vrf %s: afi %s: setting sid %pI6 for vrf id %d",
374 __func__
, bgp
->name_pretty
, afi2str(afi
), tovpn_sid
,
377 vrf
= vrf_lookup_by_id(bgp
->vrf_id
);
381 ctx
.table
= vrf
->data
.l
.table_id
;
382 act
= afi
== AFI_IP
? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
383 : ZEBRA_SEG6_LOCAL_ACTION_END_DT6
;
384 zclient_send_localsid(zclient
, tovpn_sid
, bgp
->vrf_id
, act
, &ctx
);
386 tovpn_sid_ls
= XCALLOC(MTYPE_BGP_SRV6_SID
, sizeof(struct in6_addr
));
387 *tovpn_sid_ls
= *tovpn_sid
;
388 bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_sid_last_sent
= tovpn_sid_ls
;
392 * This function informs zebra of the srv6-function this vrf sets on routes
393 * leaked to VPN. Zebra should install this srv6-function in the kernel with
394 * an action of "End.DT46's IP FIB to route the PDU."
396 void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp
*bgp
)
398 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
399 enum seg6local_action_t act
;
400 struct seg6local_context ctx
= {};
401 struct in6_addr
*tovpn_sid
= NULL
;
402 struct in6_addr
*tovpn_sid_ls
= NULL
;
405 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
408 "%s: vrf %s: vrf_id not set, can't set zebra vrf label",
409 __func__
, bgp
->name_pretty
);
413 tovpn_sid
= bgp
->tovpn_sid
;
416 zlog_debug("%s: vrf %s: sid not set", __func__
,
422 zlog_debug("%s: vrf %s: setting sid %pI6 for vrf id %d",
423 __func__
, bgp
->name_pretty
, tovpn_sid
, bgp
->vrf_id
);
425 vrf
= vrf_lookup_by_id(bgp
->vrf_id
);
429 ctx
.table
= vrf
->data
.l
.table_id
;
430 act
= ZEBRA_SEG6_LOCAL_ACTION_END_DT46
;
431 zclient_send_localsid(zclient
, tovpn_sid
, bgp
->vrf_id
, act
, &ctx
);
433 tovpn_sid_ls
= XCALLOC(MTYPE_BGP_SRV6_SID
, sizeof(struct in6_addr
));
434 *tovpn_sid_ls
= *tovpn_sid
;
435 bgp
->tovpn_zebra_vrf_sid_last_sent
= tovpn_sid_ls
;
439 * This function informs zebra of the srv6-function this vrf sets on routes
440 * leaked to VPN. Zebra should install this srv6-function in the kernel with
441 * an action of "End.DT4/6/46's IP FIB to route the PDU."
443 void vpn_leak_zebra_vrf_sid_update(struct bgp
*bgp
, afi_t afi
)
445 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
447 if (bgp
->vpn_policy
[afi
].tovpn_sid
)
448 return vpn_leak_zebra_vrf_sid_update_per_af(bgp
, afi
);
451 return vpn_leak_zebra_vrf_sid_update_per_vrf(bgp
);
454 zlog_debug("%s: vrf %s: afi %s: sid not set", __func__
,
455 bgp
->name_pretty
, afi2str(afi
));
459 * If zebra tells us vrf has become unconfigured, tell zebra not to
460 * use this srv6-function to forward to the vrf anymore
462 void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp
*bgp
, afi_t afi
)
464 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
466 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
468 zlog_debug("%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
469 __func__
, bgp
->name_pretty
, afi2str(afi
));
474 zlog_debug("%s: deleting sid for vrf %s afi (id=%d)", __func__
,
475 bgp
->name_pretty
, bgp
->vrf_id
);
477 zclient_send_localsid(zclient
,
478 bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_sid_last_sent
,
479 bgp
->vrf_id
, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC
, NULL
);
480 XFREE(MTYPE_BGP_SRV6_SID
,
481 bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_sid_last_sent
);
485 * If zebra tells us vrf has become unconfigured, tell zebra not to
486 * use this srv6-function to forward to the vrf anymore
488 void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp
*bgp
)
490 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
492 if (bgp
->vrf_id
== VRF_UNKNOWN
) {
495 "%s: vrf %s: vrf_id not set, can't set zebra vrf label",
496 __func__
, bgp
->name_pretty
);
501 zlog_debug("%s: deleting sid for vrf %s (id=%d)", __func__
,
502 bgp
->name_pretty
, bgp
->vrf_id
);
504 zclient_send_localsid(zclient
, bgp
->tovpn_zebra_vrf_sid_last_sent
,
505 bgp
->vrf_id
, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC
,
507 XFREE(MTYPE_BGP_SRV6_SID
, bgp
->tovpn_zebra_vrf_sid_last_sent
);
511 * If zebra tells us vrf has become unconfigured, tell zebra not to
512 * use this srv6-function to forward to the vrf anymore
514 void vpn_leak_zebra_vrf_sid_withdraw(struct bgp
*bgp
, afi_t afi
)
516 if (bgp
->vpn_policy
[afi
].tovpn_zebra_vrf_sid_last_sent
)
517 vpn_leak_zebra_vrf_sid_withdraw_per_af(bgp
, afi
);
519 if (bgp
->tovpn_zebra_vrf_sid_last_sent
)
520 vpn_leak_zebra_vrf_sid_withdraw_per_vrf(bgp
);
523 int vpn_leak_label_callback(
528 struct vpn_policy
*vp
= (struct vpn_policy
*)labelid
;
529 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
532 zlog_debug("%s: label=%u, allocated=%d",
533 __func__
, label
, allocated
);
537 * previously-allocated label is now invalid
539 if (CHECK_FLAG(vp
->flags
, BGP_VPN_POLICY_TOVPN_LABEL_AUTO
) &&
540 (vp
->tovpn_label
!= MPLS_LABEL_NONE
)) {
542 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN
,
543 vp
->afi
, bgp_get_default(), vp
->bgp
);
544 vp
->tovpn_label
= MPLS_LABEL_NONE
;
545 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN
,
546 vp
->afi
, bgp_get_default(), vp
->bgp
);
552 * New label allocation
554 if (!CHECK_FLAG(vp
->flags
, BGP_VPN_POLICY_TOVPN_LABEL_AUTO
)) {
557 * not currently configured for auto label, reject allocation
562 if (vp
->tovpn_label
!= MPLS_LABEL_NONE
) {
563 if (label
== vp
->tovpn_label
) {
564 /* already have same label, accept but do nothing */
567 /* Shouldn't happen: different label allocation */
568 flog_err(EC_BGP_LABEL
,
569 "%s: %s had label %u but got new assignment %u",
570 __func__
, vp
->bgp
->name_pretty
, vp
->tovpn_label
,
575 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN
,
576 vp
->afi
, bgp_get_default(), vp
->bgp
);
577 vp
->tovpn_label
= label
;
578 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN
,
579 vp
->afi
, bgp_get_default(), vp
->bgp
);
584 static void sid_register(struct bgp
*bgp
, const struct in6_addr
*sid
,
585 const char *locator_name
)
587 struct bgp_srv6_function
*func
;
588 func
= XCALLOC(MTYPE_BGP_SRV6_FUNCTION
,
589 sizeof(struct bgp_srv6_function
));
591 snprintf(func
->locator_name
, sizeof(func
->locator_name
),
593 listnode_add(bgp
->srv6_functions
, func
);
596 static void sid_unregister(struct bgp
*bgp
, const struct in6_addr
*sid
)
598 struct listnode
*node
, *nnode
;
599 struct bgp_srv6_function
*func
;
601 for (ALL_LIST_ELEMENTS(bgp
->srv6_functions
, node
, nnode
, func
))
602 if (sid_same(&func
->sid
, sid
)) {
603 listnode_delete(bgp
->srv6_functions
, func
);
604 XFREE(MTYPE_BGP_SRV6_FUNCTION
, func
);
608 static bool sid_exist(struct bgp
*bgp
, const struct in6_addr
*sid
)
610 struct listnode
*node
;
611 struct bgp_srv6_function
*func
;
613 for (ALL_LIST_ELEMENTS_RO(bgp
->srv6_functions
, node
, func
))
614 if (sid_same(&func
->sid
, sid
))
620 * This function generates a new SID based on bgp->srv6_locator_chunks and
621 * index. The locator and generated SID are stored in arguments sid_locator
622 * and sid, respectively.
624 * if index != 0: try to allocate as index-mode
625 * else: try to allocate as auto-mode
627 static uint32_t alloc_new_sid(struct bgp
*bgp
, uint32_t index
,
628 struct srv6_locator_chunk
*sid_locator_chunk
,
629 struct in6_addr
*sid
)
631 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_LABEL
);
632 struct listnode
*node
;
633 struct srv6_locator_chunk
*chunk
;
634 bool alloced
= false;
637 uint8_t func_len
= 0, shift_len
= 0;
638 uint32_t index_max
= 0;
640 if (!bgp
|| !sid_locator_chunk
|| !sid
)
643 for (ALL_LIST_ELEMENTS_RO(bgp
->srv6_locator_chunks
, node
, chunk
)) {
644 if (chunk
->function_bits_length
>
645 BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH
) {
648 "%s: invalid SRv6 Locator chunk (%pFX): Function Length must be less or equal to %d",
649 __func__
, &chunk
->prefix
,
650 BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH
);
654 index_max
= (1 << chunk
->function_bits_length
) - 1;
656 if (index
> index_max
) {
659 "%s: skipped SRv6 Locator chunk (%pFX): Function Length is too short to support specified index (%u)",
660 __func__
, &chunk
->prefix
, index
);
664 *sid
= chunk
->prefix
.prefix
;
665 *sid_locator_chunk
= *chunk
;
666 offset
= chunk
->block_bits_length
+ chunk
->node_bits_length
;
667 func_len
= chunk
->function_bits_length
;
668 shift_len
= BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH
- func_len
;
671 label
= index
<< shift_len
;
672 if (label
< MPLS_LABEL_UNRESERVED_MIN
) {
675 "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
676 __func__
, &chunk
->prefix
,
681 transpose_sid(sid
, label
, offset
, func_len
);
682 if (sid_exist(bgp
, sid
))
688 for (uint32_t i
= 1; i
< index_max
; i
++) {
689 label
= i
<< shift_len
;
690 if (label
< MPLS_LABEL_UNRESERVED_MIN
) {
693 "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
694 __func__
, &chunk
->prefix
,
698 transpose_sid(sid
, label
, offset
, func_len
);
699 if (sid_exist(bgp
, sid
))
709 sid_register(bgp
, sid
, bgp
->srv6_locator_name
);
713 void ensure_vrf_tovpn_sid_per_af(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
,
716 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
717 struct srv6_locator_chunk
*tovpn_sid_locator
;
718 struct in6_addr
*tovpn_sid
;
719 uint32_t tovpn_sid_index
= 0, tovpn_sid_transpose_label
;
720 bool tovpn_sid_auto
= false;
723 zlog_debug("%s: try to allocate new SID for vrf %s: afi %s",
724 __func__
, bgp_vrf
->name_pretty
, afi2str(afi
));
726 /* skip when tovpn sid is already allocated on vrf instance */
727 if (bgp_vrf
->vpn_policy
[afi
].tovpn_sid
)
731 * skip when bgp vpn instance ins't allocated
732 * or srv6 locator chunk isn't allocated
734 if (!bgp_vpn
|| !bgp_vpn
->srv6_locator_chunks
)
737 tovpn_sid_index
= bgp_vrf
->vpn_policy
[afi
].tovpn_sid_index
;
738 tovpn_sid_auto
= CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
739 BGP_VPN_POLICY_TOVPN_SID_AUTO
);
741 /* skip when VPN isn't configured on vrf-instance */
742 if (tovpn_sid_index
== 0 && !tovpn_sid_auto
)
745 /* check invalid case both configured index and auto */
746 if (tovpn_sid_index
!= 0 && tovpn_sid_auto
) {
747 zlog_err("%s: index-mode and auto-mode both selected. ignored.",
752 tovpn_sid_locator
= srv6_locator_chunk_alloc();
753 tovpn_sid
= XCALLOC(MTYPE_BGP_SRV6_SID
, sizeof(struct in6_addr
));
755 tovpn_sid_transpose_label
= alloc_new_sid(bgp_vpn
, tovpn_sid_index
,
756 tovpn_sid_locator
, tovpn_sid
);
758 if (tovpn_sid_transpose_label
== 0) {
761 "%s: not allocated new sid for vrf %s: afi %s",
762 __func__
, bgp_vrf
->name_pretty
, afi2str(afi
));
763 srv6_locator_chunk_free(&tovpn_sid_locator
);
764 XFREE(MTYPE_BGP_SRV6_SID
, tovpn_sid
);
769 zlog_debug("%s: new sid %pI6 allocated for vrf %s: afi %s",
770 __func__
, tovpn_sid
, bgp_vrf
->name_pretty
,
773 bgp_vrf
->vpn_policy
[afi
].tovpn_sid
= tovpn_sid
;
774 bgp_vrf
->vpn_policy
[afi
].tovpn_sid_locator
= tovpn_sid_locator
;
775 bgp_vrf
->vpn_policy
[afi
].tovpn_sid_transpose_label
=
776 tovpn_sid_transpose_label
;
779 void ensure_vrf_tovpn_sid_per_vrf(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
)
781 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
782 struct srv6_locator_chunk
*tovpn_sid_locator
;
783 struct in6_addr
*tovpn_sid
;
784 uint32_t tovpn_sid_index
= 0, tovpn_sid_transpose_label
;
785 bool tovpn_sid_auto
= false;
788 zlog_debug("%s: try to allocate new SID for vrf %s", __func__
,
789 bgp_vrf
->name_pretty
);
791 /* skip when tovpn sid is already allocated on vrf instance */
792 if (bgp_vrf
->tovpn_sid
)
796 * skip when bgp vpn instance ins't allocated
797 * or srv6 locator chunk isn't allocated
799 if (!bgp_vpn
|| !bgp_vpn
->srv6_locator_chunks
)
802 tovpn_sid_index
= bgp_vrf
->tovpn_sid_index
;
803 tovpn_sid_auto
= CHECK_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_TOVPN_SID_AUTO
);
805 /* skip when VPN isn't configured on vrf-instance */
806 if (tovpn_sid_index
== 0 && !tovpn_sid_auto
)
809 /* check invalid case both configured index and auto */
810 if (tovpn_sid_index
!= 0 && tovpn_sid_auto
) {
811 zlog_err("%s: index-mode and auto-mode both selected. ignored.",
816 tovpn_sid_locator
= srv6_locator_chunk_alloc();
817 tovpn_sid
= XCALLOC(MTYPE_BGP_SRV6_SID
, sizeof(struct in6_addr
));
819 tovpn_sid_transpose_label
= alloc_new_sid(bgp_vpn
, tovpn_sid_index
,
820 tovpn_sid_locator
, tovpn_sid
);
822 if (tovpn_sid_transpose_label
== 0) {
824 zlog_debug("%s: not allocated new sid for vrf %s",
825 __func__
, bgp_vrf
->name_pretty
);
826 srv6_locator_chunk_free(&tovpn_sid_locator
);
827 XFREE(MTYPE_BGP_SRV6_SID
, tovpn_sid
);
832 zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__
,
833 tovpn_sid
, bgp_vrf
->name_pretty
);
835 bgp_vrf
->tovpn_sid
= tovpn_sid
;
836 bgp_vrf
->tovpn_sid_locator
= tovpn_sid_locator
;
837 bgp_vrf
->tovpn_sid_transpose_label
= tovpn_sid_transpose_label
;
840 void ensure_vrf_tovpn_sid(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
, afi_t afi
)
843 if (bgp_vrf
->vpn_policy
[afi
].tovpn_sid_index
!= 0 ||
844 CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
845 BGP_VPN_POLICY_TOVPN_SID_AUTO
))
846 return ensure_vrf_tovpn_sid_per_af(bgp_vpn
, bgp_vrf
, afi
);
849 if (bgp_vrf
->tovpn_sid_index
!= 0 ||
850 CHECK_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_TOVPN_SID_AUTO
))
851 return ensure_vrf_tovpn_sid_per_vrf(bgp_vpn
, bgp_vrf
);
854 void delete_vrf_tovpn_sid_per_af(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
,
857 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
858 uint32_t tovpn_sid_index
= 0;
859 bool tovpn_sid_auto
= false;
862 zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__
,
863 bgp_vrf
->name_pretty
, afi2str(afi
));
865 tovpn_sid_index
= bgp_vrf
->vpn_policy
[afi
].tovpn_sid_index
;
866 tovpn_sid_auto
= CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
867 BGP_VPN_POLICY_TOVPN_SID_AUTO
);
869 /* skip when VPN is configured on vrf-instance */
870 if (tovpn_sid_index
!= 0 || tovpn_sid_auto
)
873 srv6_locator_chunk_free(&bgp_vrf
->vpn_policy
[afi
].tovpn_sid_locator
);
875 if (bgp_vrf
->vpn_policy
[afi
].tovpn_sid
) {
876 sid_unregister(bgp_vpn
, bgp_vrf
->vpn_policy
[afi
].tovpn_sid
);
877 XFREE(MTYPE_BGP_SRV6_SID
, bgp_vrf
->vpn_policy
[afi
].tovpn_sid
);
879 bgp_vrf
->vpn_policy
[afi
].tovpn_sid_transpose_label
= 0;
882 void delete_vrf_tovpn_sid_per_vrf(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
)
884 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
885 uint32_t tovpn_sid_index
= 0;
886 bool tovpn_sid_auto
= false;
889 zlog_debug("%s: try to remove SID for vrf %s", __func__
,
890 bgp_vrf
->name_pretty
);
892 tovpn_sid_index
= bgp_vrf
->tovpn_sid_index
;
894 CHECK_FLAG(bgp_vrf
->vrf_flags
, BGP_VPN_POLICY_TOVPN_SID_AUTO
);
896 /* skip when VPN is configured on vrf-instance */
897 if (tovpn_sid_index
!= 0 || tovpn_sid_auto
)
900 srv6_locator_chunk_free(&bgp_vrf
->tovpn_sid_locator
);
902 if (bgp_vrf
->tovpn_sid
) {
903 sid_unregister(bgp_vpn
, bgp_vrf
->tovpn_sid
);
904 XFREE(MTYPE_BGP_SRV6_SID
, bgp_vrf
->tovpn_sid
);
906 bgp_vrf
->tovpn_sid_transpose_label
= 0;
909 void delete_vrf_tovpn_sid(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
, afi_t afi
)
911 delete_vrf_tovpn_sid_per_af(bgp_vpn
, bgp_vrf
, afi
);
912 delete_vrf_tovpn_sid_per_vrf(bgp_vpn
, bgp_vrf
);
916 * This function embeds upper `len` bits of `label` in `sid`,
917 * starting at offset `offset` as seen from the MSB of `sid`.
919 * e.g. Given that `label` is 0x12345 and `len` is 16,
920 * then `label` will be embedded in `sid` as follows:
923 * label: 0001 0002 0003 0004 0005
924 * sid: .... 0001 0002 0003 0004
930 * e.g. Given that `label` is 0x12345 and `len` is 8,
931 * `label` will be embedded in `sid` as follows:
934 * label: 0001 0002 0003 0004 0005
935 * sid: .... 0001 0002 0000 0000
941 void transpose_sid(struct in6_addr
*sid
, uint32_t label
, uint8_t offset
,
944 for (uint8_t idx
= 0; idx
< len
; idx
++) {
945 uint8_t tidx
= offset
+ idx
;
946 sid
->s6_addr
[tidx
/ 8] &= ~(0x1 << (7 - tidx
% 8));
947 if (label
>> (19 - idx
) & 0x1)
948 sid
->s6_addr
[tidx
/ 8] |= 0x1 << (7 - tidx
% 8);
952 static bool labels_same(struct bgp_path_info
*bpi
, mpls_label_t
*label
,
964 if (n
!= bpi
->extra
->num_labels
)
967 for (i
= 0; i
< n
; ++i
) {
968 if (label
[i
] != bpi
->extra
->label
[i
])
975 * make encoded route labels match specified encoded label set
977 static void setlabels(struct bgp_path_info
*bpi
,
978 mpls_label_t
*label
, /* array of labels */
983 assert(num_labels
<= BGP_MAX_LABELS
);
987 bpi
->extra
->num_labels
= 0;
991 struct bgp_path_info_extra
*extra
= bgp_path_info_extra_get(bpi
);
994 for (i
= 0; i
< num_labels
; ++i
) {
995 extra
->label
[i
] = label
[i
];
996 if (!bgp_is_valid_label(&label
[i
])) {
997 bgp_set_valid_label(&extra
->label
[i
]);
1000 extra
->num_labels
= num_labels
;
1004 * make encoded route SIDs match specified encoded sid set
1006 static void setsids(struct bgp_path_info
*bpi
,
1007 struct in6_addr
*sid
,
1011 struct bgp_path_info_extra
*extra
;
1015 assert(num_sids
<= BGP_MAX_SIDS
);
1019 bpi
->extra
->num_sids
= 0;
1023 extra
= bgp_path_info_extra_get(bpi
);
1024 for (i
= 0; i
< num_sids
; i
++)
1025 memcpy(&extra
->sid
[i
].sid
, &sid
[i
], sizeof(struct in6_addr
));
1026 extra
->num_sids
= num_sids
;
1029 static void unsetsids(struct bgp_path_info
*bpi
)
1031 struct bgp_path_info_extra
*extra
;
1033 extra
= bgp_path_info_extra_get(bpi
);
1034 extra
->num_sids
= 0;
1035 memset(extra
->sid
, 0, sizeof(extra
->sid
));
1038 static bool leak_update_nexthop_valid(struct bgp
*to_bgp
, struct bgp_dest
*bn
,
1039 struct attr
*new_attr
, afi_t afi
,
1041 struct bgp_path_info
*source_bpi
,
1042 struct bgp_path_info
*bpi
,
1043 struct bgp
*bgp_orig
,
1044 const struct prefix
*p
, int debug
)
1046 struct bgp_path_info
*bpi_ultimate
;
1047 struct bgp
*bgp_nexthop
;
1050 bpi_ultimate
= bgp_get_imported_bpi_ultimate(source_bpi
);
1052 if (bpi
->extra
&& bpi
->extra
->bgp_orig
)
1053 bgp_nexthop
= bpi
->extra
->bgp_orig
;
1055 bgp_nexthop
= bgp_orig
;
1058 * No nexthop tracking for redistributed routes, for
1059 * EVPN-imported routes that get leaked, or for routes
1060 * leaked between VRFs with accept-own community.
1062 if (bpi_ultimate
->sub_type
== BGP_ROUTE_REDISTRIBUTE
||
1063 is_pi_family_evpn(bpi_ultimate
) ||
1064 CHECK_FLAG(bpi_ultimate
->flags
, BGP_PATH_ACCEPT_OWN
))
1068 * TBD do we need to do anything about the
1069 * 'connected' parameter?
1071 nh_valid
= bgp_find_or_add_nexthop(to_bgp
, bgp_nexthop
, afi
,
1072 safi
, bpi
, NULL
, 0, p
);
1075 * If you are using SRv6 VPN instead of MPLS, it need to check
1076 * the SID allocation. If the sid is not allocated, the rib
1079 if (to_bgp
->srv6_enabled
&&
1080 (!new_attr
->srv6_l3vpn
&& !new_attr
->srv6_vpn
)) {
1085 zlog_debug("%s: %pFX nexthop is %svalid (in %s)", __func__
, p
,
1086 (nh_valid
? "" : "not "), bgp_nexthop
->name_pretty
);
1092 * returns pointer to new bgp_path_info upon success
1094 static struct bgp_path_info
*
1095 leak_update(struct bgp
*to_bgp
, struct bgp_dest
*bn
,
1096 struct attr
*new_attr
, /* already interned */
1097 afi_t afi
, safi_t safi
, struct bgp_path_info
*source_bpi
,
1098 mpls_label_t
*label
, uint32_t num_labels
, struct bgp
*bgp_orig
,
1099 struct prefix
*nexthop_orig
, int nexthop_self_flag
, int debug
)
1101 const struct prefix
*p
= bgp_dest_get_prefix(bn
);
1102 struct bgp_path_info
*bpi
;
1103 struct bgp_path_info
*new;
1104 struct bgp_path_info_extra
*extra
;
1105 uint32_t num_sids
= 0;
1106 void *parent
= source_bpi
;
1108 if (new_attr
->srv6_l3vpn
|| new_attr
->srv6_vpn
)
1113 "%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d",
1114 __func__
, to_bgp
->name_pretty
, bn
, source_bpi
->type
,
1115 source_bpi
->sub_type
);
1118 * Routes that are redistributed into BGP from zebra do not get
1119 * nexthop tracking. However, if those routes are subsequently
1120 * imported to other RIBs within BGP, the leaked routes do not
1121 * carry the original BGP_ROUTE_REDISTRIBUTE sub_type. Therefore,
1122 * in order to determine if the route we are currently leaking
1123 * should have nexthop tracking, we must find the ultimate
1124 * parent so we can check its sub_type.
1126 * As of now, source_bpi may at most be a second-generation route
1127 * (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
1128 * Using a loop here supports more complex intra-bgp import-export
1129 * schemes that could be implemented in the future.
1136 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
1137 if (bpi
->extra
&& bpi
->extra
->parent
== parent
)
1142 bool labelssame
= labels_same(bpi
, label
, num_labels
);
1144 if (CHECK_FLAG(source_bpi
->flags
, BGP_PATH_REMOVED
)
1145 && CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
1148 "%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, being removed, not leaking",
1149 __func__
, to_bgp
->name_pretty
,
1150 source_bpi
->flags
, bpi
->flags
, p
);
1155 if (attrhash_cmp(bpi
->attr
, new_attr
) && labelssame
1156 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
1158 bgp_attr_unintern(&new_attr
);
1161 "%s: ->%s: %pBD: Found route, no change",
1162 __func__
, to_bgp
->name_pretty
, bn
);
1166 /* If the RT was changed via extended communities as an
1167 * import/export list, we should withdraw implicitly the old
1169 * For instance, RT list was modified using route-maps:
1170 * route-map test permit 10
1171 * set extcommunity rt none
1173 if (CHECK_FLAG(bpi
->attr
->flag
,
1174 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) &&
1175 CHECK_FLAG(new_attr
->flag
,
1176 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
1177 if (!ecommunity_cmp(
1178 bgp_attr_get_ecommunity(bpi
->attr
),
1179 bgp_attr_get_ecommunity(new_attr
))) {
1180 vpn_leak_to_vrf_withdraw(bpi
);
1181 bgp_aggregate_decrement(to_bgp
, p
, bpi
, afi
,
1183 bgp_path_info_delete(bn
, bpi
);
1187 /* attr is changed */
1188 bgp_path_info_set_flag(bn
, bpi
, BGP_PATH_ATTR_CHANGED
);
1190 /* Rewrite BGP route information. */
1191 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1192 bgp_path_info_restore(bn
, bpi
);
1194 bgp_aggregate_decrement(to_bgp
, p
, bpi
, afi
, safi
);
1195 bgp_attr_unintern(&bpi
->attr
);
1196 bpi
->attr
= new_attr
;
1197 bpi
->uptime
= monotime(NULL
);
1203 setlabels(bpi
, label
, num_labels
);
1209 if (new_attr
->srv6_l3vpn
) {
1210 setsids(bpi
, &new_attr
->srv6_l3vpn
->sid
,
1213 extra
= bgp_path_info_extra_get(bpi
);
1215 extra
->sid
[0].loc_block_len
=
1216 new_attr
->srv6_l3vpn
->loc_block_len
;
1217 extra
->sid
[0].loc_node_len
=
1218 new_attr
->srv6_l3vpn
->loc_node_len
;
1219 extra
->sid
[0].func_len
=
1220 new_attr
->srv6_l3vpn
->func_len
;
1221 extra
->sid
[0].arg_len
=
1222 new_attr
->srv6_l3vpn
->arg_len
;
1223 extra
->sid
[0].transposition_len
=
1224 new_attr
->srv6_l3vpn
->transposition_len
;
1225 extra
->sid
[0].transposition_offset
=
1226 new_attr
->srv6_l3vpn
1227 ->transposition_offset
;
1228 } else if (new_attr
->srv6_vpn
)
1229 setsids(bpi
, &new_attr
->srv6_vpn
->sid
,
1234 if (nexthop_self_flag
)
1235 bgp_path_info_set_flag(bn
, bpi
, BGP_PATH_ANNC_NH_SELF
);
1237 if (CHECK_FLAG(source_bpi
->flags
, BGP_PATH_ACCEPT_OWN
))
1238 bgp_path_info_set_flag(bn
, bpi
, BGP_PATH_ACCEPT_OWN
);
1240 if (leak_update_nexthop_valid(to_bgp
, bn
, new_attr
, afi
, safi
,
1241 source_bpi
, bpi
, bgp_orig
, p
,
1243 bgp_path_info_set_flag(bn
, bpi
, BGP_PATH_VALID
);
1245 bgp_path_info_unset_flag(bn
, bpi
, BGP_PATH_VALID
);
1247 /* Process change. */
1248 bgp_aggregate_increment(to_bgp
, p
, bpi
, afi
, safi
);
1249 bgp_process(to_bgp
, bn
, afi
, safi
);
1250 bgp_dest_unlock_node(bn
);
1253 zlog_debug("%s: ->%s: %pBD Found route, changed attr",
1254 __func__
, to_bgp
->name_pretty
, bn
);
1259 if (CHECK_FLAG(source_bpi
->flags
, BGP_PATH_REMOVED
)) {
1262 "%s: ->%s(s_flags: 0x%x): %pFX: New route, being removed, not leaking",
1263 __func__
, to_bgp
->name_pretty
,
1264 source_bpi
->flags
, p
);
1269 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_IMPORTED
, 0,
1270 to_bgp
->peer_self
, new_attr
, bn
);
1272 if (source_bpi
->peer
) {
1273 extra
= bgp_path_info_extra_get(new);
1274 extra
->peer_orig
= peer_lock(source_bpi
->peer
);
1277 if (nexthop_self_flag
)
1278 bgp_path_info_set_flag(bn
, new, BGP_PATH_ANNC_NH_SELF
);
1280 if (CHECK_FLAG(source_bpi
->flags
, BGP_PATH_ACCEPT_OWN
))
1281 bgp_path_info_set_flag(bn
, new, BGP_PATH_ACCEPT_OWN
);
1283 bgp_path_info_extra_get(new);
1289 if (new_attr
->srv6_l3vpn
) {
1290 setsids(new, &new_attr
->srv6_l3vpn
->sid
, num_sids
);
1292 extra
= bgp_path_info_extra_get(new);
1294 extra
->sid
[0].loc_block_len
=
1295 new_attr
->srv6_l3vpn
->loc_block_len
;
1296 extra
->sid
[0].loc_node_len
=
1297 new_attr
->srv6_l3vpn
->loc_node_len
;
1298 extra
->sid
[0].func_len
= new_attr
->srv6_l3vpn
->func_len
;
1299 extra
->sid
[0].arg_len
= new_attr
->srv6_l3vpn
->arg_len
;
1300 extra
->sid
[0].transposition_len
=
1301 new_attr
->srv6_l3vpn
->transposition_len
;
1302 extra
->sid
[0].transposition_offset
=
1303 new_attr
->srv6_l3vpn
->transposition_offset
;
1304 } else if (new_attr
->srv6_vpn
)
1305 setsids(new, &new_attr
->srv6_vpn
->sid
, num_sids
);
1310 setlabels(new, label
, num_labels
);
1312 new->extra
->parent
= bgp_path_info_lock(parent
);
1314 (struct bgp_dest
*)((struct bgp_path_info
*)parent
)->net
);
1316 new->extra
->bgp_orig
= bgp_lock(bgp_orig
);
1318 new->extra
->nexthop_orig
= *nexthop_orig
;
1320 if (leak_update_nexthop_valid(to_bgp
, bn
, new_attr
, afi
, safi
,
1321 source_bpi
, new, bgp_orig
, p
, debug
))
1322 bgp_path_info_set_flag(bn
, new, BGP_PATH_VALID
);
1324 bgp_path_info_unset_flag(bn
, new, BGP_PATH_VALID
);
1326 bgp_aggregate_increment(to_bgp
, p
, new, afi
, safi
);
1327 bgp_path_info_add(bn
, new);
1329 bgp_dest_unlock_node(bn
);
1330 bgp_process(to_bgp
, bn
, afi
, safi
);
1333 zlog_debug("%s: ->%s: %pBD: Added new route", __func__
,
1334 to_bgp
->name_pretty
, bn
);
1339 /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
1340 void vpn_leak_from_vrf_update(struct bgp
*to_bgp
, /* to */
1341 struct bgp
*from_bgp
, /* from */
1342 struct bgp_path_info
*path_vrf
) /* route */
1344 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
1345 const struct prefix
*p
= bgp_dest_get_prefix(path_vrf
->net
);
1346 afi_t afi
= family2afi(p
->family
);
1347 struct attr static_attr
= {0};
1348 struct attr
*new_attr
= NULL
;
1349 safi_t safi
= SAFI_MPLS_VPN
;
1350 mpls_label_t label_val
;
1352 struct bgp_dest
*bn
;
1353 const char *debugmsg
;
1354 int nexthop_self_flag
= 0;
1357 zlog_debug("%s: from vrf %s", __func__
, from_bgp
->name_pretty
);
1359 if (debug
&& bgp_attr_get_ecommunity(path_vrf
->attr
)) {
1360 char *s
= ecommunity_ecom2str(
1361 bgp_attr_get_ecommunity(path_vrf
->attr
),
1362 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1364 zlog_debug("%s: %s path_vrf->type=%d, EC{%s}", __func__
,
1365 from_bgp
->name
, path_vrf
->type
, s
);
1366 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1374 zlog_debug("%s: can't get afi of prefix", __func__
);
1378 /* Is this route exportable into the VPN table? */
1379 if (!is_route_injectable_into_vpn(path_vrf
))
1382 if (!vpn_leak_to_vpn_active(from_bgp
, afi
, &debugmsg
)) {
1384 zlog_debug("%s: %s skipping: %s", __func__
,
1385 from_bgp
->name
, debugmsg
);
1390 static_attr
= *path_vrf
->attr
;
1393 * route map handling
1395 if (from_bgp
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
]) {
1396 struct bgp_path_info info
;
1397 route_map_result_t ret
;
1399 memset(&info
, 0, sizeof(info
));
1400 info
.peer
= to_bgp
->peer_self
;
1401 info
.attr
= &static_attr
;
1402 ret
= route_map_apply(from_bgp
->vpn_policy
[afi
]
1403 .rmap
[BGP_VPN_POLICY_DIR_TOVPN
],
1405 if (RMAP_DENYMATCH
== ret
) {
1406 bgp_attr_flush(&static_attr
); /* free any added parts */
1409 "%s: vrf %s route map \"%s\" says DENY, returning",
1410 __func__
, from_bgp
->name_pretty
,
1411 from_bgp
->vpn_policy
[afi
]
1412 .rmap
[BGP_VPN_POLICY_DIR_TOVPN
]
1418 if (debug
&& bgp_attr_get_ecommunity(&static_attr
)) {
1419 char *s
= ecommunity_ecom2str(
1420 bgp_attr_get_ecommunity(&static_attr
),
1421 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1423 zlog_debug("%s: post route map static_attr.ecommunity{%s}",
1425 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1429 * Add the vpn-policy rt-list
1431 struct ecommunity
*old_ecom
;
1432 struct ecommunity
*new_ecom
;
1434 /* Export with the 'from' instance's export RTs. */
1435 /* If doing VRF-to-VRF leaking, strip existing RTs first. */
1436 old_ecom
= bgp_attr_get_ecommunity(&static_attr
);
1438 new_ecom
= ecommunity_dup(old_ecom
);
1439 if (CHECK_FLAG(from_bgp
->af_flags
[afi
][SAFI_UNICAST
],
1440 BGP_CONFIG_VRF_TO_VRF_EXPORT
))
1441 ecommunity_strip_rts(new_ecom
);
1442 new_ecom
= ecommunity_merge(
1443 new_ecom
, from_bgp
->vpn_policy
[afi
]
1444 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]);
1445 if (!old_ecom
->refcnt
)
1446 ecommunity_free(&old_ecom
);
1448 new_ecom
= ecommunity_dup(
1449 from_bgp
->vpn_policy
[afi
]
1450 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]);
1452 bgp_attr_set_ecommunity(&static_attr
, new_ecom
);
1454 if (debug
&& bgp_attr_get_ecommunity(&static_attr
)) {
1455 char *s
= ecommunity_ecom2str(
1456 bgp_attr_get_ecommunity(&static_attr
),
1457 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1459 zlog_debug("%s: post merge static_attr.ecommunity{%s}",
1461 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1464 community_strip_accept_own(&static_attr
);
1467 /* if policy nexthop not set, use 0 */
1468 if (CHECK_FLAG(from_bgp
->vpn_policy
[afi
].flags
,
1469 BGP_VPN_POLICY_TOVPN_NEXTHOP_SET
)) {
1470 struct prefix
*nexthop
=
1471 &from_bgp
->vpn_policy
[afi
].tovpn_nexthop
;
1473 switch (nexthop
->family
) {
1475 /* prevent mp_nexthop_global_in <- self in bgp_route.c
1477 static_attr
.nexthop
.s_addr
= nexthop
->u
.prefix4
.s_addr
;
1479 static_attr
.mp_nexthop_global_in
= nexthop
->u
.prefix4
;
1480 static_attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
1484 static_attr
.mp_nexthop_global
= nexthop
->u
.prefix6
;
1485 static_attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1492 if (!CHECK_FLAG(from_bgp
->af_flags
[afi
][SAFI_UNICAST
],
1493 BGP_CONFIG_VRF_TO_VRF_EXPORT
)) {
1494 if (afi
== AFI_IP
&&
1495 !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf
->attr
)) {
1497 * For ipv4, copy to multiprotocol
1500 static_attr
.mp_nexthop_global_in
=
1501 static_attr
.nexthop
;
1502 static_attr
.mp_nexthop_len
=
1503 BGP_ATTR_NHLEN_IPV4
;
1505 * XXX Leave static_attr.nexthop
1509 ~ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1512 /* Update based on next-hop family to account for
1513 * RFC 5549 (BGP unnumbered) scenario. Note that
1514 * specific action is only needed for the case of
1515 * IPv4 nexthops as the attr has been copied
1519 && !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf
->attr
)) {
1520 static_attr
.mp_nexthop_global_in
.s_addr
=
1521 static_attr
.nexthop
.s_addr
;
1522 static_attr
.mp_nexthop_len
=
1523 BGP_ATTR_NHLEN_IPV4
;
1525 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1528 nexthop_self_flag
= 1;
1531 label_val
= from_bgp
->vpn_policy
[afi
].tovpn_label
;
1532 if (label_val
== MPLS_LABEL_NONE
) {
1533 encode_label(MPLS_LABEL_IMPLICIT_NULL
, &label
);
1535 encode_label(label_val
, &label
);
1538 /* Set originator ID to "me" */
1539 SET_FLAG(static_attr
.flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
));
1540 static_attr
.originator_id
= to_bgp
->router_id
;
1542 /* Set SID for SRv6 VPN */
1543 if (from_bgp
->vpn_policy
[afi
].tovpn_sid_locator
) {
1544 struct srv6_locator_chunk
*locator
=
1545 from_bgp
->vpn_policy
[afi
].tovpn_sid_locator
;
1547 from_bgp
->vpn_policy
[afi
].tovpn_sid_transpose_label
,
1549 static_attr
.srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
1550 sizeof(struct bgp_attr_srv6_l3vpn
));
1551 static_attr
.srv6_l3vpn
->sid_flags
= 0x00;
1552 static_attr
.srv6_l3vpn
->endpoint_behavior
=
1554 ? (CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
)
1555 ? SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID
1556 : SRV6_ENDPOINT_BEHAVIOR_END_DT4
)
1557 : (CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
)
1558 ? SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID
1559 : SRV6_ENDPOINT_BEHAVIOR_END_DT6
);
1560 static_attr
.srv6_l3vpn
->loc_block_len
=
1561 from_bgp
->vpn_policy
[afi
]
1562 .tovpn_sid_locator
->block_bits_length
;
1563 static_attr
.srv6_l3vpn
->loc_node_len
=
1564 from_bgp
->vpn_policy
[afi
]
1565 .tovpn_sid_locator
->node_bits_length
;
1566 static_attr
.srv6_l3vpn
->func_len
=
1567 from_bgp
->vpn_policy
[afi
]
1568 .tovpn_sid_locator
->function_bits_length
;
1569 static_attr
.srv6_l3vpn
->arg_len
=
1570 from_bgp
->vpn_policy
[afi
]
1571 .tovpn_sid_locator
->argument_bits_length
;
1572 static_attr
.srv6_l3vpn
->transposition_len
=
1573 from_bgp
->vpn_policy
[afi
]
1574 .tovpn_sid_locator
->function_bits_length
;
1575 static_attr
.srv6_l3vpn
->transposition_offset
=
1576 from_bgp
->vpn_policy
[afi
]
1577 .tovpn_sid_locator
->block_bits_length
+
1578 from_bgp
->vpn_policy
[afi
]
1579 .tovpn_sid_locator
->node_bits_length
;
1581 memcpy(&static_attr
.srv6_l3vpn
->sid
,
1582 &from_bgp
->vpn_policy
[afi
]
1583 .tovpn_sid_locator
->prefix
.prefix
,
1584 sizeof(struct in6_addr
));
1585 } else if (from_bgp
->tovpn_sid_locator
) {
1586 struct srv6_locator_chunk
*locator
=
1587 from_bgp
->tovpn_sid_locator
;
1588 encode_label(from_bgp
->tovpn_sid_transpose_label
, &label
);
1589 static_attr
.srv6_l3vpn
=
1590 XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
1591 sizeof(struct bgp_attr_srv6_l3vpn
));
1592 static_attr
.srv6_l3vpn
->sid_flags
= 0x00;
1593 static_attr
.srv6_l3vpn
->endpoint_behavior
=
1594 CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
)
1595 ? SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID
1596 : SRV6_ENDPOINT_BEHAVIOR_END_DT46
;
1597 static_attr
.srv6_l3vpn
->loc_block_len
=
1598 from_bgp
->tovpn_sid_locator
->block_bits_length
;
1599 static_attr
.srv6_l3vpn
->loc_node_len
=
1600 from_bgp
->tovpn_sid_locator
->node_bits_length
;
1601 static_attr
.srv6_l3vpn
->func_len
=
1602 from_bgp
->tovpn_sid_locator
->function_bits_length
;
1603 static_attr
.srv6_l3vpn
->arg_len
=
1604 from_bgp
->tovpn_sid_locator
->argument_bits_length
;
1605 static_attr
.srv6_l3vpn
->transposition_len
=
1606 from_bgp
->tovpn_sid_locator
->function_bits_length
;
1607 static_attr
.srv6_l3vpn
->transposition_offset
=
1608 from_bgp
->tovpn_sid_locator
->block_bits_length
+
1609 from_bgp
->tovpn_sid_locator
->node_bits_length
;
1610 memcpy(&static_attr
.srv6_l3vpn
->sid
,
1611 &from_bgp
->tovpn_sid_locator
->prefix
.prefix
,
1612 sizeof(struct in6_addr
));
1616 new_attr
= bgp_attr_intern(
1617 &static_attr
); /* hashed refcounted everything */
1618 bgp_attr_flush(&static_attr
); /* free locally-allocated parts */
1620 if (debug
&& bgp_attr_get_ecommunity(new_attr
)) {
1621 char *s
= ecommunity_ecom2str(bgp_attr_get_ecommunity(new_attr
),
1622 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1624 zlog_debug("%s: new_attr->ecommunity{%s}", __func__
, s
);
1625 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1628 /* Now new_attr is an allocated interned attr */
1630 bn
= bgp_afi_node_get(to_bgp
->rib
[afi
][safi
], afi
, safi
, p
,
1631 &(from_bgp
->vpn_policy
[afi
].tovpn_rd
));
1633 struct bgp_path_info
*new_info
;
1636 leak_update(to_bgp
, bn
, new_attr
, afi
, safi
, path_vrf
, &label
,
1637 1, from_bgp
, NULL
, nexthop_self_flag
, debug
);
1640 * Routes actually installed in the vpn RIB must also be
1641 * offered to all vrfs (because now they originate from
1644 * Acceptance into other vrfs depends on rt-lists.
1645 * Originating vrf will not accept the looped back route
1646 * because of loop checking.
1649 vpn_leak_to_vrf_update(from_bgp
, new_info
, NULL
);
1652 void vpn_leak_from_vrf_withdraw(struct bgp
*to_bgp
, /* to */
1653 struct bgp
*from_bgp
, /* from */
1654 struct bgp_path_info
*path_vrf
) /* route */
1656 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
1657 const struct prefix
*p
= bgp_dest_get_prefix(path_vrf
->net
);
1658 afi_t afi
= family2afi(p
->family
);
1659 safi_t safi
= SAFI_MPLS_VPN
;
1660 struct bgp_path_info
*bpi
;
1661 struct bgp_dest
*bn
;
1662 const char *debugmsg
;
1666 "%s: entry: leak-from=%s, p=%pBD, type=%d, sub_type=%d",
1667 __func__
, from_bgp
->name_pretty
, path_vrf
->net
,
1668 path_vrf
->type
, path_vrf
->sub_type
);
1676 zlog_debug("%s: can't get afi of prefix", __func__
);
1680 /* Is this route exportable into the VPN table? */
1681 if (!is_route_injectable_into_vpn(path_vrf
))
1684 if (!vpn_leak_to_vpn_active(from_bgp
, afi
, &debugmsg
)) {
1686 zlog_debug("%s: skipping: %s", __func__
, debugmsg
);
1691 zlog_debug("%s: withdrawing (path_vrf=%p)", __func__
, path_vrf
);
1693 bn
= bgp_afi_node_get(to_bgp
->rib
[afi
][safi
], afi
, safi
, p
,
1694 &(from_bgp
->vpn_policy
[afi
].tovpn_rd
));
1700 * match original bpi imported from
1702 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
1703 if (bpi
->extra
&& bpi
->extra
->parent
== path_vrf
) {
1709 /* withdraw from looped vrfs as well */
1710 vpn_leak_to_vrf_withdraw(bpi
);
1712 bgp_aggregate_decrement(to_bgp
, p
, bpi
, afi
, safi
);
1713 bgp_path_info_delete(bn
, bpi
);
1714 bgp_process(to_bgp
, bn
, afi
, safi
);
1716 bgp_dest_unlock_node(bn
);
1719 void vpn_leak_from_vrf_withdraw_all(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
1722 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
1723 struct bgp_dest
*pdest
;
1724 safi_t safi
= SAFI_MPLS_VPN
;
1727 * Walk vpn table, delete bpi with bgp_orig == from_bgp
1729 for (pdest
= bgp_table_top(to_bgp
->rib
[afi
][safi
]); pdest
;
1730 pdest
= bgp_route_next(pdest
)) {
1732 struct bgp_table
*table
;
1733 struct bgp_dest
*bn
;
1734 struct bgp_path_info
*bpi
;
1736 /* This is the per-RD table of prefixes */
1737 table
= bgp_dest_get_bgp_table_info(pdest
);
1742 for (bn
= bgp_table_top(table
); bn
; bn
= bgp_route_next(bn
)) {
1743 bpi
= bgp_dest_get_bgp_path_info(bn
);
1745 zlog_debug("%s: looking at prefix %pBD",
1749 for (; bpi
; bpi
= bpi
->next
) {
1751 zlog_debug("%s: type %d, sub_type %d",
1752 __func__
, bpi
->type
,
1754 if (bpi
->sub_type
!= BGP_ROUTE_IMPORTED
)
1758 if ((struct bgp
*)bpi
->extra
->bgp_orig
==
1762 zlog_debug("%s: deleting it",
1764 /* withdraw from leak-to vrfs as well */
1765 vpn_leak_to_vrf_withdraw(bpi
);
1766 bgp_aggregate_decrement(
1767 to_bgp
, bgp_dest_get_prefix(bn
),
1769 bgp_path_info_delete(bn
, bpi
);
1770 bgp_process(to_bgp
, bn
, afi
, safi
);
1777 void vpn_leak_from_vrf_update_all(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
1780 struct bgp_dest
*bn
;
1781 struct bgp_path_info
*bpi
;
1782 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
);
1785 zlog_debug("%s: entry, afi=%d, vrf=%s", __func__
, afi
,
1786 from_bgp
->name_pretty
);
1788 for (bn
= bgp_table_top(from_bgp
->rib
[afi
][SAFI_UNICAST
]); bn
;
1789 bn
= bgp_route_next(bn
)) {
1792 zlog_debug("%s: node=%p", __func__
, bn
);
1794 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
;
1798 "%s: calling vpn_leak_from_vrf_update",
1800 vpn_leak_from_vrf_update(to_bgp
, from_bgp
, bpi
);
1805 static struct bgp
*bgp_lookup_by_rd(struct bgp_path_info
*bpi
,
1806 struct prefix_rd
*rd
, afi_t afi
)
1808 struct listnode
*node
, *nnode
;
1814 /* If ACCEPT_OWN is not enabled for this path - return. */
1815 if (!CHECK_FLAG(bpi
->flags
, BGP_PATH_ACCEPT_OWN
))
1818 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1819 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
1822 if (!CHECK_FLAG(bgp
->vpn_policy
[afi
].flags
,
1823 BGP_VPN_POLICY_TOVPN_RD_SET
))
1826 /* Check if we have source VRF by RD value */
1827 if (memcmp(&bgp
->vpn_policy
[afi
].tovpn_rd
.val
, rd
->val
,
1828 ECOMMUNITY_SIZE
) == 0)
1835 static bool vpn_leak_to_vrf_update_onevrf(struct bgp
*to_bgp
, /* to */
1836 struct bgp
*from_bgp
, /* from */
1837 struct bgp_path_info
*path_vpn
,
1838 struct prefix_rd
*prd
)
1840 const struct prefix
*p
= bgp_dest_get_prefix(path_vpn
->net
);
1841 afi_t afi
= family2afi(p
->family
);
1843 struct attr static_attr
= {0};
1844 struct attr
*new_attr
= NULL
;
1845 struct bgp_dest
*bn
;
1846 safi_t safi
= SAFI_UNICAST
;
1847 const char *debugmsg
;
1848 struct prefix nexthop_orig
;
1849 mpls_label_t
*pLabels
= NULL
;
1850 uint32_t num_labels
= 0;
1851 int nexthop_self_flag
= 1;
1852 struct bgp_path_info
*bpi_ultimate
= NULL
;
1853 int origin_local
= 0;
1854 struct bgp
*src_vrf
;
1855 struct interface
*ifp
;
1856 char rd_buf
[RD_ADDRSTRLEN
];
1857 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
1859 if (!vpn_leak_from_vpn_active(to_bgp
, afi
, &debugmsg
)) {
1862 "%s: from vpn (%s) to vrf (%s), skipping: %s",
1863 __func__
, from_bgp
->name_pretty
,
1864 to_bgp
->name_pretty
, debugmsg
);
1869 * For VRF-2-VRF route-leaking,
1870 * the source will be the originating VRF.
1872 * If ACCEPT_OWN mechanism is enabled, then we SHOULD(?)
1873 * get the source VRF (BGP) by looking at the RD.
1875 struct bgp
*src_bgp
= bgp_lookup_by_rd(path_vpn
, prd
, afi
);
1877 if (path_vpn
->extra
&& path_vpn
->extra
->bgp_orig
)
1878 src_vrf
= path_vpn
->extra
->bgp_orig
;
1884 /* Check for intersection of route targets */
1885 if (!ecommunity_include(
1886 to_bgp
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
1887 bgp_attr_get_ecommunity(path_vpn
->attr
))) {
1890 "from vpn (%s) to vrf (%s), skipping after no intersection of route targets",
1891 from_bgp
->name_pretty
, to_bgp
->name_pretty
);
1897 prefix_rd2str(prd
, rd_buf
, sizeof(rd_buf
), to_bgp
->asnotation
);
1899 /* A route MUST NOT ever be accepted back into its source VRF, even if
1900 * it carries one or more RTs that match that VRF.
1902 if (CHECK_FLAG(path_vpn
->flags
, BGP_PATH_ACCEPT_OWN
) && prd
&&
1903 memcmp(&prd
->val
, &to_bgp
->vpn_policy
[afi
].tovpn_rd
.val
,
1904 ECOMMUNITY_SIZE
) == 0) {
1907 "%s: skipping import, match RD (%s) of src VRF (%s) and the prefix (%pFX)",
1908 __func__
, rd_buf
, to_bgp
->name_pretty
, p
);
1913 zlog_debug("%s: updating RD %s, %pFX to %s", __func__
, rd_buf
,
1914 p
, to_bgp
->name_pretty
);
1917 static_attr
= *path_vpn
->attr
;
1919 struct ecommunity
*old_ecom
;
1920 struct ecommunity
*new_ecom
;
1922 /* If doing VRF-to-VRF leaking, strip RTs. */
1923 old_ecom
= bgp_attr_get_ecommunity(&static_attr
);
1924 if (old_ecom
&& CHECK_FLAG(to_bgp
->af_flags
[afi
][safi
],
1925 BGP_CONFIG_VRF_TO_VRF_IMPORT
)) {
1926 new_ecom
= ecommunity_dup(old_ecom
);
1927 ecommunity_strip_rts(new_ecom
);
1928 bgp_attr_set_ecommunity(&static_attr
, new_ecom
);
1930 if (new_ecom
->size
== 0) {
1931 ecommunity_free(&new_ecom
);
1932 bgp_attr_set_ecommunity(&static_attr
, NULL
);
1935 if (!old_ecom
->refcnt
)
1936 ecommunity_free(&old_ecom
);
1939 community_strip_accept_own(&static_attr
);
1942 * Nexthop: stash and clear
1944 * Nexthop is valid in context of VPN core, but not in destination vrf.
1945 * Stash it for later label resolution by vrf ingress path and then
1946 * overwrite with 0, i.e., "me", for the sake of vrf advertisement.
1948 uint8_t nhfamily
= NEXTHOP_FAMILY(path_vpn
->attr
->mp_nexthop_len
);
1950 memset(&nexthop_orig
, 0, sizeof(nexthop_orig
));
1951 nexthop_orig
.family
= nhfamily
;
1953 /* If the path has accept-own community and the source VRF
1954 * is valid, reset next-hop to self, to allow importing own
1955 * routes between different VRFs on the same node.
1956 * Set the nh ifindex to VRF's interface, not the real interface.
1957 * Let the kernel to decide with double lookup the real next-hop
1958 * interface when installing the route.
1961 subgroup_announce_reset_nhop(nhfamily
, &static_attr
);
1962 ifp
= if_get_vrf_loopback(src_vrf
->vrf_id
);
1964 static_attr
.nh_ifindex
= ifp
->ifindex
;
1970 nexthop_orig
.u
.prefix4
= path_vpn
->attr
->mp_nexthop_global_in
;
1971 nexthop_orig
.prefixlen
= IPV4_MAX_BITLEN
;
1973 if (CHECK_FLAG(to_bgp
->af_flags
[afi
][safi
],
1974 BGP_CONFIG_VRF_TO_VRF_IMPORT
)) {
1975 static_attr
.nexthop
.s_addr
=
1976 nexthop_orig
.u
.prefix4
.s_addr
;
1978 static_attr
.mp_nexthop_global_in
=
1979 path_vpn
->attr
->mp_nexthop_global_in
;
1980 static_attr
.mp_nexthop_len
=
1981 path_vpn
->attr
->mp_nexthop_len
;
1983 static_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1987 nexthop_orig
.u
.prefix6
= path_vpn
->attr
->mp_nexthop_global
;
1988 nexthop_orig
.prefixlen
= IPV6_MAX_BITLEN
;
1990 if (CHECK_FLAG(to_bgp
->af_flags
[afi
][safi
],
1991 BGP_CONFIG_VRF_TO_VRF_IMPORT
)) {
1992 static_attr
.mp_nexthop_global
= nexthop_orig
.u
.prefix6
;
1998 * route map handling
2000 if (to_bgp
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
2001 struct bgp_path_info info
;
2002 route_map_result_t ret
;
2004 memset(&info
, 0, sizeof(info
));
2005 info
.peer
= to_bgp
->peer_self
;
2006 info
.attr
= &static_attr
;
2007 info
.extra
= path_vpn
->extra
; /* Used for source-vrf filter */
2008 ret
= route_map_apply(to_bgp
->vpn_policy
[afi
]
2009 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
],
2011 if (RMAP_DENYMATCH
== ret
) {
2012 bgp_attr_flush(&static_attr
); /* free any added parts */
2015 "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning",
2016 __func__
, to_bgp
->name_pretty
,
2017 to_bgp
->vpn_policy
[afi
]
2018 .rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]
2023 * if route-map changed nexthop, don't nexthop-self on output
2025 if (!CHECK_FLAG(static_attr
.rmap_change_flags
,
2026 BATTR_RMAP_NEXTHOP_UNCHANGED
))
2027 nexthop_self_flag
= 0;
2030 new_attr
= bgp_attr_intern(&static_attr
);
2031 bgp_attr_flush(&static_attr
);
2033 bn
= bgp_afi_node_get(to_bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
2036 * ensure labels are copied
2038 * However, there is a special case: if the route originated in
2039 * another local VRF (as opposed to arriving via VPN), then the
2040 * nexthop is reached by hairpinning through this router (me)
2041 * using IP forwarding only (no LSP). Therefore, the route
2042 * imported to the VRF should not have labels attached. Note
2043 * that nexthop tracking is also involved: eliminating the
2044 * labels for these routes enables the non-labeled nexthops
2045 * from the originating VRF to be considered valid for this route.
2047 if (!CHECK_FLAG(to_bgp
->af_flags
[afi
][safi
],
2048 BGP_CONFIG_VRF_TO_VRF_IMPORT
)) {
2049 /* work back to original route */
2050 bpi_ultimate
= bgp_get_imported_bpi_ultimate(path_vpn
);
2053 * if original route was unicast,
2054 * then it did not arrive over vpn
2056 if (bpi_ultimate
->net
) {
2057 struct bgp_table
*table
;
2059 table
= bgp_dest_table(bpi_ultimate
->net
);
2060 if (table
&& (table
->safi
== SAFI_UNICAST
))
2065 if (!origin_local
&& path_vpn
->extra
2066 && path_vpn
->extra
->num_labels
) {
2067 num_labels
= path_vpn
->extra
->num_labels
;
2068 if (num_labels
> BGP_MAX_LABELS
)
2069 num_labels
= BGP_MAX_LABELS
;
2070 pLabels
= path_vpn
->extra
->label
;
2075 zlog_debug("%s: pfx %pBD: num_labels %d", __func__
,
2076 path_vpn
->net
, num_labels
);
2078 leak_update(to_bgp
, bn
, new_attr
, afi
, safi
, path_vpn
, pLabels
,
2079 num_labels
, src_vrf
, &nexthop_orig
, nexthop_self_flag
,
2084 bool vpn_leak_to_vrf_update(struct bgp
*from_bgp
,
2085 struct bgp_path_info
*path_vpn
,
2086 struct prefix_rd
*prd
)
2088 struct listnode
*mnode
, *mnnode
;
2090 bool leak_success
= false;
2092 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
2095 zlog_debug("%s: start (path_vpn=%p)", __func__
, path_vpn
);
2097 /* Loop over VRFs */
2098 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
2100 if (!path_vpn
->extra
2101 || path_vpn
->extra
->bgp_orig
!= bgp
) { /* no loop */
2102 leak_success
|= vpn_leak_to_vrf_update_onevrf(
2103 bgp
, from_bgp
, path_vpn
, prd
);
2106 return leak_success
;
2109 void vpn_leak_to_vrf_withdraw(struct bgp_path_info
*path_vpn
)
2111 const struct prefix
*p
;
2113 safi_t safi
= SAFI_UNICAST
;
2115 struct listnode
*mnode
, *mnnode
;
2116 struct bgp_dest
*bn
;
2117 struct bgp_path_info
*bpi
;
2118 const char *debugmsg
;
2120 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
2123 zlog_debug("%s: entry: p=%pBD, type=%d, sub_type=%d", __func__
,
2124 path_vpn
->net
, path_vpn
->type
, path_vpn
->sub_type
);
2127 zlog_debug("%s: start (path_vpn=%p)", __func__
, path_vpn
);
2129 if (!path_vpn
->net
) {
2130 #ifdef ENABLE_BGP_VNC
2131 /* BGP_ROUTE_RFP routes do not have path_vpn->net set (yet) */
2132 if (path_vpn
->type
== ZEBRA_ROUTE_BGP
2133 && path_vpn
->sub_type
== BGP_ROUTE_RFP
) {
2140 "%s: path_vpn->net unexpectedly NULL, no prefix, bailing",
2145 p
= bgp_dest_get_prefix(path_vpn
->net
);
2146 afi
= family2afi(p
->family
);
2148 /* Loop over VRFs */
2149 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
2150 if (!vpn_leak_from_vpn_active(bgp
, afi
, &debugmsg
)) {
2152 zlog_debug("%s: from %s, skipping: %s",
2153 __func__
, bgp
->name_pretty
,
2158 /* Check for intersection of route targets */
2159 if (!ecommunity_include(
2160 bgp
->vpn_policy
[afi
]
2161 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
2162 bgp_attr_get_ecommunity(path_vpn
->attr
))) {
2168 zlog_debug("%s: withdrawing from vrf %s", __func__
,
2171 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
2173 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
;
2176 && (struct bgp_path_info
*)bpi
->extra
->parent
2184 zlog_debug("%s: deleting bpi %p", __func__
,
2186 bgp_aggregate_decrement(bgp
, p
, bpi
, afi
, safi
);
2187 bgp_path_info_delete(bn
, bpi
);
2188 bgp_process(bgp
, bn
, afi
, safi
);
2190 bgp_dest_unlock_node(bn
);
2194 void vpn_leak_to_vrf_withdraw_all(struct bgp
*to_bgp
, afi_t afi
)
2196 struct bgp_dest
*bn
;
2197 struct bgp_path_info
*bpi
;
2198 safi_t safi
= SAFI_UNICAST
;
2199 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
);
2202 zlog_debug("%s: entry", __func__
);
2204 * Walk vrf table, delete bpi with bgp_orig in a different vrf
2206 for (bn
= bgp_table_top(to_bgp
->rib
[afi
][safi
]); bn
;
2207 bn
= bgp_route_next(bn
)) {
2209 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
;
2211 if (bpi
->extra
&& bpi
->extra
->bgp_orig
!= to_bgp
&&
2212 bpi
->extra
->parent
&&
2213 is_pi_family_vpn(bpi
->extra
->parent
)) {
2216 bgp_aggregate_decrement(to_bgp
,
2217 bgp_dest_get_prefix(bn
),
2219 bgp_path_info_delete(bn
, bpi
);
2220 bgp_process(to_bgp
, bn
, afi
, safi
);
2226 void vpn_leak_to_vrf_update_all(struct bgp
*to_bgp
, struct bgp
*vpn_from
,
2229 struct bgp_dest
*pdest
;
2230 safi_t safi
= SAFI_MPLS_VPN
;
2237 for (pdest
= bgp_table_top(vpn_from
->rib
[afi
][safi
]); pdest
;
2238 pdest
= bgp_route_next(pdest
)) {
2239 struct bgp_table
*table
;
2240 struct bgp_dest
*bn
;
2241 struct bgp_path_info
*bpi
;
2243 /* This is the per-RD table of prefixes */
2244 table
= bgp_dest_get_bgp_table_info(pdest
);
2249 for (bn
= bgp_table_top(table
); bn
; bn
= bgp_route_next(bn
)) {
2251 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
;
2255 bpi
->extra
->bgp_orig
== to_bgp
)
2258 vpn_leak_to_vrf_update_onevrf(to_bgp
, vpn_from
,
2266 * This function is called for definition/deletion/change to a route-map
2268 static void vpn_policy_routemap_update(struct bgp
*bgp
, const char *rmap_name
)
2270 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_RMAP_EVENT
);
2272 struct route_map
*rmap
;
2274 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
2275 && bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
) {
2280 rmap
= route_map_lookup_by_name(rmap_name
); /* NULL if deleted */
2282 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
2284 if (bgp
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
]
2285 && !strcmp(rmap_name
,
2286 bgp
->vpn_policy
[afi
]
2287 .rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
])) {
2291 "%s: rmap \"%s\" matches vrf-policy tovpn for as %d afi %s",
2292 __func__
, rmap_name
, bgp
->as
,
2295 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN
, afi
,
2296 bgp_get_default(), bgp
);
2298 zlog_debug("%s: after vpn_leak_prechange",
2301 /* in case of definition/deletion */
2302 bgp
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
] =
2305 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN
, afi
,
2306 bgp_get_default(), bgp
);
2309 zlog_debug("%s: after vpn_leak_postchange",
2313 if (bgp
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_FROMVPN
]
2314 && !strcmp(rmap_name
,
2315 bgp
->vpn_policy
[afi
]
2316 .rmap_name
[BGP_VPN_POLICY_DIR_FROMVPN
])) {
2319 zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
2320 __func__
, rmap_name
, bgp
->as
,
2324 vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN
, afi
,
2325 bgp_get_default(), bgp
);
2327 /* in case of definition/deletion */
2328 bgp
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_FROMVPN
] =
2331 vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN
, afi
,
2332 bgp_get_default(), bgp
);
2337 /* This API is used during router-id change, reflect VPNs
2338 * auto RD and RT values and readvertise routes to VPN table.
2340 void vpn_handle_router_id_update(struct bgp
*bgp
, bool withdraw
,
2344 int debug
= (BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
)
2345 | BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
));
2347 const char *export_name
;
2348 char buf
[RD_ADDRSTRLEN
];
2349 struct bgp
*bgp_import
;
2350 struct listnode
*node
;
2351 struct ecommunity
*ecom
;
2352 enum vpn_policy_direction idir
, edir
;
2355 * Router-id change that is not explicitly configured
2356 * (a change from zebra, frr restart for example)
2357 * should not replace a configured vpn RD/RT.
2361 zlog_debug("%s: skipping non explicit router-id change",
2366 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
2367 && bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
2370 export_name
= bgp
->name
? bgp
->name
: VRF_DEFAULT_NAME
;
2371 idir
= BGP_VPN_POLICY_DIR_FROMVPN
;
2372 edir
= BGP_VPN_POLICY_DIR_TOVPN
;
2374 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
2375 if (!vpn_leak_to_vpn_active(bgp
, afi
, NULL
))
2379 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN
,
2380 afi
, bgp_get_default(), bgp
);
2382 zlog_debug("%s: %s after to_vpn vpn_leak_prechange",
2383 __func__
, export_name
);
2385 /* Remove import RT from VRFs */
2386 ecom
= bgp
->vpn_policy
[afi
].rtlist
[edir
];
2387 for (ALL_LIST_ELEMENTS_RO(bgp
->vpn_policy
[afi
].
2388 export_vrf
, node
, vname
)) {
2389 if (strcmp(vname
, VRF_DEFAULT_NAME
) == 0)
2390 bgp_import
= bgp_get_default();
2392 bgp_import
= bgp_lookup_by_name(vname
);
2397 bgp_import
->vpn_policy
[afi
]
2399 (struct ecommunity_val
*)ecom
->val
);
2402 /* New router-id derive auto RD and RT and export
2405 form_auto_rd(bgp
->router_id
, bgp
->vrf_rd_id
,
2406 &bgp
->vrf_prd_auto
);
2407 bgp
->vpn_policy
[afi
].tovpn_rd
= bgp
->vrf_prd_auto
;
2408 prefix_rd2str(&bgp
->vpn_policy
[afi
].tovpn_rd
, buf
,
2409 sizeof(buf
), bgp
->asnotation
);
2411 /* free up pre-existing memory if any and allocate
2412 * the ecommunity attribute with new RD/RT
2414 if (bgp
->vpn_policy
[afi
].rtlist
[edir
])
2416 &bgp
->vpn_policy
[afi
].rtlist
[edir
]);
2417 bgp
->vpn_policy
[afi
].rtlist
[edir
] = ecommunity_str2com(
2418 buf
, ECOMMUNITY_ROUTE_TARGET
, 0);
2420 /* Update import_vrf rt_list */
2421 ecom
= bgp
->vpn_policy
[afi
].rtlist
[edir
];
2422 for (ALL_LIST_ELEMENTS_RO(bgp
->vpn_policy
[afi
].
2423 export_vrf
, node
, vname
)) {
2424 if (strcmp(vname
, VRF_DEFAULT_NAME
) == 0)
2425 bgp_import
= bgp_get_default();
2427 bgp_import
= bgp_lookup_by_name(vname
);
2430 if (bgp_import
->vpn_policy
[afi
].rtlist
[idir
])
2431 bgp_import
->vpn_policy
[afi
].rtlist
[idir
]
2433 bgp_import
->vpn_policy
[afi
]
2434 .rtlist
[idir
], ecom
);
2436 bgp_import
->vpn_policy
[afi
].rtlist
[idir
]
2437 = ecommunity_dup(ecom
);
2440 /* Update routes to VPN */
2441 vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN
,
2442 afi
, bgp_get_default(),
2445 zlog_debug("%s: %s after to_vpn vpn_leak_postchange",
2446 __func__
, export_name
);
2451 void vpn_policy_routemap_event(const char *rmap_name
)
2453 int debug
= BGP_DEBUG(vpn
, VPN_LEAK_RMAP_EVENT
);
2454 struct listnode
*mnode
, *mnnode
;
2458 zlog_debug("%s: entry", __func__
);
2460 if (bm
->bgp
== NULL
) /* may be called during cleanup */
2463 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
))
2464 vpn_policy_routemap_update(bgp
, rmap_name
);
2467 void vrf_import_from_vrf(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
2468 afi_t afi
, safi_t safi
)
2470 const char *export_name
;
2471 enum vpn_policy_direction idir
, edir
;
2472 char *vname
, *tmp_name
;
2473 char buf
[RD_ADDRSTRLEN
];
2474 struct ecommunity
*ecom
;
2475 bool first_export
= false;
2477 struct listnode
*node
;
2478 bool is_inst_match
= false;
2480 export_name
= to_bgp
->name
? to_bgp
->name
: VRF_DEFAULT_NAME
;
2481 idir
= BGP_VPN_POLICY_DIR_FROMVPN
;
2482 edir
= BGP_VPN_POLICY_DIR_TOVPN
;
2484 debug
= (BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
) |
2485 BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
));
2488 * Cross-ref both VRFs. Also, note if this is the first time
2489 * any VRF is importing from "import_vrf".
2491 vname
= (from_bgp
->name
? XSTRDUP(MTYPE_TMP
, from_bgp
->name
)
2492 : XSTRDUP(MTYPE_TMP
, VRF_DEFAULT_NAME
));
2494 /* Check the import_vrf list of destination vrf for the source vrf name,
2497 for (ALL_LIST_ELEMENTS_RO(to_bgp
->vpn_policy
[afi
].import_vrf
,
2499 if (strcmp(vname
, tmp_name
) == 0) {
2500 is_inst_match
= true;
2505 listnode_add(to_bgp
->vpn_policy
[afi
].import_vrf
,
2508 XFREE(MTYPE_TMP
, vname
);
2510 /* Check if the source vrf already exports to any vrf,
2511 * first time export requires to setup auto derived RD/RT values.
2512 * Add the destination vrf name to export vrf list if it is
2515 is_inst_match
= false;
2516 vname
= XSTRDUP(MTYPE_TMP
, export_name
);
2517 if (!listcount(from_bgp
->vpn_policy
[afi
].export_vrf
)) {
2518 first_export
= true;
2520 for (ALL_LIST_ELEMENTS_RO(from_bgp
->vpn_policy
[afi
].export_vrf
,
2522 if (strcmp(vname
, tmp_name
) == 0) {
2523 is_inst_match
= true;
2529 listnode_add(from_bgp
->vpn_policy
[afi
].export_vrf
,
2532 XFREE(MTYPE_TMP
, vname
);
2534 /* Update import RT for current VRF using export RT of the VRF we're
2535 * importing from. First though, make sure "import_vrf" has that
2539 form_auto_rd(from_bgp
->router_id
, from_bgp
->vrf_rd_id
,
2540 &from_bgp
->vrf_prd_auto
);
2541 from_bgp
->vpn_policy
[afi
].tovpn_rd
= from_bgp
->vrf_prd_auto
;
2542 SET_FLAG(from_bgp
->vpn_policy
[afi
].flags
,
2543 BGP_VPN_POLICY_TOVPN_RD_SET
);
2544 prefix_rd2str(&from_bgp
->vpn_policy
[afi
].tovpn_rd
, buf
,
2545 sizeof(buf
), from_bgp
->asnotation
);
2546 from_bgp
->vpn_policy
[afi
].rtlist
[edir
] =
2547 ecommunity_str2com(buf
, ECOMMUNITY_ROUTE_TARGET
, 0);
2548 SET_FLAG(from_bgp
->af_flags
[afi
][safi
],
2549 BGP_CONFIG_VRF_TO_VRF_EXPORT
);
2550 from_bgp
->vpn_policy
[afi
].tovpn_label
=
2551 BGP_PREVENT_VRF_2_VRF_LEAK
;
2553 ecom
= from_bgp
->vpn_policy
[afi
].rtlist
[edir
];
2554 if (to_bgp
->vpn_policy
[afi
].rtlist
[idir
])
2555 to_bgp
->vpn_policy
[afi
].rtlist
[idir
] =
2556 ecommunity_merge(to_bgp
->vpn_policy
[afi
]
2557 .rtlist
[idir
], ecom
);
2559 to_bgp
->vpn_policy
[afi
].rtlist
[idir
] = ecommunity_dup(ecom
);
2560 SET_FLAG(to_bgp
->af_flags
[afi
][safi
], BGP_CONFIG_VRF_TO_VRF_IMPORT
);
2563 const char *from_name
;
2564 char *ecom1
, *ecom2
;
2566 from_name
= from_bgp
->name
? from_bgp
->name
:
2569 ecom1
= ecommunity_ecom2str(
2570 to_bgp
->vpn_policy
[afi
].rtlist
[idir
],
2571 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2573 ecom2
= ecommunity_ecom2str(
2574 to_bgp
->vpn_policy
[afi
].rtlist
[edir
],
2575 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2578 "%s from %s to %s first_export %u import-rt %s export-rt %s",
2579 __func__
, from_name
, export_name
, first_export
, ecom1
,
2582 ecommunity_strfree(&ecom1
);
2583 ecommunity_strfree(&ecom2
);
2586 /* Does "import_vrf" first need to export its routes or that
2587 * is already done and we just need to import those routes
2588 * from the global table?
2591 vpn_leak_postchange(edir
, afi
, bgp_get_default(), from_bgp
);
2593 vpn_leak_postchange(idir
, afi
, bgp_get_default(), to_bgp
);
2596 void vrf_unimport_from_vrf(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
2597 afi_t afi
, safi_t safi
)
2599 const char *export_name
, *tmp_name
;
2600 enum vpn_policy_direction idir
, edir
;
2602 struct ecommunity
*ecom
= NULL
;
2603 struct listnode
*node
;
2606 export_name
= to_bgp
->name
? to_bgp
->name
: VRF_DEFAULT_NAME
;
2607 tmp_name
= from_bgp
->name
? from_bgp
->name
: VRF_DEFAULT_NAME
;
2608 idir
= BGP_VPN_POLICY_DIR_FROMVPN
;
2609 edir
= BGP_VPN_POLICY_DIR_TOVPN
;
2611 debug
= (BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
) |
2612 BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
));
2614 /* Were we importing from "import_vrf"? */
2615 for (ALL_LIST_ELEMENTS_RO(to_bgp
->vpn_policy
[afi
].import_vrf
, node
,
2617 if (strcmp(vname
, tmp_name
) == 0)
2622 * We do not check in the cli if the passed in bgp
2623 * instance is actually imported into us before
2624 * we call this function. As such if we do not
2625 * find this in the import_vrf list than
2626 * we just need to return safely.
2632 zlog_debug("%s from %s to %s", __func__
, tmp_name
, export_name
);
2634 /* Remove "import_vrf" from our import list. */
2635 listnode_delete(to_bgp
->vpn_policy
[afi
].import_vrf
, vname
);
2636 XFREE(MTYPE_TMP
, vname
);
2638 /* Remove routes imported from "import_vrf". */
2639 /* TODO: In the current logic, we have to first remove all
2640 * imported routes and then (if needed) import back routes
2642 vpn_leak_prechange(idir
, afi
, bgp_get_default(), to_bgp
);
2644 if (to_bgp
->vpn_policy
[afi
].import_vrf
->count
== 0) {
2645 if (!to_bgp
->vpn_policy
[afi
].rmap
[idir
])
2646 UNSET_FLAG(to_bgp
->af_flags
[afi
][safi
],
2647 BGP_CONFIG_VRF_TO_VRF_IMPORT
);
2648 if (to_bgp
->vpn_policy
[afi
].rtlist
[idir
])
2649 ecommunity_free(&to_bgp
->vpn_policy
[afi
].rtlist
[idir
]);
2651 ecom
= from_bgp
->vpn_policy
[afi
].rtlist
[edir
];
2653 ecommunity_del_val(to_bgp
->vpn_policy
[afi
].rtlist
[idir
],
2654 (struct ecommunity_val
*)ecom
->val
);
2655 vpn_leak_postchange(idir
, afi
, bgp_get_default(), to_bgp
);
2660 * So SA is assuming that since the ALL_LIST_ELEMENTS_RO
2661 * below is checking for NULL that export_vrf can be
2662 * NULL, consequently it is complaining( like a cabbage )
2663 * that we could dereference and crash in the listcount(..)
2665 * So make it happy, under protest, with liberty and justice
2668 assert(from_bgp
->vpn_policy
[afi
].export_vrf
);
2670 /* Remove us from "import_vrf's" export list. If no other VRF
2671 * is importing from "import_vrf", cleanup appropriately.
2673 for (ALL_LIST_ELEMENTS_RO(from_bgp
->vpn_policy
[afi
].export_vrf
,
2675 if (strcmp(vname
, export_name
) == 0)
2680 * If we have gotten to this point then the vname must
2681 * exist. If not, we are in a world of trouble and
2682 * have slag sitting around.
2684 * import_vrf and export_vrf must match in having
2685 * the in/out names as appropriate.
2686 * export_vrf list could have been cleaned up
2687 * as part of no router bgp source instnace.
2692 listnode_delete(from_bgp
->vpn_policy
[afi
].export_vrf
, vname
);
2693 XFREE(MTYPE_TMP
, vname
);
2695 if (!listcount(from_bgp
->vpn_policy
[afi
].export_vrf
)) {
2696 vpn_leak_prechange(edir
, afi
, bgp_get_default(), from_bgp
);
2697 ecommunity_free(&from_bgp
->vpn_policy
[afi
].rtlist
[edir
]);
2698 UNSET_FLAG(from_bgp
->af_flags
[afi
][safi
],
2699 BGP_CONFIG_VRF_TO_VRF_EXPORT
);
2700 memset(&from_bgp
->vpn_policy
[afi
].tovpn_rd
, 0,
2701 sizeof(struct prefix_rd
));
2702 UNSET_FLAG(from_bgp
->vpn_policy
[afi
].flags
,
2703 BGP_VPN_POLICY_TOVPN_RD_SET
);
2704 from_bgp
->vpn_policy
[afi
].tovpn_label
= MPLS_LABEL_NONE
;
2709 /* For testing purpose, static route of MPLS-VPN. */
2710 DEFUN (vpnv4_network
,
2712 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
2713 "Specify a network to announce via BGP\n"
2715 "Specify Route Distinguisher\n"
2716 "VPN Route Distinguisher\n"
2717 "VPN NLRI label (tag)\n"
2718 "VPN NLRI label (tag)\n"
2721 int idx_ipv4_prefixlen
= 1;
2722 int idx_ext_community
= 3;
2724 return bgp_static_set_safi(
2725 AFI_IP
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2726 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
, NULL
, 0,
2727 NULL
, NULL
, NULL
, NULL
);
2730 DEFUN (vpnv4_network_route_map
,
2731 vpnv4_network_route_map_cmd
,
2732 "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map RMAP_NAME",
2733 "Specify a network to announce via BGP\n"
2735 "Specify Route Distinguisher\n"
2736 "VPN Route Distinguisher\n"
2737 "VPN NLRI label (tag)\n"
2738 "VPN NLRI label (tag)\n"
2743 int idx_ipv4_prefixlen
= 1;
2744 int idx_ext_community
= 3;
2747 return bgp_static_set_safi(
2748 AFI_IP
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2749 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2750 argv
[idx_word_2
]->arg
, 0, NULL
, NULL
, NULL
, NULL
);
2753 /* For testing purpose, static route of MPLS-VPN. */
2754 DEFUN (no_vpnv4_network
,
2755 no_vpnv4_network_cmd
,
2756 "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
2758 "Specify a network to announce via BGP\n"
2760 "Specify Route Distinguisher\n"
2761 "VPN Route Distinguisher\n"
2762 "VPN NLRI label (tag)\n"
2763 "VPN NLRI label (tag)\n"
2766 int idx_ipv4_prefixlen
= 2;
2767 int idx_ext_community
= 4;
2769 return bgp_static_unset_safi(AFI_IP
, SAFI_MPLS_VPN
, vty
,
2770 argv
[idx_ipv4_prefixlen
]->arg
,
2771 argv
[idx_ext_community
]->arg
,
2772 argv
[idx_label
]->arg
, 0, NULL
, NULL
, NULL
);
2775 DEFUN (vpnv6_network
,
2777 "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map RMAP_NAME]",
2778 "Specify a network to announce via BGP\n"
2779 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
2780 "Specify Route Distinguisher\n"
2781 "VPN Route Distinguisher\n"
2782 "VPN NLRI label (tag)\n"
2783 "VPN NLRI label (tag)\n"
2788 int idx_ipv6_prefix
= 1;
2789 int idx_ext_community
= 3;
2793 return bgp_static_set_safi(
2794 AFI_IP6
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv6_prefix
]->arg
,
2795 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2796 argv
[idx_word_2
]->arg
, 0, NULL
, NULL
, NULL
, NULL
);
2798 return bgp_static_set_safi(
2799 AFI_IP6
, SAFI_MPLS_VPN
, vty
, argv
[idx_ipv6_prefix
]->arg
,
2800 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2801 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2804 /* For testing purpose, static route of MPLS-VPN. */
2805 DEFUN (no_vpnv6_network
,
2806 no_vpnv6_network_cmd
,
2807 "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
2809 "Specify a network to announce via BGP\n"
2810 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
2811 "Specify Route Distinguisher\n"
2812 "VPN Route Distinguisher\n"
2813 "VPN NLRI label (tag)\n"
2814 "VPN NLRI label (tag)\n"
2817 int idx_ipv6_prefix
= 2;
2818 int idx_ext_community
= 4;
2820 return bgp_static_unset_safi(AFI_IP6
, SAFI_MPLS_VPN
, vty
,
2821 argv
[idx_ipv6_prefix
]->arg
,
2822 argv
[idx_ext_community
]->arg
,
2823 argv
[idx_label
]->arg
, 0, NULL
, NULL
, NULL
);
2826 int bgp_show_mpls_vpn(struct vty
*vty
, afi_t afi
, struct prefix_rd
*prd
,
2827 enum bgp_show_type type
, void *output_arg
, int tags
,
2831 struct bgp_table
*table
;
2832 uint16_t show_flags
= 0;
2835 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
2837 bgp
= bgp_get_default();
2840 vty_out(vty
, "No BGP process is configured\n");
2842 vty_out(vty
, "{}\n");
2845 table
= bgp
->rib
[afi
][SAFI_MPLS_VPN
];
2846 return bgp_show_table_rd(vty
, bgp
, SAFI_MPLS_VPN
, table
, prd
, type
,
2847 output_arg
, show_flags
);
2850 DEFUN (show_bgp_ip_vpn_all_rd
,
2851 show_bgp_ip_vpn_all_rd_cmd
,
2852 "show bgp "BGP_AFI_CMD_STR
" vpn all [rd <ASN:NN_OR_IP-ADDRESS:NN|all>] [json]",
2856 "Display VPN NLRI specific information\n"
2857 "Display VPN NLRI specific information\n"
2858 "Display information for a route distinguisher\n"
2859 "VPN Route Distinguisher\n"
2860 "All VPN Route Distinguishers\n"
2864 struct prefix_rd prd
;
2868 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
2869 /* Constrain search if user supplies RD && RD != "all" */
2870 if (argv_find(argv
, argc
, "rd", &idx
)
2871 && strcmp(argv
[idx
+ 1]->arg
, "all")) {
2872 ret
= str2prefix_rd(argv
[idx
+ 1]->arg
, &prd
);
2875 "%% Malformed Route Distinguisher\n");
2878 return bgp_show_mpls_vpn(vty
, afi
, &prd
,
2879 bgp_show_type_normal
, NULL
, 0,
2880 use_json(argc
, argv
));
2882 return bgp_show_mpls_vpn(vty
, afi
, NULL
,
2883 bgp_show_type_normal
, NULL
, 0,
2884 use_json(argc
, argv
));
2890 ALIAS(show_bgp_ip_vpn_all_rd
,
2891 show_bgp_ip_vpn_rd_cmd
,
2892 "show bgp "BGP_AFI_CMD_STR
" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
2896 "Display VPN NLRI specific information\n"
2897 "Display information for a route distinguisher\n"
2898 "VPN Route Distinguisher\n"
2899 "All VPN Route Distinguishers\n"
2902 #ifdef KEEP_OLD_VPN_COMMANDS
2903 DEFUN (show_ip_bgp_vpn_rd
,
2904 show_ip_bgp_vpn_rd_cmd
,
2905 "show ip bgp "BGP_AFI_CMD_STR
" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all>",
2911 "Display information for a route distinguisher\n"
2912 "VPN Route Distinguisher\n"
2913 "All VPN Route Distinguishers\n")
2915 int idx_ext_community
= argc
- 1;
2917 struct prefix_rd prd
;
2921 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
2922 if (!strcmp(argv
[idx_ext_community
]->arg
, "all"))
2923 return bgp_show_mpls_vpn(vty
, afi
, NULL
,
2924 bgp_show_type_normal
, NULL
, 0,
2926 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
2928 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2931 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_normal
,
2937 DEFUN (show_ip_bgp_vpn_all
,
2938 show_ip_bgp_vpn_all_cmd
,
2939 "show [ip] bgp <vpnv4|vpnv6>",
2948 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
))
2949 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
2954 DEFUN (show_ip_bgp_vpn_all_tags
,
2955 show_ip_bgp_vpn_all_tags_cmd
,
2956 "show [ip] bgp <vpnv4|vpnv6> all tags",
2961 "Display information about all VPNv4/VPNV6 NLRIs\n"
2962 "Display BGP tags for prefixes\n")
2967 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
))
2968 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
2973 DEFUN (show_ip_bgp_vpn_rd_tags
,
2974 show_ip_bgp_vpn_rd_tags_cmd
,
2975 "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
2980 "Display information for a route distinguisher\n"
2981 "VPN Route Distinguisher\n"
2982 "All VPN Route Distinguishers\n"
2983 "Display BGP tags for prefixes\n")
2985 int idx_ext_community
= 5;
2987 struct prefix_rd prd
;
2991 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
2992 if (!strcmp(argv
[idx_ext_community
]->arg
, "all"))
2993 return bgp_show_mpls_vpn(vty
, afi
, NULL
,
2994 bgp_show_type_normal
, NULL
, 1,
2996 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
2998 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3001 return bgp_show_mpls_vpn(vty
, afi
, &prd
, bgp_show_type_normal
,
3007 DEFUN (show_ip_bgp_vpn_all_neighbor_routes
,
3008 show_ip_bgp_vpn_all_neighbor_routes_cmd
,
3009 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
3014 "Display information about all VPNv4/VPNv6 NLRIs\n"
3015 "Detailed information on TCP and BGP neighbor connections\n"
3016 "Neighbor to display information about\n"
3017 "Display routes learned from neighbor\n"
3024 bool uj
= use_json(argc
, argv
);
3028 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
3029 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
3032 json_object
*json_no
= NULL
;
3033 json_no
= json_object_new_object();
3034 json_object_string_add(json_no
, "warning",
3035 "Malformed address");
3036 vty_out(vty
, "%s\n",
3037 json_object_to_json_string(json_no
));
3038 json_object_free(json_no
);
3040 vty_out(vty
, "Malformed address: %s\n",
3041 argv
[idx_ipv4
]->arg
);
3045 peer
= peer_lookup(NULL
, &su
);
3046 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
3048 json_object
*json_no
= NULL
;
3049 json_no
= json_object_new_object();
3050 json_object_string_add(
3052 "No such neighbor or address family");
3053 vty_out(vty
, "%s\n",
3054 json_object_to_json_string(json_no
));
3055 json_object_free(json_no
);
3058 "%% No such neighbor or address family\n");
3062 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_neighbor
,
3068 DEFUN (show_ip_bgp_vpn_rd_neighbor_routes
,
3069 show_ip_bgp_vpn_rd_neighbor_routes_cmd
,
3070 "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors A.B.C.D routes [json]",
3075 "Display information for a route distinguisher\n"
3076 "VPN Route Distinguisher\n"
3077 "All VPN Route Distinguishers\n"
3078 "Detailed information on TCP and BGP neighbor connections\n"
3079 "Neighbor to display information about\n"
3080 "Display routes learned from neighbor\n"
3083 int idx_ext_community
= 5;
3088 struct prefix_rd prd
;
3089 bool prefix_rd_all
= false;
3090 bool uj
= use_json(argc
, argv
);
3094 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
3095 if (!strcmp(argv
[idx_ext_community
]->arg
, "all"))
3096 prefix_rd_all
= true;
3098 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
3101 json_object
*json_no
= NULL
;
3102 json_no
= json_object_new_object();
3103 json_object_string_add(
3105 "Malformed Route Distinguisher");
3106 vty_out(vty
, "%s\n",
3107 json_object_to_json_string(
3109 json_object_free(json_no
);
3112 "%% Malformed Route Distinguisher\n");
3117 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
3120 json_object
*json_no
= NULL
;
3121 json_no
= json_object_new_object();
3122 json_object_string_add(json_no
, "warning",
3123 "Malformed address");
3124 vty_out(vty
, "%s\n",
3125 json_object_to_json_string(json_no
));
3126 json_object_free(json_no
);
3128 vty_out(vty
, "Malformed address: %s\n",
3129 argv
[idx_ext_community
]->arg
);
3133 peer
= peer_lookup(NULL
, &su
);
3134 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
3136 json_object
*json_no
= NULL
;
3137 json_no
= json_object_new_object();
3138 json_object_string_add(
3140 "No such neighbor or address family");
3141 vty_out(vty
, "%s\n",
3142 json_object_to_json_string(json_no
));
3143 json_object_free(json_no
);
3146 "%% No such neighbor or address family\n");
3151 return bgp_show_mpls_vpn(vty
, afi
, NULL
,
3152 bgp_show_type_neighbor
, &su
, 0,
3155 return bgp_show_mpls_vpn(vty
, afi
, &prd
,
3156 bgp_show_type_neighbor
, &su
, 0,
3162 DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes
,
3163 show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd
,
3164 "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
3169 "Display information about all VPNv4/VPNv6 NLRIs\n"
3170 "Detailed information on TCP and BGP neighbor connections\n"
3171 "Neighbor to display information about\n"
3172 "Display the routes advertised to a BGP neighbor\n"
3179 bool uj
= use_json(argc
, argv
);
3183 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
3184 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
3187 json_object
*json_no
= NULL
;
3188 json_no
= json_object_new_object();
3189 json_object_string_add(json_no
, "warning",
3190 "Malformed address");
3191 vty_out(vty
, "%s\n",
3192 json_object_to_json_string(json_no
));
3193 json_object_free(json_no
);
3195 vty_out(vty
, "Malformed address: %s\n",
3196 argv
[idx_ipv4
]->arg
);
3199 peer
= peer_lookup(NULL
, &su
);
3200 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
3202 json_object
*json_no
= NULL
;
3203 json_no
= json_object_new_object();
3204 json_object_string_add(
3206 "No such neighbor or address family");
3207 vty_out(vty
, "%s\n",
3208 json_object_to_json_string(json_no
));
3209 json_object_free(json_no
);
3212 "%% No such neighbor or address family\n");
3215 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_IP
,
3221 DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes
,
3222 show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd
,
3223 "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors A.B.C.D advertised-routes [json]",
3228 "Display information for a route distinguisher\n"
3229 "VPN Route Distinguisher\n"
3230 "All VPN Route Distinguishers\n"
3231 "Detailed information on TCP and BGP neighbor connections\n"
3232 "Neighbor to display information about\n"
3233 "Display the routes advertised to a BGP neighbor\n"
3236 int idx_ext_community
= 5;
3240 struct prefix_rd prd
;
3242 bool uj
= use_json(argc
, argv
);
3246 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
3247 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
3250 json_object
*json_no
= NULL
;
3251 json_no
= json_object_new_object();
3252 json_object_string_add(json_no
, "warning",
3253 "Malformed address");
3254 vty_out(vty
, "%s\n",
3255 json_object_to_json_string(json_no
));
3256 json_object_free(json_no
);
3258 vty_out(vty
, "Malformed address: %s\n",
3259 argv
[idx_ext_community
]->arg
);
3262 peer
= peer_lookup(NULL
, &su
);
3263 if (!peer
|| !peer
->afc
[afi
][SAFI_MPLS_VPN
]) {
3265 json_object
*json_no
= NULL
;
3266 json_no
= json_object_new_object();
3267 json_object_string_add(
3269 "No such neighbor or address family");
3270 vty_out(vty
, "%s\n",
3271 json_object_to_json_string(json_no
));
3272 json_object_free(json_no
);
3275 "%% No such neighbor or address family\n");
3279 if (!strcmp(argv
[idx_ext_community
]->arg
, "all"))
3280 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_IP
,
3282 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
3285 json_object
*json_no
= NULL
;
3286 json_no
= json_object_new_object();
3287 json_object_string_add(
3289 "Malformed Route Distinguisher");
3290 vty_out(vty
, "%s\n",
3291 json_object_to_json_string(json_no
));
3292 json_object_free(json_no
);
3295 "%% Malformed Route Distinguisher\n");
3299 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_IP
,
3304 #endif /* KEEP_OLD_VPN_COMMANDS */
3306 void bgp_mplsvpn_init(void)
3308 install_element(BGP_VPNV4_NODE
, &vpnv4_network_cmd
);
3309 install_element(BGP_VPNV4_NODE
, &vpnv4_network_route_map_cmd
);
3310 install_element(BGP_VPNV4_NODE
, &no_vpnv4_network_cmd
);
3312 install_element(BGP_VPNV6_NODE
, &vpnv6_network_cmd
);
3313 install_element(BGP_VPNV6_NODE
, &no_vpnv6_network_cmd
);
3315 install_element(VIEW_NODE
, &show_bgp_ip_vpn_all_rd_cmd
);
3316 install_element(VIEW_NODE
, &show_bgp_ip_vpn_rd_cmd
);
3317 #ifdef KEEP_OLD_VPN_COMMANDS
3318 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_cmd
);
3319 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_cmd
);
3320 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_tags_cmd
);
3321 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_tags_cmd
);
3322 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_neighbor_routes_cmd
);
3323 install_element(VIEW_NODE
, &show_ip_bgp_vpn_rd_neighbor_routes_cmd
);
3324 install_element(VIEW_NODE
,
3325 &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd
);
3326 install_element(VIEW_NODE
,
3327 &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd
);
3328 #endif /* KEEP_OLD_VPN_COMMANDS */
3331 vrf_id_t
get_first_vrf_for_redirect_with_rt(struct ecommunity
*eckey
)
3333 struct listnode
*mnode
, *mnnode
;
3337 if (eckey
->unit_size
== IPV6_ECOMMUNITY_SIZE
)
3340 for (ALL_LIST_ELEMENTS(bm
->bgp
, mnode
, mnnode
, bgp
)) {
3341 struct ecommunity
*ec
;
3343 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3346 ec
= bgp
->vpn_policy
[afi
].import_redirect_rtlist
;
3348 if (ec
&& eckey
->unit_size
!= ec
->unit_size
)
3351 if (ecommunity_include(ec
, eckey
))
3358 * The purpose of this function is to process leaks that were deferred
3359 * from earlier per-vrf configuration due to not-yet-existing default
3360 * vrf, in other words, configuration such as:
3362 * router bgp MMM vrf FOO
3363 * address-family ipv4 unicast
3365 * exit-address-family
3370 * This function gets called when the default instance ("router bgp NNN")
3373 void vpn_leak_postchange_all(void)
3375 struct listnode
*next
;
3377 struct bgp
*bgp_default
= bgp_get_default();
3379 assert(bgp_default
);
3381 /* First, do any exporting from VRFs to the single VPN RIB */
3382 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, next
, bgp
)) {
3384 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3387 vpn_leak_postchange(
3388 BGP_VPN_POLICY_DIR_TOVPN
,
3393 vpn_leak_postchange(
3394 BGP_VPN_POLICY_DIR_TOVPN
,
3400 /* Now, do any importing to VRFs from the single VPN RIB */
3401 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, next
, bgp
)) {
3403 if (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3406 vpn_leak_postchange(
3407 BGP_VPN_POLICY_DIR_FROMVPN
,
3412 vpn_leak_postchange(
3413 BGP_VPN_POLICY_DIR_FROMVPN
,
3420 /* When a bgp vrf instance is unconfigured, remove its routes
3421 * from the VPN table and this vrf could be importing routes from other
3422 * bgp vrf instnaces, unimport them.
3423 * VRF X and VRF Y are exporting routes to each other.
3424 * When VRF X is deleted, unimport its routes from all target vrfs,
3425 * also VRF Y should unimport its routes from VRF X table.
3426 * This will ensure VPN table is cleaned up appropriately.
3428 void bgp_vpn_leak_unimport(struct bgp
*from_bgp
)
3431 const char *tmp_name
;
3433 struct listnode
*node
, *next
;
3434 safi_t safi
= SAFI_UNICAST
;
3436 bool is_vrf_leak_bind
;
3439 if (from_bgp
->inst_type
!= BGP_INSTANCE_TYPE_VRF
)
3442 debug
= (BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
) |
3443 BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
));
3445 tmp_name
= from_bgp
->name
? from_bgp
->name
: VRF_DEFAULT_NAME
;
3447 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
3448 /* vrf leak is for IPv4 and IPv6 Unicast only */
3449 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
3452 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, next
, to_bgp
)) {
3453 if (from_bgp
== to_bgp
)
3456 /* Unimport and remove source vrf from the
3457 * other vrfs import list.
3459 struct vpn_policy
*to_vpolicy
;
3461 is_vrf_leak_bind
= false;
3462 to_vpolicy
= &(to_bgp
->vpn_policy
[afi
]);
3463 for (ALL_LIST_ELEMENTS_RO(to_vpolicy
->import_vrf
, node
,
3465 if (strcmp(vname
, tmp_name
) == 0) {
3466 is_vrf_leak_bind
= true;
3470 /* skip this bgp instance as there is no leak to this
3473 if (!is_vrf_leak_bind
)
3477 zlog_debug("%s: unimport routes from %s to_bgp %s afi %s import vrfs count %u",
3478 __func__
, from_bgp
->name_pretty
,
3479 to_bgp
->name_pretty
, afi2str(afi
),
3480 to_vpolicy
->import_vrf
->count
);
3482 vrf_unimport_from_vrf(to_bgp
, from_bgp
, afi
, safi
);
3484 /* readd vrf name as unimport removes import vrf name
3485 * from the destination vrf's import list where the
3486 * `import vrf` configuration still exist.
3488 vname
= XSTRDUP(MTYPE_TMP
, tmp_name
);
3489 listnode_add(to_bgp
->vpn_policy
[afi
].import_vrf
,
3491 SET_FLAG(to_bgp
->af_flags
[afi
][safi
],
3492 BGP_CONFIG_VRF_TO_VRF_IMPORT
);
3494 /* If to_bgp exports its routes to the bgp vrf
3495 * which is being deleted, un-import the
3496 * to_bgp routes from VPN.
3498 for (ALL_LIST_ELEMENTS_RO(to_bgp
->vpn_policy
[afi
]
3501 if (strcmp(vname
, tmp_name
) == 0) {
3502 vrf_unimport_from_vrf(from_bgp
, to_bgp
,
3512 /* When a router bgp is configured, there could be a bgp vrf
3513 * instance importing routes from this newly configured
3514 * bgp vrf instance. Export routes from configured
3516 * VRF Y has import from bgp vrf x,
3517 * when a bgp vrf x instance is created, export its routes
3518 * to VRF Y instance.
3520 void bgp_vpn_leak_export(struct bgp
*from_bgp
)
3523 const char *export_name
;
3525 struct listnode
*node
, *next
;
3526 struct ecommunity
*ecom
;
3527 enum vpn_policy_direction idir
, edir
;
3528 safi_t safi
= SAFI_UNICAST
;
3532 debug
= (BGP_DEBUG(vpn
, VPN_LEAK_TO_VRF
) |
3533 BGP_DEBUG(vpn
, VPN_LEAK_FROM_VRF
));
3535 idir
= BGP_VPN_POLICY_DIR_FROMVPN
;
3536 edir
= BGP_VPN_POLICY_DIR_TOVPN
;
3538 export_name
= from_bgp
->name
? from_bgp
->name
: VRF_DEFAULT_NAME
;
3540 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
3541 /* vrf leak is for IPv4 and IPv6 Unicast only */
3542 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
3545 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, next
, to_bgp
)) {
3546 if (from_bgp
== to_bgp
)
3549 /* bgp instance has import list, check to see if newly
3550 * configured bgp instance is the list.
3552 struct vpn_policy
*to_vpolicy
;
3554 to_vpolicy
= &(to_bgp
->vpn_policy
[afi
]);
3555 for (ALL_LIST_ELEMENTS_RO(to_vpolicy
->import_vrf
,
3557 if (strcmp(vname
, export_name
) != 0)
3561 zlog_debug("%s: found from_bgp %s in to_bgp %s import list, import routes.",
3563 export_name
, to_bgp
->name_pretty
);
3565 ecom
= from_bgp
->vpn_policy
[afi
].rtlist
[edir
];
3566 /* remove import rt, it will be readded
3567 * as part of import from vrf.
3571 to_vpolicy
->rtlist
[idir
],
3572 (struct ecommunity_val
*)
3574 vrf_import_from_vrf(to_bgp
, from_bgp
,