aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2016-04-14 12:19:14 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-14 16:22:03 -0400
commitdf38dafd255954ee7012785c62e615f595d5cb3c (patch)
tree493e781aa7b44ba00a23ea6162b04c93918d0732
parentbf7974710a40aaeb69dee7f62d91048bdaf79c76 (diff)
devlink: implement shared buffer occupancy monitoring interface
User needs to monitor shared buffer occupancy. For that, he issues a snapshot command in order to instruct hardware to catch current and maximal occupancy values, and clear command in order to clear the historical maximal values. Also port-pool and tc-pool-bind command response messages are extended to carry occupancy values. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/devlink.h12
-rw-r--r--include/uapi/linux/devlink.h6
-rw-r--r--net/core/devlink.c98
3 files changed, 110 insertions, 6 deletions
diff --git a/include/net/devlink.h b/include/net/devlink.h
index e4c27473ee4f..be64218e0254 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -78,6 +78,18 @@ struct devlink_ops {
78 u16 tc_index, 78 u16 tc_index,
79 enum devlink_sb_pool_type pool_type, 79 enum devlink_sb_pool_type pool_type,
80 u16 pool_index, u32 threshold); 80 u16 pool_index, u32 threshold);
81 int (*sb_occ_snapshot)(struct devlink *devlink,
82 unsigned int sb_index);
83 int (*sb_occ_max_clear)(struct devlink *devlink,
84 unsigned int sb_index);
85 int (*sb_occ_port_pool_get)(struct devlink_port *devlink_port,
86 unsigned int sb_index, u16 pool_index,
87 u32 *p_cur, u32 *p_max);
88 int (*sb_occ_tc_port_bind_get)(struct devlink_port *devlink_port,
89 unsigned int sb_index,
90 u16 tc_index,
91 enum devlink_sb_pool_type pool_type,
92 u32 *p_cur, u32 *p_max);
81}; 93};
82 94
83static inline void *devlink_priv(struct devlink *devlink) 95static inline void *devlink_priv(struct devlink *devlink)
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 9c1aa5783090..ba0073b26fa6 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -53,6 +53,10 @@ enum devlink_command {
53 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 53 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
54 DEVLINK_CMD_SB_TC_POOL_BIND_DEL, 54 DEVLINK_CMD_SB_TC_POOL_BIND_DEL,
55 55
56 /* Shared buffer occupancy monitoring commands */
57 DEVLINK_CMD_SB_OCC_SNAPSHOT,
58 DEVLINK_CMD_SB_OCC_MAX_CLEAR,
59
56 /* add new commands above here */ 60 /* add new commands above here */
57 61
58 __DEVLINK_CMD_MAX, 62 __DEVLINK_CMD_MAX,
@@ -119,6 +123,8 @@ enum devlink_attr {
119 DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */ 123 DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */
120 DEVLINK_ATTR_SB_THRESHOLD, /* u32 */ 124 DEVLINK_ATTR_SB_THRESHOLD, /* u32 */
121 DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ 125 DEVLINK_ATTR_SB_TC_INDEX, /* u16 */
126 DEVLINK_ATTR_SB_OCC_CUR, /* u32 */
127 DEVLINK_ATTR_SB_OCC_MAX, /* u32 */
122 128
123 /* add new attributes above here, update the policy in devlink.c */ 129 /* add new attributes above here, update the policy in devlink.c */
124 130
diff --git a/net/core/devlink.c b/net/core/devlink.c
index aa0b9e1542e7..933e8d4d3968 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -280,6 +280,10 @@ devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
280#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) 280#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
281#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) 281#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
282#define DEVLINK_NL_FLAG_NEED_SB BIT(2) 282#define DEVLINK_NL_FLAG_NEED_SB BIT(2)
283#define DEVLINK_NL_FLAG_LOCK_PORTS BIT(3)
284 /* port is not needed but we need to ensure they don't
285 * change in the middle of command
286 */
283 287
284static int devlink_nl_pre_doit(const struct genl_ops *ops, 288static int devlink_nl_pre_doit(const struct genl_ops *ops,
285 struct sk_buff *skb, struct genl_info *info) 289 struct sk_buff *skb, struct genl_info *info)
@@ -306,6 +310,9 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops,
306 } 310 }
307 info->user_ptr[0] = devlink_port; 311 info->user_ptr[0] = devlink_port;
308 } 312 }
313 if (ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS) {
314 mutex_lock(&devlink_port_mutex);
315 }
309 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { 316 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
310 struct devlink_sb *devlink_sb; 317 struct devlink_sb *devlink_sb;
311 318
@@ -324,7 +331,8 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops,
324static void devlink_nl_post_doit(const struct genl_ops *ops, 331static void devlink_nl_post_doit(const struct genl_ops *ops,
325 struct sk_buff *skb, struct genl_info *info) 332 struct sk_buff *skb, struct genl_info *info)
326{ 333{
327 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) 334 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT ||
335 ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS)
328 mutex_unlock(&devlink_port_mutex); 336 mutex_unlock(&devlink_port_mutex);
329 mutex_unlock(&devlink_mutex); 337 mutex_unlock(&devlink_mutex);
330} 338}
@@ -942,12 +950,13 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
942 enum devlink_command cmd, 950 enum devlink_command cmd,
943 u32 portid, u32 seq, int flags) 951 u32 portid, u32 seq, int flags)
944{ 952{
953 const struct devlink_ops *ops = devlink->ops;
945 u32 threshold; 954 u32 threshold;
946 void *hdr; 955 void *hdr;
947 int err; 956 int err;
948 957
949 err = devlink->ops->sb_port_pool_get(devlink_port, devlink_sb->index, 958 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
950 pool_index, &threshold); 959 pool_index, &threshold);
951 if (err) 960 if (err)
952 return err; 961 return err;
953 962
@@ -966,6 +975,22 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
966 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 975 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
967 goto nla_put_failure; 976 goto nla_put_failure;
968 977
978 if (ops->sb_occ_port_pool_get) {
979 u32 cur;
980 u32 max;
981
982 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
983 pool_index, &cur, &max);
984 if (err && err != -EOPNOTSUPP)
985 return err;
986 if (!err) {
987 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
988 goto nla_put_failure;
989 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
990 goto nla_put_failure;
991 }
992 }
993
969 genlmsg_end(msg, hdr); 994 genlmsg_end(msg, hdr);
970 return 0; 995 return 0;
971 996
@@ -1114,14 +1139,15 @@ devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1114 enum devlink_command cmd, 1139 enum devlink_command cmd,
1115 u32 portid, u32 seq, int flags) 1140 u32 portid, u32 seq, int flags)
1116{ 1141{
1142 const struct devlink_ops *ops = devlink->ops;
1117 u16 pool_index; 1143 u16 pool_index;
1118 u32 threshold; 1144 u32 threshold;
1119 void *hdr; 1145 void *hdr;
1120 int err; 1146 int err;
1121 1147
1122 err = devlink->ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1148 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1123 tc_index, pool_type, 1149 tc_index, pool_type,
1124 &pool_index, &threshold); 1150 &pool_index, &threshold);
1125 if (err) 1151 if (err)
1126 return err; 1152 return err;
1127 1153
@@ -1144,6 +1170,24 @@ devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1144 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1170 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1145 goto nla_put_failure; 1171 goto nla_put_failure;
1146 1172
1173 if (ops->sb_occ_tc_port_bind_get) {
1174 u32 cur;
1175 u32 max;
1176
1177 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1178 devlink_sb->index,
1179 tc_index, pool_type,
1180 &cur, &max);
1181 if (err && err != -EOPNOTSUPP)
1182 return err;
1183 if (!err) {
1184 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1185 goto nla_put_failure;
1186 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1187 goto nla_put_failure;
1188 }
1189 }
1190
1147 genlmsg_end(msg, hdr); 1191 genlmsg_end(msg, hdr);
1148 return 0; 1192 return 0;
1149 1193
@@ -1326,6 +1370,30 @@ static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1326 pool_index, threshold); 1370 pool_index, threshold);
1327} 1371}
1328 1372
1373static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1374 struct genl_info *info)
1375{
1376 struct devlink *devlink = info->user_ptr[0];
1377 struct devlink_sb *devlink_sb = info->user_ptr[1];
1378 const struct devlink_ops *ops = devlink->ops;
1379
1380 if (ops && ops->sb_occ_snapshot)
1381 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1382 return -EOPNOTSUPP;
1383}
1384
1385static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1386 struct genl_info *info)
1387{
1388 struct devlink *devlink = info->user_ptr[0];
1389 struct devlink_sb *devlink_sb = info->user_ptr[1];
1390 const struct devlink_ops *ops = devlink->ops;
1391
1392 if (ops && ops->sb_occ_max_clear)
1393 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1394 return -EOPNOTSUPP;
1395}
1396
1329static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 1397static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
1330 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 1398 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
1331 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 1399 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
@@ -1439,6 +1507,24 @@ static const struct genl_ops devlink_nl_ops[] = {
1439 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 1507 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1440 DEVLINK_NL_FLAG_NEED_SB, 1508 DEVLINK_NL_FLAG_NEED_SB,
1441 }, 1509 },
1510 {
1511 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
1512 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
1513 .policy = devlink_nl_policy,
1514 .flags = GENL_ADMIN_PERM,
1515 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1516 DEVLINK_NL_FLAG_NEED_SB |
1517 DEVLINK_NL_FLAG_LOCK_PORTS,
1518 },
1519 {
1520 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
1521 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
1522 .policy = devlink_nl_policy,
1523 .flags = GENL_ADMIN_PERM,
1524 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1525 DEVLINK_NL_FLAG_NEED_SB |
1526 DEVLINK_NL_FLAG_LOCK_PORTS,
1527 },
1442}; 1528};
1443 1529
1444/** 1530/**