// SPDX-License-Identifier: GPL-2.0
/* Toeplitz test
 *
 * 1. Read packets and their rx_hash using PF_PACKET/TPACKET_V3
 * 2. Compute the rx_hash in software based on the packet contents
 * 3. Compare the two
 *
 * Optionally, either '-C $rx_irq_cpu_list' or '-r $rps_bitmap' may be given.
 *
 * If '-C $rx_irq_cpu_list' is given, also
 *
 * 4. Identify the cpu on which the packet arrived with PACKET_FANOUT_CPU
 * 5. Compute the rxqueue that RSS would select based on this rx_hash
 * 6. Using the $rx_irq_cpu_list map, identify the arriving cpu based on rxq irq
 * 7. Compare the cpus from 4 and 6
 *
 * Else if '-r $rps_bitmap' is given, also
 *
 * 4. Identify the cpu on which the packet arrived with PACKET_FANOUT_CPU
 * 5. Compute the cpu that RPS should select based on rx_hash and $rps_bitmap
 * 6. Compare the cpus from 4 and 5
 */

#define _GNU_SOURCE

#include <arpa/inet.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/filter.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <poll.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include "../kselftest.h"

#define TOEPLITZ_KEY_MIN_LEN	40
#define TOEPLITZ_KEY_MAX_LEN	60

#define TOEPLITZ_STR_LEN(K)	(((K) * 3) - 1)	/* hex encoded: AA:BB:CC:...:ZZ */
#define TOEPLITZ_STR_MIN_LEN	TOEPLITZ_STR_LEN(TOEPLITZ_KEY_MIN_LEN)
#define TOEPLITZ_STR_MAX_LEN	TOEPLITZ_STR_LEN(TOEPLITZ_KEY_MAX_LEN)

#define FOUR_TUPLE_MAX_LEN	((sizeof(struct in6_addr) * 2) + (sizeof(uint16_t) * 2))

#define RSS_MAX_CPUS (1 << 16)	/* real constraint is PACKET_FANOUT_MAX */

#define RPS_MAX_CPUS 16UL	/* must be a power of 2 */

/* configuration options (cmdline arguments) */
static uint16_t cfg_dport =	8000;
static int cfg_family =		AF_INET6;
static char *cfg_ifname =	"eth0";
static int cfg_num_queues;
static int cfg_num_rps_cpus;
static bool cfg_sink;
static int cfg_type =		SOCK_STREAM;
static int cfg_timeout_msec =	1000;
static bool cfg_verbose;

/* global vars */
static int num_cpus;
static int ring_block_nr;
static int ring_block_sz;

/* stats */
static int frames_received;
static int frames_nohash;
static int frames_error;

#define log_verbose(args...)	do { if (cfg_verbose) fprintf(stderr, args); } while (0)

/* tpacket ring */
struct ring_state {
	int fd;
	char *mmap;
	int idx;
	int cpu;
};

static unsigned int rx_irq_cpus[RSS_MAX_CPUS];	/* map from rxq to cpu */
static int rps_silo_to_cpu[RPS_MAX_CPUS];
static unsigned char toeplitz_key[TOEPLITZ_KEY_MAX_LEN];
static struct ring_state rings[RSS_MAX_CPUS];

static inline uint32_t toeplitz(const unsigned char *four_tuple,
				const unsigned char *key)
{
	int i, bit, ret = 0;
	uint32_t key32;

	key32 = ntohl(*((uint32_t *)key));
	key += 4;

	for (i = 0; i < FOUR_TUPLE_MAX_LEN; i++) {
		for (bit = 7; bit >= 0; bit--) {
			if (four_tuple[i] & (1 << bit))
				ret ^= key32;

			key32 <<= 1;
			key32 |= !!(key[0] & (1 << bit));
		}
		key++;
	}

	return ret;
}

/* Compare computed cpu with arrival cpu from packet_fanout_cpu */
static void verify_rss(uint32_t rx_hash, int cpu)
{
	int queue = rx_hash % cfg_num_queues;

	log_verbose(" rxq %d (cpu %d)", queue, rx_irq_cpus[queue]);
	if (rx_irq_cpus[queue] != cpu) {
		log_verbose(". error: rss cpu mismatch (%d)", cpu);
		frames_error++;
	}
}

static void verify_rps(uint64_t rx_hash, int cpu)
{
	int silo = (rx_hash * cfg_num_rps_cpus) >> 32;

	log_verbose(" silo %d (cpu %d)", silo, rps_silo_to_cpu[silo]);
	if (rps_silo_to_cpu[silo] != cpu) {
		log_verbose(". error: rps cpu mismatch (%d)", cpu);
		frames_error++;
	}
}

