Skip to content

Commit fed87cc

Browse files
vladimirolteandavem330
authored andcommitted
net/sched: taprio: automatically calculate queueMaxSDU based on TC gate durations
taprio today has a huge problem with small TC gate durations, because it might accept packets in taprio_enqueue() which will never be sent by taprio_dequeue(). Since not much infrastructure was available, a kludge was added in commit 497cc00 ("taprio: Handle short intervals and large packets"), which segmented large TCP segments, but the fact of the matter is that the issue isn't specific to large TCP segments (and even worse, the performance penalty in segmenting those is absolutely huge). In commit a54fc09 ("net/sched: taprio: allow user input of per-tc max SDU"), taprio gained support for queueMaxSDU, which is precisely the mechanism through which packets should be dropped at qdisc_enqueue() if they cannot be sent. After that patch, it was necessary for the user to manually limit the maximum MTU per TC. This change adds the necessary logic for taprio to further limit the values specified (or not specified) by the user to some minimum values which never allow oversized packets to be sent. Signed-off-by: Vladimir Oltean <[email protected]> Reviewed-by: Kurt Kanzenbach <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a878fd4 commit fed87cc

File tree

1 file changed

+60
-10
lines changed

1 file changed

+60
-10
lines changed

net/sched/sch_taprio.c

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct sched_gate_list {
6464
*/
6565
u64 max_open_gate_duration[TC_MAX_QUEUE];
6666
u32 max_frm_len[TC_MAX_QUEUE]; /* for the fast path */
67+
u32 max_sdu[TC_MAX_QUEUE]; /* for dump */
6768
struct rcu_head rcu;
6869
struct list_head entries;
6970
size_t num_entries;
@@ -94,7 +95,7 @@ struct taprio_sched {
9495
struct hrtimer advance_timer;
9596
struct list_head taprio_list;
9697
int cur_txq[TC_MAX_QUEUE];
97-
u32 max_sdu[TC_MAX_QUEUE]; /* for dump and offloading */
98+
u32 max_sdu[TC_MAX_QUEUE]; /* save info from the user */
9899
u32 txtime_delay;
99100
};
100101

@@ -246,18 +247,52 @@ static int length_to_duration(struct taprio_sched *q, int len)
246247
return div_u64(len * atomic64_read(&q->picos_per_byte), PSEC_PER_NSEC);
247248
}
248249

250+
static int duration_to_length(struct taprio_sched *q, u64 duration)
251+
{
252+
return div_u64(duration * PSEC_PER_NSEC, atomic64_read(&q->picos_per_byte));
253+
}
254+
255+
/* Sets sched->max_sdu[] and sched->max_frm_len[] to the minimum between the
256+
* q->max_sdu[] requested by the user and the max_sdu dynamically determined by
257+
* the maximum open gate durations at the given link speed.
258+
*/
249259
static void taprio_update_queue_max_sdu(struct taprio_sched *q,
250-
struct sched_gate_list *sched)
260+
struct sched_gate_list *sched,
261+
struct qdisc_size_table *stab)
251262
{
252263
struct net_device *dev = qdisc_dev(q->root);
253264
int num_tc = netdev_get_num_tc(dev);
265+
u32 max_sdu_from_user;
266+
u32 max_sdu_dynamic;
267+
u32 max_sdu;
254268
int tc;
255269

256270
for (tc = 0; tc < num_tc; tc++) {
257-
if (q->max_sdu[tc])
258-
sched->max_frm_len[tc] = q->max_sdu[tc] + dev->hard_header_len;
259-
else
271+
max_sdu_from_user = q->max_sdu[tc] ?: U32_MAX;
272+
273+
/* TC gate never closes => keep the queueMaxSDU
274+
* selected by the user
275+
*/
276+
if (sched->max_open_gate_duration[tc] == sched->cycle_time) {
277+
max_sdu_dynamic = U32_MAX;
278+
} else {
279+
u32 max_frm_len;
280+
281+
max_frm_len = duration_to_length(q, sched->max_open_gate_duration[tc]);
282+
if (stab)
283+
max_frm_len -= stab->szopts.overhead;
284+
max_sdu_dynamic = max_frm_len - dev->hard_header_len;
285+
}
286+
287+
max_sdu = min(max_sdu_dynamic, max_sdu_from_user);
288+
289+
if (max_sdu != U32_MAX) {
290+
sched->max_frm_len[tc] = max_sdu + dev->hard_header_len;
291+
sched->max_sdu[tc] = max_sdu;
292+
} else {
260293
sched->max_frm_len[tc] = U32_MAX; /* never oversized */
294+
sched->max_sdu[tc] = 0;
295+
}
261296
}
262297
}
263298

