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
582 * @map: pointer to sockmap to update582 * @map: pointer to sockmap to update
583 * @key: key to insert/update sock in map583 * @key: key to insert/update sock in map
584 * @flags: same flags as map update elem584 * @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
585 */591 */
586#define __BPF_FUNC_MAPPER(FN) \592#define __BPF_FUNC_MAPPER(FN) \
587 FN(unspec), \593 FN(unspec), \
@@ -638,6 +644,7 @@ union bpf_attr { · 50 unmodified lines
638 FN(redirect_map), \644 FN(redirect_map), \
639 FN(sk_redirect_map), \645 FN(sk_redirect_map), \
640 FN(sock_map_update), \646 FN(sock_map_update), \
647 FN(xdp_adjust_meta),
641 648
642/* integer value in 'imm' field of BPF_CALL instruction selects which helper649/* integer value in 'imm' field of BPF_CALL instruction selects which helper
643 * function eBPF program intends to call650 * function eBPF program intends to call
@@ -715,7 +722,7 @@ struct __sk_buff { · 71 unmodified lines
715 __u32 data_end;722 __u32 data_end;
716 __u32 napi_id;723 __u32 napi_id;
717 724
718 /* accessed by BPF_PROG_TYPE_sk_skb types */725 /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */
719 __u32 family;726 __u32 family;
720 __u32 remote_ip4; /* Stored in network byte order */727 __u32 remote_ip4; /* Stored in network byte order */
721 __u32 local_ip4; /* Stored in network byte order */728 __u32 local_ip4; /* Stored in network byte order */
@@ -723,6 +730,9 @@ struct __sk_buff { · 1 unmodified line
723 __u32 local_ip6[4]; /* Stored in network byte order */730 __u32 local_ip6[4]; /* Stored in network byte order */
724 __u32 remote_port; /* Stored in network byte order */731 __u32 remote_port; /* Stored in network byte order */
725 __u32 local_port; /* stored in host byte order */732 __u32 local_port; /* stored in host byte order */
733 /* ... here. */
734
735 __u32 data_meta;
726};736};
727 737
728struct bpf_tunnel_key {738struct bpf_tunnel_key {
@@ -783,6 +793,7 @@ enum xdp_action { · 54 unmodified lines
783struct xdp_md {793struct xdp_md {
784 __u32 data;794 __u32 data;
785 __u32 data_end;795 __u32 data_end;
796 __u32 data_meta;
786};797};
787 798
788enum sk_action {799enum sk_action {