Browse Source

Merge pull request #1119 from aozima/ipv_dev

[lwIP] update ipv6 support.
Bernard Xiong 7 years ago
parent
commit
89944a7837

+ 122 - 1
bsp/stm32f107/drivers/stm32_eth.c

@@ -3027,6 +3027,9 @@ struct rt_stm32_eth
 
 
     /* interface address info. */
     /* interface address info. */
     rt_uint8_t  dev_addr[MAX_ADDR_LEN];			/* hw address	*/
     rt_uint8_t  dev_addr[MAX_ADDR_LEN];			/* hw address	*/
+
+	uint32_t ETH_HashTableHigh;
+	uint32_t ETH_HashTableLow;
 };
 };
 static struct rt_stm32_eth stm32_eth_device;
 static struct rt_stm32_eth stm32_eth_device;
 static struct rt_semaphore tx_buf_free;
 static struct rt_semaphore tx_buf_free;
@@ -3082,10 +3085,118 @@ void ETH_IRQHandler(void)
 
 
 /* RT-Thread Device Interface */
 /* RT-Thread Device Interface */
 
 
+#if (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD)
+/* polynomial: 0x04C11DB7 */
+static uint32_t ethcrc(const uint8_t *data, size_t length)
+{
+	uint32_t crc = 0xffffffff;
+	size_t i;
+	int j;
+
+	for (i = 0; i < length; i++)
+	{
+		for (j = 0; j < 8; j++)
+		{
+			if (((crc >> 31) ^ (data[i] >> j)) & 0x01)
+			{
+				/* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */
+				crc = (crc << 1) ^ 0x04C11DB7;
+			}
+			else
+			{
+				crc = crc << 1;
+			}
+		}
+	}
+
+	return ~crc;
+}
+
+#define HASH_BITS	6		/* #bits in hash */
+static void register_multicast_address(struct rt_stm32_eth *stm32_eth, const uint8_t *mac)
+{
+	uint32_t crc;
+	uint8_t hash;
+
+	/* calculate crc32 value of mac address */
+	crc = ethcrc(mac, 6);
+
+	/* only upper 6 bits (HASH_BITS) are used
+	* which point to specific bit in he hash registers
+	*/
+	hash = (crc >> 26) & 0x3F;
+	//rt_kprintf("register_multicast_address crc: %08X hash: %02X\n", crc, hash);
+
+	if (hash > 31)
+	{
+		stm32_eth->ETH_HashTableHigh |= 1 << (hash - 32);
+		ETH->MACHTHR = stm32_eth->ETH_HashTableHigh;
+	}
+	else
+	{
+		stm32_eth->ETH_HashTableLow |= 1 << hash;
+		ETH->MACHTLR = stm32_eth->ETH_HashTableLow;
+	}
+}
+#endif /* (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD) */
+
+#if LWIP_IPV4 && LWIP_IGMP
+static err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, u8_t action )
+{
+    uint8_t mac[6];
+	const uint8_t *p = (const uint8_t *)ip4_addr;
+    struct rt_stm32_eth *stm32_eth = (struct rt_stm32_eth *)netif->state;
+
+	mac[0] = 0x01;
+	mac[1] = 0x00;
+	mac[2] = 0x5E;
+	mac[3] = *(p+1) & 0x7F;
+	mac[4] = *(p+2);
+	mac[5] = *(p+3);
+
+	register_multicast_address(stm32_eth, mac);
+
+	if(1)
+	{
+		rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip4addr_ntoa(ip4_addr));
+		rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	}
+
+	return 0;
+}
+#endif /* LWIP_IPV4 && LWIP_IGMP */
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+static err_t mld_mac_filter( struct netif *netif, const ip6_addr_t *ip6_addr, u8_t action )
+{
+    uint8_t mac[6];
+	const uint8_t *p = (const uint8_t *)&ip6_addr->addr[3];
+    struct rt_stm32_eth *stm32_eth = (struct rt_stm32_eth *)netif->state;
+
+	mac[0] = 0x33;
+	mac[1] = 0x33;
+	mac[2] = *(p+0);
+	mac[3] = *(p+1);
+	mac[4] = *(p+2);
+	mac[5] = *(p+3);
+
+	register_multicast_address(stm32_eth, mac);
+
+	if(1)
+	{
+		rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip6addr_ntoa(ip6_addr));
+		rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	}
+
+	return 0;
+}
+#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
+
 /* initialize the interface */
 /* initialize the interface */
 static rt_err_t rt_stm32_eth_init(rt_device_t dev)
 static rt_err_t rt_stm32_eth_init(rt_device_t dev)
 {
 {
     vu32 Value = 0;
     vu32 Value = 0;
+    struct rt_stm32_eth * stm32_eth = (struct rt_stm32_eth *)dev;
 
 
     /* Reset ETHERNET on AHB Bus */
     /* Reset ETHERNET on AHB Bus */
     ETH_DeInit();
     ETH_DeInit();
@@ -3112,7 +3223,9 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
     ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable;
     ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable;
     ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable;
     ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable;
     ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
     ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
-    ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
+    ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_HashTable;
+    ETH_InitStructure.ETH_HashTableHigh = stm32_eth->ETH_HashTableHigh;
+    ETH_InitStructure.ETH_HashTableLow  = stm32_eth->ETH_HashTableLow;
     ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
     ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
 #if CHECKSUM_BY_HARDWARE
 #if CHECKSUM_BY_HARDWARE
     ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
     ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
@@ -3153,6 +3266,14 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
     /* Enable MAC and DMA transmission and reception */
     /* Enable MAC and DMA transmission and reception */
     ETH_Start();
     ETH_Start();
 
 
+#if LWIP_IPV4 && LWIP_IGMP
+    netif_set_igmp_mac_filter(stm32_eth->parent.netif, igmp_mac_filter);
+#endif /* LWIP_IPV4 && LWIP_IGMP */
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+    netif_set_mld_mac_filter(stm32_eth->parent.netif, mld_mac_filter);
+#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
+
     return RT_EOK;
     return RT_EOK;
 }
 }
 
 

