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 static struct zd_dpdk_ctx dpdk_ctx_buf
, *dpdk_ctx
= &dpdk_ctx_buf
;
39 #define dpdk_stat (&dpdk_ctx->stats)
41 static struct zd_dpdk_port
*zd_dpdk_port_find_by_index(int ifindex
);
43 DEFINE_MTYPE_STATIC(ZEBRA
, DPDK_PORTS
, "ZD DPDK port database");
45 void zd_dpdk_stat_show(struct vty
*vty
)
49 vty_out(vty
, "%30s\n%30s\n", "Dataplane DPDK counters",
50 "=======================");
52 #define ZD_DPDK_SHOW_COUNTER(label, counter) \
55 atomic_load_explicit(&counter, memory_order_relaxed); \
56 vty_out(vty, "%28s: %u\n", (label), (tmp_cnt)); \
59 ZD_DPDK_SHOW_COUNTER("PBR rule adds", dpdk_stat
->rule_adds
);
60 ZD_DPDK_SHOW_COUNTER("PBR rule dels", dpdk_stat
->rule_dels
);
61 ZD_DPDK_SHOW_COUNTER("Ignored updates", dpdk_stat
->ignored_updates
);
65 static void zd_dpdk_flow_stat_show(struct vty
*vty
, int in_ifindex
,
68 struct rte_flow_action_count count
= {.shared
= 0, .id
= 0};
69 const struct rte_flow_action actions
[] = {
71 .type
= RTE_FLOW_ACTION_TYPE_COUNT
,
75 .type
= RTE_FLOW_ACTION_TYPE_END
,
79 struct zd_dpdk_port
*in_dport
;
80 struct rte_flow_query_count query
;
81 struct rte_flow_error error
;
84 in_dport
= zd_dpdk_port_find_by_index(in_ifindex
);
86 vty_out(vty
, "PBR dpdk flow query failed; in_port %d missing\n",
90 memset(&query
, 0, sizeof(query
));
91 rc
= rte_flow_query(in_dport
->port_id
, (struct rte_flow
*)dp_flow_ptr
,
92 actions
, &query
, &error
);
95 "PBR dpdk flow query failed; in_ifindex %d rc %d\n",
96 in_ifindex
, error
.type
);
99 hits
= (query
.hits_set
) ? query
.hits
: 0;
100 bytes
= (query
.bytes_set
) ? query
.bytes
: 0;
101 vty_out(vty
, " DPDK stats: packets %" PRIu64
" bytes %" PRIu64
"\n",
106 static int zd_dpdk_pbr_show_rules_walkcb(struct hash_bucket
*bucket
, void *arg
)
108 struct zebra_pbr_rule
*rule
= (struct zebra_pbr_rule
*)bucket
->data
;
109 struct vty
*vty
= (struct vty
*)arg
;
111 struct interface
*ifp
= NULL
;
112 struct zebra_pbr_action
*zaction
= &rule
->action
;
114 zebra_pbr_show_rule_unit(rule
, vty
);
115 if (zaction
->dp_flow_ptr
) {
116 vrf
= vrf_lookup_by_id(rule
->vrf_id
);
118 ifp
= if_lookup_by_name_vrf(rule
->ifname
, vrf
);
121 zd_dpdk_flow_stat_show(vty
, ifp
->ifindex
,
122 zaction
->dp_flow_ptr
);
124 return HASHWALK_CONTINUE
;
128 void zd_dpdk_pbr_flows_show(struct vty
*vty
)
130 hash_walk(zrouter
.rules_hash
, zd_dpdk_pbr_show_rules_walkcb
, vty
);
134 static void zd_dpdk_rule_add(struct zebra_dplane_ctx
*ctx
)
136 static struct rte_flow_attr attrs
= {.ingress
= 1, .transfer
= 1};
137 uint32_t filter_bm
= dplane_ctx_rule_get_filter_bm(ctx
);
138 int in_ifindex
= dplane_ctx_get_ifindex(ctx
);
139 int out_ifindex
= dplane_ctx_rule_get_out_ifindex(ctx
);
140 struct rte_flow_item_eth eth
, eth_mask
;
141 struct rte_flow_item_ipv4 ip
, ip_mask
;
142 struct rte_flow_item_udp udp
, udp_mask
;
143 struct rte_flow_action_count conf_count
;
144 struct rte_flow_action_set_mac conf_smac
, conf_dmac
;
145 struct rte_flow_action_port_id conf_port
;
146 struct rte_flow_item items
[ZD_PBR_PATTERN_MAX
];
147 struct rte_flow_action actions
[ZD_PBR_ACTION_MAX
];
150 struct in_addr tmp_mask
;
151 const struct ethaddr
*mac
;
152 struct rte_flow
*flow
;
153 struct rte_flow_error error
;
154 struct zd_dpdk_port
*in_dport
;
155 struct zd_dpdk_port
*out_dport
;
156 uint32_t pri
= dplane_ctx_rule_get_priority(ctx
);
157 int seq
= dplane_ctx_rule_get_seq(ctx
);
158 int unique
= dplane_ctx_rule_get_unique(ctx
);
160 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
162 "PBR dpdk flow create ifname %s seq %d pri %u unique %d\n",
163 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
, unique
);
164 in_dport
= zd_dpdk_port_find_by_index(in_ifindex
);
166 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
168 "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; in_port %d missing\n",
169 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
,
174 out_dport
= zd_dpdk_port_find_by_index(out_ifindex
);
176 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
178 "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; out_port %d missing\n",
179 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
,
180 unique
, out_ifindex
);
184 /*********************** match items **************************/
185 memset(ð
, 0, sizeof(eth
));
186 memset(ð_mask
, 0, sizeof(eth_mask
));
187 eth
.type
= eth_mask
.type
= htons(RTE_ETHER_TYPE_IPV4
);
188 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_ETH
;
189 items
[item_cnt
].spec
= ð
;
190 items
[item_cnt
].mask
= ð_mask
;
191 items
[item_cnt
].last
= NULL
;
194 memset(&ip
, 0, sizeof(ip
));
195 memset(&ip_mask
, 0, sizeof(ip_mask
));
196 if (filter_bm
& PBR_FILTER_SRC_IP
) {
197 const struct prefix
*src_ip
;
199 src_ip
= dplane_ctx_rule_get_src_ip(ctx
);
200 ip
.hdr
.src_addr
= src_ip
->u
.prefix4
.s_addr
;
201 masklen2ip(src_ip
->prefixlen
, &tmp_mask
);
202 ip_mask
.hdr
.src_addr
= tmp_mask
.s_addr
;
204 if (filter_bm
& PBR_FILTER_DST_IP
) {
205 const struct prefix
*dst_ip
;
207 dst_ip
= dplane_ctx_rule_get_dst_ip(ctx
);
208 ip
.hdr
.dst_addr
= dst_ip
->u
.prefix4
.s_addr
;
209 masklen2ip(dst_ip
->prefixlen
, &tmp_mask
);
210 ip_mask
.hdr
.dst_addr
= tmp_mask
.s_addr
;
212 if (filter_bm
& PBR_FILTER_IP_PROTOCOL
) {
213 ip
.hdr
.next_proto_id
= dplane_ctx_rule_get_ipproto(ctx
);
214 ip_mask
.hdr
.next_proto_id
= UINT8_MAX
;
216 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_IPV4
;
217 items
[item_cnt
].spec
= &ip
;
218 items
[item_cnt
].mask
= &ip_mask
;
219 items
[item_cnt
].last
= NULL
;
222 if ((filter_bm
& (PBR_FILTER_SRC_PORT
| PBR_FILTER_DST_PORT
))) {
223 memset(&udp
, 0, sizeof(udp
));
224 memset(&udp_mask
, 0, sizeof(udp_mask
));
225 if (filter_bm
& PBR_FILTER_SRC_PORT
) {
227 RTE_BE16(dplane_ctx_rule_get_src_port(ctx
));
228 udp_mask
.hdr
.src_port
= UINT16_MAX
;
230 if (filter_bm
& PBR_FILTER_DST_PORT
) {
232 RTE_BE16(dplane_ctx_rule_get_dst_port(ctx
));
233 udp_mask
.hdr
.dst_port
= UINT16_MAX
;
235 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_UDP
;
236 items
[item_cnt
].spec
= &udp
;
237 items
[item_cnt
].mask
= &udp_mask
;
238 items
[item_cnt
].last
= NULL
;
242 items
[item_cnt
].type
= RTE_FLOW_ITEM_TYPE_END
;
244 /*************************** actions *****************************/
245 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_COUNT
;
246 memset(&conf_count
, 0, sizeof(conf_count
));
247 actions
[act_cnt
].conf
= &conf_count
;
250 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_DEC_TTL
;
253 mac
= dplane_ctx_rule_get_smac(ctx
);
254 memcpy(conf_smac
.mac_addr
, mac
, RTE_ETHER_ADDR_LEN
);
255 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
;
256 actions
[act_cnt
].conf
= &conf_smac
;
259 mac
= dplane_ctx_rule_get_dmac(ctx
);
260 memcpy(conf_dmac
.mac_addr
, mac
, RTE_ETHER_ADDR_LEN
);
261 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_SET_MAC_DST
;
262 actions
[act_cnt
].conf
= &conf_dmac
;
265 memset(&conf_port
, 0, sizeof(conf_port
));
266 conf_port
.id
= out_dport
->port_id
;
267 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_PORT_ID
;
268 actions
[act_cnt
].conf
= &conf_port
;
271 actions
[act_cnt
].type
= RTE_FLOW_ACTION_TYPE_END
;
273 frr_with_privs (&zserv_privs
) {
274 flow
= rte_flow_create(in_dport
->port_id
, &attrs
, items
,
279 dplane_ctx_rule_set_dp_flow_ptr(ctx
, (intptr_t)flow
);
280 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
282 "PBR dpdk flow 0x%" PRIxPTR
283 " created ifname %s seq %d pri %u unique %d\n",
284 (intptr_t)flow
, dplane_ctx_rule_get_ifname(ctx
),
288 "PBR dpdk flow create failed ifname %s seq %d pri %u unique %d; rc %d\n",
289 dplane_ctx_rule_get_ifname(ctx
), seq
, pri
, unique
,
295 static void zd_dpdk_rule_del(struct zebra_dplane_ctx
*ctx
, const char *ifname
,
296 int in_ifindex
, intptr_t dp_flow_ptr
)
298 struct zd_dpdk_port
*in_dport
;
299 struct rte_flow_error error
;
302 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
304 "PBR dpdk flow delete ifname %s ifindex %d dp_flow 0x%" PRIxPTR
306 ifname
, in_ifindex
, dp_flow_ptr
);
309 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
311 "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
313 ifname
, in_ifindex
, dp_flow_ptr
);
317 dplane_ctx_rule_set_dp_flow_ptr(ctx
, (intptr_t)NULL
);
318 in_dport
= zd_dpdk_port_find_by_index(in_ifindex
);
320 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
322 "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
323 " in port missing\n",
324 ifname
, in_ifindex
, dp_flow_ptr
);
328 frr_with_privs (&zserv_privs
) {
329 rc
= rte_flow_destroy(in_dport
->port_id
,
330 (struct rte_flow
*)dp_flow_ptr
, &error
);
335 "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
337 ifname
, in_ifindex
, dp_flow_ptr
);
341 static void zd_dpdk_rule_update(struct zebra_dplane_ctx
*ctx
)
345 intptr_t dp_flow_ptr
;
347 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
348 zlog_debug("Dplane %s", dplane_op2str(dplane_ctx_get_op(ctx
)));
351 op
= dplane_ctx_get_op(ctx
);
353 case DPLANE_OP_RULE_ADD
:
354 atomic_fetch_add_explicit(&dpdk_stat
->rule_adds
, 1,
355 memory_order_relaxed
);
356 zd_dpdk_rule_add(ctx
);
359 case DPLANE_OP_RULE_UPDATE
:
360 /* delete old rule and install new one */
361 atomic_fetch_add_explicit(&dpdk_stat
->rule_adds
, 1,
362 memory_order_relaxed
);
363 in_ifindex
= dplane_ctx_get_ifindex(ctx
);
364 dp_flow_ptr
= dplane_ctx_rule_get_old_dp_flow_ptr(ctx
);
365 zd_dpdk_rule_del(ctx
, dplane_ctx_rule_get_ifname(ctx
),
366 in_ifindex
, dp_flow_ptr
);
367 zd_dpdk_rule_add(ctx
);
370 case DPLANE_OP_RULE_DELETE
:
371 atomic_fetch_add_explicit(&dpdk_stat
->rule_dels
, 1,
372 memory_order_relaxed
);
373 in_ifindex
= dplane_ctx_get_ifindex(ctx
);
374 dp_flow_ptr
= dplane_ctx_rule_get_dp_flow_ptr(ctx
);
375 zd_dpdk_rule_del(ctx
, dplane_ctx_rule_get_ifname(ctx
),
376 in_ifindex
, dp_flow_ptr
);
380 case DPLANE_OP_ROUTE_INSTALL
:
381 case DPLANE_OP_ROUTE_UPDATE
:
382 case DPLANE_OP_ROUTE_DELETE
:
383 case DPLANE_OP_ROUTE_NOTIFY
:
384 case DPLANE_OP_NH_INSTALL
:
385 case DPLANE_OP_NH_UPDATE
:
386 case DPLANE_OP_NH_DELETE
:
387 case DPLANE_OP_LSP_INSTALL
:
388 case DPLANE_OP_LSP_UPDATE
:
389 case DPLANE_OP_LSP_DELETE
:
390 case DPLANE_OP_LSP_NOTIFY
:
391 case DPLANE_OP_PW_INSTALL
:
392 case DPLANE_OP_PW_UNINSTALL
:
393 case DPLANE_OP_SYS_ROUTE_ADD
:
394 case DPLANE_OP_SYS_ROUTE_DELETE
:
395 case DPLANE_OP_ADDR_INSTALL
:
396 case DPLANE_OP_ADDR_UNINSTALL
:
397 case DPLANE_OP_MAC_INSTALL
:
398 case DPLANE_OP_MAC_DELETE
:
399 case DPLANE_OP_NEIGH_INSTALL
:
400 case DPLANE_OP_NEIGH_UPDATE
:
401 case DPLANE_OP_NEIGH_DELETE
:
402 case DPLANE_OP_VTEP_ADD
:
403 case DPLANE_OP_VTEP_DELETE
:
404 case DPLANE_OP_NEIGH_DISCOVER
:
405 case DPLANE_OP_BR_PORT_UPDATE
:
406 case DPLANE_OP_IPTABLE_ADD
:
407 case DPLANE_OP_IPTABLE_DELETE
:
408 case DPLANE_OP_IPSET_ADD
:
409 case DPLANE_OP_IPSET_DELETE
:
410 case DPLANE_OP_IPSET_ENTRY_ADD
:
411 case DPLANE_OP_IPSET_ENTRY_DELETE
:
412 case DPLANE_OP_NEIGH_IP_INSTALL
:
413 case DPLANE_OP_NEIGH_IP_DELETE
:
414 case DPLANE_OP_NEIGH_TABLE_UPDATE
:
415 case DPLANE_OP_GRE_SET
:
416 case DPLANE_OP_INTF_ADDR_ADD
:
417 case DPLANE_OP_INTF_ADDR_DEL
:
418 case DPLANE_OP_INTF_NETCONFIG
:
419 case DPLANE_OP_INTF_INSTALL
:
420 case DPLANE_OP_INTF_UPDATE
:
421 case DPLANE_OP_INTF_DELETE
:
427 /* DPDK provider callback.
429 static void zd_dpdk_process_update(struct zebra_dplane_ctx
*ctx
)
431 switch (dplane_ctx_get_op(ctx
)) {
433 case DPLANE_OP_RULE_ADD
:
434 case DPLANE_OP_RULE_UPDATE
:
435 case DPLANE_OP_RULE_DELETE
:
436 zd_dpdk_rule_update(ctx
);
439 case DPLANE_OP_ROUTE_INSTALL
:
440 case DPLANE_OP_ROUTE_UPDATE
:
441 case DPLANE_OP_ROUTE_DELETE
:
442 case DPLANE_OP_ROUTE_NOTIFY
:
443 case DPLANE_OP_NH_INSTALL
:
444 case DPLANE_OP_NH_UPDATE
:
445 case DPLANE_OP_NH_DELETE
:
446 case DPLANE_OP_LSP_INSTALL
:
447 case DPLANE_OP_LSP_UPDATE
:
448 case DPLANE_OP_LSP_DELETE
:
449 case DPLANE_OP_LSP_NOTIFY
:
450 case DPLANE_OP_PW_INSTALL
:
451 case DPLANE_OP_PW_UNINSTALL
:
452 case DPLANE_OP_SYS_ROUTE_ADD
:
453 case DPLANE_OP_SYS_ROUTE_DELETE
:
454 case DPLANE_OP_ADDR_INSTALL
:
455 case DPLANE_OP_ADDR_UNINSTALL
:
456 case DPLANE_OP_MAC_INSTALL
:
457 case DPLANE_OP_MAC_DELETE
:
458 case DPLANE_OP_NEIGH_INSTALL
:
459 case DPLANE_OP_NEIGH_UPDATE
:
460 case DPLANE_OP_NEIGH_DELETE
:
461 case DPLANE_OP_VTEP_ADD
:
462 case DPLANE_OP_VTEP_DELETE
:
463 case DPLANE_OP_NEIGH_DISCOVER
:
464 case DPLANE_OP_BR_PORT_UPDATE
:
465 case DPLANE_OP_IPTABLE_ADD
:
466 case DPLANE_OP_IPTABLE_DELETE
:
467 case DPLANE_OP_IPSET_ADD
:
468 case DPLANE_OP_IPSET_DELETE
:
469 case DPLANE_OP_IPSET_ENTRY_ADD
:
470 case DPLANE_OP_IPSET_ENTRY_DELETE
:
471 case DPLANE_OP_NEIGH_IP_INSTALL
:
472 case DPLANE_OP_NEIGH_IP_DELETE
:
473 case DPLANE_OP_NEIGH_TABLE_UPDATE
:
474 case DPLANE_OP_GRE_SET
:
475 case DPLANE_OP_INTF_ADDR_ADD
:
476 case DPLANE_OP_INTF_ADDR_DEL
:
477 case DPLANE_OP_INTF_NETCONFIG
:
478 case DPLANE_OP_INTF_INSTALL
:
479 case DPLANE_OP_INTF_UPDATE
:
480 case DPLANE_OP_INTF_DELETE
:
481 atomic_fetch_add_explicit(&dpdk_stat
->ignored_updates
, 1,
482 memory_order_relaxed
);
489 static int zd_dpdk_process(struct zebra_dplane_provider
*prov
)
491 struct zebra_dplane_ctx
*ctx
;
494 if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL
)
495 zlog_debug("processing %s", dplane_provider_get_name(prov
));
497 limit
= dplane_provider_get_work_limit(prov
);
498 for (counter
= 0; counter
< limit
; counter
++) {
499 ctx
= dplane_provider_dequeue_in_ctx(prov
);
503 zd_dpdk_process_update(ctx
);
504 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
505 dplane_provider_enqueue_out_ctx(prov
, ctx
);
511 static void zd_dpdk_port_show_entry(struct zd_dpdk_port
*dport
, struct vty
*vty
,
514 struct rte_eth_dev_info
*dev_info
;
516 dev_info
= &dport
->dev_info
;
518 vty_out(vty
, "DPDK port: %u\n", dport
->port_id
);
519 vty_out(vty
, " Device: %s\n",
520 dev_info
->device
? dev_info
->device
->name
: "-");
521 vty_out(vty
, " Driver: %s\n",
522 dev_info
->driver_name
? dev_info
->driver_name
: "-");
523 vty_out(vty
, " Interface: %s (%d)\n",
524 ifindex2ifname(dev_info
->if_index
, VRF_DEFAULT
),
526 vty_out(vty
, " Switch: %s Domain: %u Port: %u\n",
527 dev_info
->switch_info
.name
,
528 dev_info
->switch_info
.domain_id
,
529 dev_info
->switch_info
.port_id
);
532 vty_out(vty
, "%-4u %-16s %-16s %-16d %s,%u,%u\n",
534 dev_info
->device
? dev_info
->device
->name
: "-",
535 ifindex2ifname(dev_info
->if_index
, VRF_DEFAULT
),
536 dev_info
->if_index
, dev_info
->switch_info
.name
,
537 dev_info
->switch_info
.domain_id
,
538 dev_info
->switch_info
.port_id
);
543 static struct zd_dpdk_port
*zd_dpdk_port_find_by_index(int ifindex
)
546 struct zd_dpdk_port
*dport
;
547 struct rte_eth_dev_info
*dev_info
;
549 for (count
= 0; count
< RTE_MAX_ETHPORTS
; ++count
) {
550 dport
= &dpdk_ctx
->dpdk_ports
[count
];
551 if (!(dport
->flags
& ZD_DPDK_PORT_FLAG_INITED
))
553 dev_info
= &dport
->dev_info
;
554 if (dev_info
->if_index
== (uint32_t)ifindex
)
562 void zd_dpdk_port_show(struct vty
*vty
, uint16_t port_id
, bool uj
, int detail
)
565 struct zd_dpdk_port
*dport
;
567 /* XXX - support for json is yet to be added */
572 vty_out(vty
, "%-4s %-16s %-16s %-16s %s\n", "Port", "Device",
573 "IfName", "IfIndex", "sw,domain,port");
576 for (count
= 0; count
< RTE_MAX_ETHPORTS
; ++count
) {
577 dport
= &dpdk_ctx
->dpdk_ports
[count
];
578 if (dport
->flags
& ZD_DPDK_PORT_FLAG_INITED
)
579 zd_dpdk_port_show_entry(dport
, vty
, detail
);
584 static void zd_dpdk_port_init(void)
586 struct zd_dpdk_port
*dport
;
588 struct rte_eth_dev_info
*dev_info
;
591 struct rte_flow_error error
;
593 /* allocate a list of ports */
594 dpdk_ctx
->dpdk_ports
=
595 XCALLOC(MTYPE_DPDK_PORTS
,
596 sizeof(struct zd_dpdk_port
) * RTE_MAX_ETHPORTS
);
598 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
599 zlog_debug("dpdk port init");
601 RTE_ETH_FOREACH_DEV(port_id
)
603 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
604 zlog_debug("dpdk port init %d", port_id
);
605 dport
= &dpdk_ctx
->dpdk_ports
[count
];
607 dport
->port_id
= port_id
;
608 dport
->flags
|= ZD_DPDK_PORT_FLAG_PROBED
;
609 dev_info
= &dport
->dev_info
;
610 if (rte_eth_dev_info_get(port_id
, dev_info
) < 0) {
611 zlog_warn("failed to get dev info for %u, %s", port_id
,
612 rte_strerror(rte_errno
));
615 dport
->flags
|= ZD_DPDK_PORT_FLAG_INITED
;
616 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
618 "port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u",
620 dev_info
->device
? dev_info
->device
->name
: "-",
621 dev_info
->if_index
, dev_info
->switch_info
.name
,
622 dev_info
->switch_info
.domain_id
,
623 dev_info
->switch_info
.port_id
);
624 if (rte_flow_isolate(port_id
, 1, &error
)) {
625 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
627 "Flow isolate on port %u failed %d\n",
628 port_id
, error
.type
);
630 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
631 zlog_debug("Flow isolate on port %u\n",
634 rc
= rte_eth_dev_start(port_id
);
636 zlog_warn("DPDK port %d start error: %s", port_id
,
640 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
641 zlog_debug("DPDK port %d started in promiscuous mode ",
646 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
647 zlog_debug("no probed ethernet devices");
652 static int zd_dpdk_init(void)
655 static const char *argv
[] = {(char *)"/usr/lib/frr/zebra",
660 frr_with_privs (&zserv_privs
) {
661 rc
= rte_eal_init(ARRAY_SIZE(argv
), argv
);
664 zlog_warn("EAL init failed %s", rte_strerror(rte_errno
));
668 frr_with_privs (&zserv_privs
) {
675 static int zd_dpdk_start(struct zebra_dplane_provider
*prov
)
677 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
678 zlog_debug("%s start", dplane_provider_get_name(prov
));
680 return zd_dpdk_init();
684 static int zd_dpdk_finish(struct zebra_dplane_provider
*prov
, bool early
)
689 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
690 zlog_debug("%s early finish",
691 dplane_provider_get_name(prov
));
696 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
697 zlog_debug("%s finish", dplane_provider_get_name(prov
));
700 frr_with_privs (&zserv_privs
) {
701 rc
= rte_eal_cleanup();
704 zlog_warn("EAL cleanup failed %s", rte_strerror(rte_errno
));
710 static int zd_dpdk_plugin_init(struct thread_master
*tm
)
714 ret
= dplane_provider_register(
715 plugin_name
, DPLANE_PRIO_KERNEL
, DPLANE_PROV_FLAGS_DEFAULT
,
716 zd_dpdk_start
, zd_dpdk_process
, zd_dpdk_finish
, dpdk_ctx
, NULL
);
718 if (IS_ZEBRA_DEBUG_DPLANE_DPDK
)
719 zlog_debug("%s register status %d", plugin_name
, ret
);
725 static int zd_dpdk_module_init(void)
727 hook_register(frr_late_init
, zd_dpdk_plugin_init
);
731 FRR_MODULE_SETUP(.name
= "dplane_dpdk", .version
= "0.0.1",
732 .description
= "Data plane plugin using dpdk for hw offload",
733 .init
= zd_dpdk_module_init
);