コード例 #1
0
/* Mimics netmap's nm_nextpkt function.  This version does not
 * release buffer in order to avoid extra copies.  This has the
 * disadvantage of potentially holding up the ring if service times
 * are not equal.
 *
 * TODO: explore swapping buffers with a tx and rx ring with a 3rd buffer.
 *       This may prevent packets with exceptionally long service time from
 *       holding up the entire ring...
 */
static u_char*
fp_netmap_nextpkt(struct nm_desc* d, struct nm_pkthdr* hdr) {
  int ring_i = d->cur_rx_ring;

  do {
    /* compute current ring to use */
    struct netmap_ring* ring = NETMAP_RXRING(d->nifp, ring_i);
    if (!nm_ring_empty(ring)) {
      u_int buf_i = ring->cur;
      u_int buf_idx = ring->slot[buf_i].buf_idx;
      u_char* buf_ptr = (u_char*)NETMAP_BUF(ring, buf_idx);

      // __builtin_prefetch(buf);
      hdr->ts = ring->ts;
      hdr->len = hdr->caplen = ring->slot[buf_i].len;
      ring->cur = nm_ring_next(ring, buf_i);
      /* we could postpone advancing head if we want
       * to hold the buffer. This can be supported in
       * the future.
       */
//      ring->head = ring->cur;
      d->cur_rx_ring = ring_i;
      return buf_ptr;
    }
    ring_i++;
    if (ring_i > d->last_rx_ring)
      ring_i = d->first_rx_ring;
  } while (ring_i != d->cur_rx_ring);

  return NULL; /* nothing found */
}
コード例 #2
0
/* move packts from src to destination */
static int
move(struct my_ring *src, struct my_ring *dst, u_int limit)
{
	struct netmap_ring *txring, *rxring;
	u_int m = 0, si = src->begin, di = dst->begin;
	const char *msg = (src->queueid & NETMAP_SW_RING) ?
		"host->net" : "net->host";

	while (si < src->end && di < dst->end) {
		rxring = NETMAP_RXRING(src->nifp, si);
		txring = NETMAP_TXRING(dst->nifp, di);
		ND("txring %p rxring %p", txring, rxring);
		if (rxring->avail == 0) {
			si++;
			continue;
		}
		if (txring->avail == 0) {
			di++;
			continue;
		}
		m += process_rings(rxring, txring, limit, msg);
	}

	return (m);
}
コード例 #3
0
ファイル: netmap.c プロジェクト: 8tab/qemu
/* The exported init function
 *
 * ... -net netmap,ifname="..."
 */
int net_init_netmap(const Netdev *netdev,
                    const char *name, NetClientState *peer, Error **errp)
{
    const NetdevNetmapOptions *netmap_opts = &netdev->u.netmap;
    struct nm_desc *nmd;
    NetClientState *nc;
    Error *err = NULL;
    NetmapState *s;

    nmd = netmap_open(netmap_opts, &err);
    if (err) {
        error_propagate(errp, err);
        return -1;
    }
    /* Create the object. */
    nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name);
    s = DO_UPCAST(NetmapState, nc, nc);
    s->nmd = nmd;
    s->tx = NETMAP_TXRING(nmd->nifp, 0);
    s->rx = NETMAP_RXRING(nmd->nifp, 0);
    s->vnet_hdr_len = 0;
    pstrcpy(s->ifname, sizeof(s->ifname), netmap_opts->ifname);
    netmap_read_poll(s, true); /* Initially only poll for reads. */

    return 0;
}
コード例 #4
0
ファイル: bridge.c プロジェクト: victordetoni/netmap-tools
/* move packts from src to destination */
static int
move(struct thr_ctx *th, struct nm_desc *src, struct nm_desc *dst, u_int limit)
{
	struct netmap_ring *txring, *rxring;
	u_int m = 0, si = src->first_rx_ring, di = dst->first_tx_ring;
	const char *msg = (src->req.nr_ringid & NETMAP_SW_RING) ?
		"host->net" : "net->host";

	while (si <= src->last_rx_ring && di <= dst->last_tx_ring) {
		rxring = NETMAP_RXRING(src->nifp, si);
		txring = NETMAP_TXRING(dst->nifp, di);
		ND("txring %p rxring %p", txring, rxring);
		if (nm_ring_empty(rxring)) {
			si++;
			continue;
		}
		if (nm_ring_empty(txring)) {
			di++;
			continue;
		}
		m += process_rings(th, rxring, txring, limit, msg);
	}

	return (m);
}
コード例 #5
0
ファイル: netmap.c プロジェクト: Netgate/netmap-fwd
static void
netmap_read(evutil_socket_t fd, short event, void *data)
{
	char *buf;
	int err, i, pkts, rx_rings;
	struct netmap_if *ifp;
	struct netmap_ring *nring;
	struct nm_if *nmif;

	nmif = (struct nm_if *)data;
	ifp = nmif->nm_if_ifp;
	rx_rings = ifp->ni_rx_rings;
	if (!nohostring && !nmif->nm_if_vale)
		rx_rings++;
	pkts = 0;
	for (i = 0; i < rx_rings; i++) {
		nring = NETMAP_RXRING(ifp, i);
		while (!nm_ring_empty(nring)) {
			buf = NETMAP_GET_BUF(nring);
			err = ether_input(nmif, i, buf, NETMAP_SLOT_LEN(nring));
			/* Send the packet to hw <-> host bridge. */
			if (!nohostring && err == 1)
				err = ether_bridge(nmif, i, buf,
				    NETMAP_SLOT_LEN(nring));
			NETMAP_RING_NEXT(nring);
			if (err < 0 || ++pkts == burst)
				goto done;
		}
	}
done:
	if_netmap_txsync();
}
コード例 #6
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);
}
コード例 #7
0
ファイル: peak_netmap.c プロジェクト: javarange/libpeak
static struct peak_netmap *
_peak_netmap_claim(void)
{
	struct _peak_netmap *packet;
	struct netmap_ring *ring;
	struct my_ring *me;
	unsigned int j, si;

	for (j = 0; j < NETMAP_COUNT(); ++j) {
		me = self->me[j];

		for (si = me->begin; si < me->end; ++si) {
			unsigned int i, idx;

			ring = NETMAP_RXRING(me->nifp, si);
			if (!ring->avail) {
				continue;
			}

			packet = NETPKT_GET();
			if (!packet) {
				alert("netmap packet pool empty\n");
				return (NULL);
			}

			bzero(packet, sizeof(*packet));

			i = ring->cur;
			idx = ring->slot[i].buf_idx;
			if (idx < 2) {
				panic("%s bugus RX index %d at offset %d\n",
				    me->nifp->ni_name, idx, i);
			}

			/* volatile internals */
			packet->ring = ring;
			packet->i = i;

			/* external stuff */
			packet->data.buf = NETMAP_BUF(ring, idx);
			packet->data.len = ring->slot[i].len;
			packet->data.ll = LINKTYPE_ETHERNET;
			packet->data.ts_ms = (int64_t)ring->ts.tv_sec *
			    1000 + (int64_t)ring->ts.tv_usec / 1000;
			packet->data.ts_unix = ring->ts.tv_sec;
			packet->data.ifname = me->ifname;

			return (NETPKT_TO_USER(packet));
		}
	}

	return (NULL);
}
コード例 #8
0
ファイル: usnet_core.c プロジェクト: carriercomm/libusnet
struct nm_desc*
usnet_init( struct nm_desc *gg_nmd, const char *dev_name, u_int flags)
{
   struct nmreq        nmr;
   struct nm_desc     *nmd = NULL;
   struct netmap_if   *nifp = NULL;
   struct netmap_ring *txr, *rxr;

   signal(SIGINT, sigint_h);

   bzero(&nmr, sizeof(nmr));
   strcpy(nmr.nr_name, dev_name);

   // XXX: which netmap flags?
   //nmr.nr_flags = NR_REG_ALL_NIC; //| flags;

   printf("nm_open: %s\n", nmr.nr_name);
   nmd = nm_open(nmr.nr_name, &nmr, 0, NULL);
   if ( nmd == NULL ) {
      DEBUG("Cannot open interface %s", nmr.nr_name);
      exit(1);
   }
   nifp = nmd->nifp;
   txr = NETMAP_TXRING(nifp, 0);
   rxr = NETMAP_RXRING(nifp, 0);

   printf("nmreq info, name=%s, version=%d,"
     " flags=%d, memsize=%d,"
     " ni_tx_rings=%d, ni_rx_rings=%d, num_tx_slots=%d, num_rx_slot=%d \n",
      nifp->ni_name,
      nifp->ni_version,
      nifp->ni_flags,
      nmd->memsize,
      nifp->ni_tx_rings,
      nifp->ni_rx_rings,
      txr->num_slots,
      rxr->num_slots);

   memset(&g_config, 0, sizeof(g_config));
   g_config.burst = 1000;
   g_config.tx_rate = 0;

   memset(&g_ipq, 0, sizeof(g_ipq));

   usnet_init_internal();
   usnet_route_init();
   usnet_network_init();
   usnet_udp_init();
   usnet_ipv4_init();
   usnet_socket_init();

   return nmd;
}
コード例 #9
0
ファイル: vnfacl.c プロジェクト: carriercomm/vnfapp
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;
}
コード例 #10
0
ファイル: main.c プロジェクト: binBASH/cloudflare-blog
static void receiver(lua_State *L, int cb_ref, struct nm_desc *d, unsigned int ring_id) {
    struct pollfd fds;
    struct netmap_ring *ring;
    unsigned int i, len;
    char *buf;
    time_t now;
    int pps;

    now = time(NULL);
    pps = 0;

    while (1) {
        fds.fd     = d->fd;
        fds.events = POLLIN;

        int r = poll(&fds, 1, 1000);
        if (r < 0) {
            if (errno != EINTR) {
                perror("poll()");
                exit(3);
            }
        }

        if (time(NULL) > now) {
            printf("[+] receiving %d pps\n", pps);
            pps = 0;
            now = time(NULL);
        }

        ring = NETMAP_RXRING(d->nifp, ring_id);

        while (!nm_ring_empty(ring)) {
            i   = ring->cur;
            buf = NETMAP_BUF(ring, ring->slot[i].buf_idx);
            len = ring->slot[i].len;

            pps++;

            if (filter_packet(L, cb_ref, buf, len)) {
                // forward packet to kernel
                ring->flags         |= NR_FORWARD;
                ring->slot[i].flags |= NS_FORWARD;
                printf("+++ PASS\n");
            } else {
                // drop packet
                printf("--- DROP\n");
            }

            ring->head = ring->cur = nm_ring_next(ring, i);
        }
    }
}
コード例 #11
0
/*
 * Note: this thread is the only one pulling packets off of any
 * given netmap instance
 */
