Git Product home page Git Product logo

Comments (18)

calmh avatar calmh commented on September 25, 2024 1

No rush on my part. With this merged we can do our change with the dependency pointing at main, and we can just point it at a real quic-go release before we release.

from quic-go.

calmh avatar calmh commented on September 25, 2024 1

Thanks for all the work!

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

Related discussion: #3727 (comment). Let's continue the discussion here, now that we have the new Transport.

Pinging @AudriusButkevicius @calmh @ydnar @zllovesuki @tobyxdd, who were all involved in that discussion.

The QUIC packet header was designed to make it possible to demultiplex with common protocols: quicwg/base-drafts#426. We introduced the "QUIC bit" (0x40), which is set to 1 in both Short Header and Long Header packets: quicwg/base-drafts#426. While this is not a version-independent property, it holds for both QUIC v1 and QUIC v2.

We could make it possible for users of a Transport to get access to packets that don't have the QUIC bit set. Would that solve your use case?


I can see two ways this could be implemented:

  1. Add a Transport.ReadNonQUICPacketFrom(p []byte) (int, net.Addr, error) method (suggestions for a better name would be appreciated). Internally, this method would read packets from a channel. After the first call to this function, the listen Go routine would add non-QUIC packets to this channel (so we only create the channel if know that there's actually a consumer), dropping them if the channel overflows.
  2. Add a callback to the the Transport: HandleNonQUICPacket(b []byte, net.Addr). If set, the listen Go routine would call this callback with non-QUIC packets. It's the applications responsibility to process the packet quickly and not block the run loop.

Tradeoffs:

  • (1) is arguably the more idiomatic API
  • (1) requires an additional copy into the user-provided buffer
  • (2) doesn't require a copy, but wouldn't allow us to reuse the buffer, effectively leading to an extra allocation for every non-QUIC packet

Given these tradeoffs, I'm leaning towards (1). Thoughts? Anything else we should consider here?

from quic-go.

AudriusButkevicius avatar AudriusButkevicius commented on September 25, 2024

What about providing a net.PacketConn, that also supports writing etc, that writes to the real transport, and a config option in the transport to adjust the buffer size?

t := Transport {
   NonQuicPacketBufferSize: 1 << 20,
}
conn := t.GetNonQicPacketConn()

Both of the proposed APIs still require you to keep a handle on the write side of things, so this would solve that.

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

Would this allow us to drop the OptimizeConn function? One thing you wouldn't be able to do with the new API is have a way to only inject packets (but not read packets), but maybe we can live with that?

from quic-go.

ydnar avatar ydnar commented on September 25, 2024

What if handling non-QUIC packets was the responsibility of the caller, via their own net.PacketConn implementation?

This package could provide a helper func IsQUIC(b []byte) to ease that process.

from quic-go.

ydnar avatar ydnar commented on September 25, 2024

Or this package could provide a PacketConn type that wraps/implements net.PacketConn plus ReadQUICFrom() that Transport would use if present.

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

@ydnar We'd like to be in control of the underlying UDP socket. We already do that to read the ECN bits and the packet info. At some point, quic-go will add support for GRO (#3838). As soon as we do that, every call to Read might return giant packets that we first need to chop up. This will introduce some significant complexity, but we've seen with GSO that batch handling can lead to a dramatic increase in performance.

from quic-go.

bt90 avatar bt90 commented on September 25, 2024

If we only look at the STUN use case, both approaches would work. The question is if someone would want to demultiplex a protocol with more traffic. The first proposal might drop packets if the channel overflows.

You also mentioned that the second proposal suffers from more allocations because quic-go can't reuse the buffer. Wouldn't it be better to split the burden of buffer reuse and allow the non-QUIC side to provide its own buffer?

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

You also mentioned that the second proposal suffers from more allocations because quic-go can't reuse the buffer. Wouldn't it be better to split the burden of buffer reuse and allow the non-QUIC side to provide its own buffer?

How would the API look like?

from quic-go.

bt90 avatar bt90 commented on September 25, 2024

I've no real insight on the internals of quic-go and I'm not a go developer but you're reusing buffers by pooling them? Can't we use a dedicated pool or a second pooled buffer for non-QUIC consumers and transfer the content to that buffer? At least if the intention is to avoid concurrent access.

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

I don't really want to expose quic-go's buffer pool to the outside world. If we want to make pooling possible, the user needs to be able to pass the buffer into quic-go.

The first proposal might drop packets if the channel overflows.

To be honest, this is probably not as bad. There's a lot of places in the networking stack where packets are dropped when a queue overflows, this would just be one more.

from quic-go.

ydnar avatar ydnar commented on September 25, 2024

What about providing a net.PacketConn, that also supports writing etc, that writes to the real transport, and a config option in the transport to adjust the buffer size?


t := Transport {

   NonQuicPacketBufferSize: 1 << 20,

}

conn := t.GetNonQicPacketConn()

This is probably the most sane proposal. I'd bikeshed it to (*Transport).UnknownPacketConn or (*Transport).OtherPacketConn, but it makes sense for multiplexed reads/writes.

If a caller grabs this PacketConn, would Transport implicitly start a server?

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

If a caller grabs this PacketConn, would Transport implicitly start a server?

There's no need to start a server, all we need to do is start listening on the connection.

I'm wondering if we can find an API that fixed the problem I described in #3911 (comment) (the last point about the WriteTo method).

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

#3992 is a draft implementation of (1) without any configuration option for the buffer size.

from quic-go.

bt90 avatar bt90 commented on September 25, 2024

@marten-seemann any ETA for the next release?

from quic-go.

marten-seemann avatar marten-seemann commented on September 25, 2024

Some time next week probably. The milestone is almost done: https://github.com/quic-go/quic-go/milestone/20

Any reason to release early? Are you waiting for this release?

from quic-go.

bt90 avatar bt90 commented on September 25, 2024

I think the syncthing maintainers are in no hurry, but it wouldn't hurt to have a release that works with go 1.21 and avoids the minefield of having to adapt the current packet filtering to the GSO changes.

(disclaimer: i'm not one of the maintainers)

from quic-go.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.