History

devlink: support default values for param-get and param-set

Support querying and resetting to default param values. Introduce two new devlink netlink attrs: DEVLINK_ATTR_PARAM_VALUE_DEFAULT and DEVLINK_ATTR_PARAM_RESET_DEFAULT. The former is used to contain an optional parameter value inside of the param_value nested attribute. The latter is used in param-set requests from userspace to indicate that the driver should reset the param to its default value. To implement this, two new functions are added to the devlink driver api: devlink_param::get_default() and devlink_param::reset_default(). These callbacks allow drivers to implement default param actions for runtime and permanent cmodes. For driverinit params, the core latches the last value set by a driver via devl_param_driverinit_value_set(), and uses that as the default value for a param. Because default parameter values are optional, it would be impossible to discern whether or not a param of type bool has default value of false or not provided if the default value is encoded using a netlink flag type. For this reason, when a DEVLINK_PARAM_TYPE_BOOL has an associated default value, the default value is encoded using a u8 type.

Daniel Zahka committed 12 months ago

Commit 2a367001 parent 17a42aa6 files · +160 −14Browse files

Unified · Split

6 files
  1. Documentation/netlink/specs/devlink.yaml +9 −0
  2. Documentation/networking/devlink/devlink-params.rst +10 −0
  3. include/net/devlink.h +42 −0
  4. include/uapi/linux/devlink.h +3 −0
  5. net/devlink/netlink_gen.c +3 −2
  6. net/devlink/param.c +93 −12
