예제 #1
0
static int
thr_teardown(struct thr_ctx *ctx)
{

	if (ctx->pa)
		nm_close(ctx->pa);
	if (ctx->pb)
		nm_close(ctx->pb);

	free(ctx->ifa);
	free(ctx->ifb);

	return (0);
}
예제 #2
0
static void
free_buffers(void)
{
	struct netmap_ring *ring;

	if (pa == NULL)
		return;

	ring = NETMAP_RXRING(pa->nifp, pa->first_rx_ring);

	dedup_get_fifo_buffers(&dedup, ring, &pa->nifp->ni_bufs_head);
	nm_close(pa);
	nm_close(pb);
}
예제 #3
0
파일: lb.c 프로젝트: LTD-Beget/netmap
static void
free_buffers(void)
{
	int i, tot = 0;
	struct port_des *rxport = &ports[glob_arg.output_rings];

	/* build a netmap free list with the buffers in all the overflow queues */
	for (i = 0; i < glob_arg.output_rings + 1; i++) {
		struct port_des *cp = &ports[i];
		struct overflow_queue *q = cp->oq;

		if (!q)
			continue;

		while (q->n) {
			struct netmap_slot s = oq_deq(q);
			uint32_t *b = (uint32_t *)NETMAP_BUF(cp->ring, s.buf_idx);

			*b = rxport->nmd->nifp->ni_bufs_head;
			rxport->nmd->nifp->ni_bufs_head = s.buf_idx;
			tot++;
		}
	}
	D("added %d buffers to netmap free list", tot);

	for (i = 0; i < glob_arg.output_rings + 1; ++i) {
		nm_close(ports[i].nmd);
	}
}
예제 #4
0
/* Close and destroy the Netmap port. The object pointed to by port
   is no longer valid after this operation. */
void
fp_netmap_close(struct fp_device* device)
{
  struct fp_netmap_device* dev = (struct fp_netmap_device*)device;
  nm_close(dev->handle);
  fp_deallocate(dev);
}
예제 #5
0
파일: netmap.c 프로젝트: 8tab/qemu
/* Flush and close. */
static void netmap_cleanup(NetClientState *nc)
{
    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);

    qemu_purge_queued_packets(nc);

    netmap_poll(nc, false);
    nm_close(s->nmd);
    s->nmd = NULL;
}
예제 #6
0
static PyObject *
NetmapDesc_exit(NetmapDesc *self, PyObject *args)
{
    if (self->nmd) {
        nm_close(self->nmd);
        self->nmd = NULL;
    }

    Py_RETURN_NONE;
}
예제 #7
0
/* Destructor method for NetmapDescType. */
static void
NetmapDesc_dealloc(NetmapDesc* self)
{
    NetmapMemory_dealloc(&self->memory);

    if (self->nmd) {
        nm_close(self->nmd);
        self->nmd = NULL;
    }
    self->ob_type->tp_free((PyObject*)self);
}
예제 #8
0
void nm_desc_destructor::operator()(nm_desc *d) const
{
    // We wrap the fd in an asio handle, which takes care of closing it.
    // To prevent nm_close from closing it too, we nullify it here.
    d->fd = -1;
    int status = nm_close(d);
    if (status != 0)
    {
        std::error_code code(status, std::system_category());
        log_warning("Failed to close the netmap fd: %1% (%2%)", code.value(), code.message());
    }
}
예제 #9
0
파일: netmap.c 프로젝트: guanhe0/packages
/**
 * Close netmap descriptors
 *
 * Can be reopened using netmap_start() function.
 *
 * @param pktio_entry    Packet IO entry
 */
