Skip to content

Commit

Permalink
pkg/netutil: get list of Ethernet for tc command
Browse files Browse the repository at this point in the history
  • Loading branch information
gyuho committed Nov 16, 2016
1 parent 377f19b commit 53801a7
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 4 deletions.
83 changes: 79 additions & 4 deletions pkg/netutil/isolate_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@
package netutil

import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"sort"
)

// DropPort drops all tcp packets that are received from the given port and sent to the given port.
Expand All @@ -43,14 +48,20 @@ func RecoverPort(port int) error {

// SetLatency adds latency in millisecond scale with random variations.
func SetLatency(ms, rv int) error {
eths, err := getEthernet()
if err != nil {
return err
}
eth := eths[0]

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", eth, 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", eth, ms, rv)
_, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
Expand All @@ -61,6 +72,70 @@ 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()
eths, err := getEthernet()
if err != nil {
return err
}
eth := eths[0]

_, err = exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo tc qdisc del dev %s root netem", eth)).Output()
return err
}

func getEthernet() (eths []string, err error) {
var ifs []string
ifs, err = readNetworkInterface()
if err != nil {
return
}

for _, name := range ifs {
if isEthernet(name) {
eths = append(eths, name)
}
}
if len(eths) == 0 {
return nil, fmt.Errorf("no ethernet network interface found (%v)", ifs)
}

sort.Strings(eths)
return
}

const sysClassNet = "/sys/class/net/"

func readNetworkInterface() ([]string, error) {
d, err := os.Open(sysClassNet)
if err != nil {
return nil, err
}
defer d.Close()

ns, err := d.Readdirnames(-1)
if err != nil {
return nil, err
}
sort.Strings(ns)

return ns, nil
}

var typeEthernet = []byte{49, 10}

// isEthernet returns true if the network interface is Ethernet.
// '/sys/class/net/type' with 1 is Ethernet 10Mbps, 772 is Loopback device.
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_arp.h
func isEthernet(name string) bool {
path := filepath.Join(sysClassNet, name, "type")
f, err := os.Open(path)
if err != nil {
return false
}
defer f.Close()

b, err := ioutil.ReadAll(f)
if err != nil {
return false
}
return bytes.Equal(typeEthernet, b)
}
25 changes: 25 additions & 0 deletions pkg/netutil/isolate_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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.

package netutil

import "testing"

func TestGetEthernet(t *testing.T) {
eths, err := getEthernet()
if err != nil {
t.Fatal(err)
}
t.Log(eths)
}

0 comments on commit 53801a7

Please sign in to comment.