aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/samples/bpf/sockex3_kern.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@plumgrid.com>2015-06-04 10:11:54 -0700
committerDavid S. Miller <davem@davemloft.net>2015-06-07 02:01:33 -0700
commitd691f9e8d4405c334aa10d556e73c8bf44cb0e01 (patch)
tree295b1d647364407c42990d916358a72381f4d534 /samples/bpf/sockex3_kern.c
parentbpf: make programs see skb->data == L2 for ingress and egress (diff)
downloadwireguard-linux-d691f9e8d4405c334aa10d556e73c8bf44cb0e01.tar.xz
wireguard-linux-d691f9e8d4405c334aa10d556e73c8bf44cb0e01.zip
bpf: allow programs to write to certain skb fields
allow programs read/write skb->mark, tc_index fields and ((struct qdisc_skb_cb *)cb)->data. mark and tc_index are generically useful in TC. cb[0]-cb[4] are primarily used to pass arguments from one program to another called via bpf_tail_call() which can be seen in sockex3_kern.c example. All fields of 'struct __sk_buff' are readable to socket and tc_cls_act progs. mark, tc_index are writeable from tc_cls_act only. cb[0]-cb[4] are writeable by both sockets and tc_cls_act. Add verifier tests and improve sample code. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples/bpf/sockex3_kern.c')
-rw-r--r--samples/bpf/sockex3_kern.c35
1 files changed, 11 insertions, 24 deletions
diff --git a/samples/bpf/sockex3_kern.c b/samples/bpf/sockex3_kern.c
index 2625b987944f..41ae2fd21b13 100644
--- a/samples/bpf/sockex3_kern.c
+++ b/samples/bpf/sockex3_kern.c
@@ -89,7 +89,6 @@ static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off)
struct globals {
struct flow_keys flow;
- __u32 nhoff;
};
struct bpf_map_def SEC("maps") percpu_map = {
@@ -139,7 +138,7 @@ static void update_stats(struct __sk_buff *skb, struct globals *g)
static __always_inline void parse_ip_proto(struct __sk_buff *skb,
struct globals *g, __u32 ip_proto)
{
- __u32 nhoff = g->nhoff;
+ __u32 nhoff = skb->cb[0];
int poff;
switch (ip_proto) {
@@ -165,7 +164,7 @@ static __always_inline void parse_ip_proto(struct __sk_buff *skb,
if (gre_flags & GRE_SEQ)
nhoff += 4;
- g->nhoff = nhoff;
+ skb->cb[0] = nhoff;
parse_eth_proto(skb, gre_proto);
break;
}
@@ -195,7 +194,7 @@ PROG(PARSE_IP)(struct __sk_buff *skb)
if (!g)
return 0;
- nhoff = g->nhoff;
+ nhoff = skb->cb[0];
if (unlikely(ip_is_fragment(skb, nhoff)))
return 0;
@@ -210,7 +209,7 @@ PROG(PARSE_IP)(struct __sk_buff *skb)
verlen = load_byte(skb, nhoff + 0/*offsetof(struct iphdr, ihl)*/);
nhoff += (verlen & 0xF) << 2;
- g->nhoff = nhoff;
+ skb->cb[0] = nhoff;
parse_ip_proto(skb, g, ip_proto);
return 0;
}
@@ -223,7 +222,7 @@ PROG(PARSE_IPV6)(struct __sk_buff *skb)
if (!g)
return 0;
- nhoff = g->nhoff;
+ nhoff = skb->cb[0];
ip_proto = load_byte(skb,
nhoff + offsetof(struct ipv6hdr, nexthdr));
@@ -233,25 +232,21 @@ PROG(PARSE_IPV6)(struct __sk_buff *skb)
nhoff + offsetof(struct ipv6hdr, daddr));
nhoff += sizeof(struct ipv6hdr);
- g->nhoff = nhoff;
+ skb->cb[0] = nhoff;
parse_ip_proto(skb, g, ip_proto);
return 0;
}
PROG(PARSE_VLAN)(struct __sk_buff *skb)
{
- struct globals *g = this_cpu_globals();
__u32 nhoff, proto;
- if (!g)
- return 0;
-
- nhoff = g->nhoff;
+ nhoff = skb->cb[0];
proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
h_vlan_encapsulated_proto));
nhoff += sizeof(struct vlan_hdr);
- g->nhoff = nhoff;
+ skb->cb[0] = nhoff;
parse_eth_proto(skb, proto);
@@ -260,17 +255,13 @@ PROG(PARSE_VLAN)(struct __sk_buff *skb)
PROG(PARSE_MPLS)(struct __sk_buff *skb)
{
- struct globals *g = this_cpu_globals();
__u32 nhoff, label;
- if (!g)
- return 0;
-
- nhoff = g->nhoff;
+ nhoff = skb->cb[0];
label = load_word(skb, nhoff);
nhoff += sizeof(struct mpls_label);
- g->nhoff = nhoff;
+ skb->cb[0] = nhoff;
if (label & MPLS_LS_S_MASK) {
__u8 verlen = load_byte(skb, nhoff);
@@ -288,14 +279,10 @@ PROG(PARSE_MPLS)(struct __sk_buff *skb)
SEC("socket/0")
int main_prog(struct __sk_buff *skb)
{
- struct globals *g = this_cpu_globals();
__u32 nhoff = ETH_HLEN;
__u32 proto = load_half(skb, 12);
- if (!g)
- return 0;
-
- g->nhoff = nhoff;
+ skb->cb[0] = nhoff;
parse_eth_proto(skb, proto);
return 0;
}