Exemplo n.º 1
0
struct if_netmap_host_context *
if_netmap_register_if(int nmfd, const char *ifname, unsigned int isvale, unsigned int qno)
{
	struct if_netmap_host_context *ctx;

	ctx = calloc(1, sizeof(struct if_netmap_host_context));
	if (NULL == ctx)
		return (NULL);
	
	ctx->fd = nmfd;
	ctx->isvale = isvale;
	ctx->ifname = ifname;

	/*
	 * Disable TCP and checksum offload, which can impact throughput
	 * and also cause packets to be dropped or modified gratuitously.
	 *
	 * Also disable VLAN offload/filtering - we want to talk straight to
	 * the wire.
	 *
	 */

	if (!ctx->isvale) {
		if (0 != if_netmap_set_offload(ctx, 0)) {
			goto fail;
		}

		if (0 != if_netmap_set_promisc(ctx, 1)) {
			goto fail;
		}
	}

	ctx->req.nr_version = NETMAP_API;
	ctx->req.nr_ringid = NETMAP_NO_TX_POLL | NETMAP_HW_RING | qno;
	snprintf(ctx->req.nr_name, sizeof(ctx->req.nr_name), "%s", ifname);

	if (-1 == ioctl(ctx->fd, NIOCREGIF, &ctx->req)) {
		goto fail;
	} 

	ctx->mem = uhi_mmap(NULL, ctx->req.nr_memsize, UHI_PROT_READ | UHI_PROT_WRITE, UHI_MAP_NOCORE | UHI_MAP_SHARED, ctx->fd, 0);
	if (MAP_FAILED == ctx->mem) {
		goto fail;
	}

	ctx->hw_rx_ring = NETMAP_RXRING(NETMAP_IF(ctx->mem, ctx->req.nr_offset), qno);
	ctx->hw_tx_ring = NETMAP_TXRING(NETMAP_IF(ctx->mem, ctx->req.nr_offset), qno);

	/* NIOCREGIF will reset the hardware rings, but the reserved count
	 * might still be non-zero from a previous user's activities
	 */
	ctx->hw_rx_ring->reserved = 0;

	return (ctx);

fail:
	free(ctx);
	return(NULL);
}
Exemplo n.º 2
0
struct netmap_if *
get_if()
{
	void *mmap_addr;
	uint32_t off;
	char *arg;

	/* defaults */
	off = curr_nmr.nr_offset;
	mmap_addr = last_mmap_addr;

	/* first arg: if offset */
	arg = nextarg();
	if (!arg) {
		goto doit;
	}
	off = strtoul(arg, NULL, 0);
	/* second arg: mmap address */
	arg = nextarg();
	if (!arg) {
		goto doit;
	}
	mmap_addr = (void*)strtoul(arg, NULL, 0);
doit:
	return NETMAP_IF(mmap_addr, off);
}
Exemplo n.º 3
0
int
nm_ring (char * ifname, int q, struct netmap_ring ** ring,  int x, int w)
{
	int fd;
	char * mem;
	struct nmreq nmr;
	struct netmap_if * nifp;

	/* open netmap for  ring */

 	fd = open ("/dev/netmap", O_RDWR);
	if (fd < 0) {
		D ("unable to open /dev/netmap");
		return -1;
	}

	memset (&nmr, 0, sizeof (nmr));
	strcpy (nmr.nr_name, ifname);
	nmr.nr_version = NETMAP_API;
	nmr.nr_ringid = q | (NETMAP_NO_TX_POLL | NETMAP_DO_RX_POLL);

	if (w) 
		nmr.nr_flags |= NR_REG_ONE_NIC;
	else 
		nmr.nr_flags |= NR_REG_ALL_NIC;

        if (vale_rings && strncmp (ifname, "vale", 4) == 0) {
                nmr.nr_rx_rings = vale_rings;
                nmr.nr_tx_rings = vale_rings;
        }

	if (ioctl (fd, NIOCREGIF, &nmr) < 0) {
		D ("unable to register interface %s", ifname);
		return -1;
	}

	mem = mmap (NULL, nmr.nr_memsize,
		    PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if (mem == MAP_FAILED) {
		D ("unable to mmap");
		return -1;
	}

	nifp = NETMAP_IF (mem, nmr.nr_offset);

	if (x > 0)
		*ring = NETMAP_TXRING (nifp, q);
	else
		*ring = NETMAP_RXRING (nifp, q);

	return fd;
}
Exemplo n.º 4
0
static int
opennetmap(const char *devstr, struct virtif_user *viu, uint8_t *enaddr)
{
	int fd = -1;
	struct nmreq req;
	int err = 0;

	/* fprintf(stderr, "trying to use netmap on %s\n", devstr); */

	fd = open("/dev/netmap", O_RDWR);
	if (fd == -1) {
		fprintf(stderr, "Unable to open /dev/netmap\n");
		goto out;
	}
	bzero(&req, sizeof(req));
	req.nr_version = NETMAP_API;
	strncpy(req.nr_name, devstr, sizeof(req.nr_name));
	req.nr_ringid = NETMAP_NO_TX_POLL;
	err = ioctl(fd, NIOCREGIF, &req);
	if (err) {
		fprintf(stderr, "Unable to register %s errno  %d\n",
		    req.nr_name, errno);
		goto out;
	}
	/* fprintf(stderr, "need %d MB\n", req.nr_memsize >> 20); */

	viu->nm_mem = mmap(0, req.nr_memsize,
	    PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
	if (viu->nm_mem == MAP_FAILED) {
		fprintf(stderr, "Unable to mmap\n");
		viu->nm_mem = NULL;
		goto out;
	}
	viu->nm_nifp = NETMAP_IF(viu->nm_mem, req.nr_offset);
	/* fprintf(stderr, "netmap:%s mem %d\n", devstr, req.nr_memsize); */

	if (source_hwaddr(devstr, enaddr) != 0) {
		if (strncmp(devstr, "vale", 4) != 0) {
			fprintf(stderr, "netmap:%s: failed to retrieve "
			    "MAC address\n", devstr);
		}
	}

 out:
	if (err && fd != -1) {
		close(fd);
		fd = -1;
	}
	return fd;
}
Exemplo n.º 5
0
static int
netmap_port_open(uint32_t idx)
{
	int err;
	struct netmap_port *port;
	struct nmreq req;

	port = ports.p + idx;

	port->fd = rte_netmap_open("/dev/netmap", O_RDWR);

	snprintf(req.nr_name, sizeof(req.nr_name), "%s", port->str);
	req.nr_version = NETMAP_API;
	req.nr_ringid = 0;

	err = rte_netmap_ioctl(port->fd, NIOCGINFO, &req);
	if (err) {
		printf("[E] NIOCGINFO ioctl failed (error %d)\n", err);
		return err;
	}

	snprintf(req.nr_name, sizeof(req.nr_name), "%s", port->str);
	req.nr_version = NETMAP_API;
	req.nr_ringid = 0;

	err = rte_netmap_ioctl(port->fd, NIOCREGIF, &req);
	if (err) {
		printf("[E] NIOCREGIF ioctl failed (error %d)\n", err);
		return err;
	}

	/* mmap only once. */
	if (ports.mem == NULL)
		ports.mem = rte_netmap_mmap(NULL, req.nr_memsize,
			PROT_WRITE | PROT_READ, MAP_PRIVATE, port->fd, 0);

	if (ports.mem == MAP_FAILED) {
		printf("[E] NETMAP mmap failed for fd: %d)\n", port->fd);
		return -ENOMEM;
	}

	port->nmif = NETMAP_IF(ports.mem, req.nr_offset);

	port->tx_ring = NETMAP_TXRING(port->nmif, 0);
	port->rx_ring = NETMAP_RXRING(port->nmif, 0);

	return 0;
}
Exemplo n.º 6
0
/**
 * Open netmap ring.
 * @param[in,out] ring
 * @param[in] ringid Ring ID.
 * @param[in] cached_mmap_mem Pointer to already mmapped shared netmap memory.
 */
int znm_open(struct znm_ring *ring, const char *ifname, uint16_t ringid, void *cached_mmap_mem)
{
    struct nmreq req;

    ring->fd = open(ZNM_DEVICE, O_RDWR);
    if (ring->fd < 0) {
        ZERO_ELOG(LOG_ERR, "Unable to open %s", ZNM_DEVICE);
        return -1;
    }

    memset(&req, 0, sizeof(req));
    req.nr_version = NETMAP_API;
    strncpy(req.nr_name, ifname, sizeof(req.nr_name));
    req.nr_ringid = ringid;
    req.nr_flags = NR_REG_ONE_NIC;

    if (0 == ioctl(ring->fd, NIOCGINFO, &req)) {
        ring->memsize = req.nr_memsize;
        if (0 == ioctl(ring->fd, NIOCREGIF, &req)) {
            if (NULL != cached_mmap_mem) {
                ring->mem = cached_mmap_mem;
            } else {
                ring->mem = mmap(0, ring->memsize, PROT_WRITE | PROT_READ, MAP_SHARED, ring->fd, 0);
                ring->own_mmap = 1;
            }

            if (MAP_FAILED != ring->mem) {
                ZERO_LOG(LOG_DEBUG, "Attached to %s HW ring %u", ifname, ringid);
                ring->nifp = NETMAP_IF(ring->mem, req.nr_offset);
                ring->tx = NETMAP_TXRING(ring->nifp, ringid);
                ring->rx = NETMAP_RXRING(ring->nifp, ringid);
                // Success.
                return 0;
            } else {
                ring->mem = NULL;
                ZERO_ELOG(LOG_ERR, "Unable to mmap netmap shared memory");
            }
        } else {
            ZERO_ELOG(LOG_ERR, "Unable to register %s with netmap", ifname);
        }
    } else {
        ZERO_ELOG(LOG_ERR, "Unable to query netmap for '%s' info", ifname);
    }

    close(ring->fd);
    return -1;
}
Exemplo n.º 7
0
/**
 * Inner sendpacket_open() method for using netmap
 */
void *
sendpacket_open_netmap(const char *device, char *errbuf, void *arg) {
    tcpreplay_t *ctx = (tcpreplay_t*)arg;
    sendpacket_t *sp = NULL;
    nmreq_t nmr;
    char ifname_buf[MAX_IFNAMELEN];
    const char *ifname;
    const char *port = NULL;
    size_t namelen;
    u_int32_t nr_ringid = 0;
    u_int32_t nr_flags = NR_REG_DEFAULT;
    int is_default = 0;

    assert(device);
    assert(errbuf);

    dbg(1, "sendpacket_open_netmap: using netmap");

    bzero(&nmr, sizeof(nmr));

    /* prep & return our sp handle */
    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));

    if (strlen(device) > MAX_IFNAMELEN - 8) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto IFACENAME_INVALID;
    }

    /* get the version of the netmap driver. If < 0, driver is not installed */
    sp->netmap_version = get_netmap_version();
    if (sp->netmap_version < 0) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to determine the running netmap version.\n"
                "See INSTALL document for details on installing or upgrading netmap.");
        goto NETMAP_NOT_INSTALLED;
    }

    /*
     * Sort out interface names
     *
     * ifname   (foo, netmap:foo or vale:foo) is the port name
     *      foo         bind to a single NIC hardware queue
     *      netmap:foo  bind to a single NIC hardware queue
     *      vale:foo    bind to the Vale virtual interface
     *
     * for netmap version 10+ a suffix can indicate the following:
     *      netmap:foo!     bind to all NIC hardware queues (may cause TX reordering)
     *      netmap:foo^     bind to the host (sw) ring pair
     *      netmap:foo*     bind to the host (sw) and NIC ring pairs (transparent)
     *      netmap:foo-NN   bind to the individual NIC ring pair (queue) where NN = the ring number
     *      netmap:foo{NN   bind to the master side of pipe NN
     *      netmap:foo}NN   bind to the slave side of pipe NN
     */
    if (strncmp(device, "netmap:", 7) && strncmp(device, "vale", 4)) {
        snprintf(ifname_buf, sizeof(ifname_buf), "netmap:%s", device);
        ifname = ifname_buf;
    } else {
        ifname = device;
    }

    if (!strncmp("vale", device, 4))
        sp->is_vale = 1;

    if (ifname[0] == 'n')
        ifname += 7;

    /* scan for a separator */
    for (port = ifname; *port && !index("!-*^{}", *port); port++)
        ;

    namelen = port - ifname;
    if (namelen > sizeof(nmr.nr_name)) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device);
        goto IFACENAME_INVALID;
    }
    /*
     * Open the netmap device to fetch the number of queues of our
     * interface.
     *
     * The first NIOCREGIF also detaches the card from the
     * protocol stack and may cause a reset of the card,
     * which in turn may take some time for the PHY to
     * reconfigure.
     */
    if ((sp->handle.fd = open("/dev/netmap", O_RDWR)) < 0) {
        dbg(1, "sendpacket_open_netmap: Unable to access netmap");
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to access netmap.\n"
                "See INSTALL to learn which NICs are supported and\n"
                "how to set up netmap-capable network drivers.");
        goto OPEN_FAILED;
    }

    /*
     * The nmreq structure must have the NETMAP_API version for the running machine.
     * However the binary may have been compiled on a different machine than the
     * running machine. Discover the true netmap API version, and be careful to call
     * fuctions that are available on all netmap versions.
     */
    if (sp->netmap_version >= 10) {
        switch (*port) {
        case '-': /* one NIC */
            nr_flags = NR_REG_ONE_NIC;
            nr_ringid = atoi(port + 1);
            break;

        case '*': /* NIC and SW, ignore port */
            nr_flags = NR_REG_NIC_SW;
            if (port[1]) {
                snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid netmap port for nic+sw");
                goto NETMAP_IF_PARSE_FAIL;
            }
            break;

        case '^': /* only sw ring */
            nr_flags = NR_REG_SW;
            if (port[1]) {
                snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid port for sw ring");
                goto NETMAP_IF_PARSE_FAIL;
            }
            break;

        case '{':
            nr_flags = NR_REG_PIPE_MASTER;
            nr_ringid = atoi(port + 1);
            break;

        case '}':
            nr_flags = NR_REG_PIPE_SLAVE;
            nr_ringid = atoi(port + 1);
            break;

        case '!':
            nr_flags = NR_REG_ALL_NIC;
            break;

        default:  /* '\0', no suffix */
            nr_flags = NR_REG_ALL_NIC;
            is_default = 1;
            break;
        }

        if (nr_ringid >= NETMAP_RING_MASK) {
            snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "invalid ringid");
            goto NETMAP_IF_PARSE_FAIL;
        }

        nmr.nr_ringid = nr_ringid;
        nmr.nr_flags = nr_flags;
    }

    nmr.nr_version = sp->netmap_version;
    memcpy(nmr.nr_name, ifname, namelen);
    nmr.nr_name[namelen] = '\0';
    strlcpy(sp->device, nmr.nr_name, sizeof(sp->device));

    /*
     * Register the interface on the netmap device: from now on,
     * we can operate on the network interface without any
     * interference from the legacy network stack.
     *
     * Cards take a long time to reset the PHY.
     */
    fprintf(stderr, "Switching network driver for %s to netmap bypass mode... ",
            sp->device);
    fflush(NULL);
    sleep(1);   /* ensure message prints when user is connected via ssh */

    if (ioctl (sp->handle.fd, NIOCREGIF, &nmr)) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Failure accessing netmap.\n"
                "\tRequest for netmap version %u failed.\n\tCompiled netmap driver is version %u.\n\tError=%s\n",
                sp->netmap_version, NETMAP_API, strerror(errno));
        goto NETMAP_IF_FAILED;
    }

    if (!nmr.nr_memsize) {
        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Netmap interface '%s' not configured.\n",
                device);
        goto NETMAP_IF_FAILED;
    }

    sp->mmap_size = nmr.nr_memsize;
    sp->mmap_addr = (struct netmap_d *)mmap (0, sp->mmap_size,
            PROT_WRITE | PROT_READ, MAP_SHARED, sp->handle.fd, 0);

    if (!sp->mmap_addr || sp->mmap_addr == MAP_FAILED) {
        snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "mmap: %s", strerror (errno));
        goto MMAP_FAILED;
    }

    dbgx(1, "sendpacket_open_netmap: mapping %d Kbytes queues=%d",
            sp->mmap_size >> 10, nmr.nr_tx_rings);

    sp->nm_if = NETMAP_IF(sp->mmap_addr, nmr.nr_offset);
    sp->nmr = nmr;
    sp->handle_type = SP_TYPE_NETMAP;

    /* set up ring IDs */
    sp->cur_tx_ring = 0;
    switch(nr_flags) {
    case NR_REG_DEFAULT:    /* only use one queue to prevent TX reordering */
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
        break;

    case NR_REG_ALL_NIC:
        if (is_default) {
            sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
        } else {
            sp->first_tx_ring = sp->cur_tx_ring = 0;
            sp->last_tx_ring = nmr.nr_tx_rings - 1;
        }
        break;

    case NR_REG_SW:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = nmr.nr_tx_rings;
        break;

    case NR_REG_NIC_SW:
        sp->first_tx_ring = sp->cur_tx_ring = 0;
        sp->last_tx_ring = nmr.nr_tx_rings;
        break;

    case NR_REG_ONE_NIC:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = nr_ringid;
        break;

    default:
        sp->first_tx_ring = sp->last_tx_ring = sp->cur_tx_ring = 0;
    }
    {
        /* debugging code */
        int i;

        dbgx(1, "%s tx first=%d last=%d  num=%d", ifname,
                sp->first_tx_ring, sp->last_tx_ring, sp->nmr.nr_tx_rings);
        for (i = 0; i <= sp->nmr.nr_tx_rings; i++) {
#ifdef HAVE_NETMAP_RING_HEAD_TAIL
            dbgx(1, "TX%d 0x%p head=%d cur=%d tail=%d", i, NETMAP_TXRING(sp->nm_if, i),
                    (NETMAP_TXRING(sp->nm_if, i))->head,
                    (NETMAP_TXRING(sp->nm_if, i))->cur, (NETMAP_TXRING(sp->nm_if, i))->tail);
#else
            dbgx(1, "TX%d 0x%p cur=%d avail=%d", i, NETMAP_TXRING(sp->nm_if, i),
                    (NETMAP_TXRING(sp->nm_if, i))->cur, (NETMAP_TXRING(sp->nm_if, i))->avail);
#endif
        }
    }

    dbgx(2, "Waiting %d seconds for phy reset...", ctx->options->netmap_delay);
    sleep(ctx->options->netmap_delay);
    dbg(2, "Ready!");

    if (!sp->is_vale) {
        if (nm_do_ioctl(sp, SIOCGIFFLAGS, 0) < 0)
            goto NM_DO_IOCTL_FAILED;

        if ((sp->if_flags & IFF_RUNNING) == 0) {
            dbgx(1, "sendpacket_open_netmap: %s is not running", sp->device);
            snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "interface %s is not running - check cables\n", sp->device);
            goto NETMAP_IF_NOT_RUNNING;
        }

        if ((sp->if_flags & IFF_UP) == 0) {
            dbgx(1, "%s is down, bringing up...", sp->device);
            sp->if_flags |= IFF_UP;
        }

        /* set promiscuous mode */
        sp->if_flags |= IFF_PROMISC;
        if (nm_do_ioctl(sp, SIOCSIFFLAGS, 0) < 0)
            goto NM_DO_IOCTL_FAILED;

