cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nf_queue.h (3432B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _NF_QUEUE_H
      3#define _NF_QUEUE_H
      4
      5#include <linux/ip.h>
      6#include <linux/ipv6.h>
      7#include <linux/jhash.h>
      8#include <linux/netfilter.h>
      9#include <linux/skbuff.h>
     10
     11/* Each queued (to userspace) skbuff has one of these. */
     12struct nf_queue_entry {
     13	struct list_head	list;
     14	struct sk_buff		*skb;
     15	unsigned int		id;
     16	unsigned int		hook_index;	/* index in hook_entries->hook[] */
     17#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
     18	struct net_device	*physin;
     19	struct net_device	*physout;
     20#endif
     21	struct nf_hook_state	state;
     22	u16			size; /* sizeof(entry) + saved route keys */
     23
     24	/* extra space to store route keys */
     25};
     26
     27#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
     28
     29/* Packet queuing */
     30struct nf_queue_handler {
     31	int		(*outfn)(struct nf_queue_entry *entry,
     32				 unsigned int queuenum);
     33	void		(*nf_hook_drop)(struct net *net);
     34};
     35
     36void nf_register_queue_handler(const struct nf_queue_handler *qh);
     37void nf_unregister_queue_handler(void);
     38void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
     39
     40bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
     41void nf_queue_entry_free(struct nf_queue_entry *entry);
     42
     43static inline void init_hashrandom(u32 *jhash_initval)
     44{
     45	while (*jhash_initval == 0)
     46		*jhash_initval = prandom_u32();
     47}
     48
     49static inline u32 hash_v4(const struct iphdr *iph, u32 initval)
     50{
     51	/* packets in either direction go into same queue */
     52	if ((__force u32)iph->saddr < (__force u32)iph->daddr)
     53		return jhash_3words((__force u32)iph->saddr,
     54			(__force u32)iph->daddr, iph->protocol, initval);
     55
     56	return jhash_3words((__force u32)iph->daddr,
     57			(__force u32)iph->saddr, iph->protocol, initval);
     58}
     59
     60static inline u32 hash_v6(const struct ipv6hdr *ip6h, u32 initval)
     61{
     62	u32 a, b, c;
     63
     64	if ((__force u32)ip6h->saddr.s6_addr32[3] <
     65	    (__force u32)ip6h->daddr.s6_addr32[3]) {
     66		a = (__force u32) ip6h->saddr.s6_addr32[3];
     67		b = (__force u32) ip6h->daddr.s6_addr32[3];
     68	} else {
     69		b = (__force u32) ip6h->saddr.s6_addr32[3];
     70		a = (__force u32) ip6h->daddr.s6_addr32[3];
     71	}
     72
     73	if ((__force u32)ip6h->saddr.s6_addr32[1] <
     74	    (__force u32)ip6h->daddr.s6_addr32[1])
     75		c = (__force u32) ip6h->saddr.s6_addr32[1];
     76	else
     77		c = (__force u32) ip6h->daddr.s6_addr32[1];
     78
     79	return jhash_3words(a, b, c, initval);
     80}
     81
     82static inline u32 hash_bridge(const struct sk_buff *skb, u32 initval)
     83{
     84	struct ipv6hdr *ip6h, _ip6h;
     85	struct iphdr *iph, _iph;
     86
     87	switch (eth_hdr(skb)->h_proto) {
     88	case htons(ETH_P_IP):
     89		iph = skb_header_pointer(skb, skb_network_offset(skb),
     90					 sizeof(*iph), &_iph);
     91		if (iph)
     92			return hash_v4(iph, initval);
     93		break;
     94	case htons(ETH_P_IPV6):
     95		ip6h = skb_header_pointer(skb, skb_network_offset(skb),
     96					  sizeof(*ip6h), &_ip6h);
     97		if (ip6h)
     98			return hash_v6(ip6h, initval);
     99		break;
    100	}
    101
    102	return 0;
    103}
    104
    105static inline u32
    106nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
    107	     u32 initval)
    108{
    109	switch (family) {
    110	case NFPROTO_IPV4:
    111		queue += reciprocal_scale(hash_v4(ip_hdr(skb), initval),
    112					  queues_total);
    113		break;
    114	case NFPROTO_IPV6:
    115		queue += reciprocal_scale(hash_v6(ipv6_hdr(skb), initval),
    116					  queues_total);
    117		break;
    118	case NFPROTO_BRIDGE:
    119		queue += reciprocal_scale(hash_bridge(skb, initval),
    120					  queues_total);
    121		break;
    122	}
    123
    124	return queue;
    125}
    126
    127int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
    128	     unsigned int index, unsigned int verdict);
    129
    130#endif /* _NF_QUEUE_H */