162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2021 Facebook */
362306a36Sopenharmony_ci#include <linux/types.h>
462306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
562306a36Sopenharmony_ci#include <linux/bpf.h>
662306a36Sopenharmony_ci#include <stdint.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define TWFW_MAX_TIERS (64)
962306a36Sopenharmony_ci/*
1062306a36Sopenharmony_ci * load is successful
1162306a36Sopenharmony_ci * #define TWFW_MAX_TIERS (64u)$
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct twfw_tier_value {
1562306a36Sopenharmony_ci	unsigned long mask[1];
1662306a36Sopenharmony_ci};
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct rule {
1962306a36Sopenharmony_ci	uint8_t seqnum;
2062306a36Sopenharmony_ci};
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct rules_map {
2362306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_ARRAY);
2462306a36Sopenharmony_ci	__type(key, __u32);
2562306a36Sopenharmony_ci	__type(value, struct rule);
2662306a36Sopenharmony_ci	__uint(max_entries, 1);
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct tiers_map {
3062306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_ARRAY);
3162306a36Sopenharmony_ci	__type(key, __u32);
3262306a36Sopenharmony_ci	__type(value, struct twfw_tier_value);
3362306a36Sopenharmony_ci	__uint(max_entries, 1);
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct rules_map rules SEC(".maps");
3762306a36Sopenharmony_cistruct tiers_map tiers SEC(".maps");
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciSEC("cgroup_skb/ingress")
4062306a36Sopenharmony_ciint twfw_verifier(struct __sk_buff* skb)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	const uint32_t key = 0;
4362306a36Sopenharmony_ci	const struct twfw_tier_value* tier = bpf_map_lookup_elem(&tiers, &key);
4462306a36Sopenharmony_ci	if (!tier)
4562306a36Sopenharmony_ci		return 1;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	struct rule* rule = bpf_map_lookup_elem(&rules, &key);
4862306a36Sopenharmony_ci	if (!rule)
4962306a36Sopenharmony_ci		return 1;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	if (rule && rule->seqnum < TWFW_MAX_TIERS) {
5262306a36Sopenharmony_ci		/* rule->seqnum / 64 should always be 0 */
5362306a36Sopenharmony_ci		unsigned long mask = tier->mask[rule->seqnum / 64];
5462306a36Sopenharmony_ci		if (mask)
5562306a36Sopenharmony_ci			return 0;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci	return 1;
5862306a36Sopenharmony_ci}
59