Skip to content

Commit 7cdec54

Browse files
borkmannAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: Add csum_level helper for fixing up csum levels
Add a bpf_csum_level() helper which BPF programs can use in combination with bpf_skb_adjust_room() when they pass in BPF_F_ADJ_ROOM_NO_CSUM_RESET flag to the latter to avoid falling back to CHECKSUM_NONE. The bpf_csum_level() allows to adjust CHECKSUM_UNNECESSARY skb->csum_levels via BPF_CSUM_LEVEL_{INC,DEC} which calls __skb_{incr,decr}_checksum_unnecessary() on the skb. The helper also allows a BPF_CSUM_LEVEL_RESET which sets the skb's csum to CHECKSUM_NONE as well as a BPF_CSUM_LEVEL_QUERY to just return the current level. Without this helper, there is no way to otherwise adjust the skb->csum_level. I did not add an extra dummy flags as there is plenty of free bitspace in level argument itself iff ever needed in future. Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Reviewed-by: Alan Maguire <[email protected]> Acked-by: Lorenz Bauer <[email protected]> Link: https://lore.kernel.org/bpf/279ae3717cb3d03c0ffeb511493c93c450a01e1a.1591108731.git.daniel@iogearbox.net
1 parent 836e66c commit 7cdec54

File tree

3 files changed

+122
-2
lines changed

3 files changed

+122
-2
lines changed

include/uapi/linux/bpf.h

