netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Russell Strong <russell@strong.id.au>
To: Stephen Hemminger <stephen@networkplumber.org>
Cc: netdev@vger.kernel.org
Subject: Re: amplifying qdisc
Date: Mon, 20 Jul 2020 11:39:33 +1000	[thread overview]
Message-ID: <20200720113933.15bf482c@strong.id.au> (raw)
In-Reply-To: <20200713095228.5867b7ec@hermes.lan>

On Mon, 13 Jul 2020 09:52:28 -0700
Stephen Hemminger <stephen@networkplumber.org> wrote:

> On Sun, 12 Jul 2020 11:40:01 +1000
> Russell Strong <russell@strong.id.au> wrote:
> 
> > On Wed, 8 Jul 2020 23:26:34 -0700
> > Stephen Hemminger <stephen@networkplumber.org> wrote:
> >   
> > > On Thu, 9 Jul 2020 16:10:34 +1000
> > > Russell Strong <russell@strong.id.au> wrote:
> > >     
> > > > Hi,
> > > > 
> > > > I'm attempting to fill a link with background traffic that is
> > > > sent whenever the link is idle.  To do this I've creates a
> > > > qdisc that will repeat the last packet in the queue for a
> > > > defined number of times (possibly infinite in the future). I am
> > > > able to control the contents of the fill traffic by sending the
> > > > occasional packet through this qdisc.
> > > > 
> > > > This is works as the root qdisc and below a TBF.  When I try it
> > > > as a leaf of HTB unexpected behaviour ensues.  I suspect my
> > > > approach is violating some rules for qdiscs?  Any
> > > > help/ideas/pointers would be appreciated.      
> > > 
> > > Netem can already do things like this. Why not add to that
> > >     
> > 
> > Hi,
> > 
> > Tried doing this within netem as follows; but run into similar
> > problems.  Works as the root qdisc (except for "Route cache is full:
> > consider increasing sysctl net.ipv[4|6].route.max_size.") but not
> > under htb.  I am attempting to duplicate at dequeue, rather than
> > enqueue to get an infinite stream of packets rather than a fixed
> > number of duplicates. Is this possible?
> > 
> > Thanks
> > Russell  
> 
> HTB expects any thing under it to be work conserving.

Thanks for the tip.  I've tried a new approach using tasklets that
appears to be working fine both as the root qdisc and under htb.

Basically, at dequeue, if the qlen drops below 1/2, a tasklet is
scheduled that generates more packets to fill the queue via
dev_queue_xmit.  By generating off the queue length I can avoid the
dropped packets I was getting from pktgen. Sound sane?

Next I would like to add netlink control over the packet size mix and
contents that would be dynamically updated.

This code is big hands, small map stuff to see how it might work.
Does this kind of functionality fit well with netem?

I was always intending to use it in conjunction with other qdiscs and
IPSec to obscure traffic patterns without adding too much latency or
load that might interfere with the real traffic.

diff --git a/sch_netem.c b/sch_netem.c
index 42e557d..a6eef95 100644
--- a/sch_netem.c
+++ b/sch_netem.c
@@ -145,6 +145,9 @@ struct netem_sched_data {
        } slot;
 
        struct disttable *slot_dist;
+
+       u32 fill_imix;
+       struct tasklet_struct tasklet;
 };
 
 /* Time stamp put into socket buffer control block
@@ -673,6 +676,70 @@ static void netem_erase_head(struct netem_sched_data *q, struct sk_buff *skb)
        }
 }
 
+static unsigned char template_packet[] = {
+        0x32, 0xf2, 0xa9, 0x7d, 0xfe, 0xeb,     // dst mac
+        0x06, 0x1d, 0x01, 0x59, 0x3d, 0x20,     // src mac
+
+        0x86, 0xdd,                             // eth type
+
+        0x61, 0x00, 0x00, 0x00,                 // ipv6 version + tclass + flowlabel
+
+        0x00, 0x00,                             // payload length
+
+        0x3b,                                   // next header ( no next header )
+
+        0x01,                                   // hop limit
+
+        0xfe, 0x80, 0x00, 0x00,                 // source
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x01,
+
+        0xfe, 0x80, 0x00, 0x00,                 // destination
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x02,
+
+        0x00, 0x00                              // pad to 8 align
+};
+
+static void generate_packets(unsigned long data)
+{
+        int i;
+        struct sk_buff *skb;
+        struct Qdisc *sch = (struct Qdisc *)data;
+
+        for (i = 0; i < sch->limit - sch->q.qlen; i++) {
+                u16 r, len;
+
+                get_random_bytes(&r, sizeof(r));
+
+                // perturbed IMIX
+                if (r % 12 < 7)
+                        len = 14 + 40 + 30 + (r % 20);
+                else if (r % 12 < 11)
+                        len = 14 + 40 + 526 + (r % 100);
+                else
+                        len = qdisc_dev(sch)->mtu;
+
+                skb = alloc_skb(len + 512, GFP_ATOMIC);
+                if (!skb)
+                        return;
+
+                skb_reserve(skb, 256);
+                skb_reset_mac_header(skb);
+                skb_put(skb, len);
+                template_packet[18] = (len - (14 + 40)) / 256;
+                template_packet[19] = (len - (14 + 40)) % 256;
+                memcpy(skb_mac_header(skb), template_packet, sizeof(template_packet));
+
+                skb->dev = qdisc_dev(sch);
+                skb->priority = 0x10;
+
+                dev_queue_xmit(skb);
+        }
+}
+
 static struct sk_buff *netem_dequeue(struct Qdisc *sch)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
@@ -683,6 +750,8 @@ tfifo_dequeue:
        if (skb) {
                qdisc_qstats_backlog_dec(sch, skb);
 deliver:
+               if (q->fill_imix && sch->q.qlen < sch->limit / 2)
+                       tasklet_schedule(&q->tasklet);
                qdisc_bstats_update(sch, skb);
                return skb;
        }
@@ -1055,6 +1124,10 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt,
        struct netem_sched_data *q = qdisc_priv(sch);
        int ret;
 
+       tasklet_init(&q->tasklet, generate_packets, (unsigned long)sch);
+       tasklet_schedule(&q->tasklet);
+       q->fill_imix = 1;
+
        qdisc_watchdog_init(&q->watchdog, sch);
 
        if (!opt)
@@ -1071,6 +1144,8 @@ static void netem_destroy(struct Qdisc *sch)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
 
+       tasklet_kill(&q->tasklet);
+
        qdisc_watchdog_cancel(&q->watchdog);
        if (q->qdisc)
                qdisc_put(q->qdisc);

      reply	other threads:[~2020-07-20  1:39 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-09  6:10 amplifying qdisc Russell Strong
2020-07-09  6:26 ` Stephen Hemminger
2020-07-12  1:40   ` Russell Strong
2020-07-13 16:52     ` Stephen Hemminger
2020-07-20  1:39       ` Russell Strong [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200720113933.15bf482c@strong.id.au \
    --to=russell@strong.id.au \
    --cc=netdev@vger.kernel.org \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).