Development discussion of WireGuard
 help / color / mirror / Atom feed
From: "Toke Høiland-Jørgensen" <toke@toke.dk>
To: Daniel Golle <daniel@makrotopia.org>,
	Florent Daigniere <nextgens@freenetproject.org>
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>,
	WireGuard mailing list <wireguard@lists.zx2c4.com>
Subject: Re: passing-through TOS/DSCP marking
Date: Fri, 18 Jun 2021 01:04:55 +0200	[thread overview]
Message-ID: <877disdre0.fsf@toke.dk> (raw)
In-Reply-To: <87sg1gptky.fsf@toke.dk>

Toke Høiland-Jørgensen <toke@toke.dk> writes:

> Daniel Golle <daniel@makrotopia.org> writes:
>
>> Hi Florent,
>>
>> On Thu, Jun 17, 2021 at 07:55:09AM +0000, Florent Daigniere wrote:
>>> On Thu, 2021-06-17 at 01:33 +0200, Toke Høiland-Jørgensen wrote:
>>> > Daniel Golle <daniel@makrotopia.org> writes:
>>> > 
>>> > > Hi Jason,
>>> > > 
>>> > > On Wed, Jun 16, 2021 at 06:28:12PM +0200, Jason A. Donenfeld wrote:
>>> > > > WireGuard does not copy the inner DSCP mark to the outside, aside
>>> > > > from
>>> > > > the ECN bits, in order to avoid a data leak.
>>> > > 
>>> > > That's a very valid argument.
>>> > > 
>>> > > However, from my experience now, Wireguard is not suitable for
>>> > > VoIP/RTP
>>> > > data (minimize-delay) being sent through the same tunnel as TCP bulk
>>> > > (maximize-throughput) traffic in bandwidth constraint and/or high-
>>> > > latency
>>> > > environments, as that ruins the VoIP calls to the degree of not
>>> > > being
>>> > > understandable. ECN helps quite a bit when it comes to avoid packet
>>> > > drops
>>> > > for TCP traffic, but that's not enough to avoid high jitter and
>>> > > drops for
>>> > > RTP/UDP traffic at the same time.
>>> > > 
>>> > > I thought about ways to improve that and wonder what you would
>>> > > suggest.
>>> > > My ideas are:
>>> > >  * have different tunnels depending on inner DSCP bits and mark them
>>> > >    accordingly on the outside.
>>> > >    => we already got multiple tunnels and that would double the
>>> > > number.
>>> > > 
>>> > >  * mark outer packets with DSCP bits based on their size.
>>> > >    VoIP RTP/UDP packets are typically "medium sized" while TCP
>>> > > packets
>>> > >    typically max out the MTU.
>>> > >    => we would not leak information, but that assumption may not
>>> > > always
>>> > >       be true
>>> > > 
>>> > >  * patch wireguard kernel code to allow preserving inner DSCP bits.
>>> > >    => even only having 2 differentl classes of traffic (critical vs.
>>> > >       bulk) would already help a lot...
>>> > > 
>>> > > 
>>> > > What do you think? Any other ideas?
>>> > 
>>> > Can you share a few more details about the network setup? I.e., where
>>> > is
>>> > the bottleneck link that requires this special treatment?
>>> 
>>> I can tell you about mine. WiFi in a congested environment: "voip on
>>> mobile phones". WMM/802.11e uses the diffserv markings; most commercial
>>> APs will do the right thing provided packets are marked appropriately.
>>> 
>>> At the time I have sent patches (back in 2019) for both the golang and
>>> linux implementation that turned it on by default. I believe that
>>> Russell Strong further improved upon them by adding a knob (20190318 on
>>> this mailing list).
>>
>> Thank you very much for the hint!
>> This patch is exactly what I was looking for:
>> https://lists.zx2c4.com/pipermail/wireguard/2019-March/004026.html
>>
>> Unfortunately it has not received a great amount of feedback back then.
>> I'll try forward-porting and deploying it now, because to me it looks
>> like the best solution money can buy :)
>
> I think you can achieve something similar using BPF filters, by relying
> on wireguard passing through the skb->hash value when encrypting.
>
> Simply attach a TC-BPF filter to the wireguard netdev, pull out the DSCP
> value and store it in a map keyed on skb->hash. Then, run a second BPF
> filter on the physical interface that shares that same map, lookup the
> DSCP value based on the skb->hash value, and rewrite the outer IP
> header.
>
> The read-side filter will need to use bpf_get_hash_recalc() to make sure
> the hash is calculated before the packet gets handed to wireguard, and
> it'll be subject to hash collisions, but I think it should generally
> work fairly well (for anything that's flow-based of course). And it can
> be done without patching wireguard itself :)

Just for fun I implemented such a pair of eBPF filters, and tested that
it does indeed work for preserving DSCP marks on a Wireguard tunnel. The
PoC is here:

https://github.com/xdp-project/bpf-examples/tree/master/preserve-dscp

To try it out (you'll need a recent-ish kernel and clang version) run:

git clone --recurse-submodules https://github.com/xdp-project/bpf-examples
cd bpf-examples/preserve-dscp
make
./preserve-dscp wg0 eth0

(assuming wg0 and eth0 are the wireguard and physical interfaces in
question, respectively).

To actually deploy this it would probably need a few tweaks; in
particular the second filter that rewrites packets should probably check
that the packets are actually part of the Wireguard tunnel in question
(by parsing the UDP header and checking the source port) before writing
anything to the packet.

-Toke

  parent reply	other threads:[~2021-06-17 23:05 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-16 13:24 Daniel Golle
2021-06-16 16:28 ` Jason A. Donenfeld
2021-06-16 19:26   ` Daniel Golle
2021-06-16 23:33     ` Toke Høiland-Jørgensen
2021-06-17  7:55       ` Florent Daigniere
2021-06-17  9:41         ` Daniel Golle
2021-06-17 12:24           ` Toke Høiland-Jørgensen
     [not found]             ` <CAMaqUZ09KRtp01OK3u-Di52X_kH9eT4E-wmnPc6QzjSCd5dEiw@mail.gmail.com>
2021-06-17 20:54               ` Toke Høiland-Jørgensen
2021-06-17 23:04             ` Toke Høiland-Jørgensen [this message]
2021-06-18 12:24               ` Jason A. Donenfeld
2021-06-21 12:36                 ` Daniel Golle
2021-06-21 14:27                   ` Toke Høiland-Jørgensen
2021-06-30 17:23                     ` Daniel Golle
2021-06-30 20:55                       ` Toke Høiland-Jørgensen
2021-07-04 14:15                         ` Daniel Golle
2021-07-05 15:21                           ` Toke Høiland-Jørgensen
2021-07-05 16:05                             ` Daniel Golle
2021-07-05 16:59                               ` Toke Høiland-Jørgensen
2021-07-05 17:26                                 ` Daniel Golle
2021-07-05 21:20                                   ` Toke Høiland-Jørgensen
2021-07-06  7:00   ` Florent Daigniere
2021-07-06 20:08     ` Luiz Angelo Daros de Luca

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=877disdre0.fsf@toke.dk \
    --to=toke@toke.dk \
    --cc=Jason@zx2c4.com \
    --cc=daniel@makrotopia.org \
    --cc=nextgens@freenetproject.org \
    --cc=wireguard@lists.zx2c4.com \
    /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).