+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Zebra dataplane plugin for DPDK based hw offload
*
* Copyright (C) 2021 Nvidia
* Anuradha Karuppiah
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
static const char *plugin_name = "zebra_dplane_dpdk";
-extern struct zebra_privs_t zserv_privs;
-
static struct zd_dpdk_ctx dpdk_ctx_buf, *dpdk_ctx = &dpdk_ctx_buf;
#define dpdk_stat (&dpdk_ctx->stats)
+static struct zd_dpdk_port *zd_dpdk_port_find_by_index(int ifindex);
+
+DEFINE_MTYPE_STATIC(ZEBRA, DPDK_PORTS, "ZD DPDK port database");
void zd_dpdk_stat_show(struct vty *vty)
{
tmp_cnt = \
atomic_load_explicit(&counter, memory_order_relaxed); \
vty_out(vty, "%28s: %u\n", (label), (tmp_cnt)); \
- } while (0);
+ } while (0)
ZD_DPDK_SHOW_COUNTER("PBR rule adds", dpdk_stat->rule_adds);
ZD_DPDK_SHOW_COUNTER("PBR rule dels", dpdk_stat->rule_dels);
}
+static void zd_dpdk_flow_stat_show(struct vty *vty, int in_ifindex,
+ intptr_t dp_flow_ptr)
+{
+ struct rte_flow_action_count count = {.shared = 0, .id = 0};
+ const struct rte_flow_action actions[] = {
+ {
+ .type = RTE_FLOW_ACTION_TYPE_COUNT,
+ .conf = &count,
+ },
+ {
+ .type = RTE_FLOW_ACTION_TYPE_END,
+ },
+ };
+ int rc;
+ struct zd_dpdk_port *in_dport;
+ struct rte_flow_query_count query;
+ struct rte_flow_error error;
+ uint64_t hits, bytes;
+
+ in_dport = zd_dpdk_port_find_by_index(in_ifindex);
+ if (!in_dport) {
+ vty_out(vty, "PBR dpdk flow query failed; in_port %d missing\n",
+ in_ifindex);
+ return;
+ }
+ memset(&query, 0, sizeof(query));
+ rc = rte_flow_query(in_dport->port_id, (struct rte_flow *)dp_flow_ptr,
+ actions, &query, &error);
+ if (rc) {
+ vty_out(vty,
+ "PBR dpdk flow query failed; in_ifindex %d rc %d\n",
+ in_ifindex, error.type);
+ return;
+ }
+ hits = (query.hits_set) ? query.hits : 0;
+ bytes = (query.bytes_set) ? query.bytes : 0;
+ vty_out(vty, " DPDK stats: packets %" PRIu64 " bytes %" PRIu64 "\n",
+ hits, bytes);
+}
+
+
+static int zd_dpdk_pbr_show_rules_walkcb(struct hash_bucket *bucket, void *arg)
+{
+ struct zebra_pbr_rule *rule = (struct zebra_pbr_rule *)bucket->data;
+ struct vty *vty = (struct vty *)arg;
+ struct vrf *vrf;
+ struct interface *ifp = NULL;
+ struct zebra_pbr_action *zaction = &rule->action;
+
+ zebra_pbr_show_rule_unit(rule, vty);
+ if (zaction->dp_flow_ptr) {
+ vrf = vrf_lookup_by_id(rule->vrf_id);
+ if (vrf)
+ ifp = if_lookup_by_name_vrf(rule->ifname, vrf);
+
+ if (ifp)
+ zd_dpdk_flow_stat_show(vty, ifp->ifindex,
+ zaction->dp_flow_ptr);
+ }
+ return HASHWALK_CONTINUE;
+}
+
+
+void zd_dpdk_pbr_flows_show(struct vty *vty)
+{
+ hash_walk(zrouter.rules_hash, zd_dpdk_pbr_show_rules_walkcb, vty);
+}
+
+
static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
{
- /* XXX - place holder */
+ static struct rte_flow_attr attrs = {.ingress = 1, .transfer = 1};
+ uint32_t filter_bm = dplane_ctx_rule_get_filter_bm(ctx);
+ int in_ifindex = dplane_ctx_get_ifindex(ctx);
+ int out_ifindex = dplane_ctx_rule_get_out_ifindex(ctx);
+ struct rte_flow_item_eth eth, eth_mask;
+ struct rte_flow_item_ipv4 ip, ip_mask;
+ struct rte_flow_item_udp udp, udp_mask;
+ struct rte_flow_action_count conf_count;
+ struct rte_flow_action_set_mac conf_smac, conf_dmac;
+ struct rte_flow_action_port_id conf_port;
+ struct rte_flow_item items[ZD_PBR_PATTERN_MAX];
+ struct rte_flow_action actions[ZD_PBR_ACTION_MAX];
+ int item_cnt = 0;
+ int act_cnt = 0;
+ struct in_addr tmp_mask;
+ const struct ethaddr *mac;
+ struct rte_flow *flow;
+ struct rte_flow_error error;
+ struct zd_dpdk_port *in_dport;
+ struct zd_dpdk_port *out_dport;
+ uint32_t pri = dplane_ctx_rule_get_priority(ctx);
+ int seq = dplane_ctx_rule_get_seq(ctx);
+ int unique = dplane_ctx_rule_get_unique(ctx);
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow create ifname %s seq %d pri %u unique %d\n",
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique);
+ in_dport = zd_dpdk_port_find_by_index(in_ifindex);
+ if (!in_dport) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; in_port %d missing\n",
+ dplane_ctx_rule_get_ifname(ctx), seq, pri,
+ unique, in_ifindex);
+ return;
+ }
+
+ out_dport = zd_dpdk_port_find_by_index(out_ifindex);
+ if (!out_dport) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; out_port %d missing\n",
+ dplane_ctx_rule_get_ifname(ctx), seq, pri,
+ unique, out_ifindex);
+ return;
+ }
+
+ /*********************** match items **************************/
+ memset(ð, 0, sizeof(eth));
+ memset(ð_mask, 0, sizeof(eth_mask));
+ eth.type = eth_mask.type = htons(RTE_ETHER_TYPE_IPV4);
+ items[item_cnt].type = RTE_FLOW_ITEM_TYPE_ETH;
+ items[item_cnt].spec = ð
+ items[item_cnt].mask = ð_mask;
+ items[item_cnt].last = NULL;
+ ++item_cnt;
+
+ memset(&ip, 0, sizeof(ip));
+ memset(&ip_mask, 0, sizeof(ip_mask));
+ if (filter_bm & PBR_FILTER_SRC_IP) {
+ const struct prefix *src_ip;
+
+ src_ip = dplane_ctx_rule_get_src_ip(ctx);
+ ip.hdr.src_addr = src_ip->u.prefix4.s_addr;
+ masklen2ip(src_ip->prefixlen, &tmp_mask);
+ ip_mask.hdr.src_addr = tmp_mask.s_addr;
+ }
+ if (filter_bm & PBR_FILTER_DST_IP) {
+ const struct prefix *dst_ip;
+
+ dst_ip = dplane_ctx_rule_get_dst_ip(ctx);
+ ip.hdr.dst_addr = dst_ip->u.prefix4.s_addr;
+ masklen2ip(dst_ip->prefixlen, &tmp_mask);
+ ip_mask.hdr.dst_addr = tmp_mask.s_addr;
+ }
+ if (filter_bm & PBR_FILTER_IP_PROTOCOL) {
+ ip.hdr.next_proto_id = dplane_ctx_rule_get_ipproto(ctx);
+ ip_mask.hdr.next_proto_id = UINT8_MAX;
+ }
+ items[item_cnt].type = RTE_FLOW_ITEM_TYPE_IPV4;
+ items[item_cnt].spec = &ip;
+ items[item_cnt].mask = &ip_mask;
+ items[item_cnt].last = NULL;
+ ++item_cnt;
+
+ if ((filter_bm & (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) {
+ memset(&udp, 0, sizeof(udp));
+ memset(&udp_mask, 0, sizeof(udp_mask));
+ if (filter_bm & PBR_FILTER_SRC_PORT) {
+ udp.hdr.src_port =
+ RTE_BE16(dplane_ctx_rule_get_src_port(ctx));
+ udp_mask.hdr.src_port = UINT16_MAX;
+ }
+ if (filter_bm & PBR_FILTER_DST_PORT) {
+ udp.hdr.dst_port =
+ RTE_BE16(dplane_ctx_rule_get_dst_port(ctx));
+ udp_mask.hdr.dst_port = UINT16_MAX;
+ }
+ items[item_cnt].type = RTE_FLOW_ITEM_TYPE_UDP;
+ items[item_cnt].spec = &udp;
+ items[item_cnt].mask = &udp_mask;
+ items[item_cnt].last = NULL;
+ ++item_cnt;
+ }
+
+ items[item_cnt].type = RTE_FLOW_ITEM_TYPE_END;
+
+ /*************************** actions *****************************/
+ actions[act_cnt].type = RTE_FLOW_ACTION_TYPE_COUNT;
+ memset(&conf_count, 0, sizeof(conf_count));
+ actions[act_cnt].conf = &conf_count;
+ ++act_cnt;
+
+ actions[act_cnt].type = RTE_FLOW_ACTION_TYPE_DEC_TTL;
+ ++act_cnt;
+
+ mac = dplane_ctx_rule_get_smac(ctx);
+ memcpy(conf_smac.mac_addr, mac, RTE_ETHER_ADDR_LEN);
+ actions[act_cnt].type = RTE_FLOW_ACTION_TYPE_SET_MAC_SRC;
+ actions[act_cnt].conf = &conf_smac;
+ ++act_cnt;
+
+ mac = dplane_ctx_rule_get_dmac(ctx);
+ memcpy(conf_dmac.mac_addr, mac, RTE_ETHER_ADDR_LEN);
+ actions[act_cnt].type = RTE_FLOW_ACTION_TYPE_SET_MAC_DST;
+ actions[act_cnt].conf = &conf_dmac;
+ ++act_cnt;
+
+ memset(&conf_port, 0, sizeof(conf_port));
+ conf_port.id = out_dport->port_id;
+ actions[act_cnt].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
+ actions[act_cnt].conf = &conf_port;
+ ++act_cnt;
+
+ actions[act_cnt].type = RTE_FLOW_ACTION_TYPE_END;
+
+ frr_with_privs (&zserv_privs) {
+ flow = rte_flow_create(in_dport->port_id, &attrs, items,
+ actions, &error);
+ }
+
+ if (flow) {
+ dplane_ctx_rule_set_dp_flow_ptr(ctx, (intptr_t)flow);
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow 0x%" PRIxPTR
+ " created ifname %s seq %d pri %u unique %d\n",
+ (intptr_t)flow, dplane_ctx_rule_get_ifname(ctx),
+ seq, pri, unique);
+ } else {
+ zlog_warn(
+ "PBR dpdk flow create failed ifname %s seq %d pri %u unique %d; rc %d\n",
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique,
+ error.type);
+ }
}
-static void zd_dpdk_rule_del(const char *ifname, int in_ifindex,
- intptr_t dp_flow_ptr)
+static void zd_dpdk_rule_del(struct zebra_dplane_ctx *ctx, const char *ifname,
+ int in_ifindex, intptr_t dp_flow_ptr)
{
+ struct zd_dpdk_port *in_dport;
+ struct rte_flow_error error;
+ int rc;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow delete ifname %s ifindex %d dp_flow 0x%" PRIxPTR
+ "\n",
+ ifname, in_ifindex, dp_flow_ptr);
+
+ if (!dp_flow_ptr) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
+ "; empty dp\n",
+ ifname, in_ifindex, dp_flow_ptr);
+ return;
+ }
- /* XXX - place holder */
+ dplane_ctx_rule_set_dp_flow_ptr(ctx, (intptr_t)NULL);
+ in_dport = zd_dpdk_port_find_by_index(in_ifindex);
+ if (!in_dport) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
+ zlog_debug(
+ "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
+ " in port missing\n",
+ ifname, in_ifindex, dp_flow_ptr);
+ return;
+ }
+
+ frr_with_privs (&zserv_privs) {
+ rc = rte_flow_destroy(in_dport->port_id,
+ (struct rte_flow *)dp_flow_ptr, &error);
+ }
+
+ if (rc)
+ zlog_warn(
+ "PBR dpdk flow delete failed; ifname %s ifindex %d dp_flow 0x%" PRIxPTR
+ "\n",
+ ifname, in_ifindex, dp_flow_ptr);
}
int in_ifindex;
intptr_t dp_flow_ptr;
- if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
zlog_debug("Dplane %s", dplane_op2str(dplane_ctx_get_op(ctx)));
- }
+
op = dplane_ctx_get_op(ctx);
switch (op) {
memory_order_relaxed);
in_ifindex = dplane_ctx_get_ifindex(ctx);
dp_flow_ptr = dplane_ctx_rule_get_old_dp_flow_ptr(ctx);
- zd_dpdk_rule_del(dplane_ctx_rule_get_ifname(ctx), in_ifindex,
- dp_flow_ptr);
+ zd_dpdk_rule_del(ctx, dplane_ctx_rule_get_ifname(ctx),
+ in_ifindex, dp_flow_ptr);
zd_dpdk_rule_add(ctx);
break;
memory_order_relaxed);
in_ifindex = dplane_ctx_get_ifindex(ctx);
dp_flow_ptr = dplane_ctx_rule_get_dp_flow_ptr(ctx);
- zd_dpdk_rule_del(dplane_ctx_rule_get_ifname(ctx), in_ifindex,
- dp_flow_ptr);
+ zd_dpdk_rule_del(ctx, dplane_ctx_rule_get_ifname(ctx),
+ in_ifindex, dp_flow_ptr);
break;
- default:;
+ case DPLANE_OP_NONE:
+ case DPLANE_OP_ROUTE_INSTALL:
+ case DPLANE_OP_ROUTE_UPDATE:
+ case DPLANE_OP_ROUTE_DELETE:
+ case DPLANE_OP_ROUTE_NOTIFY:
+ case DPLANE_OP_NH_INSTALL:
+ case DPLANE_OP_NH_UPDATE:
+ case DPLANE_OP_NH_DELETE:
+ case DPLANE_OP_LSP_INSTALL:
+ case DPLANE_OP_LSP_UPDATE:
+ case DPLANE_OP_LSP_DELETE:
+ case DPLANE_OP_LSP_NOTIFY:
+ case DPLANE_OP_PW_INSTALL:
+ case DPLANE_OP_PW_UNINSTALL:
+ case DPLANE_OP_SYS_ROUTE_ADD:
+ case DPLANE_OP_SYS_ROUTE_DELETE:
+ case DPLANE_OP_ADDR_INSTALL:
+ case DPLANE_OP_ADDR_UNINSTALL:
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
+ case DPLANE_OP_NEIGH_INSTALL:
+ case DPLANE_OP_NEIGH_UPDATE:
+ case DPLANE_OP_NEIGH_DELETE:
+ case DPLANE_OP_VTEP_ADD:
+ case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
+ case DPLANE_OP_BR_PORT_UPDATE:
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
+ case DPLANE_OP_NEIGH_IP_INSTALL:
+ case DPLANE_OP_NEIGH_IP_DELETE:
+ case DPLANE_OP_NEIGH_TABLE_UPDATE:
+ case DPLANE_OP_GRE_SET:
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ case DPLANE_OP_INTF_NETCONFIG:
+ case DPLANE_OP_INTF_INSTALL:
+ case DPLANE_OP_INTF_UPDATE:
+ case DPLANE_OP_INTF_DELETE:
+ break;
}
}
case DPLANE_OP_RULE_DELETE:
zd_dpdk_rule_update(ctx);
break;
-
- default:
+ case DPLANE_OP_NONE:
+ case DPLANE_OP_ROUTE_INSTALL:
+ case DPLANE_OP_ROUTE_UPDATE:
+ case DPLANE_OP_ROUTE_DELETE:
+ case DPLANE_OP_ROUTE_NOTIFY:
+ case DPLANE_OP_NH_INSTALL:
+ case DPLANE_OP_NH_UPDATE:
+ case DPLANE_OP_NH_DELETE:
+ case DPLANE_OP_LSP_INSTALL:
+ case DPLANE_OP_LSP_UPDATE:
+ case DPLANE_OP_LSP_DELETE:
+ case DPLANE_OP_LSP_NOTIFY:
+ case DPLANE_OP_PW_INSTALL:
+ case DPLANE_OP_PW_UNINSTALL:
+ case DPLANE_OP_SYS_ROUTE_ADD:
+ case DPLANE_OP_SYS_ROUTE_DELETE:
+ case DPLANE_OP_ADDR_INSTALL:
+ case DPLANE_OP_ADDR_UNINSTALL:
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
+ case DPLANE_OP_NEIGH_INSTALL:
+ case DPLANE_OP_NEIGH_UPDATE:
+ case DPLANE_OP_NEIGH_DELETE:
+ case DPLANE_OP_VTEP_ADD:
+ case DPLANE_OP_VTEP_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
+ case DPLANE_OP_BR_PORT_UPDATE:
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
+ case DPLANE_OP_NEIGH_IP_INSTALL:
+ case DPLANE_OP_NEIGH_IP_DELETE:
+ case DPLANE_OP_NEIGH_TABLE_UPDATE:
+ case DPLANE_OP_GRE_SET:
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ case DPLANE_OP_INTF_NETCONFIG:
+ case DPLANE_OP_INTF_INSTALL:
+ case DPLANE_OP_INTF_UPDATE:
+ case DPLANE_OP_INTF_DELETE:
atomic_fetch_add_explicit(&dpdk_stat->ignored_updates, 1,
memory_order_relaxed);
return 0;
}
+static void zd_dpdk_port_show_entry(struct zd_dpdk_port *dport, struct vty *vty,
+ int detail)
+{
+ struct rte_eth_dev_info *dev_info;
+
+ dev_info = &dport->dev_info;
+ if (detail) {
+ vty_out(vty, "DPDK port: %u\n", dport->port_id);
+ vty_out(vty, " Device: %s\n",
+ dev_info->device ? dev_info->device->name : "-");
+ vty_out(vty, " Driver: %s\n",
+ dev_info->driver_name ? dev_info->driver_name : "-");
+ vty_out(vty, " Interface: %s (%d)\n",
+ ifindex2ifname(dev_info->if_index, VRF_DEFAULT),
+ dev_info->if_index);
+ vty_out(vty, " Switch: %s Domain: %u Port: %u\n",
+ dev_info->switch_info.name,
+ dev_info->switch_info.domain_id,
+ dev_info->switch_info.port_id);
+ vty_out(vty, "\n");
+ } else {
+ vty_out(vty, "%-4u %-16s %-16s %-16d %s,%u,%u\n",
+ dport->port_id,
+ dev_info->device ? dev_info->device->name : "-",
+ ifindex2ifname(dev_info->if_index, VRF_DEFAULT),
+ dev_info->if_index, dev_info->switch_info.name,
+ dev_info->switch_info.domain_id,
+ dev_info->switch_info.port_id);
+ }
+}
+
+
+static struct zd_dpdk_port *zd_dpdk_port_find_by_index(int ifindex)
+{
+ int count;
+ struct zd_dpdk_port *dport;
+ struct rte_eth_dev_info *dev_info;
+
+ for (count = 0; count < RTE_MAX_ETHPORTS; ++count) {
+ dport = &dpdk_ctx->dpdk_ports[count];
+ if (!(dport->flags & ZD_DPDK_PORT_FLAG_INITED))
+ continue;
+ dev_info = &dport->dev_info;
+ if (dev_info->if_index == (uint32_t)ifindex)
+ return dport;
+ }
+
+ return NULL;
+}
+
+
+void zd_dpdk_port_show(struct vty *vty, uint16_t port_id, bool uj, int detail)
+{
+ int count;
+ struct zd_dpdk_port *dport;
+
+ /* XXX - support for json is yet to be added */
+ if (uj)
+ return;
+
+ if (!detail) {
+ vty_out(vty, "%-4s %-16s %-16s %-16s %s\n", "Port", "Device",
+ "IfName", "IfIndex", "sw,domain,port");
+ }
+
+ for (count = 0; count < RTE_MAX_ETHPORTS; ++count) {
+ dport = &dpdk_ctx->dpdk_ports[count];
+ if (dport->flags & ZD_DPDK_PORT_FLAG_INITED)
+ zd_dpdk_port_show_entry(dport, vty, detail);
+ }
+}
+
+
+static void zd_dpdk_port_init(void)
+{
+ struct zd_dpdk_port *dport;
+ uint16_t port_id;
+ struct rte_eth_dev_info *dev_info;
+ int count;
+ int rc;
+ struct rte_flow_error error;
+
+ /* allocate a list of ports */
+ dpdk_ctx->dpdk_ports =
+ XCALLOC(MTYPE_DPDK_PORTS,
+ sizeof(struct zd_dpdk_port) * RTE_MAX_ETHPORTS);
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug("dpdk port init");
+ count = 0;
+ RTE_ETH_FOREACH_DEV(port_id)
+ {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug("dpdk port init %d", port_id);
+ dport = &dpdk_ctx->dpdk_ports[count];
+ count++;
+ dport->port_id = port_id;
+ dport->flags |= ZD_DPDK_PORT_FLAG_PROBED;
+ dev_info = &dport->dev_info;
+ if (rte_eth_dev_info_get(port_id, dev_info) < 0) {
+ zlog_warn("failed to get dev info for %u, %s", port_id,
+ rte_strerror(rte_errno));
+ continue;
+ }
+ dport->flags |= ZD_DPDK_PORT_FLAG_INITED;
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug(
+ "port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u",
+ port_id,
+ dev_info->device ? dev_info->device->name : "-",
+ dev_info->if_index, dev_info->switch_info.name,
+ dev_info->switch_info.domain_id,
+ dev_info->switch_info.port_id);
+ if (rte_flow_isolate(port_id, 1, &error)) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug(
+ "Flow isolate on port %u failed %d\n",
+ port_id, error.type);
+ } else {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug("Flow isolate on port %u\n",
+ port_id);
+ }
+ rc = rte_eth_dev_start(port_id);
+ if (rc) {
+ zlog_warn("DPDK port %d start error: %s", port_id,
+ rte_strerror(-rc));
+ continue;
+ }
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug("DPDK port %d started in promiscuous mode ",
+ port_id);
+ }
+
+ if (!count) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
+ zlog_debug("no probed ethernet devices");
+ }
+}
+
+
static int zd_dpdk_init(void)
{
int rc;
- char *argv[] = {(char *)"/usr/lib/frr/zebra", (char *)"--"};
+ static const char *argv[] = {(char *)"/usr/lib/frr/zebra",
+ (char *)"--"};
zd_dpdk_vty_init();
frr_with_privs (&zserv_privs) {
- rc = rte_eal_init(sizeof(argv) / sizeof(argv[0]), argv);
+ rc = rte_eal_init(ARRAY_SIZE(argv), argv);
}
if (rc < 0) {
zlog_warn("EAL init failed %s", rte_strerror(rte_errno));
return -1;
}
+ frr_with_privs (&zserv_privs) {
+ zd_dpdk_port_init();
+ }
return 0;
}
+
static int zd_dpdk_start(struct zebra_dplane_provider *prov)
{
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
FRR_MODULE_SETUP(.name = "dplane_dpdk", .version = "0.0.1",
.description = "Data plane plugin using dpdk for hw offload",
- .init = zd_dpdk_module_init, );
+ .init = zd_dpdk_module_init);