static void *
receiver(void *arg)
{
	struct virtif_user *viu = arg;
	struct iovec iov;
	struct netmap_if *nifp = viu->nm_nifp;
	struct netmap_ring *ring = NETMAP_RXRING(nifp, 0);
	struct netmap_slot *slot;
	struct pollfd pfd;
	int prv;

	rumpuser_component_kthread();

	for (;;) {
		pfd.fd = viu->viu_fd;
		pfd.events = POLLIN;

		if (viu->viu_dying) {
			break;
		}

		prv = 0;
		while (nm_ring_empty(ring) && prv == 0) {
			DPRINTF(("receive pkt via netmap\n"));
			prv = poll(&pfd, 1, 1000);
			if (prv > 0 || (prv < 0 && errno != EAGAIN))
				break;
		}
#if 0
		/* XXX: report non-transient errors */
		if (ring->avail == 0) {
			rv = errno;
			break;
		}
#endif
		slot = &ring->slot[ring->cur];
		DPRINTF(("got pkt of size %d\n", slot->len));
		iov.iov_base = NETMAP_BUF(ring, slot->buf_idx);
		iov.iov_len = slot->len;

		/* XXX: allow batch processing */
		rumpuser_component_schedule(NULL);
		VIF_DELIVERPKT(viu->viu_virtifsc, &iov, 1);
		rumpuser_component_unschedule();

		ring->head = ring->cur = nm_ring_next(ring, ring->cur);
	}

	rumpuser_component_kthread_release();
	return NULL;
}
コード例 #12
0
ファイル: dedup-main.c プロジェクト: lsalamon/netmap
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);
}
コード例 #13
0
ファイル: bridge.c プロジェクト: Leon555/dpdk
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;
}
コード例 #14
0
ファイル: bridge.c プロジェクト: victordetoni/netmap-tools
/*
 * how many packets on this set of queues ?
 *
 * Receive: how many frames in the receive path.
 * Transmit: how many slots are available to transmit.
 */
int
pkt_queued(struct nm_desc *d, int tx)
{
	u_int i, tot = 0;

	if (tx) {
		for (i = d->first_tx_ring; i <= d->last_tx_ring; i++) {
			tot += nm_ring_space(NETMAP_TXRING(d->nifp, i));
		}
	} else {
		for (i = d->first_rx_ring; i <= d->last_rx_ring; i++) {
			tot += nm_ring_space(NETMAP_RXRING(d->nifp, i));
		}
	}
	return tot;
}
コード例 #15
0
ファイル: netmap.c プロジェクト: carriercomm/zerod
/**
 * 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;
}
コード例 #16
0
ファイル: testrangenic.c プロジェクト: juneman/netmap
static int rx(struct thread_args_t *arg, struct nm_desc *src, u_int limit)
{
    struct netmap_ring *rxring;
    u_int si = src->first_rx_ring;
    while (si <= src->last_rx_ring) {
        rxring = NETMAP_RXRING(src->nifp, si);
        if (nm_ring_empty(rxring)) {
            si++;
            continue;
        }
        g_rings_counts[si] ++;

        u_int m = process_rings(rxring, limit);
        arg->count += m;
    }

    return (1);
}
コード例 #17
0
ファイル: usnet_core.c プロジェクト: carriercomm/libusnet
int
usnet_setup(int argc, char *argv[])
{
   //struct nm_desc     *nmd;
   char               *p;
   int                 ret;

   (void)argc;
   (void)argv;
   (void)p;
   //(void)nmd;

   setaffinity(0);

   ret = usnet_get_options(argc, argv);
   if ( ret < 0 ) {
      show_help();
      exit(0);
   }

   g_nmd = usnet_init(g_nmd, (char*)g_interface, 0);

  if (1) {
      struct netmap_if *nifp = g_nmd->nifp;
      struct nmreq *req = &g_nmd->req;
      int i;
      D("fisrt_tx_ring=%d, last_tx_ring=%d", g_nmd->first_tx_ring, g_nmd->last_tx_ring);
      D("nifp at offset %d, %d tx %d rx region %d",
          req->nr_offset, req->nr_tx_rings, req->nr_rx_rings,
          req->nr_arg2);
      for (i = 0; i <= req->nr_tx_rings; i++) {
         struct netmap_ring *ring = NETMAP_TXRING(nifp, i);
         D("   TX%d at 0x%p slots %d", i,
             (void *)((char *)ring - (char *)nifp), ring->num_slots);
      }    
      for (i = 0; i <= req->nr_rx_rings; i++) {
         struct netmap_ring *ring = NETMAP_RXRING(nifp, i);
         D("   RX%d at 0x%p slots %d", i,
             (void *)((char *)ring - (char *)nifp), ring->num_slots);
      }    
   }
   return 0;
}
コード例 #18
0
ファイル: pcap.c プロジェクト: ChaosJohn/freebsd
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	struct pcap_ring *pme = p;
	struct my_ring *me = &pme->me;
	int got = 0;
	u_int si;

	ND("cnt %d", cnt);
	if (cnt == 0)
		cnt = -1;
	/* scan all rings */
	for (si = me->begin; si < me->end; si++) {
		struct netmap_ring *ring = NETMAP_RXRING(me->nifp, si);
		ND("ring has %d pkts", ring->avail);
		if (ring->avail == 0)
			continue;
		pme->hdr.ts = ring->ts;
		/*
		 * XXX a proper prefetch should be done as
		 *	prefetch(i); callback(i-1); ...
		 */
		while ((cnt == -1 || cnt != got) && ring->avail > 0) {
			u_int i = ring->cur;
			u_int idx = ring->slot[i].buf_idx;
			if (idx < 2) {
				D("%s bogus RX index %d at offset %d",
					me->nifp->ni_name, idx, i);
				sleep(2);
			}
			u_char *buf = (u_char *)NETMAP_BUF(ring, idx);
			prefetch(buf);
			pme->hdr.len = pme->hdr.caplen = ring->slot[i].len;
			// D("call %p len %d", p, me->hdr.len);
			callback(user, &pme->hdr, buf);
			ring->cur = NETMAP_RING_NEXT(ring, i);
			ring->avail--;
			got++;
		}
	}
	pme->st.ps_recv += got;
	return got;
}
コード例 #19
0
static __inline int
pci_vtnet_netmap_readv(struct nm_desc *nmd, struct iovec *iov, int iovcnt)
{
	int len = 0;
	int i = 0;
	int r;

	for (r = nmd->cur_rx_ring; ; ) {
		struct netmap_ring *ring = NETMAP_RXRING(nmd->nifp, r);
		uint32_t cur, idx;
		char *buf;
		size_t left;

		if (nm_ring_empty(ring)) {
			r++;
			if (r > nmd->last_rx_ring)
				r = nmd->first_rx_ring;
			if (r == nmd->cur_rx_ring)
				break;
			continue;
		}
		cur = ring->cur;
		idx = ring->slot[cur].buf_idx;
		buf = NETMAP_BUF(ring, idx);
		left = ring->slot[cur].len;

		for (i = 0; i < iovcnt && left > 0; i++) {
			if (iov[i].iov_len > left)
				iov[i].iov_len = left;
			memcpy(iov[i].iov_base, &buf[len], iov[i].iov_len);
			len += iov[i].iov_len;
			left -= iov[i].iov_len;
		}
		ring->head = ring->cur = nm_ring_next(ring, cur);
		nmd->cur_rx_ring = r;
		ioctl(nmd->fd, NIOCRXSYNC, NULL);
		break;
	}
	for (; i < iovcnt; i++)
		iov[i].iov_len = 0;

	return (len);
}
コード例 #20
0
/*
 * how many packets on this set of queues ?
 */
