示例#1
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();
}
示例#2
0
int
ether_input(struct nm_if *nmif, int ring, char *buf, int len)
{
	int err;
	struct ether_header *eh;
	struct ether_vlan_header *evl;
	struct nm_if_vlan *vlan;

	if (len < ETHER_HDR_LEN) {
		DPRINTF("%s: discarding packet, too short.\n", __func__);
		pktcnt.rx_drop++;
		return (-1);
	}
	err = 0;
	eh = (struct ether_header *)buf;
	switch (ntohs(eh->ether_type)) {
	case ETHERTYPE_ARP:
		pktcnt.rx_arp++;
		err = arp_input(nmif, ring, buf + ETHER_HDR_LEN,
		    len - ETHER_HDR_LEN);
		break;
	case ETHERTYPE_IP:
		pktcnt.rx_ip++;
		err = ip_input(nmif, ring, buf + ETHER_HDR_LEN,
		    len - ETHER_HDR_LEN);
		break;
	case ETHERTYPE_VLAN:
		//pktcnt.rx_vlan++;
		if (len < ETHER_VLAN_ENCAP_LEN) {
			DPRINTF("%s: discarding vlan packet, too short.\n",
			    __func__);
			pktcnt.rx_drop++;
			return (-1);
		}
		evl = (struct ether_vlan_header *)buf;
		vlan = if_find_vlan(nmif, ntohs(evl->evl_tag));
		if (vlan == NULL) {
			pktcnt.rx_drop++;
			DPRINTF("%s: unknown vlan tag %d, discanding packet.\n",
			    __func__, ntohs(evl->evl_tag));
			return (-1);
		}
		memmove(buf + ETHER_VLAN_ENCAP_LEN, buf, ETHER_ADDR_LEN * 2);
		err = ether_input(vlan->nmif, ring, buf + ETHER_VLAN_ENCAP_LEN,
		    len - ETHER_VLAN_ENCAP_LEN);
		if (!nohostring && err == 1) {
			memmove(buf, buf + ETHER_VLAN_ENCAP_LEN,
			    ETHER_ADDR_LEN * 2);
			evl = (struct ether_vlan_header *)buf;
			evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
			evl->evl_tag = htons(vlan->nmif->nm_if_vtag);
			ether_bridge(vlan->nmif, ring, buf, len);
			return (0);
		}
		break;
	default:
		pktcnt.rx_drop++;
		DPRINTF("%s: protocol %#04x not supported, discanding packet.\n",
		    __func__, ntohs(eh->ether_type));
		err = -1;
	}

	return (err);
}