static inline void netmap_close_descriptors(pktio_entry_t *pktio_entry)
{
	int i, j;
	pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;

	for (i = 0; i < PKTIO_MAX_QUEUES; i++) {
		for (j = 0; j < NM_MAX_DESC; j++)
			if (pkt_nm->rx_desc_ring[i].s.desc[j] != NULL) {
				nm_close(pkt_nm->rx_desc_ring[i].s.desc[j]);
				pkt_nm->rx_desc_ring[i].s.desc[j] = NULL;
			}

		for (j = 0; j < NM_MAX_DESC; j++)
			if (pkt_nm->tx_desc_ring[i].s.desc[j] != NULL) {
				nm_close(pkt_nm->tx_desc_ring[i].s.desc[j]);
				pkt_nm->tx_desc_ring[i].s.desc[j] = NULL;
			}
	}

	pkt_nm->num_rx_desc_rings = 0;
	pkt_nm->num_tx_desc_rings = 0;
}
예제 #10
0
파일: test_nm.c 프로젝트: deemru/netmap
int
main(int argc, char *argv[])
{
	struct nm_desc *d;
	struct pollfd pfd;
	char buf[2048];
	int count = 0;

	if (argc < 2) {
		usage(argv[0]);
	}

	bzero(&pfd, sizeof(pfd));

	d = nm_open(argv[1], NULL, 0, 0);
	if (d == NULL) {
		fprintf(stderr, "no netmap\n");
		exit(0);
	}
	pfd.fd = d->fd;
	pfd.events = argv[2] && argv[2][0] == 'w' ? POLLOUT : POLLIN;
	fprintf(stderr, "working on %s in %s mode\n", argv[1], pfd.events == POLLIN ? "read" : "write");

	for (;;) {
		if (pfd.events == POLLIN) {
			nm_dispatch(d, -1, my_cb, (void *)&count);
		} else {
			if (nm_inject(d, buf, 60) > 0) {
				count++;
				continue;
			}
			fprintf(stderr, "polling after sending %d\n", count);
			count = 0;
		}
		poll(&pfd, 1, 1000);
	}
	nm_close(d);
	return 0;
}
예제 #11
0
static void
pci_vtnet_netmap_setup(struct pci_vtnet_softc *sc, char *ifname)
{
	sc->pci_vtnet_rx = pci_vtnet_netmap_rx;
	sc->pci_vtnet_tx = pci_vtnet_netmap_tx;

	sc->vsc_nmd = nm_open(ifname, NULL, 0, 0);
	if (sc->vsc_nmd == NULL) {
		WPRINTF(("open of netmap device %s failed\n", ifname));
		return;
	}

	sc->vsc_mevp = mevent_add(sc->vsc_nmd->fd,
				  EVF_READ,
				  pci_vtnet_rx_callback,
				  sc);
	if (sc->vsc_mevp == NULL) {
		WPRINTF(("Could not register event\n"));
		nm_close(sc->vsc_nmd);
		sc->vsc_nmd = NULL;
	}
}
예제 #12
0
static int
thr_ctx_setup(struct thr_ctx *th, char *ifa, char *ifb,
    int zerocopy, int burst, struct thr_ctx *parent, int cpuid)
{
	int nm_flags = 0;
	struct nm_desc *p_pa = NULL;

	bzero(th, sizeof(struct thr_ctx));

	th->ifa = strdup(ifa);
	th->ifb = strdup(ifb);
	th->zerocopy = zerocopy;
	th->burst = burst;
	th->cpuid = cpuid;

	/* Setup netmap rings */
	if (parent) {
		nm_flags |= NM_OPEN_NO_MMAP;
		p_pa = parent->pa;
	}
	th->pa = nm_open(ifa, NULL, nm_flags, p_pa);
	if (th->pa == NULL) {
		D("cannot open %s", ifa);
		exit(1);
	}

	th->pb = nm_open(ifb, NULL, NM_OPEN_NO_MMAP, th->pa);
	if (th->pb == NULL) {
		D("cannot open %s", ifb);
		nm_close(th->pa);
		exit(1);
	}
	th->zerocopy = th->zerocopy && (th->pa->mem == th->pb->mem);

	/* Done */
	return (0);
}
void
pico_netmap_destroy(struct pico_device *dev) {
	struct pico_device_netmap *netmap = (struct pico_device_netmap *) dev;
	nm_close(netmap->conn);
}
예제 #14
0
void
pcap_close(pcap_t *p)
{
	nm_close(p);
	/* restore original flags ? */
}
예제 #15
0
static int
pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
{
	int ret;
	struct pcap_netmap *pn = p->priv;
	struct nm_desc *d = pn->d;
	struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };

	pn->cb = cb;
	pn->cb_arg = user;

	for (;;) {
		if (p->break_loop) {
			p->break_loop = 0;
			return PCAP_ERROR_BREAK;
		}
		/* nm_dispatch won't run forever */

		ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
		if (ret != 0)
			break;
		errno = 0;
		ret = poll(&pfd, 1, p->opt.timeout);
	}
	return ret;
}


/* XXX need to check the NIOCTXSYNC/poll */
static int
pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
{
	struct pcap_netmap *pn = p->priv;
	struct nm_desc *d = pn->d;

	return nm_inject(d, buf, size);
}


static int
pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
{
	struct pcap_netmap *pn = p->priv;
	struct nm_desc *d = pn->d;
	struct ifreq ifr;
	int error, fd = d->fd;

#ifdef linux
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0) {
		fprintf(stderr, "Error: cannot get device control socket.\n");
		return -1;
	}
#endif /* linux */
	bzero(&ifr, sizeof(ifr));
	strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
	switch (what) {
	case SIOCSIFFLAGS:
		/*
		 * The flags we pass in are 32-bit and unsigned.
		 *
		 * On most if not all UN*Xes, ifr_flags is 16-bit and
		 * signed, and the result of assigning a longer
		 * unsigned value to a shorter signed value is
		 * implementation-defined (even if, in practice, it'll
		 * do what's intended on all platforms we support
		 * result of assigning a 32-bit unsigned value).
		 * So we mask out the upper 16 bits.
		 */
		ifr.ifr_flags = *if_flags & 0xffff;
#ifdef __FreeBSD__
		/*
		 * In FreeBSD, we need to set the high-order flags,
		 * as we're using IFF_PPROMISC, which is in those bits.
		 *
		 * XXX - DragonFly BSD?
		 */
		ifr.ifr_flagshigh = *if_flags >> 16;
#endif /* __FreeBSD__ */
		break;
	}
	error = ioctl(fd, what, &ifr);
	if (!error) {
		switch (what) {
		case SIOCGIFFLAGS:
			/*
			 * The flags we return are 32-bit.
			 *
			 * On most if not all UN*Xes, ifr_flags is
			 * 16-bit and signed, and will get sign-
			 * extended, so that the upper 16 bits of
			 * those flags will be forced on.  So we
			 * mask out the upper 16 bits of the
			 * sign-extended value.
			 */
			*if_flags = ifr.ifr_flags & 0xffff;
#ifdef __FreeBSD__
			/*
			 * In FreeBSD, we need to return the
			 * high-order flags, as we're using
			 * IFF_PPROMISC, which is in those bits.
			 *
			 * XXX - DragonFly BSD?
			 */
			*if_flags |= (ifr.ifr_flagshigh << 16);
#endif /* __FreeBSD__ */
		}
	}
#ifdef linux
	close(fd);
#endif /* linux */
	return error ? -1 : 0;
}


static void
pcap_netmap_close(pcap_t *p)
{
	struct pcap_netmap *pn = p->priv;
	struct nm_desc *d = pn->d;
	uint32_t if_flags = 0;

	if (pn->must_clear_promisc) {
		pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
		if (if_flags & IFF_PPROMISC) {
			if_flags &= ~IFF_PPROMISC;
			pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
		}
	}
	nm_close(d);
	pcap_cleanup_live_common(p);
}


