/* SPDX-License-Identifier: GPL-2.0
 * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc.
 *
 *  Example howto extract XDP RX-queue info
 */
#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/in.h>
#include "bpf_helpers.h"

/* Config setup from with userspace
 *
 * User-side setup ifindex in config_map, to verify that
 * ctx->ingress_ifindex is correct (against configured ifindex)
 */
struct config {
	__u32 action;
	int ifindex;
	__u32 options;
};
enum cfg_options_flags {
	NO_TOUCH = 0x0U,
	READ_MEM = 0x1U,
	SWAP_MAC = 0x2U,
};

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__type(key, int);
	__type(value, struct config);
	__uint(max_entries, 1);
} config_map SEC(".maps");

/* Common stats data record (shared with userspace) */
struct datarec {
	__u64 processed;
	__u64 issue;
};

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct datarec);
	__uint(max_entries, 1);
} stats_global_map SEC(".maps");

#define MAX_RXQs 64

/* Stats per rx_queue_index (per CPU) */
struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct datarec);
	__uint(max_entries, MAX_RXQs + 1);
} rx_queue_index_map SEC(".maps");

static __always_inline
void swap_src_dst_mac(void *data)
{
	unsigned short *p = data;
	unsigned short dst[3];

	dst[0] = p[0];
	dst[1] = p[1];
	dst[2] = p[2];
	p[0] = p[3];
	p[1] = p[4];
	p[2] = p[5];
	p[3] = dst[0];
	p[4] = dst[1];
	p[5] = dst[2];
}

SEC("xdp_prog0")
int  xdp_prognum0(struct xdp_md *ctx)
{
	void *data_end = (void *)(long)ctx->data_end;
	void *data     = (void *)(long)ctx->data;
	struct datarec *rec, *rxq_rec;
	int ingress_ifindex;
	struct config *config;
	u32 key = 0;

	/* Global stats record */
	rec = bpf_map_lookup_elem(&stats_global_map, &key);
	if (!rec)
		return XDP_ABORTED;
	rec->processed++;

	/* Accessing ctx->ingress_ifindex, cause BPF to rewrite BPF
	 * instructions inside kernel to access xdp_rxq->dev->ifindex
	 */
	ingress_ifindex = ctx->ingress_ifindex;

	config = bpf_map_lookup_elem(&config_map, &key);
	if (!config)
		return XDP_ABORTED;

	/* Simple test: check ctx provided ifindex is as expected */
	if (ingress_ifindex != config->ifindex) {
		/* count this error case */
		rec->issue++;
		return XDP_ABORTED;
	}

	/* Update stats per rx_queue_index. Handle if rx_queue_index
	 * is larger than stats map can contain info for.
	 */
	key = ctx->rx_queue_index;
	if (key >= MAX_RXQs)
		key = MAX_RXQs;
	rxq_rec = bpf_map_lookup_elem(&rx_queue_index_map, &key);
	if (!rxq_rec)
		return XDP_ABORTED;
	rxq_rec->processed++;
	if (key == MAX_RXQs)
		rxq_rec->issue++;

	/* Default: Don't touch packet data, only count packets */
	if (unlikely(config->options & (READ_MEM|SWAP_MAC))) {
		struct ethhdr *eth = data;

		if (eth + 1 > data_end)
			return XDP_ABORTED;

		/* Avoid compiler removing this: Drop non 802.3 Ethertypes */
		if (ntohs(eth->h_proto) < ETH_P_802_3_MIN)
			return XDP_ABORTED;

		/* XDP_TX requires changing MAC-addrs, else HW may drop.
		 * Can also be enabled with --swapmac (for test purposes)
		 */
		if (unlikely(config->options & SWAP_MAC))
			swap_src_dst_mac(data);
	}

	return config->action;
}

char _license[] SEC("license") = "GPL";
