Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Unstable XFRM Helpers for TC-BPF hook
  3 *
  4 * These are called from SCHED_CLS BPF programs. Note that it is
  5 * allowed to break compatibility for these functions since the interface they
  6 * are exposed through to BPF programs is explicitly unstable.
  7 */
  8
  9#include <linux/bpf.h>
 10#include <linux/btf_ids.h>
 11
 12#include <net/dst_metadata.h>
 13#include <net/xfrm.h>
 14
 15/* bpf_xfrm_info - XFRM metadata information
 16 *
 17 * Members:
 18 * @if_id	- XFRM if_id:
 19 *		    Transmit: if_id to be used in policy and state lookups
 20 *		    Receive: if_id of the state matched for the incoming packet
 21 * @link	- Underlying device ifindex:
 22 *		    Transmit: used as the underlying device in VRF routing
 23 *		    Receive: the device on which the packet had been received
 24 */
 25struct bpf_xfrm_info {
 26	u32 if_id;
 27	int link;
 28};
 29
 30__diag_push();
 31__diag_ignore_all("-Wmissing-prototypes",
 32		  "Global functions as their definitions will be in xfrm_interface BTF");
 33
 34/* bpf_skb_get_xfrm_info - Get XFRM metadata
 35 *
 36 * Parameters:
 37 * @skb_ctx	- Pointer to ctx (__sk_buff) in TC program
 38 *		    Cannot be NULL
 39 * @to		- Pointer to memory to which the metadata will be copied
 40 *		    Cannot be NULL
 41 */
 42__used noinline
 43int bpf_skb_get_xfrm_info(struct __sk_buff *skb_ctx, struct bpf_xfrm_info *to)
 44{
 45	struct sk_buff *skb = (struct sk_buff *)skb_ctx;
 46	struct xfrm_md_info *info;
 47
 48	info = skb_xfrm_md_info(skb);
 49	if (!info)
 50		return -EINVAL;
 51
 52	to->if_id = info->if_id;
 53	to->link = info->link;
 54	return 0;
 55}
 56
 57/* bpf_skb_get_xfrm_info - Set XFRM metadata
 58 *
 59 * Parameters:
 60 * @skb_ctx	- Pointer to ctx (__sk_buff) in TC program
 61 *		    Cannot be NULL
 62 * @from	- Pointer to memory from which the metadata will be copied
 63 *		    Cannot be NULL
 64 */
 65__used noinline
 66int bpf_skb_set_xfrm_info(struct __sk_buff *skb_ctx,
 67			  const struct bpf_xfrm_info *from)
 68{
 69	struct sk_buff *skb = (struct sk_buff *)skb_ctx;
 70	struct metadata_dst *md_dst;
 71	struct xfrm_md_info *info;
 72
 73	if (unlikely(skb_metadata_dst(skb)))
 74		return -EINVAL;
 75
 76	if (!xfrm_bpf_md_dst) {
 77		struct metadata_dst __percpu *tmp;
 78
 79		tmp = metadata_dst_alloc_percpu(0, METADATA_XFRM, GFP_ATOMIC);
 80		if (!tmp)
 81			return -ENOMEM;
 82		if (cmpxchg(&xfrm_bpf_md_dst, NULL, tmp))
 83			metadata_dst_free_percpu(tmp);
 84	}
 85	md_dst = this_cpu_ptr(xfrm_bpf_md_dst);
 86
 87	info = &md_dst->u.xfrm_info;
 88
 89	info->if_id = from->if_id;
 90	info->link = from->link;
 91	skb_dst_force(skb);
 92	info->dst_orig = skb_dst(skb);
 93
 94	dst_hold((struct dst_entry *)md_dst);
 95	skb_dst_set(skb, (struct dst_entry *)md_dst);
 96	return 0;
 97}
 98
 99__diag_pop()
100
101BTF_SET8_START(xfrm_ifc_kfunc_set)
102BTF_ID_FLAGS(func, bpf_skb_get_xfrm_info)
103BTF_ID_FLAGS(func, bpf_skb_set_xfrm_info)
104BTF_SET8_END(xfrm_ifc_kfunc_set)
105
106static const struct btf_kfunc_id_set xfrm_interface_kfunc_set = {
107	.owner = THIS_MODULE,
108	.set   = &xfrm_ifc_kfunc_set,
109};
110
111int __init register_xfrm_interface_bpf(void)
112{
113	return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
114					 &xfrm_interface_kfunc_set);
115}