Documentation/netlink/specs/devlink.yaml+9−0
@@ -859,6 +859,14 @@ attribute-sets: · 858 unmodified lines
859859 name: health-reporter-burst-period
860860 type: u64
861861 doc: Time (in msec) for recoveries before starting the grace period.
862+
863+ # TODO: fill in the attributes in between
864+
865+ -
866+ name: param-reset-default
867+ type: flag
868+ doc: Request restoring parameter to its default value.
869+ value: 183
862870 -
863871 name: dl-dev-stats
864872 subset-of: devlink
@@ -1793,6 +1801,7 @@ operations: · 928 unmodified lines
17931801 - param-type
17941802 # param-value-data is missing here as the type is variable
17951803 - param-value-cmode
1804+ - param-reset-default
17961805
17971806 -
17981807 name: region-get
Documentation/networking/devlink/devlink-params.rst+10−0
@@ -41,6 +41,16 @@ In order for ``driverinit`` parameters to take effect, the driver must · 40 unmodified lines
4141 support reloading via the ``devlink-reload`` command. This command will
4242 request a reload of the device driver.
4343
44+Default parameter values
45+=========================
46+
47+Drivers may optionally export default values for parameters of cmode
48+``runtime`` and ``permanent``. For ``driverinit`` parameters, the last
49+value set by the driver will be used as the default value. Drivers can
50+also support resetting params with cmode ``runtime`` and ``permanent``
51+to their default values. Resetting ``driverinit`` params is supported
52+by devlink core without additional driver support needed.
53+
4454 .. _devlink_params_generic:
4555
4656 Generic configuration parameters
include/net/devlink.h+42−0
@@ -479,6 +479,10 @@ struct devlink_flash_notify { · 478 unmodified lines
479479 * @set: set parameter value, used for runtime and permanent
480480 * configuration modes
481481 * @validate: validate input value is applicable (within value range, etc.)
482+ * @get_default: get parameter default value, used for runtime and permanent
483+ * configuration modes
484+ * @reset_default: reset parameter to default value, used for runtime and permanent
485+ * configuration modes
482486 *
483487 * This struct should be used by the driver to fill the data for
484488 * a parameter it registers.
@@ -498,6 +502,12 @@ struct devlink_param { · 13 unmodified lines
498502 int (*validate)(struct devlink *devlink, u32 id,
499503 union devlink_param_value val,
500504 struct netlink_ext_ack *extack);
505+ int (*get_default)(struct devlink *devlink, u32 id,
506+ struct devlink_param_gset_ctx *ctx,
507+ struct netlink_ext_ack *extack);
508+ int (*reset_default)(struct devlink *devlink, u32 id,
509+ enum devlink_param_cmode cmode,
510+ struct netlink_ext_ack *extack);
501511 };
502512
503513 struct devlink_param_item {
@@ -509,6 +519,7 @@ struct devlink_param_item { · 5 unmodified lines
509519 * until reload.
510520 */
511521 bool driverinit_value_new_valid;
522+ union devlink_param_value driverinit_default;
512523 };
513524
514525 enum devlink_param_generic_id {
@@ -630,6 +641,37 @@ enum devlink_param_generic_id { · 115 unmodified lines
630641 .validate = _validate, \
631642 }
632643
644+#define DEVLINK_PARAM_GENERIC_WITH_DEFAULTS(_id, _cmodes, _get, _set, \
645+ _validate, _get_default, \
646+ _reset_default) \
647+{ \
648+ .id = DEVLINK_PARAM_GENERIC_ID_##_id, \
649+ .name = DEVLINK_PARAM_GENERIC_##_id##_NAME, \
650+ .type = DEVLINK_PARAM_GENERIC_##_id##_TYPE, \
651+ .generic = true, \
652+ .supported_cmodes = _cmodes, \
653+ .get = _get, \
654+ .set = _set, \
655+ .validate = _validate, \
656+ .get_default = _get_default, \
657+ .reset_default = _reset_default, \
658+}
659+
660+#define DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(_id, _name, _type, _cmodes, \
661+ _get, _set, _validate, \
662+ _get_default, _reset_default) \
663+{ \
664+ .id = _id, \
665+ .name = _name, \
666+ .type = _type, \
667+ .supported_cmodes = _cmodes, \
668+ .get = _get, \
669+ .set = _set, \
670+ .validate = _validate, \
671+ .get_default = _get_default, \
672+ .reset_default = _reset_default, \
673+}
674+
633675 /* Identifier of board design */
634676 #define DEVLINK_INFO_VERSION_GENERIC_BOARD_ID "board.id"
635677 /* Revision of board design */
include/uapi/linux/devlink.h+3−0
@@ -639,6 +639,9 @@ enum devlink_attr { · 638 unmodified lines
639639
640640 DEVLINK_ATTR_HEALTH_REPORTER_BURST_PERIOD, /* u64 */
641641
642+ DEVLINK_ATTR_PARAM_VALUE_DEFAULT, /* dynamic */
643+ DEVLINK_ATTR_PARAM_RESET_DEFAULT, /* flag */
644+
642645 /* Add new attributes above here, update the spec in
643646 * Documentation/netlink/specs/devlink.yaml and re-generate
644647 * net/devlink/netlink_gen.c.
net/devlink/netlink_gen.c+3−2
@@ -301,12 +301,13 @@ static const struct nla_policy devlink_param_get_dump_nl_policy[DEVLINK_ATTR_DEV · 300 unmodified lines
301301 };
302302
303303 /* DEVLINK_CMD_PARAM_SET - do */
304−static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_VALUE_CMODE + 1] = {
304+static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_RESET_DEFAULT + 1] = {
305305 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
306306 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
307307 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING, },
308308 [DEVLINK_ATTR_PARAM_TYPE] = NLA_POLICY_VALIDATE_FN(NLA_U8, &devlink_attr_param_type_validate),
309309 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = NLA_POLICY_MAX(NLA_U8, 2),
310+ [DEVLINK_ATTR_PARAM_RESET_DEFAULT] = { .type = NLA_FLAG, },
310311 };
311312
312313 /* DEVLINK_CMD_REGION_GET - do */
@@ -919,7 +920,7 @@ const struct genl_split_ops devlink_nl_ops[74] = { · 606 unmodified lines
919920 .doit = devlink_nl_param_set_doit,
920921 .post_doit = devlink_nl_post_doit,
921922 .policy = devlink_param_set_nl_policy,
922− .maxattr = DEVLINK_ATTR_PARAM_VALUE_CMODE,
923+ .maxattr = DEVLINK_ATTR_PARAM_RESET_DEFAULT,
923924 .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
924925 },
925926 {
net/devlink/param.c+93−12
@@ -192,9 +192,32 @@ static int devlink_param_set(struct devlink *devlink, · 191 unmodified lines
192192 return param->set(devlink, param->id, ctx, extack);
193193 }
194194
195+static int devlink_param_get_default(struct devlink *devlink,
196+ const struct devlink_param *param,
197+ struct devlink_param_gset_ctx *ctx,
198+ struct netlink_ext_ack *extack)
199+{
200+ if (!param->get_default)
201+ return -EOPNOTSUPP;
202+
203+ return param->get_default(devlink, param->id, ctx, extack);
204+}
205+
206+static int devlink_param_reset_default(struct devlink *devlink,
207+ const struct devlink_param *param,
208+ enum devlink_param_cmode cmode,
209+ struct netlink_ext_ack *extack)
210+{
211+ if (!param->reset_default)
212+ return -EOPNOTSUPP;
213+
214+ return param->reset_default(devlink, param->id, cmode, extack);
215+}
216+
195217 static int
196218 devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
197− int nla_type, union devlink_param_value val)
219+ int nla_type, union devlink_param_value val,
220+ bool flag_as_u8)
198221 {
199222 switch (type) {
200223 case DEVLINK_PARAM_TYPE_U8:
@@ -218,8 +241,16 @@ devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type, · 17 unmodified lines
218241 return -EMSGSIZE;
219242 break;
220243 case DEVLINK_PARAM_TYPE_BOOL:
221− if (val.vbool && nla_put_flag(msg, nla_type))
222− return -EMSGSIZE;
244+ /* default values of type bool are encoded with u8, so that
245+ * false can be distinguished from not present
246+ */
247+ if (flag_as_u8) {
248+ if (nla_put_u8(msg, nla_type, val.vbool))
249+ return -EMSGSIZE;
250+ } else {
251+ if (val.vbool && nla_put_flag(msg, nla_type))
252+ return -EMSGSIZE;
253+ }
223254 break;
224255 }
225256 return 0;
@@ -229,7 +260,9 @@ static int · 3 unmodified lines
229260 devlink_nl_param_value_fill_one(struct sk_buff *msg,
230261 enum devlink_param_type type,
231262 enum devlink_param_cmode cmode,
232− union devlink_param_value val)
263+ union devlink_param_value val,
264+ union devlink_param_value default_val,
265+ bool has_default)
233266 {
234267 struct nlattr *param_value_attr;
235268 int err = -EMSGSIZE;
@@ -243,10 +276,19 @@ devlink_nl_param_value_fill_one(struct sk_buff *msg, · 7 unmodified lines
243276 goto value_nest_cancel;
244277
245278 err = devlink_nl_param_value_put(msg, type,
246− DEVLINK_ATTR_PARAM_VALUE_DATA, val);
279+ DEVLINK_ATTR_PARAM_VALUE_DATA,
280+ val, false);
247281 if (err)
248282 goto value_nest_cancel;
249283
284+ if (has_default) {
285+ err = devlink_nl_param_value_put(msg, type,
286+ DEVLINK_ATTR_PARAM_VALUE_DEFAULT,
287+ default_val, true);
288+ if (err)
289+ goto value_nest_cancel;
290+ }
291+
250292 nla_nest_end(msg, param_value_attr);
251293 return 0;
252294
@@ -262,7 +304,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, · 9 unmodified lines
262304 u32 portid, u32 seq, int flags,
263305 struct netlink_ext_ack *extack)
264306 {
307+ union devlink_param_value default_value[DEVLINK_PARAM_CMODE_MAX + 1];
265308 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
309+ bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
266310 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
267311 const struct devlink_param *param = param_item->param;
268312 struct devlink_param_gset_ctx ctx;
@@ -283,12 +327,26 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, · 14 unmodified lines
283327 param_value[i] = param_item->driverinit_value;
284328 else
285329 return -EOPNOTSUPP;
330+
331+ if (param_item->driverinit_value_valid) {
332+ default_value[i] = param_item->driverinit_default;
333+ default_value_set[i] = true;
334+ }
286335 } else {
287336 ctx.cmode = i;
288337 err = devlink_param_get(devlink, param, &ctx, extack);
289338 if (err)
290339 return err;
291340 param_value[i] = ctx.val;
341+
342+ err = devlink_param_get_default(devlink, param, &ctx,
343+ extack);
344+ if (!err) {
345+ default_value[i] = ctx.val;
346+ default_value_set[i] = true;
347+ } else if (err != -EOPNOTSUPP) {
348+ return err;
349+ }
292350 }
293351 param_value_set[i] = true;
294352 }
@@ -325,7 +383,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, · 30 unmodified lines
325383 if (!param_value_set[i])
326384 continue;
327385 err = devlink_nl_param_value_fill_one(msg, param->type,
328− i, param_value[i]);
386+ i, param_value[i],
387+ default_value[i],
388+ default_value_set[i]);
329389 if (err)
330390 goto values_list_nest_cancel;
331391 }
@@ -542,6 +602,7 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, · 210 unmodified lines
542602 struct devlink_param_item *param_item;
543603 const struct devlink_param *param;
544604 union devlink_param_value value;
605+ bool reset_default;
545606 int err = 0;
546607
547608 param_item = devlink_param_get_from_info(params, info);
@@ -553,13 +614,18 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, · 5 unmodified lines
553614 return err;
554615 if (param_type != param->type)
555616 return -EINVAL;
556− err = devlink_param_value_get_from_info(param, info, &value);
557− if (err)
558− return err;
559− if (param->validate) {
560− err = param->validate(devlink, param->id, value, info->extack);
617+
618+ reset_default = info->attrs[DEVLINK_ATTR_PARAM_RESET_DEFAULT];
619+ if (!reset_default) {
620+ err = devlink_param_value_get_from_info(param, info, &value);
561621 if (err)
562622 return err;
623+ if (param->validate) {
624+ err = param->validate(devlink, param->id, value,
625+ info->extack);
626+ if (err)
627+ return err;
628+ }
563629 }
564630
565631 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
@@ -569,6 +635,15 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, · 3 unmodified lines
569635 return -EOPNOTSUPP;
570636
571637 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
638+ if (reset_default) {
639+ if (!param_item->driverinit_value_valid) {
640+ NL_SET_ERR_MSG(info->extack,
641+ "Default value not available");
642+ return -EOPNOTSUPP;
643+ }
644+ value = param_item->driverinit_default;
645+ }
646+
572647 param_item->driverinit_value_new = value;
573648 param_item->driverinit_value_new_valid = true;
574649 } else {
@@ -576,7 +651,12 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, · 1 unmodified line
576651 return -EOPNOTSUPP;
577652 ctx.val = value;
578653 ctx.cmode = cmode;
579− err = devlink_param_set(devlink, param, &ctx, info->extack);
654+ if (reset_default)
655+ err = devlink_param_reset_default(devlink, param, cmode,
656+ info->extack);
657+ else
658+ err = devlink_param_set(devlink, param, &ctx,
659+ info->extack);
580660 if (err)
581661 return err;
582662 }
@@ -824,6 +904,7 @@ void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id, · 241 unmodified lines
824904
825905 param_item->driverinit_value = init_val;
826906 param_item->driverinit_value_valid = true;
907+ param_item->driverinit_default = init_val;
827908
828909 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
829910 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t