bpf: support for adding DSCP for egress traffic#10881
bpf: support for adding DSCP for egress traffic#10881mazdakn merged 21 commits intoprojectcalico:masterfrom
Conversation
felix/bpf-gpl/qos.h
Outdated
| // The 2 least significant bits are assigned to ECN and must not be touched. | ||
| ip_hdr(ctx)->tos = (__u8) ((ip_hdr(ctx)->tos & 0x03) | (dscp << 2)); | ||
|
|
||
| __wsum ip_csum = bpf_csum_diff(0, 0, (__u32 *)ctx->ip_header, sizeof(struct iphdr), 0); |
There was a problem hiding this comment.
I think you should set csum to 0 if you want to compute the csum of the entire ip header the checksum is computed as the 16-bit ones' complement of the ones' complement sum of all 16-bit words in the header. This includes the Header Checksum field itself, which is set to zero during computation.
tomastigera
left a comment
There was a problem hiding this comment.
nothing fundamental, mostly nits
felix/bpf-gpl/qos.h
Outdated
| if (EGRESS_DSCP < 0) { | ||
| return TC_ACT_UNSPEC; | ||
| } |
There was a problem hiding this comment.
Would it make sense to take it out from this function? Could -1 be technically a valid value? (guess not since all valid values are 6bits only). Perhaps a flag that this field is set?
There was a problem hiding this comment.
Adding a flag to check if this value is set is probably an overkill. we can check EGRESS_DSCP >= 0 in the caller part.
felix/bpf/ut/bpf_prog_test.go
Outdated
|
|
||
| func withEgressDSCP(value int8) testOption { | ||
| return func(o *testOpts) { | ||
| o.dscp = &value |
There was a problem hiding this comment.
if -1 is invalid, you could have used -1 as invalid as well instead of using a pointer
There was a problem hiding this comment.
I added it this way only to consider the default value of type. Since default value of int, 0, is a valid DSCP value.
I managed to find the initialization part, so now type is int.
| return nil, err | ||
| } | ||
|
|
||
| ap.DSCP = -1 |
| } | ||
| } | ||
|
|
||
| ap.DSCP = -1 |
There was a problem hiding this comment.
you set the dscp to -1 but then you deny packets if it is set to -1 🤔
There was a problem hiding this comment.
It wasn't dropping packets, but clearly the return value was confusing. Changed the return val to bool.
felix/bpf-gpl/tc.c
Outdated
| deny_reason(ctx, CALI_REASON_DROPPED_BY_QOS); | ||
| goto deny; | ||
| } | ||
| if (set_dscp(ctx) == TC_ACT_SHOT) { |
There was a problem hiding this comment.
| if (set_dscp(ctx) == TC_ACT_SHOT) { | |
| if ((CALI_F_FROM_WEP || CALI_F_TO_HEP) && EGRESS_DSCP >= 0 && !set_dscp(ctx)) { |
you could make the set_dscp return bool. I'd suggest name it qos_set_dscp will suggest to rename the rate functions to qos_* too
There was a problem hiding this comment.
Pull Request Overview
This PR implements DSCP (Differentiated Services Code Point) support for BPF dataplane in Calico, extending the existing iptables/nftables DSCP functionality to the eBPF implementation. The changes enable setting DSCP values for egress traffic leaving the cluster when using the BPF dataplane.
Key Changes
- Removed BPF dataplane skip conditions from DSCP tests to enable testing with BPF
- Added BPF-specific DSCP implementation in the C code with IPv4/IPv6 support
- Extended BPF program configuration to include DSCP parameters
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| felix/fv/dscp_test.go | Enables DSCP tests for BPF dataplane and conditionally skips iptables-specific verification |
| felix/fv/bpf_test.go | Removes obsolete BPFIPv6Support function that returned false |
| felix/dataplane/linux/bpf_ep_mgr.go | Adds DSCP configuration logic for workload and host endpoints |
| felix/bpf/ut/qos_test.go | Adds comprehensive unit tests for DSCP functionality in both IPv4 and IPv6 |
| felix/bpf/ut/bpf_prog_test.go | Extends test framework with DSCP configuration support |
| felix/bpf/tc/attach.go | Adds DSCP field to AttachPoint struct and configuration |
| felix/bpf/libbpf/libbpf_common.go | Adds DSCP field to TcGlobalData struct |
| felix/bpf/libbpf/libbpf_api.h | Updates C API to include DSCP parameter |
| felix/bpf/libbpf/libbpf.go | Passes DSCP value to C implementation |
| felix/bpf-gpl/tc.c | Integrates DSCP setting into packet processing flow |
| felix/bpf-gpl/qos.h | Implements DSCP setting logic for IPv4 and IPv6 packets |
| felix/bpf-gpl/globals.h | Adds DSCP field to global data structure |
| felix/bpf-gpl/bpf.h | Defines EGRESS_DSCP macro for accessing DSCP configuration |
tomastigera
left a comment
There was a problem hiding this comment.
LGTM ... it would be great in the follow up PR to add a FV test that would set the DSCP. There are tests with external client (mainly for nodeports) and that could verify various scenarios. And we can use tcpdump to verify that the value is set when expected.
|
@tomastigera we have some FV for this: Line 193 in bd40575 But I'm going to add more for a couple of more scenarios. |
Description
Add support for setting DSCP for egress traffic leaving cluster.
This is the follow up on the main PRs:
The follow up PR includes a change to only set DSCP for traffic leaving cluster.
Related issues/PRs
Todos
Release Note
Reminder for the reviewer
Make sure that this PR has the correct labels and milestone set.
Every PR needs one
docs-*label.docs-pr-required: This change requires a change to the documentation that has not been completed yet.docs-completed: This change has all necessary documentation completed.docs-not-required: This change has no user-facing impact and requires no docs.Every PR needs one
release-note-*label.release-note-required: This PR has user-facing changes. Most PRs should have this label.release-note-not-required: This PR has no user-facing changes.Other optional labels:
cherry-pick-candidate: This PR should be cherry-picked to an earlier release. For bug fixes only.needs-operator-pr: This PR is related to install and requires a corresponding change to the operator.