static int
pkt_queued(struct my_ring *me, int tx)
{
	u_int i, tot = 0;

	ND("me %p begin %d end %d", me, me->begin, me->end);
	for (i = me->begin; i < me->end; i++) {
		struct netmap_ring *ring = tx ?
			NETMAP_TXRING(me->nifp, i) : NETMAP_RXRING(me->nifp, i);
		tot += ring->avail;
	}
	if (0 && verbose && tot && !tx)
		D("ring %s %s %s has %d avail at %d",
			me->ifname, tx ? "tx": "rx",
			me->end >= me->nifp->ni_tx_rings ? // XXX who comes first ?
				"host":"net",
			tot, NETMAP_TXRING(me->nifp, me->begin)->cur);
	return tot;
}
コード例 #21
0
ファイル: netmap.cpp プロジェクト: GHubgenius/fastnetmon
void netmap_thread(struct nm_desc* netmap_descriptor, int thread_number) {
    struct  nm_pkthdr h;
    u_char* buf;
    struct  pollfd fds;
    fds.fd     = netmap_descriptor->fd;//NETMAP_FD(netmap_descriptor);
    fds.events = POLLIN;

    struct netmap_ring *rxring = NULL;
    struct netmap_if *nifp = netmap_descriptor->nifp;

    printf("Reading from fd %d thread id: %d\n", netmap_descriptor->fd, thread_number);

    for (;;) {
        // We will wait 1000 microseconds for retry, for infinite timeout please use -1
        int poll_result = poll(&fds, 1, 1000);
       
        if (poll_result == 0) {
            // printf("poll return 0 return code\n");
            continue;
        }

        if (poll_result == -1) {
            printf("poll failed with return code -1\n");
        }
 
        for (int i = netmap_descriptor->first_rx_ring; i <= netmap_descriptor->last_rx_ring; i++) {
            //printf("Check ring %d from thread %d\n", i, thread_number);
            rxring = NETMAP_RXRING(nifp, i); 

            if (nm_ring_empty(rxring)) {
                continue;
            }

            int m = receive_packets(rxring);
        }

        //while ( (buf = nm_nextpkt(netmap_descriptor, &h)) ) {
        //    consume_pkt(buf, h.len);
        //}
    }

     //nm_close(netmap_descriptor);
}
コード例 #22
0
ファイル: compat_netmap.c プロジェクト: AMildner/MoonGen
static inline int
rx_sync_if(uint32_t port)
{
	uint16_t burst;
	uint32_t i, rc;
	struct netmap_if *nifp;
	struct netmap_ring *r;

	nifp = ports[port].nmif;
	burst = ports[port].rx_burst;
	rc = 0;

	for (i = 0; i < nifp->ni_rx_rings + 1; i++) {
		r = NETMAP_RXRING(nifp, i);
		rx_sync_ring(r, (uint8_t)port, (uint16_t)i, burst);
		rc += r->avail;
	}

	return (rc);
}
コード例 #23
0
ファイル: netmap_module.c プロジェクト: anhk/mtcp
/*----------------------------------------------------------------------------*/
int32_t
netmap_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
{
    struct netmap_private_context *npc;
    struct nm_desc *d;
    npc = (struct netmap_private_context *)ctxt->io_private_context;
    d = npc->local_nmd[ifidx];

    int p = 0;
    int c, got = 0, ri = d->cur_rx_ring;
    int n = d->last_rx_ring - d->first_rx_ring + 1;
    int cnt = MAX_PKT_BURST;



    for (c = 0; c < n && cnt != got && npc->dev_poll_flag[ifidx]; c++) {
        /* compute current ring to use */
        struct netmap_ring *ring;

        ri = d->cur_rx_ring + c;
        if (ri > d->last_rx_ring)
            ri = d->first_rx_ring;
        ring = NETMAP_RXRING(d->nifp, ri);
        for ( ; !nm_ring_empty(ring) && cnt != got; got++) {
            u_int i = ring->cur;
            u_int idx = ring->slot[i].buf_idx;
            npc->rcv_pktbuf[p] = (u_char *)NETMAP_BUF(ring, idx);
            npc->rcv_pkt_len[p] = ring->slot[i].len;
            p++;
            ring->head = ring->cur = nm_ring_next(ring, i);
        }
    }
    d->cur_rx_ring = ri;

    npc->dev_poll_flag[ifidx] = 0;

    return p;
}
コード例 #24
0
ファイル: pkt-gen.c プロジェクト: 2asoft/freebsd
static void *
pinger_body(void *data)
{
	struct targ *targ = (struct targ *) data;
	struct pollfd pfd = { .fd = targ->fd, .events = POLLIN };
	struct netmap_if *nifp = targ->nmd->nifp;
	int i, rx = 0, n = targ->g->npackets;
	void *frame;
	int size;
	uint32_t sent = 0;
	struct timespec ts, now, last_print;
	uint32_t count = 0, min = 1000000000, av = 0;

	frame = &targ->pkt;
	frame += sizeof(targ->pkt.vh) - targ->g->virt_header;
	size = targ->g->pkt_size + targ->g->virt_header;

	if (targ->g->nthreads > 1) {
		D("can only ping with 1 thread");
		return NULL;
	}

	clock_gettime(CLOCK_REALTIME_PRECISE, &last_print);
	now = last_print;
	while (n == 0 || (int)sent < n) {
		struct netmap_ring *ring = NETMAP_TXRING(nifp, 0);
		struct netmap_slot *slot;
		char *p;
	    for (i = 0; i < 1; i++) { /* XXX why the loop for 1 pkt ? */
		slot = &ring->slot[ring->cur];
		slot->len = size;
		p = NETMAP_BUF(ring, slot->buf_idx);

		if (nm_ring_empty(ring)) {
			D("-- ouch, cannot send");
		} else {
			struct tstamp *tp;
			nm_pkt_copy(frame, p, size);
			clock_gettime(CLOCK_REALTIME_PRECISE, &ts);
			bcopy(&sent, p+42, sizeof(sent));
			tp = (struct tstamp *)(p+46);
			tp->sec = (uint32_t)ts.tv_sec;
			tp->nsec = (uint32_t)ts.tv_nsec;
			sent++;
			ring->head = ring->cur = nm_ring_next(ring, ring->cur);
		}
	    }
		/* should use a parameter to decide how often to send */
		if (poll(&pfd, 1, 3000) <= 0) {
			D("poll error/timeout on queue %d: %s", targ->me,
				strerror(errno));
			continue;
		}
		/* see what we got back */
		for (i = targ->nmd->first_tx_ring;
			i <= targ->nmd->last_tx_ring; i++) {
			ring = NETMAP_RXRING(nifp, i);
			while (!nm_ring_empty(ring)) {
				uint32_t seq;
				struct tstamp *tp;
				slot = &ring->slot[ring->cur];
				p = NETMAP_BUF(ring, slot->buf_idx);

				clock_gettime(CLOCK_REALTIME_PRECISE, &now);
				bcopy(p+42, &seq, sizeof(seq));
				tp = (struct tstamp *)(p+46);
				ts.tv_sec = (time_t)tp->sec;
				ts.tv_nsec = (long)tp->nsec;
				ts.tv_sec = now.tv_sec - ts.tv_sec;
				ts.tv_nsec = now.tv_nsec - ts.tv_nsec;
				if (ts.tv_nsec < 0) {
					ts.tv_nsec += 1000000000;
					ts.tv_sec--;
				}
				if (1) D("seq %d/%d delta %d.%09d", seq, sent,
					(int)ts.tv_sec, (int)ts.tv_nsec);
				if (ts.tv_nsec < (int)min)
					min = ts.tv_nsec;
				count ++;
				av += ts.tv_nsec;
				ring->head = ring->cur = nm_ring_next(ring, ring->cur);
				rx++;
			}
		}
		//D("tx %d rx %d", sent, rx);
		//usleep(100000);
		ts.tv_sec = now.tv_sec - last_print.tv_sec;
		ts.tv_nsec = now.tv_nsec - last_print.tv_nsec;
		if (ts.tv_nsec < 0) {
			ts.tv_nsec += 1000000000;
			ts.tv_sec--;
		}
		if (ts.tv_sec >= 1) {
			D("count %d min %d av %d",
				count, min, av/count);
			count = 0;
			av = 0;
			min = 100000000;
			last_print = now;
		}
	}
	return NULL;
}


