-
Notifications
You must be signed in to change notification settings - Fork 7
/
xdp_ping.zig
83 lines (71 loc) · 3.07 KB
/
xdp_ping.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
const std = @import("std");
const root = @import("root.zig");
const print = std.debug.print;
const testing = std.testing;
const allocator = root.allocator;
const libbpf = root.libbpf;
const c = @cImport({
@cInclude("net/if.h");
@cInclude("linux/if_link.h");
});
test "xdp_ping" {
const bytes = @embedFile("@xdp_ping");
_ = libbpf.libbpf_set_print(root.dbg_printf);
const obj = libbpf.bpf_object__open_mem(bytes.ptr, bytes.len, null);
if (obj == null) {
print("failed to open bpf object: {}\n", .{std.posix.errno(-1)});
return error.OPEN;
}
defer libbpf.bpf_object__close(obj);
var ret = libbpf.bpf_object__load(obj);
if (ret != 0) {
print("failed to load bpf object: {}\n", .{std.posix.errno(-1)});
return error.LOAD;
}
const prog = libbpf.bpf_object__find_program_by_name(obj, "xdp_ping").?;
const ipv4 = libbpf.bpf_object__find_map_by_name(obj, "ipv4").?;
const ipv6 = libbpf.bpf_object__find_map_by_name(obj, "ipv6").?;
const idx = c.if_nametoindex("lo");
if (idx == 0) {
print("failed to get index of lo: {}\n", .{std.posix.errno(-1)});
return error.DEV;
}
const prog_fd = libbpf.bpf_program__fd(prog);
ret = libbpf.bpf_xdp_attach(@intCast(idx), prog_fd, c.XDP_FLAGS_UPDATE_IF_NOEXIST, null);
if (ret < 0) {
print("failed to attach program: {}\n", .{std.posix.errno(-1)});
return error.ATTACH;
}
defer _ = libbpf.bpf_xdp_detach(@intCast(idx), c.XDP_FLAGS_UPDATE_IF_NOEXIST, null);
const expected: u32 = @as(*const u32, @alignCast(@ptrCast("ipv4"))).*;
const expected6: u32 = @as(*const u32, @alignCast(@ptrCast("ipv6"))).*;
var buf: [16]u8 = undefined;
const pattern = try std.fmt.bufPrint(&buf, "{x}", .{expected});
var result = try std.process.Child.run(.{ .allocator = allocator, .argv = &.{ "ping", "-4", "-c", "1", "-p", pattern, "-s", "4", "localhost" } });
if (testing.expect(result.term.Exited == 0)) |_| {
allocator.free(result.stdout);
allocator.free(result.stderr);
} else |err| {
print("{s}\n{s}\n", .{ result.stdout, result.stderr });
allocator.free(result.stdout);
allocator.free(result.stderr);
return err;
}
const pattern6 = try std.fmt.bufPrint(&buf, "{x}", .{expected6});
result = try std.process.Child.run(.{ .allocator = allocator, .argv = &.{ "ping", "-6", "-c", "1", "-p", pattern6, "-s", "4", "localhost" } });
if (testing.expect(result.term.Exited == 0)) |_| {
allocator.free(result.stdout);
allocator.free(result.stderr);
} else |err| {
print("{s}\n{s}\n", .{ result.stdout, result.stderr });
allocator.free(result.stdout);
allocator.free(result.stderr);
return err;
}
var k: u32 = 0;
var v: u32 = undefined;
ret = libbpf.bpf_map__lookup_elem(ipv4, &k, @sizeOf(@TypeOf(k)), &v, @sizeOf(@TypeOf(v)), 0);
try testing.expectEqual(expected, v);
ret = libbpf.bpf_map__lookup_elem(ipv6, &k, @sizeOf(@TypeOf(k)), &v, @sizeOf(@TypeOf(v)), 0);
try testing.expectEqual(expected6, v);
}