OSDN Git Service

bpf: Add hardware timestamp field to __sk_buff
authorVadim Fedorenko <vfedorenko@novek.ru>
Thu, 9 Sep 2021 22:04:08 +0000 (01:04 +0300)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 10 Sep 2021 21:19:58 +0000 (23:19 +0200)
BPF programs may want to know hardware timestamps if NIC supports
such timestamping.

Expose this data as hwtstamp field of __sk_buff the same way as
gso_segs/gso_size. This field could be accessed from the same
programs as tstamp field, but it's read-only field. Explicit test
to deny access to padding data is added to bpf_skb_is_valid_access.

Also update BPF_PROG_TEST_RUN tests of the feature.

Signed-off-by: Vadim Fedorenko <vfedorenko@novek.ru>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20210909220409.8804-2-vfedorenko@novek.ru
include/uapi/linux/bpf.h
net/core/filter.c
tools/include/uapi/linux/bpf.h

index 791f31d..51cfd91 100644 (file)
@@ -5284,6 +5284,8 @@ struct __sk_buff {
        __u32 gso_segs;
        __bpf_md_ptr(struct bpf_sock *, sk);
        __u32 gso_size;
+       __u32 :32;              /* Padding, future use. */
+       __u64 hwtstamp;
 };
 
 struct bpf_tunnel_key {
index 2e32cee..4bace37 100644 (file)
@@ -7765,6 +7765,10 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
                break;
        case bpf_ctx_range_ptr(struct __sk_buff, flow_keys):
                return false;
+       case bpf_ctx_range(struct __sk_buff, hwtstamp):
+               if (type == BPF_WRITE || size != sizeof(__u64))
+                       return false;
+               break;
        case bpf_ctx_range(struct __sk_buff, tstamp):
                if (size != sizeof(__u64))
                        return false;
@@ -7774,6 +7778,9 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
                        return false;
                info->reg_type = PTR_TO_SOCK_COMMON_OR_NULL;
                break;
+       case offsetofend(struct __sk_buff, gso_size) ... offsetof(struct __sk_buff, hwtstamp) - 1:
+               /* Explicitly prohibit access to padding in __sk_buff. */
+               return false;
        default:
                /* Only narrow read access allowed for now. */
                if (type == BPF_WRITE) {
@@ -7802,6 +7809,7 @@ static bool sk_filter_is_valid_access(int off, int size,
        case bpf_ctx_range_till(struct __sk_buff, family, local_port):
        case bpf_ctx_range(struct __sk_buff, tstamp):
        case bpf_ctx_range(struct __sk_buff, wire_len):
+       case bpf_ctx_range(struct __sk_buff, hwtstamp):
                return false;
        }
 
@@ -7872,6 +7880,7 @@ static bool lwt_is_valid_access(int off, int size,
        case bpf_ctx_range(struct __sk_buff, data_meta):
        case bpf_ctx_range(struct __sk_buff, tstamp):
        case bpf_ctx_range(struct __sk_buff, wire_len):
+       case bpf_ctx_range(struct __sk_buff, hwtstamp):
                return false;
        }
 
@@ -8373,6 +8382,7 @@ static bool sk_skb_is_valid_access(int off, int size,
        case bpf_ctx_range(struct __sk_buff, data_meta):
        case bpf_ctx_range(struct __sk_buff, tstamp):
        case bpf_ctx_range(struct __sk_buff, wire_len):
+       case bpf_ctx_range(struct __sk_buff, hwtstamp):
                return false;
        }
 
@@ -8884,6 +8894,17 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                      si->dst_reg, si->src_reg,
                                      offsetof(struct sk_buff, sk));
                break;
+       case offsetof(struct __sk_buff, hwtstamp):
+               BUILD_BUG_ON(sizeof_field(struct skb_shared_hwtstamps, hwtstamp) != 8);
+               BUILD_BUG_ON(offsetof(struct skb_shared_hwtstamps, hwtstamp) != 0);
+
+               insn = bpf_convert_shinfo_access(si, insn);
+               *insn++ = BPF_LDX_MEM(BPF_DW,
+                                     si->dst_reg, si->dst_reg,
+                                     bpf_target_off(struct skb_shared_info,
+                                                    hwtstamps, 8,
+                                                    target_size));
+               break;
        }
 
        return insn - insn_buf;
index 791f31d..51cfd91 100644 (file)
@@ -5284,6 +5284,8 @@ struct __sk_buff {
        __u32 gso_segs;
        __bpf_md_ptr(struct bpf_sock *, sk);
        __u32 gso_size;
+       __u32 :32;              /* Padding, future use. */
+       __u64 hwtstamp;
 };
 
 struct bpf_tunnel_key {