@@ -18,6 +18,7 @@ type RdmaLinkAttrs struct {
18
18
FirmwareVersion string
19
19
NodeGuid string
20
20
SysImageGuid string
21
+ NumPorts uint32
21
22
}
22
23
23
24
// Link represents a rdma device from netlink.
@@ -69,6 +70,11 @@ func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) {
69
70
r := bytes .NewReader (value )
70
71
binary .Read (r , nl .NativeEndian (), & sysGuid )
71
72
link .Attrs .SysImageGuid = uint64ToGuidString (sysGuid )
73
+ case nl .RDMA_NLDEV_ATTR_PORT_INDEX :
74
+ var availablePort uint32
75
+ r := bytes .NewReader (value )
76
+ binary .Read (r , nl .NativeEndian (), & availablePort )
77
+ link .Attrs .NumPorts = availablePort
72
78
}
73
79
if (len % 4 ) != 0 {
74
80
// Skip pad bytes
@@ -345,3 +351,212 @@ func (h *Handle) RdmaLinkAdd(linkName string, linkType string, netdev string) er
345
351
_ , err := req .Execute (unix .NETLINK_RDMA , 0 )
346
352
return err
347
353
}
354
+
355
+ // RdmaResource represents a rdma device resource tracking summaries
356
+ type RdmaResource struct {
357
+ Index uint32
358
+ Name string
359
+ RdmaResourceSummaryEntries map [string ]uint64
360
+ }
361
+
362
+ // RdmaResourceList list rdma resource tracking information
363
+ // Returns all rdma devices resource tracking summary on success or returns error
364
+ // otherwise.
365
+ // Equivalent to: `rdma resource'
366
+ func RdmaResourceList () ([]* RdmaResource , error ) {
367
+ return pkgHandle .RdmaResourceList ()
368
+ }
369
+
370
+ // RdmaResourceList list rdma resource tracking information
371
+ // Returns all rdma devices resource tracking summary on success or returns error
372
+ // otherwise.
373
+ // Equivalent to: `rdma resource'
374
+ func (h * Handle ) RdmaResourceList () ([]* RdmaResource , error ) {
375
+ proto := getProtoField (nl .RDMA_NL_NLDEV , nl .RDMA_NLDEV_CMD_RES_GET )
376
+ req := h .newNetlinkRequest (proto , unix .NLM_F_ACK | unix .NLM_F_DUMP )
377
+
378
+ msgs , err := req .Execute (unix .NETLINK_RDMA , 0 )
379
+ if err != nil {
380
+ return nil , err
381
+ }
382
+ if len (msgs ) == 0 {
383
+ return nil , fmt .Errorf ("No valid response from kernel" )
384
+ }
385
+ var rdmaResources []* RdmaResource
386
+ for _ , msg := range msgs {
387
+ res , err := executeOneGetRdmaResourceList (msg )
388
+ if err != nil {
389
+ return nil , err
390
+ }
391
+ rdmaResources = append (rdmaResources , res )
392
+ }
393
+ return rdmaResources , nil
394
+ }
395
+
396
+ func parseRdmaCounters (counterType uint16 , data []byte ) (map [string ]uint64 , error ) {
397
+ var counterKeyType , counterValueType uint16
398
+ switch counterType {
399
+ case nl .RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY :
400
+ counterKeyType = nl .RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
401
+ counterValueType = nl .RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
402
+ case nl .RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY :
403
+ counterKeyType = nl .RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
404
+ counterValueType = nl .RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
405
+ default :
406
+ return nil , fmt .Errorf ("Invalid counter type: %d" , counterType )
407
+ }
408
+ counters := make (map [string ]uint64 )
409
+ reader := bytes .NewReader (data )
410
+
411
+ for reader .Len () >= 4 {
412
+ _ , attrType , _ , value := parseNfAttrTLV (reader )
413
+ if attrType != counterType {
414
+ return nil , fmt .Errorf ("Invalid resource summary entry type; %d" , attrType )
415
+ }
416
+
417
+ summaryReader := bytes .NewReader (value )
418
+ for summaryReader .Len () >= 4 {
419
+ _ , attrType , len , value := parseNfAttrTLV (summaryReader )
420
+ if attrType != counterKeyType {
421
+ return nil , fmt .Errorf ("Invalid resource summary entry name type; %d" , attrType )
422
+ }
423
+ name := string (value [0 : len - 1 ])
424
+ // Skip pad bytes
425
+ if (len % 4 ) != 0 {
426
+ summaryReader .Seek (int64 (4 - (len % 4 )), seekCurrent )
427
+ }
428
+ _ , attrType , len , value = parseNfAttrTLV (summaryReader )
429
+ if attrType != counterValueType {
430
+ return nil , fmt .Errorf ("Invalid resource summary entry value type; %d" , attrType )
431
+ }
432
+ counters [name ] = native .Uint64 (value )
433
+ }
434
+ }
435
+ return counters , nil
436
+ }
437
+
438
+ func executeOneGetRdmaResourceList (data []byte ) (* RdmaResource , error ) {
439
+ var res RdmaResource
440
+ reader := bytes .NewReader (data )
441
+ for reader .Len () >= 4 {
442
+ _ , attrType , len , value := parseNfAttrTLV (reader )
443
+
444
+ switch attrType {
445
+ case nl .RDMA_NLDEV_ATTR_DEV_INDEX :
446
+ var Index uint32
447
+ r := bytes .NewReader (value )
448
+ binary .Read (r , nl .NativeEndian (), & Index )
449
+ res .Index = Index
450
+ case nl .RDMA_NLDEV_ATTR_DEV_NAME :
451
+ res .Name = string (value [0 : len - 1 ])
452
+ case nl .RDMA_NLDEV_ATTR_RES_SUMMARY :
453
+ var err error
454
+ res .RdmaResourceSummaryEntries , err = parseRdmaCounters (nl .RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY , value )
455
+ if err != nil {
456
+ return nil , err
457
+ }
458
+ }
459
+ if (len % 4 ) != 0 {
460
+ // Skip pad bytes
461
+ reader .Seek (int64 (4 - (len % 4 )), seekCurrent )
462
+ }
463
+ }
464
+ return & res , nil
465
+ }
466
+
467
+ // RdmaPortStatistic represents a rdma port statistic counter
468
+ type RdmaPortStatistic struct {
469
+ PortIndex uint32
470
+ Statistics map [string ]uint64
471
+ }
472
+
473
+ // RdmaDeviceStatistic represents a rdma device statistic counter
474
+ type RdmaDeviceStatistic struct {
475
+ RdmaPortStatistics []* RdmaPortStatistic
476
+ }
477
+
478
+ // RdmaStatistic get rdma device statistic counters
479
+ // Returns rdma device statistic counters on success or returns error
480
+ // otherwise.
481
+ // Equivalent to: `rdma statistic show link [DEV]'
482
+ func RdmaStatistic (link * RdmaLink ) (* RdmaDeviceStatistic , error ) {
483
+ return pkgHandle .RdmaStatistic (link )
484
+ }
485
+
486
+ // RdmaStatistic get rdma device statistic counters
487
+ // Returns rdma device statistic counters on success or returns error
488
+ // otherwise.
489
+ // Equivalent to: `rdma statistic show link [DEV]'
490
+ func (h * Handle ) RdmaStatistic (link * RdmaLink ) (* RdmaDeviceStatistic , error ) {
491
+ rdmaLinkStatistic := make ([]* RdmaPortStatistic , 0 )
492
+ for portIndex := uint32 (1 ); portIndex <= link .Attrs .NumPorts ; portIndex ++ {
493
+ portStatistic , err := h .RdmaPortStatisticList (link , portIndex )
494
+ if err != nil {
495
+ return nil , err
496
+ }
497
+ rdmaLinkStatistic = append (rdmaLinkStatistic , portStatistic )
498
+ }
499
+ return & RdmaDeviceStatistic {RdmaPortStatistics : rdmaLinkStatistic }, nil
500
+ }
501
+
502
+ // RdmaPortStatisticList get rdma device port statistic counters
503
+ // Returns rdma device port statistic counters on success or returns error
504
+ // otherwise.
505
+ // Equivalent to: `rdma statistic show link [DEV/PORT]'
506
+ func RdmaPortStatisticList (link * RdmaLink , port uint32 ) (* RdmaPortStatistic , error ) {
507
+ return pkgHandle .RdmaPortStatisticList (link , port )
508
+ }
509
+
510
+ // RdmaPortStatisticList get rdma device port statistic counters
511
+ // Returns rdma device port statistic counters on success or returns error
512
+ // otherwise.
513
+ // Equivalent to: `rdma statistic show link [DEV/PORT]'
514
+ func (h * Handle ) RdmaPortStatisticList (link * RdmaLink , port uint32 ) (* RdmaPortStatistic , error ) {
515
+ proto := getProtoField (nl .RDMA_NL_NLDEV , nl .RDMA_NLDEV_CMD_STAT_GET )
516
+ req := h .newNetlinkRequest (proto , unix .NLM_F_ACK | unix .NLM_F_REQUEST )
517
+ b := make ([]byte , 4 )
518
+ native .PutUint32 (b , link .Attrs .Index )
519
+ data := nl .NewRtAttr (nl .RDMA_NLDEV_ATTR_DEV_INDEX , b )
520
+ req .AddData (data )
521
+
522
+ b = make ([]byte , 4 )
523
+ native .PutUint32 (b , port )
524
+ data = nl .NewRtAttr (nl .RDMA_NLDEV_ATTR_PORT_INDEX , b )
525
+ req .AddData (data )
526
+
527
+ msgs , err := req .Execute (unix .NETLINK_RDMA , 0 )
528
+ if err != nil {
529
+ return nil , err
530
+ }
531
+ if len (msgs ) != 1 {
532
+ return nil , fmt .Errorf ("No valid response from kernel" )
533
+ }
534
+ return executeOneGetRdmaPortStatistics (msgs [0 ])
535
+ }
536
+
537
+ func executeOneGetRdmaPortStatistics (data []byte ) (* RdmaPortStatistic , error ) {
538
+ var stat RdmaPortStatistic
539
+ reader := bytes .NewReader (data )
540
+ for reader .Len () >= 4 {
541
+ _ , attrType , len , value := parseNfAttrTLV (reader )
542
+
543
+ switch attrType {
544
+ case nl .RDMA_NLDEV_ATTR_PORT_INDEX :
545
+ var Index uint32
546
+ r := bytes .NewReader (value )
547
+ binary .Read (r , nl .NativeEndian (), & Index )
548
+ stat .PortIndex = Index
549
+ case nl .RDMA_NLDEV_ATTR_STAT_HWCOUNTERS :
550
+ var err error
551
+ stat .Statistics , err = parseRdmaCounters (nl .RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY , value )
552
+ if err != nil {
553
+ return nil , err
554
+ }
555
+ }
556
+ if (len % 4 ) != 0 {
557
+ // Skip pad bytes
558
+ reader .Seek (int64 (4 - (len % 4 )), seekCurrent )
559
+ }
560
+ }
561
+ return & stat , nil
562
+ }
0 commit comments