From nobody Sun Feb 8 00:26:12 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1574945910; cv=none; d=zohomail.com; s=zohoarc; b=l2bq15fgyr8QSN1vy64kKTty24UbN9GWsCPxpVxtXGvv5zU/mILyUQOVo62aFmxBLUKScHsWNWWy4Q86YGz0rA4zEbWRdAdl41JZKmAiF8AVA3rgS50JqOb2D3B7IyjX7CFF/XJcfEvkwWuBmoS3INJfly1cuCGIT4qo8bxMqz0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1574945910; h=Content-Type:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=CuFH4odQy9eB5sy9LpCGiGr2rDA2PHPn16LGN8ICTpM=; b=EvfdiVyqVFKXDj3yWKrJ+gjB7ZUdBgYcwd+ryLnlZUsKBiKCCjNWjEc5qwjdmsPwtgDoknuwN7TUQLyWHlMARQ6LoQMMkeqIxGkbC64A7yOqasYy22icl1pmhpaMDSwkGHdQ3oB9t8ReacRVXvWnNLZ6kVTG4p2vJIHqU9q6oz8= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1574945910429258.7316682098874; Thu, 28 Nov 2019 04:58:30 -0800 (PST) Received: from localhost ([::1]:48706 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iaJNL-0006UC-QT for importer@patchew.org; Thu, 28 Nov 2019 07:58:27 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39650) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iaJFD-0001Lb-1Y for qemu-devel@nongnu.org; Thu, 28 Nov 2019 07:50:06 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iaJEq-0007O5-Ru for qemu-devel@nongnu.org; Thu, 28 Nov 2019 07:49:44 -0500 Received: from esa4.mentor.iphmx.com ([68.232.137.252]:10524) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iaJEn-0007F4-OV for qemu-devel@nongnu.org; Thu, 28 Nov 2019 07:49:38 -0500 Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa4.mentor.iphmx.com with ESMTP; 28 Nov 2019 04:49:32 -0800 IronPort-SDR: wodJaMmiJvQnCYEMqMdxorBiHIAAps3RZvLaDMUun2wGfJnv2DsWF5qSIPnMrZvpCKqZdPq/2a bKEmQIJb3XHk8ZxhrYDvC9vko4kSbMgFa8wKj1mmh/xi/eKexd78KwYxpJBpWv5P4OaFXvEC3z xm7ZuZpc7EKDQ3xRR+lnWZwgUPBc+Zcc2y/2h0sa6N57SjaVHWEpo3ZyKytdkCcS2lBKVF7P0e tf2brQSpTIduIW7xcGXaM4/WuO+aLBSK/oF/iD0Gl+XnLmwMkdPe/dS1ZDW6hrEktrNYQ6FLz0 MBw= X-IronPort-AV: E=Sophos;i="5.69,253,1571731200"; d="scan'208,217";a="43631364" IronPort-SDR: H1o8IWMpEB4vsWodXcJgtJQCN/+RLr3OtRiNxsaMvf+KM+mesUohZT3itaOobPzIRsssjTTK5a kfVQ38w3k18lGKbYiPKZdsAheMslPl8LpChiI1etWKEozh7b8BgPYpa1Co6jKT/W96N3p/gwvq PM3OgQWusRrd0B5Xfm3U54eMW7UkkG0o+zPeIfamMHmA4LtoiBwSXM9PXdK0DCDP5TGUQWAEBe 1xi47CFEJNpES7Ntpp/TLJDjngRy45WcdMgSfY0/MH0xLX79BkbWPNpAvNBqKLpQ4lwA4MEM9W +Xc= From: "Wasim, Bilal" To: "qemu-devel@nongnu.org" Subject: [PATCH] Adding support for MAC filtering in the FEC IP implementation Thread-Topic: [PATCH] Adding support for MAC filtering in the FEC IP implementation Thread-Index: AQHVpenGG+H5kkbz0ECoeUMLi/ynzw== Date: Thu, 28 Nov 2019 12:49:26 +0000 Message-ID: <1574945365996.88572@mentor.com> Accept-Language: en-GB, en-IE, en-US Content-Language: en-GB X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [137.202.0.90] Content-Type: multipart/alternative; boundary="_000_157494536599688572mentorcom_" MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 68.232.137.252 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "peter.maydell@linaro.org" , "jasowang@redhat.com" , "armbru@redhat.com" , "aa1ronham@gmail.com" , "jcd@tribudubois.net" , "Wasim, Bilal" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" --_000_157494536599688572mentorcom_ Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Adding support for MAC filtering in the FEC IP implementation. This addition ensures that the IP does NOT boot up in promiscuous mode by default, and so the software only receives the desired packets(Unicast, Broadcast, Unicast / Multicast hashed) by default. The software running on-top of QEMU can also modify these settings and disable reception of broadcast frames or make the IP receive all packets (PROM mod= e). This patch greatly reduces the number of packets received by the software running on-top of the QEMU model. Tested with the armv7-a SABRE_LITE machi= ne. Testing included running a custom OS with IPv4 / IPv6 support. Hashing and filtering of packets is tested to work well. Skeleton taken from the CADENCE_GEM IP and hash generation algorithm from the Linux Kernel. Signed-off-by: Bilal Wasim --- hw/net/imx_fec.c | 92 ++++++++++++++++++++++++++++++++++++++++++++= +++- include/hw/net/imx_fec.h | 12 +++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index bd99236..96c52dd 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -419,6 +419,80 @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_= addr_t addr) dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd)); } +/* + * Calculate a FEC MAC Address hash index + */ +static unsigned calc_mac_hash(const uint8_t *mac, uint8_t mac_length) +{ + uint32_t crc =3D -1; + int i; + + while (mac_length --) { + crc ^=3D *mac++; + for (i =3D 0; i < 8; i++) { + crc =3D (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + } + + /* only upper 6 bits (FEC_HASH_BITS) are used + * which point to specific bit in the hash registers + */ + return ((crc >> (32 - FEC_HASH_BITS)) & 0x3f); +} + +/* + * fec_mac_address_filter: + * Accept or reject this destination address? + */ +static int fec_mac_address_filter(IMXFECState *s, const uint8_t *packet) +{ + const uint8_t broadcast_addr[] =3D { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF= F }; + uint32_t addr1, addr2; + uint8_t hash; + + /* Promiscuous mode? */ + if (s->regs[ENET_RCR] & ENET_RCR_PROM) { + return (FEC_RX_PROMISCUOUS_ACCEPT); /* Accept all packets in promi= scuous mode (even if bc_rej is set). */ + } + + /* Broadcast packet? */ + if (!memcmp(packet, broadcast_addr, 6)) { + /* Reject broadcast packets? */ + if (s->regs[ENET_RCR] & ENET_RCR_BC_REJ) { + return (FEC_RX_REJECT); + } + return (FEC_RX_BROADCAST_ACCEPT); /* Accept packets from broadcast= address. */ + } + + /* Accept packets -w- hash match? */ + hash =3D calc_mac_hash(packet, 6); + + /* Accept packets -w- multicast hash match? */ + if ((packet[0] & 0x01) =3D=3D 0x01) { + /* See if the computed hash matches a set bit in either GAUR / GAL= R register. */ + if (((hash < 32) && (s->regs[ENET_GALR] & (1 << hash))) + || ((hash > 31) && (s->regs[ENET_GAUR] & (1 << (hash-32)))= )) { + return (FEC_RX_MULTICAST_HASH_ACCEPT); /* Accept multicast has= h enabled address. */ + } + } else { + /* See if the computed hash matches a set bit in either IAUR / IAL= R register. */ + if (((hash < 32) && (s->regs[ENET_IALR] & (1 << hash))) + || ((hash > 31) && (s->regs[ENET_IAUR] & (1 << (hash-32)))= )) { + return (FEC_RX_UNICAST_HASH_ACCEPT); /* Accept multicast hash = enabled address. */ + } + } + + /* Match Unicast address. */ + addr1 =3D g_htonl(s->regs[ENET_PALR]); + addr2 =3D g_htonl(s->regs[ENET_PAUR]); + if (!(memcmp(packet, (uint8_t *) &addr1, 4) || memcmp(packet+4, (uint8= _t *) &addr2, 2))) { + return (FEC_RX_UNICAST_ACCEPT); /* Accept packet because it matche= s my unicast address. */ + } + + /* Return -1 because we do NOT support MAC address filtering.. */ + return (FEC_RX_REJECT); +} + static void imx_eth_update(IMXFECState *s) { /* @@ -984,7 +1058,7 @@ static void imx_eth_write(void *opaque, hwaddr offset,= uint64_t value, case ENET_IALR: case ENET_GAUR: case ENET_GALR: - /* TODO: implement MAC hash filtering. */ + s->regs[index] |=3D value; break; case ENET_TFWR: if (s->is_fec) { @@ -1066,8 +1140,16 @@ static ssize_t imx_fec_receive(NetClientState *nc, c= onst uint8_t *buf, uint32_t buf_addr; uint8_t *crc_ptr; unsigned int buf_len; + int maf; size_t size =3D len; + /* Is this destination MAC address "for us" ? */ + maf =3D fec_mac_address_filter(s, buf); + if (maf =3D=3D FEC_RX_REJECT) + { + return (FEC_RX_REJECT); + } + FEC_PRINTF("len %d\n", (int)size); if (!s->regs[ENET_RDAR]) { @@ -1133,6 +1215,14 @@ static ssize_t imx_fec_receive(NetClientState *nc, c= onst uint8_t *buf, } else { s->regs[ENET_EIR] |=3D ENET_INT_RXB; } + + /* Update descriptor based on the "maf" flag. */ + if (maf =3D=3D FEC_RX_BROADCAST_ACCEPT) { + bd.flags |=3D ENET_BD_BC; /* The packet is destined for the "b= roadcast" address. */ + } else if (maf =3D=3D FEC_RX_MULTICAST_HASH_ACCEPT) { + bd.flags |=3D ENET_BD_MC; /* The packet is destined for a "mul= ticast" address. */ + } + imx_fec_write_bd(&bd, addr); /* Advance to the next descriptor. */ if ((bd.flags & ENET_BD_W) !=3D 0) { diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h index 7b3faa4..d38c8fe 100644 --- a/include/hw/net/imx_fec.h +++ b/include/hw/net/imx_fec.h @@ -275,4 +275,16 @@ typedef struct IMXFECState { uint8_t frame[ENET_MAX_FRAME_SIZE]; } IMXFECState; +/* FEC address filtering defines. */ +#define FEC_RX_REJECT (-1) +#define FEC_RX_PROMISCUOUS_ACCEPT (-2) +#define FEC_RX_BROADCAST_ACCEPT (-3) +#define FEC_RX_MULTICAST_HASH_ACCEPT (-4) +#define FEC_RX_UNICAST_HASH_ACCEPT (-5) +#define FEC_RX_UNICAST_ACCEPT (-6) + +/* FEC hash filtering defines.*/ +#define CRCPOLY_LE 0xedb88320 +#define FEC_HASH_BITS 6 /* #bits in hash */ + #endif -- 2.9.3 --_000_157494536599688572mentorcom_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable

 Adding support for MAC filtering in the FEC IP
 implementation. This addition ensures that the IP does NOT boot up in=
 promiscuous mode by default, and so the software only receives the de= sired
 packets(Unicast, Broadcast, Unicast / Multicast hashed) by default. T= he
 software running on-top of QEMU can also modify these settings and di= sable
 reception of broadcast frames or make the IP receive all packets (PRO= M mode).
 This patch greatly reduces the number of packets received by the soft= ware
 running on-top of the QEMU model. Tested with the armv7-a SABRE_LITE = machine.
 Testing included running a custom OS with IPv4 / IPv6 support. Hashin= g and
 filtering of packets is tested to work well. Skeleton taken from the<= br>  CADENCE_GEM IP and hash generation algorithm from the Linux Kernel.