#ifdef linux
        /* disable:
         * - generic-segmentation-offload
         * - tcp-segmentation-offload
         * - rx-checksumming
         * - tx-checksumming
         */
        if (nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GGSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GTSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GRXCSUM) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_GTXCSUM) < 0)
            goto NM_DO_IOCTL_FAILED;

        sp->data = 0;
        if (nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SGSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STSO) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_SRXCSUM) < 0 ||
                nm_do_ioctl(sp, SIOCETHTOOL, ETHTOOL_STXCSUM))
            goto NM_DO_IOCTL_FAILED;
#endif
    }

    if(sp->abort)
        goto NETMAP_ABORT;

    notice("done!");

    return sp;

NM_DO_IOCTL_FAILED:
    snprintf (errbuf, SENDPACKET_ERRBUF_SIZE, "nm_do_ioctl: %s", strerror (errno));
NETMAP_IF_NOT_RUNNING:
    notice("failed!");
NETMAP_ABORT:
    fprintf(stderr, " Switching network driver for %s to normal mode... ",
            sp->device);
    fflush(NULL);
    munmap(sp->mmap_addr, sp->mmap_size);
MMAP_FAILED:
#if NETMAP_API < 10
    ioctl(sp->handle.fd, NIOCUNREGIF, NULL);
