authorgravatar for bjorn.linse@gmail.combfredl <bjorn.linse@gmail.com> 2022-11-24 09:52:09+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-27 02:07:49-05:00
log0196010b0cdc0854286fa2442dc28b45f1278425
tree94779d112f29ca23f8f34c41d2052cb9c5c2a7cf
parent87a14f2b03e74b4f19a31d21becb634a4979a381

linux.bpf: expose map_get_next_key

Returning a bool allows to conveniently use it as the condition of a while loop. Also remove restriction that ST cannot be double-word. While imm is only 32-bit, this value is extended into a 64-bit memory location.

1 files changed, 31 insertions(+), 1 deletions(-)

lib/std/os/linux/bpf.zig+31-1
......@@ -667,7 +667,6 @@ pub const Insn = packed struct {
667667 }
668668
669669 pub fn st(comptime size: Size, dst: Reg, off: i16, imm: i32) Insn {
670 if (size == .double_word) @compileError("TODO: need to determine how to correctly handle double words");
671670 return Insn{
672671 .code = MEM | @enumToInt(size) | ST,
673672 .dst = @enumToInt(dst),
......@@ -1585,6 +1584,27 @@ pub fn map_delete_elem(fd: fd_t, key: []const u8) !void {
15851584 }
15861585}
15871586
1587pub fn map_get_next_key(fd: fd_t, key: []const u8, next_key: []u8) !bool {
1588 var attr = Attr{
1589 .map_elem = std.mem.zeroes(MapElemAttr),
1590 };
1591
1592 attr.map_elem.map_fd = fd;
1593 attr.map_elem.key = @ptrToInt(key.ptr);
1594 attr.map_elem.result.next_key = @ptrToInt(next_key.ptr);
1595
1596 const rc = linux.bpf(.map_get_next_key, &attr, @sizeOf(MapElemAttr));
1597 switch (errno(rc)) {
1598 .SUCCESS => return true,
1599 .BADF => return error.BadFd,
1600 .FAULT => unreachable,
1601 .INVAL => return error.FieldInAttrNeedsZeroing,
1602 .NOENT => return false,
1603 .PERM => return error.AccessDenied,
1604 else => |err| return unexpectedErrno(err),
1605 }
1606}
1607
15881608test "map lookup, update, and delete" {
15891609 const key_size = 4;
15901610 const value_size = 4;
......@@ -1605,6 +1625,16 @@ test "map lookup, update, and delete" {
16051625 const second_key = [key_size]u8{ 0, 0, 0, 1 };
16061626 try expectError(error.ReachedMaxEntries, map_update_elem(map, &second_key, &value, 0));
16071627
1628 // succeed at iterating all keys of map
1629 var lookup_key = [_]u8{ 1, 0, 0, 0 };
1630 var next_key = [_]u8{ 2, 3, 4, 5 }; // garbage value
1631 const status = try map_get_next_key(map, &lookup_key, &next_key);
1632 try expectEqual(status, true);
1633 try expectEqual(next_key, key);
1634 std.mem.copy(u8, &lookup_key, &next_key);
1635 const status2 = try map_get_next_key(map, &lookup_key, &next_key);
1636 try expectEqual(status2, false);
1637
16081638 // succeed at deleting an existing elem
16091639 try map_delete_elem(map, &key);
16101640 try expectError(error.NotFound, map_lookup_elem(map, &key, &value));