| ... | @@ -667,7 +667,6 @@ pub const Insn = packed struct { | ... | @@ -667,7 +667,6 @@ pub const Insn = packed struct { |
| 667 | } | 667 | } |
| 668 | | 668 | |
| 669 | pub fn st(comptime size: Size, dst: Reg, off: i16, imm: i32) Insn { | 669 | 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"); | | |
| 671 | return Insn{ | 670 | return Insn{ |
| 672 | .code = MEM | @enumToInt(size) | ST, | 671 | .code = MEM | @enumToInt(size) | ST, |
| 673 | .dst = @enumToInt(dst), | 672 | .dst = @enumToInt(dst), |
| ... | @@ -1585,6 +1584,27 @@ pub fn map_delete_elem(fd: fd_t, key: []const u8) !void { | ... | @@ -1585,6 +1584,27 @@ pub fn map_delete_elem(fd: fd_t, key: []const u8) !void { |
| 1585 | } | 1584 | } |
| 1586 | } | 1585 | } |
| 1587 | | 1586 | |
| | 1587 | pub 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 | |
| 1588 | test "map lookup, update, and delete" { | 1608 | test "map lookup, update, and delete" { |
| 1589 | const key_size = 4; | 1609 | const key_size = 4; |
| 1590 | const value_size = 4; | 1610 | const value_size = 4; |
| ... | @@ -1605,6 +1625,16 @@ test "map lookup, update, and delete" { | ... | @@ -1605,6 +1625,16 @@ test "map lookup, update, and delete" { |
| 1605 | const second_key = [key_size]u8{ 0, 0, 0, 1 }; | 1625 | const second_key = [key_size]u8{ 0, 0, 0, 1 }; |
| 1606 | try expectError(error.ReachedMaxEntries, map_update_elem(map, &second_key, &value, 0)); | 1626 | try expectError(error.ReachedMaxEntries, map_update_elem(map, &second_key, &value, 0)); |
| 1607 | | 1627 | |
| | 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 | |
| 1608 | // succeed at deleting an existing elem | 1638 | // succeed at deleting an existing elem |
| 1609 | try map_delete_elem(map, &key); | 1639 | try map_delete_elem(map, &key); |
| 1610 | try expectError(error.NotFound, map_lookup_elem(map, &key, &value)); | 1640 | try expectError(error.NotFound, map_lookup_elem(map, &key, &value)); |