diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-10-28 10:20:40 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-10-28 10:20:40 +0000 |
commit | c513d7e8cc27215e7ed78489cbd72f85ff5bf27c (patch) | |
tree | 4c7c448bc45521b7e28d1505aa7da7dd8a30e4bc /sys/dev | |
parent | da6b4da42b1583e72699661e0898f5f2e04409b9 (diff) |
Improve protocol version negotiation for Integrated Components
modelled on the upstream version.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pv/hypervic.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/sys/dev/pv/hypervic.c b/sys/dev/pv/hypervic.c index 876992e8e0d..dcf812268d4 100644 --- a/sys/dev/pv/hypervic.c +++ b/sys/dev/pv/hypervic.c @@ -178,22 +178,52 @@ hv_attach_icdevs(struct hv_softc *sc) } static inline void -hv_ic_negotiate(struct vmbus_icmsg_hdr *hdr) +hv_ic_negotiate(struct vmbus_icmsg_hdr *hdr, uint32_t *rlen, uint32_t fwver, + uint32_t msgver) { struct vmbus_icmsg_negotiate *msg; + uint16_t propmin, propmaj, chosenmaj, chosenmin; + int i; msg = (struct vmbus_icmsg_negotiate *)hdr; - if (msg->ic_fwver_cnt >= 2 && - VMBUS_ICVER_MAJOR(msg->ic_ver[1]) == 3) { - msg->ic_ver[0] = VMBUS_IC_VERSION(3, 0); - msg->ic_ver[1] = VMBUS_IC_VERSION(3, 0); - } else { - msg->ic_ver[0] = VMBUS_IC_VERSION(1, 0); - msg->ic_ver[1] = VMBUS_IC_VERSION(1, 0); + + chosenmaj = chosenmin = 0; + printf("\n"); + for (i = 0; i < msg->ic_fwver_cnt; i++) { + propmaj = VMBUS_ICVER_MAJOR(msg->ic_ver[i]); + propmin = VMBUS_ICVER_MINOR(msg->ic_ver[i]); + if (propmaj > chosenmaj && + propmaj <= VMBUS_ICVER_MAJOR(fwver) && + propmin >= chosenmin && + propmin <= VMBUS_ICVER_MINOR(fwver)) { + chosenmaj = propmaj; + chosenmin = propmin; + } } + fwver = VMBUS_IC_VERSION(chosenmaj, chosenmin); + + chosenmaj = chosenmin = 0; + for (; i < msg->ic_fwver_cnt + msg->ic_msgver_cnt; i++) { + propmaj = VMBUS_ICVER_MAJOR(msg->ic_ver[i]); + propmin = VMBUS_ICVER_MINOR(msg->ic_ver[i]); + if (propmaj > chosenmaj && + propmaj <= VMBUS_ICVER_MAJOR(msgver) && + propmin >= chosenmin && + propmin <= VMBUS_ICVER_MINOR(msgver)) { + chosenmaj = propmaj; + chosenmin = propmin; + } + } + msgver = VMBUS_IC_VERSION(chosenmaj, chosenmin); + msg->ic_fwver_cnt = 1; + msg->ic_ver[0] = fwver; msg->ic_msgver_cnt = 1; - hdr->ic_dsize = sizeof(*msg) + 2 * sizeof(uint32_t); + msg->ic_ver[1] = msgver; + hdr->ic_dsize = sizeof(*msg) + 2 * sizeof(uint32_t) - + sizeof(struct vmbus_icmsg_hdr); + if (*rlen < sizeof(*msg) + 2 * sizeof(uint32_t)) + *rlen = sizeof(*msg) + 2 * sizeof(uint32_t); } void @@ -223,7 +253,8 @@ hv_heartbeat(void *arg) hdr = (struct vmbus_icmsg_hdr *)dv->dv_buf; switch (hdr->ic_type) { case VMBUS_ICMSG_TYPE_NEGOTIATE: - hv_ic_negotiate(hdr); + hv_ic_negotiate(hdr, &rlen, VMBUS_IC_VERSION(3, 0), + VMBUS_IC_VERSION(3, 0)); break; case VMBUS_ICMSG_TYPE_HEARTBEAT: msg = (struct vmbus_icmsg_heartbeat *)hdr; @@ -289,7 +320,8 @@ hv_shutdown(void *arg) hdr = (struct vmbus_icmsg_hdr *)dv->dv_buf; switch (hdr->ic_type) { case VMBUS_ICMSG_TYPE_NEGOTIATE: - hv_ic_negotiate(hdr); + hv_ic_negotiate(hdr, &rlen, VMBUS_IC_VERSION(3, 0), + VMBUS_IC_VERSION(3, 0)); break; case VMBUS_ICMSG_TYPE_SHUTDOWN: msg = (struct vmbus_icmsg_shutdown *)hdr; @@ -357,7 +389,8 @@ hv_timesync(void *arg) hdr = (struct vmbus_icmsg_hdr *)dv->dv_buf; switch (hdr->ic_type) { case VMBUS_ICMSG_TYPE_NEGOTIATE: - hv_ic_negotiate(hdr); + hv_ic_negotiate(hdr, &rlen, VMBUS_IC_VERSION(3, 0), + VMBUS_IC_VERSION(3, 0)); break; case VMBUS_ICMSG_TYPE_TIMESYNC: msg = (struct vmbus_icmsg_timesync *)hdr; |