static void log_rxhash(int cpu, uint32_t rx_hash,
		       const char *addrs, int addr_len)
{
	char saddr[INET6_ADDRSTRLEN], daddr[INET6_ADDRSTRLEN];
	uint16_t *ports;

	if (!inet_ntop(cfg_family, addrs, saddr, sizeof(saddr)) ||
	    !inet_ntop(cfg_family, addrs + addr_len, daddr, sizeof(daddr)))
		error(1, 0, "address parse error");

	ports = (void *)addrs + (addr_len * 2);
	log_verbose("cpu %d: rx_hash 0x%08x [saddr %s daddr %s sport %02hu dport %02hu]",
		    cpu, rx_hash, saddr, daddr,
		    ntohs(ports[0]), ntohs(ports[1]));
}

/* Compare computed rxhash with rxhash received from tpacket_v3 */
static void verify_rxhash(const char *pkt, uint32_t rx_hash, int cpu)
{
	unsigned char four_tuple[FOUR_TUPLE_MAX_LEN] = {0};
	uint32_t rx_hash_sw;
	const char *addrs;
	int addr_len;

	if (cfg_family == AF_INET) {
		addr_len = sizeof(struct in_addr);
		addrs = pkt + offsetof(struct iphdr, saddr);
	} else {
		addr_len = sizeof(struct in6_addr);
		addrs = pkt + offsetof(struct ip6_hdr, ip6_src);
	}

	memcpy(four_tuple, addrs, (addr_len * 2) + (sizeof(uint16_t) * 2));
	rx_hash_sw = toeplitz(four_tuple, toeplitz_key);

	if (cfg_verbose)
		log_rxhash(cpu, rx_hash, addrs, addr_len);

	if (rx_hash != rx_hash_sw) {
		log_verbose(" != expected 0x%x\n", rx_hash_sw);
		frames_error++;
		return;
	}

	log_verbose(" OK");
	if (cfg_num_queues)
		verify_rss(rx_hash, cpu);
	else if (cfg_num_rps_cpus)
		verify_rps(rx_hash, cpu);
	log_verbose("\n");
}

static char *recv_frame(const struct ring_state *ring, char *frame)
{
	struct tpacket3_hdr *hdr = (void *)frame;

	if (hdr->hv1.tp_rxhash)
		verify_rxhash(frame + hdr->tp_net, hdr->hv1.tp_rxhash,
			      ring->cpu);
	else
		frames_nohash++;

	return frame + hdr->tp_next_offset;
}

/* A single TPACKET_V3 block can hold multiple frames */
static void recv_block(struct ring_state *ring)
{
	struct tpacket_block_desc *block;
	char *frame;
	int i;

	block = (void *)(ring->mmap + ring->idx * ring_block_sz);
	if (!(block->hdr.bh1.block_status & TP_STATUS_USER))
		return;

	frame = (char *)block;
	frame += block->hdr.bh1.offset_to_first_pkt;

	for (i = 0; i < block->hdr.bh1.num_pkts; i++) {
		frame = recv_frame(ring, frame);
		frames_received++;
	}

	block->hdr.bh1.block_status = TP_STATUS_KERNEL;
	ring->idx = (ring->idx + 1) % ring_block_nr;
}

/* simple test: sleep once unconditionally and then process all rings */
static void process_rings(void)
{
	int i;

	usleep(1000 * cfg_timeout_msec);

	for (i = 0; i < num_cpus; i++)
		recv_block(&rings[i]);

	fprintf(stderr, "count: pass=%u nohash=%u fail=%u\n",
		frames_received - frames_nohash - frames_error,
		frames_nohash, frames_error);
}

static char *setup_ring(int fd)
{
	struct tpacket_req3 req3 = {0};
	void *ring;

	req3.tp_retire_blk_tov = cfg_timeout_msec;
	req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;

	req3.tp_frame_size = 2048;
	req3.tp_frame_nr = 1 << 10;
	req3.tp_block_nr = 2;

	req3.tp_block_size = req3.tp_frame_size * req3.tp_frame_nr;
	req3.tp_block_size /= req3.tp_block_nr;

	if (setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &req3, sizeof(req3)))
		error(1, errno, "setsockopt PACKET_RX_RING");

	ring_block_sz = req3.tp_block_size;
	ring_block_nr = req3.tp_block_nr;

	ring = mmap(0, req3.tp_block_size * req3.tp_block_nr,
		    PROT_READ | PROT_WRITE,
		    MAP_SHARED | MAP_LOCKED | MAP_POPULATE, fd, 0);
	if (ring == MAP_FAILED)
		error(1, 0, "mmap failed");

	return ring;
}

