aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMoshe Shemesh <moshe@mellanox.com>2018-07-04 07:30:30 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-05 06:58:35 -0400
commite3b7ca18ad7b2f47ebd3b6e6ce58a42c6ec24746 (patch)
treec7c71c7baef0f531561d190862a1cd2f9be68c42 /net
parent45f05def5c44c806f094709f1c9b03dcecdd54f0 (diff)
devlink: Add param set command
Add param set command to set value for a parameter. Value can be set to any of the supported configuration modes. Signed-off-by: Moshe Shemesh <moshe@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/devlink.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/net/core/devlink.c b/net/core/devlink.c
index b22d41275f0b..0cd7a42dcec2 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -2661,6 +2661,15 @@ static int devlink_param_get(struct devlink *devlink,
2661 return param->get(devlink, param->id, ctx); 2661 return param->get(devlink, param->id, ctx);
2662} 2662}
2663 2663
2664static int devlink_param_set(struct devlink *devlink,
2665 const struct devlink_param *param,
2666 struct devlink_param_gset_ctx *ctx)
2667{
2668 if (!param->set)
2669 return -EOPNOTSUPP;
2670 return param->set(devlink, param->id, ctx);
2671}
2672
2664static int 2673static int
2665devlink_param_type_to_nla_type(enum devlink_param_type param_type) 2674devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2666{ 2675{
@@ -2847,6 +2856,69 @@ out:
2847 return msg->len; 2856 return msg->len;
2848} 2857}
2849 2858
2859static int
2860devlink_param_type_get_from_info(struct genl_info *info,
2861 enum devlink_param_type *param_type)
2862{
2863 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
2864 return -EINVAL;
2865
2866 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
2867 case NLA_U8:
2868 *param_type = DEVLINK_PARAM_TYPE_U8;
2869 break;
2870 case NLA_U16:
2871 *param_type = DEVLINK_PARAM_TYPE_U16;
2872 break;
2873 case NLA_U32:
2874 *param_type = DEVLINK_PARAM_TYPE_U32;
2875 break;
2876 case NLA_STRING:
2877 *param_type = DEVLINK_PARAM_TYPE_STRING;
2878 break;
2879 case NLA_FLAG:
2880 *param_type = DEVLINK_PARAM_TYPE_BOOL;
2881 break;
2882 default:
2883 return -EINVAL;
2884 }
2885
2886 return 0;
2887}
2888
2889static int
2890devlink_param_value_get_from_info(const struct devlink_param *param,
2891 struct genl_info *info,
2892 union devlink_param_value *value)
2893{
2894 if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
2895 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
2896 return -EINVAL;
2897
2898 switch (param->type) {
2899 case DEVLINK_PARAM_TYPE_U8:
2900 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
2901 break;
2902 case DEVLINK_PARAM_TYPE_U16:
2903 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
2904 break;
2905 case DEVLINK_PARAM_TYPE_U32:
2906 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
2907 break;
2908 case DEVLINK_PARAM_TYPE_STRING:
2909 if (nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) >
2910 DEVLINK_PARAM_MAX_STRING_VALUE)
2911 return -EINVAL;
2912 value->vstr = nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
2913 break;
2914 case DEVLINK_PARAM_TYPE_BOOL:
2915 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
2916 true : false;
2917 break;
2918 }
2919 return 0;
2920}
2921
2850static struct devlink_param_item * 2922static struct devlink_param_item *
2851devlink_param_get_from_info(struct devlink *devlink, 2923devlink_param_get_from_info(struct devlink *devlink,
2852 struct genl_info *info) 2924 struct genl_info *info)
@@ -2887,6 +2959,58 @@ static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
2887 return genlmsg_reply(msg, info); 2959 return genlmsg_reply(msg, info);
2888} 2960}
2889 2961
2962static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
2963 struct genl_info *info)
2964{
2965 struct devlink *devlink = info->user_ptr[0];
2966 enum devlink_param_type param_type;
2967 struct devlink_param_gset_ctx ctx;
2968 enum devlink_param_cmode cmode;
2969 struct devlink_param_item *param_item;
2970 const struct devlink_param *param;
2971 union devlink_param_value value;
2972 int err = 0;
2973
2974 param_item = devlink_param_get_from_info(devlink, info);
2975 if (!param_item)
2976 return -EINVAL;
2977 param = param_item->param;
2978 err = devlink_param_type_get_from_info(info, &param_type);
2979 if (err)
2980 return err;
2981 if (param_type != param->type)
2982 return -EINVAL;
2983 err = devlink_param_value_get_from_info(param, info, &value);
2984 if (err)
2985 return err;
2986 if (param->validate) {
2987 err = param->validate(devlink, param->id, value, info->extack);
2988 if (err)
2989 return err;
2990 }
2991
2992 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
2993 return -EINVAL;
2994 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
2995 if (!devlink_param_cmode_is_supported(param, cmode))
2996 return -EOPNOTSUPP;
2997
2998 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
2999 param_item->driverinit_value = value;
3000 param_item->driverinit_value_valid = true;
3001 } else {
3002 if (!param->set)
3003 return -EOPNOTSUPP;
3004 ctx.val = value;
3005 ctx.cmode = cmode;
3006 err = devlink_param_set(devlink, param, &ctx);
3007 if (err)
3008 return err;
3009 }
3010
3011 return 0;
3012}
3013
2890static int devlink_param_register_one(struct devlink *devlink, 3014static int devlink_param_register_one(struct devlink *devlink,
2891 const struct devlink_param *param) 3015 const struct devlink_param *param)
2892{ 3016{
@@ -2942,6 +3066,9 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
2942 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 3066 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
2943 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 3067 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
2944 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 3068 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
3069 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
3070 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
3071 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
2945}; 3072};
2946 3073
2947static const struct genl_ops devlink_nl_ops[] = { 3074static const struct genl_ops devlink_nl_ops[] = {
@@ -3133,6 +3260,13 @@ static const struct genl_ops devlink_nl_ops[] = {
3133 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3260 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3134 /* can be retrieved by unprivileged users */ 3261 /* can be retrieved by unprivileged users */
3135 }, 3262 },
3263 {
3264 .cmd = DEVLINK_CMD_PARAM_SET,
3265 .doit = devlink_nl_cmd_param_set_doit,
3266 .policy = devlink_nl_policy,
3267 .flags = GENL_ADMIN_PERM,
3268 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3269 },
3136}; 3270};
3137 3271
3138static struct genl_family devlink_nl_family __ro_after_init = { 3272static struct genl_family devlink_nl_family __ro_after_init = {