diff options
| author | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2018-12-05 11:57:16 +0000 |
|---|---|---|
| committer | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2018-12-05 11:57:16 +0000 |
| commit | b6e66be22bdce2aadcf52ee6230faa1e6cd3f805 (patch) | |
| tree | e9311c45835e19b2d58f105e0627078f15f1cd63 /sys/dev/netmap/netmap_kern.h | |
| parent | abc73e04c2a0add60dea19c7aab5a0a4d51ab418 (diff) | |
Notes
Diffstat (limited to 'sys/dev/netmap/netmap_kern.h')
| -rw-r--r-- | sys/dev/netmap/netmap_kern.h | 341 |
1 files changed, 210 insertions, 131 deletions
diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h index 4abd16b6d17f..5f21f586c46b 100644 --- a/sys/dev/netmap/netmap_kern.h +++ b/sys/dev/netmap/netmap_kern.h @@ -54,30 +54,31 @@ #if defined(CONFIG_NETMAP_GENERIC) #define WITH_GENERIC #endif -#if defined(CONFIG_NETMAP_PTNETMAP_GUEST) -#define WITH_PTNETMAP_GUEST -#endif -#if defined(CONFIG_NETMAP_PTNETMAP_HOST) -#define WITH_PTNETMAP_HOST +#if defined(CONFIG_NETMAP_PTNETMAP) +#define WITH_PTNETMAP #endif #if defined(CONFIG_NETMAP_SINK) #define WITH_SINK #endif +#if defined(CONFIG_NETMAP_NULL) +#define WITH_NMNULL +#endif #elif defined (_WIN32) #define WITH_VALE // comment out to disable VALE support #define WITH_PIPES #define WITH_MONITOR #define WITH_GENERIC +#define WITH_NMNULL #else /* neither linux nor windows */ #define WITH_VALE // comment out to disable VALE support #define WITH_PIPES #define WITH_MONITOR #define WITH_GENERIC -#define WITH_PTNETMAP_HOST /* ptnetmap host support */ -#define WITH_PTNETMAP_GUEST /* ptnetmap guest support */ +#define WITH_PTNETMAP /* ptnetmap guest support */ #define WITH_EXTMEM +#define WITH_NMNULL #endif #if defined(__FreeBSD__) @@ -239,28 +240,39 @@ typedef struct hrtimer{ #define NMG_LOCK_ASSERT() NM_MTX_ASSERT(netmap_global_lock) #if defined(__FreeBSD__) -#define nm_prerr printf -#define nm_prinf printf +#define nm_prerr_int printf +#define nm_prinf_int printf #elif defined (_WIN32) -#define nm_prerr DbgPrint -#define nm_prinf DbgPrint +#define nm_prerr_int DbgPrint +#define nm_prinf_int DbgPrint #elif defined(linux) -#define nm_prerr(fmt, arg...) printk(KERN_ERR fmt, ##arg) -#define nm_prinf(fmt, arg...) printk(KERN_INFO fmt, ##arg) +#define nm_prerr_int(fmt, arg...) printk(KERN_ERR fmt, ##arg) +#define nm_prinf_int(fmt, arg...) printk(KERN_INFO fmt, ##arg) #endif -#define ND(format, ...) -#define D(format, ...) \ +#define nm_prinf(format, ...) \ + do { \ + struct timeval __xxts; \ + microtime(&__xxts); \ + nm_prinf_int("%03d.%06d [%4d] %-25s " format "\n",\ + (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ + __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define nm_prerr(format, ...) \ do { \ struct timeval __xxts; \ microtime(&__xxts); \ - nm_prerr("%03d.%06d [%4d] %-25s " format "\n", \ + nm_prerr_int("%03d.%06d [%4d] %-25s " format "\n",\ (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \ __LINE__, __FUNCTION__, ##__VA_ARGS__); \ } while (0) -/* rate limited, lps indicates how many per second */ -#define RD(lps, format, ...) \ +/* Disabled printf (used to be ND). */ +#define nm_prdis(format, ...) + +/* Rate limited, lps indicates how many per second. */ +#define nm_prlim(lps, format, ...) \ do { \ static int t0, __cnt; \ if (t0 != time_second) { \ @@ -268,9 +280,14 @@ typedef struct hrtimer{ __cnt = 0; \ } \ if (__cnt++ < lps) \ - D(format, ##__VA_ARGS__); \ + nm_prinf(format, ##__VA_ARGS__); \ } while (0) +/* Old macros. */ +#define ND nm_prdis +#define D nm_prerr +#define RD nm_prlim + struct netmap_adapter; struct nm_bdg_fwd; struct nm_bridge; @@ -700,7 +717,7 @@ struct netmap_adapter { */ #define NAF_HOST_RINGS 64 /* the adapter supports the host rings */ #define NAF_FORCE_NATIVE 128 /* the adapter is always NATIVE */ -#define NAF_PTNETMAP_HOST 256 /* the adapter supports ptnetmap in the host */ +/* free */ #define NAF_MOREFRAG 512 /* the adapter supports NS_MOREFRAG */ #define NAF_ZOMBIE (1U<<30) /* the nic driver has been unloaded */ #define NAF_BUSY (1U<<31) /* the adapter is used internally and @@ -718,9 +735,9 @@ struct netmap_adapter { u_int num_tx_desc; /* number of descriptor in each queue */ u_int num_rx_desc; - /* tx_rings and rx_rings are private but allocated - * as a contiguous chunk of memory. Each array has - * N+1 entries, for the adapter queues and for the host queue. + /* tx_rings and rx_rings are private but allocated as a + * contiguous chunk of memory. Each array has N+K entries, + * N for the hardware rings and K for the host rings. */ struct netmap_kring **tx_rings; /* array of TX rings. */ struct netmap_kring **rx_rings; /* array of RX rings. */ @@ -1080,12 +1097,12 @@ struct netmap_bwrap_adapter { */ struct netmap_vp_adapter *saved_na_vp; }; -int nm_bdg_ctl_attach(struct nmreq_header *hdr, void *auth_token); -int nm_bdg_ctl_detach(struct nmreq_header *hdr, void *auth_token); int nm_bdg_polling(struct nmreq_header *hdr); -int netmap_bdg_list(struct nmreq_header *hdr); #ifdef WITH_VALE +int netmap_vale_attach(struct nmreq_header *hdr, void *auth_token); +int netmap_vale_detach(struct nmreq_header *hdr, void *auth_token); +int netmap_vale_list(struct nmreq_header *hdr); int netmap_vi_create(struct nmreq_header *hdr, int); int nm_vi_create(struct nmreq_header *); int nm_vi_destroy(const char *name); @@ -1115,6 +1132,12 @@ struct netmap_pipe_adapter { #endif /* WITH_PIPES */ +#ifdef WITH_NMNULL +struct netmap_null_adapter { + struct netmap_adapter up; +}; +#endif /* WITH_NMNULL */ + /* return slots reserved to rx clients; used in drivers */ static inline uint32_t @@ -1442,51 +1465,8 @@ void netmap_unget_na(struct netmap_adapter *na, struct ifnet *ifp); int netmap_get_hw_na(struct ifnet *ifp, struct netmap_mem_d *nmd, struct netmap_adapter **na); - -/* - * The following bridge-related functions are used by other - * kernel modules. - * - * VALE only supports unicast or broadcast. The lookup - * function can return 0 .. NM_BDG_MAXPORTS-1 for regular ports, - * NM_BDG_MAXPORTS for broadcast, NM_BDG_MAXPORTS+1 to indicate - * drop. - */ -typedef uint32_t (*bdg_lookup_fn_t)(struct nm_bdg_fwd *ft, uint8_t *ring_nr, - struct netmap_vp_adapter *, void *private_data); -typedef int (*bdg_config_fn_t)(struct nm_ifreq *); -typedef void (*bdg_dtor_fn_t)(const struct netmap_vp_adapter *); -typedef void *(*bdg_update_private_data_fn_t)(void *private_data, void *callback_data, int *error); -typedef int (*bdg_vp_create_fn_t)(struct nmreq_header *hdr, - struct ifnet *ifp, struct netmap_mem_d *nmd, - struct netmap_vp_adapter **ret); -typedef int (*bdg_bwrap_attach_fn_t)(const char *nr_name, struct netmap_adapter *hwna); -struct netmap_bdg_ops { - bdg_lookup_fn_t lookup; - bdg_config_fn_t config; - bdg_dtor_fn_t dtor; - bdg_vp_create_fn_t vp_create; - bdg_bwrap_attach_fn_t bwrap_attach; - char name[IFNAMSIZ]; -}; -int netmap_bwrap_attach(const char *name, struct netmap_adapter *, struct netmap_bdg_ops *); -int netmap_bdg_regops(const char *name, struct netmap_bdg_ops *bdg_ops, void *private_data, void *auth_token); - -#define NM_BRIDGES 8 /* number of bridges */ -#define NM_BDG_MAXPORTS 254 /* up to 254 */ -#define NM_BDG_BROADCAST NM_BDG_MAXPORTS -#define NM_BDG_NOPORT (NM_BDG_MAXPORTS+1) - -struct nm_bridge *netmap_init_bridges2(u_int); -void netmap_uninit_bridges2(struct nm_bridge *, u_int); -int netmap_init_bridges(void); -void netmap_uninit_bridges(void); -int nm_bdg_update_private_data(const char *name, bdg_update_private_data_fn_t callback, - void *callback_data, void *auth_token); -int netmap_bdg_config(struct nm_ifreq *nifr); - #ifdef WITH_VALE -uint32_t netmap_bdg_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring, +uint32_t netmap_vale_learning(struct nm_bdg_fwd *ft, uint8_t *dst_ring, struct netmap_vp_adapter *, void *private_data); /* these are redefined in case of no VALE support */ @@ -1525,11 +1505,20 @@ void netmap_monitor_stop(struct netmap_adapter *na); (((struct nmreq_register *)(uintptr_t)hdr->nr_body)->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX) ? EOPNOTSUPP : 0) #endif +#ifdef WITH_NMNULL +int netmap_get_null_na(struct nmreq_header *hdr, struct netmap_adapter **na, + struct netmap_mem_d *nmd, int create); +#else /* !WITH_NMNULL */ +#define netmap_get_null_na(hdr, _2, _3, _4) \ + (((struct nmreq_register *)(uintptr_t)hdr->nr_body)->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX) ? EOPNOTSUPP : 0) +#endif /* WITH_NMNULL */ + #ifdef CONFIG_NET_NS struct net *netmap_bns_get(void); void netmap_bns_put(struct net *); void netmap_bns_getbridges(struct nm_bridge **, u_int *); #else +extern struct nm_bridge *nm_bridges; #define netmap_bns_get() #define netmap_bns_put(_1) #define netmap_bns_getbridges(b, n) \ @@ -1591,16 +1580,24 @@ int netmap_adapter_put(struct netmap_adapter *na); #define NETMAP_BUF_SIZE(_na) ((_na)->na_lut.objsize) extern int netmap_no_pendintr; extern int netmap_mitigate; -extern int netmap_verbose; /* for debugging */ -enum { /* verbose flags */ - NM_VERB_ON = 1, /* generic verbose */ - NM_VERB_HOST = 0x2, /* verbose host stack */ - NM_VERB_RXSYNC = 0x10, /* verbose on rxsync/txsync */ - NM_VERB_TXSYNC = 0x20, - NM_VERB_RXINTR = 0x100, /* verbose on rx/tx intr (driver) */ - NM_VERB_TXINTR = 0x200, - NM_VERB_NIC_RXSYNC = 0x1000, /* verbose on rx/tx intr (driver) */ - NM_VERB_NIC_TXSYNC = 0x2000, +extern int netmap_verbose; +#ifdef CONFIG_NETMAP_DEBUG +extern int netmap_debug; /* for debugging */ +#else /* !CONFIG_NETMAP_DEBUG */ +#define netmap_debug (0) +#endif /* !CONFIG_NETMAP_DEBUG */ +enum { /* debug flags */ + NM_DEBUG_ON = 1, /* generic debug messsages */ + NM_DEBUG_HOST = 0x2, /* debug host stack */ + NM_DEBUG_RXSYNC = 0x10, /* debug on rxsync/txsync */ + NM_DEBUG_TXSYNC = 0x20, + NM_DEBUG_RXINTR = 0x100, /* debug on rx/tx intr (driver) */ + NM_DEBUG_TXINTR = 0x200, + NM_DEBUG_NIC_RXSYNC = 0x1000, /* debug on rx/tx intr (driver) */ + NM_DEBUG_NIC_TXSYNC = 0x2000, + NM_DEBUG_MEM = 0x4000, /* verbose memory allocations/deallocations */ + NM_DEBUG_VALE = 0x8000, /* debug messages from memory allocators */ + NM_DEBUG_BDG = NM_DEBUG_VALE, }; extern int netmap_txsync_retry; @@ -1612,7 +1609,6 @@ extern int netmap_generic_rings; #ifdef linux extern int netmap_generic_txqdisc; #endif -extern int ptnetmap_tx_workers; /* * NA returns a pointer to the struct netmap adapter from the ifp. @@ -1809,6 +1805,11 @@ static inline int netmap_idx_n2k(struct netmap_kring *kr, int idx) { int n = kr->nkr_num_slots; + + if (likely(kr->nkr_hwofs == 0)) { + return idx; + } + idx += kr->nkr_hwofs; if (idx < 0) return idx + n; @@ -1823,6 +1824,11 @@ static inline int netmap_idx_k2n(struct netmap_kring *kr, int idx) { int n = kr->nkr_num_slots; + + if (likely(kr->nkr_hwofs == 0)) { + return idx; + } + idx -= kr->nkr_hwofs; if (idx < 0) return idx + n; @@ -1911,6 +1917,9 @@ struct netmap_priv_d { u_int np_qfirst[NR_TXRX], np_qlast[NR_TXRX]; /* range of tx/rx rings to scan */ uint16_t np_txpoll; + uint16_t np_kloop_state; /* use with NMG_LOCK held */ +#define NM_SYNC_KLOOP_RUNNING (1 << 0) +#define NM_SYNC_KLOOP_STOPPING (1 << 1) int np_sync_flags; /* to be passed to nm_sync */ int np_refs; /* use with NMG_LOCK held */ @@ -1920,7 +1929,26 @@ struct netmap_priv_d { * number of rings. */ NM_SELINFO_T *np_si[NR_TXRX]; + + /* In the optional CSB mode, the user must specify the start address + * of two arrays of Communication Status Block (CSB) entries, for the + * two directions (kernel read application write, and kernel write + * application read). + * The number of entries must agree with the number of rings bound to + * the netmap file descriptor. The entries corresponding to the TX + * rings are laid out before the ones corresponding to the RX rings. + * + * Array of CSB entries for application --> kernel communication + * (N entries). */ + struct nm_csb_atok *np_csb_atok_base; + /* Array of CSB entries for kernel --> application communication + * (N entries). */ + struct nm_csb_ktoa *np_csb_ktoa_base; + struct thread *np_td; /* kqueue, just debugging */ +#ifdef linux + struct file *np_filp; /* used by sync kloop */ +#endif /* linux */ }; struct netmap_priv_d *netmap_priv_new(void); @@ -1943,6 +1971,14 @@ static inline int nm_kring_pending(struct netmap_priv_d *np) return 0; } +/* call with NMG_LOCK held */ +static __inline int +nm_si_user(struct netmap_priv_d *priv, enum txrx t) +{ + return (priv->np_na != NULL && + (priv->np_qlast[t] - priv->np_qfirst[t] > 1)); +} + #ifdef WITH_PIPES int netmap_pipe_txsync(struct netmap_kring *txkring, int flags); int netmap_pipe_rxsync(struct netmap_kring *rxkring, int flags); @@ -2143,17 +2179,14 @@ void nm_os_vi_init_index(void); * kernel thread routines */ struct nm_kctx; /* OS-specific kernel context - opaque */ -typedef void (*nm_kctx_worker_fn_t)(void *data, int is_kthread); -typedef void (*nm_kctx_notify_fn_t)(void *data); +typedef void (*nm_kctx_worker_fn_t)(void *data); /* kthread configuration */ struct nm_kctx_cfg { long type; /* kthread type/identifier */ nm_kctx_worker_fn_t worker_fn; /* worker function */ void *worker_private;/* worker parameter */ - nm_kctx_notify_fn_t notify_fn; /* notify function */ int attach_user; /* attach kthread to user process */ - int use_kthread; /* use a kthread for the context */ }; /* kthread configuration */ struct nm_kctx *nm_os_kctx_create(struct nm_kctx_cfg *cfg, @@ -2161,47 +2194,24 @@ struct nm_kctx *nm_os_kctx_create(struct nm_kctx_cfg *cfg, int nm_os_kctx_worker_start(struct nm_kctx *); void nm_os_kctx_worker_stop(struct nm_kctx *); void nm_os_kctx_destroy(struct nm_kctx *); -void nm_os_kctx_worker_wakeup(struct nm_kctx *nmk); -void nm_os_kctx_send_irq(struct nm_kctx *); void nm_os_kctx_worker_setaff(struct nm_kctx *, int); u_int nm_os_ncpus(void); -#ifdef WITH_PTNETMAP_HOST -/* - * netmap adapter for host ptnetmap ports - */ -struct netmap_pt_host_adapter { - struct netmap_adapter up; +int netmap_sync_kloop(struct netmap_priv_d *priv, + struct nmreq_header *hdr); +int netmap_sync_kloop_stop(struct netmap_priv_d *priv); - /* the passed-through adapter */ - struct netmap_adapter *parent; - /* parent->na_flags, saved at NETMAP_PT_HOST_CREATE time, - * and restored at NETMAP_PT_HOST_DELETE time */ - uint32_t parent_na_flags; +#ifdef WITH_PTNETMAP +/* ptnetmap guest routines */ - int (*parent_nm_notify)(struct netmap_kring *kring, int flags); - void *ptns; -}; - -/* ptnetmap host-side routines */ -int netmap_get_pt_host_na(struct nmreq_header *hdr, struct netmap_adapter **na, - struct netmap_mem_d * nmd, int create); -int ptnetmap_ctl(const char *nr_name, int create, struct netmap_adapter *na); - -static inline int -nm_ptnetmap_host_on(struct netmap_adapter *na) -{ - return na && na->na_flags & NAF_PTNETMAP_HOST; -} -#else /* !WITH_PTNETMAP_HOST */ -#define netmap_get_pt_host_na(hdr, _2, _3, _4) \ - (((struct nmreq_register *)(uintptr_t)hdr->nr_body)->nr_flags & (NR_PTNETMAP_HOST) ? EOPNOTSUPP : 0) -#define ptnetmap_ctl(_1, _2, _3) EINVAL -#define nm_ptnetmap_host_on(_1) EINVAL -#endif /* !WITH_PTNETMAP_HOST */ - -#ifdef WITH_PTNETMAP_GUEST -/* ptnetmap GUEST routines */ +/* + * ptnetmap_memdev routines used to talk with ptnetmap_memdev device driver + */ +struct ptnetmap_memdev; +int nm_os_pt_memdev_iomap(struct ptnetmap_memdev *, vm_paddr_t *, void **, + uint64_t *); +void nm_os_pt_memdev_iounmap(struct ptnetmap_memdev *); +uint32_t nm_os_pt_memdev_ioread(struct ptnetmap_memdev *, unsigned int); /* * netmap adapter for guest ptnetmap ports @@ -2218,26 +2228,83 @@ struct netmap_pt_guest_adapter { * network stack and netmap clients. * Used to decide when we need (de)allocate krings/rings and * start (stop) ptnetmap kthreads. */ - int backend_regifs; + int backend_users; }; int netmap_pt_guest_attach(struct netmap_adapter *na, unsigned int nifp_offset, unsigned int memid); -struct ptnet_csb_gh; -struct ptnet_csb_hg; -bool netmap_pt_guest_txsync(struct ptnet_csb_gh *ptgh, - struct ptnet_csb_hg *pthg, - struct netmap_kring *kring, - int flags); -bool netmap_pt_guest_rxsync(struct ptnet_csb_gh *ptgh, - struct ptnet_csb_hg *pthg, +bool netmap_pt_guest_txsync(struct nm_csb_atok *atok, + struct nm_csb_ktoa *ktoa, + struct netmap_kring *kring, int flags); +bool netmap_pt_guest_rxsync(struct nm_csb_atok *atok, + struct nm_csb_ktoa *ktoa, struct netmap_kring *kring, int flags); int ptnet_nm_krings_create(struct netmap_adapter *na); void ptnet_nm_krings_delete(struct netmap_adapter *na); void ptnet_nm_dtor(struct netmap_adapter *na); -#endif /* WITH_PTNETMAP_GUEST */ + +/* Guest driver: Write kring pointers (cur, head) to the CSB. + * This routine is coupled with ptnetmap_host_read_kring_csb(). */ +static inline void +ptnetmap_guest_write_kring_csb(struct nm_csb_atok *atok, uint32_t cur, + uint32_t head) +{ + /* + * We need to write cur and head to the CSB but we cannot do it atomically. + * There is no way we can prevent the host from reading the updated value + * of one of the two and the old value of the other. However, if we make + * sure that the host never reads a value of head more recent than the + * value of cur we are safe. We can allow the host to read a value of cur + * more recent than the value of head, since in the netmap ring cur can be + * ahead of head and cur cannot wrap around head because it must be behind + * tail. Inverting the order of writes below could instead result into the + * host to think head went ahead of cur, which would cause the sync + * prologue to fail. + * + * The following memory barrier scheme is used to make this happen: + * + * Guest Host + * + * STORE(cur) LOAD(head) + * mb() <-----------> mb() + * STORE(head) LOAD(cur) + */ + atok->cur = cur; + nm_stst_barrier(); + atok->head = head; +} + +/* Guest driver: Read kring pointers (hwcur, hwtail) from the CSB. + * This routine is coupled with ptnetmap_host_write_kring_csb(). */ +static inline void +ptnetmap_guest_read_kring_csb(struct nm_csb_ktoa *ktoa, + struct netmap_kring *kring) +{ + /* + * We place a memory barrier to make sure that the update of hwtail never + * overtakes the update of hwcur. + * (see explanation in ptnetmap_host_write_kring_csb). + */ + kring->nr_hwtail = ktoa->hwtail; + nm_stst_barrier(); + kring->nr_hwcur = ktoa->hwcur; +} + +/* Helper function wrapping ptnetmap_guest_read_kring_csb(). */ +static inline void +ptnet_sync_tail(struct nm_csb_ktoa *ktoa, struct netmap_kring *kring) +{ + struct netmap_ring *ring = kring->ring; + + /* Update hwcur and hwtail as known by the host. */ + ptnetmap_guest_read_kring_csb(ktoa, kring); + + /* nm_sync_finalize */ + ring->tail = kring->rtail = kring->nr_hwtail; +} +#endif /* WITH_PTNETMAP */ #ifdef __FreeBSD__ /* @@ -2355,4 +2422,16 @@ nm_os_get_mbuf(struct ifnet *ifp, int len) struct nmreq_option * nmreq_findoption(struct nmreq_option *, uint16_t); int nmreq_checkduplicate(struct nmreq_option *); +int netmap_init_bridges(void); +void netmap_uninit_bridges(void); + +/* Functions to read and write CSB fields from the kernel. */ +#if defined (linux) +#define CSB_READ(csb, field, r) (get_user(r, &csb->field)) +#define CSB_WRITE(csb, field, v) (put_user(v, &csb->field)) +#else /* ! linux */ +#define CSB_READ(csb, field, r) (r = fuword32(&csb->field)) +#define CSB_WRITE(csb, field, v) (suword32(&csb->field, v)) +#endif /* ! linux */ + #endif /* _NET_NETMAP_KERN_H_ */ |