static void __set_filter(int fd, int off_proto, uint8_t proto, int off_dport)
{
	struct sock_filter filter[] = {
		BPF_STMT(BPF_LD  + BPF_B   + BPF_ABS, SKF_AD_OFF + SKF_AD_PKTTYPE),
		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, PACKET_HOST, 0, 4),
		BPF_STMT(BPF_LD  + BPF_B   + BPF_ABS, off_proto),
		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, proto, 0, 2),
		BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, off_dport),
		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, cfg_dport, 1, 0),
		BPF_STMT(BPF_RET + BPF_K, 0),
		BPF_STMT(BPF_RET + BPF_K, 0xFFFF),
	};
	struct sock_fprog prog = {};

	prog.filter = filter;
	prog.len = ARRAY_SIZE(filter);
	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)))
		error(1, errno, "setsockopt filter");
}

/* filter on transport protocol and destination port */
static void set_filter(int fd)
{
	const int off_dport = offsetof(struct tcphdr, dest);	/* same for udp */
	uint8_t proto;

	proto = cfg_type == SOCK_STREAM ? IPPROTO_TCP : IPPROTO_UDP;
	if (cfg_family == AF_INET)
		__set_filter(fd, offsetof(struct iphdr, protocol), proto,
			     sizeof(struct iphdr) + off_dport);
	else
		__set_filter(fd, offsetof(struct ip6_hdr, ip6_nxt), proto,
			     sizeof(struct ip6_hdr) + off_dport);
}

/* drop everything: used temporarily during setup */
static void set_filter_null(int fd)
{
	struct sock_filter filter[] = {
		BPF_STMT(BPF_RET + BPF_K, 0),
	};
	struct sock_fprog prog = {};

	prog.filter = filter;
	prog.len = ARRAY_SIZE(filter);
	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)))
		error(1, errno, "setsockopt filter");
}

static int create_ring(char **ring)
{
	struct fanout_args args = {
		.id = 1,
		.type_flags = PACKET_FANOUT_CPU,
		.max_num_members = RSS_MAX_CPUS
	};
	struct sockaddr_ll ll = { 0 };
	int fd, val;

	fd = socket(PF_PACKET, SOCK_DGRAM, 0);
	if (fd == -1)
		error(1, errno, "socket creation failed");

	val = TPACKET_V3;
	if (setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)))
		error(1, errno, "setsockopt PACKET_VERSION");
	*ring = setup_ring(fd);

	/* block packets until all rings are added to the fanout group:
	 * else packets can arrive during setup and get misclassified
	 */
	set_filter_null(fd);

	ll.sll_family = AF_PACKET;
	ll.sll_ifindex = if_nametoindex(cfg_ifname);
	ll.sll_protocol = cfg_family == AF_INET ? htons(ETH_P_IP) :
						  htons(ETH_P_IPV6);
	if (bind(fd, (void *)&ll, sizeof(ll)))
		error(1, errno, "bind");

	/* must come after bind: verifies all programs in group match */
	if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &args, sizeof(args))) {
		/* on failure, retry using old API if that is sufficient:
		 * it has a hard limit of 256 sockets, so only try if
		 * (a) only testing rxhash, not RSS or (b) <= 256 cpus.
		 * in this API, the third argument is left implicit.
		 */
		if (cfg_num_queues || num_cpus > 256 ||
		    setsockopt(fd, SOL_PACKET, PACKET_FANOUT,
			       &args, sizeof(uint32_t)))
			error(1, errno, "setsockopt PACKET_FANOUT cpu");
	}

	return fd;
}

/* setup inet(6) socket to blackhole the test traffic, if arg '-s' */
static int setup_sink(void)
{
	int fd, val;

	fd = socket(cfg_family, cfg_type, 0);
	if (fd == -1)
		error(1, errno, "socket %d.%d", cfg_family, cfg_type);

	val = 1 << 20;
	if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &val, sizeof(val)))
		error(1, errno, "setsockopt rcvbuf");

	return fd;
}

static void setup_rings(void)
{
	int i;

	for (i = 0; i < num_cpus; i++) {
		rings[i].cpu = i;
		rings[i].fd = create_ring(&rings[i].mmap);
	}

	/* accept packets once all rings in the fanout group are up */
	for (i = 0; i < num_cpus; i++)
		set_filter(rings[i].fd);
}

static void cleanup_rings(void)
{
	int i;

	for (i = 0; i < num_cpus; i++) {
		if (munmap(rings[i].mmap, ring_block_nr * ring_block_sz))
			error(1, errno, "munmap");
		if (close(rings[i].fd))
			error(1, errno, "close");
	}
}

