@@ -523,6 +523,31 @@ func (s *StationInfo) attributes() []netlink.Attribute {
523
523
}
524
524
}
525
525
526
+ func (s * SurveyInfo ) attributes () []netlink.Attribute {
527
+ attributes := []netlink.Attribute {
528
+ {Type : unix .NL80211_SURVEY_INFO_FREQUENCY , Data : nlenc .Uint32Bytes (uint32 (s .Frequency ))},
529
+ {Type : unix .NL80211_SURVEY_INFO_NOISE , Data : []byte {byte (int8 (s .Noise ))}},
530
+ }
531
+ if s .InUse {
532
+ attributes = append (attributes , netlink.Attribute {Type : unix .NL80211_SURVEY_INFO_IN_USE })
533
+ }
534
+ attributes = append (attributes , []netlink.Attribute {
535
+ {Type : unix .NL80211_SURVEY_INFO_TIME , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTime / time .Millisecond ))},
536
+ {Type : unix .NL80211_SURVEY_INFO_TIME_BUSY , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTimeBusy / time .Millisecond ))},
537
+ {Type : unix .NL80211_SURVEY_INFO_TIME_EXT_BUSY , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTimeExtBusy / time .Millisecond ))},
538
+ {Type : unix .NL80211_SURVEY_INFO_TIME_BSS_RX , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTimeBssRx / time .Millisecond ))},
539
+ {Type : unix .NL80211_SURVEY_INFO_TIME_RX , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTimeRx / time .Millisecond ))},
540
+ {Type : unix .NL80211_SURVEY_INFO_TIME_TX , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTimeTx / time .Millisecond ))},
541
+ {Type : unix .NL80211_SURVEY_INFO_TIME_SCAN , Data : nlenc .Uint64Bytes (uint64 (s .ChannelTimeScan / time .Millisecond ))},
542
+ }... )
543
+ return []netlink.Attribute {
544
+ {
545
+ Type : unix .NL80211_ATTR_SURVEY_INFO ,
546
+ Data : mustMarshalAttributes (attributes ),
547
+ },
548
+ }
549
+ }
550
+
526
551
func bitrateAttr (bitrate int ) uint32 {
527
552
return uint32 (bitrate / 100 / 1000 )
528
553
}
@@ -542,6 +567,10 @@ func mustMessages(t *testing.T, command uint8, want interface{}) genltest.Func {
542
567
for _ , x := range xs {
543
568
as = append (as , x )
544
569
}
570
+ case []* SurveyInfo :
571
+ for _ , x := range xs {
572
+ as = append (as , x )
573
+ }
545
574
default :
546
575
t .Fatalf ("cannot make messages for type: %T" , xs )
547
576
}
@@ -606,3 +635,112 @@ func Test_decodeBSSLoadError(t *testing.T) {
606
635
t .Error ("want error on bogus IE with wrong length" )
607
636
}
608
637
}
638
+
639
+ func TestLinux_clientSurveryInfoMissingAttributeIsNotExist (t * testing.T ) {
640
+ c := testClient (t , func (_ genetlink.Message , _ netlink.Message ) ([]genetlink.Message , error ) {
641
+ // One message without station info attribute
642
+ return []genetlink.Message {{
643
+ Header : genetlink.Header {
644
+ Command : unix .NL80211_CMD_GET_SURVEY ,
645
+ },
646
+ Data : mustMarshalAttributes ([]netlink.Attribute {{
647
+ Type : unix .NL80211_ATTR_IFINDEX ,
648
+ Data : nlenc .Uint32Bytes (1 ),
649
+ }}),
650
+ }}, nil
651
+ })
652
+
653
+ _ , err := c .StationInfo (& Interface {
654
+ Index : 1 ,
655
+ HardwareAddr : net.HardwareAddr {0xe , 0xad , 0xbe , 0xef , 0xde , 0xad },
656
+ })
657
+ if ! os .IsNotExist (err ) {
658
+ t .Fatalf ("expected is not exist, got: %v" , err )
659
+ }
660
+ }
661
+
662
+ func TestLinux_clientSurveyInfoNoMessagesIsNotExist (t * testing.T ) {
663
+ c := testClient (t , func (_ genetlink.Message , _ netlink.Message ) ([]genetlink.Message , error ) {
664
+ // No messages about station info at the generic netlink level.
665
+ // Caller will interpret this as no station info.
666
+ return nil , io .EOF
667
+ })
668
+
669
+ info , err := c .SurveyInfo (& Interface {
670
+ Index : 1 ,
671
+ HardwareAddr : net.HardwareAddr {0xe , 0xad , 0xbe , 0xef , 0xde , 0xad },
672
+ })
673
+ if err != nil {
674
+ t .Fatalf ("undexpected error: %v" , err )
675
+ }
676
+ if ! reflect .DeepEqual (info , []* SurveyInfo {}) {
677
+ t .Fatalf ("expected info to be an empty slice, got %v" , info )
678
+ }
679
+ }
680
+
681
+ func TestLinux_clientSurveyInfoOK (t * testing.T ) {
682
+ want := []* SurveyInfo {
683
+ {
684
+ Frequency : 2412 ,
685
+ Noise : - 95 ,
686
+ InUse : true ,
687
+ ChannelTime : 100 * time .Millisecond ,
688
+ ChannelTimeBusy : 50 * time .Millisecond ,
689
+ ChannelTimeExtBusy : 10 * time .Millisecond ,
690
+ ChannelTimeBssRx : 20 * time .Millisecond ,
691
+ ChannelTimeRx : 30 * time .Millisecond ,
692
+ ChannelTimeTx : 40 * time .Millisecond ,
693
+ ChannelTimeScan : 5 * time .Millisecond ,
694
+ },
695
+ {
696
+ Frequency : 2437 ,
697
+ Noise : - 90 ,
698
+ InUse : false ,
699
+ ChannelTime : 200 * time .Millisecond ,
700
+ ChannelTimeBusy : 100 * time .Millisecond ,
701
+ ChannelTimeExtBusy : 20 * time .Millisecond ,
702
+ ChannelTimeBssRx : 40 * time .Millisecond ,
703
+ ChannelTimeRx : 60 * time .Millisecond ,
704
+ ChannelTimeTx : 80 * time .Millisecond ,
705
+ ChannelTimeScan : 10 * time .Millisecond ,
706
+ },
707
+ }
708
+
709
+ ifi := & Interface {
710
+ Index : 1 ,
711
+ HardwareAddr : net.HardwareAddr {0xe , 0xad , 0xbe , 0xef , 0xde , 0xad },
712
+ }
713
+
714
+ const flags = netlink .Request | netlink .Dump
715
+
716
+ msgsFn := mustMessages (t , unix .NL80211_CMD_GET_SURVEY , want )
717
+
718
+ c := testClient (t , genltest .CheckRequest (familyID , unix .NL80211_CMD_GET_SURVEY , flags ,
719
+ func (greq genetlink.Message , nreq netlink.Message ) ([]genetlink.Message , error ) {
720
+ // Also verify that the correct interface attributes are
721
+ // present in the request.
722
+ attrs , err := netlink .UnmarshalAttributes (greq .Data )
723
+ if err != nil {
724
+ t .Fatalf ("failed to unmarshal attributes: %v" , err )
725
+ }
726
+
727
+ if diff := diffNetlinkAttributes (ifi .idAttrs (), attrs ); diff != "" {
728
+ t .Fatalf ("unexpected request netlink attributes (-want +got):\n %s" , diff )
729
+ }
730
+
731
+ return msgsFn (greq , nreq )
732
+ },
733
+ ))
734
+
735
+ got , err := c .SurveyInfo (ifi )
736
+ if err != nil {
737
+ log .Fatalf ("unexpected error: %v" , err )
738
+ }
739
+
740
+ for i := range want {
741
+ if ! reflect .DeepEqual (want [i ], got [i ]) {
742
+ t .Fatalf ("unexpected station info:\n - want: %v\n - got: %v" ,
743
+ want [i ], got [i ])
744
+ }
745
+ }
746
+ }
0 commit comments