File Index
Files and directories
Sign in
FILE

xsk_xdp_progs.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2022 Intel */
  3
  4#include <linux/bpf.h>
  5#include <bpf/bpf_helpers.h>
  6#include <linux/if_ether.h>
  7#include <linux/ip.h>
  8#include <linux/errno.h>
  9#include "xsk_xdp_common.h"
 10
 11struct {
 12	__uint(type, BPF_MAP_TYPE_XSKMAP);
 13	__uint(max_entries, 2);
 14	__uint(key_size, sizeof(int));
 15	__uint(value_size, sizeof(int));
 16} xsk SEC(".maps");
 17
 18static unsigned int idx;
 19int adjust_value = 0;
 20int count = 0;
 21
 22SEC("xdp.frags") int xsk_def_prog(struct xdp_md *xdp)
 23{
 24	return bpf_redirect_map(&xsk, 0, XDP_DROP);
 25}
 26
 27SEC("xdp.frags") int xsk_xdp_drop(struct xdp_md *xdp)
 28{
 29	/* Drop every other packet */
 30	if (idx++ % 2)
 31		return XDP_DROP;
 32
 33	return bpf_redirect_map(&xsk, 0, XDP_DROP);
 34}
 35
 36SEC("xdp.frags") int xsk_xdp_populate_metadata(struct xdp_md *xdp)
 37{
 38	void *data, *data_meta;
 39	struct xdp_info *meta;
 40	int err;
 41
 42	/* Reserve enough for all custom metadata. */
 43	err = bpf_xdp_adjust_meta(xdp, -(int)sizeof(struct xdp_info));
 44	if (err)
 45		return XDP_DROP;
 46
 47	data = (void *)(long)xdp->data;
 48	data_meta = (void *)(long)xdp->data_meta;
 49
 50	if (data_meta + sizeof(struct xdp_info) > data)
 51		return XDP_DROP;
 52
 53	meta = data_meta;
 54	meta->count = count++;
 55
 56	return bpf_redirect_map(&xsk, 0, XDP_DROP);
 57}
 58
 59SEC("xdp") int xsk_xdp_shared_umem(struct xdp_md *xdp)
 60{
 61	void *data = (void *)(long)xdp->data;
 62	void *data_end = (void *)(long)xdp->data_end;
 63	struct ethhdr *eth = data;
 64
 65	if (eth + 1 > data_end)
 66		return XDP_DROP;
 67
 68	/* Redirecting packets based on the destination MAC address */
 69	idx = ((unsigned int)(eth->h_dest[5])) / 2;
 70	if (idx > MAX_SOCKETS)
 71		return XDP_DROP;
 72
 73	return bpf_redirect_map(&xsk, idx, XDP_DROP);
 74}
 75
 76SEC("xdp.frags") int xsk_xdp_adjust_tail(struct xdp_md *xdp)
 77{
 78	__u32 buff_len, curr_buff_len;
 79	int ret;
 80
 81	buff_len = bpf_xdp_get_buff_len(xdp);
 82	if (buff_len == 0)
 83		return XDP_DROP;
 84
 85	ret = bpf_xdp_adjust_tail(xdp, adjust_value);
 86	if (ret < 0) {
 87		/* Handle unsupported cases */
 88		if (ret == -EOPNOTSUPP) {
 89			/* Set adjust_value to -EOPNOTSUPP to indicate to userspace that this case
 90			 * is unsupported
 91			 */
 92			adjust_value = -EOPNOTSUPP;
 93			return bpf_redirect_map(&xsk, 0, XDP_DROP);
 94		}
 95
 96		return XDP_DROP;
 97	}
 98
 99	curr_buff_len = bpf_xdp_get_buff_len(xdp);
100	if (curr_buff_len != buff_len + adjust_value)
101		return XDP_DROP;
102
103	if (curr_buff_len > buff_len) {
104		__u32 *pkt_data = (void *)(long)xdp->data;
105		__u32 len, words_to_end, seq_num;
106
107		len = curr_buff_len - PKT_HDR_ALIGN;
108		words_to_end = len / sizeof(*pkt_data) - 1;
109		seq_num = words_to_end;
110
111		/* Convert sequence number to network byte order. Store this in the last 4 bytes of
112		 * the packet. Use 'adjust_value' to determine the position at the end of the
113		 * packet for storing the sequence number.
114		 */
115		seq_num = __constant_htonl(words_to_end);
116		bpf_xdp_store_bytes(xdp, curr_buff_len - sizeof(seq_num), &seq_num,
117				    sizeof(seq_num));
118	}
119
120	return bpf_redirect_map(&xsk, 0, XDP_DROP);
121}
122
123char _license[] SEC("license") = "GPL";
~/ Read-only file preview.