问题
I have a client/server LWIP program that works correctly with unicast communication however I want to use multicast features so I used IGMP library did the following:
1- in lwipopts.h:
#define LWIP_IGMP 1 //allowed IGMP
2- in ethernetif.c:
netif->flags |= NETIF_FLAG_IGMP; //in low_level_init function
3-in my source file (for both client and server projects):
implemented the following code:
void recCallBack (void)
{
printf("connected"); //BREAK_POINT
}
static void UDP_Multicast_init(void *arg)
{
struct ip4_addr ipgroup, localIP;
struct udp_pcb *g_udppcb;
char msg[] = "hello";
struct pbuf* p;
p = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg),PBUF_RAM);
memcpy (p->payload, msg, sizeof(msg));
IP4_ADDR(&ipgroup, 224, 0, 1, 129 ); //Multicast IP address.
IP4_ADDR(&localIP, 192, 168, 1, 2); //Interface IP address
#if LWIP_IGMP
s8_t iret = igmp_joingroup((ip4_addr_t *)(&localIP),(ip4_addr_t *)(&ipgroup));
#endif
g_udppcb =( struct udp_pcb*) udp_new();
udp_bind(g_udppcb, &localIP, 319); //to allow receiving multicast
udp_recv(g_udppcb, recCallBack,NULL); //recCallBack is the callback function that will be called every time you receive multicast
udp_sendto(g_udppcb,p,&ipgroup,319); //send a multicast packet
}
void telnet_shell_init(void)
{
sys_thread_new("TELNET", UDP_Multicast_init, NULL, DEFAULT_THREAD_STACKSIZE, osPriorityAboveNormal);
}
The result: all the mentioned code steps are executed successfully in both projects (client and server) but I'm not receiving any multicast messages (or maybe not even sending)!
I added a "BREAK_POINT" in the callback function but I never reached it. Can you help me? either by suggesting a solution or at least a way to track the problem... I'm using STM32F746 Nucleo board with LWIP, FreeRTOS libraries generated by cubeMX.
Thank you.
<<< Edit >>> After more investigations I found out that the problem is in the reception of the multi-cast frames which should be enabled during the MAC initialization. Although the following code did not work for me, it was helpful to others so here it is:
4- in the stm32f7xx_hal_eth.c (ETH_MACDMAConfig function):
macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_ENABLE;
macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE;
回答1:
My multicast testing was finished successfully with STM32F407 and CubeMX version 4.25.0.
The Kalkhouri's question was helpful.
I share my working code here.
Following code must be included same as Kalkhouri did.
#define LWIP_IGMP 1
macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE;
netif->flags |= NETIF_FLAG_IGMP;
I used socket API of LWIP rather than low level function.
#include "lwip/opt.h"
#include "lwip/dhcp.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "lwip/sockets.h"
int Bind(int sock, uint16_t port)
{
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &serv_addr, (socklen_t)sizeof(serv_addr)) < 0)
return -1;
return 0;
}
int JoinGroup(int sock, const char* join_ip, const char* local_ip)
{
ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(join_ip);
mreq.imr_interface.s_addr = inet_addr(local_ip);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0)
return -1;
return 0;
}
void MulticastStart()
{
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
Bind(sock, 5000);
JoinGroup(sock, "224.1.1.1", "192.168.10.123");
// Now you can do recvfrom() in RTOS task.
........
}
Note: You should use this code under the RTOS support.
来源:https://stackoverflow.com/questions/50438577/implementing-lwip-multicast-on-stm32f7-freertos