Skip to content

Commit b25dd66

Browse files
authored
fix(sidecar): rename P2P kv_transfer_params sub-dict keys to match vLLM (llm-d#2140)
* fix(sidecar): rename P2P kv_transfer_params sub-dict keys to match vLLM The OffloadingConnector P2P branch renamed the request-level sub-dict keys for clarity (liranschour/vllm@530fa0d7 + @5bcf5b31): "prefill" -> "remote_prefiller", "decode" -> "remote_decoder", "p2p" -> "remote_kv_source", each named for the remote party it describes. Inner fields (kv_request_id, remote_host, remote_port) and the secondary-tier type "p2p" are unchanged. A sidecar emitting the old keys against a renamed engine is silently inert - the engine ignores unknown sub-dicts and every request recomputes - so the sidecar and engine must move together. Signed-off-by: nilig <nili.ifergan@gmail.com> * docs: wrap the renamed disaggregation paragraphs at 80 columns Review feedback on llm-d#2140: the two protocol paragraphs were single long lines; wrapped for reviewable diffs. No content change. Signed-off-by: nilig <nili.ifergan@gmail.com> * fix(sidecar): sweep stale p2p key references from comments and specs The kv_transfer_params nesting key is remote_kv_source; comments and test descriptions that still call it the p2p key or p2p params read as if the secondary-tier type (p2p, unchanged) were the request-field key. Signed-off-by: nilig <nili.ifergan@gmail.com> * refactor(sidecar): name request-field constants after their wire keys The requestFieldP2P* constants held remote_* wire keys, so the names no longer described the values. Naming them for their values matches the sibling request-field constants and leaves P2P to name only the OffloadingConnector tier and its protocol functions. Also sweeps test comments and one spec title that still named the sub-dicts by the old decode/prefill/p2p keys. Signed-off-by: nilig <nili.ifergan@gmail.com> --------- Signed-off-by: nilig <nili.ifergan@gmail.com>
1 parent 26df3f1 commit b25dd66

7 files changed

Lines changed: 78 additions & 53 deletions

File tree

docs/disaggregation.md

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,30 @@ Specifies which KV transfer protocol the sidecar uses to coordinate prefill/deco
539539
| `mooncake` | `MooncakeConnector` | [Mooncake](https://github.com/kvcache-ai/Mooncake) KV transfer using RDMA |
540540
| `offloading` | `OffloadingConnector` | KV transfer over the vLLM CPU offloading tier. The decoder pulls KV from the prefiller via the `p2p` secondary tier. |
541541

542-
With `offloading`, the sidecar dispatches prefill and decode concurrently. It injects role-keyed `kv_transfer_params`: the prefiller receives `{"decode": {"kv_request_id": <id>}}` (no peer address), and the decoder receives `{"prefill": {"kv_request_id": <id>, "remote_host": <prefiller host>, "remote_port": <p2p-connector-port>}}` so it can pull KV from the prefiller. The prefiller host comes from the `x-prefiller-host-port` header; the port is `--p2p-connector-port`.
543-
544-
When the request also carries the `x-kv-cache-source-host-port` header (set by the EPP `p2p-source-producer` to a peer holding more cached prefix than the pod computing the prefix), the sidecar injects an additional `p2p` key so vLLM pulls that cached prefix over the P2P tier instead of recomputing it. Under disaggregation the prefiller leg carries `{"decode": {...}, "p2p": {"kv_request_id": <own id>, "remote_host": <source host>, "remote_port": <p2p-connector-port>}}` (the only supported multi-key combination); without a prefiller the decoder-only request carries `{"p2p": {...}}` alone. A malformed or disallowed source header is ignored and the request proceeds unchanged, as is any source header on a connector that cannot pull over the P2P tier: only `offloading`, or NIXLv2 with `--enable-p2p-pull`, honors it. For the pulled blocks to be servable, the source pod must offload its generated (decode-phase) KV: set `offload_prompt_only: false` in its `kv_connector_extra_config` (the default `true` offloads only prefill blocks).
542+
With `offloading`, the sidecar dispatches prefill and decode concurrently. It
543+
injects role-keyed `kv_transfer_params`, each key named for the remote party it
544+
describes: the prefiller receives `{"remote_decoder": {"kv_request_id": <id>}}`
545+
(no peer address), and the decoder receives `{"remote_prefiller":
546+
{"kv_request_id": <id>, "remote_host": <prefiller host>, "remote_port":
547+
<p2p-connector-port>}}` so it can pull KV from the prefiller. The prefiller host
548+
comes from the `x-prefiller-host-port` header; the port is
549+
`--p2p-connector-port`.
550+
551+
When the request also carries the `x-kv-cache-source-host-port` header (set by
552+
the EPP `p2p-source-producer` to a peer holding more cached prefix than the pod
553+
computing the prefix), the sidecar injects an additional `remote_kv_source` key
554+
so vLLM pulls that cached prefix over the P2P tier instead of recomputing it.
555+
Under disaggregation the prefiller leg carries `{"remote_decoder": {...},
556+
"remote_kv_source": {"kv_request_id": <own id>, "remote_host": <source host>,
557+
"remote_port": <p2p-connector-port>}}` (the only supported multi-key
558+
combination); without a prefiller the decoder-only request carries
559+
`{"remote_kv_source": {...}}` alone. A malformed or disallowed source header is
560+
ignored and the request proceeds unchanged, as is any source header on a
561+
connector that cannot pull over the P2P tier: only `offloading`, or NIXLv2 with
562+
`--enable-p2p-pull`, honors it. For the pulled blocks to be servable, the source
563+
pod must offload its generated (decode-phase) KV: set `offload_prompt_only:
564+
false` in its `kv_connector_extra_config` (the default `true` offloads only
565+
prefill blocks).
545566

546567
Both prefill and decode pods require the following `--kv-transfer-config`:
547568

pkg/sidecar/proxy/connector_nixlv2_p2p_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ var _ = Describe("NIXL Connector with P2P pull", func() {
103103
// NIXL fields still drive the NixlConnector under MultiConnector.
104104
Expect(kv).To(HaveKeyWithValue(requestFieldDoRemoteDecode, true))
105105
Expect(kv).To(HaveKeyWithValue(requestFieldDoRemotePrefill, false))
106-
// The p2p block drives the OffloadingConnector's cached-prefix pull.
107-
p2p, ok := kv[requestFieldP2PParams].(map[string]any)
106+
// The remote_kv_source block drives the OffloadingConnector's cached-prefix pull.
107+
p2p, ok := kv[requestFieldRemoteKVSource].(map[string]any)
108108
Expect(ok).To(BeTrue())
109109
Expect(p2p[requestFieldKVRequestID]).ToNot(BeEmpty())
110110
Expect(p2p[requestFieldRemoteHost]).To(Equal("10.9.9.9"))
@@ -120,7 +120,7 @@ var _ = Describe("NIXL Connector with P2P pull", func() {
120120
routing.KVCacheSourceHeader: kvCacheSource,
121121
})
122122

123-
Expect(prefillKV()).ToNot(HaveKey(requestFieldP2PParams))
123+
Expect(prefillKV()).ToNot(HaveKey(requestFieldRemoteKVSource))
124124
})
125125

126126
It("does not compose a p2p pull when the source is the prefiller itself", func() {
@@ -133,7 +133,7 @@ var _ = Describe("NIXL Connector with P2P pull", func() {
133133
routing.KVCacheSourceHeader: prefillHostPort,
134134
})
135135

136-
Expect(prefillKV()).ToNot(HaveKey(requestFieldP2PParams))
136+
Expect(prefillKV()).ToNot(HaveKey(requestFieldRemoteKVSource))
137137
})
138138

139139
// The parallel-dispatch (MoRI-IO WRITE) path builds the prefill leg in a
@@ -157,10 +157,10 @@ var _ = Describe("NIXL Connector with P2P pull", func() {
157157
body, _ := io.ReadAll(resp.Body) //nolint:errcheck
158158
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
159159

160-
// Prefill leg keeps the NIXL WRITE fields and gains the composed p2p block.
160+
// Prefill leg keeps the NIXL WRITE fields and gains the composed remote_kv_source block.
161161
pkv := kvParams(env.prefillHandler, 0)
162162
Expect(pkv).To(HaveKeyWithValue(requestFieldDoRemoteDecode, true))
163-
p2p, ok := pkv[requestFieldP2PParams].(map[string]any)
163+
p2p, ok := pkv[requestFieldRemoteKVSource].(map[string]any)
164164
Expect(ok).To(BeTrue())
165165
Expect(p2p[requestFieldRemoteHost]).To(Equal("10.9.9.9"))
166166
Expect(p2p[requestFieldRemotePort]).To(BeNumerically("==", p2pConnectorPort))

pkg/sidecar/proxy/connector_p2p.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (s *Server) handleP2P(w http.ResponseWriter, r *http.Request, prefillPodHos
6969
prefillData[k] = v
7070
}
7171
prefillKVParams := map[string]any{
72-
requestFieldP2PDecodeParams: map[string]any{
72+
requestFieldRemoteDecoder: map[string]any{
7373
requestFieldKVRequestID: kvRequestID,
7474
},
7575
}
@@ -95,7 +95,7 @@ func (s *Server) handleP2P(w http.ResponseWriter, r *http.Request, prefillPodHos
9595
decodeData[k] = v
9696
}
9797
decodeData[requestFieldKVTransferParams] = map[string]any{
98-
requestFieldP2PPrefillParams: map[string]any{
98+
requestFieldRemotePrefiller: map[string]any{
9999
requestFieldKVRequestID: kvRequestID,
100100
requestFieldRemoteHost: extractHost(prefillPodHostPort),
101101
requestFieldRemotePort: s.config.P2PConnectorPort,
@@ -213,27 +213,28 @@ func (s *Server) handleP2PConcurrentRequests(w http.ResponseWriter, r *http.Requ
213213
// KVConnector is offloading, or is composed alongside NIXL via MultiConnector
214214
// (declared with --enable-p2p-pull) when the PD connector is NIXLv2. On any
215215
// other connector --enable-p2p-pull has no effect, since no MultiConnector
216-
// routes the p2p params to an OffloadingConnector.
216+
// routes the remote_kv_source params to an OffloadingConnector.
217217
func (s *Server) p2pPullAvailable() bool {
218218
return s.config.KVConnector == KVConnectorOffloading ||
219219
(s.config.EnableP2PPull && s.config.KVConnector == KVConnectorNIXLV2)
220220
}
221221

222-
// addP2PPullToPrefill adds the OffloadingConnector p2p pull block to a prefill
222+
// addP2PPullToPrefill adds the OffloadingConnector P2P pull block to a prefill
223223
// leg's kv_transfer_params so the prefiller pulls cached prefix from
224224
// kvCacheSource while keeping its own computed blocks available for the
225225
// decoder. It is a no-op when no source is set or the source resolves to the
226-
// prefiller itself, since there is nothing to pull from oneself. The p2p key
227-
// composes with NIXL params: vLLM's MultiConnector routes it to the
228-
// OffloadingConnector and the NIXL fields to the NixlConnector.
226+
// prefiller itself, since there is nothing to pull from oneself. The
227+
// remote_kv_source key composes with NIXL params: vLLM's MultiConnector
228+
// routes it to the OffloadingConnector and the NIXL fields to the
229+
// NixlConnector.
229230
func (s *Server) addP2PPullToPrefill(prefillKVParams map[string]any, kvCacheSource, prefillPodHostPort string) {
230231
if kvCacheSource != "" && extractHost(kvCacheSource) != extractHost(prefillPodHostPort) {
231-
prefillKVParams[requestFieldP2PParams] = s.p2pSourceParams(kvCacheSource)
232+
prefillKVParams[requestFieldRemoteKVSource] = s.p2pSourceParams(kvCacheSource)
232233
}
233234
}
234235

235-
// p2pSourceParams builds the kv_transfer_params.p2p block for a pull from
236-
// sourceHostPort's OffloadingConnector P2P tier. The kv_request_id is its
236+
// p2pSourceParams builds the kv_transfer_params.remote_kv_source block for a
237+
// pull from sourceHostPort's OffloadingConnector P2P tier. The kv_request_id is its
237238
// own fresh UUID: in P2P mode it is consumer-side only.
238239
func (s *Server) p2pSourceParams(sourceHostPort string) map[string]any {
239240
return map[string]any{
@@ -244,7 +245,7 @@ func (s *Server) p2pSourceParams(sourceHostPort string) map[string]any {
244245
}
245246

246247
// decodeWithP2PSource serves a decoder-only request through the local vLLM
247-
// with kv_transfer_params.p2p injected, so the engine looks up and pulls
248+
// with kv_transfer_params.remote_kv_source injected, so the engine looks up and pulls
248249
// cached prefix blocks from the peer at sourceHostPort instead of recomputing
249250
// them. It replaces any client-supplied kv_transfer_params (the sidecar owns
250251
// that field) and routes through dispatchDecode so chunked decode still
@@ -266,7 +267,7 @@ func (s *Server) decodeWithP2PSource(w http.ResponseWriter, r *http.Request, sou
266267
p2pParams := s.p2pSourceParams(sourceHostPort)
267268
// Rebuild kv_transfer_params from scratch: the sidecar owns this field, so
268269
// client-supplied keys are dropped rather than forwarded to vLLM.
269-
requestData[requestFieldKVTransferParams] = map[string]any{requestFieldP2PParams: p2pParams}
270+
requestData[requestFieldKVTransferParams] = map[string]any{requestFieldRemoteKVSource: p2pParams}
270271

271272
s.logger.Info("running P2P source protocol",
272273
"source_host", extractHost(sourceHostPort),

pkg/sidecar/proxy/connector_p2p_source_test.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ var _ = Describe("P2P KV cache source header", func() {
7373
return sendBody(proxyBaseAddr, chatCompletionsRequestBodyWithMaxCompletionTokens, headers)
7474
}
7575

76-
It("should inject p2p params on the local request without disaggregation", func() {
76+
It("should inject remote_kv_source params on the local request without disaggregation", func() {
7777
proxyBaseAddr := testInfo.startProxy()
7878

7979
sendRequest(proxyBaseAddr, map[string]string{routing.KVCacheSourceHeader: kvCacheSource})
@@ -84,9 +84,9 @@ var _ = Describe("P2P KV cache source header", func() {
8484

8585
kvParams, ok := dreq[requestFieldKVTransferParams].(map[string]any)
8686
Expect(ok).To(BeTrue())
87-
Expect(kvParams).ToNot(HaveKey(requestFieldP2PDecodeParams))
88-
Expect(kvParams).ToNot(HaveKey(requestFieldP2PPrefillParams))
89-
p2p, ok := kvParams[requestFieldP2PParams].(map[string]any)
87+
Expect(kvParams).ToNot(HaveKey(requestFieldRemoteDecoder))
88+
Expect(kvParams).ToNot(HaveKey(requestFieldRemotePrefiller))
89+
p2p, ok := kvParams[requestFieldRemoteKVSource].(map[string]any)
9090
Expect(ok).To(BeTrue())
9191
Expect(p2p[requestFieldKVRequestID]).ToNot(BeEmpty())
9292
Expect(p2p[requestFieldRemoteHost]).To(Equal("10.9.9.9"))
@@ -99,7 +99,7 @@ var _ = Describe("P2P KV cache source header", func() {
9999
<-testInfo.stoppedCh
100100
})
101101

102-
It("should add p2p params to the prefill leg under disaggregation", func() {
102+
It("should add remote_kv_source params to the prefill leg under disaggregation", func() {
103103
proxyBaseAddr := testInfo.startProxy()
104104

105105
prefillHostPort := testInfo.prefillBackend.URL[len("http://"):]
@@ -112,37 +112,38 @@ var _ = Describe("P2P KV cache source header", func() {
112112
return len(testInfo.prefillHandler.GetCompletionRequests())
113113
}).Should(Equal(1))
114114

115-
// Prefill leg: decode + p2p, each with its own kv_request_id.
115+
// Prefill leg: remote_decoder + remote_kv_source, each with its own
116+
// kv_request_id.
116117
preq := testInfo.prefillHandler.GetCompletionRequests()[0]
117118
prefillKVParams, ok := preq[requestFieldKVTransferParams].(map[string]any)
118119
Expect(ok).To(BeTrue())
119-
decodeParams, ok := prefillKVParams[requestFieldP2PDecodeParams].(map[string]any)
120+
decodeParams, ok := prefillKVParams[requestFieldRemoteDecoder].(map[string]any)
120121
Expect(ok).To(BeTrue())
121-
p2p, ok := prefillKVParams[requestFieldP2PParams].(map[string]any)
122+
p2p, ok := prefillKVParams[requestFieldRemoteKVSource].(map[string]any)
122123
Expect(ok).To(BeTrue())
123124
Expect(p2p[requestFieldKVRequestID]).ToNot(BeEmpty())
124125
Expect(p2p[requestFieldKVRequestID]).ToNot(Equal(decodeParams[requestFieldKVRequestID]))
125126
Expect(p2p[requestFieldRemoteHost]).To(Equal("10.9.9.9"))
126127
Expect(p2p[requestFieldRemotePort]).To(BeNumerically("==", p2pConnectorPort))
127128

128-
// Decode leg: prefill only, never prefill + p2p.
129+
// Decode leg: remote_prefiller only, never remote_kv_source.
129130
decodeReqs := testInfo.decodeHandler.GetCompletionRequests()
130131
Expect(decodeReqs).To(HaveLen(1))
131132
decodeKVParams, ok := decodeReqs[0][requestFieldKVTransferParams].(map[string]any)
132133
Expect(ok).To(BeTrue())
133-
Expect(decodeKVParams).To(HaveKey(requestFieldP2PPrefillParams))
134-
Expect(decodeKVParams).ToNot(HaveKey(requestFieldP2PParams))
134+
Expect(decodeKVParams).To(HaveKey(requestFieldRemotePrefiller))
135+
Expect(decodeKVParams).ToNot(HaveKey(requestFieldRemoteKVSource))
135136

136137
testInfo.cancelFn()
137138
<-testInfo.stoppedCh
138139
})
139140

140-
It("should not add p2p to the prefill leg when the source is the prefiller itself", func() {
141+
It("should not add remote_kv_source params to the prefill leg when the source is the prefiller itself", func() {
141142
proxyBaseAddr := testInfo.startProxy()
142143

143144
prefillHostPort := testInfo.prefillBackend.URL[len("http://"):]
144145
// The source resolves to the selected prefiller - there is nothing to
145-
// pull from itself, so the prefill leg carries decode only.
146+
// pull from itself, so the prefill leg carries remote_decoder only.
146147
sendRequest(proxyBaseAddr, map[string]string{
147148
routing.PrefillEndpointHeader: prefillHostPort,
148149
routing.KVCacheSourceHeader: prefillHostPort,
@@ -155,14 +156,14 @@ var _ = Describe("P2P KV cache source header", func() {
155156
preq := testInfo.prefillHandler.GetCompletionRequests()[0]
156157
prefillKVParams, ok := preq[requestFieldKVTransferParams].(map[string]any)
157158
Expect(ok).To(BeTrue())
158-
Expect(prefillKVParams).To(HaveKey(requestFieldP2PDecodeParams))
159-
Expect(prefillKVParams).ToNot(HaveKey(requestFieldP2PParams))
159+
Expect(prefillKVParams).To(HaveKey(requestFieldRemoteDecoder))
160+
Expect(prefillKVParams).ToNot(HaveKey(requestFieldRemoteKVSource))
160161

161162
testInfo.cancelFn()
162163
<-testInfo.stoppedCh
163164
})
164165

165-
It("should not inject p2p params without the header", func() {
166+
It("should not inject remote_kv_source params without the header", func() {
166167
proxyBaseAddr := testInfo.startProxy()
167168

168169
sendRequest(proxyBaseAddr, nil)
@@ -198,9 +199,9 @@ var _ = Describe("P2P KV cache source header", func() {
198199
Expect(decodeReqs).To(HaveLen(1))
199200
kvParams, ok := decodeReqs[0][requestFieldKVTransferParams].(map[string]any)
200201
Expect(ok).To(BeTrue())
201-
// Only the sidecar-owned p2p key survives; the client's keys are gone.
202+
// Only the sidecar-owned remote_kv_source key survives; the client's keys are gone.
202203
Expect(kvParams).To(HaveLen(1))
203-
p2p, ok := kvParams[requestFieldP2PParams].(map[string]any)
204+
p2p, ok := kvParams[requestFieldRemoteKVSource].(map[string]any)
204205
Expect(ok).To(BeTrue())
205206
Expect(p2p[requestFieldRemoteHost]).To(Equal("10.9.9.9"))
206207

@@ -221,7 +222,7 @@ var _ = Describe("P2P KV cache source header", func() {
221222
<-testInfo.stoppedCh
222223
})
223224

224-
It("should not inject p2p params when the source is the local pod", func() {
225+
It("should not inject remote_kv_source params when the source is the local pod", func() {
225226
GinkgoT().Setenv("POD_IP", "10.9.9.9")
226227
proxyBaseAddr := testInfo.startProxy()
227228

@@ -247,7 +248,7 @@ var _ = Describe("P2P KV cache source header", func() {
247248
for _, dreq := range decodeReqs {
248249
kvParams, ok := dreq[requestFieldKVTransferParams].(map[string]any)
249250
Expect(ok).To(BeTrue())
250-
p2p, ok := kvParams[requestFieldP2PParams].(map[string]any)
251+
p2p, ok := kvParams[requestFieldRemoteKVSource].(map[string]any)
251252
Expect(ok).To(BeTrue())
252253
ids = append(ids, p2p[requestFieldKVRequestID])
253254
}

pkg/sidecar/proxy/connector_p2p_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ var _ = Describe("P2P Connector", func() {
6060
return len(testInfo.prefillHandler.GetCompletionRequests())
6161
}).Should(Equal(1))
6262

63-
// Prefill leg: kv_transfer_params.decode carries only kv_request_id,
63+
// Prefill leg: kv_transfer_params.remote_decoder carries only kv_request_id,
6464
// with no peer address.
6565
prefillReqs := testInfo.prefillHandler.GetCompletionRequests()
6666
Expect(prefillReqs).To(HaveLen(1))
@@ -69,8 +69,8 @@ var _ = Describe("P2P Connector", func() {
6969
Expect(preq).To(HaveKey(requestFieldKVTransferParams))
7070
prefillKVParams, ok := preq[requestFieldKVTransferParams].(map[string]any)
7171
Expect(ok).To(BeTrue())
72-
Expect(prefillKVParams).ToNot(HaveKey(requestFieldP2PPrefillParams))
73-
prefillDecode, ok := prefillKVParams[requestFieldP2PDecodeParams].(map[string]any)
72+
Expect(prefillKVParams).ToNot(HaveKey(requestFieldRemotePrefiller))
73+
prefillDecode, ok := prefillKVParams[requestFieldRemoteDecoder].(map[string]any)
7474
Expect(ok).To(BeTrue())
7575
prefillKVRequestID := prefillDecode[requestFieldKVRequestID]
7676
Expect(prefillKVRequestID).ToNot(BeEmpty())
@@ -82,7 +82,7 @@ var _ = Describe("P2P Connector", func() {
8282
Expect(preq).To(HaveKeyWithValue(requestFieldMaxCompletionTokens, BeNumerically("==", 1)))
8383
Expect(preq[requestFieldStream]).To(BeFalse())
8484

85-
// Decode leg: kv_transfer_params.prefill carries the prefiller's
85+
// Decode leg: kv_transfer_params.remote_prefiller carries the prefiller's
8686
// OffloadingConnector P2P tier address plus the matching kv_request_id.
8787
Expect(testInfo.decodeHandler.RequestCount.Load()).To(BeNumerically("==", 1))
8888
decodeReqs := testInfo.decodeHandler.GetCompletionRequests()
@@ -92,8 +92,8 @@ var _ = Describe("P2P Connector", func() {
9292
Expect(dreq).To(HaveKey(requestFieldKVTransferParams))
9393
decodeKVParams, ok := dreq[requestFieldKVTransferParams].(map[string]any)
9494
Expect(ok).To(BeTrue())
95-
Expect(decodeKVParams).ToNot(HaveKey(requestFieldP2PDecodeParams))
96-
decodePrefill, ok := decodeKVParams[requestFieldP2PPrefillParams].(map[string]any)
95+
Expect(decodeKVParams).ToNot(HaveKey(requestFieldRemoteDecoder))
96+
decodePrefill, ok := decodeKVParams[requestFieldRemotePrefiller].(map[string]any)
9797
Expect(ok).To(BeTrue())
9898
Expect(decodePrefill[requestFieldKVRequestID]).To(Equal(prefillKVRequestID))
9999
Expect(decodePrefill[requestFieldRemoteHost]).To(Equal(extractHost(prefillHostPort)))

pkg/sidecar/proxy/proxy.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,13 @@ const (
9292
requestFieldRemoteBootstrapAddr = "remote_bootstrap_addr"
9393

9494
// OffloadingConnector kv_transfer_params fields. The role is encoded by the
95-
// nesting key: "decode" on the prefiller leg, "prefill" on the decoder leg.
96-
requestFieldP2PDecodeParams = "decode"
97-
requestFieldP2PPrefillParams = "prefill"
98-
requestFieldP2PParams = "p2p"
99-
requestFieldKVRequestID = "kv_request_id"
95+
// nesting key, named for the remote party it describes: "remote_decoder" on
96+
// the prefiller leg, "remote_prefiller" on the decoder leg, "remote_kv_source"
97+
// for a symmetric cached-prefix pull.
98+
requestFieldRemoteDecoder = "remote_decoder"
99+
requestFieldRemotePrefiller = "remote_prefiller"
100+
requestFieldRemoteKVSource = "remote_kv_source"
101+
requestFieldKVRequestID = "kv_request_id"
100102

101103
KVConnectorNIXLV2 = constants.KVConnectorNIXLV2
102104
KVConnectorSharedStorage = constants.KVConnectorSharedStorage

release-notes.d/unreleased/1937.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ url: https://github.com/llm-d/llm-d-router/pull/1937
44
author: nilig
55
date: 2026-07-14
66
---
7-
The routing sidecar honors the `x-kv-cache-source-host-port` header, injecting `kv_transfer_params.p2p` so vLLM pulls cached prefix KV from the named peer over the OffloadingConnector P2P tier instead of recomputing it.
7+
The routing sidecar honors the `x-kv-cache-source-host-port` header, injecting `kv_transfer_params.remote_kv_source` so vLLM pulls cached prefix KV from the named peer over the OffloadingConnector P2P tier instead of recomputing it.

0 commit comments

Comments
 (0)