1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Zebra dataplane plugin for DPDK based hw offload
5 * Copyright (C) 2021 Nvidia
10 #include "config.h" /* Include this explicitly */
13 #include "lib/libfrr.h"
15 #include "zebra/debug.h"
16 #include "zebra/interface.h"
17 #include "zebra/zebra_dplane.h"
18 #include "zebra/debug.h"
19 #include "zebra/zebra_pbr.h"
21 #include "zebra/dpdk/zebra_dplane_dpdk_private.h"
23 static const char *plugin_name
= "zebra_dplane_dpdk";
25 static struct zd_dpdk_ctx dpdk_ctx_buf
, *dpdk_ctx
= &dpdk_ctx_buf
;
26 #define dpdk_stat (&dpdk_ctx->stats)
28 static struct zd_dpdk_port
*zd_dpdk_port_find_by_index(int ifindex
);
30 DEFINE_MTYPE_STATIC(ZEBRA
, DPDK_PORTS
, "ZD DPDK port database");
32 void zd_dpdk_stat_show(struct vty
*vty
)
36 vty_out(vty
, "%30s\n%30s\n", "Dataplane DPDK counters",
37 "=======================");
39 #define ZD_DPDK_SHOW_COUNTER(label, counter) \
42 atomic_load_explicit(&counter, memory_order_relaxed); \
43 vty_out(vty, "%28s: %u\n", (label), (tmp_cnt)); \
46 ZD_DPDK_SHOW_COUNTER("PBR rule adds", dpdk_stat
->rule_adds
);
47 ZD_DPDK_SHOW_COUNTER("PBR rule dels", dpdk_stat
->rule_dels
);
48 ZD_DPDK_SHOW_COUNTER("Ignored updates", dpdk_stat
->ignored_updates
);
52 static void zd_dpdk_flow_stat_show(struct vty
*vty
, int in_ifindex
,
55 struct rte_flow_action_count count
= {.shared
= 0, .id
= 0};
56 const struct rte_flow_action actions
[] = {
58 .type
= RTE_FLOW_ACTION_TYPE_COUNT
,
62 .type
= RTE_FLOW_ACTION_TYPE_END
,
66 struct zd_dpdk_port
*in_dport
;
67 struct rte_flow_query_count query
;
68 struct rte_flow_error error
;
71 in_dport
= zd_dpdk_port_find_by_index(in_ifindex
);
73 vty_out(vty
, "PBR dpdk flow query failed; in_port %d missing\n",
77 memset(&query
, 0, sizeof(query
));
78 rc
= rte_flow_query(in_dport
->port_id
, (struct rte_flow
*)dp_flow_ptr
,
79 actions
, &query
, &error
);
82 "PBR dpdk flow query failed; in_ifindex %d rc %d\n",
83 in_ifindex
, error
.type
);
86 hits
= (query
.hits_set
) ? query
.hits
: 0;
87 bytes
= (query
.bytes_set
) ? query
.bytes
: 0;
88 vty_out(vty
, " DPDK stats: packets %" PRIu64
" bytes %" PRIu64
"\n",
93 static int zd_dpdk_pbr_show_rules_walkcb(struct hash_bucket
*bucket
, void *arg
)
95 struct zebra_pbr_rule
*rule
= (struct zebra_pbr_rule
*)bucket
->data
;
96 struct vty
*vty
= (struct vty
*)arg
;
98 struct interface
*ifp
= NULL
;
99 struct zebra_pbr_action
*zaction
= &rule
->action
;
101 zebra_pbr_show_rule_unit(rule
, vty
);
102 if (zaction
->dp_flow_ptr
) {
103 vrf
= vrf_lookup_by_id(rule
->vrf_id
);
105 ifp
= if_lookup_by_name_vrf(rule
->ifname
, vrf
);
108 zd_dpdk_flow_stat_show(vty
, ifp
->ifindex
,
109 zaction
->dp_flow_ptr
);
111 return HASHWALK_CONTINUE
;
115 void zd_dpdk_pbr_flows_show(struct vty
*vty
)
117 hash_walk(zrouter
.rules_hash
, zd_dpdk_pbr_show_rules_walkcb
, vty
);
121 static void zd_dpdk_rule_add(struct zebra_dplane_ctx
*ctx
)
123 static struct rte_flow_attr attrs
= {.ingress
= 1, .transfer
= 1};
124 uint32_t filter_bm
= dplane_ctx_rule_get_filter_bm(ctx
);
125 int in_ifindex
= dplane_ctx_get_ifindex(ctx
);
126 int out_ifindex
= dplane_ctx_rule_get_out_ifindex(ctx
);
127 struct rte_flow_item_eth eth
, eth_mask
;
128 struct rte_flow_item_ipv4 ip
, ip_mask
;
129 struct rte_flow_item_udp udp
, udp_mask
;
130 struct rte_flow_action_count conf_count
;
131 struct rte_flow_action_set_mac conf_smac
, conf_dmac
;
132 struct rte_flow_action_port_id conf_port
;
133 struct rte_flow_item items
[ZD_PBR_PATTERN_MAX
];
134 struct rte_flow_action actions
[ZD_PBR_ACTION_MAX
];
137 struct in_addr tmp_mask
;
138 const struct ethaddr
*mac
;
139 struct rte_flow
*flow
;
140 struct rte_flow_error error
;
141 struct zd_dpdk_port
*in_dport
;
142 struct zd_dpdk_port
*out_dport
;
143 uint32_t pri
= dplane_ctx_rule_get_priority(ctx
);
144 int seq
= dplane_ctx_rule_get_seq(ctx
);
145 int unique
= dplane_ctx_rule_get_unique(ctx
);
147 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
149 "PBR dpdk flow create ifname %s seq %d pri %u unique %d\n",
150 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
, unique
);
151 in_dport
= zd_dpdk_port_find_by_index(in_ifindex
);
153 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
155 "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; in_port %d missing\n",
156 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
,
161 out_dport
= zd_dpdk_port_find_by_index(out_ifindex
);
163 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
165 "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; out_port %d missing\n",
166 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
,
167 unique
, out_ifindex
);
171 /*********************** match items **************************/
172 memset(ð
, 0, sizeof(eth
));
173 memset(ð_mask
, 0, sizeof(eth_mask
));
174 eth
.type
= eth_mask
.type
= htons(RTE_ETHER_TYPE_IPV4
);
175 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_ETH
;
176 items
[item_cnt
].spec
= ð
;
177 items
[item_cnt
].mask
= ð_mask
;
178 items
[item_cnt
].last
= NULL
;
181 memset(&ip
, 0, sizeof(ip
));
182 memset(&ip_mask
, 0, sizeof(ip_mask
));
183 if (filter_bm
& PBR_FILTER_SRC_IP
) {
184 const struct prefix
*src_ip
;
186 src_ip
= dplane_ctx_rule_get_src_ip(ctx
);
187 ip
.hdr
.src_addr
= src_ip
->u
.prefix4
.s_addr
;
188 masklen2ip(src_ip
->prefixlen
, &tmp_mask
);
189 ip_mask
.hdr
.src_addr
= tmp_mask
.s_addr
;
191 if (filter_bm
& PBR_FILTER_DST_IP
) {
192 const struct prefix
*dst_ip
;
194 dst_ip
= dplane_ctx_rule_get_dst_ip(ctx
);
195 ip
.hdr
.dst_addr
= dst_ip
->u
.prefix4
.s_addr
;
196 masklen2ip(dst_ip
->prefixlen
, &tmp_mask
);
197 ip_mask
.hdr
.dst_addr
= tmp_mask
.s_addr
;
199 if (filter_bm
& PBR_FILTER_IP_PROTOCOL
) {
200 ip
.hdr
.next_proto_id
= dplane_ctx_rule_get_ipproto(ctx
);
201 ip_mask
.hdr
.next_proto_id
= UINT8_MAX
;
203 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_IPV4
;
204 items
[item_cnt
].spec
= &ip
;
205 items
[item_cnt
].mask
= &ip_mask
;
206 items
[item_cnt
].last
= NULL
;
209 if ((filter_bm
& (PBR_FILTER_SRC_PORT
| PBR_FILTER_DST_PORT
))) {
210 memset(&udp
, 0, sizeof(udp
));
211 memset(&udp_mask
, 0, sizeof(udp_mask
));
212 if (filter_bm
& PBR_FILTER_SRC_PORT
) {
214 RTE_BE16(dplane_ctx_rule_get_src_port(ctx
));
215 udp_mask
.hdr
.src_port
= UINT16_MAX
;
217 if (filter_bm
& PBR_FILTER_DST_PORT
) {
219 RTE_BE16(dplane_ctx_rule_get_dst_port(ctx
));
220 udp_mask
.hdr
.dst_port
= UINT16_MAX
;
222 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_UDP
;
223 items
[item_cnt
].spec
= &udp
;
224 items
[item_cnt
].mask
= &udp_mask
;
225 items
[item_cnt
].last
= NULL
;
229 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_END
;
231 /*************************** actions *****************************/
232 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_COUNT
;
233 memset(&conf_count
, 0, sizeof(conf_count
));
234 actions
[act_cnt
].conf
= &conf_count
;
237 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_DEC_TTL
;
240 mac
= dplane_ctx_rule_get_smac(ctx
);
241 memcpy(conf_smac
.mac_addr
, mac
, RTE_ETHER_ADDR_LEN
);
242 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
;
243 actions
[act_cnt
].conf
= &conf_smac
;
246 mac
= dplane_ctx_rule_get_dmac(ctx
);
247 memcpy(conf_dmac
.mac_addr
, mac
, RTE_ETHER_ADDR_LEN
);
248 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_SET_MAC_DST
;
249 actions
[act_cnt
].conf
= &conf_dmac
;
252 memset(&conf_port
, 0, sizeof(conf_port
));
253 conf_port
.id
= out_dport
->port_id
;
254 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_PORT_ID
;
255 actions
[act_cnt
].conf
= &conf_port
;
258 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_END
;
260 frr_with_privs (&zserv_privs
) {
261 flow
= rte_flow_create(in_dport
->port_id
, &attrs
, items
,
266 dplane_ctx_rule_set_dp_flow_ptr(ctx
, (intptr_t)flow
);
267 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
269 "PBR dpdk flow 0x%" PRIxPTR
270 " created ifname %s seq %d pri %u unique %d\n",
271 (intptr_t)flow
, dplane_ctx_rule_get_ifname(ctx
),
275 "PBR dpdk flow create failed ifname %s seq %d pri %u unique %d; rc %d\n",
276 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
, unique
,
282 static void zd_dpdk_rule_del(struct zebra_dplane_ctx
*ctx
, const char *ifname
,
283 int in_ifindex
, intptr_t dp_flow_ptr
)
285 struct zd_dpdk_port
*in_dport
;
286 struct rte_flow_error error
;
289 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
291 "PBR dpdk flow delete ifname %s ifindex %d dp_flow 0x%" PRIxPTR
293 ifname
, in_ifindex
, dp_flow_ptr
);
296 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
298 "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
300 ifname
, in_ifindex
, dp_flow_ptr
);
304 dplane_ctx_rule_set_dp_flow_ptr(ctx
, (intptr_t)NULL
);
305 in_dport
= zd_dpdk_port_find_by_index(in_ifindex
);
307 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
309 "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
310 " in port missing\n",
311 ifname
, in_ifindex
, dp_flow_ptr
);
315 frr_with_privs (&zserv_privs
) {
316 rc
= rte_flow_destroy(in_dport
->port_id
,
317 (struct rte_flow
*)dp_flow_ptr
, &error
);
322 "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
324 ifname
, in_ifindex
, dp_flow_ptr
);
328 static void zd_dpdk_rule_update(struct zebra_dplane_ctx
*ctx
)
332 intptr_t dp_flow_ptr
;
334 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
335 zlog_debug("Dplane %s", dplane_op2str(dplane_ctx_get_op(ctx
)));
338 op
= dplane_ctx_get_op(ctx
);
340 case DPLANE_OP_RULE_ADD
:
341 atomic_fetch_add_explicit(&dpdk_stat
->rule_adds
, 1,
342 memory_order_relaxed
);
343 zd_dpdk_rule_add(ctx
);
346 case DPLANE_OP_RULE_UPDATE
:
347 /* delete old rule and install new one */
348 atomic_fetch_add_explicit(&dpdk_stat
->rule_adds
, 1,
349 memory_order_relaxed
);
350 in_ifindex
= dplane_ctx_get_ifindex(ctx
);
351 dp_flow_ptr
= dplane_ctx_rule_get_old_dp_flow_ptr(ctx
);
352 zd_dpdk_rule_del(ctx
, dplane_ctx_rule_get_ifname(ctx
),
353 in_ifindex
, dp_flow_ptr
);
354 zd_dpdk_rule_add(ctx
);
357 case DPLANE_OP_RULE_DELETE
:
358 atomic_fetch_add_explicit(&dpdk_stat
->rule_dels
, 1,
359 memory_order_relaxed
);
360 in_ifindex
= dplane_ctx_get_ifindex(ctx
);
361 dp_flow_ptr
= dplane_ctx_rule_get_dp_flow_ptr(ctx
);
362 zd_dpdk_rule_del(ctx
, dplane_ctx_rule_get_ifname(ctx
),
363 in_ifindex
, dp_flow_ptr
);
367 case DPLANE_OP_ROUTE_INSTALL
:
368 case DPLANE_OP_ROUTE_UPDATE
:
369 case DPLANE_OP_ROUTE_DELETE
:
370 case DPLANE_OP_ROUTE_NOTIFY
:
371 case DPLANE_OP_NH_INSTALL
:
372 case DPLANE_OP_NH_UPDATE
:
373 case DPLANE_OP_NH_DELETE
:
374 case DPLANE_OP_LSP_INSTALL
:
375 case DPLANE_OP_LSP_UPDATE
:
376 case DPLANE_OP_LSP_DELETE
:
377 case DPLANE_OP_LSP_NOTIFY
:
378 case DPLANE_OP_PW_INSTALL
:
379 case DPLANE_OP_PW_UNINSTALL
:
380 case DPLANE_OP_SYS_ROUTE_ADD
:
381 case DPLANE_OP_SYS_ROUTE_DELETE
:
382 case DPLANE_OP_ADDR_INSTALL
:
383 case DPLANE_OP_ADDR_UNINSTALL
:
384 case DPLANE_OP_MAC_INSTALL
:
385 case DPLANE_OP_MAC_DELETE
:
386 case DPLANE_OP_NEIGH_INSTALL
:
387 case DPLANE_OP_NEIGH_UPDATE
:
388 case DPLANE_OP_NEIGH_DELETE
:
389 case DPLANE_OP_VTEP_ADD
:
390 case DPLANE_OP_VTEP_DELETE
:
391 case DPLANE_OP_NEIGH_DISCOVER
:
392 case DPLANE_OP_BR_PORT_UPDATE
:
393 case DPLANE_OP_IPTABLE_ADD
:
394 case DPLANE_OP_IPTABLE_DELETE
:
395 case DPLANE_OP_IPSET_ADD
:
396 case DPLANE_OP_IPSET_DELETE
:
397 case DPLANE_OP_IPSET_ENTRY_ADD
:
398 case DPLANE_OP_IPSET_ENTRY_DELETE
:
399 case DPLANE_OP_NEIGH_IP_INSTALL
:
400 case DPLANE_OP_NEIGH_IP_DELETE
:
401 case DPLANE_OP_NEIGH_TABLE_UPDATE
:
402 case DPLANE_OP_GRE_SET
:
403 case DPLANE_OP_INTF_ADDR_ADD
:
404 case DPLANE_OP_INTF_ADDR_DEL
:
405 case DPLANE_OP_INTF_NETCONFIG
:
406 case DPLANE_OP_INTF_INSTALL
:
407 case DPLANE_OP_INTF_UPDATE
:
408 case DPLANE_OP_INTF_DELETE
:
414 /* DPDK provider callback.
416 static void zd_dpdk_process_update(struct zebra_dplane_ctx
*ctx
)
418 switch (dplane_ctx_get_op(ctx
)) {
420 case DPLANE_OP_RULE_ADD
:
421 case DPLANE_OP_RULE_UPDATE
:
422 case DPLANE_OP_RULE_DELETE
:
423 zd_dpdk_rule_update(ctx
);
426 case DPLANE_OP_ROUTE_INSTALL
:
427 case DPLANE_OP_ROUTE_UPDATE
:
428 case DPLANE_OP_ROUTE_DELETE
:
429 case DPLANE_OP_ROUTE_NOTIFY
:
430 case DPLANE_OP_NH_INSTALL
:
431 case DPLANE_OP_NH_UPDATE
:
432 case DPLANE_OP_NH_DELETE
:
433 case DPLANE_OP_LSP_INSTALL
:
434 case DPLANE_OP_LSP_UPDATE
:
435 case DPLANE_OP_LSP_DELETE
:
436 case DPLANE_OP_LSP_NOTIFY
:
437 case DPLANE_OP_PW_INSTALL
:
438 case DPLANE_OP_PW_UNINSTALL
:
439 case DPLANE_OP_SYS_ROUTE_ADD
:
440 case DPLANE_OP_SYS_ROUTE_DELETE
:
441 case DPLANE_OP_ADDR_INSTALL
:
442 case DPLANE_OP_ADDR_UNINSTALL
:
443 case DPLANE_OP_MAC_INSTALL
:
444 case DPLANE_OP_MAC_DELETE
:
445 case DPLANE_OP_NEIGH_INSTALL
:
446 case DPLANE_OP_NEIGH_UPDATE
:
447 case DPLANE_OP_NEIGH_DELETE
:
448 case DPLANE_OP_VTEP_ADD
:
449 case DPLANE_OP_VTEP_DELETE
:
450 case DPLANE_OP_NEIGH_DISCOVER
:
451 case DPLANE_OP_BR_PORT_UPDATE
:
452 case DPLANE_OP_IPTABLE_ADD
:
453 case DPLANE_OP_IPTABLE_DELETE
:
454 case DPLANE_OP_IPSET_ADD
:
455 case DPLANE_OP_IPSET_DELETE
:
456 case DPLANE_OP_IPSET_ENTRY_ADD
:
457 case DPLANE_OP_IPSET_ENTRY_DELETE
:
458 case DPLANE_OP_NEIGH_IP_INSTALL
:
459 case DPLANE_OP_NEIGH_IP_DELETE
:
460 case DPLANE_OP_NEIGH_TABLE_UPDATE
:
461 case DPLANE_OP_GRE_SET
:
462 case DPLANE_OP_INTF_ADDR_ADD
:
463 case DPLANE_OP_INTF_ADDR_DEL
:
464 case DPLANE_OP_INTF_NETCONFIG
:
465 case DPLANE_OP_INTF_INSTALL
:
466 case DPLANE_OP_INTF_UPDATE
:
467 case DPLANE_OP_INTF_DELETE
:
468 atomic_fetch_add_explicit(&dpdk_stat
->ignored_updates
, 1,
469 memory_order_relaxed
);
476 static int zd_dpdk_process(struct zebra_dplane_provider
*prov
)
478 struct zebra_dplane_ctx
*ctx
;
481 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
482 zlog_debug("processing %s", dplane_provider_get_name(prov
));
484 limit
= dplane_provider_get_work_limit(prov
);
485 for (counter
= 0; counter
< limit
; counter
++) {
486 ctx
= dplane_provider_dequeue_in_ctx(prov
);
490 zd_dpdk_process_update(ctx
);
491 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
492 dplane_provider_enqueue_out_ctx(prov
, ctx
);
498 static void zd_dpdk_port_show_entry(struct zd_dpdk_port
*dport
, struct vty
*vty
,
501 struct rte_eth_dev_info
*dev_info
;
503 dev_info
= &dport
->dev_info
;
505 vty_out(vty
, "DPDK port: %u\n", dport
->port_id
);
506 vty_out(vty
, " Device: %s\n",
507 dev_info
->device
? dev_info
->device
->name
: "-");
508 vty_out(vty
, " Driver: %s\n",
509 dev_info
->driver_name
? dev_info
->driver_name
: "-");
510 vty_out(vty
, " Interface: %s (%d)\n",
511 ifindex2ifname(dev_info
->if_index
, VRF_DEFAULT
),
513 vty_out(vty
, " Switch: %s Domain: %u Port: %u\n",
514 dev_info
->switch_info
.name
,
515 dev_info
->switch_info
.domain_id
,
516 dev_info
->switch_info
.port_id
);
519 vty_out(vty
, "%-4u %-16s %-16s %-16d %s,%u,%u\n",
521 dev_info
->device
? dev_info
->device
->name
: "-",
522 ifindex2ifname(dev_info
->if_index
, VRF_DEFAULT
),
523 dev_info
->if_index
, dev_info
->switch_info
.name
,
524 dev_info
->switch_info
.domain_id
,
525 dev_info
->switch_info
.port_id
);
530 static struct zd_dpdk_port
*zd_dpdk_port_find_by_index(int ifindex
)
533 struct zd_dpdk_port
*dport
;
534 struct rte_eth_dev_info
*dev_info
;
536 for (count
= 0; count
< RTE_MAX_ETHPORTS
; ++count
) {
537 dport
= &dpdk_ctx
->dpdk_ports
[count
];
538 if (!(dport
->flags
& ZD_DPDK_PORT_FLAG_INITED
))
540 dev_info
= &dport
->dev_info
;
541 if (dev_info
->if_index
== (uint32_t)ifindex
)
549 void zd_dpdk_port_show(struct vty
*vty
, uint16_t port_id
, bool uj
, int detail
)
552 struct zd_dpdk_port
*dport
;
554 /* XXX - support for json is yet to be added */
559 vty_out(vty
, "%-4s %-16s %-16s %-16s %s\n", "Port", "Device",
560 "IfName", "IfIndex", "sw,domain,port");
563 for (count
= 0; count
< RTE_MAX_ETHPORTS
; ++count
) {
564 dport
= &dpdk_ctx
->dpdk_ports
[count
];
565 if (dport
->flags
& ZD_DPDK_PORT_FLAG_INITED
)
566 zd_dpdk_port_show_entry(dport
, vty
, detail
);
571 static void zd_dpdk_port_init(void)
573 struct zd_dpdk_port
*dport
;
575 struct rte_eth_dev_info
*dev_info
;
578 struct rte_flow_error error
;
580 /* allocate a list of ports */
581 dpdk_ctx
->dpdk_ports
=
582 XCALLOC(MTYPE_DPDK_PORTS
,
583 sizeof(struct zd_dpdk_port
) * RTE_MAX_ETHPORTS
);
585 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
586 zlog_debug("dpdk port init");
588 RTE_ETH_FOREACH_DEV(port_id
)
590 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
591 zlog_debug("dpdk port init %d", port_id
);
592 dport
= &dpdk_ctx
->dpdk_ports
[count
];
594 dport
->port_id
= port_id
;
595 dport
->flags
|= ZD_DPDK_PORT_FLAG_PROBED
;
596 dev_info
= &dport
->dev_info
;
597 if (rte_eth_dev_info_get(port_id
, dev_info
) < 0) {
598 zlog_warn("failed to get dev info for %u, %s", port_id
,
599 rte_strerror(rte_errno
));
602 dport
->flags
|= ZD_DPDK_PORT_FLAG_INITED
;
603 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
605 "port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u",
607 dev_info
->device
? dev_info
->device
->name
: "-",
608 dev_info
->if_index
, dev_info
->switch_info
.name
,
609 dev_info
->switch_info
.domain_id
,
610 dev_info
->switch_info
.port_id
);
611 if (rte_flow_isolate(port_id
, 1, &error
)) {
612 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
614 "Flow isolate on port %u failed %d\n",
615 port_id
, error
.type
);
617 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
618 zlog_debug("Flow isolate on port %u\n",
621 rc
= rte_eth_dev_start(port_id
);
623 zlog_warn("DPDK port %d start error: %s", port_id
,
627 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
628 zlog_debug("DPDK port %d started in promiscuous mode ",
633 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
634 zlog_debug("no probed ethernet devices");
639 static int zd_dpdk_init(void)
642 static const char *argv
[] = {(char *)"/usr/lib/frr/zebra",
647 frr_with_privs (&zserv_privs
) {
648 rc
= rte_eal_init(ARRAY_SIZE(argv
), argv
);
651 zlog_warn("EAL init failed %s", rte_strerror(rte_errno
));
655 frr_with_privs (&zserv_privs
) {
662 static int zd_dpdk_start(struct zebra_dplane_provider
*prov
)
664 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
665 zlog_debug("%s start", dplane_provider_get_name(prov
));
667 return zd_dpdk_init();
671 static int zd_dpdk_finish(struct zebra_dplane_provider
*prov
, bool early
)
676 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
677 zlog_debug("%s early finish",
678 dplane_provider_get_name(prov
));
683 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
684 zlog_debug("%s finish", dplane_provider_get_name(prov
));
687 frr_with_privs (&zserv_privs
) {
688 rc
= rte_eal_cleanup();
691 zlog_warn("EAL cleanup failed %s", rte_strerror(rte_errno
));
697 static int zd_dpdk_plugin_init(struct thread_master
*tm
)
701 ret
= dplane_provider_register(
702 plugin_name
, DPLANE_PRIO_KERNEL
, DPLANE_PROV_FLAGS_DEFAULT
,
703 zd_dpdk_start
, zd_dpdk_process
, zd_dpdk_finish
, dpdk_ctx
, NULL
);
705 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
706 zlog_debug("%s register status %d", plugin_name
, ret
);
712 static int zd_dpdk_module_init(void)
714 hook_register(frr_late_init
, zd_dpdk_plugin_init
);
718 FRR_MODULE_SETUP(.name
= "dplane_dpdk", .version
= "0.0.1",
719 .description
= "Data plane plugin using dpdk for hw offload",
720 .init
= zd_dpdk_module_init
);