skip to content
==> tests/nic.c <==
1/* net.rs's tests: proc_net_dev, ext_wraps_and_resets, total_is_monotonic_and_skips_virtual,
2 * loopback_address_is_on_lo, this_machine_has_interfaces, nic_record_layout. */
3#include "mesh/check.h"
4#include "mesh/nic.h"
5
6#include <stdlib.h>
7#include <string.h>
8
9static const char *DEV = "Inter-|   Receive                                                |  Transmit\n"
10                         " face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed\n"
11                         "    lo: 1000      10    0    0    0     0          0         0     1000      10    0    0    0     0       0          0\n"
12                         "enP7s7: 18446744073709551000 200 1 2 0 0 0 0 3000 300 3 4 0 0 0 0\n"
13                         "docker0: 50 1 0 0 0 0 0 0 60 1 0 0 0 0 0 0\n";
14
15static mesh_nic_raw raw(const char *name, uint64_t b) {
16    mesh_nic_raw r;
17    memset(&r, 0, sizeof r);
18    strcpy(r.name, name);
19    r.v[0] = b;
20    r.v[1] = 2 * b;
21    for (int i = 0; i < 8; i++) r.bits[i] = 64;
22    return r;
23}
24
25static void sample(mesh_nics *s, const mesh_nic_raw *r, size_t n, mesh_nic_now **now, size_t *nn) {
26    if (*now) free(*now);
27    mesh_nics_sample(s, r, n, now, nn);
28}
29
30int main(void) {
31    mesh_nic_raw *r;
32    size_t n;
33    char *err = NULL;
34    CHECK_I(mesh_nic_parse_proc_net_dev(DEV, &r, &n, &err), 0);
35    CHECK_U(n, 3);
36    CHECK_S(r[1].name, "enP7s7");
37    const uint64_t want[8] = {18446744073709551000ull, 3000, 200, 300, 1, 3, 2, 4};
38    CHECK(memcmp(r[1].v, want, sizeof want) == 0);
39    free(r);
40    CHECK_I(mesh_nic_parse_proc_net_dev("a\nb\n", &r, &n, &err), -1);
41    free(err);
42    CHECK_I(mesh_nic_parse_proc_net_dev("a\nb\neth0: 1 2 3\n", &r, &n, &err), -1);
43    CHECK_S(err, "/proc/net/dev line 3: 3 fields, want 16");
44    free(err);
45    CHECK_I(mesh_nic_parse_proc_net_dev("a\nb\neth0 1 2\n", &r, &n, &err), -1);
46    CHECK_S(err, "/proc/net/dev line 3: no ':'");
47    free(err);
48
49    mesh_nic_ext e = mesh_nic_ext_new(0xfffffff0u);
50    CHECK_U(mesh_nic_ext_update(&e, 0x10, 32), 0x20);
51    CHECK_U(e.value, 0x100000010ull);
52    CHECK_U(mesh_nic_ext_update(&e, 0x30, 32), 0x20);
53    e = mesh_nic_ext_new(1000);
54    CHECK_U(mesh_nic_ext_update(&e, 1500, 64), 500);
55    CHECK_U(mesh_nic_ext_update(&e, 200, 64), 200);
56    CHECK_U(e.value, 1700);
57    e = mesh_nic_ext_new(UINT64_MAX - 5);
58    CHECK_U(mesh_nic_ext_update(&e, UINT64_MAX, 64), 5);
59
60    mesh_nics s = {0};
61    mesh_nic_now *now = NULL;
62    size_t nn;
63    mesh_nic_raw a[3] = {raw("lo", 100), raw("en0", 1000), raw("veth1", 50)};
64    sample(&s, a, 3, &now, &nn);
65    CHECK_U(s.total[0], 1000);
66    CHECK_U(s.total[1], 2000);
67    CHECK_U(s.counted, 1);
68    mesh_nic_raw b[3] = {raw("lo", 900), raw("en0", 1100), raw("en1", 5000)};
69    sample(&s, b, 3, &now, &nn);
70    CHECK_U(s.total[0], 1100);
71    CHECK_U(mesh_nic_lookup(now, nn, "en1")[0], 5000);
72    mesh_nic_raw c[2] = {raw("en0", 1200), raw("en1", 5100)};
73    sample(&s, c, 2, &now, &nn);
74    CHECK_U(s.total[0], 1300);
75    mesh_nic_raw d[2] = {raw("en0", 50), raw("en1", 5100)};
76    sample(&s, d, 2, &now, &nn);
77    CHECK_U(s.total[0], 1350);
78    mesh_nic_raw f[1] = {raw("en1", 5200)};
79    sample(&s, f, 1, &now, &nn);
80    CHECK_U(s.total[0], 1450);
81    free(now);
82    mesh_nics_free(&s);
83
84    char name[MESH_NIC_NAME_MAX];
85    CHECK_I(mesh_nic_iface_of("127.0.0.1", name, &err), 0);
86    CHECK(strncmp(name, "lo", 2) == 0);
87    CHECK_I(mesh_nic_iface_of("203.0.113.77", name, &err), -1);
88    CHECK_S(err, "no interface holds 203.0.113.77");
89    free(err);
90
91    CHECK_I(mesh_nic_read(&r, &n, &err), 0);
92    int lo = 0;
93    for (size_t i = 0; i < n; i++) lo |= strncmp(r[i].name, "lo", 2) == 0;
94    CHECK(lo);
95    free(r);
96
97    uint8_t rec[MESH_NIC_BYTES];
98    const uint64_t v[8] = {1, 2, 3, 4, 5, 6, 7, 8};
99    mesh_nic_record(rec, "enP2p1s0f1np1-long", v, 6, 1);
100    CHECK(memcmp(rec, "enP2p1s0f1np1-l\0", 16) == 0);
101    CHECK_U(rec[MESH_NI_TX_DROP], 8);
102    CHECK_U(rec[MESH_NI_LINKS], 6);
103    return mesh_check_done();
104}