/*
 * reply to ping requests
 */
static void *
ponger_body(void *data)
{
	struct targ *targ = (struct targ *) data;
	struct pollfd pfd = { .fd = targ->fd, .events = POLLIN };
	struct netmap_if *nifp = targ->nmd->nifp;
	struct netmap_ring *txring, *rxring;
	int i, rx = 0, sent = 0, n = targ->g->npackets;

	if (targ->g->nthreads > 1) {
		D("can only reply ping with 1 thread");
		return NULL;
	}
	D("understood ponger %d but don't know how to do it", n);
	while (n == 0 || sent < n) {
		uint32_t txcur, txavail;
//#define BUSYWAIT
#ifdef BUSYWAIT
		ioctl(pfd.fd, NIOCRXSYNC, NULL);
#else
		if (poll(&pfd, 1, 1000) <= 0) {
			D("poll error/timeout on queue %d: %s", targ->me,
				strerror(errno));
			continue;
		}
#endif
		txring = NETMAP_TXRING(nifp, 0);
		txcur = txring->cur;
		txavail = nm_ring_space(txring);
		/* see what we got back */
		for (i = targ->nmd->first_rx_ring; i <= targ->nmd->last_rx_ring; i++) {
			rxring = NETMAP_RXRING(nifp, i);
			while (!nm_ring_empty(rxring)) {
				uint16_t *spkt, *dpkt;
				uint32_t cur = rxring->cur;
				struct netmap_slot *slot = &rxring->slot[cur];
				char *src, *dst;
				src = NETMAP_BUF(rxring, slot->buf_idx);
				//D("got pkt %p of size %d", src, slot->len);
				rxring->head = rxring->cur = nm_ring_next(rxring, cur);
				rx++;
				if (txavail == 0)
					continue;
				dst = NETMAP_BUF(txring,
				    txring->slot[txcur].buf_idx);
				/* copy... */
				dpkt = (uint16_t *)dst;
				spkt = (uint16_t *)src;
				nm_pkt_copy(src, dst, slot->len);
				dpkt[0] = spkt[3];
				dpkt[1] = spkt[4];
				dpkt[2] = spkt[5];
				dpkt[3] = spkt[0];
				dpkt[4] = spkt[1];
				dpkt[5] = spkt[2];
				txring->slot[txcur].len = slot->len;
				/* XXX swap src dst mac */
				txcur = nm_ring_next(txring, txcur);
				txavail--;
				sent++;
			}
		}
		txring->head = txring->cur = txcur;
		targ->count = sent;
#ifdef BUSYWAIT
		ioctl(pfd.fd, NIOCTXSYNC, NULL);
#endif
		//D("tx %d rx %d", sent, rx);
	}
	return NULL;
}

static __inline int
timespec_ge(const struct timespec *a, const struct timespec *b)
{

	if (a->tv_sec > b->tv_sec)
		return (1);
	if (a->tv_sec < b->tv_sec)
		return (0);
	if (a->tv_nsec >= b->tv_nsec)
		return (1);
	return (0);
}

static __inline struct timespec
timeval2spec(const struct timeval *a)
{
	struct timespec ts = {
		.tv_sec = a->tv_sec,
		.tv_nsec = a->tv_usec * 1000
	};
	return ts;
}

static __inline struct timeval
timespec2val(const struct timespec *a)
{
	struct timeval tv = {
		.tv_sec = a->tv_sec,
		.tv_usec = a->tv_nsec / 1000
	};
	return tv;
}


static __inline struct timespec
timespec_add(struct timespec a, struct timespec b)
{
	struct timespec ret = { a.tv_sec + b.tv_sec, a.tv_nsec + b.tv_nsec };
	if (ret.tv_nsec >= 1000000000) {
		ret.tv_sec++;
		ret.tv_nsec -= 1000000000;
	}
	return ret;
}

static __inline struct timespec
timespec_sub(struct timespec a, struct timespec b)
{
	struct timespec ret = { a.tv_sec - b.tv_sec, a.tv_nsec - b.tv_nsec };
	if (ret.tv_nsec < 0) {
		ret.tv_sec--;
		ret.tv_nsec += 1000000000;
	}
	return ret;
}


/*
 * wait until ts, either busy or sleeping if more than 1ms.
 * Return wakeup time.
 */
static struct timespec
wait_time(struct timespec ts)
{
	for (;;) {
		struct timespec w, cur;
		clock_gettime(CLOCK_REALTIME_PRECISE, &cur);
		w = timespec_sub(ts, cur);
		if (w.tv_sec < 0)
			return cur;
		else if (w.tv_sec > 0 || w.tv_nsec > 1000000)
			poll(NULL, 0, 1);
	}
}

static void *
sender_body(void *data)
{
	struct targ *targ = (struct targ *) data;
	struct pollfd pfd = { .fd = targ->fd, .events = POLLOUT };
	struct netmap_if *nifp;
	struct netmap_ring *txring;
	int i, n = targ->g->npackets / targ->g->nthreads;
	int64_t sent = 0;
	int options = targ->g->options | OPT_COPY;
	struct timespec nexttime = { 0, 0}; // XXX silence compiler
	int rate_limit = targ->g->tx_rate;
	struct pkt *pkt = &targ->pkt;
	void *frame;
	int size;

	if (targ->frame == NULL) {
		frame = pkt;
		frame += sizeof(pkt->vh) - targ->g->virt_header;
		size = targ->g->pkt_size + targ->g->virt_header;
	} else {
		frame = targ->frame;
		size = targ->g->pkt_size;
	}
	
	D("start, fd %d main_fd %d", targ->fd, targ->g->main_fd);
	if (setaffinity(targ->thread, targ->affinity))
		goto quit;

	/* main loop.*/
	clock_gettime(CLOCK_REALTIME_PRECISE, &targ->tic);
	if (rate_limit) {
		targ->tic = timespec_add(targ->tic, (struct timespec){2,0});
		targ->tic.tv_nsec = 0;
		wait_time(targ->tic);
		nexttime = targ->tic;
	}
        if (targ->g->dev_type == DEV_TAP) {
	    D("writing to file desc %d", targ->g->main_fd);

	    for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) {
		if (write(targ->g->main_fd, frame, size) != -1)
			sent++;
		update_addresses(pkt, targ->g);
		if (i > 10000) {
			targ->count = sent;
			i = 0;
		}
	    }
#ifndef NO_PCAP
    } else if (targ->g->dev_type == DEV_PCAP) {
	    pcap_t *p = targ->g->p;

	    for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) {
		if (pcap_inject(p, frame, size) != -1)
			sent++;
		update_addresses(pkt, targ->g);
		if (i > 10000) {
			targ->count = sent;
			i = 0;
		}
	    }
