History

devlink: Add health buffer support

Devlink health buffer is a mechanism to pass descriptors between drivers and devlink. The API allows the driver to add objects, object pair, value array (nested attributes), value and name. Driver can use this API to fill the buffers in a format which can be translated by the devlink to the netlink message. In order to fulfill it, an internal buffer descriptor is defined. This will hold the data and metadata per each attribute and by used to pass actual commands to the netlink. This mechanism will be later used in devlink health for dump and diagnose data store by the drivers.

Eran Ben Elisha committed 7 years ago

Commit cb5ccfb1 parent f88c19a3 files · +585 −0Browse files

Unified · Split

3 files
  1. include/net/devlink.h +76 −0
  2. include/uapi/linux/devlink.h +8 −0
  3. net/core/devlink.c +501 −0
include/net/devlink.h+76−0
@@ -423,6 +423,8 @@ struct devlink_region; · 422 unmodified lines
423 423
424typedef void devlink_snapshot_data_dest_t(const void *data);424typedef void devlink_snapshot_data_dest_t(const void *data);
425 425
426struct devlink_health_buffer;
427
426struct devlink_ops {428struct devlink_ops {
427 int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack);429 int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack);
428 int (*port_type_set)(struct devlink_port *devlink_port,430 int (*port_type_set)(struct devlink_port *devlink_port,
@@ -584,6 +586,22 @@ int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, · 155 unmodified lines
584 u8 *data, u32 snapshot_id,586 u8 *data, u32 snapshot_id,
585 devlink_snapshot_data_dest_t *data_destructor);587 devlink_snapshot_data_dest_t *data_destructor);
586 588
589int devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer,
590 int attrtype);
591void devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer);
592void devlink_health_buffer_nest_cancel(struct devlink_health_buffer *buffer);
593int devlink_health_buffer_put_object_name(struct devlink_health_buffer *buffer,
594 char *name);
595int devlink_health_buffer_put_value_u8(struct devlink_health_buffer *buffer,
596 u8 value);
597int devlink_health_buffer_put_value_u32(struct devlink_health_buffer *buffer,
598 u32 value);
599int devlink_health_buffer_put_value_u64(struct devlink_health_buffer *buffer,
600 u64 value);
601int devlink_health_buffer_put_value_string(struct devlink_health_buffer *buffer,
602 char *name);
603int devlink_health_buffer_put_value_data(struct devlink_health_buffer *buffer,
604 void *data, int len);
587#else605#else
588 606
589static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,607static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
@@ -844,6 +862,64 @@ devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, · 254 unmodified lines
844 return 0;862 return 0;
845}863}
846 864
865static inline int
866devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer,
867 int attrtype)
868{
869 return 0;
870}
871
872static inline void
873devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer)
874{
875}
876
877static inline void
878devlink_health_buffer_nest_cancel(struct devlink_health_buffer *buffer)
879{
880}
881
882static inline int
883devlink_health_buffer_put_object_name(struct devlink_health_buffer *buffer,
884 char *name)
885{
886 return 0;
887}
888
889static inline int
890devlink_health_buffer_put_value_u8(struct devlink_health_buffer *buffer,
891 u8 value)
892{
893 return 0;
894}
895
896static inline int
897devlink_health_buffer_put_value_u32(struct devlink_health_buffer *buffer,
898 u32 value)
899{
900 return 0;
901}
902
903static inline int
904devlink_health_buffer_put_value_u64(struct devlink_health_buffer *buffer,
905 u64 value)
906{
907 return 0;
908}
909
910static inline int
911devlink_health_buffer_put_value_string(struct devlink_health_buffer *buffer,
912 char *name)
913{
914 return 0;
915}
916
917static inline int
918devlink_health_buffer_put_value_data(struct devlink_health_buffer *buffer,
919 void *data, int len)
920{
921 return 0;
922}
847#endif923#endif
848 924
849#endif /* _NET_DEVLINK_H_ */925#endif /* _NET_DEVLINK_H_ */
include/uapi/linux/devlink.h+8−0
@@ -285,6 +285,14 @@ enum devlink_attr { · 284 unmodified lines
285 DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */285 DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */
286 DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */286 DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */
287 287
288 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT, /* nested */
289 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR, /* nested */
290 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_NAME, /* string */
291 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE, /* nested */
292 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_ARRAY, /* nested */
293 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, /* u8 */
294 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, /* dynamic */
295
288 /* add new attributes above here, update the policy in devlink.c */296 /* add new attributes above here, update the policy in devlink.c */
289 297
290 __DEVLINK_ATTR_MAX,298 __DEVLINK_ATTR_MAX,
net/core/devlink.c+501−0
@@ -3597,6 +3597,507 @@ out: · 3596 unmodified lines
3597 return 0;3597 return 0;
3598}3598}
3599 3599
3600#define DEVLINK_HEALTH_BUFFER_SIZE (4096 - GENL_HDRLEN)
3601#define DEVLINK_HEALTH_BUFFER_DATA_SIZE (DEVLINK_HEALTH_BUFFER_SIZE / 2)
3602#define DEVLINK_HEALTH_SIZE_TO_BUFFERS(size) DIV_ROUND_UP(size, DEVLINK_HEALTH_BUFFER_DATA_SIZE)
3603#define DEVLINK_HEALTH_BUFFER_MAX_CHUNK 1024
3604
3605struct devlink_health_buffer {
3606 void *data;
3607 u64 offset;
3608 u64 bytes_left;
3609 u64 bytes_left_metadata;
3610 u64 max_nested_depth;
3611 u64 curr_nest;
3612};
3613
3614struct devlink_health_buffer_desc {
3615 int attrtype;
3616 u16 len;
3617 u8 nla_type;
3618 u8 nest_end;
3619 int value[0];
3620};
3621
3622static void
3623devlink_health_buffers_reset(struct devlink_health_buffer **buffers_list,
3624 u64 num_of_buffers)
3625{
3626 u64 i;
3627
3628 for (i = 0; i < num_of_buffers; i++) {
3629 memset(buffers_list[i]->data, 0, DEVLINK_HEALTH_BUFFER_SIZE);
3630 buffers_list[i]->offset = 0;
3631 buffers_list[i]->bytes_left = DEVLINK_HEALTH_BUFFER_DATA_SIZE;
3632 buffers_list[i]->bytes_left_metadata =
3633 DEVLINK_HEALTH_BUFFER_DATA_SIZE;
3634 buffers_list[i]->max_nested_depth = 0;
3635 buffers_list[i]->curr_nest = 0;
3636 }
3637}
3638
3639static void
3640devlink_health_buffers_destroy(struct devlink_health_buffer **buffers_list,
3641 u64 size);
3642
3643static struct devlink_health_buffer **
3644devlink_health_buffers_create(u64 size)
3645{
3646 struct devlink_health_buffer **buffers_list;
3647 u64 num_of_buffers = DEVLINK_HEALTH_SIZE_TO_BUFFERS(size);
3648 u64 i;
3649
3650 buffers_list = kcalloc(num_of_buffers,
3651 sizeof(struct devlink_health_buffer *),
3652 GFP_KERNEL);
3653 if (!buffers_list)
3654 return NULL;
3655
3656 for (i = 0; i < num_of_buffers; i++) {
3657 struct devlink_health_buffer *buffer;
3658 void *data;
3659
3660 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
3661 data = kzalloc(DEVLINK_HEALTH_BUFFER_SIZE, GFP_KERNEL);
3662 if (!buffer || !data) {
3663 kfree(buffer);
3664 kfree(data);
3665 goto buffers_cleanup;
3666 }
3667 buffers_list[i] = buffer;
3668 buffer->data = data;
3669 }
3670 devlink_health_buffers_reset(buffers_list, num_of_buffers);
3671
3672 return buffers_list;
3673
3674buffers_cleanup:
3675 devlink_health_buffers_destroy(buffers_list, --i);
3676 kfree(buffers_list);
3677 return NULL;
3678}
3679
3680static void
3681devlink_health_buffers_destroy(struct devlink_health_buffer **buffers_list,
3682 u64 num_of_buffers)
3683{
3684 u64 i;
3685
3686 for (i = 0; i < num_of_buffers; i++) {
3687 kfree(buffers_list[i]->data);
3688 kfree(buffers_list[i]);
3689 }
3690}
3691
3692void
3693devlink_health_buffer_offset_inc(struct devlink_health_buffer *buffer,
3694 int len)
3695{
3696 buffer->offset += len;
3697}
3698
3699/* In order to store a nest, need two descriptors, for start and end */
3700#define DEVLINK_HEALTH_BUFFER_NEST_SIZE (sizeof(struct devlink_health_buffer_desc) * 2)
3701
3702int devlink_health_buffer_verify_len(struct devlink_health_buffer *buffer,
3703 int len, int metadata_len)
3704{
3705 if (len > DEVLINK_HEALTH_BUFFER_DATA_SIZE)
3706 return -EINVAL;
3707
3708 if (buffer->bytes_left < len ||
3709 buffer->bytes_left_metadata < metadata_len)
3710 return -ENOMEM;
3711
3712 return 0;
3713}
3714
3715static struct devlink_health_buffer_desc *
3716devlink_health_buffer_get_desc_from_offset(struct devlink_health_buffer *buffer)
3717{
3718 return buffer->data + buffer->offset;
3719}
3720
3721int
3722devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer,
3723 int attrtype)
3724{
3725 struct devlink_health_buffer_desc *desc;
3726 int err;
3727
3728 err = devlink_health_buffer_verify_len(buffer, 0,
3729 DEVLINK_HEALTH_BUFFER_NEST_SIZE);
3730 if (err)
3731 return err;
3732
3733 if (attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT &&
3734 attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR &&
3735 attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE &&
3736 attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_ARRAY)
3737 return -EINVAL;
3738
3739 desc = devlink_health_buffer_get_desc_from_offset(buffer);
3740
3741 desc->attrtype = attrtype;
3742 buffer->bytes_left_metadata -= DEVLINK_HEALTH_BUFFER_NEST_SIZE;
3743 devlink_health_buffer_offset_inc(buffer, sizeof(*desc));
3744
3745 buffer->curr_nest++;
3746 buffer->max_nested_depth = max(buffer->max_nested_depth,
3747 buffer->curr_nest);
3748
3749 return 0;
3750}
3751EXPORT_SYMBOL_GPL(devlink_health_buffer_nest_start);
3752
3753enum devlink_health_buffer_nest_end_cancel {
3754 DEVLINK_HEALTH_BUFFER_NEST_END = 1,
3755 DEVLINK_HEALTH_BUFFER_NEST_CANCEL,
3756};
3757
3758static void
3759devlink_health_buffer_nest_end_cancel(struct devlink_health_buffer *buffer,
3760 enum devlink_health_buffer_nest_end_cancel nest)
3761{
3762 struct devlink_health_buffer_desc *desc;
3763
3764 WARN_ON(!buffer->curr_nest);
3765 buffer->curr_nest--;
3766
3767 desc = devlink_health_buffer_get_desc_from_offset(buffer);
3768 desc->nest_end = nest;
3769 devlink_health_buffer_offset_inc(buffer, sizeof(*desc));
3770}
3771
3772void devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer)
3773{
3774 devlink_health_buffer_nest_end_cancel(buffer,
3775 DEVLINK_HEALTH_BUFFER_NEST_END);
3776}
3777EXPORT_SYMBOL_GPL(devlink_health_buffer_nest_end);
3778
3779void devlink_health_buffer_nest_cancel(struct devlink_health_buffer *buffer)
3780{
3781 devlink_health_buffer_nest_end_cancel(buffer,
3782 DEVLINK_HEALTH_BUFFER_NEST_CANCEL);
3783}
3784EXPORT_SYMBOL_GPL(devlink_health_buffer_nest_cancel);
3785
3786int
3787devlink_health_buffer_put_object_name(struct devlink_health_buffer *buffer,
3788 char *name)
3789{
3790 struct devlink_health_buffer_desc *desc;
3791 int err;
3792
3793 err = devlink_health_buffer_verify_len(buffer, strlen(name) + 1,
3794 sizeof(*desc));
3795 if (err)
3796 return err;
3797
3798 desc = devlink_health_buffer_get_desc_from_offset(buffer);
3799 desc->attrtype = DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_NAME;
3800 desc->nla_type = NLA_NUL_STRING;
3801 desc->len = strlen(name) + 1;
3802 memcpy(&desc->value, name, desc->len);
3803 devlink_health_buffer_offset_inc(buffer, sizeof(*desc) + desc->len);
3804
3805 buffer->bytes_left_metadata -= sizeof(*desc);
3806 buffer->bytes_left -= (strlen(name) + 1);
3807
3808 return 0;
3809}
3810EXPORT_SYMBOL_GPL(devlink_health_buffer_put_object_name);
3811
3812static int
3813devlink_health_buffer_put_value(struct devlink_health_buffer *buffer,
3814 u8 nla_type, void *value, int len)
3815{
3816 struct devlink_health_buffer_desc *desc;
3817 int err;
3818
3819 err = devlink_health_buffer_verify_len(buffer, len, sizeof(*desc));
3820 if (err)
3821 return err;
3822
3823 desc = devlink_health_buffer_get_desc_from_offset(buffer);
3824 desc->attrtype = DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA;
3825 desc->nla_type = nla_type;
3826 desc->len = len;
3827 memcpy(&desc->value, value, len);
3828 devlink_health_buffer_offset_inc(buffer, sizeof(*desc) + desc->len);
3829
3830 buffer->bytes_left_metadata -= sizeof(*desc);
3831 buffer->bytes_left -= len;
3832
3833 return 0;
3834}
3835
3836int
3837devlink_health_buffer_put_value_u8(struct devlink_health_buffer *buffer,
3838 u8 value)
3839{
3840 int err;
3841
3842 err = devlink_health_buffer_put_value(buffer, NLA_U8, &value,
3843 sizeof(value));
3844 if (err)
3845 return err;
3846
3847 return 0;
3848}
3849EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_u8);
3850
3851int
3852devlink_health_buffer_put_value_u32(struct devlink_health_buffer *buffer,
3853 u32 value)
3854{
3855 int err;
3856
3857 err = devlink_health_buffer_put_value(buffer, NLA_U32, &value,
3858 sizeof(value));
3859 if (err)
3860 return err;
3861
3862 return 0;
3863}
3864EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_u32);
3865
3866int
3867devlink_health_buffer_put_value_u64(struct devlink_health_buffer *buffer,
3868 u64 value)
3869{
3870 int err;
3871
3872 err = devlink_health_buffer_put_value(buffer, NLA_U64, &value,
3873 sizeof(value));
3874 if (err)
3875 return err;
3876
3877 return 0;
3878}
3879EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_u64);
3880
3881int
3882devlink_health_buffer_put_value_string(struct devlink_health_buffer *buffer,
3883 char *name)
3884{
3885 int err;
3886
3887 if (strlen(name) + 1 > DEVLINK_HEALTH_BUFFER_MAX_CHUNK)
3888 return -EINVAL;
3889
3890 err = devlink_health_buffer_put_value(buffer, NLA_NUL_STRING, name,
3891 strlen(name) + 1);
3892 if (err)
3893 return err;
3894
3895 return 0;
3896}
3897EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_string);
3898
3899int
3900devlink_health_buffer_put_value_data(struct devlink_health_buffer *buffer,
3901 void *data, int len)
3902{
3903 int err;
3904
3905 if (len > DEVLINK_HEALTH_BUFFER_MAX_CHUNK)
3906 return -EINVAL;
3907
3908 err = devlink_health_buffer_put_value(buffer, NLA_BINARY, data, len);
3909 if (err)
3910 return err;
3911
3912 return 0;
3913}
3914EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_data);
3915
3916static int
3917devlink_health_buffer_fill_data(struct sk_buff *skb,
3918 struct devlink_health_buffer_desc *desc)
3919{
3920 int err = -EINVAL;
3921
3922 switch (desc->nla_type) {
3923 case NLA_U8:
3924 err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA,
3925 *(u8 *)desc->value);
3926 break;
3927 case NLA_U32:
3928 err = nla_put_u32(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA,
3929 *(u32 *)desc->value);
3930 break;
3931 case NLA_U64:
3932 err = nla_put_u64_64bit(skb,
3933 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA,
3934 *(u64 *)desc->value, DEVLINK_ATTR_PAD);
3935 break;
3936 case NLA_NUL_STRING:
3937 err = nla_put_string(skb,
3938 DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA,
3939 (char *)&desc->value);
3940 break;
3941 case NLA_BINARY:
3942 err = nla_put(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA,
3943 desc->len, (void *)&desc->value);
3944 break;
3945 }
3946
3947 return err;
3948}
3949
3950static int
3951devlink_health_buffer_fill_type(struct sk_buff *skb,
3952 struct devlink_health_buffer_desc *desc)
3953{
3954 int err = -EINVAL;
3955
3956 switch (desc->nla_type) {
3957 case NLA_U8:
3958 err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE,
3959 NLA_U8);
3960 break;
3961 case NLA_U32:
3962 err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE,
3963 NLA_U32);
3964 break;
3965 case NLA_U64:
3966 err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE,
3967 NLA_U64);
3968 break;
3969 case NLA_NUL_STRING:
3970 err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE,
3971 NLA_NUL_STRING);
3972 break;
3973 case NLA_BINARY:
3974 err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE,
3975 NLA_BINARY);
3976 break;
3977 }
3978
3979 return err;
3980}
3981
3982static inline struct devlink_health_buffer_desc *
3983devlink_health_buffer_get_next_desc(struct devlink_health_buffer_desc *desc)
3984{
3985 return (void *)&desc->value + desc->len;
3986}
3987
3988static int
3989devlink_health_buffer_prepare_skb(struct sk_buff *skb,
3990 struct devlink_health_buffer *buffer)
3991{
3992 struct devlink_health_buffer_desc *last_desc, *desc;
3993 struct nlattr **buffer_nlattr;
3994 int err;
3995 int i = 0;
3996
3997 buffer_nlattr = kcalloc(buffer->max_nested_depth,
3998 sizeof(*buffer_nlattr), GFP_KERNEL);
3999 if (!buffer_nlattr)
4000 return -EINVAL;
4001
4002 last_desc = devlink_health_buffer_get_desc_from_offset(buffer);
4003 desc = buffer->data;
4004 while (desc != last_desc) {
4005 switch (desc->attrtype) {
4006 case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT:
4007 case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR:
4008 case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE:
4009 case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_ARRAY:
4010 buffer_nlattr[i] = nla_nest_start(skb, desc->attrtype);
4011 if (!buffer_nlattr[i])
4012 goto nla_put_failure;
4013 i++;
4014 break;
4015 case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA:
4016 err = devlink_health_buffer_fill_data(skb, desc);
4017 if (err)
4018 goto nla_put_failure;
4019 err = devlink_health_buffer_fill_type(skb, desc);
4020 if (err)
4021 goto nla_put_failure;
4022 break;
4023 case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_NAME:
4024 err = nla_put_string(skb, desc->attrtype,
4025 (char *)&desc->value);
4026 if (err)
4027 goto nla_put_failure;
4028 break;
4029 default:
4030 WARN_ON(!desc->nest_end);
4031 WARN_ON(i <= 0);
4032 if (desc->nest_end == DEVLINK_HEALTH_BUFFER_NEST_END)
4033 nla_nest_end(skb, buffer_nlattr[--i]);
4034 else
4035 nla_nest_cancel(skb, buffer_nlattr[--i]);
4036 break;
4037 }
4038 desc = devlink_health_buffer_get_next_desc(desc);
4039 }
4040
4041 return 0;
4042
4043nla_put_failure:
4044 kfree(buffer_nlattr);
4045 return err;
4046}
4047
4048static int
4049devlink_health_buffer_snd(struct genl_info *info,
4050 enum devlink_command cmd, int flags,
4051 struct devlink_health_buffer **buffers_array,
4052 u64 num_of_buffers)
4053{
4054 struct sk_buff *skb;
4055 struct nlmsghdr *nlh;
4056 void *hdr;
4057 int err;
4058 u64 i;
4059
4060 for (i = 0; i < num_of_buffers; i++) {
4061 /* Skip buffer if driver did not fill it up with any data */
4062 if (!buffers_array[i]->offset)
4063 continue;
4064
4065 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4066 if (!skb)
4067 return -ENOMEM;
4068
4069 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4070 &devlink_nl_family, NLM_F_MULTI, cmd);
4071 if (!hdr)
4072 goto nla_put_failure;
4073
4074 err = devlink_health_buffer_prepare_skb(skb, buffers_array[i]);
4075 if (err)
4076 goto nla_put_failure;
4077
4078 genlmsg_end(skb, hdr);
4079 err = genlmsg_reply(skb, info);
4080 if (err)
4081 return err;
4082 }
4083
4084 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4085 if (!skb)
4086 return -ENOMEM;
4087 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4088 NLMSG_DONE, 0, flags | NLM_F_MULTI);
4089 err = genlmsg_reply(skb, info);
4090 if (err)
4091 return err;
4092
4093 return 0;
4094
4095nla_put_failure:
4096 err = -EIO;
4097 nlmsg_free(skb);
4098 return err;
4099}
4100
3600static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {4101static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
3601 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },4102 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
3602 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },4103 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },