handle_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package netlink
  2. import (
  3. "crypto/rand"
  4. "encoding/hex"
  5. "fmt"
  6. "io"
  7. "net"
  8. "sync"
  9. "sync/atomic"
  10. "testing"
  11. "github.com/vishvananda/netns"
  12. )
  13. func TestHandleCreateDelete(t *testing.T) {
  14. h, err := NewHandle()
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. if h.routeSocket == nil || h.xfrmSocket == nil {
  19. t.Fatalf("Handle socket(s) were not created")
  20. }
  21. h.Delete()
  22. if h.routeSocket != nil || h.xfrmSocket != nil {
  23. t.Fatalf("Handle socket(s) were not destroyed")
  24. }
  25. }
  26. func TestHandleCreateNetns(t *testing.T) {
  27. id := make([]byte, 4)
  28. if _, err := io.ReadFull(rand.Reader, id); err != nil {
  29. t.Fatal(err)
  30. }
  31. ifName := "dummy-" + hex.EncodeToString(id)
  32. // Create an handle on the current netns
  33. curNs, err := netns.Get()
  34. if err != nil {
  35. t.Fatal(err)
  36. }
  37. defer curNs.Close()
  38. ch, err := NewHandleAt(curNs)
  39. if err != nil {
  40. t.Fatal(err)
  41. }
  42. defer ch.Delete()
  43. // Create an handle on a custom netns
  44. newNs, err := netns.New()
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. defer newNs.Close()
  49. nh, err := NewHandleAt(newNs)
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. defer nh.Delete()
  54. // Create an interface using the current handle
  55. err = ch.LinkAdd(&Dummy{LinkAttrs{Name: ifName}})
  56. if err != nil {
  57. t.Fatal(err)
  58. }
  59. l, err := ch.LinkByName(ifName)
  60. if err != nil {
  61. t.Fatal(err)
  62. }
  63. if l.Type() != "dummy" {
  64. t.Fatalf("Unexpected link type: %s", l.Type())
  65. }
  66. // Verify the new handle cannot find the interface
  67. ll, err := nh.LinkByName(ifName)
  68. if err == nil {
  69. t.Fatalf("Unexpected link found on netns %s: %v", newNs, ll)
  70. }
  71. // Move the interface to the new netns
  72. err = ch.LinkSetNsFd(l, int(newNs))
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. // Verify new netns handle can find the interface while current cannot
  77. ll, err = nh.LinkByName(ifName)
  78. if err != nil {
  79. t.Fatal(err)
  80. }
  81. if ll.Type() != "dummy" {
  82. t.Fatalf("Unexpected link type: %s", ll.Type())
  83. }
  84. ll, err = ch.LinkByName(ifName)
  85. if err == nil {
  86. t.Fatalf("Unexpected link found on netns %s: %v", curNs, ll)
  87. }
  88. }
  89. var (
  90. iter = 10
  91. numThread = uint32(4)
  92. prefix = "iface"
  93. handle1 *Handle
  94. handle2 *Handle
  95. ns1 netns.NsHandle
  96. ns2 netns.NsHandle
  97. done uint32
  98. initError error
  99. once sync.Once
  100. )
  101. func getXfrmState(thread int) *XfrmState {
  102. return &XfrmState{
  103. Src: net.IPv4(byte(192), byte(168), 1, byte(1+thread)),
  104. Dst: net.IPv4(byte(192), byte(168), 2, byte(1+thread)),
  105. Proto: XFRM_PROTO_AH,
  106. Mode: XFRM_MODE_TUNNEL,
  107. Spi: thread,
  108. Auth: &XfrmStateAlgo{
  109. Name: "hmac(sha256)",
  110. Key: []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
  111. },
  112. }
  113. }
  114. func getXfrmPolicy(thread int) *XfrmPolicy {
  115. return &XfrmPolicy{
  116. Src: &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}},
  117. Dst: &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}},
  118. Proto: 17,
  119. DstPort: 1234,
  120. SrcPort: 5678,
  121. Dir: XFRM_DIR_OUT,
  122. Tmpls: []XfrmPolicyTmpl{
  123. {
  124. Src: net.IPv4(byte(192), byte(168), 1, byte(thread)),
  125. Dst: net.IPv4(byte(192), byte(168), 2, byte(thread)),
  126. Proto: XFRM_PROTO_ESP,
  127. Mode: XFRM_MODE_TUNNEL,
  128. },
  129. },
  130. }
  131. }
  132. func initParallel() {
  133. ns1, initError = netns.New()
  134. if initError != nil {
  135. return
  136. }
  137. handle1, initError = NewHandleAt(ns1)
  138. if initError != nil {
  139. return
  140. }
  141. ns2, initError = netns.New()
  142. if initError != nil {
  143. return
  144. }
  145. handle2, initError = NewHandleAt(ns2)
  146. if initError != nil {
  147. return
  148. }
  149. }
  150. func parallelDone() {
  151. atomic.AddUint32(&done, 1)
  152. if done == numThread {
  153. if ns1.IsOpen() {
  154. ns1.Close()
  155. }
  156. if ns2.IsOpen() {
  157. ns2.Close()
  158. }
  159. if handle1 != nil {
  160. handle1.Delete()
  161. }
  162. if handle2 != nil {
  163. handle2.Delete()
  164. }
  165. }
  166. }
  167. // Do few route and xfrm operation on the two handles in parallel
  168. func runParallelTests(t *testing.T, thread int) {
  169. defer parallelDone()
  170. t.Parallel()
  171. once.Do(initParallel)
  172. if initError != nil {
  173. t.Fatal(initError)
  174. }
  175. state := getXfrmState(thread)
  176. policy := getXfrmPolicy(thread)
  177. for i := 0; i < iter; i++ {
  178. ifName := fmt.Sprintf("%s_%d_%d", prefix, thread, i)
  179. link := &Dummy{LinkAttrs{Name: ifName}}
  180. err := handle1.LinkAdd(link)
  181. if err != nil {
  182. t.Fatal(err)
  183. }
  184. l, err := handle1.LinkByName(ifName)
  185. if err != nil {
  186. t.Fatal(err)
  187. }
  188. err = handle1.LinkSetUp(l)
  189. if err != nil {
  190. t.Fatal(err)
  191. }
  192. handle1.LinkSetNsFd(l, int(ns2))
  193. if err != nil {
  194. t.Fatal(err)
  195. }
  196. err = handle1.XfrmStateAdd(state)
  197. if err != nil {
  198. t.Fatal(err)
  199. }
  200. err = handle1.XfrmPolicyAdd(policy)
  201. if err != nil {
  202. t.Fatal(err)
  203. }
  204. err = handle2.LinkSetDown(l)
  205. if err != nil {
  206. t.Fatal(err)
  207. }
  208. err = handle2.XfrmStateAdd(state)
  209. if err != nil {
  210. t.Fatal(err)
  211. }
  212. err = handle2.XfrmPolicyAdd(policy)
  213. if err != nil {
  214. t.Fatal(err)
  215. }
  216. _, err = handle2.LinkByName(ifName)
  217. if err != nil {
  218. t.Fatal(err)
  219. }
  220. handle2.LinkSetNsFd(l, int(ns1))
  221. if err != nil {
  222. t.Fatal(err)
  223. }
  224. err = handle1.LinkSetUp(l)
  225. if err != nil {
  226. t.Fatal(err)
  227. }
  228. l, err = handle1.LinkByName(ifName)
  229. if err != nil {
  230. t.Fatal(err)
  231. }
  232. err = handle1.XfrmPolicyDel(policy)
  233. if err != nil {
  234. t.Fatal(err)
  235. }
  236. err = handle2.XfrmPolicyDel(policy)
  237. if err != nil {
  238. t.Fatal(err)
  239. }
  240. err = handle1.XfrmStateDel(state)
  241. if err != nil {
  242. t.Fatal(err)
  243. }
  244. err = handle2.XfrmStateDel(state)
  245. if err != nil {
  246. t.Fatal(err)
  247. }
  248. }
  249. }
  250. func TestHandleParallel1(t *testing.T) {
  251. runParallelTests(t, 1)
  252. }
  253. func TestHandleParallel2(t *testing.T) {
  254. runParallelTests(t, 2)
  255. }
  256. func TestHandleParallel3(t *testing.T) {
  257. runParallelTests(t, 3)
  258. }
  259. func TestHandleParallel4(t *testing.T) {
  260. runParallelTests(t, 4)
  261. }