Message ID | 1d9d533b5d2640fe958d599ac0944132c3b7d61b.1524591163.git.m.xhonneux@gmail.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
Series | ipv6: sr: introduce seg6local End.BPF action | expand |
Hi Mathieu,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Mathieu-Xhonneux/ipv6-sr-introduce-seg6local-End-BPF-action/20180426-082209
config: microblaze-mmu_defconfig (attached as .config)
compiler: microblaze-linux-gcc (GCC) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=microblaze
All errors (new ones prefixed by >>):
In file included from net/core/filter.c:63:0:
include/net/seg6.h: In function 'seg6_pernet':
>> include/net/seg6.h:52:14: error: 'struct net' has no member named 'ipv6'; did you mean 'ipv4'?
return net->ipv6.seg6_data;
^~~~
ipv4
vim +52 include/net/seg6.h
915d7e5e David Lebrun 2016-11-08 49
915d7e5e David Lebrun 2016-11-08 50 static inline struct seg6_pernet_data *seg6_pernet(struct net *net)
915d7e5e David Lebrun 2016-11-08 51 {
915d7e5e David Lebrun 2016-11-08 @52 return net->ipv6.seg6_data;
915d7e5e David Lebrun 2016-11-08 53 }
915d7e5e David Lebrun 2016-11-08 54
:::::: The code at line 52 was first introduced by commit
:::::: 915d7e5e5930b4f01d0971d93b9b25ed17d221aa ipv6: sr: add code base for control plane support of SR-IPv6
:::::: TO: David Lebrun <david.lebrun@uclouvain.be>
:::::: CC: David S. Miller <davem@davemloft.net>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Mathieu, Thank you for the patch! Yet something to improve: [auto build test ERROR on net-next/master] url: https://github.com/0day-ci/linux/commits/Mathieu-Xhonneux/ipv6-sr-introduce-seg6local-End-BPF-action/20180426-082209 config: i386-randconfig-n0-201816 (attached as .config) compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): net/core/filter.o: In function `bpf_push_seg6_encap': >> net/core/filter.c:3741: undefined reference to `seg6_do_srh_inline' >> net/core/filter.c:3746: undefined reference to `seg6_do_srh_encap' >> net/core/filter.c:3757: undefined reference to `seg6_lookup_nexthop' net/core/filter.o: In function `____bpf_lwt_seg6_action': net/core/filter.c:3856: undefined reference to `seg6_lookup_nexthop' vim +3741 net/core/filter.c 3727 3728 int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len) 3729 { 3730 int err; 3731 struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)hdr; 3732 3733 if (!seg6_validate_srh(srh, len)) 3734 return -EINVAL; 3735 3736 switch (type) { 3737 case BPF_LWT_ENCAP_SEG6_INLINE: 3738 if (skb->protocol != htons(ETH_P_IPV6)) 3739 return -EBADMSG; 3740 > 3741 err = seg6_do_srh_inline(skb, srh); 3742 break; 3743 case BPF_LWT_ENCAP_SEG6: 3744 skb_reset_inner_headers(skb); 3745 skb->encapsulation = 1; > 3746 err = seg6_do_srh_encap(skb, srh, IPPROTO_IPV6); 3747 break; 3748 default: 3749 return -EINVAL; 3750 } 3751 if (err) 3752 return err; 3753 3754 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 3755 skb_set_transport_header(skb, sizeof(struct ipv6hdr)); 3756 > 3757 return seg6_lookup_nexthop(skb, NULL, 0); 3758 } 3759 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Mathieu,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Mathieu-Xhonneux/ipv6-sr-introduce-seg6local-End-BPF-action/20180426-082209
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
net/core/filter.c:110:48: sparse: expression using sizeof(void)
net/core/filter.c:110:48: sparse: expression using sizeof(void)
net/core/filter.c:323:33: sparse: subtraction of functions? Share your drugs
net/core/filter.c:326:33: sparse: subtraction of functions? Share your drugs
net/core/filter.c:329:33: sparse: subtraction of functions? Share your drugs
net/core/filter.c:332:33: sparse: subtraction of functions? Share your drugs
net/core/filter.c:335:33: sparse: subtraction of functions? Share your drugs
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
net/core/filter.c:1189:39: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct sock_filter const *filter @@ got struct sockstruct sock_filter const *filter @@
net/core/filter.c:1189:39: expected struct sock_filter const *filter
net/core/filter.c:1189:39: got struct sock_filter [noderef] <asn:1>*filter
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
net/core/filter.c:1291:39: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct sock_filter const *filter @@ got struct sockstruct sock_filter const *filter @@
net/core/filter.c:1291:39: expected struct sock_filter const *filter
net/core/filter.c:1291:39: got struct sock_filter [noderef] <asn:1>*filter
include/linux/filter.h:612:16: sparse: expression using sizeof(void)
net/core/filter.c:1552:43: sparse: incorrect type in argument 2 (different base types) @@ expected restricted __wsum [usertype] diff @@ got unsigned lonrestricted __wsum [usertype] diff @@
net/core/filter.c:1552:43: expected restricted __wsum [usertype] diff
net/core/filter.c:1552:43: got unsigned long long [unsigned] [usertype] to
net/core/filter.c:1555:36: sparse: incorrect type in argument 2 (different base types) @@ expected restricted __be16 [usertype] old @@ got unsigned lonrestricted __be16 [usertype] old @@
net/core/filter.c:1555:36: expected restricted __be16 [usertype] old
net/core/filter.c:1555:36: got unsigned long long [unsigned] [usertype] from
net/core/filter.c:1555:42: sparse: incorrect type in argument 3 (different base types) @@ expected restricted __be16 [usertype] new @@ got unsigned lonrestricted __be16 [usertype] new @@
net/core/filter.c:1555:42: expected restricted __be16 [usertype] new
net/core/filter.c:1555:42: got unsigned long long [unsigned] [usertype] to
net/core/filter.c:1558:36: sparse: incorrect type in argument 2 (different base types) @@ expected restricted __be32 [usertype] from @@ got unsigned lonrestricted __be32 [usertype] from @@
net/core/filter.c:1558:36: expected restricted __be32 [usertype] from
net/core/filter.c:1558:36: got unsigned long long [unsigned] [usertype] from
net/core/filter.c:1558:42: sparse: incorrect type in argument 3 (different base types) @@ expected restricted __be32 [usertype] to @@ got unsigned lonrestricted __be32 [usertype] to @@
net/core/filter.c:1558:42: expected restricted __be32 [usertype] to
net/core/filter.c:1558:42: got unsigned long long [unsigned] [usertype] to
net/core/filter.c:1603:59: sparse: incorrect type in argument 3 (different base types) @@ expected restricted __wsum [usertype] diff @@ got unsigned lonrestricted __wsum [usertype] diff @@
net/core/filter.c:1603:59: expected restricted __wsum [usertype] diff
net/core/filter.c:1603:59: got unsigned long long [unsigned] [usertype] to
net/core/filter.c:1606:52: sparse: incorrect type in argument 3 (different base types) @@ expected restricted __be16 [usertype] from @@ got unsigned lonrestricted __be16 [usertype] from @@
net/core/filter.c:1606:52: expected restricted __be16 [usertype] from
net/core/filter.c:1606:52: got unsigned long long [unsigned] [usertype] from
net/core/filter.c:1606:58: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __be16 [usertype] to @@ got unsigned lonrestricted __be16 [usertype] to @@
net/core/filter.c:1606:58: expected restricted __be16 [usertype] to
net/core/filter.c:1606:58: got unsigned long long [unsigned] [usertype] to
net/core/filter.c:1609:52: sparse: incorrect type in argument 3 (different base types) @@ expected restricted __be32 [usertype] from @@ got unsigned lonrestricted __be32 [usertype] from @@
net/core/filter.c:1609:52: expected restricted __be32 [usertype] from
net/core/filter.c:1609:52: got unsigned long long [unsigned] [usertype] from
net/core/filter.c:1609:58: sparse: incorrect type in argument 4 (different base types) @@ expected restricted __be32 [usertype] to @@ got unsigned lonrestricted __be32 [usertype] to @@
net/core/filter.c:1609:58: expected restricted __be32 [usertype] to
net/core/filter.c:1609:58: got unsigned long long [unsigned] [usertype] to
net/core/filter.c:1655:28: sparse: incorrect type in return expression (different base types) @@ expected unsigned long long @@ got nsigned long long @@
net/core/filter.c:1655:28: expected unsigned long long
net/core/filter.c:1655:28: got restricted __wsum
net/core/filter.c:1677:35: sparse: incorrect type in return expression (different base types) @@ expected unsigned long long @@ got restricted unsigned long long @@
net/core/filter.c:1677:35: expected unsigned long long
net/core/filter.c:1677:35: got restricted __wsum [usertype] csum
net/core/filter.c:3462:41: sparse: expression using sizeof(void)
net/core/filter.c:3466:41: sparse: expression using sizeof(void)
net/core/filter.c:3470:46: sparse: expression using sizeof(void)
net/core/filter.c:3470:46: sparse: expression using sizeof(void)
net/core/filter.c:3538:47: sparse: expression using sizeof(void)
>> net/core/filter.c:3728:5: sparse: symbol 'bpf_push_seg6_encap' was not declared. Should it be static?
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/include/net/seg6_local.h b/include/net/seg6_local.h index 57498b23085d..661fd5b4d3e0 100644 --- a/include/net/seg6_local.h +++ b/include/net/seg6_local.h @@ -15,10 +15,18 @@ #ifndef _NET_SEG6_LOCAL_H #define _NET_SEG6_LOCAL_H +#include <linux/percpu.h> #include <linux/net.h> #include <linux/ipv6.h> extern int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr, u32 tbl_id); +struct seg6_bpf_srh_state { + bool valid; + u16 hdrlen; +}; + +DECLARE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states); + #endif diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index c8383a289f7b..23421dbc29a7 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -774,6 +774,51 @@ union bpf_attr { * @xdp_md: pointer to xdp_md * @delta: A negative integer to be added to xdp_md.data_end * Return: 0 on success or negative on error + * + * int lwt_push_encap(skb, type, hdr, len) + * Push an encapsulation header on top of current packet. + * @type: type of header to push : + * - BPF_LWT_ENCAP_SEG6 (push an IPv6 Segment Routing Header, struct + * ipv6_sr_hdr, the helper will add the outer IPv6 header) + * - BPF_LWT_ENCAP_SEG6_INLINE (push an IPv6 Segment Routing Header, + * struct ipv6_sr_hdr, inside the existing IPv6 header) + * @hdr: pointer where to copy the header from + * @len: size of hdr in bytes + * Return: 0 on success or negative error + * + * int lwt_seg6_store_bytes(skb, offset, from, len) + * Store bytes into the outermost Segment Routing header of an IPv6 header. + * Only the flags, tag and TLVs can be modified. + * @skb: pointer to skb + * @offset: offset within packet from skb->data + * @from: pointer where to copy bytes from + * @len: number of bytes to store into packet + * Return: 0 on success or negative error + * + * int lwt_seg6_adjust_srh(skb, offset, delta) + * Adjust the size allocated to TLVs in the outermost IPv6 Segment Routing + * Header (grow if delta > 0, else shrink) + * @skb: pointer to skb + * @offset: offset within packet from skb->data where SRH will grow/shrink, + * only offsets after the segments are accepted + * @delta: a positive/negative integer + * Return: 0 on success or negative on error + * + * int lwt_seg6_action(skb, action, param, param_len) + * Apply a IPv6 Segment Routing action on a packet with an IPv6 Segment + * Routing Header. + * @action: + * - End.X: SEG6_LOCAL_ACTION_END_X + * (type of param: struct in6_addr) + * - End.T: SEG6_LOCAL_ACTION_END_T + * (type of param: int) + * - End.B6: SEG6_LOCAL_ACTION_END_B6 + * (type of param: struct ipv6_sr_hdr) + * - End.B6.Encap: SEG6_LOCAL_ACTION_END_B6_ENCAP + * (type of param: struct ipv6_sr_hdr) + * @param: pointer to the parameter required by the action + * @param_len: length of param in bytes + * Return: 0 on success or negative error */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -841,7 +886,11 @@ union bpf_attr { FN(msg_cork_bytes), \ FN(msg_pull_data), \ FN(bind), \ - FN(xdp_adjust_tail), + FN(xdp_adjust_tail), \ + FN(lwt_push_encap), \ + FN(lwt_seg6_store_bytes), \ + FN(lwt_seg6_adjust_srh), \ + FN(lwt_seg6_action), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@ -899,6 +948,12 @@ enum bpf_adj_room_mode { BPF_ADJ_ROOM_NET, }; +/* Encapsulation type for BPF_FUNC_lwt_push_encap helper. */ +enum bpf_lwt_encap_mode { + BPF_LWT_ENCAP_SEG6, + BPF_LWT_ENCAP_SEG6_INLINE +}; + /* user accessible mirror of in-kernel sk_buff. * new fields can only be added to the end of this structure */ diff --git a/net/core/filter.c b/net/core/filter.c index e25bc4a3aa1a..8e67c423db35 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -58,6 +58,10 @@ #include <net/busy_poll.h> #include <net/tcp.h> #include <linux/bpf_trace.h> +#include <net/ipv6.h> +#include <linux/seg6_local.h> +#include <net/seg6.h> +#include <net/seg6_local.h> /** * sk_filter_trim_cap - run a packet through a socket filter @@ -3077,28 +3081,6 @@ static const struct bpf_func_proto bpf_xdp_redirect_map_proto = { .arg3_type = ARG_ANYTHING, }; -bool bpf_helper_changes_pkt_data(void *func) -{ - if (func == bpf_skb_vlan_push || - func == bpf_skb_vlan_pop || - func == bpf_skb_store_bytes || - func == bpf_skb_change_proto || - func == bpf_skb_change_head || - func == bpf_skb_change_tail || - func == bpf_skb_adjust_room || - func == bpf_skb_pull_data || - func == bpf_clone_redirect || - func == bpf_l3_csum_replace || - func == bpf_l4_csum_replace || - func == bpf_xdp_adjust_head || - func == bpf_xdp_adjust_meta || - func == bpf_msg_pull_data || - func == bpf_xdp_adjust_tail) - return true; - - return false; -} - static unsigned long bpf_skb_copy(void *dst_buff, const void *skb, unsigned long off, unsigned long len) { @@ -3743,6 +3725,246 @@ static const struct bpf_func_proto bpf_bind_proto = { .arg3_type = ARG_CONST_SIZE, }; +int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len) +{ + int err; + struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)hdr; + + if (!seg6_validate_srh(srh, len)) + return -EINVAL; + + switch (type) { + case BPF_LWT_ENCAP_SEG6_INLINE: + if (skb->protocol != htons(ETH_P_IPV6)) + return -EBADMSG; + + err = seg6_do_srh_inline(skb, srh); + break; + case BPF_LWT_ENCAP_SEG6: + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + err = seg6_do_srh_encap(skb, srh, IPPROTO_IPV6); + break; + default: + return -EINVAL; + } + if (err) + return err; + + ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + skb_set_transport_header(skb, sizeof(struct ipv6hdr)); + + return seg6_lookup_nexthop(skb, NULL, 0); +} + +BPF_CALL_4(bpf_lwt_push_encap, struct sk_buff *, skb, u32, type, void *, hdr, + u32, len) +{ + switch (type) { + case BPF_LWT_ENCAP_SEG6: + case BPF_LWT_ENCAP_SEG6_INLINE: + return bpf_push_seg6_encap(skb, type, hdr, len); + default: + return -EINVAL; + } +} + +static const struct bpf_func_proto bpf_lwt_push_encap_proto = { + .func = bpf_lwt_push_encap, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_CONST_SIZE +}; + +DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states); + +BPF_CALL_4(bpf_lwt_seg6_store_bytes, struct sk_buff *, skb, u32, offset, + const void *, from, u32, len) +{ + struct seg6_bpf_srh_state *srh_state = + this_cpu_ptr(&seg6_bpf_srh_states); + void *srh_tlvs, *srh_end, *ptr; + struct ipv6_sr_hdr *srh; + int srhoff = 0; + + if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) + return -EINVAL; + + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); + srh_tlvs = (void *)((char *)srh + ((srh->first_segment + 1) << 4)); + srh_end = (void *)((char *)srh + sizeof(*srh) + srh_state->hdrlen); + + ptr = skb->data + offset; + if (ptr >= srh_tlvs && ptr + len <= srh_end) + srh_state->valid = 0; + else if (ptr < (void *)&srh->flags || + ptr + len > (void *)&srh->segments) + return -EFAULT; + + if (unlikely(bpf_try_make_writable(skb, offset + len))) + return -EFAULT; + + memcpy(ptr, from, len); + return 0; +} + +static const struct bpf_func_proto bpf_lwt_seg6_store_bytes_proto = { + .func = bpf_lwt_seg6_store_bytes, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_CONST_SIZE +}; + +BPF_CALL_4(bpf_lwt_seg6_action, struct sk_buff *, skb, + u32, action, void *, param, u32, param_len) +{ + struct seg6_bpf_srh_state *srh_state = + this_cpu_ptr(&seg6_bpf_srh_states); + struct ipv6_sr_hdr *srh; + int srhoff = 0; + int err; + + if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) + return -EINVAL; + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); + + if (!srh_state->valid) { + if (unlikely((srh_state->hdrlen & 7) != 0)) + return -EBADMSG; + + srh->hdrlen = (u8)(srh_state->hdrlen >> 3); + if (unlikely(!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))) + return -EBADMSG; + + srh_state->valid = 1; + } + + switch (action) { + case SEG6_LOCAL_ACTION_END_X: + if (param_len != sizeof(struct in6_addr)) + return -EINVAL; + return seg6_lookup_nexthop(skb, (struct in6_addr *)param, 0); + case SEG6_LOCAL_ACTION_END_T: + if (param_len != sizeof(int)) + return -EINVAL; + return seg6_lookup_nexthop(skb, NULL, *(int *)param); + case SEG6_LOCAL_ACTION_END_B6: + err = bpf_push_seg6_encap(skb, BPF_LWT_ENCAP_SEG6_INLINE, + param, param_len); + if (!err) + srh_state->hdrlen = + ((struct ipv6_sr_hdr *)param)->hdrlen << 3; + return err; + case SEG6_LOCAL_ACTION_END_B6_ENCAP: + err = bpf_push_seg6_encap(skb, BPF_LWT_ENCAP_SEG6, + param, param_len); + if (!err) + srh_state->hdrlen = + ((struct ipv6_sr_hdr *)param)->hdrlen << 3; + return err; + default: + return -EINVAL; + } +} + +static const struct bpf_func_proto bpf_lwt_seg6_action_proto = { + .func = bpf_lwt_seg6_action, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_CONST_SIZE +}; + +BPF_CALL_3(bpf_lwt_seg6_adjust_srh, struct sk_buff *, skb, u32, offset, + s32, len) +{ + struct seg6_bpf_srh_state *srh_state = + this_cpu_ptr(&seg6_bpf_srh_states); + void *srh_end, *srh_tlvs, *ptr; + struct ipv6_sr_hdr *srh; + struct ipv6hdr *hdr; + int srhoff = 0; + int ret; + + if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) + return -EINVAL; + srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); + + srh_tlvs = (void *)((unsigned char *)srh + sizeof(*srh) + + ((srh->first_segment + 1) << 4)); + srh_end = (void *)((unsigned char *)srh + sizeof(*srh) + + srh_state->hdrlen); + ptr = skb->data + offset; + + if (unlikely(ptr < srh_tlvs || ptr > srh_end)) + return -EFAULT; + if (unlikely(len < 0 && (void *)((char *)ptr - len) > srh_end)) + return -EFAULT; + + if (len > 0) { + ret = skb_cow_head(skb, len); + if (unlikely(ret < 0)) + return ret; + + ret = bpf_skb_net_hdr_push(skb, offset, len); + } else { + ret = bpf_skb_net_hdr_pop(skb, offset, -1 * len); + } + if (unlikely(ret < 0)) + return ret; + + hdr = (struct ipv6hdr *)skb->data; + hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + + bpf_compute_data_pointers(skb); + srh_state->hdrlen += len; + srh_state->valid = 0; + return 0; +} + +static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = { + .func = bpf_lwt_seg6_adjust_srh, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, +}; + +bool bpf_helper_changes_pkt_data(void *func) +{ + if (func == bpf_skb_vlan_push || + func == bpf_skb_vlan_pop || + func == bpf_skb_store_bytes || + func == bpf_skb_change_proto || + func == bpf_skb_change_head || + func == bpf_skb_change_tail || + func == bpf_skb_adjust_room || + func == bpf_skb_pull_data || + func == bpf_clone_redirect || + func == bpf_l3_csum_replace || + func == bpf_l4_csum_replace || + func == bpf_xdp_adjust_head || + func == bpf_xdp_adjust_meta || + func == bpf_msg_pull_data || + func == bpf_xdp_adjust_tail || + func == bpf_lwt_push_encap || + func == bpf_lwt_seg6_store_bytes || + func == bpf_lwt_seg6_adjust_srh + ) + return true; + + return false; +} + static const struct bpf_func_proto * bpf_base_func_proto(enum bpf_func_id func_id) { @@ -4139,7 +4361,6 @@ static bool lwt_is_valid_access(int off, int size, return bpf_skb_is_valid_access(off, size, type, prog, info); } - /* Attach type specific accesses */ static bool __sock_filter_check_attach_type(int off, enum bpf_access_type access_type,