2 * Copyright (C) 2015 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
22 #include "testutils.h"
24 #define LIBVIRT_VIRNETDEVPRIV_H_ALLOW
29 # include "virnetdevpriv.h"
31 # define VIR_FROM_THIS VIR_FROM_NONE
33 struct testVirNetDevGetLinkInfoData
{
34 const char *ifname
; /* ifname to get info on */
35 virNetDevIfState state
; /* expected state */
36 unsigned int speed
; /* expected speed */
40 testVirNetDevGetLinkInfo(const void *opaque
)
42 const struct testVirNetDevGetLinkInfoData
*data
= opaque
;
45 if (virNetDevGetLinkInfo(data
->ifname
, &lnk
) < 0)
48 if (lnk
.state
!= data
->state
) {
50 "Fetched link state (%s) doesn't match the expected one (%s)",
51 virNetDevIfStateTypeToString(lnk
.state
),
52 virNetDevIfStateTypeToString(data
->state
));
56 if (lnk
.speed
!= data
->speed
) {
58 "Fetched link speed (%u) doesn't match the expected one (%u)",
59 lnk
.speed
, data
->speed
);
66 # if defined(WITH_LIBNL)
69 (*real_virNetDevSendVfSetLinkRequest
)(const char *ifname
,
72 const size_t payloadLen
);
75 (*real_virNetDevSetVfMac
)(const char *ifname
,
77 const virMacAddr
*macaddr
,
81 (*real_virNetDevSetVfVlan
)(const char *ifname
,
88 VIR_MOCK_REAL_INIT(virNetDevSendVfSetLinkRequest
);
89 VIR_MOCK_REAL_INIT(virNetDevSetVfMac
);
90 VIR_MOCK_REAL_INIT(virNetDevSetVfVlan
);
94 virNetDevSetVfMac(const char *ifname
,
96 const virMacAddr
*macaddr
,
101 if (STREQ_NULLABLE(ifname
, "fakeiface-macerror")) {
103 } else if (STREQ_NULLABLE(ifname
, "fakeiface-altmacerror")) {
105 } else if (STREQ_NULLABLE(ifname
, "fakeiface-macerror-novlanerror")) {
107 } else if (STREQ_NULLABLE(ifname
, "fakeiface-macerror-vlanerror")) {
109 } else if (STREQ_NULLABLE(ifname
, "fakeiface-nomacerror-vlanerror")) {
111 } else if (STREQ_NULLABLE(ifname
, "fakeiface-nomacerror-novlanerror")) {
114 return real_virNetDevSetVfMac(ifname
, vf
, macaddr
, allowRetry
);
118 virNetDevSetVfVlan(const char *ifname
,
124 if (STREQ_NULLABLE(ifname
, "fakeiface-macerror-vlanerror")) {
126 } else if (STREQ_NULLABLE(ifname
, "fakeiface-nomacerror-vlanerror")) {
128 } else if (STREQ_NULLABLE(ifname
, "fakeiface-macerror-novlanerror")) {
130 } else if (STREQ_NULLABLE(ifname
, "fakeiface-nomacerror-novlanerror")) {
133 return real_virNetDevSetVfVlan(ifname
, vf
, vlanid
);
137 virNetDevSendVfSetLinkRequest(const char *ifname
,
140 const size_t payloadLen
)
144 if (STREQ_NULLABLE(ifname
, "fakeiface-eperm")) {
146 } else if (STREQ_NULLABLE(ifname
, "fakeiface-eagain")) {
148 } else if (STREQ_NULLABLE(ifname
, "fakeiface-einval")) {
150 } else if (STREQ_NULLABLE(ifname
, "fakeiface-ok")) {
153 return real_virNetDevSendVfSetLinkRequest(ifname
, vfInfoType
, payload
, payloadLen
);
157 testVirNetDevSetVfMac(const void *opaque G_GNUC_UNUSED
)
162 const virMacAddr macaddr
;
168 struct testCase testCases
[] = {
169 { .ifname
= "fakeiface-ok", .vf_num
= 1,
170 .macaddr
= { .addr
= { 0, 0, 0, 0, 0, 0 } }, .allow_retry
= false, .rc
= 0 },
171 { .ifname
= "fakeiface-ok", .vf_num
= 2,
172 .macaddr
= { .addr
= { 0, 0, 0, 7, 7, 7 } }, .allow_retry
= false, .rc
= 0 },
173 { .ifname
= "fakeiface-ok", .vf_num
= 3,
174 .macaddr
= { .addr
= { 0, 0, 0, 0, 0, 0 } }, .allow_retry
= true, .rc
= 0 },
175 { .ifname
= "fakeiface-ok", .vf_num
= 4,
176 .macaddr
= { .addr
= { 0, 0, 0, 7, 7, 7 } }, .allow_retry
= true, .rc
= 0 },
177 { .ifname
= "fakeiface-eperm", .vf_num
= 5,
178 .macaddr
= { .addr
= { 0, 0, 0, 0, 0, 0 } }, .allow_retry
= false, .rc
= -EPERM
},
179 { .ifname
= "fakeiface-einval", .vf_num
= 6,
180 .macaddr
= { .addr
= { 0, 0, 0, 0, 0, 0 } }, .allow_retry
= false, .rc
= -EINVAL
},
181 { .ifname
= "fakeiface-einval", .vf_num
= 7,
182 .macaddr
= { .addr
= { 0, 0, 0, 0, 0, 0 } }, .allow_retry
= true, .rc
= -EINVAL
},
183 { .ifname
= "fakeiface-einval", .vf_num
= 8,
184 .macaddr
= { .addr
= { 0, 0, 0, 7, 7, 7 } }, .allow_retry
= false, .rc
= -EINVAL
},
185 { .ifname
= "fakeiface-einval", .vf_num
= 9,
186 .macaddr
= { .addr
= { 0, 0, 0, 7, 7, 7 } }, .allow_retry
= true, .rc
= -EINVAL
},
189 for (i
= 0; i
< G_N_ELEMENTS(testCases
); ++i
) {
190 rc
= virNetDevSetVfMac(testCases
[i
].ifname
, testCases
[i
].vf_num
,
191 &testCases
[i
].macaddr
, &testCases
[i
].allow_retry
);
192 if (rc
!= testCases
[i
].rc
) {
200 testVirNetDevSetVfMissingMac(const void *opaque G_GNUC_UNUSED
)
202 bool allowRetry
= false;
203 /* NULL MAC pointer. */
204 if (virNetDevSetVfMac("fakeiface-ok", 1, NULL
, &allowRetry
) != -EINVAL
) {
208 if (virNetDevSetVfMac("fakeiface-ok", 1, NULL
, &allowRetry
) != -EINVAL
) {
215 testVirNetDevSetVfVlan(const void *opaque G_GNUC_UNUSED
)
223 struct nullVlanTestCase
{
230 const struct testCase testCases
[] = {
231 /* VLAN ID is out of range of valid values (0-4095). */
232 { .ifname
= "enxdeadbeefcafe", .vf_num
= 1, .vlan_id
= 4096, .rc
= -ERANGE
},
233 { .ifname
= "enxdeadbeefcafe", .vf_num
= 1, .vlan_id
= -1, .rc
= -ERANGE
},
234 { .ifname
= "fakeiface-eperm", .vf_num
= 1, .vlan_id
= 0, .rc
= -EPERM
},
235 { .ifname
= "fakeiface-eagain", .vf_num
= 1, .vlan_id
= 0, .rc
= -EAGAIN
},
236 /* Successful requests with vlan id 0 need to have a zero return code. */
237 { .ifname
= "fakeiface-ok", .vf_num
= 1, .vlan_id
= 0, .rc
= 0 },
238 /* Requests with a non-zero VLAN ID that result in an EPERM need to result in failures.
240 { .ifname
= "fakeiface-eperm", .vf_num
= 1, .vlan_id
= 42, .rc
= -EPERM
},
241 /* Requests with a non-zero VLAN ID that result in some other errors need to result in
243 { .ifname
= "fakeiface-eagain", .vf_num
= 1, .vlan_id
= 42, .rc
= -EAGAIN
},
244 /* Successful requests with a non-zero VLAN ID */
245 { .ifname
= "fakeiface-ok", .vf_num
= 1, .vlan_id
= 42, .rc
= 0 },
248 const struct nullVlanTestCase nullVLANTestCases
[] = {
249 { .ifname
= "fakeiface-eperm", .vf_num
= 1, .rc
= 0 },
250 { .ifname
= "fakeiface-eagain", .vf_num
= 1, .rc
= -EAGAIN
},
251 /* Successful requests with vlan id 0 need to have a zero return code. */
252 { .ifname
= "fakeiface-ok", .vf_num
= 1, .rc
= 0 },
255 for (i
= 0; i
< G_N_ELEMENTS(testCases
); ++i
) {
256 rc
= virNetDevSetVfVlan(testCases
[i
].ifname
, testCases
[i
].vf_num
, &testCases
[i
].vlan_id
);
257 if (rc
!= testCases
[i
].rc
) {
262 for (i
= 0; i
< G_N_ELEMENTS(nullVLANTestCases
); ++i
) {
263 rc
= virNetDevSetVfVlan(nullVLANTestCases
[i
].ifname
, nullVLANTestCases
[i
].vf_num
, NULL
);
264 if (rc
!= nullVLANTestCases
[i
].rc
) {
273 testVirNetDevSetVfConfig(const void *opaque G_GNUC_UNUSED
)
281 /* Nested functions are mocked so dummy values are used. */
282 const virMacAddr mac
= { .addr
= { 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE }};
284 const int vlanid
= 0;
285 bool *allowRetry
= NULL
;
287 const struct testCase testCases
[] = {
288 { .ifname
= "fakeiface-macerror", .rc
= -EBUSY
},
289 { .ifname
= "fakeiface-altmacerror", .rc
= -EINVAL
},
290 { .ifname
= "fakeiface-macerror-novlanerror", .rc
= -EAGAIN
},
291 { .ifname
= "fakeiface-macerror-vlanerror", .rc
= -ENODEV
},
292 { .ifname
= "fakeiface-nomacerror-novlanerror", .rc
= 0 },
295 for (i
= 0; i
< G_N_ELEMENTS(testCases
); ++i
) {
296 rc
= virNetDevSetVfConfig(testCases
[i
].ifname
, vfNum
, &mac
, &vlanid
, allowRetry
);
297 if (rc
!= testCases
[i
].rc
) {
304 # endif /* defined(WITH_LIBNL) */
311 # define DO_TEST_LINK(ifname, state, speed) \
313 struct testVirNetDevGetLinkInfoData data = {ifname, state, speed}; \
314 if (virTestRun("Link info: " # ifname, \
315 testVirNetDevGetLinkInfo, &data) < 0) \
319 DO_TEST_LINK("eth0", VIR_NETDEV_IF_STATE_UP
, 1000);
320 DO_TEST_LINK("lo", VIR_NETDEV_IF_STATE_UNKNOWN
, 0);
321 DO_TEST_LINK("eth0-broken", VIR_NETDEV_IF_STATE_DOWN
, 0);
323 # if defined(WITH_LIBNL)
325 if (virTestRun("Set VF MAC", testVirNetDevSetVfMac
, NULL
) < 0)
327 if (virTestRun("Set VF MAC: missing MAC pointer", testVirNetDevSetVfMissingMac
, NULL
) < 0)
329 if (virTestRun("Set VF VLAN", testVirNetDevSetVfVlan
, NULL
) < 0)
331 if (virTestRun("Set VF Config", testVirNetDevSetVfConfig
, NULL
) < 0)
334 # endif /* defined(WITH_LIBNL) */
336 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
339 VIR_TEST_MAIN_PRELOAD(mymain
, VIR_TEST_MOCK("virnetdev"))