![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0 0002 * Copyright (c) 2018 Jesper Dangaard Brouer, Red Hat Inc. 0003 * 0004 * Example howto transfer info from XDP to SKB, e.g. skb->mark 0005 * ----------------------------------------------------------- 0006 * This uses the XDP data_meta infrastructure, and is a cooperation 0007 * between two bpf-programs (1) XDP and (2) clsact at TC-ingress hook. 0008 * 0009 * Notice: This example does not use the BPF C-loader, 0010 * but instead rely on the iproute2 TC tool for loading BPF-objects. 0011 */ 0012 #include <uapi/linux/bpf.h> 0013 #include <uapi/linux/pkt_cls.h> 0014 0015 #include <bpf/bpf_helpers.h> 0016 0017 /* 0018 * This struct is stored in the XDP 'data_meta' area, which is located 0019 * just in-front-of the raw packet payload data. The meaning is 0020 * specific to these two BPF programs that use it as a communication 0021 * channel. XDP adjust/increase the area via a bpf-helper, and TC use 0022 * boundary checks to see if data have been provided. 0023 * 0024 * The struct must be 4 byte aligned, which here is enforced by the 0025 * struct __attribute__((aligned(4))). 0026 */ 0027 struct meta_info { 0028 __u32 mark; 0029 } __attribute__((aligned(4))); 0030 0031 SEC("xdp_mark") 0032 int _xdp_mark(struct xdp_md *ctx) 0033 { 0034 struct meta_info *meta; 0035 void *data, *data_end; 0036 int ret; 0037 0038 /* Reserve space in-front of data pointer for our meta info. 0039 * (Notice drivers not supporting data_meta will fail here!) 0040 */ 0041 ret = bpf_xdp_adjust_meta(ctx, -(int)sizeof(*meta)); 0042 if (ret < 0) 0043 return XDP_ABORTED; 0044 0045 /* Notice: Kernel-side verifier requires that loading of 0046 * ctx->data MUST happen _after_ helper bpf_xdp_adjust_meta(), 0047 * as pkt-data pointers are invalidated. Helpers that require 0048 * this are determined/marked by bpf_helper_changes_pkt_data() 0049 */ 0050 data = (void *)(unsigned long)ctx->data; 0051 0052 /* Check data_meta have room for meta_info struct */ 0053 meta = (void *)(unsigned long)ctx->data_meta; 0054 if (meta + 1 > data) 0055 return XDP_ABORTED; 0056 0057 meta->mark = 42; 0058 0059 return XDP_PASS; 0060 } 0061 0062 SEC("tc_mark") 0063 int _tc_mark(struct __sk_buff *ctx) 0064 { 0065 void *data = (void *)(unsigned long)ctx->data; 0066 void *data_end = (void *)(unsigned long)ctx->data_end; 0067 void *data_meta = (void *)(unsigned long)ctx->data_meta; 0068 struct meta_info *meta = data_meta; 0069 0070 /* Check XDP gave us some data_meta */ 0071 if (meta + 1 > data) { 0072 ctx->mark = 41; 0073 /* Skip "accept" if no data_meta is avail */ 0074 return TC_ACT_OK; 0075 } 0076 0077 /* Hint: See func tc_cls_act_is_valid_access() for BPF_WRITE access */ 0078 ctx->mark = meta->mark; /* Transfer XDP-mark to SKB-mark */ 0079 0080 return TC_ACT_OK; 0081 } 0082 0083 /* Manually attaching these programs: 0084 export DEV=ixgbe2 0085 export FILE=xdp2skb_meta_kern.o 0086 0087 # via TC command 0088 tc qdisc del dev $DEV clsact 2> /dev/null 0089 tc qdisc add dev $DEV clsact 0090 tc filter add dev $DEV ingress prio 1 handle 1 bpf da obj $FILE sec tc_mark 0091 tc filter show dev $DEV ingress 0092 0093 # XDP via IP command: 0094 ip link set dev $DEV xdp off 0095 ip link set dev $DEV xdp obj $FILE sec xdp_mark 0096 0097 # Use iptable to "see" if SKBs are marked 0098 iptables -I INPUT -p icmp -m mark --mark 41 # == 0x29 0099 iptables -I INPUT -p icmp -m mark --mark 42 # == 0x2a 0100 0101 # Hint: catch XDP_ABORTED errors via 0102 perf record -e xdp:* 0103 perf script 0104 0105 */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |