add ingress interface index to xdp context. (#623)
* add ingress interface index to xdp context. * Address PR feedback. Co-authored-by: Dave Thaler <dthaler@microsoft.com> Co-authored-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Родитель
9a7eebd993
Коммит
97bd9cf7f6
|
@ -9,12 +9,13 @@
|
|||
// XDP hook. We use "struct xdp_md" for cross-platform compatibility.
|
||||
typedef struct xdp_md
|
||||
{
|
||||
void* data; ///< Pointer to start of packet data.
|
||||
void* data_end; ///< Pointer to end of packet data.
|
||||
uint64_t data_meta; ///< Packet metadata.
|
||||
void* data; ///< Pointer to start of packet data.
|
||||
void* data_end; ///< Pointer to end of packet data.
|
||||
uint64_t data_meta; ///< Packet metadata.
|
||||
uint32_t ingress_ifindex; ///< Ingress interface index.
|
||||
|
||||
/* size: 12, cachelines: 1, members: 3 */
|
||||
/* last cacheline: 12 bytes */
|
||||
/* size: 26, cachelines: 1, members: 4 */
|
||||
/* last cacheline: 26 bytes */
|
||||
} xdp_md_t;
|
||||
|
||||
typedef enum _xdp_action
|
||||
|
|
|
@ -303,6 +303,9 @@ net_ebpf_ext_layer_2_classify(
|
|||
goto Done;
|
||||
}
|
||||
|
||||
net_xdp_ctx.ingress_ifindex =
|
||||
incoming_fixed_values->incomingValue[FWPS_FIELD_INBOUND_MAC_FRAME_NATIVE_INTERFACE_INDEX].value.uint32;
|
||||
|
||||
net_xdp_ctx.original_nbl = nbl;
|
||||
|
||||
net_buffer = NET_BUFFER_LIST_FIRST_NB(nbl);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define DROP_PACKET_PROGRAM_COUNT 1
|
||||
#define BIND_MONITOR_PROGRAM_COUNT 1
|
||||
|
||||
#define DROP_PACKET_MAP_COUNT 1
|
||||
#define DROP_PACKET_MAP_COUNT 2
|
||||
#define BIND_MONITOR_MAP_COUNT 2
|
||||
|
||||
static service_install_helper
|
||||
|
|
|
@ -226,7 +226,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
|||
error_message = nullptr;
|
||||
}
|
||||
REQUIRE(result == EBPF_SUCCESS);
|
||||
fd_t port_map_fd = bpf_object__find_map_fd_by_name(object, "port_map");
|
||||
fd_t dropped_packet_map_fd = bpf_object__find_map_fd_by_name(object, "dropped_packet_map");
|
||||
|
||||
REQUIRE(hook.attach_link(program_fd, &link) == EBPF_SUCCESS);
|
||||
|
||||
|
@ -234,7 +234,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
|||
|
||||
uint32_t key = 0;
|
||||
uint64_t value = 1000;
|
||||
REQUIRE(bpf_map_update_elem(port_map_fd, &key, &value, EBPF_ANY) == EBPF_SUCCESS);
|
||||
REQUIRE(bpf_map_update_elem(dropped_packet_map_fd, &key, &value, EBPF_ANY) == EBPF_SUCCESS);
|
||||
|
||||
// Test that we drop the packet and increment the map
|
||||
xdp_md_t ctx{packet.data(), packet.data() + packet.size()};
|
||||
|
@ -243,12 +243,12 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
|||
REQUIRE(hook.fire(&ctx, &hook_result) == EBPF_SUCCESS);
|
||||
REQUIRE(hook_result == 2);
|
||||
|
||||
REQUIRE(bpf_map_lookup_elem(port_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(value == 1001);
|
||||
|
||||
REQUIRE(bpf_map_delete_elem(port_map_fd, &key) == EBPF_SUCCESS);
|
||||
REQUIRE(bpf_map_delete_elem(dropped_packet_map_fd, &key) == EBPF_SUCCESS);
|
||||
|
||||
REQUIRE(bpf_map_lookup_elem(port_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(value == 0);
|
||||
|
||||
packet = prepare_udp_packet(10, ETHERNET_TYPE_IPV4);
|
||||
|
@ -257,9 +257,27 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
|||
REQUIRE(hook.fire(&ctx2, &hook_result) == EBPF_SUCCESS);
|
||||
REQUIRE(hook_result == 1);
|
||||
|
||||
REQUIRE(bpf_map_lookup_elem(port_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(value == 0);
|
||||
|
||||
fd_t interface_index_map_fd = bpf_object__find_map_fd_by_name(object, "interface_index_map");
|
||||
uint32_t if_index = 17;
|
||||
REQUIRE(bpf_map_update_elem(interface_index_map_fd, &key, &if_index, EBPF_ANY) == EBPF_SUCCESS);
|
||||
|
||||
packet = prepare_udp_packet(0, ETHERNET_TYPE_IPV4);
|
||||
// Fire a 0-length UDP packet on the interface index in the map, which should be dropped.
|
||||
xdp_md_t ctx3{packet.data(), packet.data() + packet.size(), 0, if_index};
|
||||
REQUIRE(hook.fire(&ctx3, &hook_result) == EBPF_SUCCESS);
|
||||
REQUIRE(hook_result == 2);
|
||||
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(value == 1);
|
||||
// Fire a 0-length packet on any interface that is not in the map, which should be allowed.
|
||||
xdp_md_t ctx4{packet.data(), packet.data() + packet.size(), 0, if_index + 1};
|
||||
REQUIRE(hook.fire(&ctx4, &hook_result) == EBPF_SUCCESS);
|
||||
REQUIRE(hook_result == 1);
|
||||
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||
REQUIRE(value == 1);
|
||||
|
||||
hook.detach_link(link);
|
||||
hook.close_link(link);
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ TEST_CASE("show verification droppacket.o", "[netsh][verification]")
|
|||
"\n"
|
||||
"0 errors\n"
|
||||
"Verification succeeded\n"
|
||||
"Program terminates within 114 instructions\n");
|
||||
"Program terminates within 151 instructions\n");
|
||||
}
|
||||
|
||||
TEST_CASE("show verification droppacket_unsafe.o", "[netsh][verification]")
|
||||
|
|
|
@ -10,19 +10,36 @@
|
|||
#include "ebpf.h"
|
||||
|
||||
SEC("maps")
|
||||
ebpf_map_definition_in_file_t port_map = {
|
||||
ebpf_map_definition_in_file_t dropped_packet_map = {
|
||||
.size = sizeof(ebpf_map_definition_in_file_t),
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(uint32_t),
|
||||
.value_size = sizeof(uint64_t),
|
||||
.max_entries = 1};
|
||||
|
||||
SEC("maps")
|
||||
ebpf_map_definition_in_file_t interface_index_map = {
|
||||
.size = sizeof(ebpf_map_definition_in_file_t),
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(uint32_t),
|
||||
.value_size = sizeof(uint32_t),
|
||||
.max_entries = 1};
|
||||
|
||||
SEC("xdp")
|
||||
int
|
||||
DropPacket(xdp_md_t* ctx)
|
||||
{
|
||||
int rc = XDP_PASS;
|
||||
ETHERNET_HEADER* eth = NULL;
|
||||
long key = 0;
|
||||
|
||||
uint32_t* interface_index = bpf_map_lookup_elem(&interface_index_map, &key);
|
||||
if (interface_index != NULL) {
|
||||
if (ctx->ingress_ifindex != *interface_index) {
|
||||
// Not interested in packets indicated over this interfce.
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((char*)ctx->data + sizeof(ETHERNET_HEADER) + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) > (char*)ctx->data_end)
|
||||
goto Done;
|
||||
|
@ -38,8 +55,7 @@ DropPacket(xdp_md_t* ctx)
|
|||
goto Done;
|
||||
UDP_HEADER* udp_header = (UDP_HEADER*)((char*)ipv4_header + sizeof(uint32_t) * ipv4_header->HeaderLength);
|
||||
if (ntohs(udp_header->length) <= sizeof(UDP_HEADER)) {
|
||||
long key = 0;
|
||||
long* count = bpf_map_lookup_elem(&port_map, &key);
|
||||
long* count = bpf_map_lookup_elem(&dropped_packet_map, &key);
|
||||
if (count)
|
||||
*count = (*count + 1);
|
||||
rc = XDP_DROP;
|
||||
|
|
|
@ -47,7 +47,7 @@ TEST_CASE("libbpf program", "[libbpf]")
|
|||
REQUIRE(fd2 == program_fd);
|
||||
|
||||
size_t size = bpf_program__size(program);
|
||||
REQUIRE(size == 272);
|
||||
REQUIRE(size == 376);
|
||||
|
||||
REQUIRE(bpf_program__next(program, object) == nullptr);
|
||||
REQUIRE(bpf_program__prev(program, object) == nullptr);
|
||||
|
@ -168,17 +168,24 @@ TEST_CASE("libbpf map", "[libbpf]")
|
|||
REQUIRE(result == 0);
|
||||
REQUIRE(object != nullptr);
|
||||
|
||||
// Get the first (and only) map.
|
||||
// Get the first map.
|
||||
struct bpf_map* map = bpf_map__next(nullptr, object);
|
||||
REQUIRE(map != nullptr);
|
||||
|
||||
// Verify that it's the only map.
|
||||
REQUIRE(bpf_map__next(map, object) == nullptr);
|
||||
// Verify that there are no maps before this.
|
||||
REQUIRE(bpf_map__prev(map, object) == nullptr);
|
||||
REQUIRE(bpf_map__prev(nullptr, object) == map);
|
||||
|
||||
// Get the next map.
|
||||
struct bpf_map* map2 = bpf_map__next(map, object);
|
||||
REQUIRE(map2 != nullptr);
|
||||
REQUIRE(bpf_map__prev(map2, object) == map);
|
||||
|
||||
// Verify that there are no other maps after this.
|
||||
REQUIRE(bpf_map__next(map2, object) == nullptr);
|
||||
REQUIRE(bpf_map__prev(nullptr, object) == map2);
|
||||
|
||||
const char* name = bpf_map__name(map);
|
||||
REQUIRE(strcmp(name, "port_map") == 0);
|
||||
REQUIRE(strcmp(name, "dropped_packet_map") == 0);
|
||||
REQUIRE(bpf_map__type(map) == BPF_MAP_TYPE_ARRAY);
|
||||
REQUIRE(bpf_map__key_size(map) == 4);
|
||||
REQUIRE(bpf_map__value_size(map) == 8);
|
||||
|
@ -962,7 +969,7 @@ TEST_CASE("bpf_obj_get_info_by_fd", "[libbpf]")
|
|||
REQUIRE(bpf_obj_get_info_by_fd(program_fd, &program_info, &program_info_size) == 0);
|
||||
REQUIRE(program_info_size == sizeof(program_info));
|
||||
REQUIRE(strcmp(program_info.name, program_name) == 0);
|
||||
REQUIRE(program_info.nr_map_ids == 1);
|
||||
REQUIRE(program_info.nr_map_ids == 2);
|
||||
|
||||
// Fetch info about the attachment and verify it matches what we'd expect.
|
||||
uint32_t link_id;
|
||||
|
|
Загрузка…
Ссылка в новой задаче