+ 121 - 1
bsp/stm32f40x/drivers/stm32f4xx_eth.c

@@ -3274,6 +3274,9 @@ struct rt_stm32_eth
 
 
 	uint32_t    ETH_Speed; /*!< @ref ETH_Speed */
 	uint32_t    ETH_Speed; /*!< @ref ETH_Speed */
 	uint32_t    ETH_Mode;  /*!< @ref ETH_Duplex_Mode */
 	uint32_t    ETH_Mode;  /*!< @ref ETH_Duplex_Mode */
+
+	uint32_t ETH_HashTableHigh;
+	uint32_t ETH_HashTableLow;
 };
 };
 static struct rt_stm32_eth stm32_eth_device;
 static struct rt_stm32_eth stm32_eth_device;
 static struct rt_semaphore tx_wait;
 static struct rt_semaphore tx_wait;
@@ -3408,6 +3411,113 @@ void ETH_IRQHandler(void)
 #include <lwip/icmp.h>
 #include <lwip/icmp.h>
 #include "lwipopts.h"
 #include "lwipopts.h"
 
 
+#if (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD)
+/* polynomial: 0x04C11DB7 */
+static uint32_t ethcrc(const uint8_t *data, size_t length)
+{
+	uint32_t crc = 0xffffffff;
+	size_t i;
+	int j;
+
+	for (i = 0; i < length; i++)
+	{
+		for (j = 0; j < 8; j++)
+		{
+			if (((crc >> 31) ^ (data[i] >> j)) & 0x01)
+			{
+				/* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */
+				crc = (crc << 1) ^ 0x04C11DB7;
+			}
+			else
+			{
+				crc = crc << 1;
+			}
+		}
+	}
+
+	return ~crc;
+}
+
+#define HASH_BITS	6		/* #bits in hash */
+static void register_multicast_address(struct rt_stm32_eth *stm32_eth, const uint8_t *mac)
+{
+	uint32_t crc;
+	uint8_t hash;
+
+	/* calculate crc32 value of mac address */
+	crc = ethcrc(mac, 6);
+
+	/* only upper 6 bits (HASH_BITS) are used
+	* which point to specific bit in he hash registers
+	*/
+	hash = (crc >> 26) & 0x3F;
+	//rt_kprintf("register_multicast_address crc: %08X hash: %02X\n", crc, hash);
+
+	if (hash > 31)
+	{
+		stm32_eth->ETH_HashTableHigh |= 1 << (hash - 32);
+		ETH->MACHTHR = stm32_eth->ETH_HashTableHigh;
+	}
+	else
+	{
+		stm32_eth->ETH_HashTableLow |= 1 << hash;
+		ETH->MACHTLR = stm32_eth->ETH_HashTableLow;
+	}
+}
+#endif /* (LWIP_IPV4 && LWIP_IGMP) || (LWIP_IPV6 && LWIP_IPV6_MLD) */
+
+#if LWIP_IPV4 && LWIP_IGMP
+static err_t igmp_mac_filter( struct netif *netif, const ip4_addr_t *ip4_addr, u8_t action )
+{
+    uint8_t mac[6];
+	const uint8_t *p = (const uint8_t *)ip4_addr;
+    struct rt_stm32_eth *stm32_eth = (struct rt_stm32_eth *)netif->state;
+
+	mac[0] = 0x01;
+	mac[1] = 0x00;
+	mac[2] = 0x5E;
+	mac[3] = *(p+1) & 0x7F;
+	mac[4] = *(p+2);
+	mac[5] = *(p+3);
+
+	register_multicast_address(stm32_eth, mac);
+
+	if(1)
+	{
+		rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip4addr_ntoa(ip4_addr));
+		rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	}
+
+	return 0;
+}
+#endif /* LWIP_IPV4 && LWIP_IGMP */
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+static err_t mld_mac_filter( struct netif *netif, const ip6_addr_t *ip6_addr, u8_t action )
+{
+    uint8_t mac[6];
+	const uint8_t *p = (const uint8_t *)&ip6_addr->addr[3];
+    struct rt_stm32_eth *stm32_eth = (struct rt_stm32_eth *)netif->state;
+
+	mac[0] = 0x33;
+	mac[1] = 0x33;
+	mac[2] = *(p+0);
+	mac[3] = *(p+1);
+	mac[4] = *(p+2);
+	mac[5] = *(p+3);
+
+	register_multicast_address(stm32_eth, mac);
+
+	if(1)
+	{
+		rt_kprintf("%s %s %s ", __FUNCTION__, (action==NETIF_ADD_MAC_FILTER)?"add":"del", ip6addr_ntoa(ip6_addr));
+		rt_kprintf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	}
+
+	return 0;
+}
+#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
+
 /* initialize the interface */
 /* initialize the interface */
 static rt_err_t rt_stm32_eth_init(rt_device_t dev)
 static rt_err_t rt_stm32_eth_init(rt_device_t dev)
 {
 {
@@ -3445,7 +3555,9 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
     ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
     ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
     ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
     ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
     ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
     ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
-    ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
+    ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_HashTable;
+    ETH_InitStructure.ETH_HashTableHigh = stm32_eth->ETH_HashTableHigh;
+    ETH_InitStructure.ETH_HashTableLow  = stm32_eth->ETH_HashTableLow;
     ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
     ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
 #ifdef CHECKSUM_BY_HARDWARE
 #ifdef CHECKSUM_BY_HARDWARE
     ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
     ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
@@ -3486,6 +3598,14 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
     /* Enable MAC and DMA transmission and reception */
     /* Enable MAC and DMA transmission and reception */
     ETH_Start();
     ETH_Start();
 
 
+#if LWIP_IPV4 && LWIP_IGMP
+    netif_set_igmp_mac_filter(stm32_eth->parent.netif, igmp_mac_filter);
+#endif /* LWIP_IPV4 && LWIP_IGMP */
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+    netif_set_mld_mac_filter(stm32_eth->parent.netif, mld_mac_filter);
+#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
+
     return RT_EOK;
     return RT_EOK;
 }
 }
 
 

