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

dst_metadata.h (5521B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef __NET_DST_METADATA_H
      3#define __NET_DST_METADATA_H 1
      4
      5#include <linux/skbuff.h>
      6#include <net/ip_tunnels.h>
      7#include <net/dst.h>
      8
      9enum metadata_type {
     10	METADATA_IP_TUNNEL,
     11	METADATA_HW_PORT_MUX,
     12};
     13
     14struct hw_port_info {
     15	struct net_device *lower_dev;
     16	u32 port_id;
     17};
     18
     19struct metadata_dst {
     20	struct dst_entry		dst;
     21	enum metadata_type		type;
     22	union {
     23		struct ip_tunnel_info	tun_info;
     24		struct hw_port_info	port_info;
     25	} u;
     26};
     27
     28static inline struct metadata_dst *skb_metadata_dst(const struct sk_buff *skb)
     29{
     30	struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb);
     31
     32	if (md_dst && md_dst->dst.flags & DST_METADATA)
     33		return md_dst;
     34
     35	return NULL;
     36}
     37
     38static inline struct ip_tunnel_info *
     39skb_tunnel_info(const struct sk_buff *skb)
     40{
     41	struct metadata_dst *md_dst = skb_metadata_dst(skb);
     42	struct dst_entry *dst;
     43
     44	if (md_dst && md_dst->type == METADATA_IP_TUNNEL)
     45		return &md_dst->u.tun_info;
     46
     47	dst = skb_dst(skb);
     48	if (dst && dst->lwtstate &&
     49	    (dst->lwtstate->type == LWTUNNEL_ENCAP_IP ||
     50	     dst->lwtstate->type == LWTUNNEL_ENCAP_IP6))
     51		return lwt_tun_info(dst->lwtstate);
     52
     53	return NULL;
     54}
     55
     56static inline bool skb_valid_dst(const struct sk_buff *skb)
     57{
     58	struct dst_entry *dst = skb_dst(skb);
     59
     60	return dst && !(dst->flags & DST_METADATA);
     61}
     62
     63static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
     64				       const struct sk_buff *skb_b)
     65{
     66	const struct metadata_dst *a, *b;
     67
     68	if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
     69		return 0;
     70
     71	a = (const struct metadata_dst *) skb_dst(skb_a);
     72	b = (const struct metadata_dst *) skb_dst(skb_b);
     73
     74	if (!a != !b || a->type != b->type)
     75		return 1;
     76
     77	switch (a->type) {
     78	case METADATA_HW_PORT_MUX:
     79		return memcmp(&a->u.port_info, &b->u.port_info,
     80			      sizeof(a->u.port_info));
     81	case METADATA_IP_TUNNEL:
     82		return memcmp(&a->u.tun_info, &b->u.tun_info,
     83			      sizeof(a->u.tun_info) +
     84					 a->u.tun_info.options_len);
     85	default:
     86		return 1;
     87	}
     88}
     89
     90void metadata_dst_free(struct metadata_dst *);
     91struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type,
     92					gfp_t flags);
     93void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst);
     94struct metadata_dst __percpu *
     95metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags);
     96
     97static inline struct metadata_dst *tun_rx_dst(int md_size)
     98{
     99	struct metadata_dst *tun_dst;
    100
    101	tun_dst = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
    102	if (!tun_dst)
    103		return NULL;
    104
    105	tun_dst->u.tun_info.options_len = 0;
    106	tun_dst->u.tun_info.mode = 0;
    107	return tun_dst;
    108}
    109
    110static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
    111{
    112	struct metadata_dst *md_dst = skb_metadata_dst(skb);
    113	int md_size;
    114	struct metadata_dst *new_md;
    115
    116	if (!md_dst || md_dst->type != METADATA_IP_TUNNEL)
    117		return ERR_PTR(-EINVAL);
    118
    119	md_size = md_dst->u.tun_info.options_len;
    120	new_md = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
    121	if (!new_md)
    122		return ERR_PTR(-ENOMEM);
    123
    124	memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
    125	       sizeof(struct ip_tunnel_info) + md_size);
    126#ifdef CONFIG_DST_CACHE
    127	/* Unclone the dst cache if there is one */
    128	if (new_md->u.tun_info.dst_cache.cache) {
    129		int ret;
    130
    131		ret = dst_cache_init(&new_md->u.tun_info.dst_cache, GFP_ATOMIC);
    132		if (ret) {
    133			metadata_dst_free(new_md);
    134			return ERR_PTR(ret);
    135		}
    136	}
    137#endif
    138
    139	skb_dst_drop(skb);
    140	skb_dst_set(skb, &new_md->dst);
    141	return new_md;
    142}
    143
    144static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
    145{
    146	struct metadata_dst *dst;
    147
    148	dst = tun_dst_unclone(skb);
    149	if (IS_ERR(dst))
    150		return NULL;
    151
    152	return &dst->u.tun_info;
    153}
    154
    155static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
    156						    __be32 daddr,
    157						    __u8 tos, __u8 ttl,
    158						    __be16 tp_dst,
    159						    __be16 flags,
    160						    __be64 tunnel_id,
    161						    int md_size)
    162{
    163	struct metadata_dst *tun_dst;
    164
    165	tun_dst = tun_rx_dst(md_size);
    166	if (!tun_dst)
    167		return NULL;
    168
    169	ip_tunnel_key_init(&tun_dst->u.tun_info.key,
    170			   saddr, daddr, tos, ttl,
    171			   0, 0, tp_dst, tunnel_id, flags);
    172	return tun_dst;
    173}
    174
    175static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
    176						 __be16 flags,
    177						 __be64 tunnel_id,
    178						 int md_size)
    179{
    180	const struct iphdr *iph = ip_hdr(skb);
    181
    182	return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
    183				0, flags, tunnel_id, md_size);
    184}
    185
    186static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
    187						      const struct in6_addr *daddr,
    188						      __u8 tos, __u8 ttl,
    189						      __be16 tp_dst,
    190						      __be32 label,
    191						      __be16 flags,
    192						      __be64 tunnel_id,
    193						      int md_size)
    194{
    195	struct metadata_dst *tun_dst;
    196	struct ip_tunnel_info *info;
    197
    198	tun_dst = tun_rx_dst(md_size);
    199	if (!tun_dst)
    200		return NULL;
    201
    202	info = &tun_dst->u.tun_info;
    203	info->mode = IP_TUNNEL_INFO_IPV6;
    204	info->key.tun_flags = flags;
    205	info->key.tun_id = tunnel_id;
    206	info->key.tp_src = 0;
    207	info->key.tp_dst = tp_dst;
    208
    209	info->key.u.ipv6.src = *saddr;
    210	info->key.u.ipv6.dst = *daddr;
    211
    212	info->key.tos = tos;
    213	info->key.ttl = ttl;
    214	info->key.label = label;
    215
    216	return tun_dst;
    217}
    218
    219static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
    220						   __be16 flags,
    221						   __be64 tunnel_id,
    222						   int md_size)
    223{
    224	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
    225
    226	return __ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
    227				  ipv6_get_dsfield(ip6h), ip6h->hop_limit,
    228				  0, ip6_flowlabel(ip6h), flags, tunnel_id,
    229				  md_size);
    230}
    231#endif /* __NET_DST_METADATA_H */