1 /**
2 * collectd - src/netlink_test.c
3 *
4 * Copyright(c) 2020 Intel Corporation. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 * Kamil Wiatrowski <kamilx.wiatrowski@intel.com>
26 **/
27
28 #define plugin_dispatch_values plugin_dispatch_values_nl_test
29
30 #include "netlink.c" /* sic */
31 #include "testing.h"
32
33 #ifdef HAVE_IFLA_VF_STATS
34 static vf_stats_t g_test_res;
35 static char g_instance[512];
36 static int g_type_valid;
37 static void *g_test_payload;
38 static uint16_t g_attr_type;
39
40 /* mock functions */
plugin_dispatch_values_nl_test(value_list_t const * vl)41 int plugin_dispatch_values_nl_test(value_list_t const *vl) {
42 if (g_instance[0] == '\0')
43 sstrncpy(g_instance, vl->plugin_instance, sizeof(g_instance));
44
45 if (strcmp("vf_link_info", vl->type) == 0 &&
46 strcmp("vlan", vl->type_instance) == 0)
47 g_test_res.vlan = vl->values[0].gauge;
48
49 if (strcmp("vf_link_info", vl->type) == 0 &&
50 strcmp("spoofcheck", vl->type_instance) == 0)
51 g_test_res.spoofcheck = vl->values[0].gauge;
52
53 if (strcmp("vf_link_info", vl->type) == 0 &&
54 strcmp("link_state", vl->type_instance) == 0)
55 g_test_res.link_state = vl->values[0].gauge;
56
57 if (strcmp("vf_broadcast", vl->type) == 0)
58 g_test_res.broadcast = vl->values[0].derive;
59
60 if (strcmp("vf_multicast", vl->type) == 0)
61 g_test_res.multicast = vl->values[0].derive;
62
63 if (strcmp("vf_packets", vl->type) == 0) {
64 g_test_res.rx_packets = vl->values[0].derive;
65 g_test_res.tx_packets = vl->values[1].derive;
66 }
67
68 if (strcmp("vf_bytes", vl->type) == 0) {
69 g_test_res.rx_bytes = vl->values[0].derive;
70 g_test_res.tx_bytes = vl->values[1].derive;
71 }
72
73 return 0;
74 }
75
mnl_attr_type_valid(const struct nlattr * attr,uint16_t maxtype)76 int mnl_attr_type_valid(__attribute__((unused)) const struct nlattr *attr,
77 __attribute__((unused)) uint16_t maxtype) {
78 return g_type_valid;
79 }
80
mnl_attr_get_type(const struct nlattr * attr)81 uint16_t mnl_attr_get_type(__attribute__((unused)) const struct nlattr *attr) {
82 return g_attr_type;
83 }
84
mnl_attr_validate(const struct nlattr * attr,enum mnl_attr_data_type type)85 int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type) {
86 return attr->nla_type == type ? 0 : -1;
87 }
88
mnl_attr_validate2(const struct nlattr * attr,enum mnl_attr_data_type type,size_t len)89 int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type,
90 __attribute__((unused)) size_t len) {
91 return attr->nla_type == type ? 0 : -1;
92 }
93
mnl_attr_get_payload(const struct nlattr * attr)94 void *mnl_attr_get_payload(__attribute__((unused)) const struct nlattr *attr) {
95 return g_test_payload;
96 }
97 #else /* HAVE_IFLA_VF_STATS */
plugin_dispatch_values_nl_test(value_list_t const * vl)98 int plugin_dispatch_values_nl_test(__attribute__((unused))
99 value_list_t const *vl) {
100 return 0;
101 }
102 #endif
103 /* end mock functions */
104
105 #ifdef HAVE_IFLA_VF_STATS
DEF_TEST(plugin_nl_config)106 DEF_TEST(plugin_nl_config) {
107 EXPECT_EQ_INT(0, collect_vf_stats);
108 int ret = ir_config("CollectVFStats", "true");
109 EXPECT_EQ_INT(0, ret);
110 EXPECT_EQ_INT(1, collect_vf_stats);
111 ret = ir_config("CollectVFStats", "0");
112 EXPECT_EQ_INT(0, ret);
113 EXPECT_EQ_INT(0, collect_vf_stats);
114 ret = ir_config("CollectVFStats", "true false");
115 EXPECT_EQ_INT(-1, ret);
116 EXPECT_EQ_INT(0, collect_vf_stats);
117 ret = ir_config("CollectVFStats", "false");
118 EXPECT_EQ_INT(0, ret);
119 EXPECT_EQ_INT(0, collect_vf_stats);
120 ret = ir_config("CollectVFStats", "yes");
121 EXPECT_EQ_INT(0, ret);
122 EXPECT_EQ_INT(1, collect_vf_stats);
123
124 return 0;
125 }
126 #endif
127
DEF_TEST(ignorelist_test)128 DEF_TEST(ignorelist_test) {
129 ir_ignorelist_invert = 1;
130 int ret = add_ignorelist("eno1", "interface", NULL);
131 EXPECT_EQ_INT(0, ret);
132 ret = add_ignorelist("eno2", "if_detail", NULL);
133 EXPECT_EQ_INT(0, ret);
134
135 ret = check_ignorelist("eno1", "interface", NULL);
136 EXPECT_EQ_INT(0, ret);
137 ret = check_ignorelist("eno2", "if_detail", NULL);
138 EXPECT_EQ_INT(0, ret);
139 ret = check_ignorelist("eno1", "if_detail", NULL);
140 EXPECT_EQ_INT(1, ret);
141 ret = check_ignorelist("eno2", "interface", NULL);
142 EXPECT_EQ_INT(1, ret);
143
144 #if HAVE_REGEX_H
145 ret = add_ignorelist("/^eno[1-3]|^eth[0-2|4]/", "interface", NULL);
146 EXPECT_EQ_INT(0, ret);
147 ret = add_ignorelist("/^ens0[1|3]/", "if_detail", NULL);
148 EXPECT_EQ_INT(0, ret);
149
150 ret = check_ignorelist("eno1", "interface", NULL);
151 EXPECT_EQ_INT(0, ret);
152 ret = check_ignorelist("eno3", "interface", NULL);
153 EXPECT_EQ_INT(0, ret);
154 ret = check_ignorelist("eth0", "interface", NULL);
155 EXPECT_EQ_INT(0, ret);
156 ret = check_ignorelist("eth1", "interface", NULL);
157 EXPECT_EQ_INT(0, ret);
158 ret = check_ignorelist("eth2", "interface", NULL);
159 EXPECT_EQ_INT(0, ret);
160 ret = check_ignorelist("eth3", "interface", NULL);
161 EXPECT_EQ_INT(1, ret);
162 ret = check_ignorelist("eth4", "interface", NULL);
163 EXPECT_EQ_INT(0, ret);
164
165 ret = check_ignorelist("ens01", "if_detail", NULL);
166 EXPECT_EQ_INT(0, ret);
167 ret = check_ignorelist("ens02", "if_detail", NULL);
168 EXPECT_EQ_INT(1, ret);
169 ret = check_ignorelist("ens03", "if_detail", NULL);
170 EXPECT_EQ_INT(0, ret);
171
172 ret = check_ignorelist("eth0", "if_detail", NULL);
173 EXPECT_EQ_INT(1, ret);
174 ret = check_ignorelist("ens01", "interface", NULL);
175 EXPECT_EQ_INT(1, ret);
176 #endif
177
178 ir_ignorelist_invert = 0;
179 ret = check_ignorelist("eno1", "interface", NULL);
180 EXPECT_EQ_INT(1, ret);
181 ret = check_ignorelist("eno2", "if_detail", NULL);
182 EXPECT_EQ_INT(1, ret);
183 ret = check_ignorelist("abcdf", "if_detail", NULL);
184 EXPECT_EQ_INT(0, ret);
185 ret = check_ignorelist("abcfdf", "interface", NULL);
186 EXPECT_EQ_INT(0, ret);
187
188 #if HAVE_REGEX_H
189 ret = check_ignorelist("ens03", "if_detail", NULL);
190 EXPECT_EQ_INT(1, ret);
191 #endif
192 ir_ignorelist_invert = 1;
193
194 ir_ignorelist_t *next = NULL;
195 for (ir_ignorelist_t *i = ir_ignorelist_head; i != NULL; i = next) {
196 next = i->next;
197 #if HAVE_REGEX_H
198 if (i->rdevice != NULL) {
199 regfree(i->rdevice);
200 sfree(i->rdevice);
201 }
202 #endif
203 sfree(i->inst);
204 sfree(i->type);
205 sfree(i->device);
206 sfree(i);
207 }
208 ir_ignorelist_head = NULL;
209
210 return 0;
211 }
212
213 #ifdef HAVE_IFLA_VF_STATS
DEF_TEST(vf_submit_test)214 DEF_TEST(vf_submit_test) {
215 const char *test_dev = "eth0";
216 vf_stats_t test_stats;
217 struct ifla_vf_mac test_mac;
218 test_mac.mac[0] = 0x01;
219 test_mac.mac[1] = 0x1a;
220 test_mac.mac[2] = 0x2b;
221 test_mac.mac[3] = 0x3c;
222 test_mac.mac[4] = 0x4d;
223 test_mac.mac[5] = 0x5e;
224 test_mac.vf = 2;
225 test_stats.vf_mac = &test_mac;
226 test_stats.vlan = 100;
227 test_stats.spoofcheck = 1;
228 test_stats.link_state = 2;
229 test_stats.broadcast = 1234;
230 test_stats.multicast = 0;
231 test_stats.rx_packets = 21110;
232 test_stats.tx_packets = 31110;
233 test_stats.rx_bytes = 4294967295;
234 test_stats.tx_bytes = 8;
235
236 g_instance[0] = '\0';
237 vf_info_submit(test_dev, &test_stats);
238
239 EXPECT_EQ_STR("eth0_vf2_01:1a:2b:3c:4d:5e", g_instance);
240 EXPECT_EQ_UINT64(100, g_test_res.vlan);
241 EXPECT_EQ_UINT64(1, g_test_res.spoofcheck);
242 EXPECT_EQ_UINT64(2, g_test_res.link_state);
243 EXPECT_EQ_UINT64(1234, g_test_res.broadcast);
244 EXPECT_EQ_UINT64(0, g_test_res.multicast);
245 EXPECT_EQ_UINT64(21110, g_test_res.rx_packets);
246 EXPECT_EQ_UINT64(31110, g_test_res.tx_packets);
247 EXPECT_EQ_UINT64(4294967295, g_test_res.rx_bytes);
248 EXPECT_EQ_UINT64(8, g_test_res.tx_bytes);
249
250 return 0;
251 }
252
DEF_TEST(vf_info_attr_cb_test)253 DEF_TEST(vf_info_attr_cb_test) {
254 struct nlattr attr;
255 vf_stats_t test_stats = {0};
256
257 attr.nla_type = -1;
258 g_type_valid = -1;
259 int ret = vf_info_attr_cb(&attr, &test_stats);
260 EXPECT_EQ_INT(MNL_CB_OK, ret);
261
262 struct ifla_vf_mac test_mac;
263 g_test_payload = &test_mac;
264 g_type_valid = 0;
265 g_attr_type = IFLA_VF_MAC;
266 ret = vf_info_attr_cb(&attr, &test_stats);
267 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
268
269 attr.nla_type = MNL_TYPE_UNSPEC;
270 ret = vf_info_attr_cb(&attr, &test_stats);
271 EXPECT_EQ_INT(MNL_CB_OK, ret);
272 EXPECT_EQ_PTR(&test_mac, test_stats.vf_mac);
273
274 struct ifla_vf_vlan test_vlan = {.vlan = 1024, .qos = 2};
275 g_test_payload = &test_vlan;
276 g_attr_type = IFLA_VF_VLAN;
277 attr.nla_type = -1;
278 ret = vf_info_attr_cb(&attr, &test_stats);
279 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
280
281 attr.nla_type = MNL_TYPE_UNSPEC;
282 ret = vf_info_attr_cb(&attr, &test_stats);
283 EXPECT_EQ_INT(MNL_CB_OK, ret);
284 EXPECT_EQ_UINT64(1024, test_stats.vlan);
285 EXPECT_EQ_UINT64(2, test_stats.qos);
286
287 struct ifla_vf_tx_rate test_tx_rate = {.rate = 100};
288 g_test_payload = &test_tx_rate;
289 g_attr_type = IFLA_VF_TX_RATE;
290 attr.nla_type = -1;
291 ret = vf_info_attr_cb(&attr, &test_stats);
292 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
293
294 attr.nla_type = MNL_TYPE_UNSPEC;
295 ret = vf_info_attr_cb(&attr, &test_stats);
296 EXPECT_EQ_INT(MNL_CB_OK, ret);
297 EXPECT_EQ_UINT64(100, test_stats.txrate);
298
299 struct ifla_vf_spoofchk test_spoofchk = {.setting = 1};
300 g_test_payload = &test_spoofchk;
301 g_attr_type = IFLA_VF_SPOOFCHK;
302 attr.nla_type = -1;
303 ret = vf_info_attr_cb(&attr, &test_stats);
304 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
305
306 attr.nla_type = MNL_TYPE_UNSPEC;
307 ret = vf_info_attr_cb(&attr, &test_stats);
308 EXPECT_EQ_INT(MNL_CB_OK, ret);
309 EXPECT_EQ_UINT64(1, test_stats.spoofcheck);
310
311 struct ifla_vf_link_state test_link_state = {.link_state = 2};
312 g_test_payload = &test_link_state;
313 g_attr_type = IFLA_VF_LINK_STATE;
314 attr.nla_type = -1;
315 ret = vf_info_attr_cb(&attr, &test_stats);
316 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
317
318 attr.nla_type = MNL_TYPE_UNSPEC;
319 ret = vf_info_attr_cb(&attr, &test_stats);
320 EXPECT_EQ_INT(MNL_CB_OK, ret);
321 EXPECT_EQ_UINT64(2, test_stats.link_state);
322
323 struct ifla_vf_rate test_rate = {.min_tx_rate = 1000, .max_tx_rate = 2001};
324 g_test_payload = &test_rate;
325 g_attr_type = IFLA_VF_RATE;
326 attr.nla_type = -1;
327 ret = vf_info_attr_cb(&attr, &test_stats);
328 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
329
330 attr.nla_type = MNL_TYPE_UNSPEC;
331 ret = vf_info_attr_cb(&attr, &test_stats);
332 EXPECT_EQ_INT(MNL_CB_OK, ret);
333 EXPECT_EQ_UINT64(1000, test_stats.min_txrate);
334 EXPECT_EQ_UINT64(2001, test_stats.max_txrate);
335
336 struct ifla_vf_rss_query_en test_query_en = {.setting = 1};
337 g_test_payload = &test_query_en;
338 g_attr_type = IFLA_VF_RSS_QUERY_EN;
339 attr.nla_type = -1;
340 ret = vf_info_attr_cb(&attr, &test_stats);
341 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
342
343 attr.nla_type = MNL_TYPE_UNSPEC;
344 ret = vf_info_attr_cb(&attr, &test_stats);
345 EXPECT_EQ_INT(MNL_CB_OK, ret);
346 EXPECT_EQ_UINT64(1, test_stats.rss_query_en);
347
348 struct ifla_vf_trust test_trust = {.setting = 1};
349 g_test_payload = &test_trust;
350 g_attr_type = IFLA_VF_TRUST;
351 attr.nla_type = -1;
352 ret = vf_info_attr_cb(&attr, &test_stats);
353 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
354
355 attr.nla_type = MNL_TYPE_UNSPEC;
356 ret = vf_info_attr_cb(&attr, &test_stats);
357 EXPECT_EQ_INT(MNL_CB_OK, ret);
358 EXPECT_EQ_UINT64(1, test_stats.trust);
359
360 g_attr_type = IFLA_VF_STATS;
361 ret = vf_info_attr_cb(&attr, &test_stats);
362 EXPECT_EQ_INT(MNL_CB_ERROR, ret);
363
364 return 0;
365 }
366 #endif /* HAVE_IFLA_VF_STATS */
367
main(void)368 int main(void) {
369 #ifdef HAVE_IFLA_VF_STATS
370 RUN_TEST(plugin_nl_config);
371 #endif
372 RUN_TEST(ignorelist_test);
373
374 #ifdef HAVE_IFLA_VF_STATS
375 RUN_TEST(vf_submit_test);
376 RUN_TEST(vf_info_attr_cb_test);
377 #endif
378 END_TEST;
379 }
380