static int
pcap_netmap_activate(pcap_t *p)
{
	struct pcap_netmap *pn = p->priv;
	struct nm_desc *d;
	uint32_t if_flags = 0;

	d = nm_open(p->opt.device, NULL, 0, NULL);
	if (d == NULL) {
		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
		    errno, "netmap open: cannot access %s",
		    p->opt.device);
		pcap_cleanup_live_common(p);
		return (PCAP_ERROR);
	}
	if (0)
	    fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
		__FUNCTION__, p->opt.device, d, d->fd,
		d->first_rx_ring, d->last_rx_ring);
	pn->d = d;
	p->fd = d->fd;

	/*
	 * Turn a negative snapshot value (invalid), a snapshot value of
	 * 0 (unspecified), or a value bigger than the normal maximum
	 * value, into the maximum allowed value.
	 *
	 * If some application really *needs* a bigger snapshot
	 * length, we should just increase MAXIMUM_SNAPLEN.
	 */
	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
		p->snapshot = MAXIMUM_SNAPLEN;

	if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
		pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
		if (!(if_flags & IFF_PPROMISC)) {
			pn->must_clear_promisc = 1;
			if_flags |= IFF_PPROMISC;
			pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
		}
	}
	p->linktype = DLT_EN10MB;
	p->selectable_fd = p->fd;
	p->read_op = pcap_netmap_dispatch;
	p->inject_op = pcap_netmap_inject,
	p->setfilter_op = install_bpf_program;
	p->setdirection_op = NULL;
	p->set_datalink_op = NULL;
	p->getnonblock_op = pcap_getnonblock_fd;
	p->setnonblock_op = pcap_setnonblock_fd;
	p->stats_op = pcap_netmap_stats;
	p->cleanup_op = pcap_netmap_close;

	return (0);
}


pcap_t *
pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
{
	pcap_t *p;

	*is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
	if (! *is_ours)
		return NULL;
	p = pcap_create_common(ebuf, sizeof (struct pcap_netmap));
	if (p == NULL)
		return (NULL);
	p->activate_op = pcap_netmap_activate;
	return (p);
}
예제 #16
0
int main(int argc, char **argv)
{
    int index = 0;
    int channel_nums = 4;
    int member = 2;
    const char *ifname = NULL;

    struct thread_args_t targs[MAX_RINGS]; 
    memset(targs, 0x0, sizeof(targs));

    if (argc < 2 || argc > 3) {
        printf("Usage:%s [interface] <channel nums>\n", argv[1]);
        return 1;
    }

    ifname = argv[1];
    if (argc == 3)
    {
        channel_nums = atoi(argv[2]);
    }

    if (channel_nums < 1 || channel_nums > MAX_RINGS 
            || (MAX_RINGS % channel_nums) != 0 )
    {
        printf("channel nums error.\n");
        return 1;
    }

    member = MAX_RINGS / channel_nums;
    for (index = 0; index < channel_nums; index++)
    {   
        char buff[64];
        memset(buff,0x0, 64);

        struct thread_args_t *thread_arg = &targs[index];

        unsigned short start = index * member;
        unsigned short end   = start + member - 1;
        snprintf(buff, 63, "netmap:%s+%d.%d", ifname, start, end);
        
        thread_arg->desc = nm_open(buff, NULL, NETMAP_NO_TX_POLL | NETMAP_DO_RX_POLL, NULL);
        if ( thread_arg->desc == NULL) {
            D("cannot open eth0");
            return 1;
        }
        
        printf("%d first_rx_ring:%d last_rx_rings:%d ", index,
                            thread_arg->desc->first_rx_ring,
                            thread_arg->desc->last_rx_ring);
        printf(" first_tx_ring:%d last_tx_rings:%d\n", 
                            thread_arg->desc->first_tx_ring,
                            thread_arg->desc->last_tx_ring);

        thread_arg->affinity = index;
        pthread_create(&(thread_arg->thread), NULL, run, (void*)thread_arg);
        pthread_detach(thread_arg->thread);
    }

    main_loop_statistics(targs, channel_nums);

    for (index = 0; index < channel_nums; index ++)
    {
        nm_close(targs[index].desc); 
    }

    D("exiting");
    return (0);
}
예제 #17
0
파일: netmap.c 프로젝트: guanhe0/packages
static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
		       const char *netdev, odp_pool_t pool)
{
	int i;
	int err;
	int sockfd;
	int mtu;
	uint32_t buf_size;
	pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
	struct nm_desc *desc;
	struct netmap_ring *ring;
	odp_pktin_hash_proto_t hash_proto;
	odp_pktio_stats_t   cur_stats;

	if (getenv("ODP_PKTIO_DISABLE_NETMAP"))
		return -1;

	if (pool == ODP_POOL_INVALID)
		return -1;

	/* Init pktio entry */
	memset(pkt_nm, 0, sizeof(*pkt_nm));
	pkt_nm->sockfd = -1;
	pkt_nm->pool = pool;

	/* max frame len taking into account the l2-offset */
	pkt_nm->max_frame_len = ODP_CONFIG_PACKET_BUF_LEN_MAX -
				odp_buffer_pool_headroom(pool) -
				odp_buffer_pool_tailroom(pool);

	snprintf(pktio_entry->s.name, sizeof(pktio_entry->s.name), "%s",
		 netdev);
	snprintf(pkt_nm->nm_name, sizeof(pkt_nm->nm_name), "netmap:%s",
		 netdev);

	/* Dummy open here to check if netmap module is available and to read
	 * capability info. */
	desc = nm_open(pkt_nm->nm_name, NULL, 0, NULL);
	if (desc == NULL) {
		ODP_ERR("nm_open(%s) failed\n", pkt_nm->nm_name);
		goto error;
	}

	if (desc->nifp->ni_rx_rings > NM_MAX_DESC) {
		ODP_ERR("Unable to store all rx rings\n");
		nm_close(desc);
		goto error;
	}

	pkt_nm->num_rx_rings = desc->nifp->ni_rx_rings;
	pkt_nm->capa.max_input_queues = PKTIO_MAX_QUEUES;
	if (desc->nifp->ni_rx_rings < PKTIO_MAX_QUEUES)
		pkt_nm->capa.max_input_queues = desc->nifp->ni_rx_rings;

	if (desc->nifp->ni_tx_rings > NM_MAX_DESC) {
		ODP_ERR("Unable to store all tx rings\n");
		nm_close(desc);
		goto error;
	}

	pkt_nm->num_tx_rings = desc->nifp->ni_tx_rings;
	pkt_nm->capa.max_output_queues = PKTIO_MAX_QUEUES;
	if (desc->nifp->ni_tx_rings < PKTIO_MAX_QUEUES)
		pkt_nm->capa.max_output_queues = desc->nifp->ni_tx_rings;

	ring = NETMAP_RXRING(desc->nifp, desc->cur_rx_ring);
	buf_size = ring->nr_buf_size;
	nm_close(desc);

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd == -1) {
		ODP_ERR("Cannot get device control socket\n");
		goto error;
	}

	pkt_nm->sockfd = sockfd;

	/* Use either interface MTU (+ ethernet header length) or netmap buffer
	 * size as MTU, whichever is smaller. */
	mtu = mtu_get_fd(pktio_entry->s.pkt_nm.sockfd, pktio_entry->s.name) +
	      ODPH_ETHHDR_LEN;
	if (mtu < 0) {
		ODP_ERR("Unable to read interface MTU\n");
		goto error;
	}

	pkt_nm->mtu = ((uint32_t)mtu < buf_size) ? (uint32_t)mtu : buf_size;

	/* Check if RSS is supported. If not, set 'max_input_queues' to 1. */
	if (rss_conf_get_supported_fd(sockfd, netdev, &hash_proto) == 0) {
		ODP_DBG("RSS not supported\n");
		pkt_nm->capa.max_input_queues = 1;
	}

	err = netmap_do_ioctl(pktio_entry, SIOCGIFFLAGS, 0);
	if (err)
		goto error;

	if ((pkt_nm->if_flags & IFF_UP) == 0)
		ODP_DBG("%s is down\n", pktio_entry->s.name);

	err = mac_addr_get_fd(sockfd, netdev, pkt_nm->if_mac);
	if (err)
		goto error;

	for (i = 0; i < PKTIO_MAX_QUEUES; i++) {
		odp_ticketlock_init(&pkt_nm->rx_desc_ring[i].s.lock);
		odp_ticketlock_init(&pkt_nm->tx_desc_ring[i].s.lock);
	}

	/* netmap uses only ethtool to get statistics counters */
	err = ethtool_stats_get_fd(pktio_entry->s.pkt_nm.sockfd,
				   pktio_entry->s.name,
				   &cur_stats);
	if (err) {
		ODP_ERR(
			"netmap pktio %s does not support statistics counters\n",
			pktio_entry->s.name);
		pktio_entry->s.stats_type = STATS_UNSUPPORTED;
	} else {
		pktio_entry->s.stats_type = STATS_ETHTOOL;
	}

	(void)netmap_stats_reset(pktio_entry);

	return 0;

