Re: [PATCH] Drivers: hv: vmbus: add VTL2 redirect connection ID
Saurabh Singh Sengar <[email protected]> Thu, 16 Jul 2026 08:21:36 -0700
| Newsgroups | org.kernel.vger.linux-hyperv,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <alj3AOAXk47fQx4m@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net> |
On Tue, Jul 14, 2026 at 09:38:38PM +0000, Hardik Garg wrote: > VMBus sends CHANNELMSG_INITIATE_CONTACT through a Hyper-V message > connection ID. Older protocol versions use VMBUS_MESSAGE_CONNECTION_ID, > while protocol version 5.0 and newer normally use > VMBUS_MESSAGE_CONNECTION_ID_4. > > When the Linux VMBus driver runs at VTL2, the VMBus control plane may > be reached through a VMBus relay instead of the standard host endpoint. > In that setup the relay listens on the redirect message connection ID, > and an Initiate Contact message sent to the standard ID is not delivered > to the control plane. > > The connection ID selects the Hyper-V message port used to reach the > VMBus control plane. If Linux uses the wrong port, the host does not > receive the Initiate Contact message. > > For Linux running at VTL2 with VMBus protocol 5.0 or newer, try the > redirect connection ID first. In VTL2, the redirect connection ID is the > VMBus relay endpoint. If the relay is present, it accepts Initiate > Contact and completes the normal version-response handshake. Systems > without the relay reject the redirect ID synchronously with > HV_STATUS_INVALID_CONNECTION_ID, allowing fallback to > VMBUS_MESSAGE_CONNECTION_ID_4. > > Return a distinct error for an invalid Initiate Contact connection ID so > this fallback does not mask other post-message failures or > protocol-version rejections. For older protocol versions, and for Linux > below VTL2, keep the existing connection ID selection. > > Signed-off-by: Hardik Garg <[email protected]> > --- > drivers/hv/connection.c | 76 ++++++++++++++++++++++++++++++++++++++++------- > drivers/hv/hyperv_vmbus.h | 2 ++ > 2 files changed, 67 insertions(+), 11 deletions(-) > > diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c > index 1fe3573ae52a4..eb871f87a819d 100644 > --- a/drivers/hv/connection.c > +++ b/drivers/hv/connection.c > @@ -71,7 +71,19 @@ module_param(max_version, uint, S_IRUGO); > MODULE_PARM_DESC(max_version, > "Maximal VMBus protocol version which can be negotiated"); > > -int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) > +/* Connection IDs to try for VTL2 VMBus protocol 5.0 and newer. */ > +static const u32 connection_ids[] = { Do we want to name it vtl2_connection_ids ? > + VMBUS_MESSAGE_CONNECTION_ID_REDIRECT, > + VMBUS_MESSAGE_CONNECTION_ID_4, > +}; > + > +/* > + * Send one CHANNELMSG_INITIATE_CONTACT attempt. > + * The caller supplies the message connection ID and owns retry/fallback > + * policy. > + */ > +static int vmbus_try_connection_id(struct vmbus_channel_msginfo *msginfo, > + u32 version, u32 connection_id) > { > int ret = 0; > struct vmbus_channel_initiate_contact *msg; > @@ -87,7 +99,7 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) > > /* > * VMBus protocol 5.0 (VERSION_WIN10_V5) and higher require that we must > - * use VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate Contact Message, > + * use connection_id for the Initiate Contact Message, > * and for subsequent messages, we must use the Message Connection ID > * field in the host-returned Version Response Message. And, with > * VERSION_WIN10_V5 and higher, we don't use msg->interrupt_page, but we > @@ -99,7 +111,7 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) > if (version >= VERSION_WIN10_V5) { > msg->msg_sint = VMBUS_MESSAGE_SINT; > msg->msg_vtl = ms_hyperv.vtl; > - vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4; > + vmbus_connection.msg_conn_id = connection_id; > } else { > msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); > vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID; > @@ -161,6 +173,51 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) > return ret; > } > > +/* > + * Negotiate the given VMBus protocol version with the host. > + * Protocol-specific connection ID policy is handled here so the single-try > + * helper stays simple. > + */ > +int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) > +{ > + int ret; > + size_t j; > + > + /* > + * The redirect ID is not a speculative endpoint. If the VMBus relay is > + * present, it accepts INITIATE_CONTACT and completes the normal version > + * response. Systems without the relay reject the ID synchronously, so > + * negotiation falls back to VMBUS_MESSAGE_CONNECTION_ID_4. > + */ > + if (version >= VERSION_WIN10_V5 && ms_hyperv.vtl >= 2) { > + for (j = 0; j < ARRAY_SIZE(connection_ids); j++) { > + ret = vmbus_try_connection_id(msginfo, version, > + connection_ids[j]); > + if (vmbus_connection.conn_state == CONNECTED) > + return 0; Do we need this ? ret is anyway 0 on success which we can return at the end ? > + > + if (ret == -ETIMEDOUT) > + return ret; > + > + if (connection_ids[j] == > + VMBUS_MESSAGE_CONNECTION_ID_REDIRECT && > + ret == -ENXIO) > + continue; > + > + return ret; > + } > + return ret; Dead code > + } > + > + /* > + * Non-redirect path. Protocol 5.0+ below VTL2 uses the standard > + * v5 connection ID; pre-v5 ignores the supplied ID and uses the > + * legacy connection ID. > + */ > + return vmbus_try_connection_id(msginfo, version, > + VMBUS_MESSAGE_CONNECTION_ID_4); > +} > + > /* > * vmbus_connect - Sends a connect request on the partition service connection > */ > @@ -455,17 +507,14 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) > switch (ret) { > case HV_STATUS_INVALID_CONNECTION_ID: > /* > - * See vmbus_negotiate_version(): VMBus protocol 5.0 > - * and higher require that we must use > - * VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate > - * Contact message, but on old hosts that only > - * support VMBus protocol 4.0 or lower, here we get > - * HV_STATUS_INVALID_CONNECTION_ID and we should > - * return an error immediately without retrying. > + * Let negotiation distinguish an unusable > + * endpoint from other failures. > + * > + * Other messages keep retry behavior. > */ > hdr = buffer; > if (hdr->msgtype == CHANNELMSG_INITIATE_CONTACT) > - return -EINVAL; > + return -ENXIO; > /* > * We could get this if we send messages too > * frequently. > diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h > index 49a72a4f3f6a7..951bdebdc0526 100644 > --- a/drivers/hv/hyperv_vmbus.h > +++ b/drivers/hv/hyperv_vmbus.h > @@ -109,6 +109,8 @@ struct hv_input_post_message { > enum { > VMBUS_MESSAGE_CONNECTION_ID = 1, > VMBUS_MESSAGE_CONNECTION_ID_4 = 4, > + /* VMBus relay port used for INITIATE_CONTACT probing. */ Do we want to mention specific for VTL2 in comment ? > + VMBUS_MESSAGE_CONNECTION_ID_REDIRECT = 0x800074, > VMBUS_MESSAGE_PORT_ID = 1, > VMBUS_EVENT_CONNECTION_ID = 2, > VMBUS_EVENT_PORT_ID = 2, > -- > 2.34.1 - Saurabh