Skip to content

Commit 5e0c56c

Browse files
afrindmeta-codesync[bot]
authored andcommitted
Split WT_INITIAL_MAX_STREAM_DATA_BIDI into LOCAL/REMOTE
Summary: The h2 WebTransport draft defines three per-stream data limits (UNI, BIDI_LOCAL and BIDI_REMOTE) but we only have one BIDI setting at `0x2b63`, which is really BIDI_LOCAL under an older name. With a single value a bidi stream gets whichever limit happens to be stored, regardless of which endpoint opened it. Rename `0x2b63` to `WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL`, add `_BIDI_REMOTE` at `0x2b66`, and split the `WtConfig` fields so `initStreamRecvFc` and `initStreamSendFc` can pick based on the initiator. As a side effect `QmuxConnector::makeWtConfig` becomes a straight mapping of the QUIC transport params it was already reading, instead of discarding two of them. Reviewed By: hanidamlaj Differential Revision: D115270998 fbshipit-source-id: 0da72aa6eb1c184bf06f0f59b0c764fd2aa94e93
1 parent 7efda81 commit 5e0c56c

11 files changed

Lines changed: 140 additions & 43 deletions

File tree

proxygen/lib/http/codec/HTTP2Codec.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,8 @@ ErrorCode HTTP2Codec::handleSettings(const std::deque<SettingPair>& settings) {
762762
case SettingsId::WT_ENABLED:
763763
case SettingsId::WT_INITIAL_MAX_DATA:
764764
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI:
765-
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI:
765+
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
766+
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
766767
case SettingsId::WT_INITIAL_MAX_STREAMS_UNI:
767768
case SettingsId::WT_INITIAL_MAX_STREAMS_BIDI:
768769
break;
@@ -1455,7 +1456,8 @@ size_t HTTP2Codec::generateSettings(folly::IOBufQueue& writeBuf) {
14551456
case SettingsId::MAX_FRAME_SIZE:
14561457
case SettingsId::WT_INITIAL_MAX_DATA:
14571458
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI:
1458-
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI:
1459+
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
1460+
case SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
14591461
case SettingsId::WT_INITIAL_MAX_STREAMS_UNI:
14601462
case SettingsId::WT_INITIAL_MAX_STREAMS_BIDI:
14611463
break;

proxygen/lib/http/codec/SettingsId.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ enum class SettingsId : uint64_t {
2929
WT_ENABLED = 0x2b60,
3030
WT_INITIAL_MAX_DATA = 0x2b61,
3131
WT_INITIAL_MAX_STREAM_DATA_UNI = 0x2b62,
32-
WT_INITIAL_MAX_STREAM_DATA_BIDI = 0x2b63,
32+
WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL = 0x2b63,
3333
WT_INITIAL_MAX_STREAMS_UNI = 0x2b64,
3434
WT_INITIAL_MAX_STREAMS_BIDI = 0x2b65,
35+
WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE = 0x2b66,
3536

3637
// From HQ
3738
//_HQ_HEADER_TABLE_SIZE = HQ_SETTINGS_MASK | 1, -- use HEADER_TABLE_SIZE

proxygen/lib/http/codec/test/HTTP2CodecTest.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,8 @@ TEST_F(HTTP2CodecTest, BasicSetting) {
15191519
constexpr auto kWtFlowControlSettings =
15201520
std::array{SettingsId::WT_INITIAL_MAX_DATA,
15211521
SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI,
1522-
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI,
1522+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
1523+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
15231524
SettingsId::WT_INITIAL_MAX_STREAMS_UNI,
15241525
SettingsId::WT_INITIAL_MAX_STREAMS_BIDI};
15251526

@@ -1600,7 +1601,8 @@ TEST(HTTP2CodecWebTransportTest, SetsEgressH2WebTransportSettings) {
16001601
static constexpr auto kDefaultWtSettings = {
16011602
SettingsId::WT_INITIAL_MAX_DATA,
16021603
SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI,
1603-
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI,
1604+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
1605+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
16041606
SettingsId::WT_INITIAL_MAX_STREAMS_UNI,
16051607
SettingsId::WT_INITIAL_MAX_STREAMS_BIDI};
16061608

proxygen/lib/http/webtransport/QuicWtSession.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ WtStreamManager::WtConfig createQuicConfig() {
2222
config.selfMaxStreamsBidi = kMaxVarint;
2323
config.selfMaxStreamsUni = kMaxVarint;
2424
config.selfMaxConnData = kMaxVarint;
25-
config.selfMaxStreamDataBidi = kMaxWtIngressBuf;
25+
config.selfMaxStreamDataBidiLocal = kMaxWtIngressBuf;
26+
config.selfMaxStreamDataBidiRemote = kMaxWtIngressBuf;
2627
config.selfMaxStreamDataUni = kMaxWtIngressBuf;
2728
config.peerMaxStreamsBidi = kMaxVarint;
2829
config.peerMaxStreamsUni = kMaxVarint;
2930
config.peerMaxConnData = kMaxVarint;
30-
config.peerMaxStreamDataBidi = kMaxVarint;
31+
config.peerMaxStreamDataBidiLocal = kMaxVarint;
32+
config.peerMaxStreamDataBidiRemote = kMaxVarint;
3133
config.peerMaxStreamDataUni = kMaxVarint;
3234
return config;
3335
}

proxygen/lib/http/webtransport/WtStreamManager.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -745,13 +745,22 @@ bool WtStreamManager::hasEvent() const noexcept {
745745
}
746746

747747
uint64_t WtStreamManager::initStreamRecvFc(uint64_t streamId) const noexcept {
748-
return isBidi(streamId) ? wtConfig_.selfMaxStreamDataBidi
749-
: wtConfig_.selfMaxStreamDataUni;
748+
if (!isBidi(streamId)) {
749+
return wtConfig_.selfMaxStreamDataUni;
750+
}
751+
// our advertised limits are Local/Remote relative to us
752+
return isPeer(streamId) ? wtConfig_.selfMaxStreamDataBidiRemote
753+
: wtConfig_.selfMaxStreamDataBidiLocal;
750754
}
751755

752756
uint64_t WtStreamManager::initStreamSendFc(uint64_t streamId) const noexcept {
753-
return isBidi(streamId) ? wtConfig_.peerMaxStreamDataBidi
754-
: wtConfig_.peerMaxStreamDataUni;
757+
if (!isBidi(streamId)) {
758+
return wtConfig_.peerMaxStreamDataUni;
759+
}
760+
// the peer's limits are Local/Remote relative to the peer, so a stream the
761+
// peer opened is Local to them and one we opened is Remote to them
762+
return isPeer(streamId) ? wtConfig_.peerMaxStreamDataBidiLocal
763+
: wtConfig_.peerMaxStreamDataBidiRemote;
755764
}
756765

757766
void WtStreamManager::erase(uint64_t streamId) noexcept {

proxygen/lib/http/webtransport/WtStreamManager.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,21 @@ struct WtStreamManager {
106106

107107
struct WtConfig {
108108
static constexpr auto kDefaultFc = std::numeric_limits<uint16_t>::max();
109-
// values we've advertised to the peer
109+
// values we've advertised to the peer; Local/Remote denote which endpoint
110+
// opened the bidi stream the limit applies to, relative to the advertiser
110111
uint64_t selfMaxStreamsBidi{1};
111112
uint64_t selfMaxStreamsUni{1};
112113
uint64_t selfMaxConnData{kDefaultFc};
113-
uint64_t selfMaxStreamDataBidi{kDefaultFc};
114+
uint64_t selfMaxStreamDataBidiLocal{kDefaultFc};
115+
uint64_t selfMaxStreamDataBidiRemote{kDefaultFc};
114116
uint64_t selfMaxStreamDataUni{kDefaultFc};
115117

116118
// values peer has advertised to us
117119
uint64_t peerMaxStreamsBidi{1};
118120
uint64_t peerMaxStreamsUni{1};
119121
uint64_t peerMaxConnData{kDefaultFc};
120-
uint64_t peerMaxStreamDataBidi{kDefaultFc};
122+
uint64_t peerMaxStreamDataBidiLocal{kDefaultFc};
123+
uint64_t peerMaxStreamDataBidiRemote{kDefaultFc};
121124
uint64_t peerMaxStreamDataUni{kDefaultFc};
122125

123126
// move to a new struct options?

proxygen/lib/http/webtransport/WtUtils.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ void setEgressWtHttpSettings(TransportDirection dir,
7474
static constexpr auto kMaxDataSettings = {
7575
SettingsId::WT_INITIAL_MAX_DATA,
7676
SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI,
77-
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI};
77+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
78+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE};
7879
for (auto maxDataSetting : kMaxDataSettings) {
7980
settings->setIfNotPresent(maxDataSetting, kWtInitMaxData);
8081
}
@@ -115,8 +116,10 @@ WtStreamManager::WtConfig getWtConfig(const HTTPSettings* ingress,
115116
ingress->getSetting(SettingsId::WT_INITIAL_MAX_DATA, /*defaultVal=*/0);
116117
config.peerMaxStreamDataUni = ingress->getSetting(
117118
SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI, /*defaultVal=*/0);
118-
config.peerMaxStreamDataBidi = ingress->getSetting(
119-
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI, /*defaultVal=*/0);
119+
config.peerMaxStreamDataBidiLocal = ingress->getSetting(
120+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, /*defaultVal=*/0);
121+
config.peerMaxStreamDataBidiRemote = ingress->getSetting(
122+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, /*defaultVal=*/0);
120123
config.peerMaxStreamsUni =
121124
ingress->getSetting(SettingsId::WT_INITIAL_MAX_STREAMS_UNI,
122125
/*defaultVal=*/0);
@@ -129,8 +132,10 @@ WtStreamManager::WtConfig getWtConfig(const HTTPSettings* ingress,
129132
egress->getSetting(SettingsId::WT_INITIAL_MAX_DATA, /*defaultVal=*/0);
130133
config.selfMaxStreamDataUni = egress->getSetting(
131134
SettingsId::WT_INITIAL_MAX_STREAM_DATA_UNI, /*defaultVal=*/0);
132-
config.selfMaxStreamDataBidi = egress->getSetting(
133-
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI, /*defaultVal=*/0);
135+
config.selfMaxStreamDataBidiLocal = egress->getSetting(
136+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, /*defaultVal=*/0);
137+
config.selfMaxStreamDataBidiRemote = egress->getSetting(
138+
SettingsId::WT_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, /*defaultVal=*/0);
134139
config.selfMaxStreamsUni =
135140
egress->getSetting(SettingsId::WT_INITIAL_MAX_STREAMS_UNI,
136141
/*defaultVal=*/0);
@@ -139,13 +144,15 @@ WtStreamManager::WtConfig getWtConfig(const HTTPSettings* ingress,
139144
/*defaultVal=*/0);
140145
}
141146

142-
XLOG(DBG6) << config.selfMaxStreamsBidi << "; " << config.selfMaxStreamsUni
143-
<< "; " << config.selfMaxConnData << "; "
144-
<< config.selfMaxStreamDataBidi << "; "
145-
<< config.selfMaxStreamDataUni << "; " << config.peerMaxStreamsBidi
146-
<< "; " << config.peerMaxStreamsUni << "; "
147-
<< config.peerMaxConnData << "; " << config.peerMaxStreamDataBidi
148-
<< "; " << config.peerMaxStreamDataUni;
147+
XLOG(DBG6)
148+
<< config.selfMaxStreamsBidi << "; " << config.selfMaxStreamsUni << "; "
149+
<< config.selfMaxConnData << "; " << config.selfMaxStreamDataBidiLocal
150+
<< "; " << config.selfMaxStreamDataBidiRemote << "; "
151+
<< config.selfMaxStreamDataUni << "; " << config.peerMaxStreamsBidi
152+
<< "; " << config.peerMaxStreamsUni << "; " << config.peerMaxConnData
153+
<< "; " << config.peerMaxStreamDataBidiLocal << "; "
154+
<< config.peerMaxStreamDataBidiRemote << "; "
155+
<< config.peerMaxStreamDataUni;
149156

150157
return config;
151158
}
@@ -155,8 +162,10 @@ WtStreamManager::WtConfig getH3WtConfig(const HTTPSettings* ingress,
155162
WtStreamManager::WtConfig config = getWtConfig(ingress, egress);
156163
// disables peer&self MaxStreamData(Uni|Bidi) as these are derived from quic
157164
// transport params
158-
config.peerMaxStreamDataBidi = config.peerMaxStreamDataUni =
159-
config.selfMaxStreamDataBidi = config.selfMaxStreamDataUni = kMaxVarint;
165+
config.peerMaxStreamDataBidiLocal = config.peerMaxStreamDataBidiRemote =
166+
config.peerMaxStreamDataUni = config.selfMaxStreamDataBidiLocal =
167+
config.selfMaxStreamDataBidiRemote = config.selfMaxStreamDataUni =
168+
kMaxVarint;
160169
return config;
161170
}
162171

proxygen/lib/http/webtransport/test/WtStreamManagerTest.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -550,10 +550,11 @@ TEST(WtStreamManager, GrantConnFlowControlCreditAfterRead) {
550550
TEST(WtStreamManager, NonDefaultFlowControlValues) {
551551
WtConfig config{};
552552
config.peerMaxConnData = 100;
553-
config.peerMaxStreamDataBidi = config.peerMaxStreamDataUni = 60;
553+
config.peerMaxStreamDataBidiLocal = config.peerMaxStreamDataBidiRemote =
554+
config.peerMaxStreamDataUni = 60;
554555

555-
config.selfMaxConnData = config.selfMaxStreamDataBidi =
556-
config.selfMaxStreamDataUni = 100;
556+
config.selfMaxConnData = config.selfMaxStreamDataBidiLocal =
557+
config.selfMaxStreamDataBidiRemote = config.selfMaxStreamDataUni = 100;
557558
WtSmEgressCb egressCb;
558559
WtSmIngressCb ingressCb;
559560
auto priorityQueue = std::make_unique<quic::HTTPPriorityQueue>();
@@ -605,6 +606,60 @@ TEST(WtStreamManager, NonDefaultFlowControlValues) {
605606
EXPECT_FALSE(dequeue.fin);
606607
}
607608

609+
// Bidi stream data limits are Local/Remote relative to whoever advertised
610+
// them, so which limit applies depends on who opened the stream.
611+
TEST(WtStreamManager, BidiStreamDataLimitsFollowStreamInitiator) {
612+
constexpr uint64_t kSelfLocal = 50;
613+
constexpr uint64_t kSelfRemote = 90;
614+
constexpr uint64_t kPeerLocal = 30;
615+
constexpr uint64_t kPeerRemote = 70;
616+
constexpr uint64_t kNotTheLimit = 1000;
617+
618+
WtConfig config{};
619+
config.selfMaxStreamsBidi = config.peerMaxStreamsBidi = 4;
620+
config.selfMaxConnData = config.peerMaxConnData = kNotTheLimit;
621+
config.selfMaxStreamDataBidiLocal = kSelfLocal;
622+
config.selfMaxStreamDataBidiRemote = kSelfRemote;
623+
config.peerMaxStreamDataBidiLocal = kPeerLocal;
624+
config.peerMaxStreamDataBidiRemote = kPeerRemote;
625+
626+
WtSmEgressCb egressCb;
627+
WtSmIngressCb ingressCb;
628+
auto priorityQueue = std::make_unique<quic::HTTPPriorityQueue>();
629+
WtStreamManager streamManager{
630+
detail::WtDir::Client, config, egressCb, ingressCb, *priorityQueue};
631+
632+
auto selfBidi = streamManager.createBidiHandle(); // 0x00
633+
CHECK(selfBidi.readHandle && selfBidi.writeHandle);
634+
auto peerBidi = streamManager.getOrCreateBidiHandle(0x01);
635+
CHECK(peerBidi.readHandle && peerBidi.writeHandle);
636+
637+
// egress is bounded by the peer's limits: the stream we opened is Remote to
638+
// the peer, the one it opened is Local to it
639+
constexpr auto kMoreThanAnyLimit = 200;
640+
constexpr auto kNoCap = std::numeric_limits<uint64_t>::max();
641+
selfBidi.writeHandle->writeStreamData(
642+
makeBuf(kMoreThanAnyLimit), /*fin=*/false, /*byteEventCallback=*/nullptr);
643+
auto dequeued = streamManager.dequeue(*selfBidi.writeHandle, kNoCap);
644+
EXPECT_EQ(dequeued.data->computeChainDataLength(), kPeerRemote);
645+
646+
peerBidi.writeHandle->writeStreamData(
647+
makeBuf(kMoreThanAnyLimit), /*fin=*/false, /*byteEventCallback=*/nullptr);
648+
dequeued = streamManager.dequeue(*peerBidi.writeHandle, kNoCap);
649+
EXPECT_EQ(dequeued.data->computeChainDataLength(), kPeerLocal);
650+
651+
// ingress is bounded by our own limits, mirrored: the stream we opened is
652+
// Local to us
653+
EXPECT_TRUE(streamManager.enqueue(*selfBidi.readHandle,
654+
{makeBuf(kSelfLocal), /*fin=*/false}));
655+
EXPECT_FALSE(
656+
streamManager.enqueue(*selfBidi.readHandle, {makeBuf(1), /*fin=*/false}));
657+
EXPECT_TRUE(streamManager.enqueue(*peerBidi.readHandle,
658+
{makeBuf(kSelfRemote), /*fin=*/false}));
659+
EXPECT_FALSE(
660+
streamManager.enqueue(*peerBidi.readHandle, {makeBuf(1), /*fin=*/false}));
661+
}
662+
608663
TEST(WtStreamManager, ResetStreamReleasesConnFlowControl) {
609664
WtConfig config{.selfMaxStreamsUni = 10};
610665
WtSmEgressCb egressCb;

proxygen/lib/transport/qmux/QmuxConnector.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,14 @@ WtStreamManager::WtConfig makeWtConfig(
192192
.selfMaxStreamsBidi = selfParams.initialMaxStreamsBidi,
193193
.selfMaxStreamsUni = selfParams.initialMaxStreamsUni,
194194
.selfMaxConnData = selfParams.initialMaxData,
195-
.selfMaxStreamDataBidi = selfParams.initialMaxStreamDataBidiLocal,
195+
.selfMaxStreamDataBidiLocal = selfParams.initialMaxStreamDataBidiLocal,
196+
.selfMaxStreamDataBidiRemote = selfParams.initialMaxStreamDataBidiRemote,
196197
.selfMaxStreamDataUni = selfParams.initialMaxStreamDataUni,
197198
.peerMaxStreamsBidi = peerParams.initialMaxStreamsBidi,
198199
.peerMaxStreamsUni = peerParams.initialMaxStreamsUni,
199200
.peerMaxConnData = peerParams.initialMaxData,
200-
.peerMaxStreamDataBidi = peerParams.initialMaxStreamDataBidiRemote,
201+
.peerMaxStreamDataBidiLocal = peerParams.initialMaxStreamDataBidiLocal,
202+
.peerMaxStreamDataBidiRemote = peerParams.initialMaxStreamDataBidiRemote,
201203
.peerMaxStreamDataUni = peerParams.initialMaxStreamDataUni};
202204
}
203205

proxygen/lib/transport/qmux/test/QmuxConnectorTest.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,15 @@ TEST(MakeWtConfigTest, MapsParamsCorrectly) {
163163

164164
EXPECT_EQ(cfg.selfMaxStreamsBidi, self.initialMaxStreamsBidi);
165165
EXPECT_EQ(cfg.selfMaxConnData, self.initialMaxData);
166-
EXPECT_EQ(cfg.selfMaxStreamDataBidi, self.initialMaxStreamDataBidiLocal);
166+
EXPECT_EQ(cfg.selfMaxStreamDataBidiLocal, self.initialMaxStreamDataBidiLocal);
167+
EXPECT_EQ(cfg.selfMaxStreamDataBidiRemote,
168+
self.initialMaxStreamDataBidiRemote);
167169
EXPECT_EQ(cfg.selfMaxStreamDataUni, self.initialMaxStreamDataUni);
168170
EXPECT_EQ(cfg.peerMaxStreamsBidi, peer.initialMaxStreamsBidi);
169171
EXPECT_EQ(cfg.peerMaxConnData, peer.initialMaxData);
170-
EXPECT_EQ(cfg.peerMaxStreamDataBidi, peer.initialMaxStreamDataBidiRemote);
172+
EXPECT_EQ(cfg.peerMaxStreamDataBidiLocal, peer.initialMaxStreamDataBidiLocal);
173+
EXPECT_EQ(cfg.peerMaxStreamDataBidiRemote,
174+
peer.initialMaxStreamDataBidiRemote);
171175
EXPECT_EQ(cfg.peerMaxStreamDataUni, peer.initialMaxStreamDataUni);
172176
}
173177

0 commit comments

Comments
 (0)