error:
	netmap_close(pktio_entry);
	return -1;
}
예제 #18
0
int
main(int argc, char **argv)
{
	struct pollfd pollfd[2];
	int ch;
	char *ifa = NULL, *ifb = NULL;
	int wait_link = 2;
	int win_size_usec = 50;
	unsigned int fifo_size = 10;
	int n;
	int hold = 0;
	struct nmreq base_req;
	uint32_t buf_head = 0;
#ifdef DEDUP_HASH_STAT
	time_t last_hash_output = 0;
#endif

	fprintf(stderr, "%s built %s %s\n\n", argv[0], __DATE__, __TIME__);

	while ((ch = getopt(argc, argv, "hci:vw:W:F:H")) != -1) {
		switch (ch) {
		default:
			D("bad option %c %s", ch, optarg);
			/* fallthrough */
		case 'h':
			usage();
			break;
		case 'i':	/* interface */
			if (ifa == NULL)
				ifa = optarg;
			else if (ifb == NULL)
				ifb = optarg;
			else
				D("%s ignored, already have 2 interfaces",
					optarg);
			break;
		case 'c':
			zerocopy = 0; /* do not zerocopy */
			break;
		case 'v':
			verbose++;
			break;
		case 'w':
			wait_link = atoi(optarg);
			break;
		case 'W':
			win_size_usec = atoi(optarg);
			break;
		case 'F':
			fifo_size = atoi(optarg);
			break;
		case 'H':
			hold = 1;
			break;
		}

	}

	if (!ifa || !ifb) {
		D("missing interface");
		usage();
	}
	memset(&base_req, 0, sizeof(base_req));
	if (!hold) {
		base_req.nr_arg3 = fifo_size;
	}
	pa = nm_open(ifa, &base_req, 0, NULL);
	if (pa == NULL) {
		D("cannot open %s", ifa);
		return (1);
	}
	if (!hold) {
	        if (base_req.nr_arg3 != fifo_size) {
			D("failed to allocate %u extra buffers", fifo_size);
			return (1); // XXX failover to copy?
		} else {
			buf_head = pa->nifp->ni_bufs_head;
		}
	}
	if (pa->first_rx_ring != pa->last_rx_ring) {
		D("%s: too many RX rings (%d)", pa->req.nr_name,
				pa->last_rx_ring - pa->first_rx_ring + 1);
		return (1);
	}
	/* try to reuse the mmap() of the first interface, if possible */
	pb = nm_open(ifb, NULL, NM_OPEN_NO_MMAP, pa);
	if (pb == NULL) {
		D("cannot open %s", ifb);
		nm_close(pa);
		return (1);
	}
	if (pb->first_tx_ring != pb->last_tx_ring) {
		D("%s: too many TX rings (%d)", pb->req.nr_name,
				pb->last_rx_ring - pb->first_rx_ring + 1);
		nm_close(pa);
		return (1);
	}

	memset(&dedup, 0, sizeof(dedup));
	dedup.out_slot = dedup.out_ring->slot;
	if (dedup_init(&dedup, fifo_size, 
			NETMAP_RXRING(pa->nifp, pa->first_rx_ring),
			NETMAP_TXRING(pb->nifp, pb->first_tx_ring)) < 0) {
		D("failed to initialize dedup with fifo_size %u", fifo_size);
		return (1);
	}
	if (fifo_size >= dedup.out_ring->num_slots - 1) {
		D("fifo_size %u too large (max %u)", fifo_size, dedup.out_ring->num_slots - 1);
		return (1);
	}
	if (dedup_set_fifo_buffers(&dedup, NULL, buf_head) != 0) {
		D("failed to set 'hold packets' option");
		return (1);
	}
	pa->nifp->ni_bufs_head = 0;
	atexit(free_buffers);

	/* enable/disable zerocopy */
	dedup.in_memid = pa->req.nr_arg2;
	dedup.out_memid = (zerocopy ? pb->req.nr_arg2 : -1 );
	dedup.fifo_memid = hold ? dedup.out_memid : dedup.in_memid;
	D("memids: in %d out %d fifo %d", dedup.in_memid, dedup.out_memid,
			dedup.fifo_memid);
	dedup.win_size.tv_sec = win_size_usec / 1000000;
	dedup.win_size.tv_usec = win_size_usec % 1000000;
	D("win_size %lld+%lld", (long long) dedup.win_size.tv_sec,
			(long long) dedup.win_size.tv_usec);

	/* setup poll(2) array */
	memset(pollfd, 0, sizeof(pollfd));
	pollfd[0].fd = pa->fd;
	pollfd[1].fd = pb->fd;

	D("Wait %d secs for link to come up...", wait_link);
	sleep(wait_link);
	D("Ready to go, %s -> %s", pa->req.nr_name, pb->req.nr_name);

	/* main loop */
	signal(SIGINT, sigint_h);
	n = 0;
	while (!do_abort) {
		int ret;
		struct timeval now;

		pollfd[0].events = pollfd[1].events = 0;
		pollfd[0].revents = pollfd[1].revents = 0;
		if (!n)
			pollfd[0].events = POLLIN;
		else
			pollfd[1].events = POLLOUT;
		/* poll() also cause kernel to txsync/rxsync the NICs */
		ret = poll(pollfd, 2, 1000);
		gettimeofday(&now, NULL);
		if (ret <= 0 || verbose)
		    D("poll %s [0] ev %x %x"
			     " [1] ev %x %x",
				ret <= 0 ? "timeout" : "ok",
				pollfd[0].events,
				pollfd[0].revents,
				pollfd[1].events,
				pollfd[1].revents
			);
		n = dedup_push_in(&dedup, &now);
#ifdef DEDUP_HASH_STAT
		if (now.tv_sec != last_hash_output) {
			unsigned int i;

			last_hash_output = now.tv_sec;
			printf("buckets: ");
			for (i = 0; i <= dedup.hashmap_mask; i++) {
				if  (dedup.hashmap[i].bucket_size)
					printf("%u: %u, ", i, dedup.hashmap[i].bucket_size);
			}
			printf("\n");
		}
#endif
	}

	return (0);
}
예제 #19
0
파일: bridge.c 프로젝트: 2asoft/freebsd
/*
 * bridge [-v] if1 [if2]
 *
 * If only one name, or the two interfaces are the same,
 * bridges userland and the adapter. Otherwise bridge
 * two intefaces.
 */
