Remove hardware offload logic from the dpif-netlink implementation. This is now handled by the dpif-offload provider as part of the dpif_operate() function, i.e., it has been moved up one layer.
Signed-off-by: Eelco Chaudron <echau...@redhat.com> --- lib/dpif-netdev.c | 3 +- lib/dpif-netlink.c | 337 +------------------------------------------- lib/dpif-provider.h | 7 +- lib/dpif.c | 5 +- 4 files changed, 8 insertions(+), 344 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index b3127dae6..a7df5119f 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -4709,8 +4709,7 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) } static void -dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops, - enum dpif_offload_type offload_type OVS_UNUSED) +dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops) { size_t i; diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index e61fbc0c5..222dc8336 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -1722,66 +1722,6 @@ dpif_netlink_flow_to_dpif_flow(struct dpif_flow *dpif_flow, dpif_flow->attrs.dp_extra_info = NULL; } -static int -dpif_netlink_netdev_match_to_dpif_flow(struct match *match, - struct ofpbuf *key_buf, - struct ofpbuf *mask_buf, - struct nlattr *actions, - struct dpif_flow_stats *stats, - struct dpif_flow_attrs *attrs, - ovs_u128 *ufid, - struct dpif_flow *flow, - bool terse) -{ - memset(flow, 0, sizeof *flow); - - if (!terse) { - struct odp_flow_key_parms odp_parms = { - .flow = &match->flow, - .mask = &match->wc.masks, - .support = { - .max_vlan_headers = 2, - .recirc = true, - .ct_state = true, - .ct_zone = true, - .ct_mark = true, - .ct_label = true, - }, - }; - size_t offset; - - /* Key */ - offset = key_buf->size; - flow->key = ofpbuf_tail(key_buf); - odp_flow_key_from_flow(&odp_parms, key_buf); - flow->key_len = key_buf->size - offset; - - /* Mask */ - offset = mask_buf->size; - flow->mask = ofpbuf_tail(mask_buf); - odp_parms.key_buf = key_buf; - odp_flow_key_from_mask(&odp_parms, mask_buf); - flow->mask_len = mask_buf->size - offset; - - /* Actions */ - flow->actions = nl_attr_get(actions); - flow->actions_len = nl_attr_get_size(actions); - } - - /* Stats */ - memcpy(&flow->stats, stats, sizeof *stats); - - /* UFID */ - flow->ufid_present = true; - flow->ufid = *ufid; - - flow->pmd_id = PMD_ID_NULL; - - memcpy(&flow->attrs, attrs, sizeof *attrs); - - return 0; -} - static int dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_, struct dpif_flow *flows, int max_flows) @@ -2062,224 +2002,11 @@ dpif_netlink_operate__(struct dpif_netlink *dpif, return n_ops; } -static int -parse_flow_get(struct dpif_netlink *dpif, struct dpif_flow_get *get) -{ - const char *dpif_type_str = dpif_normalize_type(dpif_type(&dpif->dpif)); - struct dpif_flow *dpif_flow = get->flow; - struct match match; - struct nlattr *actions; - struct dpif_flow_stats stats; - struct dpif_flow_attrs attrs; - struct ofpbuf buf; - uint64_t act_buf[1024 / 8]; - struct odputil_keybuf maskbuf; - struct odputil_keybuf keybuf; - struct odputil_keybuf actbuf; - struct ofpbuf key, mask, act; - int err; - - ofpbuf_use_stack(&buf, &act_buf, sizeof act_buf); - err = netdev_ports_flow_get(dpif_type_str, &match, &actions, get->ufid, - &stats, &attrs, &buf); - if (err) { - return err; - } - - VLOG_DBG("found flow from netdev, translating to dpif flow"); - - ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); - ofpbuf_use_stack(&act, &actbuf, sizeof actbuf); - ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf); - dpif_netlink_netdev_match_to_dpif_flow(&match, &key, &mask, actions, - &stats, &attrs, - (ovs_u128 *) get->ufid, - dpif_flow, - false); - ofpbuf_put(get->buffer, nl_attr_get(actions), nl_attr_get_size(actions)); - dpif_flow->actions = ofpbuf_at(get->buffer, 0, 0); - dpif_flow->actions_len = nl_attr_get_size(actions); - - return 0; -} - -static int -parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put) -{ - const char *dpif_type_str = dpif_normalize_type(dpif_type(&dpif->dpif)); - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); - struct match match; - odp_port_t in_port; - const struct nlattr *nla; - size_t left; - struct netdev *dev; - struct offload_info info; - int err; - - info.tc_modify_flow_deleted = false; - if (put->flags & DPIF_FP_PROBE) { - return EOPNOTSUPP; - } - - err = parse_key_and_mask_to_match(put->key, put->key_len, put->mask, - put->mask_len, &match); - if (err) { - return err; - } - - in_port = match.flow.in_port.odp_port; - dev = netdev_ports_get(in_port, dpif_type_str); - if (!dev) { - return EOPNOTSUPP; - } - - /* Check the output port for a tunnel. */ - NL_ATTR_FOR_EACH(nla, left, put->actions, put->actions_len) { - if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) { - struct netdev *outdev; - odp_port_t out_port; - - out_port = nl_attr_get_odp_port(nla); - outdev = netdev_ports_get(out_port, dpif_type_str); - if (!outdev) { - err = EOPNOTSUPP; - goto out; - } - netdev_close(outdev); - } - } - - info.recirc_id_shared_with_tc = (dpif->user_features - & OVS_DP_F_TC_RECIRC_SHARING); - err = netdev_flow_put(dev, &match, - CONST_CAST(struct nlattr *, put->actions), - put->actions_len, - CONST_CAST(ovs_u128 *, put->ufid), - &info, put->stats); - - if (!err) { - if (put->flags & DPIF_FP_MODIFY) { - struct dpif_op *opp; - struct dpif_op op; - - op.type = DPIF_OP_FLOW_DEL; - op.flow_del.key = put->key; - op.flow_del.key_len = put->key_len; - op.flow_del.ufid = put->ufid; - op.flow_del.pmd_id = put->pmd_id; - op.flow_del.stats = NULL; - op.flow_del.terse = false; - - opp = &op; - dpif_netlink_operate__(dpif, &opp, 1); - } - - VLOG_DBG("added flow"); - } else if (err != EEXIST) { - struct netdev *oor_netdev = NULL; - enum vlog_level level; - if (err == ENOSPC - && dpif_offload_is_offload_rebalance_policy_enabled()) { - /* - * We need to set OOR on the input netdev (i.e, 'dev') for the - * flow. But if the flow has a tunnel attribute (i.e, decap action, - * with a virtual device like a VxLAN interface as its in-port), - * then lookup and set OOR on the underlying tunnel (real) netdev. - */ - oor_netdev = flow_get_tunnel_netdev(&match.flow.tunnel); - if (!oor_netdev) { - /* Not a 'tunnel' flow */ - oor_netdev = dev; - } - netdev_set_hw_info(oor_netdev, HW_INFO_TYPE_OOR, true); - } - level = (err == ENOSPC || err == EOPNOTSUPP) ? VLL_DBG : VLL_ERR; - VLOG_RL(&rl, level, "failed to offload flow: %s: %s", - ovs_strerror(err), - (oor_netdev ? oor_netdev->name : dev->name)); - } - -out: - if (err && err != EEXIST && (put->flags & DPIF_FP_MODIFY)) { - /* Modified rule can't be offloaded, try and delete from HW */ - int del_err = 0; - - if (!info.tc_modify_flow_deleted) { - del_err = netdev_flow_del(dev, put->ufid, put->stats); - } - - if (!del_err) { - /* Delete from hw success, so old flow was offloaded. - * Change flags to create the flow in kernel */ - put->flags &= ~DPIF_FP_MODIFY; - put->flags |= DPIF_FP_CREATE; - } else if (del_err != ENOENT && del_err != EOPNOTSUPP) { - VLOG_ERR_RL(&rl, "failed to delete offloaded flow: %s", - ovs_strerror(del_err)); - /* stop proccesing the flow in kernel */ - err = 0; - } - } - - netdev_close(dev); - - return err; -} - -static int -try_send_to_netdev(struct dpif_netlink *dpif, struct dpif_op *op) -{ - int err = EOPNOTSUPP; - - switch (op->type) { - case DPIF_OP_FLOW_PUT: { - struct dpif_flow_put *put = &op->flow_put; - - if (!put->ufid) { - break; - } - - err = parse_flow_put(dpif, put); - log_flow_put_message(&dpif->dpif, &this_module, put, 0); - break; - } - case DPIF_OP_FLOW_DEL: { - struct dpif_flow_del *del = &op->flow_del; - - if (!del->ufid) { - break; - } - - err = netdev_ports_flow_del( - dpif_normalize_type(dpif_type(&dpif->dpif)), - del->ufid, - del->stats); - log_flow_del_message(&dpif->dpif, &this_module, del, 0); - break; - } - case DPIF_OP_FLOW_GET: { - struct dpif_flow_get *get = &op->flow_get; - - if (!op->flow_get.ufid) { - break; - } - - err = parse_flow_get(dpif, get); - log_flow_get_message(&dpif->dpif, &this_module, get, 0); - break; - } - case DPIF_OP_EXECUTE: - default: - break; - } - - return err; -} - static void -dpif_netlink_operate_chunks(struct dpif_netlink *dpif, struct dpif_op **ops, - size_t n_ops) +dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops) { + struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); + while (n_ops > 0) { size_t chunk = dpif_netlink_operate__(dpif, ops, n_ops); @@ -2288,64 +2015,6 @@ dpif_netlink_operate_chunks(struct dpif_netlink *dpif, struct dpif_op **ops, } } -static void -dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops, - enum dpif_offload_type offload_type) -{ - struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); - struct dpif_op *new_ops[OPERATE_MAX_OPS]; - int count = 0; - int i = 0; - int err = 0; - - if (offload_type == DPIF_OFFLOAD_ALWAYS - && !dpif_offload_is_offload_enabled()) { - VLOG_DBG("Invalid offload_type: %d", offload_type); - return; - } - - if (offload_type != DPIF_OFFLOAD_NEVER - && dpif_offload_is_offload_enabled()) { - while (n_ops > 0) { - count = 0; - - while (n_ops > 0 && count < OPERATE_MAX_OPS) { - struct dpif_op *op = ops[i++]; - - err = try_send_to_netdev(dpif, op); - if (err && err != EEXIST) { - if (offload_type == DPIF_OFFLOAD_ALWAYS) { - /* We got an error while offloading an op. Since - * OFFLOAD_ALWAYS is specified, we stop further - * processing and return to the caller without - * invoking kernel datapath as fallback. But the - * interface requires us to process all n_ops; so - * return the same error in the remaining ops too. - */ - op->error = err; - n_ops--; - while (n_ops > 0) { - op = ops[i++]; - op->error = err; - n_ops--; - } - return; - } - new_ops[count++] = op; - } else { - op->error = err; - } - - n_ops--; - } - - dpif_netlink_operate_chunks(dpif, new_ops, count); - } - } else if (offload_type != DPIF_OFFLOAD_ALWAYS) { - dpif_netlink_operate_chunks(dpif, ops, n_ops); - } -} - #if _WIN32 static void dpif_netlink_handler_uninit(struct dpif_handler *handler) diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index d27ad5165..e1c91caff 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -363,11 +363,8 @@ struct dpif_class { /* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the order * in which they are specified, placing each operation's results in the * "output" members documented in comments and the 'error' member of each - * dpif_op. The offload_type argument tells the provider if 'ops' should - * be submitted to to a netdev (only offload) or to the kernel datapath - * (never offload) or to both (offload if possible; software fallback). */ - void (*operate)(struct dpif *dpif, struct dpif_op **ops, size_t n_ops, - enum dpif_offload_type offload_type); + * dpif_op. */ + void (*operate)(struct dpif *dpif, struct dpif_op **ops, size_t n_ops); /* Get hardware-offloads activity counters from a dataplane. * Those counters are not offload statistics (which are accessible through diff --git a/lib/dpif.c b/lib/dpif.c index c294b79ae..c8b73ca0e 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1418,12 +1418,11 @@ dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops, ops_left = dpif_offload_operate(dpif, ops_copy, chunk, offload_type); if (ops_left) { - dpif->dpif_class->operate(dpif, ops_copy, ops_left, - offload_type); + dpif->dpif_class->operate(dpif, ops_copy, ops_left); } free(ops_copy); } else { - dpif->dpif_class->operate(dpif, ops, chunk, offload_type); + dpif->dpif_class->operate(dpif, ops, chunk); } for (i = 0; i < chunk; i++) { -- 2.50.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev