github.com/vishvananda/netlink@v1.3.1/handle_test.go (about)

     1  // +build linux
     2  
     3  package netlink
     4  
     5  import (
     6  	"crypto/rand"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"io"
    10  	"net"
    11  	"sync"
    12  	"sync/atomic"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/vishvananda/netlink/nl"
    17  	"github.com/vishvananda/netns"
    18  )
    19  
    20  func TestHandleCreateClose(t *testing.T) {
    21  	h, err := NewHandle()
    22  	if err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	for _, f := range nl.SupportedNlFamilies {
    26  		sh, ok := h.sockets[f]
    27  		if !ok {
    28  			t.Fatalf("Handle socket(s) for family %d was not created", f)
    29  		}
    30  		if sh.Socket == nil {
    31  			t.Fatalf("Socket for family %d was not created", f)
    32  		}
    33  	}
    34  
    35  	h.Close()
    36  	if h.sockets != nil {
    37  		t.Fatalf("Handle socket(s) were not closed")
    38  	}
    39  }
    40  
    41  func TestHandleCreateNetns(t *testing.T) {
    42  	skipUnlessRoot(t)
    43  
    44  	id := make([]byte, 4)
    45  	if _, err := io.ReadFull(rand.Reader, id); err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	ifName := "dummy-" + hex.EncodeToString(id)
    49  
    50  	// Create an handle on the current netns
    51  	curNs, err := netns.Get()
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  	defer curNs.Close()
    56  
    57  	ch, err := NewHandleAt(curNs)
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  	defer ch.Close()
    62  
    63  	// Create an handle on a custom netns
    64  	newNs, err := netns.New()
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	defer newNs.Close()
    69  
    70  	nh, err := NewHandleAt(newNs)
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	defer nh.Close()
    75  
    76  	// Create an interface using the current handle
    77  	err = ch.LinkAdd(&Dummy{LinkAttrs{Name: ifName}})
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	l, err := ch.LinkByName(ifName)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	if l.Type() != "dummy" {
    86  		t.Fatalf("Unexpected link type: %s", l.Type())
    87  	}
    88  
    89  	// Verify the new handle cannot find the interface
    90  	ll, err := nh.LinkByName(ifName)
    91  	if err == nil {
    92  		t.Fatalf("Unexpected link found on netns %s: %v", newNs, ll)
    93  	}
    94  
    95  	// Move the interface to the new netns
    96  	err = ch.LinkSetNsFd(l, int(newNs))
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  
   101  	// Verify new netns handle can find the interface while current cannot
   102  	ll, err = nh.LinkByName(ifName)
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	if ll.Type() != "dummy" {
   107  		t.Fatalf("Unexpected link type: %s", ll.Type())
   108  	}
   109  	ll, err = ch.LinkByName(ifName)
   110  	if err == nil {
   111  		t.Fatalf("Unexpected link found on netns %s: %v", curNs, ll)
   112  	}
   113  }
   114  
   115  func TestHandleTimeout(t *testing.T) {
   116  	h, err := NewHandle()
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	defer h.Close()
   121  
   122  	for _, sh := range h.sockets {
   123  		verifySockTimeVal(t, sh.Socket, time.Duration(0))
   124  	}
   125  
   126  	const timeout = 2*time.Second + 8*time.Millisecond
   127  	h.SetSocketTimeout(timeout)
   128  
   129  	for _, sh := range h.sockets {
   130  		verifySockTimeVal(t, sh.Socket, timeout)
   131  	}
   132  }
   133  
   134  func verifySockTimeVal(t *testing.T, socket *nl.NetlinkSocket, expTimeout time.Duration) {
   135  	t.Helper()
   136  	send, receive := socket.GetTimeouts()
   137  	if send != expTimeout || receive != expTimeout {
   138  		t.Fatalf("Expected timeout: %v, got Send: %v, Receive: %v", expTimeout, send, receive)
   139  	}
   140  }
   141  
   142  func TestHandleReceiveBuffer(t *testing.T) {
   143  	h, err := NewHandle()
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	defer h.Close()
   148  	if err := h.SetSocketReceiveBufferSize(65536, false); err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	sizes, err := h.GetSocketReceiveBufferSize()
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	if len(sizes) != len(h.sockets) {
   156  		t.Fatalf("Unexpected number of socket buffer sizes: %d (expected %d)",
   157  			len(sizes), len(h.sockets))
   158  	}
   159  	for _, s := range sizes {
   160  		if s < 65536 || s > 2*65536 {
   161  			t.Fatalf("Unexpected socket receive buffer size: %d (expected around %d)",
   162  				s, 65536)
   163  		}
   164  	}
   165  }
   166  
   167  var (
   168  	iter      = 10
   169  	numThread = uint32(4)
   170  	prefix    = "iface"
   171  	handle1   *Handle
   172  	handle2   *Handle
   173  	ns1       netns.NsHandle
   174  	ns2       netns.NsHandle
   175  	done      uint32
   176  	initError error
   177  	once      sync.Once
   178  )
   179  
   180  func getXfrmState(thread int) *XfrmState {
   181  	return &XfrmState{
   182  		Src:   net.IPv4(byte(192), byte(168), 1, byte(1+thread)),
   183  		Dst:   net.IPv4(byte(192), byte(168), 2, byte(1+thread)),
   184  		Proto: XFRM_PROTO_AH,
   185  		Mode:  XFRM_MODE_TUNNEL,
   186  		Spi:   thread,
   187  		Auth: &XfrmStateAlgo{
   188  			Name: "hmac(sha256)",
   189  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   190  		},
   191  	}
   192  }
   193  
   194  func getXfrmPolicy(thread int) *XfrmPolicy {
   195  	return &XfrmPolicy{
   196  		Src:     &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}},
   197  		Dst:     &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}},
   198  		Proto:   17,
   199  		DstPort: 1234,
   200  		SrcPort: 5678,
   201  		Dir:     XFRM_DIR_OUT,
   202  		Tmpls: []XfrmPolicyTmpl{
   203  			{
   204  				Src:   net.IPv4(byte(192), byte(168), 1, byte(thread)),
   205  				Dst:   net.IPv4(byte(192), byte(168), 2, byte(thread)),
   206  				Proto: XFRM_PROTO_ESP,
   207  				Mode:  XFRM_MODE_TUNNEL,
   208  			},
   209  		},
   210  	}
   211  }
   212  func initParallel() {
   213  	ns1, initError = netns.New()
   214  	if initError != nil {
   215  		return
   216  	}
   217  	handle1, initError = NewHandleAt(ns1)
   218  	if initError != nil {
   219  		return
   220  	}
   221  	ns2, initError = netns.New()
   222  	if initError != nil {
   223  		return
   224  	}
   225  	handle2, initError = NewHandleAt(ns2)
   226  	if initError != nil {
   227  		return
   228  	}
   229  }
   230  
   231  func parallelDone() {
   232  	atomic.AddUint32(&done, 1)
   233  	if done == numThread {
   234  		if ns1.IsOpen() {
   235  			ns1.Close()
   236  		}
   237  		if ns2.IsOpen() {
   238  			ns2.Close()
   239  		}
   240  		if handle1 != nil {
   241  			handle1.Close()
   242  		}
   243  		if handle2 != nil {
   244  			handle2.Close()
   245  		}
   246  	}
   247  }
   248  
   249  // Do few route and xfrm operation on the two handles in parallel
   250  func runParallelTests(t *testing.T, thread int) {
   251  	skipUnlessRoot(t)
   252  	defer parallelDone()
   253  
   254  	t.Parallel()
   255  
   256  	once.Do(initParallel)
   257  	if initError != nil {
   258  		t.Fatal(initError)
   259  	}
   260  
   261  	state := getXfrmState(thread)
   262  	policy := getXfrmPolicy(thread)
   263  	for i := 0; i < iter; i++ {
   264  		ifName := fmt.Sprintf("%s_%d_%d", prefix, thread, i)
   265  		link := &Dummy{LinkAttrs{Name: ifName}}
   266  		err := handle1.LinkAdd(link)
   267  		if err != nil {
   268  			t.Fatal(err)
   269  		}
   270  		l, err := handle1.LinkByName(ifName)
   271  		if err != nil {
   272  			t.Fatal(err)
   273  		}
   274  		err = handle1.LinkSetUp(l)
   275  		if err != nil {
   276  			t.Fatal(err)
   277  		}
   278  		handle1.LinkSetNsFd(l, int(ns2))
   279  		if err != nil {
   280  			t.Fatal(err)
   281  		}
   282  		err = handle1.XfrmStateAdd(state)
   283  		if err != nil {
   284  			t.Fatal(err)
   285  		}
   286  		err = handle1.XfrmPolicyAdd(policy)
   287  		if err != nil {
   288  			t.Fatal(err)
   289  		}
   290  		err = handle2.LinkSetDown(l)
   291  		if err != nil {
   292  			t.Fatal(err)
   293  		}
   294  		err = handle2.XfrmStateAdd(state)
   295  		if err != nil {
   296  			t.Fatal(err)
   297  		}
   298  		err = handle2.XfrmPolicyAdd(policy)
   299  		if err != nil {
   300  			t.Fatal(err)
   301  		}
   302  		_, err = handle2.LinkByName(ifName)
   303  		if err != nil {
   304  			t.Fatal(err)
   305  		}
   306  		handle2.LinkSetNsFd(l, int(ns1))
   307  		if err != nil {
   308  			t.Fatal(err)
   309  		}
   310  		err = handle1.LinkSetUp(l)
   311  		if err != nil {
   312  			t.Fatal(err)
   313  		}
   314  		_, err = handle1.LinkByName(ifName)
   315  		if err != nil {
   316  			t.Fatal(err)
   317  		}
   318  		err = handle1.XfrmPolicyDel(policy)
   319  		if err != nil {
   320  			t.Fatal(err)
   321  		}
   322  		err = handle2.XfrmPolicyDel(policy)
   323  		if err != nil {
   324  			t.Fatal(err)
   325  		}
   326  		err = handle1.XfrmStateDel(state)
   327  		if err != nil {
   328  			t.Fatal(err)
   329  		}
   330  		err = handle2.XfrmStateDel(state)
   331  		if err != nil {
   332  			t.Fatal(err)
   333  		}
   334  	}
   335  }
   336  
   337  func TestHandleParallel1(t *testing.T) {
   338  	runParallelTests(t, 1)
   339  }
   340  
   341  func TestHandleParallel2(t *testing.T) {
   342  	runParallelTests(t, 2)
   343  }
   344  
   345  func TestHandleParallel3(t *testing.T) {
   346  	runParallelTests(t, 3)
   347  }
   348  
   349  func TestHandleParallel4(t *testing.T) {
   350  	runParallelTests(t, 4)
   351  }