int
main(int argc, char **argv)
{
	struct pollfd pollfd[2];
	int ch;
	u_int burst = 1024, wait_link = 4;
	struct nm_desc *pa = NULL, *pb = NULL;
	char *ifa = NULL, *ifb = NULL;
	char ifabuf[64] = { 0 };

	fprintf(stderr, "%s built %s %s\n",
		argv[0], __DATE__, __TIME__);

	while ( (ch = getopt(argc, argv, "b:ci:vw:")) != -1) {
		switch (ch) {
		default:
			D("bad option %c %s", ch, optarg);
			usage();
			break;
		case 'b':	/* burst */
			burst = atoi(optarg);
			break;
		case 'i':	/* interface */
			if (ifa == NULL)
				ifa = optarg;
			else if (ifb == NULL)
				ifb = optarg;
			else
				D("%s ignored, already have 2 interfaces",
					optarg);
			break;
		case 'c':
			zerocopy = 0; /* do not zerocopy */
			break;
		case 'v':
			verbose++;
			break;
		case 'w':
			wait_link = atoi(optarg);
			break;
		}

	}

	argc -= optind;
	argv += optind;

	if (argc > 1)
		ifa = argv[1];
	if (argc > 2)
		ifb = argv[2];
	if (argc > 3)
		burst = atoi(argv[3]);
	if (!ifb)
		ifb = ifa;
	if (!ifa) {
		D("missing interface");
		usage();
	}
	if (burst < 1 || burst > 8192) {
		D("invalid burst %d, set to 1024", burst);
		burst = 1024;
	}
	if (wait_link > 100) {
		D("invalid wait_link %d, set to 4", wait_link);
		wait_link = 4;
	}
	if (!strcmp(ifa, ifb)) {
		D("same interface, endpoint 0 goes to host");
		snprintf(ifabuf, sizeof(ifabuf) - 1, "%s^", ifa);
		ifa = ifabuf;
	} else {
		/* two different interfaces. Take all rings on if1 */
	}
	pa = nm_open(ifa, NULL, 0, NULL);
	if (pa == NULL) {
		D("cannot open %s", ifa);
		return (1);
	}
	// XXX use a single mmap ?
	pb = nm_open(ifb, NULL, NM_OPEN_NO_MMAP, pa);
	if (pb == NULL) {
		D("cannot open %s", ifb);
		nm_close(pa);
		return (1);
	}
	zerocopy = zerocopy && (pa->mem == pb->mem);
	D("------- zerocopy %ssupported", zerocopy ? "" : "NOT ");

	/* setup poll(2) variables. */
	memset(pollfd, 0, sizeof(pollfd));
	pollfd[0].fd = pa->fd;
	pollfd[1].fd = pb->fd;

	D("Wait %d secs for link to come up...", wait_link);
	sleep(wait_link);
	D("Ready to go, %s 0x%x/%d <-> %s 0x%x/%d.",
		pa->req.nr_name, pa->first_rx_ring, pa->req.nr_rx_rings,
		pb->req.nr_name, pb->first_rx_ring, pb->req.nr_rx_rings);

	/* main loop */
	signal(SIGINT, sigint_h);
	while (!do_abort) {
		int n0, n1, ret;
		pollfd[0].events = pollfd[1].events = 0;
		pollfd[0].revents = pollfd[1].revents = 0;
		n0 = pkt_queued(pa, 0);
		n1 = pkt_queued(pb, 0);
		if (n0)
			pollfd[1].events |= POLLOUT;
		else
			pollfd[0].events |= POLLIN;
		if (n1)
			pollfd[0].events |= POLLOUT;
		else
			pollfd[1].events |= POLLIN;
		ret = poll(pollfd, 2, 2500);
		if (ret <= 0 || verbose)
		    D("poll %s [0] ev %x %x rx %d@%d tx %d,"
			     " [1] ev %x %x rx %d@%d tx %d",
				ret <= 0 ? "timeout" : "ok",
				pollfd[0].events,
				pollfd[0].revents,
				pkt_queued(pa, 0),
				NETMAP_RXRING(pa->nifp, pa->cur_rx_ring)->cur,
				pkt_queued(pa, 1),
				pollfd[1].events,
				pollfd[1].revents,
				pkt_queued(pb, 0),
				NETMAP_RXRING(pb->nifp, pb->cur_rx_ring)->cur,
				pkt_queued(pb, 1)
			);
		if (ret < 0)
			continue;
		if (pollfd[0].revents & POLLERR) {
			struct netmap_ring *rx = NETMAP_RXRING(pa->nifp, pa->cur_rx_ring);
			D("error on fd0, rx [%d,%d,%d)",
				rx->head, rx->cur, rx->tail);
		}
		if (pollfd[1].revents & POLLERR) {
			struct netmap_ring *rx = NETMAP_RXRING(pb->nifp, pb->cur_rx_ring);
			D("error on fd1, rx [%d,%d,%d)",
				rx->head, rx->cur, rx->tail);
		}
		if (pollfd[0].revents & POLLOUT) {
			move(pb, pa, burst);
			// XXX we don't need the ioctl */
			// ioctl(me[0].fd, NIOCTXSYNC, NULL);
		}
		if (pollfd[1].revents & POLLOUT) {
			move(pa, pb, burst);
			// XXX we don't need the ioctl */
			// ioctl(me[1].fd, NIOCTXSYNC, NULL);
		}
	}
	D("exiting");
	nm_close(pb);
	nm_close(pa);

	return (0);
}
예제 #20
0
파일: bridge.c 프로젝트: cbsd/cbsd
/*
 * bridge [-v] if1 [if2]
 *
 * If only one name, or the two interfaces are the same,
 * bridges userland and the adapter. Otherwise bridge
 * two intefaces.
 */
int
main(int argc, char **argv)
{
	struct pollfd pollfd[2];
	int ch;
	u_int burst = 1024, wait_link = 4;
	struct nm_desc *pa = NULL, *pb = NULL;
	char *ifa = NULL, *ifb = NULL;
	char ifabuf[64] = { 0 };
	int loopback = 0;

	fprintf(stderr, "%s built %s %s\n\n", argv[0], __DATE__, __TIME__);

	while ((ch = getopt(argc, argv, "hb:ci:vw:L")) != -1) {
		switch (ch) {
		default:
			D("bad option %c %s", ch, optarg);
			/* fallthrough */
		case 'h':
			usage();
			break;
		case 'b':	/* burst */
			burst = atoi(optarg);
			break;
		case 'i':	/* interface */
			if (ifa == NULL)
				ifa = optarg;
			else if (ifb == NULL)
				ifb = optarg;
			else
				D("%s ignored, already have 2 interfaces",
					optarg);
			break;
		case 'c':
			zerocopy = 0; /* do not zerocopy */
			break;
		case 'v':
			verbose++;
			break;
		case 'w':
			wait_link = atoi(optarg);
			break;
		case 'L':
			loopback = 1;
			break;
		}

	}

	argc -= optind;
	argv += optind;

	if (argc > 0)
		ifa = argv[0];
	if (argc > 1)
		ifb = argv[1];
	if (argc > 2)
		burst = atoi(argv[2]);
	if (!ifb)
		ifb = ifa;
	if (!ifa) {
		D("missing interface");
		usage();
	}
	if (burst < 1 || burst > 8192) {
		D("invalid burst %d, set to 1024", burst);
		burst = 1024;
	}
	if (wait_link > 100) {
		D("invalid wait_link %d, set to 4", wait_link);
		wait_link = 4;
	}
	if (!strcmp(ifa, ifb)) {
		if (!loopback) {
			D("same interface, endpoint 0 goes to host");
			snprintf(ifabuf, sizeof(ifabuf) - 1, "%s^", ifa);
			ifa = ifabuf;
		} else {
			D("same interface, loopbacking traffic");
		}
	} else {
		/* two different interfaces. Take all rings on if1 */
	}
	pa = nm_open(ifa, NULL, 0, NULL);
	if (pa == NULL) {
		D("cannot open %s", ifa);
		return (1);
	}
	/* try to reuse the mmap() of the first interface, if possible */
	pb = nm_open(ifb, NULL, NM_OPEN_NO_MMAP, pa);
	if (pb == NULL) {
		D("cannot open %s", ifb);
		nm_close(pa);
		return (1);
	}
	zerocopy = zerocopy && (pa->mem == pb->mem);
	D("------- zerocopy %ssupported", zerocopy ? "" : "NOT ");

	/* setup poll(2) array */
	memset(pollfd, 0, sizeof(pollfd));
	pollfd[0].fd = pa->fd;
	pollfd[1].fd = pb->fd;

	D("Wait %d secs for link to come up...", wait_link);
	sleep(wait_link);
	D("Ready to go, %s 0x%x/%d <-> %s 0x%x/%d.",
		pa->req.nr_name, pa->first_rx_ring, pa->req.nr_rx_rings,
		pb->req.nr_name, pb->first_rx_ring, pb->req.nr_rx_rings);

	/* main loop */
	signal(SIGINT, sigint_h);
	while (!do_abort) {
		int n0, n1, ret;
		pollfd[0].events = pollfd[1].events = 0;
		pollfd[0].revents = pollfd[1].revents = 0;
		n0 = pkt_queued(pa, 0);
		n1 = pkt_queued(pb, 0);
#if defined(_WIN32) || defined(BUSYWAIT)
		if (n0) {
			ioctl(pollfd[1].fd, NIOCTXSYNC, NULL);
			pollfd[1].revents = POLLOUT;
		} else {
			ioctl(pollfd[0].fd, NIOCRXSYNC, NULL);
		}
		if (n1) {
			ioctl(pollfd[0].fd, NIOCTXSYNC, NULL);
			pollfd[0].revents = POLLOUT;
		} else {
			ioctl(pollfd[1].fd, NIOCRXSYNC, NULL);
		}
		ret = 1;
#else
		if (n0)
			pollfd[1].events |= POLLOUT;
		else
			pollfd[0].events |= POLLIN;
		if (n1)
			pollfd[0].events |= POLLOUT;
		else
			pollfd[1].events |= POLLIN;

		/* poll() also cause kernel to txsync/rxsync the NICs */
		ret = poll(pollfd, 2, 2500);
#endif /* defined(_WIN32) || defined(BUSYWAIT) */
		if (ret <= 0 || verbose)
		    D("poll %s [0] ev %x %x rx %d@%d tx %d,"
			     " [1] ev %x %x rx %d@%d tx %d",
				ret <= 0 ? "timeout" : "ok",
				pollfd[0].events,
				pollfd[0].revents,
				pkt_queued(pa, 0),
				NETMAP_RXRING(pa->nifp, pa->cur_rx_ring)->cur,
				pkt_queued(pa, 1),
				pollfd[1].events,
				pollfd[1].revents,
				pkt_queued(pb, 0),
				NETMAP_RXRING(pb->nifp, pb->cur_rx_ring)->cur,
				pkt_queued(pb, 1)
			);
		if (ret < 0)
			continue;
		if (pollfd[0].revents & POLLERR) {
			struct netmap_ring *rx = NETMAP_RXRING(pa->nifp, pa->cur_rx_ring);
			D("error on fd0, rx [%d,%d,%d)",
				rx->head, rx->cur, rx->tail);
		}
		if (pollfd[1].revents & POLLERR) {
			struct netmap_ring *rx = NETMAP_RXRING(pb->nifp, pb->cur_rx_ring);
			D("error on fd1, rx [%d,%d,%d)",
				rx->head, rx->cur, rx->tail);
		}
		if (pollfd[0].revents & POLLOUT)
			move(pb, pa, burst);

		if (pollfd[1].revents & POLLOUT)
			move(pa, pb, burst);

		/* We don't need ioctl(NIOCTXSYNC) on the two file descriptors here,
		 * kernel will txsync on next poll(). */
	}
	nm_close(pb);
	nm_close(pa);

	return (0);
}
예제 #21
0
static int
pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
{
	int ret;
	struct pcap_netmap *pn = NM_PRIV(p);
	struct nm_desc *d = pn->d;
	struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };

	pn->cb = cb;
	pn->cb_arg = user;

	for (;;) {
		if (p->break_loop) {
			p->break_loop = 0;
			return PCAP_ERROR_BREAK;
		}
		/* nm_dispatch won't run forever */

		ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
		if (ret != 0)
			break;
		errno = 0;
		ret = poll(&pfd, 1, p->the_timeout);
	}
	return ret;
}


