2 * Zebra dataplane plugin for DPDK based hw offload
4 * Copyright (C) 2021 Nvidia
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "config.h" /* Include this explicitly */
26 #include "lib/libfrr.h"
28 #include "zebra/debug.h"
29 #include "zebra/interface.h"
30 #include "zebra/zebra_dplane.h"
31 #include "zebra/debug.h"
32 #include "zebra/zebra_pbr.h"
34 #include "zebra/dpdk/zebra_dplane_dpdk_private.h"
36 static const char *plugin_name
= "zebra_dplane_dpdk";
38 extern struct zebra_privs_t zserv_privs
;
40 static struct zd_dpdk_ctx dpdk_ctx_buf
, *dpdk_ctx
= &dpdk_ctx_buf
;
41 #define dpdk_stat (&dpdk_ctx->stats)
44 void zd_dpdk_stat_show(struct vty
*vty
)
48 vty_out(vty
, "%30s\n%30s\n", "Dataplane DPDK counters",
49 "=======================");
51 #define ZD_DPDK_SHOW_COUNTER(label, counter) \
54 atomic_load_explicit(&counter, memory_order_relaxed); \
55 vty_out(vty, "%28s: %u\n", (label), (tmp_cnt)); \
58 ZD_DPDK_SHOW_COUNTER("PBR rule adds", dpdk_stat
->rule_adds
);
59 ZD_DPDK_SHOW_COUNTER("PBR rule dels", dpdk_stat
->rule_dels
);
60 ZD_DPDK_SHOW_COUNTER("Ignored updates", dpdk_stat
->ignored_updates
);
64 static void zd_dpdk_rule_add(struct zebra_dplane_ctx
*ctx
)
66 /* XXX - place holder */
70 static void zd_dpdk_rule_del(const char *ifname
, int in_ifindex
,
74 /* XXX - place holder */
78 static void zd_dpdk_rule_update(struct zebra_dplane_ctx
*ctx
)
84 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
) {
85 zlog_debug("Dplane %s", dplane_op2str(dplane_ctx_get_op(ctx
)));
88 op
= dplane_ctx_get_op(ctx
);
90 case DPLANE_OP_RULE_ADD
:
91 atomic_fetch_add_explicit(&dpdk_stat
->rule_adds
, 1,
92 memory_order_relaxed
);
93 zd_dpdk_rule_add(ctx
);
96 case DPLANE_OP_RULE_UPDATE
:
97 /* delete old rule and install new one */
98 atomic_fetch_add_explicit(&dpdk_stat
->rule_adds
, 1,
99 memory_order_relaxed
);
100 in_ifindex
= dplane_ctx_get_ifindex(ctx
);
101 dp_flow_ptr
= dplane_ctx_rule_get_old_dp_flow_ptr(ctx
);
102 zd_dpdk_rule_del(dplane_ctx_rule_get_ifname(ctx
), in_ifindex
,
104 zd_dpdk_rule_add(ctx
);
107 case DPLANE_OP_RULE_DELETE
:
108 atomic_fetch_add_explicit(&dpdk_stat
->rule_dels
, 1,
109 memory_order_relaxed
);
110 in_ifindex
= dplane_ctx_get_ifindex(ctx
);
111 dp_flow_ptr
= dplane_ctx_rule_get_dp_flow_ptr(ctx
);
112 zd_dpdk_rule_del(dplane_ctx_rule_get_ifname(ctx
), in_ifindex
,
121 /* DPDK provider callback.
123 static void zd_dpdk_process_update(struct zebra_dplane_ctx
*ctx
)
125 switch (dplane_ctx_get_op(ctx
)) {
127 case DPLANE_OP_RULE_ADD
:
128 case DPLANE_OP_RULE_UPDATE
:
129 case DPLANE_OP_RULE_DELETE
:
130 zd_dpdk_rule_update(ctx
);
134 atomic_fetch_add_explicit(&dpdk_stat
->ignored_updates
, 1,
135 memory_order_relaxed
);
142 static int zd_dpdk_process(struct zebra_dplane_provider
*prov
)
144 struct zebra_dplane_ctx
*ctx
;
147 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
148 zlog_debug("processing %s", dplane_provider_get_name(prov
));
150 limit
= dplane_provider_get_work_limit(prov
);
151 for (counter
= 0; counter
< limit
; counter
++) {
152 ctx
= dplane_provider_dequeue_in_ctx(prov
);
156 zd_dpdk_process_update(ctx
);
157 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
158 dplane_provider_enqueue_out_ctx(prov
, ctx
);
164 static int zd_dpdk_init(void)
167 char *argv
[] = {(char *)"/usr/lib/frr/zebra", (char *)"--"};
171 frr_with_privs (&zserv_privs
) {
172 rc
= rte_eal_init(sizeof(argv
) / sizeof(argv
[0]), argv
);
175 zlog_warn("EAL init failed %s", rte_strerror(rte_errno
));
182 static int zd_dpdk_start(struct zebra_dplane_provider
*prov
)
184 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
185 zlog_debug("%s start", dplane_provider_get_name(prov
));
187 return zd_dpdk_init();
191 static int zd_dpdk_finish(struct zebra_dplane_provider
*prov
, bool early
)
196 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
197 zlog_debug("%s early finish",
198 dplane_provider_get_name(prov
));
203 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
204 zlog_debug("%s finish", dplane_provider_get_name(prov
));
207 frr_with_privs (&zserv_privs
) {
208 rc
= rte_eal_cleanup();
211 zlog_warn("EAL cleanup failed %s", rte_strerror(rte_errno
));
217 static int zd_dpdk_plugin_init(struct thread_master
*tm
)
221 ret
= dplane_provider_register(
222 plugin_name
, DPLANE_PRIO_KERNEL
, DPLANE_PROV_FLAGS_DEFAULT
,
223 zd_dpdk_start
, zd_dpdk_process
, zd_dpdk_finish
, dpdk_ctx
, NULL
);
225 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
226 zlog_debug("%s register status %d", plugin_name
, ret
);
232 static int zd_dpdk_module_init(void)
234 hook_register(frr_late_init
, zd_dpdk_plugin_init
);
238 FRR_MODULE_SETUP(.name
= "dplane_dpdk", .version
= "0.0.1",
239 .description
= "Data plane plugin using dpdk for hw offload",
240 .init
= zd_dpdk_module_init
, );