Skip to content

Commit e0461fb

Browse files
feat: add channel width to interface info (#118)
1 parent 79ab2fd commit e0461fb

4 files changed

Lines changed: 144 additions & 0 deletions

File tree

client_linux.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,8 @@ func (ifi *Interface) parseAttributes(attrs []netlink.Attribute) error {
575575
ifi.Device = int(nlenc.Uint64(a.Data))
576576
case unix.NL80211_ATTR_WIPHY_FREQ:
577577
ifi.Frequency = int(nlenc.Uint32(a.Data))
578+
case unix.NL80211_ATTR_CHANNEL_WIDTH:
579+
ifi.ChannelWidth = ChannelWidth(nlenc.Uint32(a.Data))
578580
}
579581
}
580582

client_linux_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func TestLinux_clientInterfacesOK(t *testing.T) {
3333
Device: 1,
3434
Type: InterfaceTypeStation,
3535
Frequency: 2412,
36+
ChannelWidth: ChannelWidth80,
3637
},
3738
{
3839
HardwareAddr: net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xae},
@@ -459,6 +460,7 @@ func (ifi *Interface) attributes() []netlink.Attribute {
459460
{Type: unix.NL80211_ATTR_IFTYPE, Data: nlenc.Uint32Bytes(uint32(ifi.Type))},
460461
{Type: unix.NL80211_ATTR_WDEV, Data: nlenc.Uint64Bytes(uint64(ifi.Device))},
461462
{Type: unix.NL80211_ATTR_WIPHY_FREQ, Data: nlenc.Uint32Bytes(uint32(ifi.Frequency))},
463+
{Type: unix.NL80211_ATTR_CHANNEL_WIDTH, Data: nlenc.Uint32Bytes(uint32(ifi.ChannelWidth))},
462464
}
463465
}
464466

wifi.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,66 @@ func (t InterfaceType) String() string {
121121
}
122122
}
123123

124+
// A ChannelWidth is the width of a WiFi channel.
125+
//
126+
// On Linux, ChannelWidth copies the ordering of nl80211's channel width constants.
127+
// This may not be the case on other operating systems.
128+
// See: https://github.com/torvalds/linux/blob/v6.17/include/uapi/linux/nl80211.h#L5136-L5177
129+
type ChannelWidth int
130+
131+
const (
132+
ChannelWidth20NoHT ChannelWidth = iota
133+
ChannelWidth20
134+
ChannelWidth40
135+
ChannelWidth80
136+
ChannelWidth80P80
137+
ChannelWidth160
138+
ChannelWidth5
139+
ChannelWidth10
140+
ChannelWidth1
141+
ChannelWidth2
142+
ChannelWidth4
143+
ChannelWidth8
144+
ChannelWidth16
145+
ChannelWidth320
146+
)
147+
148+
// String returns the string representation of an InterfaceType.
149+
func (t ChannelWidth) String() string {
150+
switch t {
151+
case ChannelWidth20NoHT:
152+
return "20 MHz (no HT)"
153+
case ChannelWidth20:
154+
return "20 MHz"
155+
case ChannelWidth40:
156+
return "40 MHz"
157+
case ChannelWidth80:
158+
return "80 MHz"
159+
case ChannelWidth80P80:
160+
return "80+80 MHz"
161+
case ChannelWidth160:
162+
return "160 MHz"
163+
case ChannelWidth5:
164+
return "5 MHz"
165+
case ChannelWidth10:
166+
return "10 MHz"
167+
case ChannelWidth1:
168+
return "1 MHz"
169+
case ChannelWidth2:
170+
return "2 MHz"
171+
case ChannelWidth4:
172+
return "4 MHz"
173+
case ChannelWidth8:
174+
return "8 MHz"
175+
case ChannelWidth16:
176+
return "16 MHz"
177+
case ChannelWidth320:
178+
return "320 MHz"
179+
default:
180+
return fmt.Sprintf("unknown(%d)", t)
181+
}
182+
}
183+
124184
// An Interface is a WiFi network interface.
125185
type Interface struct {
126186
// The index of the interface.
@@ -143,6 +203,9 @@ type Interface struct {
143203

144204
// The interface's wireless frequency in MHz.
145205
Frequency int
206+
207+
// The interface's wireless channel width.
208+
ChannelWidth ChannelWidth
146209
}
147210

148211
// StationInfo contains statistics about a WiFi interface operating in

wifi_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,83 @@ func TestInterfaceTypeString(t *testing.T) {
7676
}
7777
}
7878

79+
func TestChannelWidthString(t *testing.T) {
80+
tests := []struct {
81+
t ChannelWidth
82+
s string
83+
}{
84+
{
85+
t: ChannelWidth20NoHT,
86+
s: "20 MHz (no HT)",
87+
},
88+
{
89+
t: ChannelWidth20,
90+
s: "20 MHz",
91+
},
92+
{
93+
t: ChannelWidth40,
94+
s: "40 MHz",
95+
},
96+
{
97+
t: ChannelWidth80,
98+
s: "80 MHz",
99+
},
100+
{
101+
t: ChannelWidth80P80,
102+
s: "80+80 MHz",
103+
},
104+
{
105+
t: ChannelWidth160,
106+
s: "160 MHz",
107+
},
108+
{
109+
t: ChannelWidth5,
110+
s: "5 MHz",
111+
},
112+
{
113+
t: ChannelWidth10,
114+
s: "10 MHz",
115+
},
116+
{
117+
t: ChannelWidth1,
118+
s: "1 MHz",
119+
},
120+
{
121+
t: ChannelWidth2,
122+
s: "2 MHz",
123+
},
124+
{
125+
t: ChannelWidth4,
126+
s: "4 MHz",
127+
},
128+
{
129+
t: ChannelWidth8,
130+
s: "8 MHz",
131+
},
132+
{
133+
t: ChannelWidth16,
134+
s: "16 MHz",
135+
},
136+
{
137+
t: ChannelWidth320,
138+
s: "320 MHz",
139+
},
140+
{
141+
t: ChannelWidth320 + 1,
142+
s: "unknown(14)",
143+
},
144+
}
145+
146+
for _, tt := range tests {
147+
t.Run(tt.s, func(t *testing.T) {
148+
if want, got := tt.s, tt.t.String(); want != got {
149+
t.Fatalf("unexpected channel width string:\n- want: %q\n- got: %q",
150+
want, got)
151+
}
152+
})
153+
}
154+
}
155+
79156
func TestBSSStatusString(t *testing.T) {
80157
tests := []struct {
81158
t BSSStatus

0 commit comments

Comments
 (0)