/* XXX need to check the NIOCTXSYNC/poll */
static int
pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
{
	struct nm_desc *d = NM_PRIV(p)->d;

	return nm_inject(d, buf, size);
}


static int
pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
{
	struct pcap_netmap *pn = NM_PRIV(p);
	struct nm_desc *d = pn->d;
	struct ifreq ifr;
	int error, fd = d->fd;

#ifdef linux
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0) {
		fprintf(stderr, "Error: cannot get device control socket.\n");
		return -1;
	}
#endif /* linux */
	bzero(&ifr, sizeof(ifr));
	strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
	switch (what) {
	case SIOCSIFFLAGS:
		ifr.ifr_flags = *if_flags;
#ifdef __FreeBSD__
		ifr.ifr_flagshigh = *if_flags >> 16;
#endif /* __FreeBSD__ */
		break;
	}
	error = ioctl(fd, what, &ifr);
	if (!error) {
		switch (what) {
		case SIOCGIFFLAGS:
			*if_flags = ifr.ifr_flags;
#ifdef __FreeBSD__
			*if_flags |= (ifr.ifr_flagshigh << 16);
#endif /* __FreeBSD__ */
		}
	}
#ifdef linux
	close(fd);
#endif /* linux */
	return error ? -1 : 0;
}


static void
pcap_netmap_close(pcap_t *p)
{
	struct pcap_netmap *pn = NM_PRIV(p);
	struct nm_desc *d = pn->d;
	uint32_t if_flags = 0;

	if (pn->must_clear_promisc) {
		pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
		if (if_flags & IFF_PPROMISC) {
			if_flags &= ~IFF_PPROMISC;
			pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
		}
	}
	nm_close(d);
#ifdef HAVE_NO_PRIV
	free(pn);
	SET_PRIV(p, NULL); // unnecessary
#endif
	pcap_cleanup_live_common(p);
}