@@ -1243,6 +1278,8 @@ static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
12431278
void *ptr)
12441279
{
12451280
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1281+
struct sched_gate_list *oper, *admin;
1282+
struct qdisc_size_table *stab;
12461283
struct taprio_sched *q;
12471284

12481285
ASSERT_RTNL();
@@ -1255,6 +1292,17 @@ static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
12551292
continue;
12561293

12571294
taprio_set_picos_per_byte(dev, q);
1295+
1296+
stab = rtnl_dereference(q->root->stab);
1297+
1298+
oper = rtnl_dereference(q->oper_sched);
1299+
if (oper)
1300+
taprio_update_queue_max_sdu(q, oper, stab);
1301+
1302+
admin = rtnl_dereference(q->admin_sched);
1303+
if (admin)
1304+
taprio_update_queue_max_sdu(q, admin, stab);
1305+
12581306
break;
12591307
}
12601308

@@ -1654,7 +1702,8 @@ static int taprio_parse_tc_entries(struct Qdisc *sch,
16541702
if (nla_type(n) != TCA_TAPRIO_ATTR_TC_ENTRY)
16551703
continue;
16561704

1657-
err = taprio_parse_tc_entry(sch, n, max_sdu, &seen_tcs, extack);
1705+
err = taprio_parse_tc_entry(sch, n, max_sdu, &seen_tcs,
1706+
extack);
16581707
if (err)
16591708
goto out;
16601709
}
@@ -1784,7 +1833,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
17841833
goto free_sched;
17851834

17861835
taprio_set_picos_per_byte(dev, q);
1787-
taprio_update_queue_max_sdu(q, new_admin);
1836+
taprio_update_queue_max_sdu(q, new_admin, stab);
17881837

17891838
if (mqprio) {
17901839
err = netdev_set_num_tc(dev, mqprio->num_tc);
@@ -2142,7 +2191,8 @@ static int dump_schedule(struct sk_buff *msg,
21422191
return -1;
21432192
}
21442193

2145-
static int taprio_dump_tc_entries(struct taprio_sched *q, struct sk_buff *skb)
2194+
static int taprio_dump_tc_entries(struct sk_buff *skb,
2195+
struct sched_gate_list *sched)
21462196
{
21472197
struct nlattr *n;
21482198
int tc;
@@ -2156,7 +2206,7 @@ static int taprio_dump_tc_entries(struct taprio_sched *q, struct sk_buff *skb)
21562206
goto nla_put_failure;
21572207

21582208
if (nla_put_u32(skb, TCA_TAPRIO_TC_ENTRY_MAX_SDU,
2159-
q->max_sdu[tc]))
2209+
sched->max_sdu[tc]))
21602210
goto nla_put_failure;
21612211

21622212
nla_nest_end(skb, n);
@@ -2200,7 +2250,7 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
22002250
nla_put_u32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, q->txtime_delay))
22012251
goto options_error;
22022252

2203-
if (taprio_dump_tc_entries(q, skb))
2253+
if (oper && taprio_dump_tc_entries(skb, oper))
22042254
goto options_error;
22052255

22062256
if (oper && dump_schedule(skb, oper))

0 commit comments

Comments
 (0)