Merge pull request #6862 from gyuho/network-interface

pkg/netutil: get default interface for tc commands
release-3.1
Gyu-Ho Lee 2016-11-18 10:11:59 -08:00 committed by GitHub
commit 7da3019f42
4 changed files with 108 additions and 22 deletions

View File

@ -43,14 +43,19 @@ func RecoverPort(port int) error {
// SetLatency adds latency in millisecond scale with random variations.
func SetLatency(ms, rv int) error {
ifce, err := GetDefaultInterface()
if err != nil {
return err
}
if rv > ms {
rv = 1
}
cmdStr := fmt.Sprintf("sudo tc qdisc add dev eth0 root netem delay %dms %dms distribution normal", ms, rv)
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
cmdStr := fmt.Sprintf("sudo tc qdisc add dev %s root netem delay %dms %dms distribution normal", ifce, ms, rv)
_, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
// the rule has already been added. Overwrite it.
cmdStr = fmt.Sprintf("sudo tc qdisc change dev eth0 root netem delay %dms %dms distribution normal", ms, rv)
cmdStr = fmt.Sprintf("sudo tc qdisc change dev %s root netem delay %dms %dms distribution normal", ifce, ms, rv)
_, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
@ -61,6 +66,10 @@ func SetLatency(ms, rv int) error {
// RemoveLatency resets latency configurations.
func RemoveLatency() error {
_, err := exec.Command("/bin/sh", "-c", "sudo tc qdisc del dev eth0 root netem").Output()
ifce, err := GetDefaultInterface()
if err != nil {
return err
}
_, err = exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo tc qdisc del dev %s root netem", ifce)).Output()
return err
}

View File

@ -26,3 +26,8 @@ import (
func GetDefaultHost() (string, error) {
return "", fmt.Errorf("default host not supported on %s_%s", runtime.GOOS, runtime.GOARCH)
}
// GetDefaultInterface fetches the device name of default routable interface.
func GetDefaultInterface() (string, error) {
return "", fmt.Errorf("default host not supported on %s_%s", runtime.GOOS, runtime.GOARCH)
}

View File

@ -35,33 +35,21 @@ func GetDefaultHost() (string, error) {
return "", rerr
}
attrs, aerr := syscall.ParseNetlinkRouteAttr(rmsg)
if aerr != nil {
return "", aerr
host, oif, err := parsePREFSRC(rmsg)
if err != nil {
return "", err
}
oif := uint32(0)
for _, attr := range attrs {
if attr.Attr.Type == syscall.RTA_PREFSRC {
return net.IP(attr.Value).String(), nil
}
if attr.Attr.Type == syscall.RTA_OIF {
oif = binary.LittleEndian.Uint32(attr.Value)
}
}
if oif == 0 {
return "", errNoDefaultRoute
if host != "" {
return host, nil
}
// prefsrc not detected, fall back to getting address from iface
ifmsg, ierr := getIface(oif)
if ierr != nil {
return "", ierr
}
attrs, aerr = syscall.ParseNetlinkRouteAttr(ifmsg)
attrs, aerr := syscall.ParseNetlinkRouteAttr(ifmsg)
if aerr != nil {
return "", aerr
}
@ -131,3 +119,60 @@ func getIface(idx uint32) (*syscall.NetlinkMessage, error) {
return nil, errNoDefaultRoute
}
var errNoDefaultInterface = fmt.Errorf("could not find default interface")
func GetDefaultInterface() (string, error) {
rmsg, rerr := getDefaultRoute()
if rerr != nil {
return "", rerr
}
_, oif, err := parsePREFSRC(rmsg)
if err != nil {
return "", err
}
ifmsg, ierr := getIface(oif)
if ierr != nil {
return "", ierr
}
attrs, aerr := syscall.ParseNetlinkRouteAttr(ifmsg)
if aerr != nil {
return "", aerr
}
for _, attr := range attrs {
if attr.Attr.Type == syscall.IFLA_IFNAME {
return string(attr.Value[:len(attr.Value)-1]), nil
}
}
return "", errNoDefaultInterface
}
// parsePREFSRC returns preferred source address and output interface index (RTA_OIF).
func parsePREFSRC(m *syscall.NetlinkMessage) (host string, oif uint32, err error) {
var attrs []syscall.NetlinkRouteAttr
attrs, err = syscall.ParseNetlinkRouteAttr(m)
if err != nil {
return "", 0, err
}
for _, attr := range attrs {
if attr.Attr.Type == syscall.RTA_PREFSRC {
host = net.IP(attr.Value).String()
}
if attr.Attr.Type == syscall.RTA_OIF {
oif = binary.LittleEndian.Uint32(attr.Value)
}
if host != "" && oif != uint32(0) {
break
}
}
if oif == 0 {
err = errNoDefaultRoute
}
return
}

View File

@ -0,0 +1,27 @@
// Copyright 2016 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build linux
package netutil
import "testing"
func TestGetDefaultInterface(t *testing.T) {
ifc, err := GetDefaultInterface()
if err != nil {
t.Fatal(err)
}
t.Logf("default network interface: %q\n", ifc)
}