#endif
NETMAP_IF_FAILED:
NETMAP_IF_PARSE_FAIL:
    close (sp->handle.fd);
OPEN_FAILED:
    safe_free(sp);
IFACENAME_INVALID:
NETMAP_NOT_INSTALLED:

    return NULL;
}
Exemplo n.º 8
0
static void
start_threads(struct glob_arg *g)
{
	int i;

	targs = calloc(g->nthreads, sizeof(*targs));
	/*
	 * Now create the desired number of threads, each one
	 * using a single descriptor.
 	 */
	for (i = 0; i < g->nthreads; i++) {
		bzero(&targs[i], sizeof(targs[i]));
		targs[i].fd = -1; /* default, with pcap */
		targs[i].g = g;

	    if (g->dev_type == DEV_NETMAP) {
		struct nmreq tifreq;
		int tfd;

		/* register interface. */
		tfd = open("/dev/netmap", O_RDWR);
		if (tfd == -1) {
			D("Unable to open /dev/netmap: %s", strerror(errno));
			continue;
		}
		targs[i].fd = tfd;

		bzero(&tifreq, sizeof(tifreq));
		strncpy(tifreq.nr_name, g->ifname, sizeof(tifreq.nr_name));
		tifreq.nr_version = NETMAP_API;
		if (g->host_ring) {
			tifreq.nr_ringid = NETMAP_SW_RING;
		} else {
			tifreq.nr_ringid = (g->nthreads > 1) ? (i | NETMAP_HW_RING) : 0;
		}
		parse_nmr_config(g->nmr_config, &tifreq);

		/*
		 * if we are acting as a receiver only, do not touch the transmit ring.
		 * This is not the default because many apps may use the interface
		 * in both directions, but a pure receiver does not.
		 */
		if (g->td_body == receiver_body) {
			tifreq.nr_ringid |= NETMAP_NO_TX_POLL;
		}

		if ((ioctl(tfd, NIOCREGIF, &tifreq)) == -1) {
			D("Unable to register %s: %s", g->ifname, strerror(errno));
			continue;
		}
		D("memsize is %d MB", tifreq.nr_memsize >> 20);
		targs[i].nmr = tifreq;
		targs[i].nifp = NETMAP_IF(g->mmap_addr, tifreq.nr_offset);
		D("nifp flags 0x%x", targs[i].nifp->ni_flags);
		/* start threads. */
		if (g->host_ring) {
			targs[i].qfirst = (g->td_body == receiver_body ? tifreq.nr_rx_rings : tifreq.nr_tx_rings);
			targs[i].qlast = targs[i].qfirst + 1;
		} else {
			targs[i].qfirst = (g->nthreads > 1) ? i : 0;
			targs[i].qlast = (g->nthreads > 1) ? i+1 :
				(g->td_body == receiver_body ? tifreq.nr_rx_rings : tifreq.nr_tx_rings);
		}
	    } else {
		targs[i].fd = g->main_fd;
	    }
		targs[i].used = 1;
		targs[i].me = i;
		if (g->affinity >= 0) {
			if (g->affinity < g->cpus)
				targs[i].affinity = g->affinity;
			else
				targs[i].affinity = i % g->cpus;
		} else
			targs[i].affinity = -1;
		/* default, init packets */
		initialize_packet(&targs[i]);

		if (pthread_create(&targs[i].thread, NULL, g->td_body,
				   &targs[i]) == -1) {
			D("Unable to create thread %d: %s", i, strerror(errno));
			targs[i].used = 0;
		}
	}
Exemplo n.º 9
0
int
netmap_open(struct nm_if *nmif)
{
	char ifbuf[IF_NAMESIZE], *p;
	const char *ifname;
	int len;
	struct nmreq nmreq;

	if (nmif->nm_if_vale) {
		/* Attach hw interface to VALE switch. */
		if (netmap_vale_attach(nmif) != 0) {
			netmap_close(nmif);
			return (-1);
		}
		/* Attach netmap-fwd to VALE switch. */
		p = strchr(nmif->nm_if_name, ':');
		len = 0;
		if (p)
			len = p - nmif->nm_if_name;
		memset(ifbuf, 0, sizeof(ifbuf));
		snprintf(ifbuf, sizeof(ifbuf) - 1, "%.*s:nmfwd0", len, nmif->nm_if_name);
		ifname = ifbuf;
	} else
		ifname = nmif->nm_if_name;

	nmif->nm_if_fd = open("/dev/netmap", O_RDWR);
	if (nmif->nm_if_fd == -1) {
		perror("open");
		return (-1);
	}

	memset(&nmreq, 0, sizeof(nmreq));
	strlcpy(nmreq.nr_name, ifname, sizeof(nmreq.nr_name));
	nmreq.nr_version = NETMAP_API;
	if (nohostring || nmif->nm_if_vale)
		nmreq.nr_flags = NR_REG_ALL_NIC;
	else
		nmreq.nr_flags = NR_REG_NIC_SW;
	if (nmif->nm_if_vale)
		nmreq.nr_tx_rings = nmreq.nr_rx_rings = 4;
	if (ioctl(nmif->nm_if_fd, NIOCREGIF, &nmreq) == -1) {
		perror("ioctl");
		netmap_close(nmif);
		return (-1);
	}
DPRINTF("fd: %d\n", nmif->nm_if_fd);
DPRINTF("name: %s\n", nmreq.nr_name);
DPRINTF("version: %d\n", nmreq.nr_version);
DPRINTF("offset: %d\n", nmreq.nr_offset);
DPRINTF("memsize: %d\n", nmreq.nr_memsize);
DPRINTF("tx_slots: %d\n", nmreq.nr_tx_slots);
DPRINTF("rx_slots: %d\n", nmreq.nr_rx_slots);
DPRINTF("tx_rings: %d\n", nmreq.nr_tx_rings);
DPRINTF("rx_rings: %d\n", nmreq.nr_rx_rings);
DPRINTF("ringid: %#x\n", nmreq.nr_ringid);
DPRINTF("flags: %#x\n", nmreq.nr_flags);
	nmif->nm_if_memsize = nmreq.nr_memsize;
	nmif->nm_if_mem = mmap(NULL, nmif->nm_if_memsize,
	    PROT_READ | PROT_WRITE, MAP_SHARED, nmif->nm_if_fd, 0);
	if (nmif->nm_if_mem == MAP_FAILED) {
		perror("mmap");
		netmap_close(nmif);
		return (-1);
	}
	nmif->nm_if_ifp = NETMAP_IF(nmif->nm_if_mem, nmreq.nr_offset);
	nmif->nm_if_ev_read = event_new(ev_get_base(), nmif->nm_if_fd,
	    EV_READ | EV_PERSIST, netmap_read, nmif);
	event_add(nmif->nm_if_ev_read, NULL);

	return (0);
}