History

bpf: add meta pointer for direct access

This work enables generic transfer of metadata from XDP into skb. The basic idea is that we can make use of the fact that the resulting skb must be linear and already comes with a larger headroom for supporting bpf_xdp_adjust_head(), which mangles xdp->data. Here, we base our work on a similar principle and introduce a small helper bpf_xdp_adjust_meta() for adjusting a new pointer called xdp->data_meta. Thus, the packet has a flexible and programmable room for meta data, followed by the actual packet data. struct xdp_buff is therefore laid out that we first point to data_hard_start, then data_meta directly prepended to data followed by data_end marking the end of packet. bpf_xdp_adjust_head() takes into account whether we have meta data already prepended and if so, memmove()s this along with the given offset provided there's enough room. xdp->data_meta is optional and programs are not required to use it. The rationale is that when we process the packet in XDP (e.g. as DoS filter), we can push further meta data along with it for the XDP_PASS case, and give the guarantee that a clsact ingress BPF program on the same device can pick this up for further post-processing. Since we work with skb there, we can also set skb->mark, skb->priority or other skb meta data out of BPF, thus having this scratch space generic and programmable allows for more flexibility than defining a direct 1:1 transfer of potentially new XDP members into skb (it's also more efficient as we don't need to initialize/handle each of such new members). The facility also works together with GRO aggregation. The scratch space at the head of the packet can be multiple of 4 byte up to 32 byte large. Drivers not yet supporting xdp->data_meta can simply be set up with xdp->data_meta as xdp->data + 1 as bpf_xdp_adjust_meta() will detect this and bail out, such that the subsequent match against xdp->data for later access is guaranteed to fail. The verifier treats xdp->data_meta/xdp->data the same way as we treat xdp->data/xdp->data_end pointer comparisons. The requirement for doing the compare against xdp->data is that it hasn't been modified from it's original address we got from ctx access. It may have a range marking already from prior successful xdp->data/xdp->data_end pointer comparisons though.

Daniel Borkmann committed 9 years ago

Commit de8f3a81 parent 6aaae2b19 files · +297 −42Browse files

Showing the changes to include/uapi/linux (1 of 19 files). Show all

Unified · Split

include/uapi/linux/bpf.h+12−1
@@ -582,6 +582,12 @@ union bpf_attr { · 581 unmodified lines
582582 * @map: pointer to sockmap to update
583583 * @key: key to insert/update sock in map
584584 * @flags: same flags as map update elem
585+ *
586+ * int bpf_xdp_adjust_meta(xdp_md, delta)
587+ * Adjust the xdp_md.data_meta by delta
588+ * @xdp_md: pointer to xdp_md
589+ * @delta: An positive/negative integer to be added to xdp_md.data_meta
590+ * Return: 0 on success or negative on error
585591 */
586592 #define __BPF_FUNC_MAPPER(FN) \
587593 FN(unspec), \
@@ -638,6 +644,7 @@ union bpf_attr { · 50 unmodified lines
638644 FN(redirect_map), \
639645 FN(sk_redirect_map), \
640646 FN(sock_map_update), \
647+ FN(xdp_adjust_meta),
641648
642649 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
643650 * function eBPF program intends to call
@@ -715,7 +722,7 @@ struct __sk_buff { · 71 unmodified lines
715722 __u32 data_end;
716723 __u32 napi_id;
717724
718− /* accessed by BPF_PROG_TYPE_sk_skb types */
725+ /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */
719726 __u32 family;
720727 __u32 remote_ip4; /* Stored in network byte order */
721728 __u32 local_ip4; /* Stored in network byte order */
@@ -723,6 +730,9 @@ struct __sk_buff { · 1 unmodified line
723730 __u32 local_ip6[4]; /* Stored in network byte order */
724731 __u32 remote_port; /* Stored in network byte order */
725732 __u32 local_port; /* stored in host byte order */
733+ /* ... here. */
734+
735+ __u32 data_meta;
726736 };
727737
728738 struct bpf_tunnel_key {
@@ -783,6 +793,7 @@ enum xdp_action { · 54 unmodified lines
783793 struct xdp_md {
784794 __u32 data;
785795 __u32 data_end;
796+ __u32 data_meta;
786797 };
787798
788799 enum sk_action {