mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
Merge pull request #83572 from chendotjs/tc-fix
bandwidth: use regexp to handle tc output and add IPv6 support
This commit is contained in:
commit
e4e3d72f1c
@ -24,6 +24,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
@ -33,6 +34,11 @@ import (
|
|||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
classShowMatcher = regexp.MustCompile(`class htb (1:\d+)`)
|
||||||
|
classAndHandleMatcher = regexp.MustCompile(`filter parent 1:.*fh (\d+::\d+).*flowid (\d+:\d+)`)
|
||||||
|
)
|
||||||
|
|
||||||
// tcShaper provides an implementation of the Shaper interface on Linux using the 'tc' tool.
|
// tcShaper provides an implementation of the Shaper interface on Linux using the 'tc' tool.
|
||||||
// In general, using this requires that the caller posses the NET_CAP_ADMIN capability, though if you
|
// In general, using this requires that the caller posses the NET_CAP_ADMIN capability, though if you
|
||||||
// do this within an container, it only requires the NS_CAPABLE capability for manipulations to that
|
// 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) {
|
|||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parts := strings.Split(line, " ")
|
|
||||||
// expected tc line:
|
// expected tc line:
|
||||||
// class htb 1:1 root prio 0 rate 1000Kbit ceil 1000Kbit burst 1600b cburst 1600b
|
// class htb 1:1 root prio 0 rate 1000Kbit ceil 1000Kbit burst 1600b cburst 1600b
|
||||||
if len(parts) != 14 {
|
matches := classShowMatcher.FindStringSubmatch(line)
|
||||||
return -1, fmt.Errorf("unexpected output from tc: %s (%v)", scanner.Text(), parts)
|
if len(matches) != 2 {
|
||||||
|
return -1, fmt.Errorf("unexpected output from tc: %s (%v)", scanner.Text(), matches)
|
||||||
}
|
}
|
||||||
classes.Insert(parts[2])
|
classes.Insert(matches[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure it doesn't go forever
|
// Make sure it doesn't go forever
|
||||||
@ -153,13 +159,14 @@ func (t *tcShaper) findCIDRClass(cidr string) (classAndHandleList [][]string, fo
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.Contains(line, spec) {
|
if strings.Contains(line, spec) {
|
||||||
parts := strings.Split(filter, " ")
|
|
||||||
// expected tc line:
|
// expected tc line:
|
||||||
// filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1
|
// `filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1` (old version) or
|
||||||
if len(parts) != 19 {
|
// `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)
|
||||||
return classAndHandleList, false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(parts), parts)
|
matches := classAndHandleMatcher.FindStringSubmatch(filter)
|
||||||
|
if len(matches) != 3 {
|
||||||
|
return classAndHandleList, false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(matches), matches)
|
||||||
}
|
}
|
||||||
resultTmp := []string{parts[18], parts[9]}
|
resultTmp := []string{matches[2], matches[1]}
|
||||||
classAndHandleList = append(classAndHandleList, resultTmp)
|
classAndHandleList = append(classAndHandleList, resultTmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,7 +308,6 @@ func (t *tcShaper) Reset(cidr string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tcShaper) deleteInterface(class string) error {
|
func (t *tcShaper) deleteInterface(class string) error {
|
||||||
|
@ -212,6 +212,13 @@ filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0
|
|||||||
filter parent 1: protocol ip pref 1 u32 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:2
|
filter parent 1: protocol ip pref 1 u32 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:2
|
||||||
match 01020000/ffff0000 at 16
|
match 01020000/ffff0000 at 16
|
||||||
`
|
`
|
||||||
|
var tcFilterOutputNewVersion = `filter parent 1: protocol ip pref 1 u32
|
||||||
|
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1
|
||||||
|
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
|
||||||
|
match ac110002/ffffffff at 16
|
||||||
|
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
|
||||||
|
match 01020000/ffff0000 at 16
|
||||||
|
`
|
||||||
|
|
||||||
func TestFindCIDRClass(t *testing.T) {
|
func TestFindCIDRClass(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@ -240,6 +247,23 @@ func TestFindCIDRClass(t *testing.T) {
|
|||||||
output: tcFilterOutput,
|
output: tcFilterOutput,
|
||||||
expectNotFound: true,
|
expectNotFound: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
cidr: "172.17.0.2/32",
|
||||||
|
output: tcFilterOutputNewVersion,
|
||||||
|
expectedClass: "1:1",
|
||||||
|
expectedHandle: "800::800",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cidr: "1.2.3.4/16",
|
||||||
|
output: tcFilterOutputNewVersion,
|
||||||
|
expectedClass: "1:2",
|
||||||
|
expectedHandle: "800::801",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cidr: "2.2.3.4/16",
|
||||||
|
output: tcFilterOutputNewVersion,
|
||||||
|
expectNotFound: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
err: errors.New("test error"),
|
err: errors.New("test error"),
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user