diff --git a/sys/dev/hyperv/netvsc/hn_rndis.h b/sys/dev/hyperv/netvsc/hn_rndis.h --- a/sys/dev/hyperv/netvsc/hn_rndis.h +++ b/sys/dev/hyperv/netvsc/hn_rndis.h @@ -46,5 +46,6 @@ int hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter); void hn_rndis_rx_ctrl(struct hn_softc *sc, const void *data, int dlen); +int hn_rndis_reconf_offload(struct hn_softc *sc, int mtu); #endif /* !_HN_RNDIS_H_ */ diff --git a/sys/dev/hyperv/netvsc/hn_rndis.c b/sys/dev/hyperv/netvsc/hn_rndis.c --- a/sys/dev/hyperv/netvsc/hn_rndis.c +++ b/sys/dev/hyperv/netvsc/hn_rndis.c @@ -579,6 +579,12 @@ return (error); } +int +hn_rndis_reconf_offload(struct hn_softc *sc, int mtu) +{ + return(hn_rndis_conf_offload(sc, mtu)); +} + static int hn_rndis_conf_offload(struct hn_softc *sc, int mtu) { @@ -725,7 +731,8 @@ /* RSC offload */ if (hwcaps.ndis_hdr.ndis_rev >= NDIS_OFFLOAD_PARAMS_REV_3) { - if (hwcaps.ndis_rsc.ndis_ip4 && hwcaps.ndis_rsc.ndis_ip6) { + if (hwcaps.ndis_rsc.ndis_ip4 && hwcaps.ndis_rsc.ndis_ip6 && + sc->hn_rsc_ctrl) { params.ndis_rsc_ip4 = NDIS_OFFLOAD_RSC_ON; params.ndis_rsc_ip6 = NDIS_OFFLOAD_RSC_ON; } else { diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c --- a/sys/dev/hyperv/netvsc/if_hn.c +++ b/sys/dev/hyperv/netvsc/if_hn.c @@ -454,6 +454,8 @@ static void hn_start_txeof_taskfunc(void *, int); #endif +static int hn_rsc_sysctl(SYSCTL_HANDLER_ARGS); + SYSCTL_NODE(_hw, OID_AUTO, hn, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Hyper-V network interface"); @@ -2370,6 +2372,10 @@ "Accurate BPF for transparent VF"); } + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rsc_switch", + CTLTYPE_UINT | CTLFLAG_RW, sc, 0, hn_rsc_sysctl, "A", + "switch to rsc"); + /* * Setup the ifmedia, which has been initialized earlier. */ @@ -4567,6 +4573,30 @@ return sysctl_handle_string(oidp, filter_str, sizeof(filter_str), req); } +static int +hn_rsc_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct hn_softc *sc = arg1; + uint32_t mtu; + int error; + HN_LOCK(sc); + error = hn_rndis_get_mtu(sc, &mtu); + if (error) { + if_printf(sc->hn_ifp, "failed to get mtu\n"); + goto back; + } + error = SYSCTL_OUT(req, &(sc->hn_rsc_ctrl), sizeof(sc->hn_rsc_ctrl)); + if (error || req->newptr == NULL) + goto back; + + error = SYSCTL_IN(req, &(sc->hn_rsc_ctrl), sizeof(sc->hn_rsc_ctrl)); + if (error) + goto back; + error = hn_rndis_reconf_offload(sc, mtu); +back: + HN_UNLOCK(sc); + return (error); +} #ifndef RSS static int diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -282,6 +282,11 @@ u_int hn_saved_tsomax; u_int hn_saved_tsosegcnt; u_int hn_saved_tsosegsz; + + /* + * RSC switch, default off + */ + u_int hn_rsc_ctrl; }; #define HN_FLAG_RXBUF_CONNECTED 0x0001