#endif /* NO_PCAP */
    } else {
	int tosend = 0;
	int frags = targ->g->frags;

        nifp = targ->nmd->nifp;
	while (!targ->cancel && (n == 0 || sent < n)) {

		if (rate_limit && tosend <= 0) {
			tosend = targ->g->burst;
			nexttime = timespec_add(nexttime, targ->g->tx_period);
			wait_time(nexttime);
		}

		/*
		 * wait for available room in the send queue(s)
		 */
		if (poll(&pfd, 1, 2000) <= 0) {
			if (targ->cancel)
				break;
			D("poll error/timeout on queue %d: %s", targ->me,
				strerror(errno));
			// goto quit;
		}
		if (pfd.revents & POLLERR) {
			D("poll error");
			goto quit;
		}
		/*
		 * scan our queues and send on those with room
		 */
		if (options & OPT_COPY && sent > 100000 && !(targ->g->options & OPT_COPY) ) {
			D("drop copy");
			options &= ~OPT_COPY;
		}
		for (i = targ->nmd->first_tx_ring; i <= targ->nmd->last_tx_ring; i++) {
			int m, limit = rate_limit ?  tosend : targ->g->burst;
			if (n > 0 && n - sent < limit)
				limit = n - sent;
			txring = NETMAP_TXRING(nifp, i);
			if (nm_ring_empty(txring))
				continue;
			if (frags > 1)
				limit = ((limit + frags - 1) / frags) * frags;

			m = send_packets(txring, pkt, frame, size, targ->g,
					 limit, options, frags);
			ND("limit %d tail %d frags %d m %d",
				limit, txring->tail, frags, m);
			sent += m;
			targ->count = sent;
			if (rate_limit) {
				tosend -= m;
				if (tosend <= 0)
					break;
			}
		}
	}
	/* flush any remaining packets */
	D("flush tail %d head %d on thread %p",
		txring->tail, txring->head,
		pthread_self());
	ioctl(pfd.fd, NIOCTXSYNC, NULL);

	/* final part: wait all the TX queues to be empty. */
	for (i = targ->nmd->first_tx_ring; i <= targ->nmd->last_tx_ring; i++) {
		txring = NETMAP_TXRING(nifp, i);
		while (nm_tx_pending(txring)) {
			RD(5, "pending tx tail %d head %d on ring %d",
				txring->tail, txring->head, i);
			ioctl(pfd.fd, NIOCTXSYNC, NULL);
			usleep(1); /* wait 1 tick */
		}
	}
    } /* end DEV_NETMAP */

	clock_gettime(CLOCK_REALTIME_PRECISE, &targ->toc);
	targ->completed = 1;
	targ->count = sent;

quit:
	/* reset the ``used`` flag. */
	targ->used = 0;

	return (NULL);
}


#ifndef NO_PCAP
static void
receive_pcap(u_char *user, const struct pcap_pkthdr * h,
	const u_char * bytes)
{
	int *count = (int *)user;
	(void)h;	/* UNUSED */
	(void)bytes;	/* UNUSED */
	(*count)++;
}
#endif /* !NO_PCAP */

static int
receive_packets(struct netmap_ring *ring, u_int limit, int dump)
{
	u_int cur, rx, n;

	cur = ring->cur;
	n = nm_ring_space(ring);
	if (n < limit)
		limit = n;
	for (rx = 0; rx < limit; rx++) {
		struct netmap_slot *slot = &ring->slot[cur];
		char *p = NETMAP_BUF(ring, slot->buf_idx);

		if (dump)
			dump_payload(p, slot->len, ring, cur);

		cur = nm_ring_next(ring, cur);
	}
	ring->head = ring->cur = cur;

	return (rx);
}

static void *
receiver_body(void *data)
{
	struct targ *targ = (struct targ *) data;
	struct pollfd pfd = { .fd = targ->fd, .events = POLLIN };
	struct netmap_if *nifp;
	struct netmap_ring *rxring;
	int i;
	uint64_t received = 0;

	if (setaffinity(targ->thread, targ->affinity))
		goto quit;

	D("reading from %s fd %d main_fd %d",
		targ->g->ifname, targ->fd, targ->g->main_fd);
	/* unbounded wait for the first packet. */
	for (;!targ->cancel;) {
		i = poll(&pfd, 1, 1000);
		if (i > 0 && !(pfd.revents & POLLERR))
			break;
		RD(1, "waiting for initial packets, poll returns %d %d",
			i, pfd.revents);
	}
	/* main loop, exit after 1s silence */
	clock_gettime(CLOCK_REALTIME_PRECISE, &targ->tic);
    if (targ->g->dev_type == DEV_TAP) {
	while (!targ->cancel) {
		char buf[MAX_BODYSIZE];
		/* XXX should we poll ? */
		if (read(targ->g->main_fd, buf, sizeof(buf)) > 0)
			targ->count++;
	}
#ifndef NO_PCAP
    } else if (targ->g->dev_type == DEV_PCAP) {
	while (!targ->cancel) {
		/* XXX should we poll ? */
		pcap_dispatch(targ->g->p, targ->g->burst, receive_pcap,
			(u_char *)&targ->count);
	}
#endif /* !NO_PCAP */
    } else {
	int dump = targ->g->options & OPT_DUMP;

        nifp = targ->nmd->nifp;
	while (!targ->cancel) {
		/* Once we started to receive packets, wait at most 1 seconds
		   before quitting. */
		if (poll(&pfd, 1, 1 * 1000) <= 0 && !targ->g->forever) {
			clock_gettime(CLOCK_REALTIME_PRECISE, &targ->toc);
			targ->toc.tv_sec -= 1; /* Subtract timeout time. */
			goto out;
		}

		if (pfd.revents & POLLERR) {
			D("poll err");
			goto quit;
		}

		for (i = targ->nmd->first_rx_ring; i <= targ->nmd->last_rx_ring; i++) {
			int m;

			rxring = NETMAP_RXRING(nifp, i);
			if (nm_ring_empty(rxring))
				continue;

			m = receive_packets(rxring, targ->g->burst, dump);
			received += m;
		}
		targ->count = received;
	}
    }

	clock_gettime(CLOCK_REALTIME_PRECISE, &targ->toc);

out:
	targ->completed = 1;
	targ->count = received;

quit:
	/* reset the ``used`` flag. */
	targ->used = 0;

	return (NULL);
}

/* very crude code to print a number in normalized form.
 * Caller has to make sure that the buffer is large enough.
 */
static const char *
norm(char *buf, double val)
{
	char *units[] = { "", "K", "M", "G", "T" };
	u_int i;

	for (i = 0; val >=1000 && i < sizeof(units)/sizeof(char *) - 1; i++)
		val /= 1000;
	sprintf(buf, "%.2f %s", val, units[i]);
	return buf;
}

static void
tx_output(uint64_t sent, int size, double delta)
{
	double bw, raw_bw, pps;
	char b1[40], b2[80], b3[80];

	printf("Sent %llu packets, %d bytes each, in %.2f seconds.\n",
	       (unsigned long long)sent, size, delta);
	if (delta == 0)
		delta = 1e-6;
	if (size < 60)		/* correct for min packet size */
		size = 60;
	pps = sent / delta;
	bw = (8.0 * size * sent) / delta;
	/* raw packets have4 bytes crc + 20 bytes framing */
	raw_bw = (8.0 * (size + 24) * sent) / delta;

	printf("Speed: %spps Bandwidth: %sbps (raw %sbps)\n",
		norm(b1, pps), norm(b2, bw), norm(b3, raw_bw) );
}


static void
rx_output(uint64_t received, double delta)
{
	double pps;
	char b1[40];

	printf("Received %llu packets, in %.2f seconds.\n",
		(unsigned long long) received, delta);

	if (delta == 0)
		delta = 1e-6;
	pps = received / delta;
	printf("Speed: %spps\n", norm(b1, pps));
}
コード例 #25
0
ファイル: bridge.c プロジェクト: victordetoni/netmap-tools
static int
thr_run_loop(struct thr_ctx *th)
{
	struct pollfd pollfd[2];

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

	D("Ready to go, %s 0x%x/%d <-> %s 0x%x/%d.",
		th->pa->req.nr_name, th->pa->first_rx_ring, th->pa->req.nr_rx_rings,
		th->pb->req.nr_name, th->pb->first_rx_ring, th->pb->req.nr_rx_rings);

	while (!do_abort) {
		int n0, n1, ret;
		pollfd[0].events = pollfd[1].events = 0;
		pollfd[0].revents = pollfd[1].revents = 0;

		/* Always poll for read readiness */
		pollfd[0].events = POLLIN;
		pollfd[1].events = POLLIN;

		/*
		 * If there's no space in the destination
		 * ring, select for POLLOUT.
		 *
		 * Otherwise, an ioctl() will be done to do a
		 * hard txsync, so as to make space for subsequent
		 * read packets.
		 */
		if (pkt_queued(th->pa, 1) == 0)
			pollfd[0].events |= POLLOUT;
		if (pkt_queued(th->pb, 1) == 0)
			pollfd[1].events |= POLLOUT;

		/*
		 * This at least triggers the read check, and
		 * will also schedule TX frames out if needed.
		 */
		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(th->pa, 0),
				NETMAP_RXRING(th->pa->nifp, th->pa->cur_rx_ring)->cur,
				pkt_queued(th->pa, 1),
				pollfd[1].events,
				pollfd[1].revents,
				pkt_queued(th->pb, 0),
				NETMAP_RXRING(th->pb->nifp, th->pb->cur_rx_ring)->cur,
				pkt_queued(th->pb, 1)
			);
		}
		if (ret < 0)
			continue;
		if (pollfd[0].revents & POLLERR) {
			struct netmap_ring *rx = NETMAP_RXRING(th->pa->nifp,
			    th->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(th->pb->nifp,
			    th->pb->cur_rx_ring);
			D("error on fd1, rx [%d,%d,%d)",
				rx->head, rx->cur, rx->tail);
		}

		/*
		 * Next: the poll transmit side descriptors are only
		 * reclaimed when it's /just about/ to run out of
		 * descriptors (ie, it's done lazily.)
		 *
		 * So if we're about to run out transmit descriptor slots,
		 * don't wait until we fill the transmit side to have
		 * things reaped; just do a TXSYNC now.
		 *
		 * The poll() has already updated the driver side idea
		 * of transmit/receive availability, so check to see
		 * whether we have space.
		 */
		/*
		 * Check to see if there's enough transmit slots in th->pb
		 */
		if (pkt_queued(th->pa, 0) > pkt_queued(th->pb, 1)) {
			/* XXX spinloop? */
			while (ioctl(th->pb->fd, NIOCTXSYNC, NULL) != 0)
				usleep(1);
		}

		/*
		 * Check to see if there's enough transmit slots in th->pa
		 */
		if (pkt_queued(th->pb, 0) > pkt_queued(th->pa, 1)) {
			/* XXX spinloop? */
			while (ioctl(th->pa->fd, NIOCTXSYNC, NULL) != 0)
				usleep(1);
		}

		/* If we're read-ready, /then/ move */
		if (pollfd[1].revents & POLLIN) {
			move(th, th->pb, th->pa, th->burst);
		}
		if (pollfd[0].revents & POLLIN) {
			move(th, th->pa, th->pb, th->burst);
		}

		/*
		 * There's no need to call the ioctl() to flush;
		 * the next trip through poll() with POLLIN set
		 * will update the transmit pointer for us.
		 */
	}

	return (0);
}
コード例 #26
0
ファイル: pkt-gen.c プロジェクト: 2asoft/freebsd
int
main(int arc, char **argv)
{
	int i;

	struct glob_arg g;

	int ch;
	int wait_link = 2;
	int devqueues = 1;	/* how many device queues */

	bzero(&g, sizeof(g));

	g.main_fd = -1;
	g.td_body = receiver_body;
	g.report_interval = 1000;	/* report interval */
	g.affinity = -1;
	/* ip addresses can also be a range x.x.x.x-x.x.x.y */
	g.src_ip.name = "10.0.0.1";
	g.dst_ip.name = "10.1.0.1";
	g.dst_mac.name = "ff:ff:ff:ff:ff:ff";
	g.src_mac.name = NULL;
	g.pkt_size = 60;
	g.burst = 512;		// default
	g.nthreads = 1;
	g.cpus = 1;
	g.forever = 1;
	g.tx_rate = 0;
	g.frags = 1;
	g.nmr_config = "";
	g.virt_header = 0;

	while ( (ch = getopt(arc, argv,
			"a:f:F:n:i:Il:d:s:D:S:b:c:o:p:T:w:WvR:XC:H:e:m:P:zZ")) != -1) {
		struct sf *fn;

		switch(ch) {
		default:
			D("bad option %c %s", ch, optarg);
			usage();
			break;

		case 'n':
			g.npackets = atoi(optarg);
			break;

		case 'F':
			i = atoi(optarg);
			if (i < 1 || i > 63) {
				D("invalid frags %d [1..63], ignore", i);
				break;
			}
			g.frags = i;
			break;

		case 'f':
			for (fn = func; fn->key; fn++) {
				if (!strcmp(fn->key, optarg))
					break;
			}
			if (fn->key)
				g.td_body = fn->f;
			else
				D("unrecognised function %s", optarg);
			break;

		case 'o':	/* data generation options */
			g.options = atoi(optarg);
			break;

		case 'a':       /* force affinity */
			g.affinity = atoi(optarg);
			break;

		case 'i':	/* interface */
			/* a prefix of tap: netmap: or pcap: forces the mode.
			 * otherwise we guess
			 */
			D("interface is %s", optarg);
			if (strlen(optarg) > MAX_IFNAMELEN - 8) {
				D("ifname too long %s", optarg);
				break;
			}
			strcpy(g.ifname, optarg);
			if (!strcmp(optarg, "null")) {
				g.dev_type = DEV_NETMAP;
				g.dummy_send = 1;
			} else if (!strncmp(optarg, "tap:", 4)) {
				g.dev_type = DEV_TAP;
				strcpy(g.ifname, optarg + 4);
			} else if (!strncmp(optarg, "pcap:", 5)) {
				g.dev_type = DEV_PCAP;
				strcpy(g.ifname, optarg + 5);
			} else if (!strncmp(optarg, "netmap:", 7) ||
				   !strncmp(optarg, "vale", 4)) {
				g.dev_type = DEV_NETMAP;
			} else if (!strncmp(optarg, "tap", 3)) {
				g.dev_type = DEV_TAP;
			} else { /* prepend netmap: */
				g.dev_type = DEV_NETMAP;
				sprintf(g.ifname, "netmap:%s", optarg);
			}
			break;

		case 'I':
			g.options |= OPT_INDIRECT;	/* XXX use indirect buffer */
			break;

		case 'l':	/* pkt_size */
			g.pkt_size = atoi(optarg);
			break;

		case 'd':
			g.dst_ip.name = optarg;
			break;

		case 's':
			g.src_ip.name = optarg;
			break;

		case 'T':	/* report interval */
			g.report_interval = atoi(optarg);
			break;

		case 'w':
			wait_link = atoi(optarg);
			break;

		case 'W': /* XXX changed default */
			g.forever = 0; /* do not exit rx even with no traffic */
			break;

		case 'b':	/* burst */
			g.burst = atoi(optarg);
			break;
		case 'c':
			g.cpus = atoi(optarg);
			break;
		case 'p':
			g.nthreads = atoi(optarg);
			break;

		case 'D': /* destination mac */
			g.dst_mac.name = optarg;
			break;

		case 'S': /* source mac */
			g.src_mac.name = optarg;
			break;
		case 'v':
			verbose++;
			break;
		case 'R':
			g.tx_rate = atoi(optarg);
			break;
		case 'X':
			g.options |= OPT_DUMP;
			break;
		case 'C':
			g.nmr_config = strdup(optarg);
			break;
		case 'H':
			g.virt_header = atoi(optarg);
			break;
		case 'e': /* extra bufs */
			g.extra_bufs = atoi(optarg);
			break;
		case 'm':
			if (strcmp(optarg, "tx") == 0) {
				g.options |= OPT_MONITOR_TX;
			} else if (strcmp(optarg, "rx") == 0) {
				g.options |= OPT_MONITOR_RX;
			} else {
				D("unrecognized monitor mode %s", optarg);
			}
			break;
		case 'P':
			g.packet_file = strdup(optarg);
			break;
		case 'z':
			g.options |= OPT_RANDOM_SRC;
			break;
		case 'Z':
			g.options |= OPT_RANDOM_DST;
			break;
		}
	}

	if (strlen(g.ifname) <=0 ) {
		D("missing ifname");
		usage();
	}

	i = system_ncpus();
	if (g.cpus < 0 || g.cpus > i) {
		D("%d cpus is too high, have only %d cpus", g.cpus, i);
		usage();
	}
	if (g.cpus == 0)
		g.cpus = i;

	if (g.pkt_size < 16 || g.pkt_size > MAX_PKTSIZE) {
		D("bad pktsize %d [16..%d]\n", g.pkt_size, MAX_PKTSIZE);
		usage();
	}

	if (g.src_mac.name == NULL) {
		static char mybuf[20] = "00:00:00:00:00:00";
		/* retrieve source mac address. */
		if (source_hwaddr(g.ifname, mybuf) == -1) {
			D("Unable to retrieve source mac");
			// continue, fail later
		}
		g.src_mac.name = mybuf;
	}
	/* extract address ranges */
	extract_ip_range(&g.src_ip);
	extract_ip_range(&g.dst_ip);
	extract_mac_range(&g.src_mac);
	extract_mac_range(&g.dst_mac);

	if (g.src_ip.start != g.src_ip.end ||
	    g.src_ip.port0 != g.src_ip.port1 ||
	    g.dst_ip.start != g.dst_ip.end ||
	    g.dst_ip.port0 != g.dst_ip.port1)
		g.options |= OPT_COPY;

	if (g.virt_header != 0 && g.virt_header != VIRT_HDR_1
			&& g.virt_header != VIRT_HDR_2) {
		D("bad virtio-net-header length");
		usage();
	}

    if (g.dev_type == DEV_TAP) {
	D("want to use tap %s", g.ifname);
	g.main_fd = tap_alloc(g.ifname);
	if (g.main_fd < 0) {
		D("cannot open tap %s", g.ifname);
		usage();
	}
#ifndef NO_PCAP
    } else if (g.dev_type == DEV_PCAP) {
	char pcap_errbuf[PCAP_ERRBUF_SIZE];

	pcap_errbuf[0] = '\0'; // init the buffer
	g.p = pcap_open_live(g.ifname, 256 /* XXX */, 1, 100, pcap_errbuf);
	if (g.p == NULL) {
		D("cannot open pcap on %s", g.ifname);
		usage();
	}
	g.main_fd = pcap_fileno(g.p);
	D("using pcap on %s fileno %d", g.ifname, g.main_fd);
#endif /* !NO_PCAP */
    } else if (g.dummy_send) { /* but DEV_NETMAP */
	D("using a dummy send routine");
    } else {
	struct nmreq base_nmd;

	bzero(&base_nmd, sizeof(base_nmd));

	parse_nmr_config(g.nmr_config, &base_nmd);
	if (g.extra_bufs) {
		base_nmd.nr_arg3 = g.extra_bufs;
	}

	/*
	 * Open the netmap device using nm_open().
	 *
	 * protocol stack and may cause a reset of the card,
	 * which in turn may take some time for the PHY to
	 * reconfigure. We do the open here to have time to reset.
	 */
	g.nmd = nm_open(g.ifname, &base_nmd, 0, NULL);
	if (g.nmd == NULL) {
		D("Unable to open %s: %s", g.ifname, strerror(errno));
		goto out;
	}
	g.main_fd = g.nmd->fd;
	D("mapped %dKB at %p", g.nmd->req.nr_memsize>>10, g.nmd->mem);

	/* get num of queues in tx or rx */ 
	if (g.td_body == sender_body)
		devqueues = g.nmd->req.nr_tx_rings;
	else 
		devqueues = g.nmd->req.nr_rx_rings;

	/* validate provided nthreads. */
	if (g.nthreads < 1 || g.nthreads > devqueues) {
		D("bad nthreads %d, have %d queues", g.nthreads, devqueues);
		// continue, fail later
	}

	if (verbose) {
		struct netmap_if *nifp = g.nmd->nifp;
		struct nmreq *req = &g.nmd->req;

		D("nifp at offset %d, %d tx %d rx region %d",
		    req->nr_offset, req->nr_tx_rings, req->nr_rx_rings,
		    req->nr_arg2);
		for (i = 0; i <= req->nr_tx_rings; i++) {
			struct netmap_ring *ring = NETMAP_TXRING(nifp, i);
			D("   TX%d at 0x%lx slots %d", i,
			    (char *)ring - (char *)nifp, ring->num_slots);
		}
		for (i = 0; i <= req->nr_rx_rings; i++) {
			struct netmap_ring *ring = NETMAP_RXRING(nifp, i);
			D("   RX%d at 0x%lx slots %d", i,
			    (char *)ring - (char *)nifp, ring->num_slots);
		}
	}

	/* Print some debug information. */
	fprintf(stdout,
		"%s %s: %d queues, %d threads and %d cpus.\n",
		(g.td_body == sender_body) ? "Sending on" : "Receiving from",
		g.ifname,
		devqueues,
		g.nthreads,
		g.cpus);
	if (g.td_body == sender_body) {
		fprintf(stdout, "%s -> %s (%s -> %s)\n",
			g.src_ip.name, g.dst_ip.name,
			g.src_mac.name, g.dst_mac.name);
	}

out:
	/* Exit if something went wrong. */
	if (g.main_fd < 0) {
		D("aborting");
		usage();
	}
    }


	if (g.options) {
		D("--- SPECIAL OPTIONS:%s%s%s%s%s\n",
			g.options & OPT_PREFETCH ? " prefetch" : "",
			g.options & OPT_ACCESS ? " access" : "",
			g.options & OPT_MEMCPY ? " memcpy" : "",
			g.options & OPT_INDIRECT ? " indirect" : "",
			g.options & OPT_COPY ? " copy" : "");
	}

	g.tx_period.tv_sec = g.tx_period.tv_nsec = 0;
	if (g.tx_rate > 0) {
		/* try to have at least something every second,
		 * reducing the burst size to some 0.01s worth of data
		 * (but no less than one full set of fragments)
	 	 */
		uint64_t x;
		int lim = (g.tx_rate)/300;
		if (g.burst > lim)
			g.burst = lim;
		if (g.burst < g.frags)
			g.burst = g.frags;
		x = ((uint64_t)1000000000 * (uint64_t)g.burst) / (uint64_t) g.tx_rate;
		g.tx_period.tv_nsec = x;
		g.tx_period.tv_sec = g.tx_period.tv_nsec / 1000000000;
		g.tx_period.tv_nsec = g.tx_period.tv_nsec % 1000000000;
	}
	if (g.td_body == sender_body)
	    D("Sending %d packets every  %ld.%09ld s",
			g.burst, g.tx_period.tv_sec, g.tx_period.tv_nsec);
	/* Wait for PHY reset. */
	D("Wait %d secs for phy reset", wait_link);
	sleep(wait_link);
	D("Ready...");

	/* Install ^C handler. */
	global_nthreads = g.nthreads;
	signal(SIGINT, sigint_h);

	start_threads(&g);
	main_thread(&g);
	return 0;
}
コード例 #27
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);
}
コード例 #28
0
ファイル: compat_netmap.c プロジェクト: AMildner/MoonGen
static int
netmap_regif(struct nmreq *req, uint32_t idx, uint8_t port)
{
	struct netmap_if *nmif;
	struct netmap_ring *ring;
	uint32_t i, slots, start_ring;
	int32_t rc;

	if (ports[port].fd < RTE_DIM(fd_port)) {
	    	RTE_LOG(ERR, USER1, "port %hhu already in use by fd: %u\n",
			port, IDX_TO_FD(ports[port].fd));
		return (-EBUSY);
	}
	if (fd_port[idx].port != FD_PORT_RSRV) {
	    	RTE_LOG(ERR, USER1, "fd: %u is misconfigured\n",
			IDX_TO_FD(idx));
		return (-EBUSY);
	}

	nmif = ports[port].nmif;

	/* setup netmap_if fields. */
	memset(nmif, 0, netmap.netif_memsz);

	/* only ALL rings supported right now. */
	if (req->nr_ringid != 0)
		return (-EINVAL);

	snprintf(nmif->ni_name, sizeof(nmif->ni_name), "%s", req->nr_name);
	nmif->ni_version  = req->nr_version;

	/* Netmap uses ni_(r|t)x_rings + 1 */
	nmif->ni_rx_rings = ports[port].nr_rx_rings - 1;
	nmif->ni_tx_rings = ports[port].nr_tx_rings - 1;

	/*
	 * Setup TX rings and slots.
	 * Refer to the comments in netmap.h for details
	 */

	slots = 0;
	for (i = 0; i < nmif->ni_tx_rings + 1; i++) {

		nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i,
			PORT_NUM_RINGS, slots);

		ring = NETMAP_TXRING(nmif, i);
		netmap_ring_setup(ring, port, i, ports[port].nr_tx_slots);
		ring->avail = ring->num_slots;

		slots += ports[port].nr_tx_slots;
	}

	/*
	 * Setup  RX rings and slots.
	 * Refer to the comments in netmap.h for details
	 */

	start_ring = i;

	for (; i < nmif->ni_rx_rings + 1 + start_ring; i++) {

		nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i,
			PORT_NUM_RINGS, slots);

		ring = NETMAP_RXRING(nmif, (i - start_ring));
		netmap_ring_setup(ring, port, i, ports[port].nr_rx_slots);
		ring->avail = 0;

		slots += ports[port].nr_rx_slots;
	}

	if ((rc = rte_eth_dev_start(port)) < 0) {
		RTE_LOG(ERR, USER1,
			"Couldn't start ethernet device %s (error %d)\n",
			req->nr_name, rc);
	    return (rc);
	}

	/* setup fdi <--> port relationtip. */
	ports[port].fd = idx;
	fd_port[idx].port = port;

	req->nr_memsize = netmap.mem_sz;
	req->nr_offset = (uintptr_t)nmif - (uintptr_t)netmap.mem;

	return (0);
}
コード例 #29
0
ファイル: dispatcher.c プロジェクト: gonzopancho/netmap-test
void *dispatcher(void *threadarg) {
  assert(threadarg);

  struct thread_context *context;
  struct thread_context *contexts;
  int rv;
  struct netmap_ring *rxring;
  struct ethernet_pkt *etherpkt;
  struct pollfd pfd;
  struct dispatcher_data *data;
  uint32_t *slots_used, *open_transactions;
  uint32_t i, arpd_idx, num_threads;
  char *buf;
  struct msg_hdr *msg;
  struct ether_addr *mac;

  context = (struct thread_context *)threadarg;
  contexts = context->shared->contexts;
  data = context->data;
  arpd_idx = context->shared->arpd_idx;
  mac = &context->shared->if_info->mac;
  num_threads = context->shared->num_threads;

  struct transaction *transactions[num_threads];
  uint64_t dropped[num_threads];
  for (i=0; i < num_threads; i++) {
    transactions[i] = NULL;
    dropped[i] = 0;
  }

  rv = dispatcher_init(context);
  if (!rv) {
    pthread_exit(NULL);
  }

  rxring = NETMAP_RXRING(data->nifp, 0);
  slots_used = bitmap_new(rxring->num_slots);
  if (!slots_used)
    pthread_exit(NULL);

  open_transactions = bitmap_new(num_threads);
  if (!open_transactions)
    pthread_exit(NULL);

  pfd.fd = data->fd;
  pfd.events = (POLLIN);

  printf("dispatcher[%d]: initialized\n", context->thread_id);
  // signal to main() that we are initialized
  atomic_store_explicit(&context->initialized, 1, memory_order_release);

  for (;;) {
    rv = poll(&pfd, 1, POLL_TIMEOUT);

    // read all packets from the ring
    if (rv > 0) {
      for (; rxring->avail > 0; rxring->avail--) {
        i = rxring->cur;
        rxring->cur = NETMAP_RING_NEXT(rxring, i);
        rxring->reserved++;
        buf = NETMAP_BUF(rxring, rxring->slot[i].buf_idx);
        etherpkt = (struct ethernet_pkt *)(void *)buf;

        // TODO: consider pushing this check to the workers
        if (!ethernet_is_valid(etherpkt, mac)) {
          if (rxring->reserved == 1)
            rxring->reserved = 0;
          continue;
        }

        // TODO: dispatch to n workers instead of just 0
        switch (etherpkt->h.ether_type) {
          case IP4_ETHERTYPE:
            rv = tqueue_insert(contexts[0].pkt_recv_q,
                               &transactions[0], (char *) NULL + i);
            switch (rv) {
              case TQUEUE_SUCCESS:
                bitmap_set(slots_used, i);
                bitmap_set(open_transactions, 0);
                break;
              case TQUEUE_TRANSACTION_FULL:
                bitmap_set(slots_used, i);
                bitmap_clear(open_transactions, 0);
                break;
              case TQUEUE_FULL:
                // just drop packet and do accounting
                dropped[0]++;
                if (rxring->reserved == 1)
                  rxring->reserved = 0;
                break;
            }
            break;
          case ARP_ETHERTYPE:
            rv = tqueue_insert(contexts[arpd_idx].pkt_recv_q,
                               &transactions[arpd_idx], (char *) NULL + i);
            switch (rv) {
              case TQUEUE_SUCCESS:
                tqueue_publish_transaction(contexts[arpd_idx].pkt_recv_q,
                                            &transactions[arpd_idx]);
                bitmap_set(slots_used, i);
                break;
              case TQUEUE_TRANSACTION_FULL:
                bitmap_set(slots_used, i);
                break;
              case TQUEUE_FULL:
                // just drop packet and do accounting
                dropped[arpd_idx]++;
                if (rxring->reserved == 1)
                  rxring->reserved = 0;
                break;
            }
            break;
          default:
            printf("dispatcher[%d]: unknown/unsupported ethertype %hu\n",
                    context->thread_id, etherpkt->h.ether_type);
            if (rxring->reserved == 1)
              rxring->reserved = 0;
        } // switch (ethertype)
      } // for (rxring)

      // publish any open transactions so that the worker can start on it
      for (i=0; i < num_threads; i++) {
        if (bitmap_get(open_transactions, i))
          tqueue_publish_transaction(contexts[i].pkt_recv_q, &transactions[i]);
      }
      bitmap_clearall(open_transactions, num_threads);
    } // if (packets)

    // read the message queue
    rv = squeue_enter(context->msg_q, 1);
    if (!rv)
      continue;
    while ((msg = squeue_get_next_pop_slot(context->msg_q)) != NULL) {
      switch (msg->msg_type) {
        case MSG_TRANSACTION_UPDATE:
          update_slots_used(context->msg_q, slots_used, rxring);
          break;
        case MSG_TRANSACTION_UPDATE_SINGLE:
          update_slots_used_single((void *)msg, slots_used, rxring);
          break;
        default:
          printf("dispatcher: unknown message %hu\n", msg->msg_type);
      }
    }
    squeue_exit(context->msg_q);

  } // for(;;)

  pthread_exit(NULL);
}
コード例 #30
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;
}