Skip to content

Commit 566ae40

Browse files
committed
Keep adaptor's rings either in normal or netmap mode
After this commit, when an adapter is put in Netmap mode, all of its rings that are not requested to be in Netmap mode are kept in normal mode, which is they are still attached to the host stack. Moreover, if a packet is going to hit a TX ring which is in Netmap mode, the packets will be copied to the RX host ring.
1 parent d27e31c commit 566ae40

2 files changed

Lines changed: 132 additions & 1 deletion

File tree

sys/dev/netmap/netmap.c

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ netmap_krings_create(struct netmap_adapter *na, u_int tailroom)
815815
kring->ring_id = i;
816816
kring->tx = t;
817817
kring->nkr_num_slots = ndesc;
818+
kring->nr_mode = NKR_NETMAP_OFF;
819+
kring->nr_pending_mode = NKR_NETMAP_OFF;
818820
if (i < nma_get_nrings(na, t)) {
819821
kring->nm_sync = (t == NR_TX ? na->nm_txsync : na->nm_rxsync);
820822
} else {
@@ -909,11 +911,20 @@ static void
909911
netmap_do_unregif(struct netmap_priv_d *priv)
910912
{
911913
struct netmap_adapter *na = priv->np_na;
914+
enum txrx t;
915+
int i;
912916

913917
NMG_LOCK_ASSERT();
914918
na->active_fds--;
915919
/* release exclusive use if it was requested on regif */
916920
netmap_rel_exclusive(priv);
921+
922+
for_rx_tx(t) {
923+
for (i = priv->np_qfirst[t]; i < priv->np_qlast[t]; i++) {
924+
kring_rel_netmap_mode(priv, t, i);
925+
}
926+
}
927+
917928
if (na->active_fds <= 0) { /* last instance */
918929

919930
if (netmap_verbose)
@@ -948,6 +959,10 @@ netmap_do_unregif(struct netmap_priv_d *priv)
948959
/* delete rings and buffers */
949960
netmap_mem_rings_delete(na);
950961
na->nm_krings_delete(na);
962+
} else {
963+
if (kring_pending(priv)) {
964+
na->nm_register(na, 1);
965+
}
951966
}
952967
/* possibily decrement counter of tx_si/rx_si users */
953968
netmap_unset_ringid(priv);
@@ -1971,6 +1986,8 @@ netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na,
19711986
{
19721987
struct netmap_if *nifp = NULL;
19731988
int error;
1989+
enum txrx t;
1990+
int i;
19741991

19751992
NMG_LOCK_ASSERT();
19761993
/* ring configuration may have changed, fetch from the card */
@@ -2011,6 +2028,12 @@ netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na,
20112028
if (error)
20122029
goto err_del_rings;
20132030

2031+
for_rx_tx(t) {
2032+
for (i = priv->np_qfirst[t]; i < priv->np_qlast[t]; i++) {
2033+
kring_get_netmap_mode(priv, t, i);
2034+
}
2035+
}
2036+
20142037
/* in all cases, create a new netmap if */
20152038
nifp = netmap_mem_if_new(na);
20162039
if (nifp == NULL) {
@@ -2032,6 +2055,10 @@ netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na,
20322055
error = na->nm_register(na, 1); /* mode on */
20332056
if (error)
20342057
goto err_del_if;
2058+
} else {
2059+
if (kring_pending(priv)) {
2060+
na->nm_register(na, 1);
2061+
}
20352062
}
20362063

20372064
/*
@@ -2050,6 +2077,12 @@ netmap_do_regif(struct netmap_priv_d *priv, struct netmap_adapter *na,
20502077
netmap_mem_if_delete(na, nifp);
20512078
err_rel_excl:
20522079
netmap_rel_exclusive(priv);
2080+
2081+
for_rx_tx(t) {
2082+
for (i = priv->np_qfirst[t]; i < priv->np_qlast[t]; i++) {
2083+
kring_rel_netmap_mode(priv, t, i);
2084+
}
2085+
}
20532086
err_del_rings:
20542087
if (na->active_fds == 0)
20552088
netmap_mem_rings_delete(na);
@@ -2940,11 +2973,12 @@ int
29402973
netmap_transmit(struct ifnet *ifp, struct mbuf *m)
29412974
{
29422975
struct netmap_adapter *na = NA(ifp);
2943-
struct netmap_kring *kring;
2976+
struct netmap_kring *kring, *tx_kring;
29442977
u_int len = MBUF_LEN(m);
29452978
u_int error = ENOBUFS;
29462979
struct mbq *q;
29472980
int space;
2981+
int txr;
29482982

29492983
kring = &na->rx_rings[na->num_rx_rings];
29502984
// XXX [Linux] we do not need this lock
@@ -2957,6 +2991,23 @@ netmap_transmit(struct ifnet *ifp, struct mbuf *m)
29572991
goto done;
29582992
}
29592993

2994+
#if defined (__FreeBSD__)
2995+
txr = m->m_pkthdr.flowid;
2996+
tx_kring = &NMR(na, NR_TX)[txr];
2997+
2998+
if (tx_kring->nr_mode == NKR_NETMAP_OFF) {
2999+
return na->if_transmit(ifp, m);
3000+
}
3001+
3002+
#elif defined (linux)
3003+
txr = m->queue_mapping;
3004+
tx_kring = &NMR(na, NR_TX)[txr];
3005+
3006+
if (tx_kring->nr_mode == NKR_NETMAP_OFF) {
3007+
return ((struct net_device_ops *) na->if_transmit)->ndo_start_xmit(m, ifp);
3008+
}
3009+
#endif
3010+
29603011
q = &kring->rx_queue;
29613012

29623013
// XXX reconsider long packets if we handle fragments
@@ -3032,13 +3083,26 @@ netmap_reset(struct netmap_adapter *na, enum txrx tx, u_int n,
30323083
if (tx == NR_TX) {
30333084
if (n >= na->num_tx_rings)
30343085
return NULL;
3086+
30353087
kring = na->tx_rings + n;
3088+
3089+
if (kring->nr_pending_mode == NKR_NETMAP_OFF) {
3090+
kring->nr_mode = NKR_NETMAP_OFF;
3091+
return NULL;
3092+
}
3093+
30363094
// XXX check whether we should use hwcur or rcur
30373095
new_hwofs = kring->nr_hwcur - new_cur;
30383096
} else {
30393097
if (n >= na->num_rx_rings)
30403098
return NULL;
30413099
kring = na->rx_rings + n;
3100+
3101+
if (kring->nr_pending_mode == NKR_NETMAP_OFF) {
3102+
kring->nr_mode = NKR_NETMAP_OFF;
3103+
return NULL;
3104+
}
3105+
30423106
new_hwofs = kring->nr_hwtail - new_cur;
30433107
}
30443108
lim = kring->nkr_num_slots - 1;
@@ -3075,6 +3139,7 @@ netmap_reset(struct netmap_adapter *na, enum txrx tx, u_int n,
30753139
* We do the wakeup here, but the ring is not yet reconfigured.
30763140
* However, we are under lock so there are no races.
30773141
*/
3142+
kring->nr_mode = NKR_NETMAP_ON;
30783143
kring->nm_notify(kring, 0);
30793144
return kring->ring->slot;
30803145
}
@@ -3111,10 +3176,15 @@ netmap_common_irq(struct netmap_adapter *na, u_int q, u_int *work_done)
31113176

31123177
kring = NMR(na, t) + q;
31133178

3179+
if (kring->nr_mode == NKR_NETMAP_OFF) {
3180+
return 0;
3181+
}
3182+
31143183
if (t == NR_RX) {
31153184
kring->nr_kflags |= NKR_PENDINTR; // XXX atomic ?
31163185
*work_done = 1; /* do not fire napi again */
31173186
}
3187+
31183188
kring->nm_notify(kring, 0);
31193189
return 1;
31203190
}

sys/dev/netmap/netmap_kern.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,12 @@ struct netmap_kring {
378378
#define NKR_FORWARD 0x4 /* (host ring only) there are
379379
packets to forward
380380
*/
381+
382+
uint32_t nr_mode;
383+
uint32_t nr_pending_mode;
384+
#define NKR_NETMAP_OFF 0x0
385+
#define NKR_NETMAP_ON 0x1
386+
381387
uint32_t nkr_num_slots;
382388

383389
/*
@@ -1153,6 +1159,10 @@ nm_set_native_flags(struct netmap_adapter *na)
11531159
{
11541160
struct ifnet *ifp = na->ifp;
11551161

1162+
if (na->na_refcount > 2) {
1163+
return;
1164+
}
1165+
11561166
na->na_flags |= NAF_NETMAP_ON;
11571167
#ifdef IFCAP_NETMAP /* or FreeBSD ? */
11581168
ifp->if_capenable |= IFCAP_NETMAP;
@@ -1708,6 +1718,57 @@ struct netmap_priv_d {
17081718
struct netmap_priv_d *netmap_priv_new(void);
17091719
void netmap_priv_delete(struct netmap_priv_d *);
17101720

1721+
static inline void kring_get_netmap_mode(struct netmap_priv_d *np, enum txrx ring_txrx, int ring_nr)
1722+
{
1723+
struct netmap_adapter *na = np->np_na;
1724+
struct netmap_kring *kring = &NMR(na, ring_txrx)[ring_nr];
1725+
1726+
kring->nr_pending_mode = NKR_NETMAP_ON;
1727+
if (kring->ring_id == nma_get_nrings(na, ring_txrx)) {
1728+
/*
1729+
* If this is a sw ring, just set the mode on (no need to
1730+
* wait for netmap_reset())
1731+
*/
1732+
kring->nr_mode = NKR_NETMAP_ON;
1733+
}
1734+
}
1735+
1736+
static inline void kring_rel_netmap_mode(struct netmap_priv_d *np, enum txrx ring_txrx, int ring_nr)
1737+
{
1738+
struct netmap_adapter *na = np->np_na;
1739+
struct netmap_kring *kring = &NMR(na, ring_txrx)[ring_nr];
1740+
1741+
/*
1742+
* try to release the ring (i.e. put it in normal mode).
1743+
* The ring can actually be released only if there are no users
1744+
* using it. (users counter is managed by netmap_get_exclusive and
1745+
* netmap_rel_exclusive)
1746+
*/
1747+
if (kring->users == 0) {
1748+
kring->nr_pending_mode = NKR_NETMAP_OFF;
1749+
if (kring->ring_id == nma_get_nrings(na, ring_txrx)) {
1750+
kring->nr_mode = NKR_NETMAP_OFF;
1751+
}
1752+
}
1753+
}
1754+
1755+
static inline int kring_pending(struct netmap_priv_d *np)
1756+
{
1757+
struct netmap_adapter *na = np->np_na;
1758+
enum txrx t;
1759+
int i;
1760+
1761+
for_rx_tx(t) {
1762+
for (i = np->np_qfirst[t]; i < np->np_qlast[t]; i++) {
1763+
struct netmap_kring *kring = &NMR(na, t)[i];
1764+
if (kring->nr_mode != kring->nr_pending_mode) {
1765+
return 1;
1766+
}
1767+
}
1768+
}
1769+
return 0;
1770+
}
1771+
17111772
#ifdef WITH_MONITOR
17121773

17131774
struct netmap_monitor_adapter {

0 commit comments

Comments
 (0)