Skip to content

Commit

Permalink
Merge branch 'L4S-style-ce_threshold_ect1-marking'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Oct 15, 2021
2 parents 19757ce + e72aeb9 commit f3fafbc
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 7 deletions.
2 changes: 2 additions & 0 deletions include/net/codel.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,15 @@ 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;
codel_time_t ce_threshold;
codel_time_t interval;
u32 mtu;
bool ecn;
bool ce_threshold_ect1;
};

/**
Expand Down
18 changes: 15 additions & 3 deletions include/net/codel_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
17 changes: 17 additions & 0 deletions include/net/inet_ecn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/pkt_sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ enum {
TCA_FQ_CODEL_CE_THRESHOLD,
TCA_FQ_CODEL_DROP_BATCH_SIZE,
TCA_FQ_CODEL_MEMORY_LIMIT,
TCA_FQ_CODEL_CE_THRESHOLD_ECT1,
__TCA_FQ_CODEL_MAX
};

Expand Down
1 change: 1 addition & 0 deletions net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->cparams.target = MS2TIME(20);
sta->cparams.interval = MS2TIME(100);
sta->cparams.ecn = true;
sta->cparams.ce_threshold_ect1 = false;

sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);

Expand Down
15 changes: 11 additions & 4 deletions net/sched/sch_fq_codel.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
[TCA_FQ_CODEL_CE_THRESHOLD] = { .type = NLA_U32 },
[TCA_FQ_CODEL_DROP_BATCH_SIZE] = { .type = NLA_U32 },
[TCA_FQ_CODEL_MEMORY_LIMIT] = { .type = NLA_U32 },
[TCA_FQ_CODEL_CE_THRESHOLD_ECT1] = { .type = NLA_U8 },
};

static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
Expand Down Expand Up @@ -408,6 +409,9 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
q->cparams.ce_threshold = (val * NSEC_PER_USEC) >> CODEL_SHIFT;
}

if (tb[TCA_FQ_CODEL_CE_THRESHOLD_ECT1])
q->cparams.ce_threshold_ect1 = !!nla_get_u8(tb[TCA_FQ_CODEL_CE_THRESHOLD_ECT1]);

if (tb[TCA_FQ_CODEL_INTERVAL]) {
u64 interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]);

Expand Down Expand Up @@ -544,10 +548,13 @@ static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
q->flows_cnt))
goto nla_put_failure;

if (q->cparams.ce_threshold != CODEL_DISABLED_THRESHOLD &&
nla_put_u32(skb, TCA_FQ_CODEL_CE_THRESHOLD,
codel_time_to_us(q->cparams.ce_threshold)))
goto nla_put_failure;
if (q->cparams.ce_threshold != CODEL_DISABLED_THRESHOLD) {
if (nla_put_u32(skb, TCA_FQ_CODEL_CE_THRESHOLD,
codel_time_to_us(q->cparams.ce_threshold)))
goto nla_put_failure;
if (nla_put_u8(skb, TCA_FQ_CODEL_CE_THRESHOLD_ECT1, q->cparams.ce_threshold_ect1))
goto nla_put_failure;
}

return nla_nest_end(skb, opts);

Expand Down

0 comments on commit f3fafbc

Please sign in to comment.