Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Aug 2015 16:24:12 GMT
From:      iateaca@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r289111 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve
Message-ID:  <201508021624.t72GOCfi068539@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: iateaca
Date: Sun Aug  2 16:24:11 2015
New Revision: 289111
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=289111

Log:
  handle the received multicast traffic

Modified:
  soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c

Modified: soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c
==============================================================================
--- soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c	Sun Aug  2 14:56:30 2015	(r289110)
+++ soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c	Sun Aug  2 16:24:11 2015	(r289111)
@@ -281,6 +281,9 @@
 
 	DPRINTF("Receive Packet: from tap interface of %zd bytes", read_len);
 
+	/* clear the Receiver Status Register */
+	ne2000_set_reg_by_offset(sc, NE2000_P0_RO, ED_P0_RSR, 0x00);
+
 	if (!ne2000_ether_frame_is_valid(sc)) {
 		DPRINTF("Drop the packet since the ether frame did not match");
 		return 0;
@@ -291,6 +294,9 @@
 		return 0;
 	}
 
+	ne2000_set_field_by_offset(sc, NE2000_P0_RO, ED_P0_RSR,
+			ED_RSR_PRX, ED_RSR_PRX);
+
 	size = read_len < ETHER_MIN_FRAME_LEN ? ETHER_MIN_FRAME_LEN : read_len;
 
 	/* psize is the number of pages used by the frame and ne2000 header */
@@ -313,9 +319,6 @@
 	DPRINTF("Receive Packet: size: %d psize: %d next_curr: %d index: %d",
 			size, psize, next_curr, index);
 
-	ne2000_set_field_by_offset(sc, NE2000_P0_RO, ED_P0_RSR,
-			0xff, ED_RSR_PRX);
-
 	ed_hdr = (struct ed_ring *)(sc->ram + index);
 	ed_hdr->rsr = ne2000_get_reg_by_offset(sc, NE2000_P0_RO, ED_P0_RSR);
 	ed_hdr->next_packet = next_curr;
@@ -424,6 +427,9 @@
 static int
 ne2000_ether_frame_is_valid(struct pci_ne2000_softc *sc)
 {
+	uint8_t key = 0;
+	uint8_t mar_offset = 0;
+	uint8_t mar_reg = 0;
 	uint8_t rcr = 0;
 	uint8_t broadcast_addr[] = {[0 ... (ETHER_ADDR_LEN - 1)] = 0xff};
 
@@ -445,8 +451,25 @@
 
 	/* is valid if the destination MAC is the broadcast address */
 	if (rcr & ED_RCR_AB) {
-		if (memcmp(sc->rcv_buf, broadcast_addr, ETHER_ADDR_LEN) == 0)
+		if (memcmp(sc->rcv_buf, broadcast_addr, ETHER_ADDR_LEN) == 0) {
+			ne2000_set_field_by_offset(sc, NE2000_P0_RO, ED_P0_RSR,
+					ED_RSR_PHY, ED_RSR_PHY);
 			return 1;
+		}
+	}
+
+	/* is valid if the destination MAC represents a multicast address group */
+	if ((rcr & ED_RCR_AM) && (sc->rcv_buf[0] & 0x01)) {
+		key = ne2000_ether_crc32_be(sc->rcv_buf, ETHER_ADDR_LEN) >> 26;
+
+		mar_offset = ED_P1_MAR0 + (key >> 3);
+		mar_reg = ne2000_get_reg_by_offset(sc, NE2000_P1, mar_offset);
+
+		if (mar_reg & (1 << (key & 7))) {
+			ne2000_set_field_by_offset(sc, NE2000_P0_RO, ED_P0_RSR,
+					ED_RSR_PHY, ED_RSR_PHY);
+			return 1;
+		}
 	}
 
 	return 0;
@@ -837,16 +860,29 @@
 ne2000_emul_reg_page1(struct pci_ne2000_softc *sc, uint8_t offset,
 		uint8_t value)
 {
+	int err;
 	uint8_t pstart = 0;
 	uint8_t pstop = 0;
 
-	if (offset == ED_P1_CR)
-		return ne2000_emul_reg_page0(sc, offset, value);
-	else if (offset == ED_P1_CURR) {
+	switch (offset) {
+	case ED_P1_CR:
+		err = ne2000_emul_reg_page0(sc, offset, value);
+		assert(err == 0);
+		break;
+	case ED_P1_PAR0 ... ED_P1_PAR5:
+		DPRINTF("PAR[%d]: 0x%x", offset - ED_P1_PAR0, value);
+		break;
+	case ED_P1_CURR:
 		DPRINTF("Current Page Register: %d", value);
 		pstart = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_PSTART);
 		pstop = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_PSTOP);
 		assert(value >= pstart && value < pstop);
+		break;
+	case ED_P1_MAR0 ... ED_P1_MAR7:
+		DPRINTF("MAR[%d]: 0x%x", offset - ED_P1_MAR0, value);
+		break;
+	default:
+		assert(0);
 	}
 
 	return 0;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508021624.t72GOCfi068539>