ipv6: sr: introduce seg6local End.BPF action
Subsystems (8)
v2 cover ipv6: sr: introduce seg6local End.BPF action
As of Linux 4.14, it is possible to define advanced local processing for IPv6 packets with a Segment Routing Header through the seg6local LWT infrastructure. This LWT implements the network programming principles defined in the IETF “SRv6 Network Programming” draft.
The implemented operations are generic, and it would be very interesting to be able to implement user-specific seg6local actions, without having to modify the kernel directly. To do so, this patchset adds an End.BPF action to seg6local, powered by some specific Segment Routing-related helpers, which provide SR functionalities that can be applied on the packet. This BPF hook would then allow to implement specific actions at native kernel speed such as OAM features, advanced SR SDN policies, SRv6 actions like Segment Routing Header (SRH) encapsulation depending on the content of the packet, etc ...
This patchset is divided in 5 patches, whose main features are :
- A new seg6local action End.BPF with the corresponding new BPF program type BPF_PROG_TYPE_LWT_SEG6LOCAL. Such attached BPF program can be passed to the LWT seg6local through netlink, the same way as the LWT BPF hook operates.
- 3 new BPF helpers for the seg6local BPF hook, allowing to edit/grow/ shrink a SRH and apply on a packet some of the generic SRv6 actions.
- 1 new BPF helper for the LWT BPF IN hook, allowing to add a SRH through encapsulation (via IPv6 encapsulation or inlining if the packet contains already an IPv6 header).
As this patchset adds a new LWT BPF hook, I took into account the result of the discussions when the LWT BPF infrastructure got merged. Hence, the seg6local BPF hook doesn’t allow write access to skb->data directly, only the SRH can be modified through specific helpers, which ensures that the integrity of the packet is maintained.
More details are available in the related patches messages.
The performances of this BPF hook have been assessed with the BPF JIT enabled on a Intel Xeon X3440 processors with 4 cores and 8 threads clocked at 2.53 GHz. No throughput losses are noted with the seg6local BPF hook when the BPF program does nothing (440kpps). Adding a 8-bytes TLV (1 call each to bpf_lwt_seg6_adjust_srh and bpf_lwt_seg6_store_bytes) drops the throughput to 410kpps, and inlining a SRH via bpf_lwt_seg6_action drops the throughput to 420kpps.
All throughputs are stable.
-------
v2: move the SRH integrity state from skb->cb to a per-cpu buffer
Thanks.
Mathieu Xhonneux (5):
ipv6: sr: export function lookup_nexthop
bpf: Add IPv6 Segment Routing helpers
bpf: Split lwt inout verifier structures
ipv6: sr: Add seg6local action End.BPF selftests/bpf: test for seg6local End.BPF action
include/linux/bpf_types.h | 4 +- include/net/seg6.h | 3 +- include/net/seg6_local.h | 32 ++ include/uapi/linux/bpf.h | 58 ++- include/uapi/linux/seg6_local.h | 3 + kernel/bpf/verifier.c | 1 + net/core/filter.c | 375 +++++++++++++++--- net/ipv6/seg6_local.c | 176 ++++++++- tools/include/uapi/linux/bpf.h | 59 ++- tools/testing/selftests/bpf/Makefile | 6 +- tools/testing/selftests/bpf/bpf_helpers.h | 13 +- tools/testing/selftests/bpf/test_lwt_seg6local.c | 438 ++++++++++++++++++++++ tools/testing/selftests/bpf/test_lwt_seg6local.sh | 140 +++++++ 13 files changed, 1234 insertions(+), 74 deletions(-) create mode 100644 include/net/seg6_local.h create mode 100644 tools/testing/selftests/bpf/test_lwt_seg6local.c create mode 100755 tools/testing/selftests/bpf/test_lwt_seg6local.sh
Signature · 1 line
2.16.1
PATCH v2 1/5 ipv6: sr: export function lookup_nexthop
The function lookup_nexthop is essential to implement most of the seg6local actions. As we want to provide a BPF helper allowing to apply some of these actions on the packet being processed, the helper should be able to call this function, hence the need to make it public.
Moreover, if one argument is incorrect or if the next hop can not be found, an error should be returned by the BPF helper so the BPF program can adapt its processing of the packet (return an error, properly force the drop, ...). This patch hence makes this function return dst->error to indicate a possible error.
--- include/net/seg6.h | 3 ++- include/net/seg6_local.h | 24 ++++++++++++++++++++++++ net/ipv6/seg6_local.c | 20 +++++++++++--------- 3 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 include/net/seg6_local.h
include/net/seg6.h +2 -1
@@ -63,5 +63,6 @@ extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);extern int seg6_do_srh_encap (struct sk_buff *skb,struct ipv6_sr_hdr *osrh,int proto);extern int seg6_do_srh_inline (struct sk_buff *skb,struct ipv6_sr_hdr *osrh); - +extern int seg6_lookup_nexthop (struct sk_buff *skb,struct in6_addr *nhaddr, +u32 tbl_id);#endif
include/net/seg6_local.h new file +24 -0
@@ -0,0 +1,24 @@ +/* +* SR-IPv6 implementation +* +* Authors: +* David Lebrun <[email protected]> +* eBPF support: Mathieu Xhonneux <[email protected]> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version +* 2 of the License, or (at your option) any later version. +*/ + +#ifndef _NET_SEG6_LOCAL_H +#define _NET_SEG6_LOCAL_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); + +#endif
net/ipv6/seg6_local.c +11 -9
@@ -30,6 +30,7 @@#ifdef CONFIG_IPV6_SEG6_HMAC #include <net/seg6_hmac.h> #endif +#include <net/seg6_local.h> #include <linux/etherdevice.h> struct seg6_local_lwt ;
@@ -140,8 +141,8 @@ static void advance_nextseg(struct ipv6_sr_hdr *srh, struct in6_addr *daddr) *daddr = *addr; } -static void lookup_nexthop (struct sk_buff *skb,struct in6_addr *nhaddr, -u32 tbl_id) +int seg6_lookup_nexthop (struct sk_buff *skb,struct in6_addr *nhaddr, +u32 tbl_id) {struct net *net =dev_net (skb->dev);struct ipv6hdr *hdr =ipv6_hdr (skb);
@@ -187,6 +188,7 @@ static void lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,skb_dst_drop (skb);skb_dst_set (skb, dst); +return dst->error; }/* regular endpoint function */
@@ -200,7 +202,7 @@ static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)advance_nextseg (srh, &ipv6_hdr (skb)->daddr); -lookup_nexthop (skb,NULL ,0 ); +seg6_lookup_nexthop (skb,NULL ,0 );return dst_input (skb);
@@ -220,7 +222,7 @@ static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)advance_nextseg (srh, &ipv6_hdr (skb)->daddr); -lookup_nexthop (skb, &slwt->nh6,0 ); +seg6_lookup_nexthop (skb, &slwt->nh6,0 );return dst_input (skb);
@@ -239,7 +241,7 @@ static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt)advance_nextseg (srh, &ipv6_hdr (skb)->daddr); -lookup_nexthop (skb,NULL , slwt->table); +seg6_lookup_nexthop (skb,NULL , slwt->table);return dst_input (skb);
@@ -331,7 +333,7 @@ static int input_action_end_dx6(struct sk_buff *skb,if (!ipv6_addr_any (&slwt->nh6)) nhaddr = &slwt->nh6; -lookup_nexthop (skb, nhaddr,0 ); +seg6_lookup_nexthop (skb, nhaddr,0 );return dst_input (skb); drop:
@@ -380,7 +382,7 @@ static int input_action_end_dt6(struct sk_buff *skb,if (!pskb_may_pull (skb,sizeof (struct ipv6hdr ))) goto drop; -lookup_nexthop (skb,NULL , slwt->table); +seg6_lookup_nexthop (skb,NULL , slwt->table);return dst_input (skb);
@@ -406,7 +408,7 @@ static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)ipv6_hdr (skb)->payload_len =htons (skb->len -sizeof (struct ipv6hdr ));skb_set_transport_header (skb,sizeof (struct ipv6hdr )); -lookup_nexthop (skb,NULL ,0 ); +seg6_lookup_nexthop (skb,NULL ,0 );return dst_input (skb);
@@ -438,7 +440,7 @@ static int input_action_end_b6_encap(struct sk_buff *skb,ipv6_hdr (skb)->payload_len =htons (skb->len -sizeof (struct ipv6hdr ));skb_set_transport_header (skb,sizeof (struct ipv6hdr )); -lookup_nexthop (skb,NULL ,0 ); +seg6_lookup_nexthop (skb,NULL ,0 );return dst_input (skb);
Signature · 1 line
2.16.1
PATCH v2 2/5 bpf: Add IPv6 Segment Routing helpers
In reply to Mathieu XhonneuxThe BPF seg6local hook should be powerful enough to enable users to implement most of the use-cases one could think of. After some thinking, we figured out that the following actions should be possible on a SRv6 packet, requiring 3 specific helpers :
- bpf_lwt_seg6_store_bytes: Modify non-sensitive fields of the SRH
- bpf_lwt_seg6_adjust_srh: Allow to grow or shrink a SRH (to add/delete TLVs)
- bpf_lwt_seg6_action: Apply some SRv6 network programming actions (specifically End.X, End.T, End.B6 and End.B6.Encap)
The specifications of these helpers are provided in the patch (see include/uapi/linux/bpf.h).
The non-sensitive fields of the SRH are the following : flags, tag and TLVs. The other fields can not be modified, to maintain the SRH integrity. Flags, tag and TLVs can easily be modified as their validity can be checked afterwards via seg6_validate_srh. It is not allowed to modify the segments directly. If one wants to add segments on the path, he should stack a new SRH using the End.B6 action via bpf_lwt_seg6_action.
Growing, shrinking or editing TLVs via the helpers will flag the SRH as invalid, and it will have to be re-validated before re-entering the IPv6 layer. This flag is stored in a per-CPU buffer, along with the current header length in bytes.
Storing the SRH len in bytes in the control block is mandatory when using bpf_lwt_seg6_adjust_srh. The Header Ext. Length field contains the SRH len rounded to 8 bytes (a padding TLV can be inserted to ensure the 8-bytes boundary). When adding/deleting TLVs within the BPF program, the SRH may temporary be in an invalid state where its length cannot be rounded to 8 bytes without remainder, hence the need to store the length in bytes separately. The caller of the BPF program can then ensure that the SRH's final length is valid using this value. Again, a final SRH modified by a BPF program which doesn’t respect the 8-bytes boundary will be discarded as it will be considered as invalid.
Finally, a fourth helper is provided, bpf_lwt_push_encap, which is available from the LWT BPF IN hook, but not from the seg6local BPF one. This helper allows to encapsulate a Segment Routing Header (either with a new outer IPv6 header, or by inlining it directly in the existing IPv6 header) into a non-SRv6 packet. This helper is required if we want to offer the possibility to dynamically encapsulate a SRH for non-SRv6 packet, as the BPF seg6local hook only works on traffic already containing a SRH. This is the BPF equivalent of the seg6 LWT infrastructure, which achieves the same purpose but with a static SRH per route.
--- include/net/seg6_local.h | 8 ++ include/uapi/linux/bpf.h | 57 +++++++++- net/core/filter.c | 267 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 308 insertions(+), 24 deletions(-)
include/net/seg6_local.h +8 -0
@@ -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
include/uapi/linux/bpf.h +56 -1
75 lines not on this page · raw message
net/core/filter.c +244 -23
291 lines not on this page · raw message
Signature · 1 line
2.16.1
kbuild test robot
build botRe: [PATCH net-next v2 2/5] bpf: Add IPv6 Segment Routing helpers
Thank you for the patch! Yet something to improve:
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;
^~~~
ipv4vim +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 <[email protected]> :::::: CC: David S. Miller <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
kbuild test robot
build botRe: [PATCH net-next v2 2/5] bpf: Add IPv6 Segment Routing helpers
In reply to Mathieu XhonneuxThank you for the patch! Yet something to improve:
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
kbuild test robot
build bot[RFC PATCH] bpf: bpf_push_seg6_encap() can be static
In reply to Mathieu XhonneuxFixes: 14ab8554dc46 ("bpf: Add IPv6 Segment Routing helpers")
--- filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/filter.c +1 -1
@@ -3725,7 +3725,7 @@ 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) +static 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;
kbuild test robot
build botRe: [PATCH net-next v2 2/5] bpf: Add IPv6 Segment Routing helpers
In reply to Mathieu XhonneuxThank you for the patch! Perhaps something to improve:
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
PATCH v2 3/5 bpf: Split lwt inout verifier structures
In reply to Mathieu XhonneuxThe new bpf_lwt_push_encap helper should only be accessible within the LWT BPF IN hook, and not the OUT one, as this may lead to a skb under panic.
At the moment, both LWT BPF IN and OUT share the same list of helpers, whose calls are authorized by the verifier. This patch separates the verifier ops for the IN and OUT hooks, and allows the IN hook to call the bpf_lwt_push_encap helper.
This patch is also the occasion to put all lwt_*_func_proto functions together for clarity. At the moment, socks_op_func_proto is in the middle of lwt_inout_func_proto and lwt_xmit_func_proto.
--- include/linux/bpf_types.h | 3 +- net/core/filter.c | 83 +++++++++++++++++++++++++++++------------------ 2 files changed, 53 insertions(+), 33 deletions(-)
include/linux/bpf_types.h +1 -2
@@ -9,8 +9,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_XDP, xdp) BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SKB, cg_skb) BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK, cg_sock) BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, cg_sock_addr) -BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_IN, lwt_inout) -BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_OUT, lwt_inout) +BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_IN, lwt_in) BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_XMIT, lwt_xmit) BPF_PROG_TYPE(BPF_PROG_TYPE_SOCK_OPS, sock_ops)BPF_PROG_TYPE (BPF_PROG_TYPE_SK_SKB , sk_skb)
net/core/filter.c +52 -31
111 lines not on this page · raw message
Signature · 1 line
2.16.1
kbuild test robot
build bot[RFC PATCH] bpf: lwt_out_verifier_ops can be static
Fixes: 5c3289b57b1b ("bpf: Split lwt inout verifier structures")
--- filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/filter.c +2 -2
@@ -5803,13 +5803,13 @@ const struct bpf_prog_ops lwt_in_prog_ops = { .test_run = bpf_prog_test_run_skb, }; -const struct bpf_verifier_ops lwt_out_verifier_ops = { +static const struct bpf_verifier_ops lwt_out_verifier_ops = { .get_func_proto = lwt_out_func_proto, .is_valid_access = lwt_is_valid_access, .convert_ctx_access = bpf_convert_ctx_access, }; -const struct bpf_prog_ops lwt_out_prog_ops = { +static const struct bpf_prog_ops lwt_out_prog_ops = { .test_run = bpf_prog_test_run_skb, };
kbuild test robot
build botRe: [PATCH net-next v2 3/5] bpf: Split lwt inout verifier structures
In reply to Mathieu XhonneuxThank you for the patch! Perhaps something to improve:
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?
>> net/core/filter.c:5806:31: sparse: symbol 'lwt_out_verifier_ops' was not declared. Should it be static? >> net/core/filter.c:5812:27: sparse: symbol 'lwt_out_prog_ops' 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
PATCH v2 4/5 ipv6: sr: Add seg6local action End.BPF
In reply to Mathieu XhonneuxThis patch adds the End.BPF action to the LWT seg6local infrastructure. This action works like any other seg6local End action, meaning that an IPv6 header with SRH is needed, whose DA has to be equal to the SID of the action. It will also advance the SRH to the next segment, the BPF program does not have to take care of this.
Since the BPF program may not be a source of instability in the kernel, it is important to ensure that the integrity of the packet is maintained before yielding it back to the IPv6 layer. The hook hence keeps track if the SRH has been altered through the helpers, and re-validates its content if needed with seg6_validate_srh. The state kept for validation is stored in a per-CPU buffer. The BPF program is not allowed to directly write into the packet, and only some fields of the SRH can be altered through the helper bpf_lwt_seg6_store_bytes.
Performances profiling has shown that the SRH re-validation does not induce a significant overhead. If the altered SRH is deemed as invalid, the packet is dropped.
This validation is also done before executing any action through bpf_lwt_seg6_action, and will not be performed again if the SRH is not modified after calling the action.
The BPF program may return 3 types of return codes:
- BPF_OK: the End.BPF action will look up the next destination through seg6_lookup_nexthop.
- BPF_REDIRECT: if an action has been executed through the bpf_lwt_seg6_action helper, the BPF program should return this value, as the skb's destination is already set and the default lookup should not be performed.
- BPF_DROP : the packet will be dropped.
--- include/linux/bpf_types.h | 1 + include/uapi/linux/bpf.h | 1 + include/uapi/linux/seg6_local.h | 3 + kernel/bpf/verifier.c | 1 + net/core/filter.c | 25 +++++++ net/ipv6/seg6_local.c | 156 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 184 insertions(+), 3 deletions(-)
include/linux/bpf_types.h +1 -0
@@ -11,6 +11,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK, cg_sock) BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, cg_sock_addr) BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_IN, lwt_in) BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_XMIT, lwt_xmit) +BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_SEG6LOCAL, lwt_seg6local) BPF_PROG_TYPE(BPF_PROG_TYPE_SOCK_OPS, sock_ops) BPF_PROG_TYPE(BPF_PROG_TYPE_SK_SKB, sk_skb)BPF_PROG_TYPE (BPF_PROG_TYPE_SK_MSG , sk_msg)
include/uapi/linux/bpf.h +1 -0
@@ -138,6 +138,7 @@ enum bpf_prog_type {BPF_PROG_TYPE_SK_MSG ,BPF_PROG_TYPE_RAW_TRACEPOINT ,BPF_PROG_TYPE_CGROUP_SOCK_ADDR , + BPF_PROG_TYPE_LWT_SEG6LOCAL, }; enum bpf_attach_type {
include/uapi/linux/seg6_local.h +3 -0
@@ -25,6 +25,7 @@ enum {SEG6_LOCAL_NH6 ,SEG6_LOCAL_IIF ,SEG6_LOCAL_OIF , +SEG6_LOCAL_BPF , __SEG6_LOCAL_MAX, };#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
@@ -59,6 +60,8 @@ enum {SEG6_LOCAL_ACTION_END_AS =13 ,/* forward to SR-unaware VNF with masquerading */ SEG6_LOCAL_ACTION_END_AM =14 , +/* custom BPF action */ +SEG6_LOCAL_ACTION_END_BPF =15 , __SEG6_LOCAL_ACTION_MAX, };
kernel/bpf/verifier.c +1 -0
@@ -1251,6 +1251,7 @@ static bool may_access_direct_pkt_data(struct bpf_verifier_env *env,switch (env->prog->type) {case BPF_PROG_TYPE_LWT_IN :case BPF_PROG_TYPE_LWT_OUT : +case BPF_PROG_TYPE_LWT_SEG6LOCAL :/* dst_input() and dst_output() can't write for now */ if (t ==BPF_WRITE )return false;
net/core/filter.c +25 -0
@@ -4268,6 +4268,21 @@ lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) } } +static const struct bpf_func_proto * +lwt_seg6local_func_proto (enum bpf_func_id func_id,const struct bpf_prog *prog) +{ +switch (func_id) { +case BPF_FUNC_lwt_seg6_store_bytes: +return &bpf_lwt_seg6_store_bytes_proto; +case BPF_FUNC_lwt_seg6_action: +return &bpf_lwt_seg6_action_proto; +case BPF_FUNC_lwt_seg6_adjust_srh: +return &bpf_lwt_seg6_adjust_srh_proto; +default : +return lwt_out_func_proto (func_id, prog); + } +} +static bool bpf_skb_is_valid_access (int off,int size,enum bpf_access_type type,const struct bpf_prog *prog,struct bpf_insn_access_aux *info)
@@ -5824,6 +5839,16 @@ const struct bpf_prog_ops lwt_xmit_prog_ops = { .test_run = bpf_prog_test_run_skb, }; +const struct bpf_verifier_ops lwt_seg6local_verifier_ops = { + .get_func_proto = lwt_seg6local_func_proto, + .is_valid_access = lwt_is_valid_access, + .convert_ctx_access = bpf_convert_ctx_access, +}; + +const struct bpf_prog_ops lwt_seg6local_prog_ops = { + .test_run = bpf_prog_test_run_skb, +}; +const struct bpf_verifier_ops cg_sock_verifier_ops = { .get_func_proto = sock_filter_func_proto, .is_valid_access = sock_filter_is_valid_access,
net/ipv6/seg6_local.c +153 -3
223 lines not on this page · raw message
Signature · 1 line
2.16.1
David Miller
maintainerRe: [PATCH net-next v2 4/5] ipv6: sr: Add seg6local action End.BPF
From: Mathieu Xhonneux <[email protected]>
Date: Tue, 24 Apr 2018 18:44:15 +0100
Quoted 5 lines
This patch adds the End.BPF action to the LWT seg6local infrastructure. This action works like any other seg6local End action, meaning that an IPv6 header with SRH is needed, whose DA has to be equal to the SID of the action. It will also advance the SRH to the next segment, the BPF program does not have to take care of this.
I'd like to see some BPF developers review this change.
But on my side I wonder if, instead of validating the whole thing afterwards, we should make the helpers accessible by the eBPF program validate the changes as they are made.
Re: [PATCH net-next v2 4/5] ipv6: sr: Add seg6local action End.BPF
Quoted 9 lines · David Miller
From: Mathieu Xhonneux <[email protected]>
Date: Tue, 24 Apr 2018 18:44:15 +0100Quoted 5 lines
This patch adds the End.BPF action to the LWT seg6local infrastructure. This action works like any other seg6local End action, meaning that an IPv6 header with SRH is needed, whose DA has to be equal to the SID of the action. It will also advance the SRH to the next segment, the BPF program does not have to take care of this.
Quoted 5 lines
I'd like to see some BPF developers review this change.
But on my side I wonder if, instead of validating the whole thing afterwards, we should make the helpers accessible by the eBPF program validate the changes as they are made.
Looking at the code I don't think it's possible to keep it valid all the time while building, so seg6_validate_srh() after the program run seems necessary.
I think the whole set should be targeting bpf-next tree.
Please fix kbuild errors, rebase and document new helper in man-page style. Things like:
+ test_btf_haskv.o test_btf_nokv.o test_lwt_seg6local.o
+>>>>>>> selftests/bpf: test for seg6local End.BPF action should be fixed properly.
Re: [PATCH net-next v2 4/5] ipv6: sr: Add seg6local action End.BPF
2018-04-28 2:01 GMT+02:00 Alexei Starovoitov <[email protected]>:
Quoted 11 lines · David Miller
Quoted 9 lines
From: Mathieu Xhonneux <[email protected]>
Date: Tue, 24 Apr 2018 18:44:15 +0100Quoted 5 lines
This patch adds the End.BPF action to the LWT seg6local infrastructure. This action works like any other seg6local End action, meaning that an IPv6 header with SRH is needed, whose DA has to be equal to the SID of the action. It will also advance the SRH to the next segment, the BPF program does not have to take care of this.
Quoted 8 lines
Quoted 5 lines
I'd like to see some BPF developers review this change.
But on my side I wonder if, instead of validating the whole thing afterwards, we should make the helpers accessible by the eBPF program validate the changes as they are made.
Looking at the code I don't think it's possible to keep it valid all the time while building, so
seg6_validate_srh()after the program run seems necessary.
Indeed, e.g. to add a TLV in the SRH one needs to call bpf_lwt_seg6_adjust_srh (to add some room for the TLV), then bpf_lwt_seg6_store_bytes() (to fill the space with the TLV). Between those two calls, the SRH is in an invalid state.
Quoted 8 lines
I think the whole set should be targeting bpf-next tree.
Please fix kbuild errors, rebase and document new helper in man-page style. Things like:
+ test_btf_haskv.o test_btf_nokv.o test_lwt_seg6local.o
+>>>>>>> selftests/bpf: test for seg6local End.BPF action should be fixed properly.
Oops, I didn't catch this one, thanks. I'll send a v3 towards bpf-next.
PATCH v2 5/5 selftests/bpf: test for seg6local End.BPF action
In reply to Mathieu XhonneuxAdd a new test for the seg6local End.BPF action. The following helpers are also tested :
- bpf_lwt_push_encap within the LWT BPF IN hook
- bpf_lwt_seg6_action
- bpf_lwt_seg6_adjust_srh
- bpf_lwt_seg6_store_bytes
A chain of End.BPF actions is built. The SRH is injected through a LWT BPF IN hook before the chain. Each End.BPF action validates the previous one, otherwise the packet is dropped.
The test succeeds if the last node in the chain receives the packet and the UDP datagram contained can be retrieved from userspace.
--- tools/include/uapi/linux/bpf.h | 59 ++- tools/testing/selftests/bpf/Makefile | 6 +- tools/testing/selftests/bpf/bpf_helpers.h | 13 +- tools/testing/selftests/bpf/test_lwt_seg6local.c | 438 ++++++++++++++++++++++ tools/testing/selftests/bpf/test_lwt_seg6local.sh | 140 +++++++ 5 files changed, 652 insertions(+), 4 deletions(-) create mode 100644 tools/testing/selftests/bpf/test_lwt_seg6local.c create mode 100755 tools/testing/selftests/bpf/test_lwt_seg6local.sh
tools/include/uapi/linux/bpf.h +58 -1
@@ -138,6 +138,7 @@ enum bpf_prog_type {BPF_PROG_TYPE_SK_MSG ,BPF_PROG_TYPE_RAW_TRACEPOINT ,BPF_PROG_TYPE_CGROUP_SOCK_ADDR , + BPF_PROG_TYPE_LWT_SEG6LOCAL, }; enum bpf_attach_type {
@@ -774,6 +775,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 +887,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
@@ -884,6 +934,7 @@ enum bpf_func_id {/* BPF_FUNC_skb_set_tunnel_key flags. */ #define BPF_F_ZERO_CSUM_TX (1ULL << 1)#define BPF_F_DONT_FRAGMENT (1ULL << 2) +#define BPF_F_SEQ_NUMBER (1ULL << 3)/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and * BPF_FUNC_perf_event_read_value flags.
@@ -898,6 +949,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 */
tools/testing/selftests/bpf/Makefile +4 -2
@@ -32,7 +32,8 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \ sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \ sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \ - test_btf_haskv.o test_btf_nokv.o + test_btf_haskv.o test_btf_nokv.o test_lwt_seg6local.o +>>>>>>> selftests/bpf: test for seg6local End.BPF action # Order correspond to 'make run_tests' order TEST_PROGS := test_kmod.sh \
@@ -40,7 +41,8 @@ TEST_PROGS := test_kmod.sh \ test_xdp_redirect.sh \ test_xdp_meta.sh \ test_offload.py \ - test_sock_addr.sh + test_sock_addr.sh \ + test_lwt_seg6local.sh # Compile but not part of 'make run_tests' TEST_GEN_PROGS_EXTENDED = test_libbpf_open
tools/testing/selftests/bpf/bpf_helpers.h +12 -1
@@ -98,7 +98,18 @@ static int (*bpf_bind)(void *ctx, void *addr, int addr_len) = (void *) BPF_FUNC_bind;static int (*bpf_xdp_adjust_tail)(void *ctx,int offset) = (void *) BPF_FUNC_xdp_adjust_tail; - +static int (*bpf_lwt_push_encap)(void *ctx,unsigned int type,void *hdr, +unsigned int len) = + (void *) BPF_FUNC_lwt_push_encap; +static int (*bpf_lwt_seg6_store_bytes)(void *ctx,unsigned int offset, +void *from,unsigned int len) = + (void *) BPF_FUNC_lwt_seg6_store_bytes; +static int (*bpf_lwt_seg6_action)(void *ctx,unsigned int action,void *param, +unsigned int param_len) = + (void *) BPF_FUNC_lwt_seg6_action; +static int (*bpf_lwt_seg6_adjust_srh)(void *ctx,unsigned int offset, +unsigned int len) = + (void *) BPF_FUNC_lwt_seg6_adjust_srh;/* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions
tools/testing/selftests/bpf/test_lwt_seg6local.c new file +438 -0
438 lines not on this page · raw message
tools/testing/selftests/bpf/test_lwt_seg6local.sh new file +140 -0
140 lines not on this page · raw message
Signature · 1 line
2.16.1