On Wed, Feb 15, 2017 at 03:44:30PM +0200, Roi Dayan wrote: > > > On 14/02/2017 01:55, Chandran, Sugesh wrote: > > > > > > Regards > > _Sugesh > > > > > > > -----Original Message----- > > > From: Roi Dayan [mailto:r...@mellanox.com] > > > Sent: Wednesday, February 8, 2017 3:29 PM > > > To: d...@openvswitch.org > > > Cc: Paul Blakey <pa...@mellanox.com>; Or Gerlitz > > > <ogerl...@mellanox.com>; Hadar Hen Zion <had...@mellanox.com>; Shahar > > > Klein <shah...@mellanox.com>; Mark Bloch <ma...@mellanox.com>; Rony > > > Efraim <ro...@mellanox.com>; Fastabend, John R > > > <john.r.fastab...@intel.com>; Joe Stringer <j...@ovn.org>; Andy > > > Gospodarek <a...@greyhouse.net>; Lance Richardson > > > <lrich...@redhat.com>; Marcelo Ricardo Leitner <mleit...@redhat.com>; > > > Simon Horman <simon.hor...@netronome.com>; Jiri Pirko > > > <j...@mellanox.com>; Chandran, Sugesh <sugesh.chand...@intel.com> > > > Subject: [PATCH ovs V3 12/25] dpif-netlink: Use netdev flow put api to > > > insert > > > a flow > > > > > > From: Paul Blakey <pa...@mellanox.com> > > > > > > + > > > + // XXX: missing ofpbuf_uninit? > > > + return 0; > > > +} > > > + > > > +static int > > > +parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put) { > > > + 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; > > > + int outputs = 0; > > > + struct netdev *dev; > > > + struct offload_info info; > > > + ovs_be16 dst_port = 0; > > > + int err = 0; > > > + > > > + 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; > > > + } > > > + > > > + /* Get tunnel dst port and count outputs */ > > > + NL_ATTR_FOR_EACH(nla, left, put->actions, put->actions_len) { > > > + if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) { > > > + const struct netdev_tunnel_config *tnl_cfg; > > > + struct netdev *outdev; > > > + odp_port_t out_port; > > > + > > [Sugesh] Just wondering , is it the right place to do these checks. In > > fact these are limited by the hardware(Correct me if I am wrong here). So > > this has to under the specific netdev_flow_put than here? > > right. it was done here for convenience. should probably move it. thanks. > > > > + outputs++; > > > + if (outputs > 1) { > > > + VLOG_WARN_RL(&rl, "offloading multiple ports isn't > > > supported");
Also, you may want to consider reducing the log level of this message. Seems I'm hitting it for all broadcasts on the subnet. 2017-02-17T17:28:35.025Z|03238|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:28:45.437Z|03239|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:28:50.315Z|03240|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:28:55.376Z|00649|dpif_netlink(handler20)|WARN|offloading multiple ports isn't supported 2017-02-17T17:29:17.834Z|03241|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:29:39.952Z|00650|dpif_netlink(handler20)|WARN|offloading multiple ports isn't supported 2017-02-17T17:29:54.321Z|03242|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:29:59.498Z|03243|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:30:14.300Z|03244|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:30:22.338Z|03245|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported 2017-02-17T17:30:24.896Z|00651|dpif_netlink(handler20)|WARN|offloading multiple ports isn't supported 2017-02-17T17:30:43.072Z|03246|dpif_netlink(handler14)|WARN|offloading multiple ports isn't supported .... for flows like: recirc_id(0),in_port(2),eth(src=XX:XX:XX:cb:76:af,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:692, used:8.821s, actions:3,1 And/or you plan to support it? > > > + err = EOPNOTSUPP; > > > + goto err_out; > > > + } > > > + > > > + out_port = nl_attr_get_odp_port(nla); > > > + outdev = netdev_hmap_port_get(out_port, DPIF_HMAP_KEY(&dpif- > > > > dpif)); > > > + tnl_cfg = netdev_get_tunnel_config(outdev); > > > + if (tnl_cfg && tnl_cfg->dst_port != 0) { > > > + dst_port = tnl_cfg->dst_port; > > > + } > > > + netdev_close(outdev); > > > + } > > > + } > > > + > > > + > > > + info.port_hmap_obj = DPIF_HMAP_KEY(&dpif->dpif); > > > + info.tp_dst_port = dst_port; > > > + in_port = match.flow.in_port.odp_port; > > > + dev = netdev_hmap_port_get(in_port, DPIF_HMAP_KEY(&dpif->dpif)); > > > + err = netdev_flow_put(dev, &match, > > > + CONST_CAST(struct nlattr *, put->actions), > > > + put->actions_len, put->stats, > > > + CONST_CAST(ovs_u128 *, put->ufid), &info); > > > + netdev_close(dev); > > > + > > > + if (!err) { > > > + if (put->flags & DPIF_FP_MODIFY) { > > > + struct dpif_op *opp; > > > + struct dpif_op op; > > > + > > > + op.type = DPIF_OP_FLOW_DEL; > > > + op.u.flow_del.key = put->key; > > > + op.u.flow_del.key_len = put->key_len; > > > + op.u.flow_del.ufid = put->ufid; > > > + op.u.flow_del.pmd_id = put->pmd_id; > > > + op.u.flow_del.stats = NULL; > > > + op.u.flow_del.terse = false; > > > + > > > + opp = &op; > > > + dpif_netlink_operate__(dpif, &opp, 1); > > > + } > > > + VLOG_DBG("added flow"); > > > + } else if (err != EEXIST) { > > > + VLOG_ERR_RL(&rl, "failed adding flow: %s", ovs_strerror(err)); > > > + } > > > + > > > +err_out: > > > + > > > + return err; > > > +} > > > + > > > static void > > > -dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t > > > n_ops) > > > +dbg_print_flow(const struct nlattr *key, size_t key_len, > > > + const struct nlattr *mask, size_t mask_len, > > > + const struct nlattr *actions, size_t actions_len, > > > + const ovs_u128 *ufid, > > > + const char *op) > > > +{ > > > + struct ds s; > > > + > > > + ds_init(&s); > > > + ds_put_cstr(&s, op); > > > + ds_put_cstr(&s, " ("); > > > + odp_format_ufid(ufid, &s); > > > + ds_put_cstr(&s, ")"); > > > + if (key_len) { > > > + ds_put_cstr(&s, "\nflow (verbose): "); > > > + odp_flow_format(key, key_len, mask, mask_len, NULL, &s, > > > true); > > > + ds_put_cstr(&s, "\nflow: "); > > > + odp_flow_format(key, key_len, mask, mask_len, NULL, &s, > > > false); > > > + } > > > + ds_put_cstr(&s, "\nactions: "); > > > + format_odp_actions(&s, actions, actions_len); > > > + VLOG_DBG("\n%s", ds_cstr(&s)); > > > + ds_destroy(&s); > > > +} > > > + > > > +static int > > > +try_send_to_netdev(struct dpif_netlink *dpif, struct dpif_op *op) > > > { > > > - struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); > > > + switch (op->type) { > > > + case DPIF_OP_FLOW_PUT: { > > > + struct dpif_flow_put *put = &op->u.flow_put; > > > + > > > + if (!put->ufid) { > > > + break; > > > + } > > > + dbg_print_flow(put->key, put->key_len, put->mask, put->mask_len, > > > + put->actions, put->actions_len, put->ufid, "PUT"); > > > + return parse_flow_put(dpif, put); > > > + } > > > + case DPIF_OP_FLOW_DEL: > > > + case DPIF_OP_FLOW_GET: > > > + case DPIF_OP_EXECUTE: > > > + default: > > > + break; > > > + } > > > + return EOPNOTSUPP; > > > +} > > > > > > +static void > > > +dpif_netlink_operate_chunks(struct dpif_netlink *dpif, struct dpif_op > > > **ops, > > > + size_t n_ops) { > > > while (n_ops > 0) { > > > size_t chunk = dpif_netlink_operate__(dpif, ops, n_ops); > > > + > > > ops += chunk; > > > n_ops -= chunk; > > > } > > > } > > > > > > +static void > > > +dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t > > > +n_ops) { > > > + 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 (netdev_flow_api_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) { > > > + new_ops[count++] = op; > > > + } else { > > > + op->error = err; > > > + } > > > + > > > + n_ops--; > > > + } > > > + > > > + dpif_netlink_operate_chunks(dpif, new_ops, count); > > > + } > > > + > > > + return; > > > + } > > > + > > > + dpif_netlink_operate_chunks(dpif, ops, n_ops); } > > > + > > > #if _WIN32 > > > static void > > > dpif_netlink_handler_uninit(struct dpif_handler *handler) diff --git > > > a/lib/odp-util.c b/lib/odp-util.c index 4106738..274d2ee 100644 > > > --- a/lib/odp-util.c > > > +++ b/lib/odp-util.c > > > @@ -41,6 +41,7 @@ > > > #include "util.h" > > > #include "uuid.h" > > > #include "openvswitch/vlog.h" > > > +#include "openvswitch/match.h" > > > > > > VLOG_DEFINE_THIS_MODULE(odp_util); > > > > > > @@ -5294,6 +5295,58 @@ odp_flow_key_to_mask(const struct nlattr > > > *mask_key, size_t mask_key_len, > > > } > > > } > > > > > > +/* Converts the netlink formated key/mask to match. > > > + * Fails if odp_flow_key_from_key/mask and odp_flow_key_key/mask > > > + * disagree on the acceptable form of flow */ int > > > +parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len, > > > + const struct nlattr *mask, size_t mask_len, > > > + struct match *match) { > > > + enum odp_key_fitness fitness; > > > + > > > + fitness = odp_flow_key_to_flow(key, key_len, &match->flow); > > > + if (fitness) { > > > + /* This should not happen: it indicates that > > > odp_flow_key_from_flow() > > > + * and odp_flow_key_to_flow() disagree on the acceptable form of > > > a > > > + * flow. Log the problem as an error, with enough details to > > > enable > > > + * debugging. */ > > > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); > > > + > > > + if (!VLOG_DROP_ERR(&rl)) { > > > + struct ds s; > > > + > > > + ds_init(&s); > > > + odp_flow_format(key, key_len, NULL, 0, NULL, &s, true); > > > + VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s)); > > > + ds_destroy(&s); > > > + } > > > + > > > + return EINVAL; > > > + } > > > + > > > + fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, > > > &match->flow); > > > + if (fitness) { > > > + /* This should not happen: it indicates that > > > + * odp_flow_key_from_mask() and odp_flow_key_to_mask() > > > + * disagree on the acceptable form of a mask. Log the problem > > > + * as an error, with enough details to enable debugging. */ > > > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); > > > + > > > + if (!VLOG_DROP_ERR(&rl)) { > > > + struct ds s; > > > + > > > + VLOG_ERR("internal error parsing flow mask %s (%s)", > > > + ds_cstr(&s), odp_key_fitness_to_string(fitness)); > > > + ds_destroy(&s); > > > + } > > > + > > > + return EINVAL; > > > + } > > > + > > > + return 0; > > > +} > > > + > > > /* Returns 'fitness' as a string, for use in debug messages. */ const > > > char * > > > odp_key_fitness_to_string(enum odp_key_fitness fitness) diff --git > > > a/lib/odp-util.h b/lib/odp-util.h index 42011bc..3f59ab7 100644 > > > --- a/lib/odp-util.h > > > +++ b/lib/odp-util.h > > > @@ -236,6 +236,9 @@ enum odp_key_fitness > > > odp_flow_key_to_mask(const struct nlattr *mask_key, > > > size_t mask_key_len, > > > struct flow_wildcards *mask, > > > const struct flow *flow); > > > +int parse_key_and_mask_to_match(const struct nlattr *key, size_t > > > key_len, > > > + const struct nlattr *mask, size_t > > > mask_len, > > > + struct match *match); > > > > > > const char *odp_key_fitness_to_string(enum odp_key_fitness); > > > > > > -- > > > 2.7.4 > > > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev