Skip to content

Commit a1e6ad3

Browse files
vladimirolteandavem330
authored andcommitted
net/sched: taprio: calculate guard band against actual TC gate close time
taprio_dequeue_from_txq() looks at the entry->end_time to determine whether the skb will overrun its traffic class gate, as if at the end of the schedule entry there surely is a "gate close" event for it. Hint: maybe there isn't. For each schedule entry, introduce an array of kernel times which actually tracks when in the future will there be an *actual* gate close event for that traffic class, and use that in the guard band overrun calculation. Signed-off-by: Vladimir Oltean <[email protected]> Reviewed-by: Kurt Kanzenbach <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d2ad689 commit a1e6ad3

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

net/sched/sch_taprio.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ struct sched_entry {
4444
*/
4545
u64 gate_duration[TC_MAX_QUEUE];
4646
atomic_t budget[TC_MAX_QUEUE];
47-
struct list_head list;
48-
49-
/* The instant that this entry ends and the next one
50-
* should open, the qdisc will make some effort so that no
51-
* packet leaves after this time.
47+
/* The qdisc makes some effort so that no packet leaves
48+
* after this time
5249
*/
50+
ktime_t gate_close_time[TC_MAX_QUEUE];
51+
struct list_head list;
52+
/* Used to calculate when to advance the schedule */
5353
ktime_t end_time;
5454
ktime_t next_txtime;
5555
int index;
@@ -148,6 +148,12 @@ static void taprio_calculate_gate_durations(struct taprio_sched *q,
148148
}
149149
}
150150

151+
static bool taprio_entry_allows_tx(ktime_t skb_end_time,
152+
struct sched_entry *entry, int tc)
153+
{
154+
return ktime_before(skb_end_time, entry->gate_close_time[tc]);
155+
}
156+
151157
static ktime_t sched_base_time(const struct sched_gate_list *sched)
152158
{
153159
if (!sched)
@@ -644,7 +650,7 @@ static struct sk_buff *taprio_dequeue_from_txq(struct Qdisc *sch, int txq,
644650
* guard band ...
645651
*/
646652
if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
647-
ktime_after(guard, entry->end_time))
653+
!taprio_entry_allows_tx(guard, entry, tc))
648654
return NULL;
649655

650656
/* ... and no budget. */
@@ -820,10 +826,13 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer)
820826
{
821827
struct taprio_sched *q = container_of(timer, struct taprio_sched,
822828
advance_timer);
829+
struct net_device *dev = qdisc_dev(q->root);
823830
struct sched_gate_list *oper, *admin;
831+
int num_tc = netdev_get_num_tc(dev);
824832
struct sched_entry *entry, *next;
825833
struct Qdisc *sch = q->root;
826834
ktime_t end_time;
835+
int tc;
827836

828837
spin_lock(&q->current_entry_lock);
829838
entry = rcu_dereference_protected(q->current_entry,
@@ -861,6 +870,14 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer)
861870
end_time = ktime_add_ns(entry->end_time, next->interval);
862871
end_time = min_t(ktime_t, end_time, oper->cycle_end_time);
863872

873+
for (tc = 0; tc < num_tc; tc++) {
874+
if (next->gate_duration[tc] == oper->cycle_time)
875+
next->gate_close_time[tc] = KTIME_MAX;
876+
else
877+
next->gate_close_time[tc] = ktime_add_ns(entry->end_time,
878+
next->gate_duration[tc]);
879+
}
880+
864881
if (should_change_schedules(admin, oper, end_time)) {
865882
/* Set things so the next time this runs, the new
866883
* schedule runs.
@@ -1117,8 +1134,11 @@ static int taprio_get_start_time(struct Qdisc *sch,
11171134
static void setup_first_end_time(struct taprio_sched *q,
11181135
struct sched_gate_list *sched, ktime_t base)
11191136
{
1137+
struct net_device *dev = qdisc_dev(q->root);
1138+
int num_tc = netdev_get_num_tc(dev);
11201139
struct sched_entry *first;
11211140
ktime_t cycle;
1141+
int tc;
11221142

11231143
first = list_first_entry(&sched->entries,
11241144
struct sched_entry, list);
@@ -1130,6 +1150,14 @@ static void setup_first_end_time(struct taprio_sched *q,
11301150

11311151
first->end_time = ktime_add_ns(base, first->interval);
11321152
taprio_set_budgets(q, sched, first);
1153+
1154+
for (tc = 0; tc < num_tc; tc++) {
1155+
if (first->gate_duration[tc] == sched->cycle_time)
1156+
first->gate_close_time[tc] = KTIME_MAX;
1157+
else
1158+
first->gate_close_time[tc] = ktime_add_ns(base, first->gate_duration[tc]);
1159+
}
1160+
11331161
rcu_assign_pointer(q->current_entry, NULL);
11341162
}
11351163

0 commit comments

Comments
 (0)