diff options
author | Or Gerlitz <ogerlitz@mellanox.com> | 2016-07-01 07:51:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-02 14:40:40 -0400 |
commit | 08f4b5918b2d6b491f0403cc1886f5cdccef89bb (patch) | |
tree | 35da396f43f718b63095c9e552ec4cfe26a27a6e | |
parent | fed9ce22bf8ae8f417b8f047d2d630542d152ccf (diff) |
net/devlink: Add E-Switch mode control
Add the commands to set and show the mode of SRIOV E-Switch, two modes
are supported:
* legacy: operating in the "old" L2 based mode (DMAC --> VF vport)
* switchdev: the E-Switch is referred to as whitebox switch configured
using standard tools such as tc, bridge, openvswitch etc. To allow
working with the tools, for each VF, a VF representor netdevice is
created by the E-Switch manager vendor device driver instance (e.g PF).
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/devlink.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/devlink.h | 8 | ||||
-rw-r--r-- | net/core/devlink.c | 87 |
3 files changed, 98 insertions, 0 deletions
diff --git a/include/net/devlink.h b/include/net/devlink.h index 1d45b61cb320..c99ffe8cef3c 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h | |||
@@ -90,6 +90,9 @@ struct devlink_ops { | |||
90 | u16 tc_index, | 90 | u16 tc_index, |
91 | enum devlink_sb_pool_type pool_type, | 91 | enum devlink_sb_pool_type pool_type, |
92 | u32 *p_cur, u32 *p_max); | 92 | u32 *p_cur, u32 *p_max); |
93 | |||
94 | int (*eswitch_mode_get)(struct devlink *devlink, u16 *p_mode); | ||
95 | int (*eswitch_mode_set)(struct devlink *devlink, u16 mode); | ||
93 | }; | 96 | }; |
94 | 97 | ||
95 | static inline void *devlink_priv(struct devlink *devlink) | 98 | static inline void *devlink_priv(struct devlink *devlink) |
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index ba0073b26fa6..915bfa74458c 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h | |||
@@ -57,6 +57,8 @@ enum devlink_command { | |||
57 | DEVLINK_CMD_SB_OCC_SNAPSHOT, | 57 | DEVLINK_CMD_SB_OCC_SNAPSHOT, |
58 | DEVLINK_CMD_SB_OCC_MAX_CLEAR, | 58 | DEVLINK_CMD_SB_OCC_MAX_CLEAR, |
59 | 59 | ||
60 | DEVLINK_CMD_ESWITCH_MODE_GET, | ||
61 | DEVLINK_CMD_ESWITCH_MODE_SET, | ||
60 | /* add new commands above here */ | 62 | /* add new commands above here */ |
61 | 63 | ||
62 | __DEVLINK_CMD_MAX, | 64 | __DEVLINK_CMD_MAX, |
@@ -95,6 +97,11 @@ enum devlink_sb_threshold_type { | |||
95 | 97 | ||
96 | #define DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX 20 | 98 | #define DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX 20 |
97 | 99 | ||
100 | enum devlink_eswitch_mode { | ||
101 | DEVLINK_ESWITCH_MODE_LEGACY, | ||
102 | DEVLINK_ESWITCH_MODE_SWITCHDEV, | ||
103 | }; | ||
104 | |||
98 | enum devlink_attr { | 105 | enum devlink_attr { |
99 | /* don't change the order or add anything between, this is ABI! */ | 106 | /* don't change the order or add anything between, this is ABI! */ |
100 | DEVLINK_ATTR_UNSPEC, | 107 | DEVLINK_ATTR_UNSPEC, |
@@ -125,6 +132,7 @@ enum devlink_attr { | |||
125 | DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ | 132 | DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ |
126 | DEVLINK_ATTR_SB_OCC_CUR, /* u32 */ | 133 | DEVLINK_ATTR_SB_OCC_CUR, /* u32 */ |
127 | DEVLINK_ATTR_SB_OCC_MAX, /* u32 */ | 134 | DEVLINK_ATTR_SB_OCC_MAX, /* u32 */ |
135 | DEVLINK_ATTR_ESWITCH_MODE, /* u16 */ | ||
128 | 136 | ||
129 | /* add new attributes above here, update the policy in devlink.c */ | 137 | /* add new attributes above here, update the policy in devlink.c */ |
130 | 138 | ||
diff --git a/net/core/devlink.c b/net/core/devlink.c index 933e8d4d3968..b2e592a198c0 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c | |||
@@ -1394,6 +1394,78 @@ static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, | |||
1394 | return -EOPNOTSUPP; | 1394 | return -EOPNOTSUPP; |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | static int devlink_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, | ||
1398 | enum devlink_command cmd, u32 portid, | ||
1399 | u32 seq, int flags, u16 mode) | ||
1400 | { | ||
1401 | void *hdr; | ||
1402 | |||
1403 | hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); | ||
1404 | if (!hdr) | ||
1405 | return -EMSGSIZE; | ||
1406 | |||
1407 | if (devlink_nl_put_handle(msg, devlink)) | ||
1408 | goto nla_put_failure; | ||
1409 | |||
1410 | if (nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode)) | ||
1411 | goto nla_put_failure; | ||
1412 | |||
1413 | genlmsg_end(msg, hdr); | ||
1414 | return 0; | ||
1415 | |||
1416 | nla_put_failure: | ||
1417 | genlmsg_cancel(msg, hdr); | ||
1418 | return -EMSGSIZE; | ||
1419 | } | ||
1420 | |||
1421 | static int devlink_nl_cmd_eswitch_mode_get_doit(struct sk_buff *skb, | ||
1422 | struct genl_info *info) | ||
1423 | { | ||
1424 | struct devlink *devlink = info->user_ptr[0]; | ||
1425 | const struct devlink_ops *ops = devlink->ops; | ||
1426 | struct sk_buff *msg; | ||
1427 | u16 mode; | ||
1428 | int err; | ||
1429 | |||
1430 | if (!ops || !ops->eswitch_mode_get) | ||
1431 | return -EOPNOTSUPP; | ||
1432 | |||
1433 | err = ops->eswitch_mode_get(devlink, &mode); | ||
1434 | if (err) | ||
1435 | return err; | ||
1436 | |||
1437 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1438 | if (!msg) | ||
1439 | return -ENOMEM; | ||
1440 | |||
1441 | err = devlink_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_MODE_GET, | ||
1442 | info->snd_portid, info->snd_seq, 0, mode); | ||
1443 | |||
1444 | if (err) { | ||
1445 | nlmsg_free(msg); | ||
1446 | return err; | ||
1447 | } | ||
1448 | |||
1449 | return genlmsg_reply(msg, info); | ||
1450 | } | ||
1451 | |||
1452 | static int devlink_nl_cmd_eswitch_mode_set_doit(struct sk_buff *skb, | ||
1453 | struct genl_info *info) | ||
1454 | { | ||
1455 | struct devlink *devlink = info->user_ptr[0]; | ||
1456 | const struct devlink_ops *ops = devlink->ops; | ||
1457 | u16 mode; | ||
1458 | |||
1459 | if (!info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) | ||
1460 | return -EINVAL; | ||
1461 | |||
1462 | mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); | ||
1463 | |||
1464 | if (ops && ops->eswitch_mode_set) | ||
1465 | return ops->eswitch_mode_set(devlink, mode); | ||
1466 | return -EOPNOTSUPP; | ||
1467 | } | ||
1468 | |||
1397 | static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { | 1469 | static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { |
1398 | [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, | 1470 | [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, |
1399 | [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, | 1471 | [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, |
@@ -1407,6 +1479,7 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { | |||
1407 | [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, | 1479 | [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, |
1408 | [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, | 1480 | [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, |
1409 | [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, | 1481 | [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, |
1482 | [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, | ||
1410 | }; | 1483 | }; |
1411 | 1484 | ||
1412 | static const struct genl_ops devlink_nl_ops[] = { | 1485 | static const struct genl_ops devlink_nl_ops[] = { |
@@ -1525,6 +1598,20 @@ static const struct genl_ops devlink_nl_ops[] = { | |||
1525 | DEVLINK_NL_FLAG_NEED_SB | | 1598 | DEVLINK_NL_FLAG_NEED_SB | |
1526 | DEVLINK_NL_FLAG_LOCK_PORTS, | 1599 | DEVLINK_NL_FLAG_LOCK_PORTS, |
1527 | }, | 1600 | }, |
1601 | { | ||
1602 | .cmd = DEVLINK_CMD_ESWITCH_MODE_GET, | ||
1603 | .doit = devlink_nl_cmd_eswitch_mode_get_doit, | ||
1604 | .policy = devlink_nl_policy, | ||
1605 | .flags = GENL_ADMIN_PERM, | ||
1606 | .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, | ||
1607 | }, | ||
1608 | { | ||
1609 | .cmd = DEVLINK_CMD_ESWITCH_MODE_SET, | ||
1610 | .doit = devlink_nl_cmd_eswitch_mode_set_doit, | ||
1611 | .policy = devlink_nl_policy, | ||
1612 | .flags = GENL_ADMIN_PERM, | ||
1613 | .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, | ||
1614 | }, | ||
1528 | }; | 1615 | }; |
1529 | 1616 | ||
1530 | /** | 1617 | /** |