Example #1
0
void
ether_bridge(struct nm_if *nmif, int ring, char *inbuf, int len)
{
	char *buf;
	struct netmap_if *ifp;
	struct netmap_ring *nring;
	struct nm_if *parentif;

	parentif = NETMAP_PARENTIF(nmif);
	ifp = parentif->nm_if_ifp;
	if (NETMAP_HOST_RING(parentif, ring))
		nring = netmap_hw_tx_ring(ifp);
	else
		nring = NETMAP_TXRING(ifp, ifp->ni_tx_rings);

	buf = NETMAP_GET_BUF(nring);
	if (buf == NULL) {
		DPRINTF("%s: no available buffer for tx (%s).\n",
		    __func__, nmif->nm_if_name);
		parentif->nm_if_txsync = 1;
		pktcnt.tx_drop++;
		return;
	}
	/* Copy the payload. */
	memcpy(buf, inbuf, len);

	NETMAP_UPDATE_LEN(nring, len);

	/* Update the current ring slot. */
	NETMAP_RING_NEXT(nring);

	pktcnt.tx_pkts++;
	parentif->nm_if_txsync = 1;
}
Example #2
0
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();
}
Example #3
0
int
ether_output(struct nm_if *nmif, struct in_addr *dst, struct ether_addr *lladdr,
	unsigned short ether_type, char *inbuf, int inlen)
{
	char *buf;
	int err, len;
	struct arp *arp;
	struct ether_header *eh;
	struct ether_vlan_header *evl;
	struct netmap_ring *ring;
	struct nm_if *parentif;

	if (lladdr == NULL) {
		err = arp_search_if(nmif, dst, &arp);
		if (err != 0)
			return (err);
	}

	parentif = NETMAP_PARENTIF(nmif);
	ring = netmap_hw_tx_ring(parentif->nm_if_ifp);
	if (ring == NULL) {
		DPRINTF("%s: no available ring for tx (%s).\n",
		    __func__, parentif->nm_if_name);
		parentif->nm_if_txsync = 1;
		pktcnt.tx_drop++;
		return (-1);
	}
	if (inlen + ETHER_HDR_LEN > ring->nr_buf_size) {
		DPRINTF("%s: buffer too big, cannot tx.\n", __func__);
		pktcnt.tx_drop++;
		return (-1);
	}
	buf = NETMAP_GET_BUF(ring);
	if (buf == NULL) {
		DPRINTF("%s: no available buffer for tx (%s).\n",
		    __func__, parentif->nm_if_name);
		parentif->nm_if_txsync = 1;
		pktcnt.tx_drop++;
		return (-1);
	}

	if (NETMAP_VLANIF(nmif)) {
		/* Copy the ethernet vlan header. */
		evl = (struct ether_vlan_header *)buf;
		evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
		evl->evl_tag = htons(nmif->nm_if_vtag);
		evl->evl_proto = htons(ether_type);
		if (lladdr != NULL)
			memcpy(evl->evl_dhost, lladdr, sizeof(evl->evl_dhost));
		else
			memcpy(evl->evl_dhost, &arp->lladdr,
			    sizeof(evl->evl_dhost));
		memcpy(evl->evl_shost, LLADDR(&nmif->nm_if_dl),
		    sizeof(evl->evl_shost));
		len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
	} else {
		/* Copy the ethernet header. */
		eh = (struct ether_header *)buf;
		eh->ether_type = htons(ether_type);
		if (lladdr != NULL)
			memcpy(eh->ether_dhost, lladdr,
			    sizeof(eh->ether_dhost));
		else
			memcpy(eh->ether_dhost, &arp->lladdr,
			    sizeof(eh->ether_dhost));
		memcpy(eh->ether_shost, LLADDR(&nmif->nm_if_dl),
		    sizeof(eh->ether_shost));
		len = ETHER_HDR_LEN;
	}

	/* Copy the payload. */
	memcpy(buf + len, inbuf, inlen);
	len += inlen;

	NETMAP_UPDATE_LEN(ring, len);

//DPRINTF("%s: len: %d\n", __func__, len);
//if (verbose) hexdump(buf, len, NULL, 0);

	/* Update the current ring slot. */
	NETMAP_RING_NEXT(ring);

	pktcnt.tx_pkts++;
	parentif->nm_if_txsync = 1;

	return (0);
}