@@ -247,6 +247,107 @@ func (dlrs *DevlinkResources) parseAttributes(attrs map[uint16]syscall.NetlinkRo
247
247
return nil
248
248
}
249
249
250
+ // DevlinkParam represents parameter of the device
251
+ type DevlinkParam struct {
252
+ Name string
253
+ IsGeneric bool
254
+ Type uint8 // possible values are in nl.DEVLINK_PARAM_TYPE_* constants
255
+ Values []DevlinkParamValue
256
+ }
257
+
258
+ // DevlinkParamValue contains values of the parameter
259
+ // Data field contains specific type which can be casted by unsing info from the DevlinkParam.Type field
260
+ type DevlinkParamValue struct {
261
+ rawData []byte
262
+ Data interface {}
263
+ CMODE uint8 // possible values are in nl.DEVLINK_PARAM_CMODE_* constants
264
+ }
265
+
266
+ // parseAttributes parses provided Netlink Attributes and populates DevlinkParam, returns error if occured
267
+ func (dlp * DevlinkParam ) parseAttributes (attrs []syscall.NetlinkRouteAttr ) error {
268
+ var valuesList [][]syscall.NetlinkRouteAttr
269
+ for _ , attr := range attrs {
270
+ switch attr .Attr .Type {
271
+ case nl .DEVLINK_ATTR_PARAM :
272
+ nattrs , err := nl .ParseRouteAttr (attr .Value )
273
+ if err != nil {
274
+ return err
275
+ }
276
+ for _ , nattr := range nattrs {
277
+ switch nattr .Attr .Type {
278
+ case nl .DEVLINK_ATTR_PARAM_NAME :
279
+ dlp .Name = nl .BytesToString (nattr .Value )
280
+ case nl .DEVLINK_ATTR_PARAM_GENERIC :
281
+ dlp .IsGeneric = true
282
+ case nl .DEVLINK_ATTR_PARAM_TYPE :
283
+ if len (nattr .Value ) == 1 {
284
+ dlp .Type = nattr .Value [0 ]
285
+ }
286
+ case nl .DEVLINK_ATTR_PARAM_VALUES_LIST :
287
+ nnattrs , err := nl .ParseRouteAttr (nattr .Value )
288
+ if err != nil {
289
+ return err
290
+ }
291
+ valuesList = append (valuesList , nnattrs )
292
+ }
293
+ }
294
+ }
295
+ }
296
+ for _ , valAttr := range valuesList {
297
+ v := DevlinkParamValue {}
298
+ if err := v .parseAttributes (valAttr , dlp .Type ); err != nil {
299
+ return err
300
+ }
301
+ dlp .Values = append (dlp .Values , v )
302
+ }
303
+ return nil
304
+ }
305
+
306
+ func (dlpv * DevlinkParamValue ) parseAttributes (attrs []syscall.NetlinkRouteAttr , paramType uint8 ) error {
307
+ for _ , attr := range attrs {
308
+ nattrs , err := nl .ParseRouteAttr (attr .Value )
309
+ if err != nil {
310
+ return err
311
+ }
312
+ var rawData []byte
313
+ for _ , nattr := range nattrs {
314
+ switch nattr .Attr .Type {
315
+ case nl .DEVLINK_ATTR_PARAM_VALUE_DATA :
316
+ rawData = nattr .Value
317
+ case nl .DEVLINK_ATTR_PARAM_VALUE_CMODE :
318
+ if len (nattr .Value ) == 1 {
319
+ dlpv .CMODE = nattr .Value [0 ]
320
+ }
321
+ }
322
+ }
323
+ switch paramType {
324
+ case nl .DEVLINK_PARAM_TYPE_U8 :
325
+ dlpv .Data = uint8 (0 )
326
+ if rawData != nil && len (rawData ) == 1 {
327
+ dlpv .Data = uint8 (rawData [0 ])
328
+ }
329
+ case nl .DEVLINK_PARAM_TYPE_U16 :
330
+ dlpv .Data = uint16 (0 )
331
+ if rawData != nil {
332
+ dlpv .Data = native .Uint16 (rawData )
333
+ }
334
+ case nl .DEVLINK_PARAM_TYPE_U32 :
335
+ dlpv .Data = uint32 (0 )
336
+ if rawData != nil {
337
+ dlpv .Data = native .Uint32 (rawData )
338
+ }
339
+ case nl .DEVLINK_PARAM_TYPE_STRING :
340
+ dlpv .Data = ""
341
+ if rawData != nil {
342
+ dlpv .Data = nl .BytesToString (rawData )
343
+ }
344
+ case nl .DEVLINK_PARAM_TYPE_BOOL :
345
+ dlpv .Data = rawData != nil
346
+ }
347
+ }
348
+ return nil
349
+ }
350
+
250
351
func parseDevLinkDeviceList (msgs [][]byte ) ([]* DevlinkDevice , error ) {
251
352
devices := make ([]* DevlinkDevice , 0 , len (msgs ))
252
353
for _ , m := range msgs {
@@ -635,6 +736,144 @@ func (h *Handle) DevlinkGetDeviceResources(bus string, device string) (*DevlinkR
635
736
return & resources , nil
636
737
}
637
738
739
+ // DevlinkGetDeviceParams returns parameters for devlink device
740
+ // Equivalent to: `devlink dev param show <bus>/<device>`
741
+ func (h * Handle ) DevlinkGetDeviceParams (bus string , device string ) ([]* DevlinkParam , error ) {
742
+ _ , req , err := h .createCmdReq (nl .DEVLINK_CMD_PARAM_GET , bus , device )
743
+ if err != nil {
744
+ return nil , err
745
+ }
746
+ req .Flags |= unix .NLM_F_DUMP
747
+ respmsg , err := req .Execute (unix .NETLINK_GENERIC , 0 )
748
+ if err != nil {
749
+ return nil , err
750
+ }
751
+ var params []* DevlinkParam
752
+ for _ , m := range respmsg {
753
+ attrs , err := nl .ParseRouteAttr (m [nl .SizeofGenlmsg :])
754
+ if err != nil {
755
+ return nil , err
756
+ }
757
+ p := & DevlinkParam {}
758
+ if err := p .parseAttributes (attrs ); err != nil {
759
+ return nil , err
760
+ }
761
+ params = append (params , p )
762
+ }
763
+
764
+ return params , nil
765
+ }
766
+
767
+ // DevlinkGetDeviceParams returns parameters for devlink device
768
+ // Equivalent to: `devlink dev param show <bus>/<device>`
769
+ func DevlinkGetDeviceParams (bus string , device string ) ([]* DevlinkParam , error ) {
770
+ return pkgHandle .DevlinkGetDeviceParams (bus , device )
771
+ }
772
+
773
+ // DevlinkGetDeviceParamByName returns specific parameter for devlink device
774
+ // Equivalent to: `devlink dev param show <bus>/<device> name <param>`
775
+ func (h * Handle ) DevlinkGetDeviceParamByName (bus string , device string , param string ) (* DevlinkParam , error ) {
776
+ _ , req , err := h .createCmdReq (nl .DEVLINK_CMD_PARAM_GET , bus , device )
777
+ if err != nil {
778
+ return nil , err
779
+ }
780
+ req .AddData (nl .NewRtAttr (nl .DEVLINK_ATTR_PARAM_NAME , nl .ZeroTerminated (param )))
781
+ respmsg , err := req .Execute (unix .NETLINK_GENERIC , 0 )
782
+ if err != nil {
783
+ return nil , err
784
+ }
785
+ if len (respmsg ) == 0 {
786
+ return nil , fmt .Errorf ("unexpected response" )
787
+ }
788
+ attrs , err := nl .ParseRouteAttr (respmsg [0 ][nl .SizeofGenlmsg :])
789
+ if err != nil {
790
+ return nil , err
791
+ }
792
+ p := & DevlinkParam {}
793
+ if err := p .parseAttributes (attrs ); err != nil {
794
+ return nil , err
795
+ }
796
+ return p , nil
797
+ }
798
+
799
+ // DevlinkGetDeviceParamByName returns specific parameter for devlink device
800
+ // Equivalent to: `devlink dev param show <bus>/<device> name <param>`
801
+ func DevlinkGetDeviceParamByName (bus string , device string , param string ) (* DevlinkParam , error ) {
802
+ return pkgHandle .DevlinkGetDeviceParamByName (bus , device , param )
803
+ }
804
+
805
+ // DevlinkSetDeviceParam set specific parameter for devlink device
806
+ // Equivalent to: `devlink dev param set <bus>/<device> name <param> cmode <cmode> value <value>`
807
+ // cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants
808
+ // value argument should have one of the following types: uint8, uint16, uint32, string, bool
809
+ func (h * Handle ) DevlinkSetDeviceParam (bus string , device string , param string , cmode uint8 , value interface {}) error {
810
+ // retrive the param type
811
+ p , err := h .DevlinkGetDeviceParamByName (bus , device , param )
812
+ if err != nil {
813
+ return fmt .Errorf ("failed to get device param: %v" , err )
814
+ }
815
+ paramType := p .Type
816
+
817
+ _ , req , err := h .createCmdReq (nl .DEVLINK_CMD_PARAM_SET , bus , device )
818
+ if err != nil {
819
+ return err
820
+ }
821
+ req .AddData (nl .NewRtAttr (nl .DEVLINK_ATTR_PARAM_TYPE , nl .Uint8Attr (paramType )))
822
+ req .AddData (nl .NewRtAttr (nl .DEVLINK_ATTR_PARAM_NAME , nl .ZeroTerminated (param )))
823
+ req .AddData (nl .NewRtAttr (nl .DEVLINK_ATTR_PARAM_VALUE_CMODE , nl .Uint8Attr (cmode )))
824
+
825
+ var valueAsBytes []byte
826
+ switch paramType {
827
+ case nl .DEVLINK_PARAM_TYPE_U8 :
828
+ v , ok := value .(uint8 )
829
+ if ! ok {
830
+ return fmt .Errorf ("unepected value type required: uint8, actual: %T" , value )
831
+ }
832
+ valueAsBytes = nl .Uint8Attr (v )
833
+ case nl .DEVLINK_PARAM_TYPE_U16 :
834
+ v , ok := value .(uint16 )
835
+ if ! ok {
836
+ return fmt .Errorf ("unepected value type required: uint16, actual: %T" , value )
837
+ }
838
+ valueAsBytes = nl .Uint16Attr (v )
839
+ case nl .DEVLINK_PARAM_TYPE_U32 :
840
+ v , ok := value .(uint32 )
841
+ if ! ok {
842
+ return fmt .Errorf ("unepected value type required: uint32, actual: %T" , value )
843
+ }
844
+ valueAsBytes = nl .Uint32Attr (v )
845
+ case nl .DEVLINK_PARAM_TYPE_STRING :
846
+ v , ok := value .(string )
847
+ if ! ok {
848
+ return fmt .Errorf ("unepected value type required: string, actual: %T" , value )
849
+ }
850
+ valueAsBytes = nl .ZeroTerminated (v )
851
+ case nl .DEVLINK_PARAM_TYPE_BOOL :
852
+ v , ok := value .(bool )
853
+ if ! ok {
854
+ return fmt .Errorf ("unepected value type required: bool, actual: %T" , value )
855
+ }
856
+ if v {
857
+ valueAsBytes = []byte {}
858
+ }
859
+ default :
860
+ return fmt .Errorf ("unsupported parameter type: %d" , paramType )
861
+ }
862
+ if valueAsBytes != nil {
863
+ req .AddData (nl .NewRtAttr (nl .DEVLINK_ATTR_PARAM_VALUE_DATA , valueAsBytes ))
864
+ }
865
+ _ , err = req .Execute (unix .NETLINK_GENERIC , 0 )
866
+ return err
867
+ }
868
+
869
+ // DevlinkSetDeviceParam set specific parameter for devlink device
870
+ // Equivalent to: `devlink dev param set <bus>/<device> name <param> cmode <cmode> value <value>`
871
+ // cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants
872
+ // value argument should have one of the following types: uint8, uint16, uint32, string, bool
873
+ func DevlinkSetDeviceParam (bus string , device string , param string , cmode uint8 , value interface {}) error {
874
+ return pkgHandle .DevlinkSetDeviceParam (bus , device , param , cmode , value )
875
+ }
876
+
638
877
// DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
639
878
// otherwise returns an error code.
640
879
func DevLinkGetPortByIndex (Bus string , Device string , PortIndex uint32 ) (* DevlinkPort , error ) {
0 commit comments