static int
pcap_netmap_activate(pcap_t *p)
{
	struct pcap_netmap *pn = NM_PRIV(p);
	struct nm_desc *d = nm_open(p->opt.source, NULL, 0, NULL);
	uint32_t if_flags = 0;

	if (d == NULL) {
		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
			"netmap open: cannot access %s: %s\n",
			p->opt.source, pcap_strerror(errno));
#ifdef HAVE_NO_PRIV
		free(pn);
		SET_PRIV(p, NULL); // unnecessary
#endif
		pcap_cleanup_live_common(p);
		return (PCAP_ERROR);
	}
	if (0)
	    fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
		__FUNCTION__, p->opt.source, d, d->fd,
		d->first_rx_ring, d->last_rx_ring);
	pn->d = d;
	p->fd = d->fd;
	if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
		pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
		if (!(if_flags & IFF_PPROMISC)) {
			pn->must_clear_promisc = 1;
			if_flags |= IFF_PPROMISC;
			pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
		}
	}
	p->linktype = DLT_EN10MB;
	p->selectable_fd = p->fd;
	p->read_op = pcap_netmap_dispatch;
	p->inject_op = pcap_netmap_inject,
	p->setfilter_op = install_bpf_program;
	p->setdirection_op = NULL;
	p->set_datalink_op = NULL;
	p->getnonblock_op = pcap_getnonblock_fd;
	p->setnonblock_op = pcap_setnonblock_fd;
	p->stats_op = pcap_netmap_stats;
	p->cleanup_op = pcap_netmap_close;

	return (0);
}


pcap_t *
pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
{
	pcap_t *p;

	*is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
	if (! *is_ours)
		return NULL;
#ifdef HAVE_NO_PRIV
	{
		void *pn = calloc(1, sizeof(struct pcap_netmap));
		if (pn == NULL)
			return NULL;
		p = pcap_create_common(device, ebuf);
		if (p == NULL) {
			free(pn);
			return NULL;
		}
		SET_PRIV(p, pn);
	}
#else
	p = pcap_create_common(device, ebuf, sizeof (struct pcap_netmap));
	if (p == NULL)
		return (NULL);
#endif
	p->activate_op = pcap_netmap_activate;
	return (p);
}
예제 #22
0
void
usnet_dispatch()
{
   struct netmap_if   *nifp;
   struct pollfd       fds;
   struct netmap_ring *rxring;
   int                 ret;

   nifp = g_nmd->nifp;
   fds.fd = g_nmd->fd;

   while(!do_abort) {
       //fds.events = POLLIN | POLLOUT;
       fds.events = POLLIN;
       fds.revents = 0;
       ret = poll(&fds, 1, 3000);
       if (ret <= 0 ) {
          DEBUG("poll %s ev %x %x rx @%d:%d:%d ", 
            ret <= 0 ? "timeout" : "ok",
            fds.events,
            fds.revents,
            NETMAP_RXRING(g_nmd->nifp, g_nmd->cur_rx_ring)->head,
            NETMAP_RXRING(g_nmd->nifp, g_nmd->cur_rx_ring)->cur,
            NETMAP_RXRING(g_nmd->nifp, g_nmd->cur_rx_ring)->tail);
          DEBUG("poll %s ev %x %x tx @%d:%d:%d ", 
            ret <= 0 ? "timeout" : "ok",
            fds.events,
            fds.revents,
            NETMAP_RXRING(g_nmd->nifp, g_nmd->cur_tx_ring)->head,
            NETMAP_RXRING(g_nmd->nifp, g_nmd->cur_tx_ring)->cur,
            NETMAP_RXRING(g_nmd->nifp, g_nmd->cur_tx_ring)->tail);
          continue;
       }
       if (fds.revents & POLLERR) {
          struct netmap_ring *rx = NETMAP_RXRING(nifp, g_nmd->cur_rx_ring);
          (void)rx;
			 DEBUG("error on em1, rx [%d,%d,%d]",
					 rx->head, rx->cur, rx->tail);
       }
/*       
       if (fds.revents & POLLOUT) {
          for (int j = g_nmd->first_tx_ring; 
                   j <= g_nmd->last_tx_ring; j++) {
             txring = NETMAP_RXRING(nifp, j);

				 DEBUG("Ring info tx(%d), head=%d, cur=%d, tail=%d", 
                   j, txring->head, txring->cur, txring->tail); 

             if (nm_ring_empty(txring)) {
                continue;
             }

             //send_packets(rxring, 512, 1);
          }
       }
*/
       if (fds.revents & POLLIN) {
          int j;
          for (j = g_nmd->first_rx_ring; 
                   j <= g_nmd->last_rx_ring; j++) {
             rxring = NETMAP_RXRING(nifp, j);

				 DEBUG("Ring info rx(%d), head=%d, cur=%d, tail=%d", 
                   j, rxring->head, rxring->cur, rxring->tail); 

             if (nm_ring_empty(rxring)) {
                continue;
             }

             receive_packets(rxring, 512, 1);
          }
       }
   }
   nm_close(g_nmd);
   return;
}