static void parse_cpulist(const char *arg)
{
	do {
		rx_irq_cpus[cfg_num_queues++] = strtol(arg, NULL, 10);

		arg = strchr(arg, ',');
		if (!arg)
			break;
		arg++;			// skip ','
	} while (1);
}

static void show_cpulist(void)
{
	int i;

	for (i = 0; i < cfg_num_queues; i++)
		fprintf(stderr, "rxq %d: cpu %d\n", i, rx_irq_cpus[i]);
}

static void show_silos(void)
{
	int i;

	for (i = 0; i < cfg_num_rps_cpus; i++)
		fprintf(stderr, "silo %d: cpu %d\n", i, rps_silo_to_cpu[i]);
}

static void parse_toeplitz_key(const char *str, int slen, unsigned char *key)
{
	int i, ret, off;

	if (slen < TOEPLITZ_STR_MIN_LEN ||
	    slen > TOEPLITZ_STR_MAX_LEN + 1)
		error(1, 0, "invalid toeplitz key");

	for (i = 0, off = 0; off < slen; i++, off += 3) {
		ret = sscanf(str + off, "%hhx", &key[i]);
		if (ret != 1)
			error(1, 0, "key parse error at %d off %d len %d",
			      i, off, slen);
	}
}

static void parse_rps_bitmap(const char *arg)
{
	unsigned long bitmap;
	int i;

	bitmap = strtoul(arg, NULL, 0);

	if (bitmap & ~(RPS_MAX_CPUS - 1))
		error(1, 0, "rps bitmap 0x%lx out of bounds 0..%lu",
		      bitmap, RPS_MAX_CPUS - 1);

	for (i = 0; i < RPS_MAX_CPUS; i++)
		if (bitmap & 1UL << i)
			rps_silo_to_cpu[cfg_num_rps_cpus++] = i;
}

static void parse_opts(int argc, char **argv)
{
	static struct option long_options[] = {
	    {"dport",	required_argument, 0, 'd'},
	    {"cpus",	required_argument, 0, 'C'},
	    {"key",	required_argument, 0, 'k'},
	    {"iface",	required_argument, 0, 'i'},
	    {"ipv4",	no_argument, 0, '4'},
	    {"ipv6",	no_argument, 0, '6'},
	    {"sink",	no_argument, 0, 's'},
	    {"tcp",	no_argument, 0, 't'},
	    {"timeout",	required_argument, 0, 'T'},
	    {"udp",	no_argument, 0, 'u'},
	    {"verbose",	no_argument, 0, 'v'},
	    {"rps",	required_argument, 0, 'r'},
	    {0, 0, 0, 0}
	};
	bool have_toeplitz = false;
	int index, c;

	while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:uv", long_options, &index)) != -1) {
		switch (c) {
		case '4':
			cfg_family = AF_INET;
			break;
		case '6':
			cfg_family = AF_INET6;
			break;
		case 'C':
			parse_cpulist(optarg);
			break;
		case 'd':
			cfg_dport = strtol(optarg, NULL, 0);
			break;
		case 'i':
			cfg_ifname = optarg;
			break;
		case 'k':
			parse_toeplitz_key(optarg, strlen(optarg),
					   toeplitz_key);
			have_toeplitz = true;
			break;
		case 'r':
			parse_rps_bitmap(optarg);
			break;
		case 's':
			cfg_sink = true;
			break;
		case 't':
			cfg_type = SOCK_STREAM;
			break;
		case 'T':
			cfg_timeout_msec = strtol(optarg, NULL, 0);
			break;
		case 'u':
			cfg_type = SOCK_DGRAM;
			break;
		case 'v':
			cfg_verbose = true;
			break;

		default:
			error(1, 0, "unknown option %c", optopt);
			break;
		}
	}

	if (!have_toeplitz)
		error(1, 0, "Must supply rss key ('-k')");

	num_cpus = get_nprocs();
	if (num_cpus > RSS_MAX_CPUS)
		error(1, 0, "increase RSS_MAX_CPUS");

	if (cfg_num_queues && cfg_num_rps_cpus)
		error(1, 0,
		      "Can't supply both RSS cpus ('-C') and RPS map ('-r')");
	if (cfg_verbose) {
		show_cpulist();
		show_silos();
	}
}

int main(int argc, char **argv)
{
	const int min_tests = 10;
	int fd_sink = -1;

	parse_opts(argc, argv);

	if (cfg_sink)
		fd_sink = setup_sink();

	setup_rings();
	process_rings();
	cleanup_rings();

	if (cfg_sink && close(fd_sink))
		error(1, errno, "close sink");

	if (frames_received - frames_nohash < min_tests)
		error(1, 0, "too few frames for verification");

	return frames_error;
}
