// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2023 Isovalent */
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/filter.h>
#include <linux/netfilter_netdev.h>
#include <linux/bpf_mprog.h>
#include <linux/indirect_call_wrapper.h>
#include <net/netdev_lock.h>
#include <net/netdev_queues.h>
#include <net/netdev_rx_queue.h>
#include <net/xdp_sock_drv.h>
#include <net/netkit.h>
#include <net/dst.h>
#include <net/tcx.h>
#define NETKIT_DRV_NAME "netkit"
#define NETKIT_NUM_RX_QUEUES_MAX 1024
#define NETKIT_NUM_TX_QUEUES_MAX 1
#define NETKIT_NUM_RX_QUEUES_REAL 1
#define NETKIT_NUM_TX_QUEUES_REAL 1
struct netkit {
__cacheline_group_begin(netkit_fastpath);
struct net_device __rcu *peer;
struct bpf_mprog_entry __rcu *active;
enum netkit_action policy;
enum netkit_scrub scrub;
struct bpf_mprog_bundle bundle;
__cacheline_group_end(netkit_fastpath);
__cacheline_group_begin(netkit_slowpath);
enum netkit_mode mode;
enum netkit_pairing pair;
bool primary;
u32 headroom;
__cacheline_group_end(netkit_slowpath);
};
struct netkit_link {
struct bpf_link link;
struct net_device *dev;
};
static struct rtnl_link_ops netkit_link_ops;
static __always_inline int
netkit_run(const struct bpf_mprog_entry *entry, struct sk_buff *skb,
enum netkit_action ret)
{
const struct bpf_mprog_fp *fp;
const struct bpf_prog *prog;
bpf_mprog_foreach_prog(entry, fp, prog) {
bpf_compute_data_pointers(skb);
ret = bpf_prog_run(prog, skb);
if (ret != NETKIT_NEXT)
break;
}
return ret;
}
static void netkit_xnet(struct sk_buff *skb)
{
skb->priority = 0;
skb->mark = 0;
}
static void netkit_prep_forward(struct sk_buff *skb,
bool xnet, bool xnet_scrub)
{
skb_scrub_packet(skb, false);
nf_skip_egress(skb, true);
skb_reset_mac_header(skb);
if (!xnet)
return;
skb_clear_tstamp(skb);
if (xnet_scrub)
netkit_xnet(skb);
}
static struct netkit *netkit_priv(const