[ovs-dev] [PATCH ovs V3 12/25] dpif-netlink: Use netdev flow put api to insert a flow
Roi Dayan
roid at mellanox.com
Tue Feb 21 13:07:28 UTC 2017
On 17/02/2017 19:38, Marcelo Ricardo Leitner wrote:
> 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:roid at mellanox.com]
>>>> Sent: Wednesday, February 8, 2017 3:29 PM
>>>> To: dev at openvswitch.org
>>>> Cc: Paul Blakey <paulb at mellanox.com>; Or Gerlitz
>>>> <ogerlitz at mellanox.com>; Hadar Hen Zion <hadarh at mellanox.com>; Shahar
>>>> Klein <shahark at mellanox.com>; Mark Bloch <markb at mellanox.com>; Rony
>>>> Efraim <ronye at mellanox.com>; Fastabend, John R
>>>> <john.r.fastabend at intel.com>; Joe Stringer <joe at ovn.org>; Andy
>>>> Gospodarek <andy at greyhouse.net>; Lance Richardson
>>>> <lrichard at redhat.com>; Marcelo Ricardo Leitner <mleitner at redhat.com>;
>>>> Simon Horman <simon.horman at netronome.com>; Jiri Pirko
>>>> <jiri at mellanox.com>; Chandran, Sugesh <sugesh.chandran at intel.com>
>>>> Subject: [PATCH ovs V3 12/25] dpif-netlink: Use netdev flow put api to insert
>>>> a flow
>>>>
>>>> From: Paul Blakey <paulb at 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?
>
yes we plan to support it. It is with rate limit but I guess sometimes
it's not enough depends on the traffic. We can move to debug level.
>>>> + 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
>>>
>>
More information about the dev
mailing list