tc.go 5.2 KB

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