devlink: Add E-Switch inline mode control
authorRoi Dayan <roid@mellanox.com>
Tue, 22 Nov 2016 21:09:57 +0000 (23:09 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 24 Nov 2016 21:01:14 +0000 (16:01 -0500)
Some HWs need the VF driver to put part of the packet headers on the
TX descriptor so the e-switch can do proper matching and steering.

The supported modes: none, link, network, transport.

Signed-off-by: Roi Dayan <roid@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/devlink.h
include/uapi/linux/devlink.h
net/core/devlink.c

index 211bd3c37028d80fa1fd2a7849757008d4b6ee7f..d29e5fc8258216b9d79604bc99b69b66cce3e443 100644 (file)
@@ -92,6 +92,8 @@ struct devlink_ops {
 
        int (*eswitch_mode_get)(struct devlink *devlink, u16 *p_mode);
        int (*eswitch_mode_set)(struct devlink *devlink, u16 mode);
+       int (*eswitch_inline_mode_get)(struct devlink *devlink, u8 *p_inline_mode);
+       int (*eswitch_inline_mode_set)(struct devlink *devlink, u8 inline_mode);
 };
 
 static inline void *devlink_priv(struct devlink *devlink)
index 915bfa74458c147c48a8b12d19221022e0d9e376..9014c33d4e77bf409be507f6fb8da59edc14b2f8 100644 (file)
@@ -102,6 +102,13 @@ enum devlink_eswitch_mode {
        DEVLINK_ESWITCH_MODE_SWITCHDEV,
 };
 
+enum devlink_eswitch_inline_mode {
+       DEVLINK_ESWITCH_INLINE_MODE_NONE,
+       DEVLINK_ESWITCH_INLINE_MODE_LINK,
+       DEVLINK_ESWITCH_INLINE_MODE_NETWORK,
+       DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT,
+};
+
 enum devlink_attr {
        /* don't change the order or add anything between, this is ABI! */
        DEVLINK_ATTR_UNSPEC,
@@ -133,6 +140,7 @@ enum devlink_attr {
        DEVLINK_ATTR_SB_OCC_CUR,                /* u32 */
        DEVLINK_ATTR_SB_OCC_MAX,                /* u32 */
        DEVLINK_ATTR_ESWITCH_MODE,              /* u16 */
+       DEVLINK_ATTR_ESWITCH_INLINE_MODE,       /* u8 */
 
        /* add new attributes above here, update the policy in devlink.c */
 
index c14f8b661db99f1bb2b0d6a475dbddca18703b85..2b5bf9efa720a9feed9d2f187dda6ab5bf59cda0 100644 (file)
@@ -1394,26 +1394,45 @@ static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
 
 static int devlink_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
                                enum devlink_command cmd, u32 portid,
-                               u32 seq, int flags, u16 mode)
+                               u32 seq, int flags)
 {
+       const struct devlink_ops *ops = devlink->ops;
        void *hdr;
+       int err = 0;
+       u16 mode;
+       u8 inline_mode;
 
        hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
        if (!hdr)
                return -EMSGSIZE;
 
-       if (devlink_nl_put_handle(msg, devlink))
-               goto nla_put_failure;
+       err = devlink_nl_put_handle(msg, devlink);
+       if (err)
+               goto out;
 
-       if (nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode))
-               goto nla_put_failure;
+       err = ops->eswitch_mode_get(devlink, &mode);
+       if (err)
+               goto out;
+       err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
+       if (err)
+               goto out;
+
+       if (ops->eswitch_inline_mode_get) {
+               err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
+               if (err)
+                       goto out;
+               err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
+                                inline_mode);
+               if (err)
+                       goto out;
+       }
 
        genlmsg_end(msg, hdr);
        return 0;
 
-nla_put_failure:
+out:
        genlmsg_cancel(msg, hdr);
-       return -EMSGSIZE;
+       return err;
 }
 
 static int devlink_nl_cmd_eswitch_mode_get_doit(struct sk_buff *skb,
@@ -1422,22 +1441,17 @@ static int devlink_nl_cmd_eswitch_mode_get_doit(struct sk_buff *skb,
        struct devlink *devlink = info->user_ptr[0];
        const struct devlink_ops *ops = devlink->ops;
        struct sk_buff *msg;
-       u16 mode;
        int err;
 
        if (!ops || !ops->eswitch_mode_get)
                return -EOPNOTSUPP;
 
-       err = ops->eswitch_mode_get(devlink, &mode);
-       if (err)
-               return err;
-
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg)
                return -ENOMEM;
 
        err = devlink_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_MODE_GET,
-                                  info->snd_portid, info->snd_seq, 0, mode);
+                                  info->snd_portid, info->snd_seq, 0);
 
        if (err) {
                nlmsg_free(msg);
@@ -1453,15 +1467,32 @@ static int devlink_nl_cmd_eswitch_mode_set_doit(struct sk_buff *skb,
        struct devlink *devlink = info->user_ptr[0];
        const struct devlink_ops *ops = devlink->ops;
        u16 mode;
+       u8 inline_mode;
+       int err = 0;
 
-       if (!info->attrs[DEVLINK_ATTR_ESWITCH_MODE])
-               return -EINVAL;
+       if (!ops)
+               return -EOPNOTSUPP;
 
-       mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
+       if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
+               if (!ops->eswitch_mode_set)
+                       return -EOPNOTSUPP;
+               mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
+               err = ops->eswitch_mode_set(devlink, mode);
+               if (err)
+                       return err;
+       }
 
-       if (ops && ops->eswitch_mode_set)
-               return ops->eswitch_mode_set(devlink, mode);
-       return -EOPNOTSUPP;
+       if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
+               if (!ops->eswitch_inline_mode_set)
+                       return -EOPNOTSUPP;
+               inline_mode = nla_get_u8(
+                               info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
+               err = ops->eswitch_inline_mode_set(devlink, inline_mode);
+               if (err)
+                       return err;
+       }
+
+       return 0;
 }
 
 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
@@ -1478,6 +1509,7 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
        [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
        [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
        [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
+       [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
 };
 
 static const struct genl_ops devlink_nl_ops[] = {