+ 1 - 1
components/net/Kconfig

@@ -27,7 +27,7 @@ config RT_USING_LWIP
 
 
         config RT_LWIP_IGMP
         config RT_LWIP_IGMP
             bool "IGMP protocol"
             bool "IGMP protocol"
-            default n
+            default y
 
 
         config RT_LWIP_ICMP
         config RT_LWIP_ICMP
             bool "ICMP protocol"
             bool "ICMP protocol"

+ 20 - 4
components/net/lwip-2.0.2/src/netif/ethernetif.c

@@ -173,10 +173,26 @@ static err_t eth_netif_device_init(struct netif *netif)
         netif->flags = (ethif->flags & 0xff);
         netif->flags = (ethif->flags & 0xff);
 
 
 #if LWIP_IPV6
 #if LWIP_IPV6
-		netif->output_ip6 = ethip6_output;
-		netif->ip6_autoconfig_enabled = 1;
-		netif_create_ip6_linklocal_address(netif, 1);
-		netif->flags |= NETIF_FLAG_MLD6;
+        netif->output_ip6 = ethip6_output;
+        netif->ip6_autoconfig_enabled = 1;
+        netif_create_ip6_linklocal_address(netif, 1);
+
+#if LWIP_IPV6_MLD
+        netif->flags |= NETIF_FLAG_MLD6;
+
+        /*
+        * For hardware/netifs that implement MAC filtering.
+        * All-nodes link-local is handled by default, so we must let the hardware know
+        * to allow multicast packets in.
+        * Should set mld_mac_filter previously. */
+        if (netif->mld_mac_filter != NULL)
+        {
+            ip6_addr_t ip6_allnodes_ll;
+            ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
+            netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
+        }
+#endif /* LWIP_IPV6_MLD */
+
 #endif /* LWIP_IPV6 */
 #endif /* LWIP_IPV6 */
 
 
         /* set default netif */
         /* set default netif */