diff options
| author | David S. Miller <davem@davemloft.net> | 2021-10-15 11:33:09 +0100 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2021-10-15 11:33:09 +0100 |
| commit | f3fafbcbe873cb4bf45d62623bf39897ab5f46b4 (patch) | |
| tree | 7cbd2d668e45099e5eb4943bef211c211e8f9749 /include/net | |
| parent | 19757cebf0c5016a1f36f7fe9810a9f0b33c0832 (diff) | |
| parent | e72aeb9ee0e34c57dc90793d0bf82cab9624d64e (diff) | |
Merge branch 'L4S-style-ce_threshold_ect1-marking'
Eric Dumazet says:
====================
net/sched: implement L4S style ce_threshold_ect1 marking
As suggested by Ingemar Johansson, Neal Cardwell, and others, fq_codel can be used
for Low Latency, Low Loss, Scalable Throughput (L4S) with a small change.
In ce_threshold_ect1 mode, only ECT(1) packets can be marked to CE if
their sojourn time is above the threshold.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
| -rw-r--r-- | include/net/codel.h | 2 | ||||
| -rw-r--r-- | include/net/codel_impl.h | 18 | ||||
| -rw-r--r-- | include/net/inet_ecn.h | 17 |
3 files changed, 34 insertions, 3 deletions
diff --git a/include/net/codel.h b/include/net/codel.h index a6e428f80135..5e8b181b76b8 100644 --- a/include/net/codel.h +++ b/include/net/codel.h @@ -102,6 +102,7 @@ static inline u32 codel_time_to_us(codel_time_t val) * @interval: width of moving time window * @mtu: device mtu, or minimal queue backlog in bytes. * @ecn: is Explicit Congestion Notification enabled + * @ce_threshold_ect1: if ce_threshold only marks ECT(1) packets */ struct codel_params { codel_time_t target; @@ -109,6 +110,7 @@ struct codel_params { codel_time_t interval; u32 mtu; bool ecn; + bool ce_threshold_ect1; }; /** diff --git a/include/net/codel_impl.h b/include/net/codel_impl.h index d289b91dcd65..7af2c3eb3c43 100644 --- a/include/net/codel_impl.h +++ b/include/net/codel_impl.h @@ -54,6 +54,7 @@ static void codel_params_init(struct codel_params *params) params->interval = MS2TIME(100); params->target = MS2TIME(5); params->ce_threshold = CODEL_DISABLED_THRESHOLD; + params->ce_threshold_ect1 = false; params->ecn = false; } @@ -246,9 +247,20 @@ static struct sk_buff *codel_dequeue(void *ctx, vars->rec_inv_sqrt); } end: - if (skb && codel_time_after(vars->ldelay, params->ce_threshold) && - INET_ECN_set_ce(skb)) - stats->ce_mark++; + if (skb && codel_time_after(vars->ldelay, params->ce_threshold)) { + bool set_ce = true; + + if (params->ce_threshold_ect1) { + /* Note: if skb_get_dsfield() returns -1, following + * gives INET_ECN_MASK, which is != INET_ECN_ECT_1. + */ + u8 ecn = skb_get_dsfield(skb) & INET_ECN_MASK; + + set_ce = (ecn == INET_ECN_ECT_1); + } + if (set_ce && INET_ECN_set_ce(skb)) + stats->ce_mark++; + } return skb; } diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index ba77f47ef61e..ea32393464a2 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -188,6 +188,23 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb) return 0; } +static inline int skb_get_dsfield(struct sk_buff *skb) +{ + switch (skb_protocol(skb, true)) { + case cpu_to_be16(ETH_P_IP): + if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) + break; + return ipv4_get_dsfield(ip_hdr(skb)); + + case cpu_to_be16(ETH_P_IPV6): + if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) + break; + return ipv6_get_dsfield(ipv6_hdr(skb)); + } + + return -1; +} + static inline int INET_ECN_set_ect1(struct sk_buff *skb) { switch (skb_protocol(skb, true)) { |