+42-1
Original file line numberDiff line numberDiff line change
@@ -3220,6 +3220,38 @@ union bpf_attr {
32203220
* calculation.
32213221
* Return
32223222
* Requested value, or 0, if flags are not recognized.
3223+
*
3224+
* int bpf_csum_level(struct sk_buff *skb, u64 level)
3225+
* Description
3226+
* Change the skbs checksum level by one layer up or down, or
3227+
* reset it entirely to none in order to have the stack perform
3228+
* checksum validation. The level is applicable to the following
3229+
* protocols: TCP, UDP, GRE, SCTP, FCOE. For example, a decap of
3230+
* | ETH | IP | UDP | GUE | IP | TCP | into | ETH | IP | TCP |
3231+
* through **bpf_skb_adjust_room**\ () helper with passing in
3232+
* **BPF_F_ADJ_ROOM_NO_CSUM_RESET** flag would require one call
3233+
* to **bpf_csum_level**\ () with **BPF_CSUM_LEVEL_DEC** since
3234+
* the UDP header is removed. Similarly, an encap of the latter
3235+
* into the former could be accompanied by a helper call to
3236+
* **bpf_csum_level**\ () with **BPF_CSUM_LEVEL_INC** if the
3237+
* skb is still intended to be processed in higher layers of the
3238+
* stack instead of just egressing at tc.
3239+
*
3240+
* There are three supported level settings at this time:
3241+
*
3242+
* * **BPF_CSUM_LEVEL_INC**: Increases skb->csum_level for skbs
3243+
* with CHECKSUM_UNNECESSARY.
3244+
* * **BPF_CSUM_LEVEL_DEC**: Decreases skb->csum_level for skbs
3245+
* with CHECKSUM_UNNECESSARY.
3246+
* * **BPF_CSUM_LEVEL_RESET**: Resets skb->csum_level to 0 and
3247+
* sets CHECKSUM_NONE to force checksum validation by the stack.
3248+
* * **BPF_CSUM_LEVEL_QUERY**: No-op, returns the current
3249+
* skb->csum_level.
3250+
* Return
3251+
* 0 on success, or a negative error in case of failure. In the
3252+
* case of **BPF_CSUM_LEVEL_QUERY**, the current skb->csum_level
3253+
* is returned or the error code -EACCES in case the skb is not
3254+
* subject to CHECKSUM_UNNECESSARY.
32233255
*/
32243256
#define __BPF_FUNC_MAPPER(FN) \
32253257
FN(unspec), \
@@ -3356,7 +3388,8 @@ union bpf_attr {
33563388
FN(ringbuf_reserve), \
33573389
FN(ringbuf_submit), \
33583390
FN(ringbuf_discard), \
3359-
FN(ringbuf_query),
3391+
FN(ringbuf_query), \
3392+
FN(csum_level),
33603393

33613394
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
33623395
* function eBPF program intends to call
@@ -3433,6 +3466,14 @@ enum {
34333466
BPF_F_CURRENT_NETNS = (-1L),
34343467
};
34353468

3469+
/* BPF_FUNC_csum_level level values. */
3470+
enum {
3471+
BPF_CSUM_LEVEL_QUERY,
3472+
BPF_CSUM_LEVEL_INC,
3473+
BPF_CSUM_LEVEL_DEC,
3474+
BPF_CSUM_LEVEL_RESET,
3475+
};
3476+
34363477
/* BPF_FUNC_skb_adjust_room flags. */
34373478
enum {
34383479
BPF_F_ADJ_ROOM_FIXED_GSO = (1ULL << 0),

net/core/filter.c

+38
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,40 @@ static const struct bpf_func_proto bpf_csum_update_proto = {
20152015
.arg2_type = ARG_ANYTHING,
20162016
};
20172017

2018+
BPF_CALL_2(bpf_csum_level, struct sk_buff *, skb, u64, level)
2019+
{
2020+
/* The interface is to be used in combination with bpf_skb_adjust_room()
2021+
* for encap/decap of packet headers when BPF_F_ADJ_ROOM_NO_CSUM_RESET
2022+
* is passed as flags, for example.
2023+
*/
2024+
switch (level) {
2025+
case BPF_CSUM_LEVEL_INC:
2026+
__skb_incr_checksum_unnecessary(skb);
2027+
break;
2028+
case BPF_CSUM_LEVEL_DEC:
2029+
__skb_decr_checksum_unnecessary(skb);
2030+
break;
2031+
case BPF_CSUM_LEVEL_RESET:
2032+
__skb_reset_checksum_unnecessary(skb);
2033+
break;
2034+
case BPF_CSUM_LEVEL_QUERY:
2035+
return skb->ip_summed == CHECKSUM_UNNECESSARY ?
2036+
skb->csum_level : -EACCES;
2037+
default:
2038+
return -EINVAL;
2039+
}
2040+
2041+
return 0;
2042+
}
2043+
2044+
static const struct bpf_func_proto bpf_csum_level_proto = {
2045+
.func = bpf_csum_level,
2046+
.gpl_only = false,
2047+
.ret_type = RET_INTEGER,
2048+
.arg1_type = ARG_PTR_TO_CTX,
2049+
.arg2_type = ARG_ANYTHING,
2050+
};
2051+
20182052
static inline int __bpf_rx_skb(struct net_device *dev, struct sk_buff *skb)
20192053
{
20202054
return dev_forward_skb(dev, skb);
@@ -6280,6 +6314,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
62806314
return &bpf_csum_diff_proto;
62816315
case BPF_FUNC_csum_update:
62826316
return &bpf_csum_update_proto;
6317+
case BPF_FUNC_csum_level:
6318+
return &bpf_csum_level_proto;
62836319
case BPF_FUNC_l3_csum_replace:
62846320
return &bpf_l3_csum_replace_proto;
62856321
case BPF_FUNC_l4_csum_replace:
@@ -6613,6 +6649,8 @@ lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
66136649
return &bpf_skb_store_bytes_proto;
66146650
case BPF_FUNC_csum_update:
66156651
return &bpf_csum_update_proto;
6652+
case BPF_FUNC_csum_level:
6653+
return &bpf_csum_level_proto;
66166654
case BPF_FUNC_l3_csum_replace:
66176655
return &bpf_l3_csum_replace_proto;
66186656
case BPF_FUNC_l4_csum_replace:

tools/include/uapi/linux/bpf.h

+42-1
Original file line numberDiff line numberDiff line change
@@ -3220,6 +3220,38 @@ union bpf_attr {
32203220
* calculation.
32213221
* Return
32223222
* Requested value, or 0, if flags are not recognized.
3223+
*
3224+
* int bpf_csum_level(struct sk_buff *skb, u64 level)
3225+
* Description
3226+
* Change the skbs checksum level by one layer up or down, or
3227+
* reset it entirely to none in order to have the stack perform
3228+
* checksum validation. The level is applicable to the following
3229+
* protocols: TCP, UDP, GRE, SCTP, FCOE. For example, a decap of
3230+
* | ETH | IP | UDP | GUE | IP | TCP | into | ETH | IP | TCP |
3231+
* through **bpf_skb_adjust_room**\ () helper with passing in
3232+
* **BPF_F_ADJ_ROOM_NO_CSUM_RESET** flag would require one call
3233+
* to **bpf_csum_level**\ () with **BPF_CSUM_LEVEL_DEC** since
3234+
* the UDP header is removed. Similarly, an encap of the latter
3235+
* into the former could be accompanied by a helper call to
3236+
* **bpf_csum_level**\ () with **BPF_CSUM_LEVEL_INC** if the
3237+
* skb is still intended to be processed in higher layers of the
3238+
* stack instead of just egressing at tc.
3239+
*
3240+
* There are three supported level settings at this time:
3241+
*
3242+
* * **BPF_CSUM_LEVEL_INC**: Increases skb->csum_level for skbs
3243+
* with CHECKSUM_UNNECESSARY.
3244+
* * **BPF_CSUM_LEVEL_DEC**: Decreases skb->csum_level for skbs
3245+
* with CHECKSUM_UNNECESSARY.
3246+
* * **BPF_CSUM_LEVEL_RESET**: Resets skb->csum_level to 0 and
3247+
* sets CHECKSUM_NONE to force checksum validation by the stack.
3248+
* * **BPF_CSUM_LEVEL_QUERY**: No-op, returns the current
3249+
* skb->csum_level.
3250+
* Return
3251+
* 0 on success, or a negative error in case of failure. In the
3252+
* case of **BPF_CSUM_LEVEL_QUERY**, the current skb->csum_level
3253+
* is returned or the error code -EACCES in case the skb is not
3254+
* subject to CHECKSUM_UNNECESSARY.
32233255
*/
32243256
#define __BPF_FUNC_MAPPER(FN) \
32253257
FN(unspec), \
@@ -3356,7 +3388,8 @@ union bpf_attr {
33563388
FN(ringbuf_reserve), \
33573389
FN(ringbuf_submit), \
33583390
FN(ringbuf_discard), \
3359-
FN(ringbuf_query),
3391+
FN(ringbuf_query), \
3392+
FN(csum_level),
33603393

33613394
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
33623395
* function eBPF program intends to call
@@ -3433,6 +3466,14 @@ enum {
34333466
BPF_F_CURRENT_NETNS = (-1L),
34343467
};
34353468

3469+
/* BPF_FUNC_csum_level level values. */
3470+
enum {
3471+
BPF_CSUM_LEVEL_QUERY,
3472+
BPF_CSUM_LEVEL_INC,
3473+
BPF_CSUM_LEVEL_DEC,
3474+
BPF_CSUM_LEVEL_RESET,
3475+
};
3476+
34363477
/* BPF_FUNC_skb_adjust_room flags. */
34373478
enum {
34383479
BPF_F_ADJ_ROOM_FIXED_GSO = (1ULL << 0),

0 commit comments

Comments
 (0)