Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105819801
D11618.id30901.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D11618.id30901.diff
View Options
Index: sys/dev/hyperv/netvsc/if_hn.c
===================================================================
--- sys/dev/hyperv/netvsc/if_hn.c
+++ sys/dev/hyperv/netvsc/if_hn.c
@@ -69,6 +69,8 @@
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/lock.h>
+#include <sys/rmlock.h>
+#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -119,6 +121,8 @@
#define HN_RING_CNT_DEF_MAX 8
+#define HN_VFMAP_SIZE_DEF 8
+
/* YYY should get it from the underlying channel */
#define HN_TX_DESC_CNT 512
@@ -255,6 +259,11 @@
static void hn_ifmedia_sts(struct ifnet *,
struct ifmediareq *);
+static void hn_ifnet_event(void *, struct ifnet *, int);
+static void hn_ifaddr_event(void *, struct ifnet *);
+static void hn_ifnet_attevent(void *, struct ifnet *);
+static void hn_ifnet_detevent(void *, struct ifnet *);
+
static int hn_rndis_rxinfo(const void *, int,
struct hn_rxinfo *);
static void hn_rndis_rx_data(struct hn_rx_ring *,
@@ -303,6 +312,9 @@
static int hn_txagg_align_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_polling_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_vf_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_rxvf_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_vflist_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_vfmap_sysctl(SYSCTL_HANDLER_ARGS);
static void hn_stop(struct hn_softc *, bool);
static void hn_init_locked(struct hn_softc *);
@@ -502,9 +514,21 @@
SYSCTL_INT(_hw_hn, OID_AUTO, tx_agg_pkts, CTLFLAG_RDTUN,
&hn_tx_agg_pkts, 0, "Packet transmission aggregation packet limit");
+/* VF list */
+SYSCTL_PROC(_hw_hn, OID_AUTO, vflist, CTLFLAG_RD | CTLTYPE_STRING,
+ 0, 0, hn_vflist_sysctl, "A", "VF list");
+
+/* VF mapping */
+SYSCTL_PROC(_hw_hn, OID_AUTO, vfmap, CTLFLAG_RD | CTLTYPE_STRING,
+ 0, 0, hn_vfmap_sysctl, "A", "VF mapping");
+
static u_int hn_cpu_index; /* next CPU for channel */
static struct taskqueue **hn_tx_taskque;/* shared TX taskqueues */
+static struct rmlock hn_vfmap_lock;
+static int hn_vfmap_size;
+static struct ifnet **hn_vfmap;
+
#ifndef RSS
static const uint8_t
hn_rss_key_default[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
@@ -971,7 +995,7 @@
{
struct hn_update_vf *uv = arg;
- uv->rxr->hn_vf = uv->vf;
+ uv->rxr->hn_rxvf_ifp = uv->vf;
}
static void
@@ -994,37 +1018,50 @@
uv.vf = vf;
vmbus_chan_run_task(rxr->hn_chan, &task);
} else {
- rxr->hn_vf = vf;
+ rxr->hn_rxvf_ifp = vf;
}
}
}
-static void
-hn_set_vf(struct hn_softc *sc, struct ifnet *ifp, bool vf)
+static __inline bool
+hn_ismyvf(const struct hn_softc *sc, const struct ifnet *ifp)
{
- struct ifnet *hn_ifp;
-
- HN_LOCK(sc);
-
- if (!(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED))
- goto out;
+ const struct ifnet *hn_ifp;
hn_ifp = sc->hn_ifp;
if (ifp == hn_ifp)
- goto out;
+ return (false);
if (ifp->if_alloctype != IFT_ETHER)
- goto out;
+ return (false);
/* Ignore lagg/vlan interfaces */
if (strcmp(ifp->if_dname, "lagg") == 0 ||
strcmp(ifp->if_dname, "vlan") == 0)
- goto out;
+ return (false);
if (bcmp(IF_LLADDR(ifp), IF_LLADDR(hn_ifp), ETHER_ADDR_LEN) != 0)
+ return (false);
+
+ return (true);
+}
+
+static void
+hn_set_vf(struct hn_softc *sc, struct ifnet *ifp, bool vf)
+{
+ struct ifnet *hn_ifp;
+
+ HN_LOCK(sc);
+
+ if (!(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED))
+ goto out;
+
+ if (!hn_ismyvf(sc, ifp))
goto out;
+ hn_ifp = sc->hn_ifp;
+
/* Now we're sure 'ifp' is a real VF device. */
if (vf) {
if (sc->hn_flags & HN_FLAG_VF)
@@ -1037,7 +1074,7 @@
goto out;
sc->hn_flags &= ~HN_FLAG_VF;
- if (sc->hn_ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (hn_ifp->if_drv_flags & IFF_DRV_RUNNING)
hn_rxfilter_config(sc);
else
hn_set_rxfilter(sc, NDIS_PACKET_TYPE_NONE);
@@ -1052,7 +1089,7 @@
hn_suspend_mgmt(sc);
sc->hn_link_flags &=
~(HN_LINK_FLAG_LINKUP | HN_LINK_FLAG_NETCHG);
- if_link_state_change(sc->hn_ifp, LINK_STATE_DOWN);
+ if_link_state_change(hn_ifp, LINK_STATE_DOWN);
} else {
hn_resume_mgmt(sc);
}
@@ -1082,6 +1119,85 @@
hn_set_vf(arg, ifp, ifp->if_flags & IFF_UP);
}
+static void
+hn_ifnet_attevent(void *xsc, struct ifnet *ifp)
+{
+ struct hn_softc *sc = xsc;
+
+ HN_LOCK(sc);
+
+ if (!(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED))
+ goto done;
+
+ if (!hn_ismyvf(sc, ifp))
+ goto done;
+
+ if (sc->hn_vf_ifp != NULL) {
+ if_printf(sc->hn_ifp, "%s was attached as VF\n",
+ sc->hn_vf_ifp->if_xname);
+ goto done;
+ }
+
+ rm_wlock(&hn_vfmap_lock);
+
+ if (ifp->if_index >= hn_vfmap_size) {
+ struct ifnet **newmap;
+ int newsize;
+
+ newsize = ifp->if_index + HN_VFMAP_SIZE_DEF;
+ newmap = malloc(sizeof(struct ifnet *) * newsize, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ memcpy(newmap, hn_vfmap,
+ sizeof(struct ifnet *) * hn_vfmap_size);
+ free(hn_vfmap, M_DEVBUF);
+ hn_vfmap = newmap;
+ hn_vfmap_size = newsize;
+ }
+ KASSERT(hn_vfmap[ifp->if_index] == NULL,
+ ("%s: ifindex %d was mapped to %s",
+ ifp->if_xname, ifp->if_index, hn_vfmap[ifp->if_index]->if_xname));
+ hn_vfmap[ifp->if_index] = sc->hn_ifp;
+
+ rm_wunlock(&hn_vfmap_lock);
+
+ sc->hn_vf_ifp = ifp;
+done:
+ HN_UNLOCK(sc);
+}
+
+static void
+hn_ifnet_detevent(void *xsc, struct ifnet *ifp)
+{
+ struct hn_softc *sc = xsc;
+
+ HN_LOCK(sc);
+
+ if (sc->hn_vf_ifp == NULL)
+ goto done;
+
+ if (!hn_ismyvf(sc, ifp))
+ goto done;
+
+ sc->hn_vf_ifp = NULL;
+
+ rm_wlock(&hn_vfmap_lock);
+
+ KASSERT(ifp->if_index < hn_vfmap_size,
+ ("ifindex %d, vfmapsize %d", ifp->if_index, hn_vfmap_size));
+ if (hn_vfmap[ifp->if_index] != NULL) {
+ KASSERT(hn_vfmap[ifp->if_index] == sc->hn_ifp,
+ ("%s: ifindex %d was mapped to %s",
+ ifp->if_xname, ifp->if_index,
+ hn_vfmap[ifp->if_index]->if_xname));
+ hn_vfmap[ifp->if_index] = NULL;
+ }
+
+ rm_wunlock(&hn_vfmap_lock);
+done:
+ HN_UNLOCK(sc);
+}
+
/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
static const struct hyperv_guid g_net_vsc_device_type = {
.hv_guid = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
@@ -1322,6 +1438,9 @@
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "vf",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
hn_vf_sysctl, "A", "Virtual Function's name");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxvf",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+ hn_rxvf_sysctl, "A", "activated Virtual Function's name");
/*
* Setup the ifmedia, which has been initialized earlier.
@@ -1412,10 +1531,14 @@
sc->hn_ifnet_evthand = EVENTHANDLER_REGISTER(ifnet_event,
hn_ifnet_event, sc, EVENTHANDLER_PRI_ANY);
-
sc->hn_ifaddr_evthand = EVENTHANDLER_REGISTER(ifaddr_event,
hn_ifaddr_event, sc, EVENTHANDLER_PRI_ANY);
+ sc->hn_ifnet_atthand = EVENTHANDLER_REGISTER(ether_ifattach_event,
+ hn_ifnet_attevent, sc, EVENTHANDLER_PRI_ANY);
+ sc->hn_ifnet_dethand = EVENTHANDLER_REGISTER(ifnet_departure_event,
+ hn_ifnet_detevent, sc, EVENTHANDLER_PRI_ANY);
+
return (0);
failed:
if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED)
@@ -1428,12 +1551,25 @@
hn_detach(device_t dev)
{
struct hn_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->hn_ifp;
+ struct ifnet *ifp = sc->hn_ifp, *vf_ifp;
if (sc->hn_ifaddr_evthand != NULL)
EVENTHANDLER_DEREGISTER(ifaddr_event, sc->hn_ifaddr_evthand);
if (sc->hn_ifnet_evthand != NULL)
EVENTHANDLER_DEREGISTER(ifnet_event, sc->hn_ifnet_evthand);
+ if (sc->hn_ifnet_atthand != NULL) {
+ EVENTHANDLER_DEREGISTER(ether_ifattach_event,
+ sc->hn_ifnet_atthand);
+ }
+ if (sc->hn_ifnet_dethand != NULL) {
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event,
+ sc->hn_ifnet_dethand);
+ }
+
+ vf_ifp = sc->hn_vf_ifp;
+ __compiler_membar();
+ if (vf_ifp != NULL)
+ hn_ifnet_detevent(sc, vf_ifp);
if (sc->hn_xact != NULL && vmbus_chan_is_revoked(sc->hn_prichan)) {
/*
@@ -2326,7 +2462,7 @@
int hash_type;
/* If the VF is active, inject the packet through the VF */
- ifp = rxr->hn_vf ? rxr->hn_vf : rxr->hn_ifp;
+ ifp = rxr->hn_rxvf_ifp ? rxr->hn_rxvf_ifp : rxr->hn_ifp;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
/*
@@ -3301,12 +3437,28 @@
hn_vf_sysctl(SYSCTL_HANDLER_ARGS)
{
struct hn_softc *sc = arg1;
- char vf_name[128];
+ char vf_name[IFNAMSIZ + 1];
+ struct ifnet *vf;
+
+ HN_LOCK(sc);
+ vf_name[0] = '\0';
+ vf = sc->hn_vf_ifp;
+ if (vf != NULL)
+ snprintf(vf_name, sizeof(vf_name), "%s", if_name(vf));
+ HN_UNLOCK(sc);
+ return sysctl_handle_string(oidp, vf_name, sizeof(vf_name), req);
+}
+
+static int
+hn_rxvf_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct hn_softc *sc = arg1;
+ char vf_name[IFNAMSIZ + 1];
struct ifnet *vf;
HN_LOCK(sc);
vf_name[0] = '\0';
- vf = sc->hn_rx_ring[0].hn_vf;
+ vf = sc->hn_rx_ring[0].hn_rxvf_ifp;
if (vf != NULL)
snprintf(vf_name, sizeof(vf_name), "%s", if_name(vf));
HN_UNLOCK(sc);
@@ -3314,6 +3466,94 @@
}
static int
+hn_vflist_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct rm_priotracker pt;
+ struct sbuf *sb;
+ int error, i;
+ bool first;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+
+ sb = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+ if (sb == NULL)
+ return (ENOMEM);
+
+ rm_rlock(&hn_vfmap_lock, &pt);
+
+ first = true;
+ for (i = 0; i < hn_vfmap_size; ++i) {
+ struct ifnet *ifp;
+
+ if (hn_vfmap[i] == NULL)
+ continue;
+
+ ifp = ifnet_byindex(i);
+ if (ifp != NULL) {
+ if (first)
+ sbuf_printf(sb, "%s", ifp->if_xname);
+ else
+ sbuf_printf(sb, " %s", ifp->if_xname);
+ first = false;
+ }
+ }
+
+ rm_runlock(&hn_vfmap_lock, &pt);
+
+ error = sbuf_finish(sb);
+ sbuf_delete(sb);
+ return (error);
+}
+
+static int
+hn_vfmap_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct rm_priotracker pt;
+ struct sbuf *sb;
+ int error, i;
+ bool first;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+
+ sb = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+ if (sb == NULL)
+ return (ENOMEM);
+
+ rm_rlock(&hn_vfmap_lock, &pt);
+
+ first = true;
+ for (i = 0; i < hn_vfmap_size; ++i) {
+ struct ifnet *ifp, *hn_ifp;
+
+ hn_ifp = hn_vfmap[i];
+ if (hn_ifp == NULL)
+ continue;
+
+ ifp = ifnet_byindex(i);
+ if (ifp != NULL) {
+ if (first) {
+ sbuf_printf(sb, "%s:%s", ifp->if_xname,
+ hn_ifp->if_xname);
+ } else {
+ sbuf_printf(sb, " %s:%s", ifp->if_xname,
+ hn_ifp->if_xname);
+ }
+ first = false;
+ }
+ }
+
+ rm_runlock(&hn_vfmap_lock, &pt);
+
+ error = sbuf_finish(sb);
+ sbuf_delete(sb);
+ return (error);
+}
+
+static int
hn_check_iplen(const struct mbuf *m, int hoff)
{
const struct ip *ip;
@@ -5829,11 +6069,19 @@
}
static void
-hn_tx_taskq_create(void *arg __unused)
+hn_sysinit(void *arg __unused)
{
int i;
/*
+ * Initialize VF map.
+ */
+ rm_init_flags(&hn_vfmap_lock, "hn_vfmap", RM_SLEEPABLE);
+ hn_vfmap_size = HN_VFMAP_SIZE_DEF;
+ hn_vfmap = malloc(sizeof(struct ifnet *) * hn_vfmap_size, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ /*
* Fix the # of TX taskqueues.
*/
if (hn_tx_taskq_cnt <= 0)
@@ -5869,11 +6117,10 @@
"hn tx%d", i);
}
}
-SYSINIT(hn_txtq_create, SI_SUB_DRIVERS, SI_ORDER_SECOND,
- hn_tx_taskq_create, NULL);
+SYSINIT(hn_sysinit, SI_SUB_DRIVERS, SI_ORDER_SECOND, hn_sysinit, NULL);
static void
-hn_tx_taskq_destroy(void *arg __unused)
+hn_sysuninit(void *arg __unused)
{
if (hn_tx_taskque != NULL) {
@@ -5883,6 +6130,9 @@
taskqueue_free(hn_tx_taskque[i]);
free(hn_tx_taskque, M_DEVBUF);
}
+
+ if (hn_vfmap != NULL)
+ free(hn_vfmap, M_DEVBUF);
+ rm_destroy(&hn_vfmap_lock);
}
-SYSUNINIT(hn_txtq_destroy, SI_SUB_DRIVERS, SI_ORDER_SECOND,
- hn_tx_taskq_destroy, NULL);
+SYSUNINIT(hn_sysuninit, SI_SUB_DRIVERS, SI_ORDER_SECOND, hn_sysuninit, NULL);
Index: sys/dev/hyperv/netvsc/if_hnvar.h
===================================================================
--- sys/dev/hyperv/netvsc/if_hnvar.h
+++ sys/dev/hyperv/netvsc/if_hnvar.h
@@ -59,7 +59,7 @@
struct hn_rx_ring {
struct ifnet *hn_ifp;
- struct ifnet *hn_vf; /* SR-IOV VF */
+ struct ifnet *hn_rxvf_ifp; /* SR-IOV VF for RX */
struct hn_tx_ring *hn_txr;
void *hn_pktbuf;
int hn_pktbuf_len;
@@ -174,6 +174,7 @@
*/
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;
@@ -238,6 +239,8 @@
eventhandler_tag hn_ifaddr_evthand;
eventhandler_tag hn_ifnet_evthand;
+ eventhandler_tag hn_ifnet_atthand;
+ eventhandler_tag hn_ifnet_dethand;
};
#define HN_FLAG_RXBUF_CONNECTED 0x0001
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 22, 4:43 AM (21 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15550651
Default Alt Text
D11618.id30901.diff (12 KB)
Attached To
Mode
D11618: hyperv/hn: Export VF list and VF-HN mapping
Attached
Detach File
Event Timeline
Log In to Comment