go.ligato.io/vpp-agent/v3@v3.5.0/proto/ligato/linux/interfaces/models_test.go (about)

     1  //  Copyright (c) 2018 Cisco and/or its affiliates.
     2  //
     3  //  Licensed under the Apache License, Version 2.0 (the "License");
     4  //  you may not use this file except in compliance with the License.
     5  //  You may obtain a copy of the License at:
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  //  Unless required by applicable law or agreed to in writing, software
    10  //  distributed under the License is distributed on an "AS IS" BASIS,
    11  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //  See the License for the specific language governing permissions and
    13  //  limitations under the License.
    14  
    15  package linux_interfaces
    16  
    17  import (
    18  	"testing"
    19  
    20  	"go.ligato.io/vpp-agent/v3/proto/ligato/netalloc"
    21  )
    22  
    23  func TestInterfaceAddressKey(t *testing.T) {
    24  	tests := []struct {
    25  		name        string
    26  		iface       string
    27  		address     string
    28  		source      netalloc.IPAddressSource
    29  		expectedKey string
    30  	}{
    31  		{
    32  			name:        "IPv4 address",
    33  			iface:       "memif0",
    34  			address:     "192.168.1.12/24",
    35  			source:      netalloc.IPAddressSource_STATIC,
    36  			expectedKey: "linux/interface/memif0/address/static/192.168.1.12/24",
    37  		},
    38  		{
    39  			name:        "IPv4 address from DHCP",
    40  			iface:       "memif0",
    41  			address:     "192.168.1.12/24",
    42  			source:      netalloc.IPAddressSource_FROM_DHCP,
    43  			expectedKey: "linux/interface/memif0/address/from_dhcp/192.168.1.12/24",
    44  		},
    45  		{
    46  			name:        "IPv6 address",
    47  			iface:       "memif0",
    48  			address:     "2001:db8::/32",
    49  			source:      netalloc.IPAddressSource_STATIC,
    50  			expectedKey: "linux/interface/memif0/address/static/2001:db8::/32",
    51  		},
    52  		{
    53  			name:        "IPv6 address from DHCP",
    54  			iface:       "memif0",
    55  			address:     "2001:db8::/32",
    56  			source:      netalloc.IPAddressSource_FROM_DHCP,
    57  			expectedKey: "linux/interface/memif0/address/from_dhcp/2001:db8::/32",
    58  		},
    59  		{
    60  			name:        "invalid interface",
    61  			iface:       "",
    62  			address:     "10.10.10.10/32",
    63  			source:      netalloc.IPAddressSource_STATIC,
    64  			expectedKey: "linux/interface/<invalid>/address/static/10.10.10.10/32",
    65  		},
    66  		{
    67  			name:        "undefined source",
    68  			iface:       "memif1",
    69  			address:     "10.10.10.10/32",
    70  			expectedKey: "linux/interface/memif1/address/undefined_source/10.10.10.10/32",
    71  		},
    72  		{
    73  			name:        "invalid address",
    74  			iface:       "tap0",
    75  			address:     "invalid-addr",
    76  			source:      netalloc.IPAddressSource_STATIC,
    77  			expectedKey: "linux/interface/tap0/address/static/invalid-addr",
    78  		},
    79  		{
    80  			name:        "missing mask",
    81  			iface:       "tap1",
    82  			address:     "10.10.10.10",
    83  			source:      netalloc.IPAddressSource_STATIC,
    84  			expectedKey: "linux/interface/tap1/address/static/10.10.10.10",
    85  		},
    86  		{
    87  			name:        "empty address",
    88  			iface:       "tap1",
    89  			address:     "",
    90  			source:      netalloc.IPAddressSource_STATIC,
    91  			expectedKey: "linux/interface/tap1/address/static/",
    92  		},
    93  		{
    94  			name:        "IPv4 address requested from netalloc",
    95  			iface:       "memif0",
    96  			address:     "alloc:net1",
    97  			source:      netalloc.IPAddressSource_STATIC,
    98  			expectedKey: "linux/interface/memif0/address/alloc_ref/alloc:net1",
    99  		},
   100  		{
   101  			name:        "IPv6 address requested from netalloc",
   102  			iface:       "memif0",
   103  			address:     "alloc:net1/IPV6_ADDR",
   104  			source:      netalloc.IPAddressSource_STATIC,
   105  			expectedKey: "linux/interface/memif0/address/alloc_ref/alloc:net1/IPV6_ADDR",
   106  		},
   107  	}
   108  	for _, test := range tests {
   109  		t.Run(test.name, func(t *testing.T) {
   110  			key := InterfaceAddressKey(test.iface, test.address, test.source)
   111  			if key != test.expectedKey {
   112  				t.Errorf("failed for: iface=%s address=%s source=%s\n"+
   113  					"expected key:\n\t%q\ngot key:\n\t%q",
   114  					test.iface, test.address, string(test.source), test.expectedKey, key)
   115  			}
   116  		})
   117  	}
   118  }
   119  
   120  func TestParseInterfaceAddressKey(t *testing.T) {
   121  	tests := []struct {
   122  		name               string
   123  		key                string
   124  		expectedIface      string
   125  		expectedIfaceAddr  string
   126  		expectedSource     netalloc.IPAddressSource
   127  		expectedInvalidKey bool
   128  		expectedIsAddrKey  bool
   129  	}{
   130  		{
   131  			name:              "IPv4 address",
   132  			key:               "linux/interface/memif0/address/static/192.168.1.12/24",
   133  			expectedIface:     "memif0",
   134  			expectedIfaceAddr: "192.168.1.12/24",
   135  			expectedSource:    netalloc.IPAddressSource_STATIC,
   136  			expectedIsAddrKey: true,
   137  		},
   138  		{
   139  			name:              "IPv4 address from DHCP",
   140  			key:               "linux/interface/memif0/address/from_dhcp/192.168.1.12/24",
   141  			expectedIface:     "memif0",
   142  			expectedIfaceAddr: "192.168.1.12/24",
   143  			expectedSource:    netalloc.IPAddressSource_FROM_DHCP,
   144  			expectedIsAddrKey: true,
   145  		},
   146  		{
   147  			name:              "IPv4 address requested from Netalloc",
   148  			key:               "linux/interface/memif0/address/alloc_ref/alloc:net1",
   149  			expectedIface:     "memif0",
   150  			expectedIfaceAddr: "alloc:net1",
   151  			expectedSource:    netalloc.IPAddressSource_ALLOC_REF,
   152  			expectedIsAddrKey: true,
   153  		},
   154  		{
   155  			name:              "IPv6 address",
   156  			key:               "linux/interface/tap1/address/static/2001:db8:85a3::8a2e:370:7334/48",
   157  			expectedIface:     "tap1",
   158  			expectedIfaceAddr: "2001:db8:85a3::8a2e:370:7334/48",
   159  			expectedSource:    netalloc.IPAddressSource_STATIC,
   160  			expectedIsAddrKey: true,
   161  		},
   162  		{
   163  			name:              "IPv6 address requested from netalloc",
   164  			key:               "linux/interface/tap1/address/alloc_ref/alloc:net1/IPV6_ADDR",
   165  			expectedIface:     "tap1",
   166  			expectedIfaceAddr: "alloc:net1/IPV6_ADDR",
   167  			expectedSource:    netalloc.IPAddressSource_ALLOC_REF,
   168  			expectedIsAddrKey: true,
   169  		},
   170  		{
   171  			name:              "IPv6 address from DHCP",
   172  			key:               "linux/interface/tap1/address/from_dhcp/2001:db8:85a3::8a2e:370:7334/48",
   173  			expectedIface:     "tap1",
   174  			expectedIfaceAddr: "2001:db8:85a3::8a2e:370:7334/48",
   175  			expectedSource:    netalloc.IPAddressSource_FROM_DHCP,
   176  			expectedIsAddrKey: true,
   177  		},
   178  		{
   179  			name:              "invalid interface",
   180  			key:               "linux/interface/<invalid>/address/static/10.10.10.10/30",
   181  			expectedIface:     "<invalid>",
   182  			expectedIfaceAddr: "10.10.10.10/30",
   183  			expectedSource:    netalloc.IPAddressSource_STATIC,
   184  			expectedIsAddrKey: true,
   185  		},
   186  		{
   187  			name:              "gbe interface",
   188  			key:               "linux/interface/GigabitEthernet0/8/0/address/static/192.168.5.5/16",
   189  			expectedIface:     "GigabitEthernet0/8/0",
   190  			expectedIfaceAddr: "192.168.5.5/16",
   191  			expectedSource:    netalloc.IPAddressSource_STATIC,
   192  			expectedIsAddrKey: true,
   193  		},
   194  		{
   195  			name:               "missing interface",
   196  			key:                "linux/interface//address/static/192.168.5.5/16",
   197  			expectedIface:      "<invalid>",
   198  			expectedIfaceAddr:  "192.168.5.5/16",
   199  			expectedSource:     netalloc.IPAddressSource_STATIC,
   200  			expectedInvalidKey: true,
   201  			expectedIsAddrKey:  true,
   202  		},
   203  		{
   204  			name:               "missing interface (from DHCP)",
   205  			key:                "linux/interface//address/from_dhcp/192.168.5.5/16",
   206  			expectedIface:      "<invalid>",
   207  			expectedIfaceAddr:  "192.168.5.5/16",
   208  			expectedSource:     netalloc.IPAddressSource_FROM_DHCP,
   209  			expectedInvalidKey: true,
   210  			expectedIsAddrKey:  true,
   211  		},
   212  		{
   213  			name:               "missing IP",
   214  			key:                "linux/interface/tap3/address/static/",
   215  			expectedIface:      "tap3",
   216  			expectedIfaceAddr:  "",
   217  			expectedSource:     netalloc.IPAddressSource_STATIC,
   218  			expectedInvalidKey: true,
   219  			expectedIsAddrKey:  true,
   220  		},
   221  		{
   222  			name:               "missing IP (from DHCP)",
   223  			key:                "linux/interface/tap3/address/from_dhcp/",
   224  			expectedIface:      "tap3",
   225  			expectedIfaceAddr:  "",
   226  			expectedSource:     netalloc.IPAddressSource_FROM_DHCP,
   227  			expectedInvalidKey: true,
   228  			expectedIsAddrKey:  true,
   229  		},
   230  		{
   231  			name:               "missing IP for Gbe",
   232  			key:                "linux/interface/Gbe0/1/2/address/static/",
   233  			expectedIface:      "Gbe0/1/2",
   234  			expectedIfaceAddr:  "",
   235  			expectedSource:     netalloc.IPAddressSource_STATIC,
   236  			expectedInvalidKey: true,
   237  			expectedIsAddrKey:  true,
   238  		},
   239  		{
   240  			name:              "not interface address key",
   241  			key:               "linux/config/v2/interface/GigabitEthernet0/8/0",
   242  			expectedIface:     "",
   243  			expectedIfaceAddr: "",
   244  			expectedIsAddrKey: false,
   245  		},
   246  		{
   247  			name:              "not interface address key #2",
   248  			key:               "linux/interface/veth0/vrf/blue",
   249  			expectedIface:     "",
   250  			expectedIfaceAddr: "",
   251  			expectedIsAddrKey: false,
   252  		},
   253  		{
   254  			name:               "invalid address source",
   255  			key:                "linux/interface/memif0/address/<invalid>/192.168.1.12/24",
   256  			expectedIface:      "memif0",
   257  			expectedInvalidKey: true,
   258  			expectedIsAddrKey:  true,
   259  		},
   260  		{
   261  			name:               "empty address source",
   262  			key:                "linux/interface/memif0/address//192.168.1.12/24",
   263  			expectedIface:      "memif0",
   264  			expectedInvalidKey: true,
   265  			expectedIsAddrKey:  true,
   266  		},
   267  		{
   268  			name:               "missing address source",
   269  			key:                "linux/interface/memif0/address/192.168.1.12/24",
   270  			expectedIface:      "memif0",
   271  			expectedInvalidKey: true,
   272  			expectedIsAddrKey:  true,
   273  		},
   274  	}
   275  	for _, test := range tests {
   276  		t.Run(test.name, func(t *testing.T) {
   277  			iface, ipAddr, source, invalidKey, isAddrKey := ParseInterfaceAddressKey(test.key)
   278  			if isAddrKey != test.expectedIsAddrKey {
   279  				t.Errorf("expected isAddrKey: %v\tgot: %v", test.expectedIsAddrKey, isAddrKey)
   280  			}
   281  			if source != test.expectedSource {
   282  				t.Errorf("expected source: %v\tgot: %v", test.expectedSource, source)
   283  			}
   284  			if invalidKey != test.expectedInvalidKey {
   285  				t.Errorf("expected invalidKey: %v\tgot: %v", test.expectedInvalidKey, invalidKey)
   286  			}
   287  			if iface != test.expectedIface {
   288  				t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface)
   289  			}
   290  			if ipAddr != test.expectedIfaceAddr {
   291  				t.Errorf("expected ipAddr: %s\tgot: %s", test.expectedIfaceAddr, ipAddr)
   292  			}
   293  		})
   294  	}
   295  }
   296  
   297  func TestInterfaceVrfKey(t *testing.T) {
   298  	tests := []struct {
   299  		name        string
   300  		iface       string
   301  		vrf         string
   302  		expectedKey string
   303  	}{
   304  		{
   305  			name:        "VRF 'blue'",
   306  			iface:       "veth0",
   307  			vrf:         "blue",
   308  			expectedKey: "linux/interface/veth0/vrf/blue",
   309  		},
   310  		{
   311  			name:        "VRF 'red'",
   312  			iface:       "veth0",
   313  			vrf:         "red",
   314  			expectedKey: "linux/interface/veth0/vrf/red",
   315  		},
   316  		{
   317  			name:        "invalid interface",
   318  			iface:       "",
   319  			vrf:         "blue",
   320  			expectedKey: "linux/interface/<invalid>/vrf/blue",
   321  		},
   322  		{
   323  			name:        "invalid VRF",
   324  			iface:       "veth0",
   325  			vrf:         "",
   326  			expectedKey: "linux/interface/veth0/vrf/<invalid>",
   327  		},
   328  	}
   329  	for _, test := range tests {
   330  		t.Run(test.name, func(t *testing.T) {
   331  			key := InterfaceVrfKey(test.iface, test.vrf)
   332  			if key != test.expectedKey {
   333  				t.Errorf("failed for: iface=%s vrf=%s\n"+
   334  					"expected key:\n\t%q\ngot key:\n\t%q",
   335  					test.iface, test.vrf, test.expectedKey, key)
   336  			}
   337  		})
   338  	}
   339  }
   340  
   341  func TestParseInterfaceVrfKey(t *testing.T) {
   342  	tests := []struct {
   343  		name               string
   344  		key                string
   345  		expectedIface      string
   346  		expectedIfaceVrf   string
   347  		expectedInvalidKey bool
   348  		expectedIsVrfKey   bool
   349  	}{
   350  		{
   351  			name:             "VRF 'blue'",
   352  			key:              "linux/interface/veth0/vrf/blue",
   353  			expectedIface:    "veth0",
   354  			expectedIfaceVrf: "blue",
   355  			expectedIsVrfKey: true,
   356  		},
   357  		{
   358  			name:             "VRF 'red'",
   359  			key:              "linux/interface/veth0/vrf/red",
   360  			expectedIface:    "veth0",
   361  			expectedIfaceVrf: "red",
   362  			expectedIsVrfKey: true,
   363  		},
   364  		{
   365  			name:               "missing interface",
   366  			key:                "linux/interface//vrf/blue",
   367  			expectedIface:      "<invalid>",
   368  			expectedIfaceVrf:   "blue",
   369  			expectedInvalidKey: true,
   370  			expectedIsVrfKey:   true,
   371  		},
   372  		{
   373  			name:               "missing VRF",
   374  			key:                "linux/interface/veth0/vrf",
   375  			expectedIface:      "veth0",
   376  			expectedIfaceVrf:   "<invalid>",
   377  			expectedInvalidKey: true,
   378  			expectedIsVrfKey:   true,
   379  		},
   380  		{
   381  			name:             "not interface VRF key",
   382  			key:              "linux/interface/tap1/address/static/2001:db8:85a3::8a2e:370:7334/48",
   383  			expectedIsVrfKey: false,
   384  		},
   385  		{
   386  			name:             "not interface VRF key #2",
   387  			key:              "linux/interface/tap1/address/static/192.168.1.1/32/vrf/blue",
   388  			expectedIsVrfKey: false,
   389  		},
   390  	}
   391  	for _, test := range tests {
   392  		t.Run(test.name, func(t *testing.T) {
   393  			iface, vrf, invalidKey, isVrfKey := ParseInterfaceVrfKey(test.key)
   394  			if isVrfKey != test.expectedIsVrfKey {
   395  				t.Errorf("expected isVrfKey: %v\tgot: %v", test.expectedIsVrfKey, isVrfKey)
   396  			}
   397  			if invalidKey != test.expectedInvalidKey {
   398  				t.Errorf("expected invalidKey: %v\tgot: %v", test.expectedInvalidKey, invalidKey)
   399  			}
   400  			if iface != test.expectedIface {
   401  				t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface)
   402  			}
   403  			if vrf != test.expectedIfaceVrf {
   404  				t.Errorf("expected vrf: %s\tgot: %s", test.expectedIfaceVrf, vrf)
   405  			}
   406  		})
   407  	}
   408  }