hyperv/hn: Implement transparent mode network VF.

How network VF works with hn(4) on Hyper-V in transparent mode:

- Each network VF has a cooresponding hn(4).
- The network VF and the it's cooresponding hn(4) have the same hardware
  address.
- Once the network VF is attached, the cooresponding hn(4) waits several
  seconds to make sure that the network VF attach routing completes, then:
  o  Set the intersection of the network VF's if_capabilities and the
     cooresponding hn(4)'s if_capabilities to the cooresponding hn(4)'s
     if_capabilities.  And adjust the cooresponding hn(4) if_capable and
     if_hwassist accordingly. (*)
  o  Make sure that the cooresponding hn(4)'s TSO parameters meet the
     constraints posed by both the network VF and the cooresponding hn(4).
     (*)
  o  The network VF's if_input is overridden.  The overriding if_input
     changes the input packet's rcvif to the cooreponding hn(4).  The
     network layers are tricked into thinking that all packets are
     neceived by the cooresponding hn(4).
  o  If the cooresponding hn(4) was brought up, bring up the network VF.
     The transmission dispatched to the cooresponding hn(4) are
     redispatched to the network VF.
  o  Bringing down the cooresponding hn(4) also brings down the network
     VF.
  o  All IOCTLs issued to the cooresponding hn(4) are pass-through'ed to
     the network VF; the cooresponding hn(4) changes its internal state
     if necessary.
  o  The media status of the cooresponding hn(4) solely relies on the
     network VF.
  o  If there are multicast filters on the cooresponding hn(4), allmulti
     will be enabled on the network VF. (**)
- Once the network VF is detached.  Undo all damages did to the
  cooresponding hn(4) in the above item.

NOTE:
No operation should be issued directly to the network VF, if the
network VF transparent mode is enabled.  The network VF transparent mode
can be enabled by setting tunable hw.hn.vf_transparent to 1.  The network
VF transparent mode is _not_ enabled by default, as of this commit.

The benefit of the network VF transparent mode is that the network VF
attachment and detachment are transparent to all network layers; e.g. live
migration detaches and reattaches the network VF.

The major drawbacks of the network VF transparent mode:
- The netmap(4) support is lost, even if the VF supports it.
- ALTQ does not work, since if_start method cannot be properly supported.

(*)
These decisions were made so that things will not be messed up too much
during the transition period.

(**)
This does _not_ need to go through the fancy multicast filter management
stuffs like what vlan(4) has, at least currently:
- As of this write, multicast does not work in Azure.
- As of this write, multicast packets go through the cooresponding hn(4).

MFC after:	3 days
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D11803
This commit is contained in:
Sepherosa Ziehau 2017-08-09 05:59:45 +00:00
parent 2f401b0a4b
commit 9c6cae2431
3 changed files with 811 additions and 41 deletions

File diff suppressed because it is too large Load Diff

View File

@ -133,7 +133,7 @@ struct hn_nvs_ndis_init {
} __packed;
CTASSERT(sizeof(struct hn_nvs_ndis_init) >= HN_NVS_REQSIZE_MIN);
#define HN_NVS_DATAPATH_SYNTHETIC 0
#define HN_NVS_DATAPATH_SYNTH 0
#define HN_NVS_DATAPATH_VF 1
/* No response */

View File

@ -174,7 +174,6 @@ struct hn_tx_ring {
*/
struct hn_softc {
struct ifnet *hn_ifp;
struct ifnet *hn_vf_ifp; /* SR-IOV VF */
struct ifmedia hn_media;
device_t hn_dev;
int hn_if_flags;
@ -185,6 +184,10 @@ struct hn_softc {
int hn_rx_ring_inuse;
struct hn_rx_ring *hn_rx_ring;
struct rmlock hn_vf_lock;
struct ifnet *hn_vf_ifp; /* SR-IOV VF */
uint32_t hn_xvf_flags; /* transparent VF flags */
int hn_tx_ring_cnt;
int hn_tx_ring_inuse;
struct hn_tx_ring *hn_tx_ring;
@ -241,6 +244,24 @@ struct hn_softc {
eventhandler_tag hn_ifnet_evthand;
eventhandler_tag hn_ifnet_atthand;
eventhandler_tag hn_ifnet_dethand;
eventhandler_tag hn_ifnet_lnkhand;
/*
* Transparent VF delayed initialization.
*/
int hn_vf_rdytick; /* ticks, 0 == ready */
struct taskqueue *hn_vf_taskq;
struct timeout_task hn_vf_init;
/*
* Saved information for VF under transparent mode.
*/
void (*hn_vf_input)
(struct ifnet *, struct mbuf *);
int hn_saved_caps;
u_int hn_saved_tsomax;
u_int hn_saved_tsosegcnt;
u_int hn_saved_tsosegsz;
};
#define HN_FLAG_RXBUF_CONNECTED 0x0001
@ -255,6 +276,9 @@ struct hn_softc {
#define HN_FLAG_ERRORS (HN_FLAG_RXBUF_REF | HN_FLAG_CHIM_REF)
#define HN_XVFFLAG_ENABLED 0x0001
#define HN_XVFFLAG_ACCBPF 0x0002
#define HN_NO_SLEEPING(sc) \
do { \
(sc)->hn_flags |= HN_FLAG_NO_SLEEPING; \