interface_test.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. // Copyright 2015 CoreOS, Inc.
  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. package network
  15. import (
  16. "net"
  17. "reflect"
  18. "testing"
  19. )
  20. func TestInterfaceGenerators(t *testing.T) {
  21. for _, tt := range []struct {
  22. name string
  23. netdev string
  24. link string
  25. network string
  26. kind string
  27. iface InterfaceGenerator
  28. }{
  29. {
  30. name: "",
  31. network: "[Match]\nMACAddress=00:01:02:03:04:05\n\n[Network]\n",
  32. kind: "physical",
  33. iface: &physicalInterface{logicalInterface{
  34. hwaddr: net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}),
  35. }},
  36. },
  37. {
  38. name: "testname",
  39. network: "[Match]\nName=testname\n\n[Network]\nBond=testbond1\nVLAN=testvlan1\nVLAN=testvlan2\n",
  40. kind: "physical",
  41. iface: &physicalInterface{logicalInterface{
  42. name: "testname",
  43. children: []networkInterface{
  44. &bondInterface{logicalInterface: logicalInterface{name: "testbond1"}},
  45. &vlanInterface{logicalInterface: logicalInterface{name: "testvlan1"}, id: 1},
  46. &vlanInterface{logicalInterface: logicalInterface{name: "testvlan2"}, id: 1},
  47. },
  48. }},
  49. },
  50. {
  51. name: "testname",
  52. netdev: "[NetDev]\nKind=bond\nName=testname\n\n[Bond]\n",
  53. network: "[Match]\nName=testname\n\n[Network]\nBond=testbond1\nVLAN=testvlan1\nVLAN=testvlan2\nDHCP=true\n",
  54. kind: "bond",
  55. iface: &bondInterface{logicalInterface: logicalInterface{
  56. name: "testname",
  57. config: configMethodDHCP{},
  58. children: []networkInterface{
  59. &bondInterface{logicalInterface: logicalInterface{name: "testbond1"}},
  60. &vlanInterface{logicalInterface: logicalInterface{name: "testvlan1"}, id: 1},
  61. &vlanInterface{logicalInterface: logicalInterface{name: "testvlan2"}, id: 1},
  62. },
  63. }},
  64. },
  65. {
  66. name: "testname",
  67. netdev: "[NetDev]\nKind=vlan\nName=testname\n\n[VLAN]\nId=1\n",
  68. network: "[Match]\nName=testname\n\n[Network]\n",
  69. kind: "vlan",
  70. iface: &vlanInterface{logicalInterface{name: "testname"}, 1, ""},
  71. },
  72. {
  73. name: "testname",
  74. netdev: "[NetDev]\nKind=vlan\nName=testname\nMACAddress=00:01:02:03:04:05\n\n[VLAN]\nId=1\n",
  75. network: "[Match]\nName=testname\n\n[Network]\n",
  76. kind: "vlan",
  77. iface: &vlanInterface{logicalInterface{name: "testname", config: configMethodStatic{hwaddress: net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5})}}, 1, ""},
  78. },
  79. {
  80. name: "testname",
  81. netdev: "[NetDev]\nKind=vlan\nName=testname\nMACAddress=00:01:02:03:04:05\n\n[VLAN]\nId=1\n",
  82. network: "[Match]\nName=testname\n\n[Network]\nDHCP=true\n",
  83. kind: "vlan",
  84. iface: &vlanInterface{logicalInterface{name: "testname", config: configMethodDHCP{hwaddress: net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5})}}, 1, ""},
  85. },
  86. {
  87. name: "testname",
  88. netdev: "[NetDev]\nKind=vlan\nName=testname\n\n[VLAN]\nId=0\n",
  89. network: "[Match]\nName=testname\n\n[Network]\nDomains=coreos.com example.com\nDNS=8.8.8.8\n\n[Address]\nAddress=192.168.1.100/24\n\n[Route]\nDestination=0.0.0.0/0\nGateway=1.2.3.4\n",
  90. kind: "vlan",
  91. iface: &vlanInterface{logicalInterface: logicalInterface{
  92. name: "testname",
  93. config: configMethodStatic{
  94. addresses: []net.IPNet{{IP: []byte{192, 168, 1, 100}, Mask: []byte{255, 255, 255, 0}}},
  95. nameservers: []net.IP{[]byte{8, 8, 8, 8}},
  96. domains: []string{"coreos.com", "example.com"},
  97. routes: []route{{destination: net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}}, gateway: []byte{1, 2, 3, 4}}},
  98. },
  99. }},
  100. },
  101. } {
  102. if name := tt.iface.Name(); name != tt.name {
  103. t.Fatalf("bad name (%q): want %q, got %q", tt.iface, tt.name, name)
  104. }
  105. if netdev := tt.iface.Netdev(); netdev != tt.netdev {
  106. t.Fatalf("bad netdev (%q): want %q, got %q", tt.iface, tt.netdev, netdev)
  107. }
  108. if link := tt.iface.Link(); link != tt.link {
  109. t.Fatalf("bad link (%q): want %q, got %q", tt.iface, tt.link, link)
  110. }
  111. if network := tt.iface.Network(); network != tt.network {
  112. t.Fatalf("bad network (%q): want %q, got %q", tt.iface, tt.network, network)
  113. }
  114. if kind := tt.iface.Type(); kind != tt.kind {
  115. t.Fatalf("bad type (%q): want %q, got %q", tt.iface, tt.kind, kind)
  116. }
  117. }
  118. }
  119. func TestModprobeParams(t *testing.T) {
  120. for _, tt := range []struct {
  121. i InterfaceGenerator
  122. p string
  123. }{
  124. {
  125. i: &physicalInterface{},
  126. p: "",
  127. },
  128. {
  129. i: &vlanInterface{},
  130. p: "",
  131. },
  132. {
  133. i: &bondInterface{
  134. logicalInterface{},
  135. nil,
  136. map[string]string{
  137. "a": "1",
  138. "b": "2",
  139. },
  140. },
  141. p: "a=1 b=2",
  142. },
  143. } {
  144. if p := tt.i.ModprobeParams(); p != tt.p {
  145. t.Fatalf("bad params (%q): got %s, want %s", tt.i, p, tt.p)
  146. }
  147. }
  148. }
  149. func TestBuildInterfacesLo(t *testing.T) {
  150. stanzas := []*stanzaInterface{
  151. {
  152. name: "lo",
  153. kind: interfacePhysical,
  154. auto: false,
  155. configMethod: configMethodLoopback{},
  156. options: map[string][]string{},
  157. },
  158. }
  159. interfaces := buildInterfaces(stanzas)
  160. if len(interfaces) != 0 {
  161. t.FailNow()
  162. }
  163. }
  164. func TestBuildInterfacesBlindBond(t *testing.T) {
  165. stanzas := []*stanzaInterface{
  166. {
  167. name: "bond0",
  168. kind: interfaceBond,
  169. auto: false,
  170. configMethod: configMethodManual{},
  171. options: map[string][]string{
  172. "bond-slaves": {"eth0"},
  173. },
  174. },
  175. }
  176. interfaces := buildInterfaces(stanzas)
  177. bond0 := &bondInterface{
  178. logicalInterface{
  179. name: "bond0",
  180. config: configMethodManual{},
  181. children: []networkInterface{},
  182. configDepth: 0,
  183. },
  184. []string{"eth0"},
  185. map[string]string{},
  186. }
  187. eth0 := &physicalInterface{
  188. logicalInterface{
  189. name: "eth0",
  190. config: configMethodManual{},
  191. children: []networkInterface{bond0},
  192. configDepth: 1,
  193. },
  194. }
  195. expect := []InterfaceGenerator{bond0, eth0}
  196. if !reflect.DeepEqual(interfaces, expect) {
  197. t.FailNow()
  198. }
  199. }
  200. func TestBuildInterfacesBlindVLAN(t *testing.T) {
  201. stanzas := []*stanzaInterface{
  202. {
  203. name: "vlan0",
  204. kind: interfaceVLAN,
  205. auto: false,
  206. configMethod: configMethodManual{},
  207. options: map[string][]string{
  208. "id": {"0"},
  209. "raw_device": {"eth0"},
  210. },
  211. },
  212. }
  213. interfaces := buildInterfaces(stanzas)
  214. vlan0 := &vlanInterface{
  215. logicalInterface{
  216. name: "vlan0",
  217. config: configMethodManual{},
  218. children: []networkInterface{},
  219. configDepth: 0,
  220. },
  221. 0,
  222. "eth0",
  223. }
  224. eth0 := &physicalInterface{
  225. logicalInterface{
  226. name: "eth0",
  227. config: configMethodManual{},
  228. children: []networkInterface{vlan0},
  229. configDepth: 1,
  230. },
  231. }
  232. expect := []InterfaceGenerator{eth0, vlan0}
  233. if !reflect.DeepEqual(interfaces, expect) {
  234. t.FailNow()
  235. }
  236. }
  237. func TestBuildInterfaces(t *testing.T) {
  238. stanzas := []*stanzaInterface{
  239. {
  240. name: "eth0",
  241. kind: interfacePhysical,
  242. auto: false,
  243. configMethod: configMethodManual{},
  244. options: map[string][]string{},
  245. },
  246. {
  247. name: "bond0",
  248. kind: interfaceBond,
  249. auto: false,
  250. configMethod: configMethodManual{},
  251. options: map[string][]string{
  252. "bond-slaves": {"eth0"},
  253. "bond-mode": {"4"},
  254. "bond-miimon": {"100"},
  255. },
  256. },
  257. {
  258. name: "bond1",
  259. kind: interfaceBond,
  260. auto: false,
  261. configMethod: configMethodManual{},
  262. options: map[string][]string{
  263. "bond-slaves": {"bond0"},
  264. },
  265. },
  266. {
  267. name: "vlan0",
  268. kind: interfaceVLAN,
  269. auto: false,
  270. configMethod: configMethodManual{},
  271. options: map[string][]string{
  272. "id": {"0"},
  273. "raw_device": {"eth0"},
  274. },
  275. },
  276. {
  277. name: "vlan1",
  278. kind: interfaceVLAN,
  279. auto: false,
  280. configMethod: configMethodManual{},
  281. options: map[string][]string{
  282. "id": {"1"},
  283. "raw_device": {"bond0"},
  284. },
  285. },
  286. }
  287. interfaces := buildInterfaces(stanzas)
  288. vlan1 := &vlanInterface{
  289. logicalInterface{
  290. name: "vlan1",
  291. config: configMethodManual{},
  292. children: []networkInterface{},
  293. configDepth: 0,
  294. },
  295. 1,
  296. "bond0",
  297. }
  298. vlan0 := &vlanInterface{
  299. logicalInterface{
  300. name: "vlan0",
  301. config: configMethodManual{},
  302. children: []networkInterface{},
  303. configDepth: 0,
  304. },
  305. 0,
  306. "eth0",
  307. }
  308. bond1 := &bondInterface{
  309. logicalInterface{
  310. name: "bond1",
  311. config: configMethodManual{},
  312. children: []networkInterface{},
  313. configDepth: 0,
  314. },
  315. []string{"bond0"},
  316. map[string]string{},
  317. }
  318. bond0 := &bondInterface{
  319. logicalInterface{
  320. name: "bond0",
  321. config: configMethodManual{},
  322. children: []networkInterface{bond1, vlan1},
  323. configDepth: 1,
  324. },
  325. []string{"eth0"},
  326. map[string]string{
  327. "mode": "4",
  328. "miimon": "100",
  329. },
  330. }
  331. eth0 := &physicalInterface{
  332. logicalInterface{
  333. name: "eth0",
  334. config: configMethodManual{},
  335. children: []networkInterface{bond0, vlan0},
  336. configDepth: 2,
  337. },
  338. }
  339. expect := []InterfaceGenerator{bond0, bond1, eth0, vlan0, vlan1}
  340. if !reflect.DeepEqual(interfaces, expect) {
  341. t.FailNow()
  342. }
  343. }
  344. func TestFilename(t *testing.T) {
  345. for _, tt := range []struct {
  346. i logicalInterface
  347. f string
  348. }{
  349. {logicalInterface{name: "iface", configDepth: 0}, "00-iface"},
  350. {logicalInterface{name: "iface", configDepth: 9}, "09-iface"},
  351. {logicalInterface{name: "iface", configDepth: 10}, "0a-iface"},
  352. {logicalInterface{name: "iface", configDepth: 53}, "35-iface"},
  353. {logicalInterface{hwaddr: net.HardwareAddr([]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}), configDepth: 1}, "01-01:23:45:67:89:ab"},
  354. {logicalInterface{name: "iface", hwaddr: net.HardwareAddr([]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}), configDepth: 1}, "01-iface"},
  355. } {
  356. if tt.i.Filename() != tt.f {
  357. t.Fatalf("bad filename (%q): got %q, want %q", tt.i, tt.i.Filename(), tt.f)
  358. }
  359. }
  360. }