Signed-off-by: Bilal Wasim <bilal_wasim@mentor.com>
---
 hw/net/imx_fec.c         | 92= +++++++++++++++= ;+++++++++++++++= ;+++++++++++++++= ;++-
 include/hw/net/imx_fec.h | 12 +++++++
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index bd99236..96c52dd 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -419,6 +419,80 @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, = dma_addr_t addr)
     dma_memory_write(&address_space_memory, addr, = bd, sizeof(*bd));
 }
 
+/*
+ * Calculate a FEC MAC Address hash index
+ */
+static unsigned calc_mac_hash(const uint8_t *mac, uint8_t mac_length)<= br> +{
+    uint32_t crc =3D -1;
+    int i;
+
+    while (mac_length --) {
+        crc ^=3D *mac++; +        for (i =3D 0; i < 8; i&#= 43;+) {
+            crc= =3D (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+        }
+    }
+
+    /* only upper 6 bits (FEC_HASH_BITS) are used
+     * which point to specific bit in the hash reg= isters
+     */
+    return ((crc >> (32 - FEC_HASH_BITS)) & 0= x3f);
+}
+
+/*
+ * fec_mac_address_filter:
+ * Accept or reject this destination address?
+ */
+static int fec_mac_address_filter(IMXFECState *s, const uint8_t *packe= t)
+{
+    const uint8_t broadcast_addr[] =3D { 0xFF, 0xFF, 0x= FF, 0xFF, 0xFF, 0xFF };
+    uint32_t addr1, addr2;
+    uint8_t  hash;
+
+    /* Promiscuous mode? */
+    if (s->regs[ENET_RCR] & ENET_RCR_PROM) {
+        return (FEC_RX_PROMISCUOUS_= ACCEPT); /* Accept all packets in promiscuous mode (even if bc_rej is set).= */
+    }
+
+    /* Broadcast packet? */
+    if (!memcmp(packet, broadcast_addr, 6)) {
+        /* Reject broadcast packets= ? */
+        if (s->regs[ENET_RCR] &a= mp; ENET_RCR_BC_REJ) {
+            ret= urn (FEC_RX_REJECT);
+        }
+        return (FEC_RX_BROADCAST_AC= CEPT); /* Accept packets from broadcast address. */
+    }
+
+    /* Accept packets -w- hash match? */
+    hash =3D calc_mac_hash(packet, 6);
+
+    /* Accept packets -w- multicast hash match? */
+    if ((packet[0] & 0x01) =3D=3D 0x01) {
+        /* See if the computed hash= matches a set bit in either GAUR / GALR register. */
+        if (((hash < 32) &&a= mp; (s->regs[ENET_GALR] & (1 << hash)))
+           &nbs= p;    || ((hash > 31) && (s->regs[ENET_GAUR] &= amp; (1 << (hash-32))))) {
+            ret= urn (FEC_RX_MULTICAST_HASH_ACCEPT); /* Accept multicast hash enabled addres= s. */
+        }
+    } else {
+        /* See if the computed hash= matches a set bit in either IAUR / IALR register. */
+        if (((hash < 32) &&a= mp; (s->regs[ENET_IALR] & (1 << hash)))
+           &nbs= p;    || ((hash > 31) && (s->regs[ENET_IAUR] &= amp; (1 << (hash-32))))) {
+            ret= urn (FEC_RX_UNICAST_HASH_ACCEPT); /* Accept multicast hash enabled address.= */
+        }
+    }
+
+    /* Match Unicast address. */
+    addr1  =3D g_htonl(s->regs[ENET_PALR]);
+    addr2  =3D g_htonl(s->regs[ENET_PAUR]);
+    if (!(memcmp(packet, (uint8_t *) &addr1, 4) || = memcmp(packet+4, (uint8_t *) &addr2, 2))) {
+        return (FEC_RX_UNICAST_ACCE= PT); /* Accept packet because it matches my unicast address. */
+    }
+
+    /* Return -1 because we do NOT support MAC address = filtering.. */
+    return (FEC_RX_REJECT);
+}
+
 static void imx_eth_update(IMXFECState *s)
 {
     /*
@@ -984,7 +1058,7 @@ static void imx_eth_write(void *opaque, hwaddr off= set, uint64_t value,
     case ENET_IALR:
     case ENET_GAUR:
     case ENET_GALR:
-        /* TODO: implement MAC hash fil= tering.  */
+        s->regs[index] |=3D valu= e;
         break;
     case ENET_TFWR:
         if (s->is_fec) {
@@ -1066,8 +1140,16 @@ static ssize_t imx_fec_receive(NetClientState *n= c, const uint8_t *buf,
     uint32_t buf_addr;
     uint8_t *crc_ptr;
     unsigned int buf_len;
+    int maf;
     size_t size =3D len;
 
+    /* Is this destination MAC address "for us&quo= t; ? */
+    maf =3D fec_mac_address_filter(s, buf);
+    if (maf =3D=3D FEC_RX_REJECT)
+    {
+        return (FEC_RX_REJECT);
+    }
+
     FEC_PRINTF("len %d\n", (int)size);
 
     if (!s->regs[ENET_RDAR]) {
@@ -1133,6 +1215,14 @@ static ssize_t imx_fec_receive(NetClientState *n= c, const uint8_t *buf,
         } else {
             s-= >regs[ENET_EIR] |=3D ENET_INT_RXB;
         }
+
+        /* Update descriptor based = on the "maf" flag. */
+        if (maf =3D=3D FEC_RX_BROAD= CAST_ACCEPT) {
+            bd.= flags |=3D ENET_BD_BC; /* The packet is destined for the "broadcast&qu= ot; address. */
+        } else if (maf =3D=3D FEC_R= X_MULTICAST_HASH_ACCEPT) {
+            bd.= flags |=3D ENET_BD_MC; /* The packet is destined for a "multicast"= ; address. */
+        }
+
         imx_fec_write_bd(&bd, = addr);
         /* Advance to the next des= criptor.  */
         if ((bd.flags & ENET_B= D_W) !=3D 0) {
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 7b3faa4..d38c8fe 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -275,4 +275,16 @@ typedef struct IMXFECState {
     uint8_t frame[ENET_MAX_FRAME_SIZE];
 } IMXFECState;
 
+/* FEC address filtering defines. */
+#define FEC_RX_REJECT        &= nbsp;          (-1)
+#define FEC_RX_PROMISCUOUS_ACCEPT       = (-2)
+#define FEC_RX_BROADCAST_ACCEPT      &nb= sp;  (-3)
+#define FEC_RX_MULTICAST_HASH_ACCEPT    (-4)
+#define FEC_RX_UNICAST_HASH_ACCEPT      (-5)<= br> +#define FEC_RX_UNICAST_ACCEPT       = ;    (-6)
+
+/* FEC hash filtering defines.*/
+#define CRCPOLY_LE        &nbs= p;             = 0xedb88320
+#define FEC_HASH_BITS        &= nbsp;           6 &n= bsp;  /* #bits in hash */
+
 #endif
--
2.9.3

--_000_157494536599688572mentorcom_--