@@ -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
909911netmap_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 );
20512078err_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+ }
20532086err_del_rings :
20542087 if (na -> active_fds == 0 )
20552088 netmap_mem_rings_delete (na );
@@ -2940,11 +2973,12 @@ int
29402973netmap_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}
0 commit comments