Skip to content

Commit e4e3d72

Browse files
authored
Merge pull request kubernetes#83572 from chendotjs/tc-fix
bandwidth: use regexp to handle tc output and add IPv6 support
2 parents d682c83 + ef5c920 commit e4e3d72

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

pkg/util/bandwidth/linux.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"encoding/hex"
2525
"fmt"
2626
"net"
27+
"regexp"
2728
"strings"
2829

2930
"k8s.io/apimachinery/pkg/api/resource"
@@ -33,6 +34,11 @@ import (
3334
"k8s.io/klog"
3435
)
3536

37+
var (
38+
classShowMatcher = regexp.MustCompile(`class htb (1:\d+)`)
39+
classAndHandleMatcher = regexp.MustCompile(`filter parent 1:.*fh (\d+::\d+).*flowid (\d+:\d+)`)
40+
)
41+
3642
// tcShaper provides an implementation of the Shaper interface on Linux using the 'tc' tool.
3743
// In general, using this requires that the caller posses the NET_CAP_ADMIN capability, though if you
3844
// do this within an container, it only requires the NS_CAPABLE capability for manipulations to that
@@ -75,13 +81,13 @@ func (t *tcShaper) nextClassID() (int, error) {
7581
if len(line) == 0 {
7682
continue
7783
}
78-
parts := strings.Split(line, " ")
7984
// expected tc line:
8085
// class htb 1:1 root prio 0 rate 1000Kbit ceil 1000Kbit burst 1600b cburst 1600b
81-
if len(parts) != 14 {
82-
return -1, fmt.Errorf("unexpected output from tc: %s (%v)", scanner.Text(), parts)
86+
matches := classShowMatcher.FindStringSubmatch(line)
87+
if len(matches) != 2 {
88+
return -1, fmt.Errorf("unexpected output from tc: %s (%v)", scanner.Text(), matches)
8389
}
84-
classes.Insert(parts[2])
90+
classes.Insert(matches[1])
8591
}
8692

8793
// Make sure it doesn't go forever
@@ -153,13 +159,14 @@ func (t *tcShaper) findCIDRClass(cidr string) (classAndHandleList [][]string, fo
153159
continue
154160
}
155161
if strings.Contains(line, spec) {
156-
parts := strings.Split(filter, " ")
157162
// expected tc line:
158-
// filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1
159-
if len(parts) != 19 {
160-
return classAndHandleList, false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(parts), parts)
163+
// `filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1` (old version) or
164+
// `filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw` (new version)
165+
matches := classAndHandleMatcher.FindStringSubmatch(filter)
166+
if len(matches) != 3 {
167+
return classAndHandleList, false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(matches), matches)
161168
}
162-
resultTmp := []string{parts[18], parts[9]}
169+
resultTmp := []string{matches[2], matches[1]}
163170
classAndHandleList = append(classAndHandleList, resultTmp)
164171
}
165172
}
@@ -301,7 +308,6 @@ func (t *tcShaper) Reset(cidr string) error {
301308
}
302309
}
303310
return nil
304-
305311
}
306312

307313
func (t *tcShaper) deleteInterface(class string) error {

pkg/util/bandwidth/linux_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@ filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0
212212
filter parent 1: protocol ip pref 1 u32 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:2
213213
match 01020000/ffff0000 at 16
214214
`
215+
var tcFilterOutputNewVersion = `filter parent 1: protocol ip pref 1 u32
216+
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1
217+
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
218+
match ac110002/ffffffff at 16
219+
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:2 not_in_hw
220+
match 01020000/ffff0000 at 16
221+
`
215222

216223
func TestFindCIDRClass(t *testing.T) {
217224
tests := []struct {
@@ -240,6 +247,23 @@ func TestFindCIDRClass(t *testing.T) {
240247
output: tcFilterOutput,
241248
expectNotFound: true,
242249
},
250+
{
251+
cidr: "172.17.0.2/32",
252+
output: tcFilterOutputNewVersion,
253+
expectedClass: "1:1",
254+
expectedHandle: "800::800",
255+
},
256+
{
257+
cidr: "1.2.3.4/16",
258+
output: tcFilterOutputNewVersion,
259+
expectedClass: "1:2",
260+
expectedHandle: "800::801",
261+
},
262+
{
263+
cidr: "2.2.3.4/16",
264+
output: tcFilterOutputNewVersion,
265+
expectNotFound: true,
266+
},
243267
{
244268
err: errors.New("test error"),
245269
expectErr: true,

0 commit comments

Comments
 (0)