tc.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package mux
  2. import (
  3. "errors"
  4. "math"
  5. "net"
  6. "os/exec"
  7. "strings"
  8. )
  9. type Eth struct {
  10. EthName string
  11. EthAddr string
  12. }
  13. type TrafficControl struct {
  14. Eth *Eth
  15. }
  16. func Ips() (map[string]string, error) {
  17. ips := make(map[string]string)
  18. interfaces, err := net.Interfaces()
  19. if err != nil {
  20. return nil, err
  21. }
  22. for _, i := range interfaces {
  23. byName, err := net.InterfaceByName(i.Name)
  24. if err != nil {
  25. return nil, err
  26. }
  27. if !strings.Contains(byName.Name, "Loopback") && !strings.Contains(byName.Name, "isatap") {
  28. addresses, _ := byName.Addrs()
  29. for _, v := range addresses {
  30. ips[byName.Name] = v.String()
  31. }
  32. }
  33. }
  34. return ips, nil
  35. }
  36. // get ip and Eth information by Eth name
  37. func GetIpAddrByName(EthName string) (Eth *Eth, err error) {
  38. interfaces, err := net.Interfaces()
  39. if err != nil {
  40. return
  41. }
  42. for _, i := range interfaces {
  43. byName, err := net.InterfaceByName(i.Name)
  44. if err != nil {
  45. return
  46. }
  47. if byName.Name == EthName || EthName == "" {
  48. // except lo
  49. if !strings.Contains(byName.Name, "Loopback") && !strings.Contains(byName.Name, "isatap") {
  50. addresses, _ := byName.Addrs()
  51. for _, v := range addresses {
  52. ipMask := strings.Split(v.String(), "/")
  53. if len(ipMask) == 2 {
  54. Eth.EthAddr = ipMask[0]
  55. Eth.EthName = byName.Name
  56. return
  57. }
  58. }
  59. }
  60. }
  61. }
  62. err = errors.New("not found interface")
  63. return
  64. }
  65. type tcFunc func() error
  66. func getArrayExhaustivity(arr []tcFunc) (result [][]tcFunc) {
  67. var l = int(math.Pow(float64(2), float64(len(arr))) - 1)
  68. var t []tcFunc
  69. for i := 1; i <= l; i++ {
  70. s := i
  71. t = []tcFunc{}
  72. for k := 0; s > 0; k++ {
  73. if s&1 == 1 {
  74. t = append(t, arr[k])
  75. }
  76. s >>= 1
  77. }
  78. result = append(result, t)
  79. }
  80. return
  81. }
  82. func NewTrafficControl(EthName string) (*TrafficControl, error) {
  83. Eth, err := GetIpAddrByName(EthName)
  84. if err != nil {
  85. return nil, err
  86. }
  87. t := new(TrafficControl)
  88. t.Eth = Eth
  89. return t, nil
  90. }
  91. // test the network randomly
  92. func (tc *TrafficControl) RunNetRangeTest(f func()) error {
  93. funcs := tc.getTestVariable()
  94. groups := getArrayExhaustivity(funcs)
  95. for _, v := range groups {
  96. // execute bandwidth control
  97. if err := tc.bandwidth("1mbit"); err != nil {
  98. return err
  99. }
  100. // execute random strategy
  101. for _, vv := range v {
  102. err := vv()
  103. if err != nil {
  104. return err
  105. }
  106. }
  107. // execute test func
  108. f()
  109. // clear strategy
  110. if err := tc.del(); err != nil {
  111. return err
  112. }
  113. }
  114. return nil
  115. }
  116. // create test variables
  117. func (tc *TrafficControl) getTestVariable() []tcFunc {
  118. return []tcFunc{
  119. func() error { return tc.delay("add", "100ms", "10ms", "30%") },
  120. func() error { return tc.loss("add", "1%", "30%") },
  121. func() error { return tc.duplicate("add", "1%") },
  122. func() error { return tc.corrupt("add", "0.2%") },
  123. func() error { return tc.reorder("change", "10ms", "25%", "50%") },
  124. }
  125. }
  126. // this command sets the transmission of the network card to delayVal. At the same time,
  127. // about waveRatio of the packets will be delayed by ± wave.
  128. func (tc *TrafficControl) delay(opt, delayVal, wave, waveRatio string) error {
  129. return runCmd(exec.Command("tc", "qdisc", opt, "dev", tc.Eth.EthName, "root", "netem", "delay", delayVal, wave, waveRatio))
  130. }
  131. // this command sets the transmission of the network card to randomly drop lossRatio of packets with a success rate of lossSuccessRatio.
  132. func (tc *TrafficControl) loss(opt, lossRatio, lossSuccessRatio string) error {
  133. return runCmd(exec.Command("tc", "qdisc", opt, "dev", tc.Eth.EthName, "root", "netem", "loss", lossRatio, lossSuccessRatio))
  134. }
  135. // this command sets the transmission of the network card to randomly generate repeatRatio duplicate packets
  136. func (tc *TrafficControl) duplicate(opt, duplicateRatio string) error {
  137. return runCmd(exec.Command("tc", "qdisc", opt, "dev", tc.Eth.EthName, "root", "netem", "duplicate", duplicateRatio))
  138. }
  139. // this command sets the transmission of the network card to randomly generate corruptRatio corrupted packets.
  140. // the kernel version must be above 2.6.16
  141. func (tc *TrafficControl) corrupt(opt, corruptRatio string) error {
  142. return runCmd(exec.Command("tc", "qdisc", opt, "dev", tc.Eth.EthName, "root", "netem", "corrupt", corruptRatio))
  143. }
  144. // this command sets the transmission of the network card to: reorderRatio of the packets (reorderRelationRatio related)
  145. // will be sent immediately, and the other is delayed by delayVal
  146. func (tc *TrafficControl) reorder(opt, delayVal, reorderRatio, reorderRelationRatio string) error {
  147. return runCmd(exec.Command("tc", "qdisc", opt, "dev", tc.Eth.EthName, "root", "netem", "delay", delayVal, "reorder", reorderRatio, reorderRelationRatio))
  148. }
  149. // remove all tc setting
  150. func (tc *TrafficControl) del() error {
  151. return runCmd(exec.Command("tc", "qdisc", "del", "dev", tc.Eth.EthName, "root"))
  152. }
  153. // remove all tc setting
  154. func (tc *TrafficControl) bandwidth(bw string) error {
  155. runCmd(exec.Command("tc", "qdisc", "add", "dev", tc.Eth.EthName, "root", "handle", "2:", "htb", "default", "30"))
  156. return runCmd(exec.Command("tc", "qdisc", "add", "dev", tc.Eth.EthName, "parent", "2:", "classid", "2:30", "htb", "rate", bw))
  157. }
  158. func runCmd(cmd *exec.Cmd) error {
  159. err := cmd.Run()
  160. if err != nil {
  161. return err
  162. }
  163. return nil
  164. }