github.com/vishvananda/netlink@v1.3.0/devlink_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package netlink
     5  
     6  import (
     7  	"flag"
     8  	"math/rand"
     9  	"net"
    10  	"os"
    11  	"strconv"
    12  	"testing"
    13  
    14  	"github.com/vishvananda/netlink/nl"
    15  )
    16  
    17  func TestDevLinkGetDeviceList(t *testing.T) {
    18  	minKernelRequired(t, 4, 12)
    19  	setUpNetlinkTestWithKModule(t, "devlink")
    20  	_, err := DevLinkGetDeviceList()
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  }
    25  
    26  func TestDevLinkGetDeviceByName(t *testing.T) {
    27  	minKernelRequired(t, 4, 12)
    28  	setUpNetlinkTestWithKModule(t, "devlink")
    29  	_, err := DevLinkGetDeviceByName("foo", "bar")
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  }
    34  
    35  func TestDevLinkSetEswitchMode(t *testing.T) {
    36  	minKernelRequired(t, 4, 12)
    37  	setUpNetlinkTestWithKModule(t, "devlink")
    38  	dev, err := DevLinkGetDeviceByName("foo", "bar")
    39  	if err != nil {
    40  		t.Fatal(err)
    41  	}
    42  	err = DevLinkSetEswitchMode(dev, "switchdev")
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	err = DevLinkSetEswitchMode(dev, "legacy")
    47  	if err != nil {
    48  		t.Fatal(err)
    49  	}
    50  }
    51  
    52  func TestDevLinkGetAllPortList(t *testing.T) {
    53  	minKernelRequired(t, 5, 4)
    54  	ports, err := DevLinkGetAllPortList()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	t.Log("devlink port count = ", len(ports))
    59  	for _, port := range ports {
    60  		t.Log(*port)
    61  	}
    62  }
    63  
    64  func TestDevLinkAddDelSfPort(t *testing.T) {
    65  	var addAttrs DevLinkPortAddAttrs
    66  	minKernelRequired(t, 5, 13)
    67  	if bus == "" || device == "" {
    68  		t.Log("devlink bus and device are empty, skipping test")
    69  		return
    70  	}
    71  
    72  	dev, err := DevLinkGetDeviceByName(bus, device)
    73  	if err != nil {
    74  		t.Fatal(err)
    75  		return
    76  	}
    77  	addAttrs.SfNumberValid = true
    78  	addAttrs.SfNumber = uint32(sfnum)
    79  	addAttrs.PfNumber = 0
    80  	port, err2 := DevLinkPortAdd(dev.BusName, dev.DeviceName, 7, addAttrs)
    81  	if err2 != nil {
    82  		t.Fatal(err2)
    83  		return
    84  	}
    85  	t.Log(*port)
    86  	if port.Fn != nil {
    87  		t.Log("function attributes = ", *port.Fn)
    88  	}
    89  	err2 = DevLinkPortDel(dev.BusName, dev.DeviceName, port.PortIndex)
    90  	if err2 != nil {
    91  		t.Fatal(err2)
    92  	}
    93  }
    94  
    95  func TestDevLinkSfPortFnSet(t *testing.T) {
    96  	var addAttrs DevLinkPortAddAttrs
    97  	var stateAttr DevlinkPortFnSetAttrs
    98  
    99  	minKernelRequired(t, 5, 12)
   100  	if bus == "" || device == "" {
   101  		t.Log("devlink bus and device are empty, skipping test")
   102  		return
   103  	}
   104  
   105  	dev, err := DevLinkGetDeviceByName(bus, device)
   106  	if err != nil {
   107  		t.Fatal(err)
   108  		return
   109  	}
   110  	addAttrs.SfNumberValid = true
   111  	addAttrs.SfNumber = uint32(sfnum)
   112  	addAttrs.PfNumber = 0
   113  	port, err2 := DevLinkPortAdd(dev.BusName, dev.DeviceName, 7, addAttrs)
   114  	if err2 != nil {
   115  		t.Fatal(err2)
   116  		return
   117  	}
   118  	t.Log(*port)
   119  	if port.Fn != nil {
   120  		t.Log("function attributes = ", *port.Fn)
   121  	}
   122  	macAttr := DevlinkPortFnSetAttrs{
   123  		FnAttrs: DevlinkPortFn{
   124  			HwAddr: net.HardwareAddr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55},
   125  		},
   126  		HwAddrValid: true,
   127  	}
   128  	err2 = DevlinkPortFnSet(dev.BusName, dev.DeviceName, port.PortIndex, macAttr)
   129  	if err2 != nil {
   130  		t.Log("function mac set err = ", err2)
   131  	}
   132  	stateAttr.FnAttrs.State = 1
   133  	stateAttr.StateValid = true
   134  	err2 = DevlinkPortFnSet(dev.BusName, dev.DeviceName, port.PortIndex, stateAttr)
   135  	if err2 != nil {
   136  		t.Log("function state set err = ", err2)
   137  	}
   138  
   139  	port, err3 := DevLinkGetPortByIndex(dev.BusName, dev.DeviceName, port.PortIndex)
   140  	if err3 == nil {
   141  		t.Log(*port)
   142  		t.Log(*port.Fn)
   143  	}
   144  	err2 = DevLinkPortDel(dev.BusName, dev.DeviceName, port.PortIndex)
   145  	if err2 != nil {
   146  		t.Fatal(err2)
   147  	}
   148  }
   149  
   150  var bus string
   151  var device string
   152  var sfnum uint
   153  
   154  func init() {
   155  	flag.StringVar(&bus, "bus", "", "devlink device bus name")
   156  	flag.StringVar(&device, "device", "", "devlink device devicename")
   157  	flag.UintVar(&sfnum, "sfnum", 0, "devlink port sfnumber")
   158  }
   159  
   160  func TestDevlinkGetDeviceInfoByNameAsMap(t *testing.T) {
   161  	info, err := pkgHandle.DevlinkGetDeviceInfoByNameAsMap("pci", "0000:00:00.0", mockDevlinkInfoGetter)
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	testInfo := devlinkTestInfoParesd()
   166  	for k, v := range info {
   167  		if testInfo[k] != v {
   168  			t.Fatal("Value", v, "retrieved for key", k, "is not equal to", testInfo[k])
   169  		}
   170  	}
   171  }
   172  
   173  func TestDevlinkGetDeviceInfoByName(t *testing.T) {
   174  	info, err := pkgHandle.DevlinkGetDeviceInfoByName("pci", "0000:00:00.0", mockDevlinkInfoGetter)
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	testInfo := parseInfoData(devlinkTestInfoParesd())
   179  	if !areInfoStructsEqual(info, testInfo) {
   180  		t.Fatal("Info structures are not equal")
   181  	}
   182  }
   183  
   184  func TestDevlinkGetDeviceInfoByNameAsMapFail(t *testing.T) {
   185  	_, err := pkgHandle.DevlinkGetDeviceInfoByNameAsMap("pci", "0000:00:00.0", mockDevlinkInfoGetterEmpty)
   186  	if err == nil {
   187  		t.Fatal()
   188  	}
   189  }
   190  
   191  func TestDevlinkGetDeviceInfoByNameFail(t *testing.T) {
   192  	_, err := pkgHandle.DevlinkGetDeviceInfoByName("pci", "0000:00:00.0", mockDevlinkInfoGetterEmpty)
   193  	if err == nil {
   194  		t.Fatal()
   195  	}
   196  }
   197  
   198  func mockDevlinkInfoGetter(bus, device string) ([]byte, error) {
   199  	return devlinkInfo(), nil
   200  }
   201  
   202  func mockDevlinkInfoGetterEmpty(bus, device string) ([]byte, error) {
   203  	return []byte{}, nil
   204  }
   205  
   206  func devlinkInfo() []byte {
   207  	return []byte{51, 1, 0, 0, 8, 0, 1, 0, 112, 99, 105, 0, 17, 0, 2, 0, 48,
   208  		48, 48, 48, 58, 56, 52, 58, 48, 48, 46, 48, 0, 0, 0, 0, 8, 0, 98, 0,
   209  		105, 99, 101, 0, 28, 0, 99, 0, 51, 48, 45, 56, 57, 45, 97, 51, 45,
   210  		102, 102, 45, 102, 102, 45, 99, 97, 45, 48, 53, 45, 54, 56, 0, 36,
   211  		0, 100, 0, 13, 0, 103, 0, 98, 111, 97, 114, 100, 46, 105, 100, 0, 0,
   212  		0, 0, 15, 0, 104, 0, 75, 56, 53, 53, 56, 53, 45, 48, 48, 48, 0, 0,
   213  		28, 0, 101, 0, 12, 0, 103, 0, 102, 119, 46, 109, 103, 109, 116, 0,
   214  		10, 0, 104, 0, 53, 46, 52, 46, 53, 0, 0, 0, 28, 0, 101, 0, 16, 0,
   215  		103, 0, 102, 119, 46, 109, 103, 109, 116, 46, 97, 112, 105, 0, 8, 0,
   216  		104, 0, 49, 46, 55, 0, 40, 0, 101, 0, 18, 0, 103, 0, 102, 119, 46,
   217  		109, 103, 109, 116, 46, 98, 117, 105, 108, 100, 0, 0, 0, 15, 0, 104,
   218  		0, 48, 120, 51, 57, 49, 102, 55, 54, 52, 48, 0, 0, 32, 0, 101, 0,
   219  		12, 0, 103, 0, 102, 119, 46, 117, 110, 100, 105, 0, 13, 0, 104, 0,
   220  		49, 46, 50, 56, 57, 56, 46, 48, 0, 0, 0, 0, 32, 0, 101, 0, 16, 0,
   221  		103, 0, 102, 119, 46, 112, 115, 105, 100, 46, 97, 112, 105, 0, 9, 0,
   222  		104, 0, 50, 46, 52, 50, 0, 0, 0, 0, 40, 0, 101, 0, 17, 0, 103, 0,
   223  		102, 119, 46, 98, 117, 110, 100, 108, 101, 95, 105, 100, 0, 0, 0, 0,
   224  		15, 0, 104, 0, 48, 120, 56, 48, 48, 48, 55, 48, 54, 98, 0, 0, 48, 0,
   225  		101, 0, 16, 0, 103, 0, 102, 119, 46, 97, 112, 112, 46, 110, 97, 109,
   226  		101, 0, 27, 0, 104, 0, 73, 67, 69, 32, 79, 83, 32, 68, 101, 102, 97,
   227  		117, 108, 116, 32, 80, 97, 99, 107, 97, 103, 101, 0, 0, 32, 0, 101,
   228  		0, 11, 0, 103, 0, 102, 119, 46, 97, 112, 112, 0, 0, 13, 0, 104, 0,
   229  		49, 46, 51, 46, 50, 52, 46, 48, 0, 0, 0, 0, 44, 0, 101, 0, 21, 0,
   230  		103, 0, 102, 119, 46, 97, 112, 112, 46, 98, 117, 110, 100, 108,
   231  		101, 95, 105, 100, 0, 0, 0, 0, 15, 0, 104, 0, 48, 120, 99, 48, 48,
   232  		48, 48, 48, 48, 49, 0, 0, 44, 0, 101, 0, 15, 0, 103, 0, 102, 119,
   233  		46, 110, 101, 116, 108, 105, 115, 116, 0, 0, 21, 0, 104, 0, 50, 46,
   234  		52, 48, 46, 50, 48, 48, 48, 45, 51, 46, 49, 54, 46, 48, 0, 0, 0, 0,
   235  		44, 0, 101, 0, 21, 0, 103, 0, 102, 119, 46, 110, 101, 116, 108, 105,
   236  		115, 116, 46, 98, 117, 105, 108, 100, 0, 0, 0, 0, 15, 0, 104, 0, 48,
   237  		120, 54, 55, 54, 97, 52, 56, 57, 100, 0, 0}
   238  }
   239  
   240  func devlinkTestInfoParesd() map[string]string {
   241  	return map[string]string{
   242  		"board.id":         "K85585-000",
   243  		"fw.app":           "1.3.24.0",
   244  		"fw.app.bundle_id": "0xc0000001",
   245  		"fw.app.name":      "ICE OS Default Package",
   246  		"fw.bundle_id":     "0x8000706b",
   247  		"fw.mgmt":          "5.4.5",
   248  		"fw.mgmt.api":      "1.7",
   249  		"fw.mgmt.build":    "0x391f7640",
   250  		"fw.netlist":       "2.40.2000-3.16.0",
   251  		"fw.netlist.build": "0x676a489d",
   252  		"fw.psid.api":      "2.42",
   253  		"fw.undi":          "1.2898.0",
   254  		"driver":           "ice",
   255  		"serialNumber":     "30-89-a3-ff-ff-ca-05-68",
   256  	}
   257  }
   258  
   259  func areInfoStructsEqual(first *DevlinkDeviceInfo, second *DevlinkDeviceInfo) bool {
   260  	if first.FwApp != second.FwApp || first.FwAppBoundleID != second.FwAppBoundleID ||
   261  		first.FwAppName != second.FwAppName || first.FwBoundleID != second.FwBoundleID ||
   262  		first.FwMgmt != second.FwMgmt || first.FwMgmtAPI != second.FwMgmtAPI ||
   263  		first.FwMgmtBuild != second.FwMgmtBuild || first.FwNetlist != second.FwNetlist ||
   264  		first.FwNetlistBuild != second.FwNetlistBuild || first.FwPsidAPI != second.FwPsidAPI ||
   265  		first.BoardID != second.BoardID || first.FwUndi != second.FwUndi ||
   266  		first.Driver != second.Driver || first.SerialNumber != second.SerialNumber {
   267  		return false
   268  	}
   269  	return true
   270  }
   271  
   272  func TestDevlinkGetDeviceResources(t *testing.T) {
   273  	minKernelRequired(t, 5, 11)
   274  	tearDown := setUpNetlinkTestWithKModule(t, "devlink")
   275  	defer tearDown()
   276  
   277  	if bus == "" || device == "" {
   278  		//TODO: setup netdevsim device instead of getting device from flags
   279  		t.Log("devlink bus and device are empty, skipping test")
   280  		t.SkipNow()
   281  	}
   282  
   283  	res, err := DevlinkGetDeviceResources(bus, device)
   284  	if err != nil {
   285  		t.Fatalf("failed to get device(%s/%s) resources. %s", bus, device, err)
   286  	}
   287  
   288  	if res.Bus != bus || res.Device != device {
   289  		t.Fatalf("missmatching bus/device")
   290  	}
   291  
   292  	t.Logf("Resources: %+v", res)
   293  }
   294  
   295  // devlink device parameters can be tested with netdevsim
   296  // function will create netdevsim/netdevsim<random_id> virtual device that can be used for testing
   297  // netdevsim module should be loaded to run devlink param tests
   298  func setupDevlinkDeviceParamTest(t *testing.T) (string, string, func()) {
   299  	t.Helper()
   300  	skipUnlessRoot(t)
   301  	skipUnlessKModuleLoaded(t, "netdevsim")
   302  	testDevID := strconv.Itoa(1000 + rand.Intn(1000))
   303  	err := os.WriteFile("/sys/bus/netdevsim/new_device", []byte(testDevID), 0755)
   304  	if err != nil {
   305  		t.Fatalf("can't create netdevsim test device %s: %v", testDevID, err)
   306  	}
   307  
   308  	return "netdevsim", "netdevsim" + testDevID, func() {
   309  		_ = os.WriteFile("/sys/bus/netdevsim/del_device", []byte(testDevID), 0755)
   310  	}
   311  }
   312  
   313  func TestDevlinkGetDeviceParams(t *testing.T) {
   314  	busName, deviceName, cleanupFunc := setupDevlinkDeviceParamTest(t)
   315  	defer cleanupFunc()
   316  	params, err := DevlinkGetDeviceParams(busName, deviceName)
   317  	if err != nil {
   318  		t.Fatalf("failed to get device(%s/%s) parameters. %s", busName, deviceName, err)
   319  	}
   320  	if len(params) == 0 {
   321  		t.Fatal("parameters list is empty")
   322  	}
   323  	for _, p := range params {
   324  		validateDeviceParams(t, p)
   325  	}
   326  }
   327  
   328  func TestDevlinkGetDeviceParamByName(t *testing.T) {
   329  	busName, deviceName, cleanupFunc := setupDevlinkDeviceParamTest(t)
   330  	defer cleanupFunc()
   331  	param, err := DevlinkGetDeviceParamByName(busName, deviceName, "max_macs")
   332  	if err != nil {
   333  		t.Fatalf("failed to get device(%s/%s) parameter max_macs. %s", busName, deviceName, err)
   334  	}
   335  	validateDeviceParams(t, param)
   336  }
   337  
   338  func TestDevlinkSetDeviceParam(t *testing.T) {
   339  	busName, deviceName, cleanupFunc := setupDevlinkDeviceParamTest(t)
   340  	defer cleanupFunc()
   341  	err := DevlinkSetDeviceParam(busName, deviceName, "max_macs", nl.DEVLINK_PARAM_CMODE_DRIVERINIT, uint32(8))
   342  	if err != nil {
   343  		t.Fatalf("failed to set max_macs for device(%s/%s): %s", busName, deviceName, err)
   344  	}
   345  	param, err := DevlinkGetDeviceParamByName(busName, deviceName, "max_macs")
   346  	if err != nil {
   347  		t.Fatalf("failed to get device(%s/%s) parameter max_macs. %s", busName, deviceName, err)
   348  	}
   349  	validateDeviceParams(t, param)
   350  	v, ok := param.Values[0].Data.(uint32)
   351  	if !ok {
   352  		t.Fatalf("unexpected value")
   353  	}
   354  	if v != uint32(8) {
   355  		t.Fatalf("value not set")
   356  	}
   357  }
   358  
   359  func validateDeviceParams(t *testing.T, p *DevlinkParam) {
   360  	if p.Name == "" {
   361  		t.Fatal("Name field not set")
   362  	}
   363  	if p.Name == "max_macs" && !p.IsGeneric {
   364  		t.Fatal("IsGeneric should be true for generic parameter")
   365  	}
   366  	// test1 is a driver-specific parameter in netdevsim device, check should
   367  	// also path on HW devices
   368  	if p.Name == "test1" && p.IsGeneric {
   369  		t.Fatal("IsGeneric should be false for driver-specific parameter")
   370  	}
   371  	switch p.Type {
   372  	case nl.DEVLINK_PARAM_TYPE_U8,
   373  		nl.DEVLINK_PARAM_TYPE_U16,
   374  		nl.DEVLINK_PARAM_TYPE_U32,
   375  		nl.DEVLINK_PARAM_TYPE_STRING,
   376  		nl.DEVLINK_PARAM_TYPE_BOOL:
   377  	default:
   378  		t.Fatal("Type has unexpected value")
   379  	}
   380  	if len(p.Values) == 0 {
   381  		t.Fatal("Values are not set")
   382  	}
   383  	for _, v := range p.Values {
   384  		switch v.CMODE {
   385  		case nl.DEVLINK_PARAM_CMODE_RUNTIME,
   386  			nl.DEVLINK_PARAM_CMODE_DRIVERINIT,
   387  			nl.DEVLINK_PARAM_CMODE_PERMANENT:
   388  		default:
   389  			t.Fatal("CMODE has unexpected value")
   390  		}
   391  		if p.Name == "max_macs" {
   392  			_, ok := v.Data.(uint32)
   393  			if !ok {
   394  				t.Fatalf("value max_macs has wrong type: %T, expected: uint32", v.Data)
   395  			}
   396  		}
   397  		if p.Name == "test1" {
   398  			_, ok := v.Data.(bool)
   399  			if !ok {
   400  				t.Fatalf("value test1 has wrong type: %T, expected: bool", v.Data)
   401  			}
   402  		}
   403  	}
   404  }