diff options
| author | Anuradha Karuppiah <anuradhak@nvidia.com> | 2021-12-30 15:08:07 -0800 |
|---|---|---|
| committer | Donald Sharp <sharpd@nvidia.com> | 2022-06-27 08:08:02 -0400 |
| commit | 7f0416b368b3192c1ac81834d03130b313fd67f5 (patch) | |
| tree | c77d71a682cdf2c546591652b304f8452c7e01d9 /zebra/dpdk/zebra_dplane_dpdk.c | |
| parent | a66d6246616e7ba3aebda5d2524164e3fd8f7269 (diff) | |
zebra: PBR dpdk programming
1. Offload PBR rule add/del
2. Query DPDK flow stats and display per-PBR entry
Signed-off-by: Anuradha Karuppiah <anuradhak@nvidia.com>
Diffstat (limited to 'zebra/dpdk/zebra_dplane_dpdk.c')
| -rw-r--r-- | zebra/dpdk/zebra_dplane_dpdk.c | 383 |
1 files changed, 364 insertions, 19 deletions
diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c index 79b8c22b02..11a1af86c6 100644 --- a/zebra/dpdk/zebra_dplane_dpdk.c +++ b/zebra/dpdk/zebra_dplane_dpdk.c @@ -35,8 +35,6 @@ 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) @@ -56,7 +54,7 @@ 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); @@ -64,17 +62,279 @@ void zd_dpdk_stat_show(struct vty *vty) } +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; - /* XXX - place holder */ + 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; + } + + 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); } @@ -84,9 +344,9 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx) 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) { @@ -102,8 +362,8 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx) 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; @@ -112,11 +372,54 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx) 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; } } @@ -132,8 +435,49 @@ static void zd_dpdk_process_update(struct zebra_dplane_ctx *ctx) 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); @@ -308,12 +652,13 @@ static void zd_dpdk_port_init(void) 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)); @@ -385,4 +730,4 @@ static int zd_dpdk_module_init(void) 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); |
