1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
10 * Purpose: Handle exchange of routes between VNC and Zebra
13 #include "lib/zebra.h"
14 #include "lib/prefix.h"
15 #include "lib/agg_table.h"
17 #include "lib/command.h"
18 #include "lib/zclient.h"
19 #include "lib/stream.h"
20 #include "lib/ringbuf.h"
21 #include "lib/memory.h"
22 #include "lib/lib_errors.h"
24 #include "bgpd/bgpd.h"
25 #include "bgpd/bgp_ecommunity.h"
26 #include "bgpd/bgp_route.h"
27 #include "bgpd/bgp_debug.h"
28 #include "bgpd/bgp_advertise.h"
30 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
31 #include "bgpd/rfapi/rfapi.h"
32 #include "bgpd/rfapi/rfapi_import.h"
33 #include "bgpd/rfapi/rfapi_private.h"
34 #include "bgpd/rfapi/vnc_zebra.h"
35 #include "bgpd/rfapi/rfapi_vty.h"
36 #include "bgpd/rfapi/rfapi_backend.h"
37 #include "bgpd/rfapi/vnc_debug.h"
39 static struct rfapi_descriptor vncHD1VR
; /* Single-VR export dummy nve descr */
40 static struct zclient
*zclient_vnc
= NULL
;
42 /***********************************************************************
43 * REDISTRIBUTE: Zebra sends updates/withdraws to BGPD
44 ***********************************************************************/
47 * Routes coming from zebra get added to VNC here
49 static void vnc_redistribute_add(struct prefix
*p
, uint32_t metric
,
52 struct bgp
*bgp
= bgp_get_default();
54 struct rfapi_ip_addr vnaddr
;
57 rfp_cost_to_localpref(metric
> 255 ? 255 : metric
);
62 if (!bgp
->rfapi_cfg
) {
63 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
68 afi
= family2afi(p
->family
);
70 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
75 if (!bgp
->rfapi_cfg
->redist
[afi
][type
]) {
76 vnc_zlog_debug_verbose(
77 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
81 if (!bgp
->rfapi_cfg
->rfg_redist
) {
82 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
88 * Assume nve group's configured VN address prefix is a host
89 * route which also happens to give the NVE VN address to use
90 * for redistributing into VNC.
92 vnaddr
.addr_family
= bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
.family
;
93 switch (bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
.family
) {
95 if (bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
.prefixlen
97 vnc_zlog_debug_verbose(
98 "%s: redist nve group VN prefix len (%d) != 32, skipping",
100 bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
105 bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
.u
.prefix4
;
108 if (bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
.prefixlen
109 != IPV6_MAX_BITLEN
) {
110 vnc_zlog_debug_verbose(
111 "%s: redist nve group VN prefix len (%d) != 128, skipping",
113 bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
118 bgp
->rfapi_cfg
->rfg_redist
->vn_prefix
.u
.prefix6
;
121 vnc_zlog_debug_verbose(
122 "%s: no redist nve group VN host prefix configured, skipping",
128 * Assume nve group's configured UN address prefix is a host
129 * route which also happens to give the NVE UN address to use
130 * for redistributing into VNC.
134 * Set UN address in dummy nve descriptor so add_vnc_route
135 * can use it in VNC tunnel SubTLV
138 struct rfapi_ip_prefix pfx_un
;
140 rfapiQprefix2Rprefix(&bgp
->rfapi_cfg
->rfg_redist
->un_prefix
,
143 switch (pfx_un
.prefix
.addr_family
) {
145 if (pfx_un
.length
!= IPV4_MAX_BITLEN
) {
146 vnc_zlog_debug_verbose(
147 "%s: redist nve group UN prefix len (%d) != 32, skipping",
148 __func__
, pfx_un
.length
);
153 if (pfx_un
.length
!= IPV6_MAX_BITLEN
) {
154 vnc_zlog_debug_verbose(
155 "%s: redist nve group UN prefix len (%d) != 128, skipping",
156 __func__
, pfx_un
.length
);
161 vnc_zlog_debug_verbose(
162 "%s: no redist nve group UN host prefix configured, skipping",
167 vncHD1VR
.un_addr
= pfx_un
.prefix
;
169 if (!vncHD1VR
.peer
) {
171 * Same setup as in rfapi_open()
173 vncHD1VR
.peer
= peer_new(bgp
);
174 vncHD1VR
.peer
->status
=
175 Established
; /* keep bgp core happy */
176 bgp_sync_delete(vncHD1VR
.peer
); /* don't need these */
179 * since this peer is not on the I/O thread, this lock
180 * is not strictly necessary, but serves as a reminder
181 * to those who may meddle...
183 frr_with_mutex (&vncHD1VR
.peer
->io_mtx
) {
184 // we don't need any I/O related facilities
185 if (vncHD1VR
.peer
->ibuf
)
186 stream_fifo_free(vncHD1VR
.peer
->ibuf
);
187 if (vncHD1VR
.peer
->obuf
)
188 stream_fifo_free(vncHD1VR
.peer
->obuf
);
190 if (vncHD1VR
.peer
->ibuf_work
)
191 ringbuf_del(vncHD1VR
.peer
->ibuf_work
);
192 if (vncHD1VR
.peer
->obuf_work
)
193 stream_free(vncHD1VR
.peer
->obuf_work
);
195 vncHD1VR
.peer
->ibuf
= NULL
;
196 vncHD1VR
.peer
->obuf
= NULL
;
197 vncHD1VR
.peer
->obuf_work
= NULL
;
198 vncHD1VR
.peer
->ibuf_work
= NULL
;
201 /* base code assumes have valid host pointer */
202 vncHD1VR
.peer
->host
=
203 XSTRDUP(MTYPE_BGP_PEER_HOST
, ".zebra.");
205 /* Mark peer as belonging to HD */
206 SET_FLAG(vncHD1VR
.peer
->flags
, PEER_FLAG_IS_RFAPI_HD
);
210 memset(&prd
, 0, sizeof(prd
));
211 prd
= bgp
->rfapi_cfg
->rfg_redist
->rd
;
212 prd
.family
= AF_UNSPEC
;
215 add_vnc_route(&vncHD1VR
, /* cookie + UN addr */
216 bgp
, SAFI_MPLS_VPN
, p
, &prd
, &vnaddr
, &local_pref
,
217 &(bgp
->rfapi_cfg
->redist_lifetime
),
218 NULL
, /* RFP options */
219 NULL
, /* struct rfapi_un_option */
220 NULL
, /* struct rfapi_vn_option */
221 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
, NULL
,
222 NULL
, /* label: default */
223 type
, BGP_ROUTE_REDISTRIBUTE
, 0); /* flags */
227 * Route deletions from zebra propagate to VNC here
229 static void vnc_redistribute_delete(struct prefix
*p
, uint8_t type
)
231 struct bgp
*bgp
= bgp_get_default();
232 struct prefix_rd prd
;
238 if (!bgp
->rfapi_cfg
) {
239 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
243 afi
= family2afi(p
->family
);
245 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
246 __func__
, p
->family
);
249 if (!bgp
->rfapi_cfg
->redist
[afi
][type
]) {
250 vnc_zlog_debug_verbose(
251 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
252 __func__
, afi
, type
);
255 if (!bgp
->rfapi_cfg
->rfg_redist
) {
256 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
261 memset(&prd
, 0, sizeof(prd
));
262 prd
= bgp
->rfapi_cfg
->rfg_redist
->rd
;
263 prd
.family
= AF_UNSPEC
;
266 del_vnc_route(&vncHD1VR
, /* use dummy ptr as cookie */
267 vncHD1VR
.peer
, bgp
, SAFI_MPLS_VPN
, p
, &prd
, type
,
268 BGP_ROUTE_REDISTRIBUTE
, NULL
, 0);
272 * Flush all redistributed routes of type <type>
274 static void vnc_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, uint8_t type
)
276 struct prefix_rd prd
;
277 struct bgp_table
*table
;
278 struct bgp_dest
*pdest
;
279 struct bgp_dest
*dest
;
281 vnc_zlog_debug_verbose("%s: entry", __func__
);
285 if (!bgp
->rfapi_cfg
) {
286 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
292 * Loop over all the RDs
294 for (pdest
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); pdest
;
295 pdest
= bgp_route_next(pdest
)) {
296 const struct prefix
*pdest_p
= bgp_dest_get_prefix(pdest
);
298 memset(&prd
, 0, sizeof(prd
));
299 prd
.family
= AF_UNSPEC
;
301 memcpy(prd
.val
, pdest_p
->u
.val
, 8);
303 /* This is the per-RD table of prefixes */
304 table
= bgp_dest_get_bgp_table_info(pdest
);
308 for (dest
= bgp_table_top(table
); dest
;
309 dest
= bgp_route_next(dest
)) {
311 struct bgp_path_info
*ri
;
313 for (ri
= bgp_dest_get_bgp_path_info(dest
); ri
;
316 == type
) { /* has matching redist type */
322 &vncHD1VR
, /* use dummy ptr as cookie */
323 vncHD1VR
.peer
, bgp
, SAFI_MPLS_VPN
,
324 bgp_dest_get_prefix(dest
), &prd
, type
,
325 BGP_ROUTE_REDISTRIBUTE
, NULL
, 0);
329 vnc_zlog_debug_verbose("%s: return", __func__
);
333 * Zebra route add and delete treatment.
337 static int vnc_zebra_read_route(ZAPI_CALLBACK_ARGS
)
339 struct zapi_route api
;
342 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
345 /* we completely ignore srcdest routes for now. */
346 if (CHECK_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
))
349 add
= (cmd
== ZEBRA_REDISTRIBUTE_ROUTE_ADD
);
351 vnc_redistribute_add(&api
.prefix
, api
.metric
, api
.type
);
353 vnc_redistribute_delete(&api
.prefix
, api
.type
);
355 if (BGP_DEBUG(zebra
, ZEBRA
))
356 vnc_zlog_debug_verbose(
357 "%s: Zebra rcvd: route delete %s %pFX metric %u",
358 __func__
, zebra_route_string(api
.type
), &api
.prefix
,
364 /***********************************************************************
365 * vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
366 ***********************************************************************/
369 * low-level message builder
371 static void vnc_zebra_route_msg(const struct prefix
*p
, unsigned int nhp_count
,
372 void *nhp_ary
, int add
) /* 1 = add, 0 = del */
374 struct zapi_route api
;
375 struct zapi_nexthop
*api_nh
;
377 struct in_addr
**nhp_ary4
= nhp_ary
;
378 struct in6_addr
**nhp_ary6
= nhp_ary
;
381 vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
386 memset(&api
, 0, sizeof(api
));
387 api
.vrf_id
= VRF_DEFAULT
;
388 api
.type
= ZEBRA_ROUTE_VNC
;
389 api
.safi
= SAFI_UNICAST
;
393 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
394 api
.nexthop_num
= MIN(nhp_count
, multipath_num
);
395 for (i
= 0; i
< api
.nexthop_num
; i
++) {
397 api_nh
= &api
.nexthops
[i
];
398 api_nh
->vrf_id
= VRF_DEFAULT
;
401 memcpy(&api_nh
->gate
.ipv4
, nhp_ary4
[i
],
402 sizeof(api_nh
->gate
.ipv4
));
403 api_nh
->type
= NEXTHOP_TYPE_IPV4
;
406 memcpy(&api_nh
->gate
.ipv6
, nhp_ary6
[i
],
407 sizeof(api_nh
->gate
.ipv6
));
408 api_nh
->type
= NEXTHOP_TYPE_IPV6
;
413 if (BGP_DEBUG(zebra
, ZEBRA
))
414 vnc_zlog_debug_verbose(
415 "%s: Zebra send: route %s %pFX, nhp_count=%d", __func__
,
416 (add
? "add" : "del"), &api
.prefix
, nhp_count
);
418 zclient_route_send((add
? ZEBRA_ROUTE_ADD
: ZEBRA_ROUTE_DELETE
),
424 nve_list_to_nh_array(uint8_t family
, struct list
*nve_list
,
425 unsigned int *nh_count_ret
,
426 void **nh_ary_ret
, /* returned address array */
427 void **nhp_ary_ret
) /* returned pointer array */
429 int nve_count
= listcount(nve_list
);
436 vnc_zlog_debug_verbose("%s: empty nve_list, skipping",
441 if (family
== AF_INET
) {
447 * Array of nexthop addresses
450 XCALLOC(MTYPE_TMP
, nve_count
* sizeof(struct in_addr
));
453 * Array of pointers to nexthop addresses
455 *nhp_ary_ret
= XCALLOC(MTYPE_TMP
,
456 nve_count
* sizeof(struct in_addr
*));
460 for (ln
= listhead(nve_list
); ln
; ln
= listnextnode(ln
)) {
462 struct rfapi_descriptor
*irfd
;
465 irfd
= listgetdata(ln
);
467 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
470 *iap
= nhp
.u
.prefix4
;
472 vnc_zlog_debug_verbose(
473 "%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p",
474 __func__
, iap
, nhp
.u
.prefix4
.s_addr
, v
, iap
);
481 } else if (family
== AF_INET6
) {
486 XCALLOC(MTYPE_TMP
, nve_count
* sizeof(struct in6_addr
));
488 *nhp_ary_ret
= XCALLOC(MTYPE_TMP
,
489 nve_count
* sizeof(struct in6_addr
*));
491 for (ln
= listhead(nve_list
); ln
; ln
= listnextnode(ln
)) {
493 struct rfapi_descriptor
*irfd
;
494 struct in6_addr
*iap
= *nh_ary_ret
;
495 struct in6_addr
**v
= *nhp_ary_ret
;
498 irfd
= listgetdata(ln
);
500 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
503 *iap
= nhp
.u
.prefix6
;
513 static void import_table_to_nve_list_zebra(struct bgp
*bgp
,
514 struct rfapi_import_table
*it
,
515 struct list
**nves
, uint8_t family
)
517 struct listnode
*node
;
518 struct rfapi_rfg_name
*rfgn
;
521 * Loop over the list of NVE-Groups configured for
522 * exporting to direct-bgp.
524 * Build a list of NVEs that use this import table
527 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_zebra_l
, node
,
531 * If this NVE-Group's import table matches the current one
533 if (rfgn
->rfg
&& rfgn
->rfg
->nves
534 && rfgn
->rfg
->rfapi_import_table
== it
) {
536 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
541 static void vnc_zebra_add_del_prefix(struct bgp
*bgp
,
542 struct rfapi_import_table
*import_table
,
544 int add
) /* !0 = add, 0 = del */
547 const struct prefix
*p
= agg_node_get_prefix(rn
);
548 unsigned int nexthop_count
= 0;
550 void *nhp_ary
= NULL
;
552 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__
, add
);
554 if (zclient_vnc
->sock
< 0)
557 if (p
->family
!= AF_INET
&& p
->family
!= AF_INET6
) {
558 flog_err(EC_LIB_DEVELOPMENT
,
559 "%s: invalid route node addr family", __func__
);
563 if (!vrf_bitmap_check(
564 zclient_vnc
->redist
[family2afi(p
->family
)][ZEBRA_ROUTE_VNC
],
568 if (!bgp
->rfapi_cfg
) {
569 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
573 if (!listcount(bgp
->rfapi_cfg
->rfg_export_zebra_l
)) {
574 vnc_zlog_debug_verbose(
575 "%s: no zebra export nve group, skipping", __func__
);
579 import_table_to_nve_list_zebra(bgp
, import_table
, &nves
, p
->family
);
582 nve_list_to_nh_array(p
->family
, nves
, &nexthop_count
, &nh_ary
,
588 vnc_zebra_route_msg(p
, nexthop_count
, nhp_ary
, add
);
591 XFREE(MTYPE_TMP
, nhp_ary
);
592 XFREE(MTYPE_TMP
, nh_ary
);
595 void vnc_zebra_add_prefix(struct bgp
*bgp
,
596 struct rfapi_import_table
*import_table
,
599 vnc_zebra_add_del_prefix(bgp
, import_table
, rn
, 1);
602 void vnc_zebra_del_prefix(struct bgp
*bgp
,
603 struct rfapi_import_table
*import_table
,
606 vnc_zebra_add_del_prefix(bgp
, import_table
, rn
, 0);
610 static void vnc_zebra_add_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
611 int add
) /* 0 = del, !0 = add */
613 struct listnode
*node
;
614 struct rfapi_rfg_name
*rfgn
;
615 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
616 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
620 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__
, add
);
622 if (zclient_vnc
->sock
< 0)
625 if (!vrf_bitmap_check(zclient_vnc
->redist
[afi
][ZEBRA_ROUTE_VNC
],
629 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
630 flog_err(EC_LIB_DEVELOPMENT
, "%s: invalid vn addr family",
637 if (!bgp
->rfapi_cfg
) {
638 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
643 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &nhp
)) {
644 vnc_zlog_debug_verbose("%s: can't convert vn address, skipping",
652 * Loop over the list of NVE-Groups configured for
653 * exporting to zebra and see if this new NVE's
654 * group is among them.
656 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_zebra_l
, node
,
660 * Yes, this NVE's group is configured for export to zebra
662 if (rfgn
->rfg
== rfg
) {
664 struct agg_table
*rt
= NULL
;
666 struct rfapi_import_table
*import_table
;
667 import_table
= rfg
->rfapi_import_table
;
669 vnc_zlog_debug_verbose(
670 "%s: this nve's group is in zebra export list",
673 rt
= import_table
->imported_vpn
[afi
];
676 * Walk the NVE-Group's VNC Import table
678 for (rn
= agg_route_top(rt
); rn
;
679 rn
= agg_route_next(rn
)) {
683 vnc_zlog_debug_verbose("%s: sending %s",
685 (add
? "add" : "del"));
686 vnc_zebra_route_msg(agg_node_get_prefix(rn
), 1,
693 void vnc_zebra_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
695 vnc_zebra_add_del_nve(bgp
, rfd
, 1);
698 void vnc_zebra_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
700 vnc_zebra_add_del_nve(bgp
, rfd
, 0);
703 static void vnc_zebra_add_del_group_afi(struct bgp
*bgp
,
704 struct rfapi_nve_group_cfg
*rfg
,
707 struct agg_table
*rt
= NULL
;
709 struct rfapi_import_table
*import_table
;
710 uint8_t family
= afi2family(afi
);
712 struct list
*nves
= NULL
;
713 unsigned int nexthop_count
= 0;
715 void *nhp_ary
= NULL
;
717 vnc_zlog_debug_verbose("%s: entry", __func__
);
718 import_table
= rfg
->rfapi_import_table
;
720 vnc_zlog_debug_verbose(
721 "%s: import table not defined, returning", __func__
);
725 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
726 rt
= import_table
->imported_vpn
[afi
];
728 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d", __func__
, afi
);
733 flog_err(EC_LIB_DEVELOPMENT
, "%s: computed bad family: %d",
739 /* avoid segfault below if list doesn't exist */
740 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
744 nve_group_to_nve_list(rfg
, &nves
, family
);
746 vnc_zlog_debug_verbose("%s: have nves", __func__
);
747 nve_list_to_nh_array(family
, nves
, &nexthop_count
, &nh_ary
,
750 vnc_zlog_debug_verbose("%s: family: %d, nve count: %d",
751 __func__
, family
, nexthop_count
);
757 * Walk the NVE-Group's VNC Import table
759 for (rn
= agg_route_top(rt
); rn
;
760 rn
= agg_route_next(rn
)) {
763 agg_node_get_prefix(rn
),
764 nexthop_count
, nhp_ary
, add
);
768 XFREE(MTYPE_TMP
, nhp_ary
);
769 XFREE(MTYPE_TMP
, nh_ary
);
773 void vnc_zebra_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
775 vnc_zebra_add_del_group_afi(bgp
, rfg
, AFI_IP
, 1);
776 vnc_zebra_add_del_group_afi(bgp
, rfg
, AFI_IP6
, 1);
779 void vnc_zebra_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
781 vnc_zlog_debug_verbose("%s: entry", __func__
);
782 vnc_zebra_add_del_group_afi(bgp
, rfg
, AFI_IP
, 0);
783 vnc_zebra_add_del_group_afi(bgp
, rfg
, AFI_IP6
, 0);
786 void vnc_zebra_reexport_group_afi(struct bgp
*bgp
,
787 struct rfapi_nve_group_cfg
*rfg
, afi_t afi
)
789 struct listnode
*node
;
790 struct rfapi_rfg_name
*rfgn
;
792 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_zebra_l
, node
,
795 if (rfgn
->rfg
== rfg
) {
796 vnc_zebra_add_del_group_afi(bgp
, rfg
, afi
, 0);
797 vnc_zebra_add_del_group_afi(bgp
, rfg
, afi
, 1);
804 /***********************************************************************
806 ***********************************************************************/
809 /* Other routes redistribution into BGP. */
810 int vnc_redistribute_set(struct bgp
*bgp
, afi_t afi
, int type
)
812 if (!bgp
->rfapi_cfg
) {
813 return CMD_WARNING_CONFIG_FAILED
;
816 /* Set flag to BGP instance. */
817 bgp
->rfapi_cfg
->redist
[afi
][type
] = 1;
819 // bgp->redist[afi][type] = 1;
821 /* Return if already redistribute flag is set. */
822 if (vrf_bitmap_check(zclient_vnc
->redist
[afi
][type
], VRF_DEFAULT
))
823 return CMD_WARNING_CONFIG_FAILED
;
825 vrf_bitmap_set(zclient_vnc
->redist
[afi
][type
], VRF_DEFAULT
);
827 // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
829 /* Return if zebra connection is not established. */
830 if (zclient_vnc
->sock
< 0)
831 return CMD_WARNING_CONFIG_FAILED
;
833 if (BGP_DEBUG(zebra
, ZEBRA
))
834 vnc_zlog_debug_verbose("Zebra send: redistribute add %s",
835 zebra_route_string(type
));
837 /* Send distribute add message to zebra. */
838 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD
, zclient_vnc
, afi
, type
,
844 /* Unset redistribution. */
845 int vnc_redistribute_unset(struct bgp
*bgp
, afi_t afi
, int type
)
847 vnc_zlog_debug_verbose("%s: type=%d entry", __func__
, type
);
849 if (!bgp
->rfapi_cfg
) {
850 vnc_zlog_debug_verbose("%s: return (no rfapi_cfg)", __func__
);
851 return CMD_WARNING_CONFIG_FAILED
;
854 /* Unset flag from BGP instance. */
855 bgp
->rfapi_cfg
->redist
[afi
][type
] = 0;
857 /* Return if zebra connection is disabled. */
858 if (!vrf_bitmap_check(zclient_vnc
->redist
[afi
][type
], VRF_DEFAULT
))
859 return CMD_WARNING_CONFIG_FAILED
;
860 vrf_bitmap_unset(zclient_vnc
->redist
[afi
][type
], VRF_DEFAULT
);
862 if (bgp
->rfapi_cfg
->redist
[AFI_IP
][type
] == 0
863 && bgp
->rfapi_cfg
->redist
[AFI_IP6
][type
] == 0
864 && zclient_vnc
->sock
>= 0) {
865 /* Send distribute delete message to zebra. */
866 if (BGP_DEBUG(zebra
, ZEBRA
))
867 vnc_zlog_debug_verbose(
868 "Zebra send: redistribute delete %s",
869 zebra_route_string(type
));
870 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE
, zclient_vnc
,
871 afi
, type
, 0, VRF_DEFAULT
);
874 /* Withdraw redistributed routes from current BGP's routing table. */
875 vnc_redistribute_withdraw(bgp
, afi
, type
);
877 vnc_zlog_debug_verbose("%s: return", __func__
);
882 extern struct zebra_privs_t bgpd_privs
;
884 static zclient_handler
*const vnc_handlers
[] = {
885 [ZEBRA_REDISTRIBUTE_ROUTE_ADD
] = vnc_zebra_read_route
,
886 [ZEBRA_REDISTRIBUTE_ROUTE_DEL
] = vnc_zebra_read_route
,
890 * Modeled after bgp_zebra.c'bgp_zebra_init()
891 * Charriere asks, "Is it possible to carry two?"
893 void vnc_zebra_init(struct thread_master
*master
)
895 /* Set default values. */
896 zclient_vnc
= zclient_new(master
, &zclient_options_default
,
897 vnc_handlers
, array_size(vnc_handlers
));
898 zclient_init(zclient_vnc
, ZEBRA_ROUTE_VNC
, 0, &bgpd_privs
);
901 void vnc_zebra_destroy(void)
903 if (zclient_vnc
== NULL
)
905 zclient_stop(zclient_vnc
);
906 zclient_free(zclient_vnc
);