Deleted Added
full compact
28c28
< * $FreeBSD: head/sys/dev/netmap/netmap.c 267284 2014-06-09 15:46:11Z luigi $
---
> * $FreeBSD: head/sys/dev/netmap/netmap.c 270063 2014-08-16 15:00:01Z luigi $
126a127,343
>
> /* --- internals ----
> *
> * Roadmap to the code that implements the above.
> *
> * > 1. a process/thread issues one or more open() on /dev/netmap, to create
> * > select()able file descriptor on which events are reported.
> *
> * Internally, we allocate a netmap_priv_d structure, that will be
> * initialized on ioctl(NIOCREGIF).
> *
> * os-specific:
> * FreeBSD: netmap_open (netmap_freebsd.c). The priv is
> * per-thread.
> * linux: linux_netmap_open (netmap_linux.c). The priv is
> * per-open.
> *
> * > 2. on each descriptor, the process issues an ioctl() to identify
> * > the interface that should report events to the file descriptor.
> *
> * Implemented by netmap_ioctl(), NIOCREGIF case, with nmr->nr_cmd==0.
> * Most important things happen in netmap_get_na() and
> * netmap_do_regif(), called from there. Additional details can be
> * found in the comments above those functions.
> *
> * In all cases, this action creates/takes-a-reference-to a
> * netmap_*_adapter describing the port, and allocates a netmap_if
> * and all necessary netmap rings, filling them with netmap buffers.
> *
> * In this phase, the sync callbacks for each ring are set (these are used
> * in steps 5 and 6 below). The callbacks depend on the type of adapter.
> * The adapter creation/initialization code puts them in the
> * netmap_adapter (fields na->nm_txsync and na->nm_rxsync). Then, they
> * are copied from there to the netmap_kring's during netmap_do_regif(), by
> * the nm_krings_create() callback. All the nm_krings_create callbacks
> * actually call netmap_krings_create() to perform this and the other
> * common stuff. netmap_krings_create() also takes care of the host rings,
> * if needed, by setting their sync callbacks appropriately.
> *
> * Additional actions depend on the kind of netmap_adapter that has been
> * registered:
> *
> * - netmap_hw_adapter: [netmap.c]
> * This is a system netdev/ifp with native netmap support.
> * The ifp is detached from the host stack by redirecting:
> * - transmissions (from the network stack) to netmap_transmit()
> * - receive notifications to the nm_notify() callback for
> * this adapter. The callback is normally netmap_notify(), unless
> * the ifp is attached to a bridge using bwrap, in which case it
> * is netmap_bwrap_intr_notify().
> *
> * - netmap_generic_adapter: [netmap_generic.c]
> * A system netdev/ifp without native netmap support.
> *
> * (the decision about native/non native support is taken in
> * netmap_get_hw_na(), called by netmap_get_na())
> *
> * - netmap_vp_adapter [netmap_vale.c]
> * Returned by netmap_get_bdg_na().
> * This is a persistent or ephemeral VALE port. Ephemeral ports
> * are created on the fly if they don't already exist, and are
> * always attached to a bridge.
> * Persistent VALE ports must must be created seperately, and i
> * then attached like normal NICs. The NIOCREGIF we are examining
> * will find them only if they had previosly been created and
> * attached (see VALE_CTL below).
> *
> * - netmap_pipe_adapter [netmap_pipe.c]
> * Returned by netmap_get_pipe_na().
> * Both pipe ends are created, if they didn't already exist.
> *
> * - netmap_monitor_adapter [netmap_monitor.c]
> * Returned by netmap_get_monitor_na().
> * If successful, the nm_sync callbacks of the monitored adapter
> * will be intercepted by the returned monitor.
> *
> * - netmap_bwrap_adapter [netmap_vale.c]
> * Cannot be obtained in this way, see VALE_CTL below
> *
> *
> * os-specific:
> * linux: we first go through linux_netmap_ioctl() to
> * adapt the FreeBSD interface to the linux one.
> *
> *
> * > 3. on each descriptor, the process issues an mmap() request to
> * > map the shared memory region within the process' address space.
> * > The list of interesting queues is indicated by a location in
> * > the shared memory region.
> *
> * os-specific:
> * FreeBSD: netmap_mmap_single (netmap_freebsd.c).
> * linux: linux_netmap_mmap (netmap_linux.c).
> *
> * > 4. using the functions in the netmap(4) userspace API, a process
> * > can look up the occupation state of a queue, access memory buffers,
> * > and retrieve received packets or enqueue packets to transmit.
> *
> * these actions do not involve the kernel.
> *
> * > 5. using some ioctl()s the process can synchronize the userspace view
> * > of the queue with the actual status in the kernel. This includes both
> * > receiving the notification of new packets, and transmitting new
> * > packets on the output interface.
> *
> * These are implemented in netmap_ioctl(), NIOCTXSYNC and NIOCRXSYNC
> * cases. They invoke the nm_sync callbacks on the netmap_kring
> * structures, as initialized in step 2 and maybe later modified
> * by a monitor. Monitors, however, will always call the original
> * callback before doing anything else.
> *
> *
> * > 6. select() or poll() can be used to wait for events on individual
> * > transmit or receive queues (or all queues for a given interface).
> *
> * Implemented in netmap_poll(). This will call the same nm_sync()
> * callbacks as in step 5 above.
> *
> * os-specific:
> * linux: we first go through linux_netmap_poll() to adapt
> * the FreeBSD interface to the linux one.
> *
> *
> * ---- VALE_CTL -----
> *
> * VALE switches are controlled by issuing a NIOCREGIF with a non-null
> * nr_cmd in the nmreq structure. These subcommands are handled by
> * netmap_bdg_ctl() in netmap_vale.c. Persistent VALE ports are created
> * and destroyed by issuing the NETMAP_BDG_NEWIF and NETMAP_BDG_DELIF
> * subcommands, respectively.
> *
> * Any network interface known to the system (including a persistent VALE
> * port) can be attached to a VALE switch by issuing the
> * NETMAP_BDG_ATTACH subcommand. After the attachment, persistent VALE ports
> * look exactly like ephemeral VALE ports (as created in step 2 above). The
> * attachment of other interfaces, instead, requires the creation of a
> * netmap_bwrap_adapter. Moreover, the attached interface must be put in
> * netmap mode. This may require the creation of a netmap_generic_adapter if
> * we have no native support for the interface, or if generic adapters have
> * been forced by sysctl.
> *
> * Both persistent VALE ports and bwraps are handled by netmap_get_bdg_na(),
> * called by nm_bdg_ctl_attach(), and discriminated by the nm_bdg_attach()
> * callback. In the case of the bwrap, the callback creates the
> * netmap_bwrap_adapter. The initialization of the bwrap is then
> * completed by calling netmap_do_regif() on it, in the nm_bdg_ctl()
> * callback (netmap_bwrap_bdg_ctl in netmap_vale.c).
> * A generic adapter for the wrapped ifp will be created if needed, when
> * netmap_get_bdg_na() calls netmap_get_hw_na().
> *
> *
> * ---- DATAPATHS -----
> *
> * -= SYSTEM DEVICE WITH NATIVE SUPPORT =-
> *
> * na == NA(ifp) == netmap_hw_adapter created in DEVICE_netmap_attach()
> *
> * - tx from netmap userspace:
> * concurrently:
> * 1) ioctl(NIOCTXSYNC)/netmap_poll() in process context
> * kring->nm_sync() == DEVICE_netmap_txsync()
> * 2) device interrupt handler
> * na->nm_notify() == netmap_notify()
> * - rx from netmap userspace:
> * concurrently:
> * 1) ioctl(NIOCRXSYNC)/netmap_poll() in process context
> * kring->nm_sync() == DEVICE_netmap_rxsync()
> * 2) device interrupt handler
> * na->nm_notify() == netmap_notify()
> * - tx from host stack
> * concurrently:
> * 1) host stack
> * netmap_transmit()
> * na->nm_notify == netmap_notify()
> * 2) ioctl(NIOCRXSYNC)/netmap_poll() in process context
> * kring->nm_sync() == netmap_rxsync_from_host_compat
> * netmap_rxsync_from_host(na, NULL, NULL)
> * - tx to host stack
> * ioctl(NIOCTXSYNC)/netmap_poll() in process context
> * kring->nm_sync() == netmap_txsync_to_host_compat
> * netmap_txsync_to_host(na)
> * NM_SEND_UP()
> * FreeBSD: na->if_input() == ?? XXX
> * linux: netif_rx() with NM_MAGIC_PRIORITY_RX
> *
> *
> *
> * -= SYSTEM DEVICE WITH GENERIC SUPPORT =-
> *
> *
> *
> * -= VALE PORT =-
> *
> *
> *
> * -= NETMAP PIPE =-
> *
> *
> *
> * -= SYSTEM DEVICE WITH NATIVE SUPPORT, CONNECTED TO VALE, NO HOST RINGS =-
> *
> *
> *
> * -= SYSTEM DEVICE WITH NATIVE SUPPORT, CONNECTED TO VALE, WITH HOST RINGS =-
> *
> *
> *
> * -= SYSTEM DEVICE WITH GENERIC SUPPORT, CONNECTED TO VALE, NO HOST RINGS =-
> *
> *
> *
> * -= SYSTEM DEVICE WITH GENERIC SUPPORT, CONNECTED TO VALE, WITH HOST RINGS =-
> *
> *
> *
> */
>
220a438,441
> int netmap_adaptive_io = 0;
> SYSCTL_INT(_dev_netmap, OID_AUTO, adaptive_io, CTLFLAG_RW,
> &netmap_adaptive_io, 0 , "Adaptive I/O on paravirt");
>
262c483
< void
---
> static void
271a493,506
> /* stop or enable a single tx ring */
> void
> netmap_set_txring(struct netmap_adapter *na, u_int ring_id, int stopped)
> {
> if (stopped)
> netmap_disable_ring(na->tx_rings + ring_id);
> else
> na->tx_rings[ring_id].nkr_stopped = 0;
> /* nofify that the stopped state has changed. This is currently
> *only used by bwrap to propagate the state to its own krings.
> * (see netmap_bwrap_intr_notify).
> */
> na->nm_notify(na, ring_id, NR_TX, NAF_DISABLE_NOTIFY);
> }
272a508,523
> /* stop or enable a single rx ring */
> void
> netmap_set_rxring(struct netmap_adapter *na, u_int ring_id, int stopped)
> {
> if (stopped)
> netmap_disable_ring(na->rx_rings + ring_id);
> else
> na->rx_rings[ring_id].nkr_stopped = 0;
> /* nofify that the stopped state has changed. This is currently
> *only used by bwrap to propagate the state to its own krings.
> * (see netmap_bwrap_intr_notify).
> */
> na->nm_notify(na, ring_id, NR_RX, NAF_DISABLE_NOTIFY);
> }
>
>
274,275c525,526
< static void
< netmap_set_all_rings(struct ifnet *ifp, int stopped)
---
> void
> netmap_set_all_rings(struct netmap_adapter *na, int stopped)
277d527
< struct netmap_adapter *na;
281c531
< if (!(ifp->if_capenable & IFCAP_NETMAP))
---
> if (!nm_netmap_on(na))
284,285d533
< na = NA(ifp);
<
290,294c538
< if (stopped)
< netmap_disable_ring(na->tx_rings + i);
< else
< na->tx_rings[i].nkr_stopped = 0;
< na->nm_notify(na, i, NR_TX, NAF_DISABLE_NOTIFY);
---
> netmap_set_txring(na, i, stopped);
298,302c542
< if (stopped)
< netmap_disable_ring(na->rx_rings + i);
< else
< na->rx_rings[i].nkr_stopped = 0;
< na->nm_notify(na, i, NR_RX, NAF_DISABLE_NOTIFY);
---
> netmap_set_rxring(na, i, stopped);
306d545
<
317c556
< netmap_set_all_rings(ifp, 1 /* stopped */);
---
> netmap_set_all_rings(NA(ifp), 1 /* stopped */);
320d558
<
329c567
< netmap_set_all_rings(ifp, 0 /* enabled */);
---
> netmap_set_all_rings(NA(ifp), 0 /* enabled */);
413d650
< struct ifnet *ifp = na->ifp;
432c669
< NM_IFPNAME(ifp),
---
> na->name,
436c673
< NM_IFPNAME(ifp), txr, txd, rxr, rxd);
---
> na->name, txr, txd, rxr, rxd);
450,463d686
< static int
< netmap_txsync_compat(struct netmap_kring *kring, int flags)
< {
< struct netmap_adapter *na = kring->na;
< return na->nm_txsync(na, kring->ring_id, flags);
< }
<
< static int
< netmap_rxsync_compat(struct netmap_kring *kring, int flags)
< {
< struct netmap_adapter *na = kring->na;
< return na->nm_rxsync(na, kring->ring_id, flags);
< }
<
541c764
< kring->nm_sync = netmap_txsync_compat; // XXX
---
> kring->nm_sync = na->nm_txsync;
550c773
< snprintf(kring->name, sizeof(kring->name) - 1, "%s TX%d", NM_IFPNAME(na->ifp), i);
---
> snprintf(kring->name, sizeof(kring->name) - 1, "%s TX%d", na->name, i);
565c788
< kring->nm_sync = netmap_rxsync_compat; // XXX
---
> kring->nm_sync = na->nm_rxsync;
571c794
< snprintf(kring->name, sizeof(kring->name) - 1, "%s RX%d", NM_IFPNAME(na->ifp), i);
---
> snprintf(kring->name, sizeof(kring->name) - 1, "%s RX%d", na->name, i);
627c850
< netmap_if_new(const char *ifname, struct netmap_adapter *na)
---
> netmap_if_new(struct netmap_adapter *na)
644c867
< goto cleanup;
---
> return NULL;
653c876
< nifp = netmap_mem_if_new(ifname, na);
---
> nifp = netmap_mem_if_new(na);
692c915
< error = netmap_mem_finalize(nmd);
---
> error = netmap_mem_finalize(nmd, p->np_na);
731c954
< netmap_mem_deref(p->np_mref);
---
> netmap_mem_deref(p->np_mref, p->np_na);
738,739d960
< * File descriptor's private data destructor.
< *
741c962
< * revert to normal operation. We expect that np_na->ifp has not gone.
---
> * revert to normal operation.
751d971
< struct ifnet *ifp = na->ifp;
758c978
< D("deleting last instance for %s", NM_IFPNAME(ifp));
---
> D("deleting last instance for %s", na->name);
773,774c993
< if (ifp)
< na->nm_register(na, 0); /* off, clear flags */
---
> na->nm_register(na, 0); /* off, clear flags */
925c1144
< if (slot->len < 14 || slot->len > NETMAP_BDG_BUF_SIZE(na->nm_mem)) {
---
> if (slot->len < 14 || slot->len > NETMAP_BUF_SIZE(na)) {
931c1150
< m = m_devget(BDG_NMB(na, slot), slot->len, 0, na->ifp, NULL);
---
> m = m_devget(NMB(na, slot), slot->len, 0, na->ifp, NULL);
984c1203
< rdst->head = rdst->cur = nm_next(dst_cur, dst_lim);
---
> rdst->cur = nm_next(dst_cur, dst_lim);
1030a1250,1254
> * This routine also does the selrecord if called from the poll handler
> * (we know because td != NULL).
> *
> * NOTE: on linux, selrecord() is defined as a macro and uses pwait
> * as an additional hidden argument.
1062c1286
< m_copydata(m, 0, len, BDG_NMB(na, slot));
---
> m_copydata(m, 0, len, NMB(na, slot));
1065c1289
< D("%s", nm_dump_buf(BDG_NMB(na, slot),len, 128, NULL));
---
> D("%s", nm_dump_buf(NMB(na, slot),len, 128, NULL));
1069a1294
> m_freem(m);
1085a1311,1314
> /* access copies of cur,tail in the kring */
> if (kring->rcur == kring->rtail && td) /* no bufs available */
> selrecord(td, &kring->si);
>
1131,1137c1360
< /* If an adapter already exists, but is
< * attached to a vale port, we report that the
< * port is busy.
< */
< if (NETMAP_OWNED_BY_KERN(NA(ifp)))
< return EBUSY;
<
---
> prev_na = NA(ifp);
1143,1145c1366,1376
< if (NA(ifp)->active_fds > 0 ||
< i != NETMAP_ADMODE_GENERIC) {
< *na = NA(ifp);
---
> if (NETMAP_OWNED_BY_ANY(prev_na)
> || i != NETMAP_ADMODE_GENERIC
> || prev_na->na_flags & NAF_FORCE_NATIVE
> #ifdef WITH_PIPES
> /* ugly, but we cannot allow an adapter switch
> * if some pipe is referring to this one
> */
> || prev_na->na_next_pipe > 0
> #endif
> ) {
> *na = prev_na;
1215d1445
< /* first try to see if this is a bridge port. */
1217a1448,1464
> /* we cascade through all possibile types of netmap adapter.
> * All netmap_get_*_na() functions return an error and an na,
> * with the following combinations:
> *
> * error na
> * 0 NULL type doesn't match
> * !0 NULL type matches, but na creation/lookup failed
> * 0 !NULL type matches and na created/found
> * !0 !NULL impossible
> */
>
> /* try to see if this is a monitor port */
> error = netmap_get_monitor_na(nmr, na, create);
> if (error || *na != NULL)
> return error;
>
> /* try to see if this is a pipe port */
1221a1469
> /* try to see if this is a bridge port */
1244,1248d1491
< /* Users cannot use the NIC attached to a bridge directly */
< if (NETMAP_OWNED_BY_KERN(ret)) {
< error = EBUSY;
< goto out;
< }
1447c1690
< RD(10, "called for %s", NM_IFPNAME(kring->na->ifp));
---
> RD(10, "called for %s", kring->name);
1466c1709
< } else if (len > NETMAP_BDG_BUF_SIZE(kring->na->nm_mem)) {
---
> } else if (len > NETMAP_BUF_SIZE(kring->na)) {
1484,1487c1727,1732
<
< /*
< * Set the ring ID. For devices with a single queue, a request
< * for all rings is the same as a single ring.
---
> /* interpret the ringid and flags fields of an nmreq, by translating them
> * into a pair of intervals of ring indices:
> *
> * [priv->np_txqfirst, priv->np_txqlast) and
> * [priv->np_rxqfirst, priv->np_rxqlast)
> *
1489,1490c1734,1735
< static int
< netmap_set_ringid(struct netmap_priv_d *priv, uint16_t ringid, uint32_t flags)
---
> int
> netmap_interp_ringid(struct netmap_priv_d *priv, uint16_t ringid, uint32_t flags)
1554d1798
< priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1;
1556,1559c1800
< if (nm_tx_si_user(priv))
< na->tx_si_users++;
< if (nm_rx_si_user(priv))
< na->rx_si_users++;
---
>
1562c1803
< NM_IFPNAME(na->ifp),
---
> na->name,
1571a1813
>
1572a1815,1843
> * Set the ring ID. For devices with a single queue, a request
> * for all rings is the same as a single ring.
> */
> static int
> netmap_set_ringid(struct netmap_priv_d *priv, uint16_t ringid, uint32_t flags)
> {
> struct netmap_adapter *na = priv->np_na;
> int error;
>
> error = netmap_interp_ringid(priv, ringid, flags);
> if (error) {
> return error;
> }
>
> priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1;
>
> /* optimization: count the users registered for more than
> * one ring, which are the ones sleeping on the global queue.
> * The default netmap_notify() callback will then
> * avoid signaling the global queue if nobody is using it
> */
> if (nm_tx_si_user(priv))
> na->tx_si_users++;
> if (nm_rx_si_user(priv))
> na->rx_si_users++;
> return 0;
> }
>
> /*
1575a1847,1914
> *
> * The following na callbacks are called in the process:
> *
> * na->nm_config() [by netmap_update_config]
> * (get current number and size of rings)
> *
> * We have a generic one for linux (netmap_linux_config).
> * The bwrap has to override this, since it has to forward
> * the request to the wrapped adapter (netmap_bwrap_config).
> *
> * XXX netmap_if_new calls this again (2014-03-15)
> *
> * na->nm_krings_create() [by netmap_if_new]
> * (create and init the krings array)
> *
> * One of the following:
> *
> * * netmap_hw_krings_create, (hw ports)
> * creates the standard layout for the krings
> * and adds the mbq (used for the host rings).
> *
> * * netmap_vp_krings_create (VALE ports)
> * add leases and scratchpads
> *
> * * netmap_pipe_krings_create (pipes)
> * create the krings and rings of both ends and
> * cross-link them
> *
> * * netmap_monitor_krings_create (monitors)
> * avoid allocating the mbq
> *
> * * netmap_bwrap_krings_create (bwraps)
> * create both the brap krings array,
> * the krings array of the wrapped adapter, and
> * (if needed) the fake array for the host adapter
> *
> * na->nm_register(, 1)
> * (put the adapter in netmap mode)
> *
> * This may be one of the following:
> * (XXX these should be either all *_register or all *_reg 2014-03-15)
> *
> * * netmap_hw_register (hw ports)
> * checks that the ifp is still there, then calls
> * the hardware specific callback;
> *
> * * netmap_vp_reg (VALE ports)
> * If the port is connected to a bridge,
> * set the NAF_NETMAP_ON flag under the
> * bridge write lock.
> *
> * * netmap_pipe_reg (pipes)
> * inform the other pipe end that it is no
> * longer responsibile for the lifetime of this
> * pipe end
> *
> * * netmap_monitor_reg (monitors)
> * intercept the sync callbacks of the monitored
> * rings
> *
> * * netmap_bwrap_register (bwraps)
> * cross-link the bwrap and hwna rings,
> * forward the request to the hwna, override
> * the hwna notify callback (to get the frames
> * coming from outside go through the bridge).
> *
> * XXX maybe netmap_if_new() should be merged with this (2014-03-15).
> *
1581d1919
< struct ifnet *ifp = na->ifp;
1600,1601d1937
< nifp = netmap_if_new(NM_IFPNAME(ifp), na);
<
1602a1939
> nifp = netmap_if_new(na);
1608,1611c1945,1946
< if (ifp->if_capenable & IFCAP_NETMAP) {
< /* was already set */
< } else {
< /* Otherwise set the card in netmap mode
---
> if (!nm_netmap_on(na)) {
> /* Netmap not active, set the card in netmap mode
1615c1950
< na->na_lut = na->nm_mem->pools[NETMAP_BUF_POOL].lut;
---
> na->na_lut = netmap_mem_get_lut(na->nm_mem);
1617c1952,1953
< na->na_lut_objtotal = na->nm_mem->pools[NETMAP_BUF_POOL].objtotal;
---
> na->na_lut_objtotal = netmap_mem_get_buftotal(na->nm_mem);
> na->na_lut_objsize = netmap_mem_get_bufsize(na->nm_mem);
1627d1962
< priv->np_na = NULL;
1632a1968
> priv->np_na = NULL;
1665d2000
< struct ifnet *ifp = NULL;
1743c2078,2080
< || i == NETMAP_BDG_VNET_HDR) {
---
> || i == NETMAP_BDG_VNET_HDR
> || i == NETMAP_BDG_NEWIF
> || i == NETMAP_BDG_DELIF) {
1765d2101
< ifp = na->ifp;
1827,1829c2163
< ifp = na->ifp;
< if (ifp == NULL) {
< RD(1, "the ifp is gone");
---
> if (!nm_netmap_on(na)) {
1872a2207,2209
> case NIOCCONFIG:
> error = netmap_bdg_config(nmr);
> break;
1888a2226
> struct ifnet *ifp;
1938d2275
< struct ifnet *ifp;
1977,1982d2313
< ifp = na->ifp;
< // check for deleted
< if (ifp == NULL) {
< RD(1, "the ifp is gone");
< return POLLERR;
< }
1984c2315
< if ( (ifp->if_capenable & IFCAP_NETMAP) == 0)
---
> if (!nm_netmap_on(na))
1988c2319
< D("device %s events 0x%x", NM_IFPNAME(ifp), events);
---
> D("device %s events 0x%x", na->name, events);
2059d2389
<
2117a2448,2449
> * XXX NR_FORWARD should only be read on
> * physical or NIC ports
2144,2149c2476,2482
< if (netmap_fwd || kring->ring->flags & NR_FORWARD) {
< send_down = netmap_rxsync_from_host(na, td, dev);
< if (send_down && (netmap_no_timestamp == 0 ||
< kring->ring->flags & NR_TIMESTAMP)) {
< microtime(&kring->ring->ts);
< }
---
> if (check_all_rx
> && (netmap_fwd || kring->ring->flags & NR_FORWARD)) {
> /* XXX fix to use kring fields */
> if (nm_ring_empty(kring->ring))
> send_down = netmap_rxsync_from_host(na, td, dev);
> if (!nm_ring_empty(kring->ring))
> revents |= want_rx;
2177c2510
< if (q.head)
---
> if (q.head && na->ifp != NULL)
2227c2560
< ifp->if_xname, na->num_tx_rings, na->num_rx_rings);
---
> na->name, na->num_tx_rings, na->num_rx_rings);
2230c2563,2570
< WNA(ifp) = na;
---
> /* ifp is NULL for virtual adapters (bwrap, non-persistent VALE ports,
> * pipes, monitors). For bwrap we actually have a non-null ifp for
> * use by the external modules, but that is set after this
> * function has been called.
> * XXX this is ugly, maybe split this function in two (2014-03-14)
> */
> if (ifp != NULL) {
> WNA(ifp) = na;
2236c2576
< na->if_input = ifp->if_input; /* for netmap_send_up */
---
> na->if_input = ifp->if_input; /* for netmap_send_up */
2239c2579,2580
< NETMAP_SET_CAPABLE(ifp);
---
> NETMAP_SET_CAPABLE(ifp);
> }
2252a2594
> /* use the global allocator */
2253a2596,2600
> if (na->nm_bdg_attach == NULL)
> /* no special nm_bdg_attach callback. On VALE
> * attach, we need to interpose a bwrap
> */
> na->nm_bdg_attach = netmap_bwrap_attach;
2275a2623,2637
> /* Wrapper for the register callback provided hardware drivers.
> * na->ifp == NULL means the the driver module has been
> * unloaded, so we cannot call into it.
> * Note that module unloading, in our patched linux drivers,
> * happens under NMG_LOCK and after having stopped all the
> * nic rings (see netmap_detach). This provides sufficient
> * protection for the other driver-provied callbacks
> * (i.e., nm_config and nm_*xsync), that therefore don't need
> * to wrapped.
> */
> static int
> netmap_hw_register(struct netmap_adapter *na, int onoff)
> {
> struct netmap_hw_adapter *hwna =
> (struct netmap_hw_adapter*)na;
2276a2639,2645
> if (na->ifp == NULL)
> return onoff ? ENXIO : 0;
>
> return hwna->nm_hw_register(na, onoff);
> }
>
>
2300a2670,2672
> strncpy(hwna->up.name, ifp->if_xname, sizeof(hwna->up.name));
> hwna->nm_hw_register = hwna->up.nm_register;
> hwna->up.nm_register = netmap_hw_register;
2316a2689,2698
> if (ifp->ethtool_ops) {
> hwna->nm_eto = *ifp->ethtool_ops;
> }
> hwna->nm_eto.set_ringparam = linux_netmap_set_ringparam;
> #ifdef ETHTOOL_SCHANNELS
> hwna->nm_eto.set_channels = linux_netmap_set_channels;
> #endif
> if (arg->nm_config == NULL) {
> hwna->up.nm_config = netmap_linux_config;
> }
2320c2702
< NM_IFPNAME(ifp),
---
> hwna->up.name,
2395a2778,2779
> // XXX also clear NAF_NATIVE_ON ?
> na->na_flags &= ~NAF_NETMAP_ON;
2429,2430c2813,2814
< if ( (ifp->if_capenable & IFCAP_NETMAP) == 0) {
< D("%s not in netmap mode anymore", NM_IFPNAME(ifp));
---
> if (!nm_netmap_on(na)) {
> D("%s not in netmap mode anymore", na->name);
2439,2441c2823,2825
< if (len > NETMAP_BDG_BUF_SIZE(na->nm_mem)) { /* too long for us */
< D("%s from_host, drop packet size %d > %d", NM_IFPNAME(ifp),
< len, NETMAP_BDG_BUF_SIZE(na->nm_mem));
---
> if (len > NETMAP_BUF_SIZE(na)) { /* too long for us */
> D("%s from_host, drop packet size %d > %d", na->name,
> len, NETMAP_BUF_SIZE(na));
2457c2841
< NM_IFPNAME(ifp), kring->nr_hwcur, kring->nr_hwtail, mbq_len(q),
---
> na->name, kring->nr_hwcur, kring->nr_hwtail, mbq_len(q),
2462c2846
< NM_IFPNAME(ifp), mbq_len(q), len, m);
---
> na->name, mbq_len(q), len, m);
2495,2500c2879,2880
< if (na == NULL) {
< D("NULL na, should not happen");
< return NULL; /* no netmap support here */
< }
< if (!(na->ifp->if_capenable & IFCAP_NETMAP)) {
< ND("interface not in netmap mode");
---
> if (!nm_native_on(na)) {
> ND("interface not in native netmap mode");
2531c2911
< NM_IFPNAME(na->ifp),
---
> na->name,
2573,2574c2953,2955
< * - for a switch, call the proper forwarding routine
< * - XXX more ?
---
> * (see netmap_notify)
> * - for a nic connected to a switch, call the proper forwarding routine
> * (see netmap_bwrap_intr_notify)
2623,2624c3004,3012
< // XXX could we check NAF_NATIVE_ON ?
< if (!(ifp->if_capenable & IFCAP_NETMAP))
---
> struct netmap_adapter *na = NA(ifp);
>
> /*
> * XXX emulated netmap mode sets NAF_SKIP_INTR so
> * we still use the regular driver even though the previous
> * check fails. It is unclear whether we should use
> * nm_native_on() here.
> */
> if (!nm_netmap_on(na))
2627c3015
< if (NA(ifp)->na_flags & NAF_SKIP_INTR) {
---
> if (na->na_flags & NAF_SKIP_INTR) {
2679a3068,3070
> #ifdef __FreeBSD__
> nm_vi_init_index();
> #endif