@@ -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;
@@ -1725,66 +1725,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)
@@ -2065,224 +2005,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);
@@ -2291,64 +2018,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)
@@ -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
@@ -1423,12 +1423,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++) {
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 <echaudro@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(-)