@@ -23,6 +23,16 @@
#define NETMAP_BLOCKING_IO
+/* Since we allow more than one thread to open the same device
+ * this struct uinquely identifies a device so that proper locking
+ * can be implemented
+ */
+typedef struct {
+ char ifname[IFNAMSIZ];
+ odp_spinlock_t rx_lock;
+ odp_spinlock_t tx_lock;
+} netmap_dev_t;
+
/** Packet socket using netmap mmaped rings for both Rx and Tx */
typedef struct {
odp_buffer_pool_t pool;
@@ -34,7 +44,7 @@ typedef struct {
uint32_t if_flags;
odp_packet_t *pkt_table;/** Used by recv_pkt_netmap */
int nb_rx; /** Used by recv_pkt_netmap */
- char ifname[IFNAMSIZ];
+ netmap_dev_t *nm_dev;
} pkt_netmap_t;
/**
@@ -58,11 +58,17 @@
static struct nm_desc mmap_desc; /** Used to store the mmap address;
filled in first time, used for
subsequent calls to nm_open */
-static odp_spinlock_t mmap_desc_lock;
+static odp_spinlock_t nm_global_lock; /** Global lock for mmap addr and
+ dev lookup */
+
+#define MAX_DEVS 32
+static netmap_dev_t netmap_devs[MAX_DEVS];
+static int nm_dev_cnt;
int odp_netmap_init_global(void)
{
- odp_spinlock_init(&mmap_desc_lock);
+ odp_spinlock_init(&nm_global_lock);
+ memset(netmap_devs, 0, sizeof(netmap_devs));
return 0;
}
@@ -81,7 +87,7 @@ static int nm_do_ioctl(pkt_netmap_t * const pkt_nm, unsigned long cmd,
}
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, pkt_nm->ifname, sizeof(ifr.ifr_name));
+ strncpy(ifr.ifr_name, pkt_nm->nm_dev->ifname, sizeof(ifr.ifr_name));
switch (cmd) {
case SIOCSIFFLAGS:
@@ -125,7 +131,12 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
odp_packet_t pkt;
uint8_t *pkt_buf;
uint8_t *l2_hdr;
- int ret;
+ int i, ret;
+
+ if (nm_dev_cnt == MAX_DEVS) {
+ ODP_ERR("Maximum number of devices reached: %d\n", nm_dev_cnt);
+ return -1;
+ }
if (pool == ODP_BUFFER_POOL_INVALID)
return -1;
@@ -146,10 +157,9 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
odph_packet_free(pkt);
- snprintf(pkt_nm->ifname, sizeof(pkt_nm->ifname), "%s", netdev);
snprintf(ifname, sizeof(ifname), "netmap:%s", netdev);
- odp_spinlock_lock(&mmap_desc_lock);
+ odp_spinlock_lock(&nm_global_lock);
ODP_DBG("[%04d] Initial mmap addr: %p\n",
odp_thread_id(),
mmap_desc.mem);
@@ -162,7 +172,7 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
if (pkt_nm->desc == NULL) {
ODP_ERR("Error opening nm interface: %s\n", strerror(errno));
- odp_spinlock_unlock(&mmap_desc_lock);
+ odp_spinlock_unlock(&nm_global_lock);
return -1;
}
@@ -170,7 +180,23 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
mmap_desc.mem = pkt_nm->desc->mem;
mmap_desc.memsize = pkt_nm->desc->memsize;
}
- odp_spinlock_unlock(&mmap_desc_lock);
+
+ /* Lookup dev */
+ for (i = 0; i < nm_dev_cnt; i++) {
+ if (!strcmp(netmap_devs[i].ifname, netdev)) {
+ pkt_nm->nm_dev = &netmap_devs[i];
+ break;
+ }
+ }
+ if (i == nm_dev_cnt) {
+ nm_dev_cnt++;
+ snprintf(netmap_devs[i].ifname, sizeof(netmap_devs[i].ifname),
+ "%s", netdev);
+ odp_spinlock_init(&netmap_devs[i].rx_lock);
+ odp_spinlock_init(&netmap_devs[i].tx_lock);
+ pkt_nm->nm_dev = &netmap_devs[i];
+ }
+ odp_spinlock_unlock(&nm_global_lock);
ODP_DBG("[%04d] mmap addr %p\n",
odp_thread_id(),
@@ -182,7 +208,7 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
if ((pkt_nm->if_flags & IFF_UP) == 0) {
ODP_DBG("[%04d] %s is down, bringing up...\n",
odp_thread_id(),
- pkt_nm->ifname);
+ pkt_nm->nm_dev->ifname);
pkt_nm->if_flags |= IFF_UP;
}
if (ETH_PROMISC) {
@@ -293,7 +319,10 @@ int recv_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
pkt_nm->pkt_table = pkt_table;
pkt_nm->nb_rx = 0;
+
+ odp_spinlock_lock(&pkt_nm->nm_dev->rx_lock);
nm_dispatch(pkt_nm->desc, len, nm_recv_cb, (uint8_t *)pkt_nm);
+ odp_spinlock_unlock(&pkt_nm->nm_dev->rx_lock);
if (pkt_nm->nb_rx)
ODP_DBG("[%04d] <=== rcvd %03u frames from netmap adapter\n",
@@ -322,6 +351,7 @@ int send_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
ioctl(fd, NIOCTXSYNC, NULL);
#endif
+ odp_spinlock_lock(&pkt_nm->nm_dev->tx_lock);
for (nb_tx = 0; nb_tx < len; nb_tx++) {
odp_packet_t pkt = pkt_table[nb_tx];
uint8_t *frame = odp_packet_l2(pkt);
@@ -329,6 +359,7 @@ int send_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
if (nm_inject(pkt_nm->desc, frame, frame_len))
break;
}
+ odp_spinlock_unlock(&pkt_nm->nm_dev->tx_lock);
if (nb_tx)
ODP_DBG("[%04d] ===> sent %03u frames to netmap adapter\n",
Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org> --- platform/linux-netmap/include/odp_packet_netmap.h | 12 +++++- platform/linux-netmap/odp_packet_netmap.c | 49 ++++++++++++++++++----- 2 files changed, 51 insertions(+), 10 deletions(-)