Skip to content

Commit

Permalink
bpf: add unit test for l3 to l2 traffic
Browse files Browse the repository at this point in the history
This commits add unittest case for L3 skb fast redirecting to L2 device.

Signed-off-by: Zhichuan Liang <gray.liang@isovalent.com>
  • Loading branch information
jschwinger233 authored and borkmann committed Mar 17, 2023
1 parent d56653d commit c08189c
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 6 deletions.
62 changes: 62 additions & 0 deletions bpf/tests/pktgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ static volatile const __u8 mac_six[] = {0x08, 0x14, 0x1C, 0x32, 0x52, 0x7E};
#define v4_pod_two IPV4(192, 168, 0, 2)
#define v4_pod_three IPV4(192, 168, 0, 3)

/* IPv6 addresses for pods in the cluster */
static volatile const __u8 v6_pod_one[] = {0xfd, 0x04, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};
static volatile const __u8 v6_pod_two[] = {0xfd, 0x04, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 2};
static volatile const __u8 v6_pod_three[] = {0xfd, 0x04, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 3};

/* Source port to be used by a client */
#define tcp_src_one __bpf_htons(22334)
#define tcp_src_two __bpf_htons(33445)
Expand Down Expand Up @@ -216,6 +224,46 @@ struct iphdr *pktgen__push_iphdr(struct pktgen *builder, __u32 option_bytes)
return layer;
}

/* helper to set the source and destination ipv6 address at the same time */
static __always_inline
void ipv6hdr__set_addrs(struct ipv6hdr *l3, __u8 *src, __u8 *dst)
{
memcpy((__u8 *)&l3->saddr, src, 16);
memcpy((__u8 *)&l3->daddr, dst, 16);
}

static __always_inline
__attribute__((warn_unused_result))
struct ipv6hdr *pktgen__push_ipv6hdr(struct pktgen *builder)
{
struct __ctx_buff *ctx = builder->ctx;
struct ipv6hdr *layer;
int layer_idx;

/* Request additional tailroom, and check that we got it. */
ctx_adjust_troom(ctx, builder->cur_off + sizeof(struct ipv6hdr) - ctx_full_len(ctx));
if (ctx_data(ctx) + builder->cur_off + sizeof(struct ipv6hdr) > ctx_data_end(ctx))
return 0;

/* Check that any value within the struct will not exceed a u16 which
* is the max allowed offset within a packet from ctx->data.
*/
if (builder->cur_off >= MAX_PACKET_OFF - sizeof(struct ipv6hdr))
return 0;

layer = ctx_data(ctx) + builder->cur_off;
layer_idx = pktgen__free_layer(builder);

if (layer_idx < 0)
return 0;

builder->layers[layer_idx] = PKT_LAYER_IPV6;
builder->layer_offsets[layer_idx] = builder->cur_off;
builder->cur_off += sizeof(struct ipv6hdr);

return layer;
}

/* Push a IPv4 header with sane defaults and options onto the packet */
static __always_inline
__attribute__((warn_unused_result))
Expand Down Expand Up @@ -243,6 +291,20 @@ struct iphdr *pktgen__push_default_iphdr(struct pktgen *builder)
return pktgen__push_default_iphdr_with_options(builder, 0);
}

/* Push an IPv6 header with sane defaults onto the packet */
struct ipv6hdr *pktgen__push_default_ipv6hdr(struct pktgen *builder)
{
struct ipv6hdr *hdr = pktgen__push_ipv6hdr(builder);

if (!hdr)
return 0;

hdr->version = 6;
hdr->hop_limit = 255;

return hdr;
}

/* Push an empty TCP header onto the packet */
static __always_inline
__attribute__((warn_unused_result))
Expand Down
12 changes: 6 additions & 6 deletions bpf/tests/tc_nodeport_l3_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ int ipv4_l3_to_l2_fast_redirect_pktgen(struct __ctx_buff *ctx)
pktgen__init(&builder, ctx);

/* We are building an L3 skb which doesn't have L2 header, so in theory
* we need to ignore pushing L2 header and set ctx->protocol =
* bpf_ntohs(ETH_P_IP), but bpf verifier doesn't allow us to do so, and
* kernel also doesn't handle an L3 skb properly (see https://elixir.bootlin.com/linux/v6.2.1/source/net/bpf/test_run.c#L1156).
* we need to skip L2 header and set ctx->protocol = bpf_ntohs(ETH_P_IP),
* but bpf verifier doesn't allow us to do so, and kernel also doesn't
* handle an L3 skb properly (see https://elixir.bootlin.com/linux/v6.2.1/source/net/bpf/test_run.c#L1156).
* Therefore we workaround the issue by pushing L2 header in the PKTGEN
* and stripping it in the SETUP.
*/
Expand Down Expand Up @@ -233,9 +233,9 @@ int ipv6_l3_to_l2_fast_redirect_pktgen(struct __ctx_buff *ctx)
pktgen__init(&builder, ctx);

/* We are building an L3 skb which doesn't have L2 header, so in theory
* we need to ignore pushing L2 header and set ctx->protocol =
* bpf_ntohs(ETH_P_IP), but bpf verifier doesn't allow us to do so, and
* kernel also doesn't handle an L3 skb properly (see https://elixir.bootlin.com/linux/v6.2.1/source/net/bpf/test_run.c#L1156).
* we need to skip L2 header and set ctx->protocol = bpf_ntohs(ETH_P_IP),
* but bpf verifier doesn't allow us to do so, and kernel also doesn't
* handle an L3 skb properly (see https://elixir.bootlin.com/linux/v6.2.1/source/net/bpf/test_run.c#L1156).
* Therefore we workaround the issue by pushing L2 header in the PKTGEN
* and stripping it in the SETUP.
*/
Expand Down

0 comments on commit c08189c

Please sign in to comment.