Tag: quic

Get all of the QUIC news, tips, and thoughts from our developers here.

LiteSpeed believes in QUIC. We have publicly released our open source QUIC Client Library, we are participating in the QUIC standardization process alongside Google, Microsoft, Facebook, and others, and we currently power more than 97% of sites worldwide that run QUIC.

  • Server Improvements Under the Hood

    Server Improvements Under the Hood

    LiteSpeed Web Server and Web ADC Updates

    LiteSpeed Web Server and LiteSpeed Web ADC both got significant updates at the end of 2023. Let’s look under the hood to see how these new updates can make your LiteSpeed experience even better!

    RE2 in ModSecurity

    LiteSpeed’s sleek and performant ModSecurity engine now supports the RE2 regular expression library. You can stick with the PCRE library that Apache, nginx, and others currently use, or you can switch to RE2, which comes with a resource-management advantage.

    PCRE commonly faces infinite-looping and thread-blocking issues when processing large input with poorly written patterns. This is a fatal problem for a high-performance, event-driven server. LiteSpeed minimizes the impact of thread blocking by using a thread pool that is separate from the main loop. But despite these measures, as PCRE’s resource usage grows exponentially, it can still cause a server to slow down.

    Computational resource consumption by RE2, on the other hand, grows only linearly and is more predictable.

    RE2 offers a slightly smaller number of features than PCRE does. However, RE2 is faster than PCRE when using certain operators like Boolean OR (|).

    Bottom line: if PCRE is working for you, there is no need to switch. But if you are seeing high CPU utilization, and you think ModSecurity could be to blame, try using RE2, and see if that helps. Navigate to WebAdmin Console > Server > Security > Web Application Firewall (WAF) and select Use RE2 regex engine.

    QUIC v2

    In March of 2023, we updated our LSQUIC HTTP/3 Library to use QUIC v2. Since then, we’ve taken our time integrating QUIC v2 into our server products. This has allowed for maximum testing time and confidence before rolling it out.

    As of LSWS v6.2 and LSADC v3.2, QUIC v2 is in production.

    Request Header Validation

    Request header validation is now more strict. As of these new versions, our validator checks for NULL bytes in the header value, and Transfer-Encoding value manipulation. If either of these is detected, a 400 bad request is returned.

    LSWS Apache Compatibility

    We have three compatibility improvements to share.

    First up, Litespeed now supports the new flags recently added to Apache’s rewrite engine:

    • BNP
    • backrefnoplus
    • BCTLS
    • BNE

    Second, we now support RewriteCond expr '<expression>'.

    And third, we squashed a bug that was preventing us from supporting dynamic regular expression matching. The issue was with variables in the pattern, as seen in SSI code like this:

    <!--#if expr="$referrer = /$host/" –>
    

    LiteSpeed could support fixed regular expression patterns in Apache expressions, but failed when variables were used. This issue is now solved, and LiteSpeed Web Server v6.2 fully supports dynamic regular expression matching.

    Web ADC HEAD Caching

    LiteSpeed Web ADC now supports HEAD caching. Separate cache entries will be created for HEAD requests, to avoid unnecessary hits to the back end, and to improve the cache hit rate.

    Conclusion

    Have you updated LiteSpeed Web Server or LiteSpeed Web ADC yet? The new versions are stable and ready to serve!

    If you’re new to LiteSpeed and want to take one of these products out for a spin, sign up for a 15-day trial, today:

  • LiteSpeed QUIC and HTTP/3 Library v4.0

    LiteSpeed QUIC and HTTP/3 Library v4.0

    lsquic v4.0

    After about 2 years of strong stability and performance in production, LiteSpeed’s QUIC and HTTP/3 library gets its first major feature enhancement release: lsquic v4.0. Notable enhancements include:

    • Support for QUIC version 2
    • Version negotiation
    • Packet retry for address validation
    • Handshake improvements under high packet loss
    • Greatly improved QUIC interop results.

    Below is the detailed information about the improvements.

    QUIC version 2

    QUIC version 2 is in draft 10 as of this writing, and will be published as RFC9369 soon. QUIC version 2 is not intended to deprecate version 1. Instead, it is meant to mitigate ossification concerns and exercise the version negotiation mechanisms.

    There are a few QUIC implementations that already support QUIC v2 including ngtcp2, Kwik, picoquic, and HAProxy. lsquic might have been a little late to the party, but we are here now with v4.

    We also plan to release QUIC v2 into the production environment with our commercial server products very soon.

    Version Negotiation

    Version Negotiation is pretty much in the same boat as QUIC v2. It is in draft 14, and soon will be published as RFC9368. It updates RFC8999 by defining version negotiation mechanisms that leverage the Version Negotiation packet.

    Quote from draft 14:

    It is beneficial to avoid additional round trips whenever possible, especially given that most incremental versions are broadly similar to the previous version. This specification also defines a simple version negotiation mechanism which leverages similarities between versions and can negotiate between “compatible” versions without additional round trips.

    Version negotiation is a required feature in order to support QUIC v2.

    Retry Packet for Address Validation

    This feature is defined in RFC9000 section-8.1.2. It is not something new. It has been used in our commercial WebADC product from the very beginning, however this feature was not previously available in the open source lsquic code base. The related code is now published in v4.

    Handshake under high packet loss or corruption

    In QUIC interop test cases, handshakeloss and handshakecorruption have been two of the toughest tests to pass in our course of improving lsquic interoperability.

    The network quality simulated in the test cases is so poor, it is definitely not something a user will come across everyday. However, to make successful handshakes under such conditions, makes a QUIC implementation super resilient to bad network conditions. In the process of testing, many beneficial tweaks have been made, like minimizing server hello return packets, and ACK/PING fine tuning.

    You can see how much lsquic has been improved in the next section.

    QUIC interop improvements

    lsquic was in the first batch of open source QUIC implementations. It has been running in production environments for many years, and is both stable and performant. It has not only been used in LiteSpeed products, but also by other third-parties in large scale deployments.

    However, lsquic’s interoperability results have not always been the best. This does not mean that lsquic is not as good as the implementations that have better results. It is just that we do not focus on the interop tests. Some tests were not turned on, and some needed minor tweaks.

    Since we are making big improvements to lsquic, it is a good time to take this opportunity to improve interoperability with other implementations. Here is the comparison of before and after.

    lsquic 4.0 interop results

    Green is passed, gray is not supported by the client, and red is failure. As you can see, there are only a few red ones left. Those failures mostly are due to client side problems. lsquic now joins ngtcp2 and picoquic in the “passes all interop tests” club.

    You can check the full results at https://interop.seemann.io/

    Conclusion

    The lscquic v4.0 release is a big leap forward in terms of the latest development of the QUIC protocol. The LiteSpeed team is committed to bringing the best QUIC implementation to the public. Stay tuned for what is coming next.

  • Performance Comparison of QUIC with UDP and XDP

    Performance Comparison of QUIC with UDP and XDP

    Compare Performance QUIC UDP XDP

    Goal: Determine whether any performance gain can be achieved with XDP UDP versus kernel UDP

    HTTP/3 uses QUIC which in turn uses UDP (User Datagram Protocol) rather than TCP/IP for communications. XDP (eXpress Data Path) has been added recently to several operating systems to provide User Space applications performance comparable to direct kernel applications.

    The goal of this blog is to determine if QUIC can gain significant enough performance to justify implementing XDP where it is available. Understanding performance gains usually requires detail so besides a simple test, a profiler will be used to see exactly where performance gains occur.

    XDP can be run with hardware support or can be run entirely in software. The goal is to have an XDP program be usable in the widest possible range of computing environments. This is best accomplished by targeting virtual machines.

    The Test Environment

    LSQUIC

    The QUIC engine used was the popular open-source LSQUIC library available from LiteSpeed Technologies. Only small modifications were made to the base library to support XDP. The XDP functionality was provided by a separate module, which implemented LSQUIC callbacks to send, receive, and allocate packets. Testing was performed using the http_server and http_client programs provided by LSQUIC, modified as necessary.

    The client machine ran a released version of the http_client program from the LSQUIC library and was always the receiver. It was specified to use the Q046 QUIC protocol version.

    The server machine ran the modified version of the http_server program from the LSQUIC library and was run with command line parameters to use either the native UDP or the XDP UDP. It ran in Interop mode, which is a mode of the program where data is transmitted without having to be read from disk.

    Simple volume tests of 2GB were executed to show performance differences between native UDP and XDP UDP. A profiler was used to examine the effect of XDP UDP versus native UDP in the program to help identify specific bottlenecks.

    Hardware and Software

    Server machine:

    • OS: Lubuntu v19.04
    • CPU: Xeon E7 2.4 Ghz
    • Host: Proxmox 6.1
    • Host NIC: Intel X540-AT2 10Gb dual port NIC.
    • VM type: KVM
    • VM Memory: 8 GB
    • VM NIC: virtio_net driver (it has specific performance improvements for XDP built in)

    Client machine:

    • OS: Lubuntu v19.04
    • CPU: Xeon E5 a 3.6 Ghz
    • VM type: None.
    • Memory: 8 GB
    • NIC: Intel X540-AT2 10Gb dual port NIC.

    NOTE: A non-VM machine was chosen with a high speed data path so as to best simulate access to the wider internet in a controlled environment. Other works showing performance include this one, which shows runs simply tossing away or moving data without any real involvement. In contrast, we believe our comparison is the first where a real application could be used.

    The Tests and Results

    3 runs in a row were performed by the client machine pointing to the server machine which was configured to run in native UDP mode. Results reported were:

    • Test 1: 111,036,768 bytes/sec
    • Test 2: 98,336,240 bytes/sec
    • Test 3: 96,860,121 bytes/sec

    Resulting in an average of 102,077,709 bytes per second.

    The server was restarted to run in XDP UDP mode and the client tests were repeated:

    • Test 1: 152,644,777 bytes/sec
    • Test 2: 147,426,653 bytes/sec
    • Test 3: 138,277,563 bytes/sec

    Resulting in an average of 146,116,331 bytes per second.

    XDP Gets the Win

    This is a 43% performance improvement by changing from native UDP sends to XDP UDP sends.

    By examining the top program on all runs we could see that the server program was running at 100% or nearly so. On the client machine the CPU differences were significant. When running in XDP UDP mode the CPU utilization was close to or exceeding 70%. When running in native UDP mode the CPU utilization was less than 60%. This implies that the limit was in the CPU on the server system, which is where the UDP transmissions were occurring.

    Flame Graph from perf Profiling

    Since there’s such a significant difference in performance a profiler was used to see exactly where the program was spending its time. In particular the profiler perf was used as it provides great detail.

    Flame Graph for native UDP

    Processing the perf output with FlameGraph produces:

    In a flamegraph the widest (horizontal) bars take the most CPU. As you go up the graph, you go deeper into the call stack. At the bottom is http_server. As you go up, you go into the program. The bar stays very wide until send_packets_out, an LSQUIC function that has two expensive children, gquic_encrypt_packet and send_batch, the latter being the more expensive of the two. Following send_batch it continues staying very wide into __libc_sendmsg where it leaves the program entirely and is routed into the kernel. From this we can determine that the kernel overhead is by far the most CPU intensive cost.

    Flame Graph for XDP

    Running the same perf run and FlameGraph with XDP results in:

    QUIC with XDP UDP

    This flamegraph has a much faster separation into narrower functions indicating that there are more contributors to CPU cost, in other words, not a single bottleneck. As above the widest row stays wide going into the program until send_packets out where it breaks into gquic_encrypt_packet and send_batch, where send_batch is the slightly wider function. The entry point into the kernel is __libc_sendto where it is barely the widest row at that depth indicating that CPU overhead of encryption is nearly as expensive as transmission.

    This gives us an indication that the kernel overhead is substantially reduced in XDP and explains the performance improvements.

    Conclusions

    The goal of this blog post was to determine where the bottlenecks in QUIC and HTTP/3 are and to see if the XDP UDP interface could help in improving the overall performance. The results of the tests show quite convincingly that XDP reduces the kernel penalty of native UDP.

    While XDP UDP is not a perfect solution for many environments as it is Linux specific it appears that for Linux web servers implementing XDP will result in higher overall performance.

  • Notes from the Road: QUIC Interim Zurich

    Notes from the Road: QUIC Interim Zurich

    Notes From the Road: QUIC Working Group Interim Zurich

    Push this button to melt this protocol!
    – Brian Trammell, 2/5/2020

    The QUIC Working Group Interim meeting in Zurich took place on February 5 and 6 (Wednesday and Thursday). This is the second article in the two-article series – the first described the Interop that ran earlier in that week. My recap is not exhaustive; see the official minutes for the full list of the agenda items.

    Interop Status

    At the beginning of Wednesday’s session, Lars Eggert (one of the co-chairs; NetApp) updated the Working Group on the results of the Interop.  In short: we’re still playing catch-up with the changes in the draft; getting the transfer performance batch (the “T” letter) is tricky; and very few implementations support the ECN feature.  (lsquic does support ECN, which is an optional part of the protocol.)

    Varinting the Transport Parameters

    The discussion began with one of the more contentious issues (#3294): converting the way transport parameters are encoded.  In the current draft (25), they look odd because they do not use variable length integers; almost everything else in the transport draft uses varints.  The purist point of view, which David Schinazi (Google) advocated, is that we should make the draft more uniform and use variable integers throughout.  The opposing view (and my initial position) is that this is a cosmetic change and it is too late in the process to make cosmetic changes.

    The argument then moved on whether the limitation of 64K possible transport parameters imposed by the current encoding is important.  More experienced members of the WG stated that this is indeed the case. A smaller set of codepoints leads to registrars being very protective of the unallocated values. A practically infinitely large (262 – 1) set of codepoints would make these concerns moot.

    Having considered these, I switched my preference from “no” to “neutral,” even though this, in effect, becomes wasted work.  In addition, we would have to support both encoding types when doing both ID-25 and ID-26 drafts.

    In the end, the consensus was to make this change, and so we are again changing something significant in the draft.  To lessen the impact of this change, the editors promised to release ID-26 promptly, so that we have time to implement it before the Vancouver Interop in late March.

    Two related issues were briefly touched upon.  First, should there be a requirement to detect duplicate transport parameters?  Second, should the transport parameters be required to be sorted? Certainly, duplicate detection is trivial when parameters are sorted.  Nevertheless, both these proposals were shot down. Martin Thomson (Mozilla) pointed out that the lack of ordering requirements for TLS extensions turned out to be integral for making possible backwards compatibility with TLS 1.2.

    CID Retirement Timeout

    Gorry Fairhurst expressed his concern with the lack of clarity regarding the wait time before a connection ID must be retired in issue 3215. The discussion revolved around just how long an endpoint could wait after receiving a NEW_CONNECTION_ID frame before issuing a RETIRE_CONNECTION_ID in response. If this time is too short, the tarrying endpoint risks receiving a stateless reset when it tries to use the connection ID that was supposed to be retired. Igor Lubashev (Akamai) and a few others pointed out that forgetting a stateless reset token and sending the RETIRE_CONNECTION_ID frame for the corresponding CID do not have to happen at the same time. That is to say, the risk of an aborted connection due to a stateless reset is minimal.

    As this discussion wore on without resolution, Lars preempted it. He asked for a self-organized lunch group to come to a consensus during lunch (naturally). At lunch, it was resolved to close this issue with no action (that is, no design change) and potentially a new editorial issue to clean up existing text.

    Padding Outside QUIC Packet

    Issue 3333 asks whether UDP datagram padding should be counted toward the server’s amplification limit. To prevent amplification attack, a QUIC server is not to send more than three times the number of bytes it received on the connection until the client address is verified. The current version (25) of the Transport Draft recommends padding Initial QUIC packets using PADDING frames. On the other hand, it does not proscribe padding the UDP datagrams that carry QUIC packets with garbage. At least one client implementation pads Initial packets in this manner.

    One view is that what matters are bytes received from the client. Since garbage bytes that follow an Initial packet in a UDP datagram are bytes, those bytes should count. The opposing view, advocated by Christian Huitema and others, is that QUIC is a cryptographic protocol, which means that the only way to attribute bytes to a connection is by using QUIC packets.

    In the end, the first view had more support. The next version of the draft will count garbage trailing bytes toward the server amplification limit.

    Recommend ECN Strongly

    Mirja Külhewind, one of the co-authors of the QUIC Operability Drafts, advocated for recommending ECN more strongly in issue 3373, for she deemed the current text to be too cautious. Agreeing with her were Brian Trammell (Google), David Schinazi (Google), and Lars Eggert. Eric Kinnear (Apple) reported that Apple turned on ECN for TCP three years ago and it hasn’t caused outages. Matt Joras (Facebook) and Roberto Peon (Facebook) were more cautious: “recommending ECN without deployment experience seems strange.”

    After a rather prolonged back-and-forth, the consensus was that the current text in the draft is encouraging enough and that Appendix B describing a sample ECN support detection algorithm will stay until we have something better to recommend. Mirja will work on minor editorial text improvements.

    There Be Extension Dragons

    What happens when two QUIC extensions are not compatible? For example, they might modify an existing frame, such as the ACK frame, in conflicting ways. This is the subject of issue 3332.

    QUIC Working Group Interim Meeting Zurich
    Roger Liberating Angelica (fragment) by Félix Vallotton at Kunsthaus Zürich

    Some proposed disallowing modifying existing frames. Igor Lubashev offered an algorithm for extending frames in an unambiguous manner. Others pointed out that extensions may be incompatible in a variety of ways, of which frame formatting is only one.

    In the end, it was decided to let the problem resolve itself naturally – in chronological order as extensions get proposed — add a comment to the draft that there be dragons here. Dragons indeed.

    DCID for Handshake Retransmission

    Should the server be allowed to issue new connection IDs before the handshake is complete? This is the subject of issue 3348, raised by Marten Seemann. Why would a client change its Destination CID at that time? Brian pointed out that there is no reason for the client to do it. Yet, the discussion went on. Martin Thomson said that coupling handshake state machine with CID state machine complicates things, and so it is uncomfortable to forbid changing CIDs until 1-RTT packets. Eventually Lars stopped the back-and-forth, directing people most interested in this problem to come up with something during lunch.

    The lunch consensus – I take it, people tend to be more agreeable when their bellies are full – was to allow the client to change DCID at any time. In other words, if a server does not want the client to do this, it should not issue new CIDs too early. An editorial clarification or two may follow.

    ACK Generation Recommendation

    Jana Iyengar (Fastly) opened issue 3304 before he and Ian Swett (Google) co-authored the Delayed Acks extension. (I think their collaboration was the result of the conversation in this GitHub thread). Jana pointed out that the current recommendation – produce one ACK for every two ACK-eliciting packets – results in too many ACK frames in the normal case. “Too many” here means that the large number of ACK packets sent and received affects throughput negatively. (This was likely one of the reasons for the poor nginx/quiche performance uncovered in our November benchmark tests.)

    Several implementations already do not follow this recommendation. Is providing a recommendation in the draft and expecting people to ignore it the best we can do? The tricky part, of course, is making a specific recommendation that works well most of the time. The several schemes discussed in the GitHub issue all suffer from some form of degradation under some circumstances or when interacting with a particular type of congestion controller.

    Not having come up with anything conclusive, we resolved to close this issue with no action. The current recommendation is good enough, at least for now. In addition, we have the Delayed Acks extension that we could use to experiment.

    Issuing New CIDs in 0-RTT Packets

    In issue 3423, Marten posed another corner-case riddle. Because the client does not have to remember the maximum number of active connection IDs the server supports, it risks overrunning this limit by issuing new connection IDs in its 0-RTT packet.

    Corner cases are the bane of our Working Group. Discussing them takes up valuable time, time that would be better spent discussing more practical matters. This corner case took up about 1.5 hours – almost as much as all the Thursday’s discussions of the QUIC extension drafts combined!

    The scope of the discussion is documented well in the minutes. None of us could put forth a plausible scenario for using NEW_CONNECTION_ID frames in 0-RTT packets. The voices of reason who advocated banning these frames in 0-RTT packets outright (mine and Christian Huitema’s) almost prevailed at one point, only to see our ten-votes-to-three advantage go down to one-vote-to-ten shortage. (Christian was remote and so his vote naturally was not counted.) Martin Duke (F5), who was running the vote counting, offered me a chance to “die on this hill,” which is an IETF expression for a last-ditch effort to object, akin to Demi Moore’s character’s strenuous objection in the movie The Few Good Men. Dying is a bit too dramatic for me, so I quipped, “I refuse to die!” to the clapping of three dozen pairs of hands. Thus was it decided that the client would just have to remember the server’s active_connection_id_limit setting.

    Changing ACK Frequency

    Jana’s and Ian’s presentation was about the extension they authored to reduce the number of ACKs generated.  I described their proposal in my previous post.

    They explored the problem area, highlighting the tension between having too many ACKs reducing throughput because of the need to generate and process them and having so few ACKs as to cause retransmissions that also reduce throughput.

    The Working Group was mildly enthusiastic about the possibilities this extension could offer. There is plenty of room for optimization, but there are also some hidden stones. Martin Duke asked whether the parameters communicated via the new ACK_FREQUENCY frame were advisory or mandatory. The answer is clearly advisory, as the sender of the ACK has its own limits or preferences that would trump those of its peer.

    Most of us agreed that this work is important, and that experimentation should continue.

    Multipath QUIC

    Quentin De Coninck (Université catholique de Louvain) talked about multi-path QUIC. He introduced the concept of a QUIC uniflow, which is one half of the today’s QUIC path. Using uniflows, one can model MPQUIC effectively.

    Quentin shared his implementation experience. A basic multi-path support in quickly weighed in at about 350 lines of code; a full-fledged implementation based on picoquic was 2500 lines of code – still a very reasonable number.

    The Working Group peppered Quentin with questions. How does path prioritization affect the scheduler? Is it necessary to change QUIC and HTTP/3 APIs to make this useful? Does this work need its own Working Group?

    The biggest chill was put on the proposal by Jana’s observation that there is no application that could use this capability. That is, lest it be completely transparent to the application. (This seems like a chicken-and-egg argument to me. An application utilizing multi-path capabilities cannot be created until those capabilities exist; and multi-path capabilities cannot be developed until there is an application that can use them.) We need a Research Group, said Jana, not a Working Group.

    Packet Loss Signaling

    Igor presented our packet loss signaling proposal.  (I say “our” because I recently became a co-editor of the draft along with Igor and Alexandre Ferrieux (Orange Labs)).  I touched upon the proposal in the previous post. The WG expressed several concerns. Matt pointed out that this proposal is unlike others because it modifies the packet headers and it could become a “de facto” extension that everyone is expected to implement. This change would burn both the reserved bits: what if QUICv2 needed more bits in the first byte? Does this change preclude other extensions from using these bits?

    The real answer is that this functionality should have been part of the core protocol to begin with. These bits provide real value to network operators; without them, troubleshooting of QUIC network flows is much more difficult. Another extension (that doesn’t yet exist) that would want to use the reserved bits in a similar fashion can use the L bit for its square wave, thus differentiating itself. Further than that, obviously the space is limited, and no amount of ingenuity will be able to squeeze many extensions into two bits.

    Other questions resembled those posed at the trial of Joan of Arc. Like the Virgin (although likely possessing less divine guidance), Igor parried admirably:

    Marten: Loss detection and recovery in our spec is only advisory.

    Igor: When you decide the packet is lost, you increment the counter.

    Marten: This is an implementation decision.

    Igor: Yes, when you decide it’s lost you increment the counter.

    Marten: So, the network needs to know your algorithm.

    Igor: No, the assumption is that if the sender thinks it’s lost, then it’s lost.

    The extension was deemed important enough. To quote Igor, “we need this to make the Internet better.” Mark Nottingham (co-chair of the working group; Fastly) directed us to participate in the experimental QUIC DISPATCH meeting at IETF 107 in Vancouver in March of this year.

    The Last Lunch

    The Interim wrapped up early: around half past one on Thursday.  About half of us headed for free lunch at Google cafeteria, which was just down the corridor.

    The food is fancy at Google Zurich. The “small plates” concept is in fashion there as well, so I got myself two plates. And a sandwich.

    I sat across from Junho Choi (Cloudflare), with whom we talked shop: QUIC performance and how it is affected by ACK rate, quirks of Rust and C++ programming, and QUIC deployment issues.  Later we were joined by Lucas Pardue (Cloudflare), the newly minted QUIC WG co-chair.  We discussed the events of the past few days and assessed the results of the Interim.

    As usual, it was great to share implementation experience with like-minded people. I look forward to comparing notes with them again.

    The Chagall Windows

    I stepped out from the Google building into a fresh and sunny winter afternoon.  After several gloomy, rainy days everyone was visibly in a better mood. I hurried to the Fraumünster Church while the sun was still reasonably high.

    QUIC Working Group Interim Meeting Zurich
    Chagall windows: “Jacob,” “Christ,” “Zion”

    Marc Chagall created these three (and three more, for a total of six) beautiful stained-glass windows for the Fraumünster Church in Zurich.  These were installed in 1970, when he was 83. He started doing this type of art late in life. Fame had come to Chagall earlier for his paintings, about ten of which are on display in the Zurich art museum (Kunsthaus).

    The church itself is a reincarnation of previous churches, which have existed on this spot for the last 1200 years.  The crypt reveals parts of the original church’s foundation. What were the names of the workers who cut and laid those stones? – I wondered – Were they happy or sad? Did they know that what they had wrought would be still around after so much time?

    Like the builders of the newer church, we base the workings of a new protocol on an old foundation. Like Chagall’s, our conception of what could be must be fitted into a canvas of a predetermined size. If we be granted only a fraction of those craftsmen’s and artist’s inspiration and perseverance, then our project – QUIC — will surely be successful.

  • Notes from the Road: QUIC Interop Zurich

    Notes from the Road: QUIC Interop Zurich

    QUIC Interop Zurich, Notes from the Road

    The QUIC Interop event precedes the QUIC Interim. The Interop is meant to find bugs in different implementations — and in the specifications themselves! This year, these two events take place in Zurich, Switzerland, where Google is graciously hosting us.

    Enter the Dragon

    QUIC Interop Zurich, Kasernenstrasse 97
    Kasernenstrasse 97

    On Monday, February 3rd, I arrived at Kasernenstrasse 97 at 9 o’clock in the morning. The Zurich Google office is located in Sihlpost — a massive building on the left bank of the river Sihl. Being so massive, the building possesses two entrances, about 200 feet apart, and two addresses: Kasernenstrasse 97 and Kasernenstrasse 95. The former is the regular Google employee entrance; the latter is where the Google reception is located.

    Visitors like me are to use the reception entrance where they are given a temporary guest badge. This I learned later. On that morning, having ignored the sign imploring the visitors to use the other entrance (“95? That must be on the next block!”), I tailgated my way to the fourth floor. There, having run into yet another badged entrance, I waited. Thankfully, a few seconds later, a Google employee emerged. I told her in my best German that I am here for the QUIC conference. “Oh! You should have used the other entrance. That’s OK, I will lead you to the reception.” Like the magical Sesame, gates fell open before us and, in as few as 30 seconds, I was at the reception. Thank you, my kind nameless guide!

    Boys are Back in Town

    I was one of the first people in the room. There, Brian Trammell, our host, greeted me and I met Stanislav Slusny (Akamai). Later, many familiar faces filled the room: Eric Kinnear (Apple) and his crew; Lars Eggert (NetApp); Lucas Pardue, the new QUIC Working Group co-chair, and Alessandro Ghedini (Cloudflare); Martin Duke (F5); David Schinazi and Ted Hardie (Google); Jana Iyengar (Fastly); Martin Thomson and Eric Rescorla (aka EKR) of Mozilla; and others. It was like the good old times again! We picked up where we left off: each running his QUIC client against the others’ servers.

    The “Handshake Done” Bug

    Christian Huitema, who attended the Interop remotely, and I had been debugging performance issues in lsquic/picoquic (Christian’s implementation) interactions for a few days. On Monday, I fetched the latest version of picoquic and saw the performance much improved. On the other hand, I also observed that some connections would fail during the handshake. After some digging and arguments, I had to admit that I was in the wrong and that lsquic server sent the “handshake done” confirmation too soon when TLS session was being resumed. I have a tentative bug fix that will be included in the next release of lsquic.

    Later it turned out that F5 and Cloudflare QUIC implementations have also been afflicted with the same bug, which made me feel slightly less silly. This is the great value of interops: we are bound to find bugs in implementations of newly added protocol features (of which the HANDSHAKE_DONE frame is one).

    Bug 2: Garbage Padding

    Another new feature of the QUIC protocol is allowing UDP frames carrying Initial packets to be padded with garbage. An implementation is supposed to discard this padding. This was not happening in lsquic, which is what Andy Grover (Mozilla) discovered using the neqo client. I was able to fix this lsquic issue quickly and Andy successfully tested that it works. Thanks for a nice corner case, Andy!

    GSO vs XDP

    What’s better: GSO or XDP? This was one of the questions that Igor Lubashev (Akamai), Matt Joras (Facebook), Stanislav Slusny, and I discussed. (That is to say, I mostly listened.) This was one of those spontaneous moments that one can experience only when attending a QUIC meeting in person, not remotely. I can’t wait to apply these shared bits of wisdom in lsquic.

    Delayed ACKs

    Jana Iyengar and Ian Swett (Google), erstwhile coworkers and two of the principal movers of QUIC, teamed up to propose a protocol extension to control acknowledgement delay and other ACK generation parameters dynamically. This has the potential to reduce CPU overhead significantly by sending and processing fewer ACK packets. Getting this right is tricky, however. lsquic, picoquic, and quiche have experimental support for this feature and we played with it, looking for performance gains (or losses). lsquic’s mechanism for ACK control using this extension is quite bare-bones and improves CPU utilization in some cases, while in other cases it may cause significant throughput degradation. More work is required here.

    Loss Bits

    The loss bits extension (by Igor Lubashev, Alexandre Ferrieux (Orange), and your humble author) is meant to help operators troubleshoot network problems. In particular, inclusion of the loss bits into QUIC packets allows one to determine whether packet loss occurs upstream or downstream of a probe. To date, this extension has proved to be very controversial. The spin bit debates were epic — and they were over just a single bit. Now, we want to add two more bits — Q and L bits — to the unencrypted part of the QUIC packet header!

    At LiteSpeed, we believe in being good citizens. This includes allowing network operators to do their job. From the practical side, availability of network tools should improve the chances that QUIC gets adopted. For these reasons, we had supported the spin bit when it was proposed. We now also support the loss bits extension.

    Besides lsquic, one other implementation supports the loss bits extension — Christian Huitema’s picoquic. We had already achieved interoperability prior to this week’s event. On Tuesday, Igor and I ran several tests against picoquic and lsquic servers while introducing packet loss. These tests are ongoing.

    And the Winner Is…

    Just kidding — there is no winner! The Interop is a collaboration between many organizations, large and small, and individual developers. We proved once again that the protocol works. We found bugs. lsquic benefitted from this exercise and, in turn, helped others uncover bugs in their implementations.

    The Interim meeting is tomorrow. This is the year that we ship the final spec. Let’s get it done!

    QUIC Interop Zurich, Results
    P.S. lsquic server has most purple squares!

     

  • LSQUIC on FLOSS Weekly

    LSQUIC on FLOSS Weekly

    LSQUIC on FLOSS Weekly

    On Wednesday, November 27th, I was a guest on the FLOSS Weekly show on TWiT to discuss LSQUIC, our QUIC and HTTP/3 library.

    Background

    I first learned about the FLOSS Weekly podcast a year or two ago. The idea to appear as a guest on the show did not occur to me until much later. Immediately, it made sense: our QUIC and HTTP/3 library is a full-featured, well-tested, and robust implementation of an increasingly important Internet protocol. And — it’s open source!

    Because I have been involved with QUIC and HTTP/3 development at the IETF for some time, I would also be able to shed some light on certain aspects of these protocols.

    I emailed Randal Schwartz, the host of the show, and he slotted me in for November 27th.

    Preparation

    The date of the show was drawing near and, as I still had not received any details about the setup, I began to worry. Did Randal forget about me? Finally, on the 26th, I emailed Randal basically to ask him this. He replied, somewhat incredulously, “did you not receive my previous emails?!” It turns out, Gmail had been helpfully discarding Randal’s emails as SPAM. Sabotage?*

    The preparation for the show consisted mainly of testing my audio and video equipment. While the laptop’s built-in webcam was OK, TWiT deems any built-in laptop microphone as inadequate. I also learned about positioning of the webcam (eye-level) and lighting (in front, not behind). These simple adjustments make a large difference.

    Making The Show

    I admit it: I was nervous. While I have spoken in front of large audiences before, a live TV show would be a new experience for me.

    I made a Skype connection with a TWiT Live Line user a few minutes before the show. We checked the audio and video feeds and I said hello to Randal and Jonathan Bennett, that week’s co-host. And the show was on!

    Within a few minutes — after the introduction and an advertisement from the show’s sponsors — I was brought on and chatted away happily with Randal and Jonathan about QUIC, HTTP/3, and LSQUIC. The interviewers prepared well and we discussed the evolution of HTTP/3, the good and the bad of basing a transport protocol on top of UDP, LSQUIC performance and history, and many other topics. There were a few questions from the live “studio audience,” which is just a dedicated IRC channel. Some levity was had as well: no, there is no HTTP/4… yet!

    After Recording

    Rather than providing a condensed transcript, I suggest you click the link above and watch the YouTube video or grab it from your favorite podcast platform. The discussion lasted for about 50 minutes — or almost the whole show — after which it was time to wrap up.

    The edited version of the show was posted online in three or four hours. They did not take anything out; rather, the show was rearranged by topics, as we jumped around a bit, and for a better flow. It was a good editing job, which is not surprising: ours was FLOSS Weekly show number 557.

    I loved being on the FLOSS Weekly show and I recommend it to everyone. If you have an open-source project that you love, you should consider sharing it with the rest of the world on TWiT with Randal Schwartz and his brigade of co-hosts.

    TIMTOWTDI

    It was a special thrill for me to be interviewed by Randal Schwartz, the co-author of Programming Perl and Just another Perl hacker. That book I had on my bed stand and I carried it with me on my commute to college, hiding it under my jacket from the rain. Perl was my first true love.

    *Sabotage is unlikely

  • BBR Control in QUIC and HTTP/3

    BBR Control in QUIC and HTTP/3

    BBR Congestion Control in QUIC and HTTP/3

    BBR congestion control is now available for LiteSpeed QUIC and the upcoming HTTP/3.

    The newly released LiteSpeed Web Server 5.4.2, Web ADC 2.6.0, and OpenLiteSpeed 1.6.1 use BBR congestion control for QUIC connections. BBR (which stands for Bottleneck Bandwidth and RTT) is a new congestion control algorithm developed by Google in the last few years. It features several profitable properties.

    Resistance to Loss

    The main idea behind BBR is that packet loss may not mean that there is congestion in the network. For example, a packet may be lost due to transient radio interference. Cubic and other congestion-based algorithm do not distinguish between such spurious losses and real congestion, reducing their send rate in both cases. BBR, on the other hand, is not so easily spooked.

    As a result, BBR can deliver sustained throughput performance even in the face of suboptimal network conditions.

    Minimal Latency

    Bufferbloat has been the bane of good UX for years. Since the problem was identified and alarm sounded, there have been changes to network infrastructure equipment to avoid buffering too much data. Nevertheless, the fact remains: Cubic will try to fill the bottleneck buffer on the network path, increasing connection latency. A study of 4G LTE networks reveals that to mask packet loss, buffers are used extensively, thereby inflating RTT.

    BBR keeps track of the bottleneck bandwidth and periodically tests for minimum round-trip time. These estimates are used by the sender to avoid filling the bottleneck buffer. With BBR, an interactive web application is more likely to be responsive.

    Drawbacks

    Despite its terrific advantages, BBR is not without problems. It performs poorly when there are shallow buffers on the path and it may not be fair to other flows, claiming most of available bandwidth. These issues will be addressed in BBRv2, which is being actively developed at Google.

    Test Results

    Throughput Under Loss

    To compare BBR to Cubic, I set up a pre-release build of LSWS 5.4.2 and conducted a few experiments downloading a static file from the web server using the LiteSpeed QUIC client. The bottleneck was set up on the client side using netem and ifb.

    Rate (MBit/sec) Delay (ms) Loss (%) Cubic (sec) BBR (sec)
    20 25 0 4.5 4.5
    20 25 0.5 6.7 4.6
    20 25 1 8.6 4.6
    20 25 2 14.3 4.7
    20 25 3 17.6 4.7

    Table 1: Time to transfer 10 MB file, in seconds

    It is evident that Cubic is very sensitive to packet loss, while BBR is not.

    Latency

    To test the difference in latency between Cubic and BBR, we set up a simple website with three resources: an HTML page with links to two files: one large and one tiny. The bottleneck was set up to have 20 MBit/sec bandwidth and 25 ms delay with a large buffer. The user clicks on the large file and it begins downloading. The user then clicks on the small file. When Cubic is used, it takes one to two seconds to download the small file:


    Figure 1: Downloading small file when server uses Cubic

    This is because Cubic tries to fill the intermediate buffer. BBR, on the other hand, keeps the bottleneck buffer filled “just right” so that downloading a small file take on the order of RTT:


    Figure 2: Downloading small file when server user BBR

    BBR Congestion Control in QUIC and HTTP/3

    BBR is a novel congestion control technology. It has two advantages over the widely-deployed Cubic congestion control: insensitivity to random loss and low latency. With LiteSpeed, you can take advantage of this technology today to power your server’s Google QUIC and HTTP/3 connections.

    As Google evolves BBR, we will continue to support the most recent stable version.

  • HTTP/3: State of Play

    HTTP/3: State of Play

    Current Status of HTTP/3

    It’s good to be the King! – Mel Brooks

    The October HTTP/3 Interop has come and gone. What follows is a short recap, a look at the current status of HTTP/3, and where we will go from here.

    Introduction

    The IETF QUIC Working Group held a virtual interoperability event on October 1 and 2. These events have been held regularly for the past year and a half. This interop was virtual, meaning we were collaborating online across the time zones.

    During an interop, the various server and client QUIC and HTTP/3 implementations try to talk to each other and exercise different pieces of functionality. The interops serve as a sanity check and allow us to find bugs in our code and, more importantly, in the specifications themselves.

    The Matrix

    To keep track of different features, an interop matrix is recorded in an online spreadsheet.

    Current Status of HTTP/3 Matrix
    14th Implementation Draft Interop Matrix

    Each feature is assigned a letter and categorized into Core, Optional, Performance, and HTTP/3.

    Current Status of HTTP/3 Matrix Cell
    The “aioquic client / lsquic server” cell from the matrix above

    For example, the above means that aioquic client was able to connect to LiteSpeed server and

    • perform version negotiation (V);
    • complete handshake (H);
    • transfer data (D);
    • close connection successfully (C);
    • use TLS session ticket to resume a connection (R);
    • send request in zero-rtt data and receive response (Z);
    • respond to a stateless retry (S);
    • migrate a connection to server’s preferred address (M);
    • survive a NAT port rebinding (B);
    • update TLS keys (U);
    • spin latency bits (P);
    • transfer a 10MB resource reasonably fast (T);
    • fetch an HTTP/3 resource (3);
    • utilize QPACK dynamic tables (d); and
    • receive a push request (p).

    One can see the complete list of categories and features here.

    Two more features not listed here are

    • explicit congestion notification (E) (which our server supports); and
    • structured logging support (L), which was a last-minute addition to the list of features.

    The way the letters are colored is a bit obscure, but the general rule is that more features get you a hotter color. LiteSpeed supports all but one feature (including all HTTP/3 features) and the client in this case was able to hit all but one of them. At the time of this writing, our server implementation was the only one to have earned the imperial purple. It’s good to be the king!

    Participation

    The number of participating implementations has decreased from the previous interop. Notable absentees are Quant (implementation by Lars Eggert (NetApp), the co-chair of the QUIC Working Group), quic-go (a Go implementation by Marten Seemann), and Apple. The latter only make an endpoint available in face-to-face meetings, running on someone’s laptop.

    A couple of implementations are still dragging their feet on HTTP/3 support.

    I had productive interop sessions with Cloudflare, F5, Facebook, and Microsoft, among others. We found a few bugs and clarified a couple of points in the specification.

    Throughput

    This metric is the only member of the Performance Features category. It is roughly defined as “being able to download a 10MB resource over QUIC that is at most 10% slower than the same resource downloaded using HTTP/2.”

    The problem with this definition is that most people have different servers for HTTP/2 and QUIC. This may cause highly disparate download times between the two protocols. At times, some hoodoo was used to get the coveted “T” letter. As one participant — not your humble author — muttered to himself, “I need to cripple TCP…”

    Take these results with a grain of salt

    ECN

    Only three implementations support Explicit Congestion Notifications: F5, LiteSpeed, and Quant. As Quant did not participate this time around, there is only one “E” letter in the whole matrix: LiteSpeed client and F5 server. The reverse test failed, as something dropped ECN markings on path.

    The future of ECN as a feature of QUIC is uncertain.

    Bugs Found

    With help from Alessandro Ghedini (Cloudflare), Nick Banks (Microsoft), and others, I found and fixed a couple of minor (standard compliance) bugs in our implementation. Look for them in the next release of the LiteSpeed QUIC and HTTP/3 Library.

    To return the favor, our server broke Tatsuhiro Tsujikawa’s HTTP/3 client (nghttp3) via its “unidirectional stream torture mode,” which is turned on by default for the interop purposes. Our client found a bug in the way Google server interprets transport parameters.

    Clients

    Finally, there is HTTP/3 browser support! Two weeks ago, Chrome Canary began to support HTTP/3 when provided a couple of special flags. This is wonderful, as we now can test HTTP/3 using real websites with a real browser. LiteSpeed Web Server and ADC have supported HTTP/3 since July 2019 and OpenLiteSpeed — since September. Now our customers and users can try HTTP/3 for themselves.

    As of October 4, Microsoft Edge Canary supports HTTP/3 as well.

    The venerable curl command-line tool and library added HTTP/3 support in August.

    Firefox is planning to add HTTP/3 support by the end of the year.

    These are good signs.

    Servers

    We have been shipping HTTP/3-enabled products for months. We are happy there are now real browsers to pollinate our servers, so to speak.

    Cloudflare announced QUIC availability last week to much ado. Indeed, using our http3check.net tool, one can see that they do support HTTP/3. Welcome to the party.

    LiteSpeed and Cloudflare are the only two known vendors running HTTP/3 in production.

    Future

    The next QUIC Interim Meeting is in two weeks. There are a few design items on the menu, but nothing earth-shattering. I can see the light at the end of the tunnel; HTTP/3 is inching closer to being released.

    In the meantime, our LiteSpeed QUIC Team will continue to improve our software, participate in the HTTP/3 standardization process, and think of new ways to deliver value for our customers.

  • QUIC Library Is Now Open-Source

    QUIC Library Is Now Open-Source

    LiteSpeed OpenSources QUIC HTTP/3

    LiteSpeed Technologies is releasing its QUIC and HTTP/3 library under an open-source license. This library, written in the C programming language, contains both client and server logic as well as fully functional example client and server programs to get you started. This is the same code that is used in our flagship LiteSpeed Web Server and LiteSpeed Web ADC products and in the open-source OpenLiteSpeed (OLS) web server.

    The following QUIC and HTTP/3 versions are currently supported:

    • Q039
    • Q043
    • Q046
    • h3-22

    Q039, Q043, and Q046 are versions of the Google QUIC protocol. Q046 is used by the current version of Chrome (Chrome 76). h3-22 is the experimental precursor to HTTP/3, the next-generation HTTP protocol. We will update the library as new gQUIC and HTTP/3 versions are released.

    This library subsumes the LiteSpeed QUIC Client Library which we released two years ago and replaces it on GitHub. The new module is a superset of the original client library.

    We use plenty of open-source tools and libraries. We are happy to contribute back to the community the fruits of our labor: a fully functional, mature, scalable, and robust QUIC library.

    Happy hacking!

    LiteSpeed QUIC Team.

  • Notes from the Road: QUIC Interim London

    Notes from the Road: QUIC Interim London

    Notes from the Road: QUIC Working Group London Interim Meeting

    “PLEASE TAKE NO ACTION!”
    – PSA on Cloudflare’s intercom during a fire drill, 5/23/2019, London QUIC Interim Meeting

    The QUIC Working Group met for its regular Interim Meeting last week. This time, it was hosted by Cloudflare at its headquarters in London. Once more, the author attended the meeting remotely.

    Interop Results

    As usual, a two-day interoperability hackathon preceded the interim meeting proper. The Interop was held Monday and Tuesday. The number of QUIC implementations has grown to about two dozen. There are now QUIC implementations in C, C++, Erlang, Go, Java, Objective-C, Python, Rust, and TypeScript. Most of them already implement the month-old (that’s old!) Internet-Draft 20 QUIC transport and about half of them do HTTP/3.

    Our own implementation, lsquic, successfully fetched a resource using HTTP/3 from ten servers; eight HTTP/3 clients succeeded fetching a resource from our server implementation. Two implementations already support server push. This is on our to-do list.

    Alan Frindell (Facebook), our old friend and editor of the QPACK draft, found a bug in our QPACK library, ls-qpack. A drawback of having an early implementation is that one becomes subject to an unusual category of bugs: specification changes. In this case, one of the default QPACK settings changed from 4096 to 0 – but the code did not. On the bright side, the bug was easy to fix.

    Connection ID Grows

    The Interim Meeting commenced on Wednesday with discussion of Connection ID length.

    Over a year ago in Melbourne, the proposal to grow the CID from 8 bytes was first floated. Since then, the CID transformed from fixed to variable length and grew to a maximum of 18 bytes. Martin Duke (F5) has been working on QUIC Load Balancer specification and ran into a limitation: 18 bytes is just not enough for a multi-tier load balancing solution.

    The proposal is to increase the maximum Connection ID size from 18 to 48 bytes. This change will have a significant effect on the wire format, as four bits no longer suffice to encode 49 (0 through 48) values.

    [SIDEBAR] An acute reader has noticed that four bits are not enough to represent 19 (0 through 18) values, either. The way it currently works is that the set [0 – 15] is mapped to 0, [4 – 18].

    An impact to our implementation will be unfortunate. We represent CID as a struct: four-byte integer to represent the CID length and 18-byte buffer to hold the ID. Together with padding, this structure weighs in at 24 bytes. Given that lsquic uses 8-byte CIDs, the overhead is 200%. The forecast CID growth will increase this overhead to 550%. To take this arithmetical exercise a bit further: each IETF QUIC connection averages eight source CIDs and eight destinations CIDs. This means that there will be (52-8)*16=704 bytes of overhead per connection.

    HTTP Priorities

    HTTP/3 has inherited HTTP/2 priority scheme – adjusted for the specifics of the QUIC transport. Exclusive dependencies are gone, and placeholders are used in place of zombie requests to keep priority trees stable.

    Patrick Meenan (Cloudflare) and others have been researching how well – or, rather, how poorly – web browsers and web servers utilize HTTP/2 priorities. The answer is: overall, priorities are not leveraged effectively. In large part, this is due to problems in the HTTP/2 priority design.

    Patrick Meenan, Robin Marx (Hasselt University), and Ian Swett (Google) have each made competing proposals, while many others made various suggestions to them, creating what Ian called a prioritization spectrum:

    QUIC Working Group London Interim Meeting: Ian Swett's Prioritization Spectrum
    Slide from Ian’s Presentation

    The Working Group agreed that further work is needed on this in order to have an effective prioritization that will actually be used. It is possible that prioritization will be done as an extension: that way, it can be changed should a better design appear. Stay tuned.

    Version Aliasing

    Version aliasing is an attempt to prevent version ossification. QUIC handshake packets expose QUIC version information. In order to prevent middleboxes from allowing (say) QUIC v1, but dropping other versions, it has been proposed that a server may offer the client a selection of version aliases. The server agrees to recognize these aliases for a fixed period of time as equivalent of some other version. The client, then, can use one of these aliases in a subsequent connection attempt.

    While the proposal is short, the implementation of this mechanism is sure to have some underwater stones. We hummed in favor of addressing the version ossification problem in v1 and so either this proposal, its variation, or something else entirely will likely make its way into the final QUIC transport draft.

    Next Steps

    IETF 105 takes place in Montreal at the end of July. Before that time, there may be another virtual (that is, not face-to-face) interop event, depending on when the next version of the QUIC Internet-Drafts drops. The biggest question mark in my mind is the HTTP priorities. We want to get it right – this means doing a lot of work, and a lot of work takes time.