From patchwork Wed Nov 8 23:12:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Taht X-Patchwork-Id: 836051 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="oeh6l5sd"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yXMYB6Wkmz9rvt for ; Thu, 9 Nov 2017 10:13:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752949AbdKHXNd (ORCPT ); Wed, 8 Nov 2017 18:13:33 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:51600 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752534AbdKHXNa (ORCPT ); Wed, 8 Nov 2017 18:13:30 -0500 Received: by mail-pf0-f194.google.com with SMTP id j28so522527pfk.8 for ; Wed, 08 Nov 2017 15:13:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nzgNUIFXowEt1ZgwAMDTdQdt8TmCTDzEa9S1w48jucA=; b=oeh6l5sdraHouHnVROFOyoPW9YzKDDSvrl7tqWhWbTQITd0BLnhjWxbIJyd46CZmGg onioQnWfguBhaDpanEvT4VCtk6r2FOrKw7WduW/mHJUeUOygZMNx5vxxSFenul1WfZ4c hxLv2p+zCYy0zT1k7nUG+g2kfzpnA//61eRG0oxdau/bqXkft7O2k/PvPjyQyWJ06ZFb nrmNSd9QfZabduOD6aL4cXmYfWsOPG8R2g5lSi6DfSMjPJ0MOuTphW01X8/cRSwsy3R8 9flau/A24dJ/FqAov5inLG5Pepw5aQhycoHPOpyXRtQXJ7DP7yVKezdVR4qOr+JoGeXK pERw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nzgNUIFXowEt1ZgwAMDTdQdt8TmCTDzEa9S1w48jucA=; b=bpHrJ6De/VuEZuH9HUmhFPOBmV1eiOdp3I1Y2I6myx81WXX8mKx+sEDeLvBWo4A0I0 vRRMZwDHuqM5O+tWV+Cindb6UW57OxtinqJyfbahiNwRgmM+xLjmBNk6OMWhXS9oh+QV zgMV4ozZ3SOPevh0TNmL/u/aL7A63VXmCw4JCKoD2o4pgaGUTFJ6igwBe1MuHzVqnYHV sU7ppfeHyoxMYCprHK5Dtpgvth6hTr67RSaVC/Rvp/XK+pLTqayzvq+ImUdMjbxJAaDX EmvDkxpaQMVSLJWHiTmRW5kht8I4W+0FA3RJrcm5p922FuY2WZ9bpjfVVffiPYBb82Vc 5y2g== X-Gm-Message-State: AJaThX6SuckZ/0kiRuSlPkN0jYJClvze958XCi/+3JLbH1JGgC13hmjF nEo5B/TYXxef77AUBR8I70NcoQ== X-Google-Smtp-Source: ABhQp+S2YKd43jdCKERCYZY3W/H1N1u8Lu9tfmP5nFWKnvGakPq2DB78gCXpG9Auk8NhpVfBM+qOOw== X-Received: by 10.101.75.141 with SMTP id t13mr1943833pgq.122.1510182809696; Wed, 08 Nov 2017 15:13:29 -0800 (PST) Received: from nemesis.lab.teklibre.com ([2603:3024:1536:86f0:2e0:4cff:fec1:1206]) by smtp.gmail.com with ESMTPSA id a7sm8573314pgc.81.2017.11.08.15.13.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 08 Nov 2017 15:13:28 -0800 (PST) From: Dave Taht To: netdev@vger.kernel.org Cc: stephen@networkplumber.org, edumazet@google.com, Dave Taht Subject: [PATCH v3 net-next 1/3] netem: convert to qdisc_watchdog_schedule_ns Date: Wed, 8 Nov 2017 15:12:26 -0800 Message-Id: <1510182748-10991-2-git-send-email-dave.taht@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1510182748-10991-1-git-send-email-dave.taht@gmail.com> References: <1510182748-10991-1-git-send-email-dave.taht@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Upgrade the internal netem scheduler to use nanoseconds rather than ticks throughout. Convert to and from the std "ticks" userspace api automatically, while allowing for finer grained scheduling to take place. Signed-off-by: Dave Taht --- net/sched/sch_netem.c | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index db0228a..e64e0e0 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -77,8 +77,8 @@ struct netem_sched_data { struct qdisc_watchdog watchdog; - psched_tdiff_t latency; - psched_tdiff_t jitter; + s64 latency; + s64 jitter; u32 loss; u32 ecn; @@ -145,7 +145,7 @@ struct netem_sched_data { * we save skb->tstamp value in skb->cb[] before destroying it. */ struct netem_skb_cb { - psched_time_t time_to_send; + u64 time_to_send; }; static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb) @@ -305,11 +305,11 @@ static bool loss_event(struct netem_sched_data *q) * std deviation sigma. Uses table lookup to approximate the desired * distribution, and a uniformly-distributed pseudo-random source. */ -static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma, - struct crndstate *state, - const struct disttable *dist) +static s64 tabledist(s64 mu, s64 sigma, + struct crndstate *state, + const struct disttable *dist) { - psched_tdiff_t x; + s64 x; long t; u32 rnd; @@ -332,10 +332,10 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma, return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu; } -static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q) +static u64 packet_len_2_sched_time(unsigned int len, + struct netem_sched_data *q) { - u64 ticks; - + u64 offset; len += q->packet_overhead; if (q->cell_size) { @@ -345,11 +345,9 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche cells++; len = cells * (q->cell_size + q->cell_overhead); } - - ticks = (u64)len * NSEC_PER_SEC; - - do_div(ticks, q->rate); - return PSCHED_NS2TICKS(ticks); + offset = (u64)len * NSEC_PER_SEC; + do_div(offset, q->rate); + return offset; } static void tfifo_reset(struct Qdisc *sch) @@ -369,7 +367,7 @@ static void tfifo_reset(struct Qdisc *sch) static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); - psched_time_t tnext = netem_skb_cb(nskb)->time_to_send; + u64 tnext = netem_skb_cb(nskb)->time_to_send; struct rb_node **p = &q->t_root.rb_node, *parent = NULL; while (*p) { @@ -515,13 +513,13 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, if (q->gap == 0 || /* not doing reordering */ q->counter < q->gap - 1 || /* inside last reordering gap */ q->reorder < get_crandom(&q->reorder_cor)) { - psched_time_t now; - psched_tdiff_t delay; + u64 now; + s64 delay; delay = tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist); - now = psched_get_time(); + now = ktime_get_ns(); if (q->rate) { struct netem_skb_cb *last = NULL; @@ -547,7 +545,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, * from delay. */ delay -= last->time_to_send - now; - delay = max_t(psched_tdiff_t, 0, delay); + delay = max_t(s64, 0, delay); now = last->time_to_send; } @@ -562,7 +560,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, * Do re-ordering by putting one out of N packets at the front * of the queue. */ - cb->time_to_send = psched_get_time(); + cb->time_to_send = ktime_get_ns(); q->counter = 0; netem_enqueue_skb_head(&sch->q, skb); @@ -609,13 +607,13 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) } p = rb_first(&q->t_root); if (p) { - psched_time_t time_to_send; + u64 time_to_send; skb = rb_to_skb(p); /* if more time remaining? */ time_to_send = netem_skb_cb(skb)->time_to_send; - if (time_to_send <= psched_get_time()) { + if (time_to_send <= ktime_get_ns()) { rb_erase(p, &q->t_root); sch->q.qlen--; @@ -659,7 +657,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) if (skb) goto deliver; } - qdisc_watchdog_schedule(&q->watchdog, time_to_send); + qdisc_watchdog_schedule_ns(&q->watchdog, time_to_send); } if (q->qdisc) { @@ -888,8 +886,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) sch->limit = qopt->limit; - q->latency = qopt->latency; - q->jitter = qopt->jitter; + q->latency = PSCHED_TICKS2NS(qopt->latency); + q->jitter = PSCHED_TICKS2NS(qopt->jitter); q->limit = qopt->limit; q->gap = qopt->gap; q->counter = 0; @@ -1011,8 +1009,10 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) struct tc_netem_corrupt corrupt; struct tc_netem_rate rate; - qopt.latency = q->latency; - qopt.jitter = q->jitter; + qopt.latency = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->latency), + UINT_MAX); + qopt.jitter = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->jitter), + UINT_MAX); qopt.limit = q->limit; qopt.loss = q->loss; qopt.gap = q->gap; From patchwork Wed Nov 8 23:12:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Taht X-Patchwork-Id: 836053 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mGDuVWkZ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yXMYP1FPwz9rvt for ; Thu, 9 Nov 2017 10:13:45 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753045AbdKHXNn (ORCPT ); Wed, 8 Nov 2017 18:13:43 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:48956 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752882AbdKHXNb (ORCPT ); Wed, 8 Nov 2017 18:13:31 -0500 Received: by mail-pf0-f194.google.com with SMTP id b79so2856634pfk.5 for ; Wed, 08 Nov 2017 15:13:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DdZyQy+f4/oenPqiYaD7OAF+l1bJpzg3lPHwvFGzuC0=; b=mGDuVWkZnkRnDNJhDC4BVuSEaWoSTjCegrBUlpENMpDw2xBpIek2ys4R2KPP8My2pu NzQE91tpI9qezdQ+7U7RjOWELJ/ev8DFLO5F++/LJOsm7xvvllqe7i866vnrbES+ZK+z 0nT6bZMRUlH4rVJ9dg0V2H/dEcitcdbaYIK0Ayef0S1OJqo8GIQ7M/eT+3bncUvFyagn ISAolYDcGJGXfGhB0fL7qZblTIoX9VIEyNghPJ1F14E+Lpp4Y0prQG5tV37KdW99XvAE +bgUxaWVbsGFL9ty9ajcvOg7OxemWdWAZ8h0BhpgYWao//f6PjE3JTfkO1xdCZaEUtg8 dgiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DdZyQy+f4/oenPqiYaD7OAF+l1bJpzg3lPHwvFGzuC0=; b=EcA2JdoWBFKFleIGG/kextx4y+uzDXjfRzoaQVeDlB9b/VCRlanzhJtyubRxlNgiGy ARLjSwbJ2TYGQ3jII3m7SpBgAngz1r6JCV4Sf4Pt1pmWjvbTkttT/Zx5DrGqR5wKS+m2 cp8kfZz77ql42bHk0MlKNg2hu7xZRBWu6NtqMwjNvozLaQ4EoMxksVyigQXpX9Y/swTa sXtG6kKaBuN9APTbDd/Luwex4ggKPIqgDP80ruzizOw0DO9gLRf6THgzD8nDUXJ2ysK0 LCceLDsplVHJ3e/NXGJ7v1RZ+K7hr8FRbHfRbOlYpryRnvVilOqonX2csiE1u10hF72P uqnw== X-Gm-Message-State: AJaThX4r3TS1WJUotvEJIMa72f5v59yrA29FjYBsLokBSdBa3lg4Ksup Iasu4MnJiagNcFXs2udKX05kpQ== X-Google-Smtp-Source: ABhQp+Ql43AKv+H0rKXfN3PeKbJC9KCw+HCDncweXEo47ONKVihJ0/F6zwxKYUPtblUBz8rNGMv0ww== X-Received: by 10.99.49.81 with SMTP id x78mr203101pgx.35.1510182810859; Wed, 08 Nov 2017 15:13:30 -0800 (PST) Received: from nemesis.lab.teklibre.com ([2603:3024:1536:86f0:2e0:4cff:fec1:1206]) by smtp.gmail.com with ESMTPSA id a7sm8573314pgc.81.2017.11.08.15.13.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 08 Nov 2017 15:13:30 -0800 (PST) From: Dave Taht To: netdev@vger.kernel.org Cc: stephen@networkplumber.org, edumazet@google.com, Dave Taht Subject: [PATCH v3 net-next 2/3] netem: add uapi to express delay and jitter in nanoseconds Date: Wed, 8 Nov 2017 15:12:27 -0800 Message-Id: <1510182748-10991-3-git-send-email-dave.taht@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1510182748-10991-1-git-send-email-dave.taht@gmail.com> References: <1510182748-10991-1-git-send-email-dave.taht@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org netem userspace has long relied on a horrible /proc/net/psched hack to translate the current notion of "ticks" to nanoseconds. Expressing latency and jitter instead, in well defined nanoseconds, increases the dynamic range of emulated delays and jitter in netem. It will also ease a transition where reducing a tick to nsec equivalence would constrain the max delay in prior versions of netem to only 4.3 seconds. Signed-off-by: Dave Taht Suggested-by: Eric Dumazet Reviewed-by: Eric Dumazet --- include/uapi/linux/pkt_sched.h | 2 ++ net/sched/sch_netem.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h index 6a2c5ea..8fe6d18 100644 --- a/include/uapi/linux/pkt_sched.h +++ b/include/uapi/linux/pkt_sched.h @@ -537,6 +537,8 @@ enum { TCA_NETEM_ECN, TCA_NETEM_RATE64, TCA_NETEM_PAD, + TCA_NETEM_LATENCY64, + TCA_NETEM_JITTER64, __TCA_NETEM_MAX, }; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index e64e0e0..47d6dec 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -819,6 +819,8 @@ static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = { [TCA_NETEM_LOSS] = { .type = NLA_NESTED }, [TCA_NETEM_ECN] = { .type = NLA_U32 }, [TCA_NETEM_RATE64] = { .type = NLA_U64 }, + [TCA_NETEM_LATENCY64] = { .type = NLA_S64 }, + [TCA_NETEM_JITTER64] = { .type = NLA_S64 }, }; static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, @@ -916,6 +918,12 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) q->rate = max_t(u64, q->rate, nla_get_u64(tb[TCA_NETEM_RATE64])); + if (tb[TCA_NETEM_LATENCY64]) + q->latency = nla_get_s64(tb[TCA_NETEM_LATENCY64]); + + if (tb[TCA_NETEM_JITTER64]) + q->jitter = nla_get_s64(tb[TCA_NETEM_JITTER64]); + if (tb[TCA_NETEM_ECN]) q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); @@ -1020,6 +1028,12 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt)) goto nla_put_failure; + if (nla_put(skb, TCA_NETEM_LATENCY64, sizeof(q->latency), &q->latency)) + goto nla_put_failure; + + if (nla_put(skb, TCA_NETEM_JITTER64, sizeof(q->jitter), &q->jitter)) + goto nla_put_failure; + cor.delay_corr = q->delay_cor.rho; cor.loss_corr = q->loss_cor.rho; cor.dup_corr = q->dup_cor.rho; From patchwork Wed Nov 8 23:12:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Taht X-Patchwork-Id: 836052 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tIKtX+xn"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yXMYF5ybbz9rvt for ; Thu, 9 Nov 2017 10:13:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752996AbdKHXNg (ORCPT ); Wed, 8 Nov 2017 18:13:36 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:54354 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752891AbdKHXNc (ORCPT ); Wed, 8 Nov 2017 18:13:32 -0500 Received: by mail-pf0-f194.google.com with SMTP id n89so2845622pfk.11 for ; Wed, 08 Nov 2017 15:13:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=x/s9uvryH1iAB/a2g2KBK7lS/x4jynZVASNoc0NHWUM=; b=tIKtX+xnc5LDlLt23kcLY4QK6x//CFOWBfdtSxIH/AgGXZo7/EO1KI7/hDamWHeKiI Ti6E4jzioBaiMyrc7QkLGy/U7dDSp0Xe++wCrO3gIIF9olxJeqWBNDUVaD9pZ4yTvmGO uAm3Ly6Rf6rSPxuqGC+AqpGCCe24nzSxEEhvLyJQJaNuzKQFUTKtz4SiNoIBt43mdOFs vi8Mwk89969rRoN6d2C/GlXwYfDX0XRYbsPqjwz/scL+mjQZTGBo9r+/hmldNT6ZffMM qZHcDU0PvuYKKb7UhQmQ+DWwfNh2Si1pVXfSv2wqEY0YB/I7awfz//eYu7c28r/S0EXI WJHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=x/s9uvryH1iAB/a2g2KBK7lS/x4jynZVASNoc0NHWUM=; b=nMYblSEvfYHwokgSF7/OrgLen5Kw/mWEK7Ol1hPCbEA4KPXEXYcp8Ed2MkqD+I9SoY 2g7OpV26U9hwX74Db72j1l/eMdkwX4aob7AgWkeByDo3yln/vGpV6h25KbI2M2H3Voyh KbwSfuzt1NVXRk0T4sqEW5CDqa2low5/CHr1sYEDJycHHoq1jQgh+XdxuthaeTYip3Wi iNy5t3Sm7DqTAkpsgG2l28Ss/12AMih1FBHmJ7XodWDeFxQAZqZ2C5Hfl0tM1lvGKzmg pYiX/4Cwsd474yDF9AIb8E80xttbjOKwOtee7Dn+gfrv8oeey1kg9+HjDo4sWZqsCb5s vwMQ== X-Gm-Message-State: AJaThX4qrBukBp+y59vFiscxAVHPBT6ilDWOV5lVhCGrmo44xKEP5Td8 Uz8woVyGNM7wuthUBHhaYtonvw== X-Google-Smtp-Source: ABhQp+SZspa7eaK6c7SnwFJzCk5308tP2v+9NAVVMMTd4sHn8bdlyZ6JkWv95euLBUDY63sEmr8OLQ== X-Received: by 10.84.233.67 with SMTP id k3mr1807863plt.97.1510182811907; Wed, 08 Nov 2017 15:13:31 -0800 (PST) Received: from nemesis.lab.teklibre.com ([2603:3024:1536:86f0:2e0:4cff:fec1:1206]) by smtp.gmail.com with ESMTPSA id a7sm8573314pgc.81.2017.11.08.15.13.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 08 Nov 2017 15:13:31 -0800 (PST) From: Dave Taht To: netdev@vger.kernel.org Cc: stephen@networkplumber.org, edumazet@google.com, Dave Taht Subject: [PATCH v3 net-next 3/3] netem: support delivering packets in delayed time slots Date: Wed, 8 Nov 2017 15:12:28 -0800 Message-Id: <1510182748-10991-4-git-send-email-dave.taht@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1510182748-10991-1-git-send-email-dave.taht@gmail.com> References: <1510182748-10991-1-git-send-email-dave.taht@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Slotting is a crude approximation of the behaviors of shared media such as cable, wifi, and LTE, which gather up a bunch of packets within a varying delay window and deliver them, relative to that, nearly all at once. It works within the existing loss, duplication, jitter and delay parameters of netem. Some amount of inherent latency must be specified, regardless. The new "slot" parameter specifies a minimum and maximum delay between transmission attempts. The "bytes" and "packets" parameters can be used to limit the amount of information transferred per slot. Examples of use: tc qdisc add dev eth0 root netem delay 200us \ slot 800us 10ms bytes 64k packets 42 A more correct example, using stacked netem instances and a packet limit to emulate a tail drop wifi queue with slots and variable packet delivery, with a 200Mbit isochronous underlying rate, and 20ms path delay: tc qdisc add dev eth0 root handle 1: netem delay 20ms rate 200mbit \ limit 10000 tc qdisc add dev eth0 parent 1:1 handle 10:1 netem delay 200us \ slot 800us 10ms bytes 64k packets 42 limit 512 Signed-off-by: Dave Taht --- include/uapi/linux/pkt_sched.h | 8 +++++ net/sched/sch_netem.c | 74 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h index 8fe6d18..af3cc2f 100644 --- a/include/uapi/linux/pkt_sched.h +++ b/include/uapi/linux/pkt_sched.h @@ -539,6 +539,7 @@ enum { TCA_NETEM_PAD, TCA_NETEM_LATENCY64, TCA_NETEM_JITTER64, + TCA_NETEM_SLOT, __TCA_NETEM_MAX, }; @@ -576,6 +577,13 @@ struct tc_netem_rate { __s32 cell_overhead; }; +struct tc_netem_slot { + __s64 min_delay; /* nsec */ + __s64 max_delay; + __s32 max_packets; + __s32 max_bytes; +}; + enum { NETEM_LOSS_UNSPEC, NETEM_LOSS_GI, /* General Intuitive - 4 state model */ diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 47d6dec..b686e75 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -135,6 +135,13 @@ struct netem_sched_data { u32 a5; /* p23 used only in 4-states */ } clg; + struct tc_netem_slot slot_config; + struct slotstate { + u64 slot_next; + s32 packets_left; + s32 bytes_left; + } slot; + }; /* Time stamp put into socket buffer control block @@ -591,6 +598,20 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, return NET_XMIT_SUCCESS; } +/* Delay the next round with a new future slot with a + * correct number of bytes and packets. + */ + +static void get_slot_next(struct netem_sched_data *q, u64 now) +{ + q->slot.slot_next = now + q->slot_config.min_delay + + (prandom_u32() * + (q->slot_config.max_delay - + q->slot_config.min_delay) >> 32); + q->slot.packets_left = q->slot_config.max_packets; + q->slot.bytes_left = q->slot_config.max_bytes; +} + static struct sk_buff *netem_dequeue(struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); @@ -608,14 +629,17 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) p = rb_first(&q->t_root); if (p) { u64 time_to_send; + u64 now = ktime_get_ns(); skb = rb_to_skb(p); /* if more time remaining? */ time_to_send = netem_skb_cb(skb)->time_to_send; - if (time_to_send <= ktime_get_ns()) { - rb_erase(p, &q->t_root); + if (q->slot.slot_next && q->slot.slot_next < time_to_send) + get_slot_next(q, now); + if (time_to_send <= now && q->slot.slot_next <= now) { + rb_erase(p, &q->t_root); sch->q.qlen--; qdisc_qstats_backlog_dec(sch, skb); skb->next = NULL; @@ -634,6 +658,14 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) skb->tstamp = 0; #endif + if (q->slot.slot_next) { + q->slot.packets_left--; + q->slot.bytes_left -= qdisc_pkt_len(skb); + if (q->slot.packets_left <= 0 || + q->slot.bytes_left <= 0) + get_slot_next(q, now); + } + if (q->qdisc) { unsigned int pkt_len = qdisc_pkt_len(skb); struct sk_buff *to_free = NULL; @@ -657,7 +689,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) if (skb) goto deliver; } - qdisc_watchdog_schedule_ns(&q->watchdog, time_to_send); + + qdisc_watchdog_schedule_ns(&q->watchdog, + max(time_to_send, + q->slot.slot_next)); } if (q->qdisc) { @@ -688,6 +723,7 @@ static void dist_free(struct disttable *d) * Distribution data is a variable size payload containing * signed 16 bit values. */ + static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) { struct netem_sched_data *q = qdisc_priv(sch); @@ -718,6 +754,23 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) return 0; } +static void get_slot(struct netem_sched_data *q, const struct nlattr *attr) +{ + const struct tc_netem_slot *c = nla_data(attr); + + q->slot_config = *c; + if (q->slot_config.max_packets == 0) + q->slot_config.max_packets = INT_MAX; + if (q->slot_config.max_bytes == 0) + q->slot_config.max_bytes = INT_MAX; + q->slot.packets_left = q->slot_config.max_packets; + q->slot.bytes_left = q->slot_config.max_bytes; + if (q->slot_config.min_delay | q->slot_config.max_delay) + q->slot.slot_next = ktime_get_ns(); + else + q->slot.slot_next = 0; +} + static void get_correlation(struct netem_sched_data *q, const struct nlattr *attr) { const struct tc_netem_corr *c = nla_data(attr); @@ -821,6 +874,7 @@ static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = { [TCA_NETEM_RATE64] = { .type = NLA_U64 }, [TCA_NETEM_LATENCY64] = { .type = NLA_S64 }, [TCA_NETEM_JITTER64] = { .type = NLA_S64 }, + [TCA_NETEM_SLOT] = { .len = sizeof(struct tc_netem_slot) }, }; static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, @@ -927,6 +981,9 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) if (tb[TCA_NETEM_ECN]) q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); + if (tb[TCA_NETEM_SLOT]) + get_slot(q, tb[TCA_NETEM_SLOT]); + return ret; } @@ -1016,6 +1073,7 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) struct tc_netem_reorder reorder; struct tc_netem_corrupt corrupt; struct tc_netem_rate rate; + struct tc_netem_slot slot; qopt.latency = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->latency), UINT_MAX); @@ -1070,6 +1128,16 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) if (dump_loss_model(q, skb) != 0) goto nla_put_failure; + if (q->slot_config.min_delay | q->slot_config.max_delay) { + slot = q->slot_config; + if (slot.max_packets == INT_MAX) + slot.max_packets = 0; + if (slot.max_bytes == INT_MAX) + slot.max_bytes = 0; + if (nla_put(skb, TCA_NETEM_SLOT, sizeof(slot), &slot)) + goto nla_put_failure; + } + return nla_nest_end(skb, nla); nla_put_failure: