Replying to UDP broadcast packet

Hi,

I am using FreeRTOS with FreeRTOS-TCP/IP stack on my TI ARM Cortex M4 controller i.e. TM4C129ENCPDT. I have a project that is communicating via UDP protocol and is doing good.
My firmware can communicate to a remotely connected client and serve the client request.
For example if my remote client send a UDP packet to switch on LED it will switch on and reply to the client as well.

However we need some change to it such that we want a remotely connected device send a broadcast UDP packet and then the controller extract the command from the broadcast packet and performs the requested task.

As I said my controller works fine if I send a direct udp packet to the controller IP address. However it will not reply if I send a broadcast udp packet.

Here is my code;

void UDPCommunicationTask( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )
{
	xTaskCreate( prvUDPCommandInterpreterTask, "UDP COMM", usStackSize, ( void * ) ulPort, uxPriority, NULL );
}
/*-----------------------------------------------------------*/

void prvUDPCommandInterpreterTask( void *pvParameters )
{
int32_t lBytes, lByte;
char cRxedChar, cInputIndex = 0;
char datasize;
static unsigned char cOutputString[ cmdMAX_OUTPUT_SIZE ], cLocalBuffer[ cmdSOCKET_INPUT_BUFFER_SIZE ];
static char cLastInputString[ cmdMAX_INPUT_SIZE ], cInputString[ cmdMAX_INPUT_SIZE ];
BaseType_t xMoreDataToFollow;
struct freertos_sockaddr xClient;


	memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );

	/* Attempt to open the socket.  The port number is passed in the task
	parameter.  The strange casting is to remove compiler warnings on 32-bit
	machines. */
	xSocket = prvOpenUDPServerSocket( ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL );
	uint8_t counter1,counter2,counter3,counter4;
	counter1 = 0;
	counter2 = 0;
	counter3 = 0;
	counter4 = 0;
	if( xSocket != FREERTOS_INVALID_SOCKET )
	{
		for( ;; )
		{
			/* Wait for incoming data on the opened socket. */
			lBytes = FreeRTOS_recvfrom( xSocket, ( void * ) cLocalBuffer, sizeof( cLocalBuffer ), 0, &xClient, &xClientAddressLength );
			if (lBytes > 0)
			{
			    LED0_HIGH;
                
                udp_hex_mode = 1;
                if(udp_hex_mode == 1)
                {
                    memset( cOutputString, 0x00, cmdMAX_OUTPUT_SIZE );                   
                    hex_mode_cmd_interpretor(cLocalBuffer, cOutputString);
                    FreeRTOS_sendto( xSocket, cOutputString,  strlen( ( const char * ) cOutputString ), 0, &xClient, xClientAddressLength );

                }
		        LED0_LOW;
			}

Here is how I create the socket;

static Socket_t prvOpenUDPServerSocket( uint16_t usPort )
{
struct freertos_sockaddr xServer;
Socket_t xServerSocket = FREERTOS_INVALID_SOCKET;
TickType_t xSendTimeOut = 0;

	xServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
	if( xServerSocket != FREERTOS_INVALID_SOCKET)
	{
		/* Set to non-blocking sends with a timeout of zero as the socket might
		also be used for debug prints which should not block. */
		FreeRTOS_setsockopt( xServerSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );

		/* Zero out the server structure. */
		memset( ( void * ) &xServer, 0x00, sizeof( xServer ) );

		/* Set family and port. */
		xServer.sin_port = FreeRTOS_htons( usPort );

		/* Bind the address to the socket. */
		if( FreeRTOS_bind( xServerSocket, &xServer, sizeof( xServer ) ) == -1 )
		{
			FreeRTOS_closesocket( xServerSocket );
			xServerSocket = FREERTOS_INVALID_SOCKET;
		}
	}

	return xServerSocket;
}

Thank you all

What is between the two devices, networking wise? If there are switches and routers the receiver may not receive the broadcast packet. If you use Wireshark on the network to which the receiver is connected, do you see the broadcast packet?

Hi Richard,

There are number of switches but no routers. Also I have tried a direct connection to my controller without any switch. The controller works excellent if I send a packet directly to its IP address however it will not reply to a broadcast packet.
The controller also replies to a ping request.

I just tried at my home network such that the controller is directly connected to the same router where my laptop is connected.
My laptop is connected to the router via wifi while the controller is connected directly via RJ45 cable.

I can talk to my controller if I directly send the UDP packet to the controller IP address however if I send a broadcast message, the controller will not reply.

Thank you

Hello Iftikhar, I looked at your message earlier, but I didn’t have a solution.
Often people hear: “for me is works well”, and then we have to find out what is the difference in our setup’s.

You are not showing the code that sends out the UDP broadcasts, can you show that as well?

You possibly know that there are 2 types of IPv4 broadcast addresses:

  1. Network specific address like e.g. 192.168.1.255
  2. A broad broadcast, wit the address 255.255.255.255

In both cases, the target MAC address should be ff:ff:ff:ff:ff:ff.

The first address type is more specific and it is preferable to use that address.

You are using a TI ARM Cortex M4 controller (M4C129ENCPDT). I do not know the port that you are using for FreeRTOS+TCP. You should check if broadcasts are accepted by you EMAC.

If you want your applications to work in any environment, you might also think of using multi-cast. That protocol is accepted by more routers and switches.

But please keep on posting, I want to know how it goes.

1 Like

Hi Hein,

Thanks for your message. I am using the following code to send broadcast message. My controller IP is 192.168.0.31. For broad cast I am simply changing my controller IP address with broadcast address which will be 192.168.0.255. I have also tried 255.255.255.255 with no luck. However, I dont have any field to specify the MAC address.
Here is my C code that I works well to talk to the controller if I use controller IP instead the broadcast IP.

#define SERVER_IP "192.168.0.255" //Broad cast address
//#define SERVER_IP "192.168.0.31" //Controller address

//NOTE: Use 7891 as a Port number when communicating with Local Server i.e. udp_server.c because Linux is blocking Port 5002
#define PORT 5002 


#define BUFFERLEN 5

void delay(float number_of_seconds) 
{ 
    // Converting time into milli_seconds 
    int milli_seconds = 5000 * number_of_seconds; 
  
    // Storing start time 
    clock_t start_time = clock(); 
  
    // looping till required time is not achieved 
    while (clock() < start_time + milli_seconds) 
        ; 
} 

int main()
{
  int clientSocket, portNum, nBytes;
  unsigned char buffer[BUFFERLEN];
  unsigned char buffer2[BUFFERLEN];
  char *ptr;
  ptr = &buffer2[0];
  unsigned long long int counter;
  char i;
  int broadcastPermission;
  struct sockaddr_in serverAddr;
  socklen_t addr_size;

  /*Create UDP socket*/
  clientSocket = socket(PF_INET, SOCK_DGRAM, 0);

  broadcastPermission = 1;
  setsockopt(clientSocket, SOL_SOCKET, SO_BROADCAST, (void *) 
  &broadcastPermission,sizeof(broadcastPermission));
  
  /*Configure settings in address struct*/
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(PORT);
  serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  /*Initialize size variable to be used later on*/
  addr_size = sizeof serverAddr;
  memset(buffer, 0 , BUFFERLEN);

  for(i=0;i<BUFFERLEN;i++) buffer[i] = i+1; 
  buffer[0] = 0x80; //Read Request to controller
  buffer[1] = 0x12; //Read ADC Buffer

  nBytes = sizeof(buffer);
  

  while(1)
  {
    counter += 1;    
    memset(buffer2, 0 , BUFFERLEN);    
    
    /*Send message to server*/
    sendto(clientSocket,buffer,BUFFERLEN,0,(struct sockaddr *)&serverAddr,addr_size);
    /*Receive message from server*/
    nBytes = recvfrom(clientSocket,buffer2,BUFFERLEN,0,NULL, NULL);   
    
    printf("\n\r%llu: Received %d bytes from Server:", counter, nBytes);
    for (i=0;i<nBytes;i++) printf("%X",*(ptr+i));
    delay(0.1);

  }

  return 0; 
}

You might have noticed I have enabled broadcast i.e. setsockopt(clientSocket, SOL_SOCKET, SO_BROADCAST, (void *) &broadcastPermission,sizeof(broadcastPermission)); and all I am doing is just replacing the define SERVER_IP to the broadcast address.

Thanks

This does not look like you are using the FreeRTOS TCP/IP stack as per your original post - I guess you are using lwIP?

This is not the controller code this is the C code on my laptop that I am using to talk to the controller.
The controller FreeRTOS-Plus stack code is shown in the first post.

I also tried a python script, the controller will reply to requests specifically sent to its IP and will not reply to broadcast packets.

#Controller IP = 192.168.0.31
#Broadcast IP = 192.168.0.255
UDP_IP = "192.168.0.255" #BroadCast IP
UDP_PORT = 5002 
bufferSize  = 1024

read_cmd = 0x80
write_cmd = 0x00
read_mac = 0x12


delay = 2.0
timeout = 3.0

msgFromServer       = 8012 #\h(8012) = Read Mac addr
bytesToSend         = str.encode("8012")
# Create a datagram socket
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
UDPServerSocket.settimeout(timeout)

packet = []

def Send_message():
    packet.clear()        
    packet.append(pack(">BB", read_cmd,read_mac))
    UDPServerSocket.sendto(b''.join(packet), (UDP_IP, UDP_PORT)) 
    time.sleep(0.1)
    try:
        data, addr = UDPServerSocket.recvfrom(bufferSize) # buffer size is 1024 bytes 
        print("IP Address: ", addr)
        print(data)
    except Exception as e:
        print(e)

def Run_test():    
    while True:
        print("###############")
        Send_message()
        time.sleep(0.5)
 
Run_test()
print("Script reached end")

Yep - see that now :smile:

So you are sending a UDP broadcast from a host to a TI device that is running FreeRTOS+TCP?
If the device is not receiving these UDP messages, I would look at the setup of you EMAC, and look for an option that allows broadcasts packets. i suspect that the EMAC blocks them.

1 Like

Hi Hein,

I have attached the driver files in zipped form. Could you please give it a quick look if not kindly give me some guideline what to look for. I quickly searched for “broadcast” word in the files and did not find anything.
Please find attached zipped file.

Thank you for your time.
Tiva.zip (23 KB)

Hein,

I see the following line of code in NetworkInterface.c file where the author is saying “We receive all broadcast packets along with those addressed specifically for us.” As can be seen MAP_EMACFrameFilterSet() is not set to filter broadcast or multicast.

    /**
     * Set MAC filtering options.  We receive all broadcast and mui32ticast
     * packets along with those addressed specifically for us.
     */
    MAP_EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_HASH_AND_PERFECT |
#if ipconfigUSE_IGMP == 1
            EMAC_FRMFILTER_PASS_MULTICAST
#else
            0
#endif
                       ));

Do you think, it could be my router filtering the broadcast message I am sending to the controller(the FreeRTOS TI device)?
Do you think I should connect the controller(the FreeRTOS TI device) directly to my laptop ?

EMAC_FRMFILTER_PASS_MULTICAST looks very much like the option that you need, so you might want to define ipconfigUSE_IGMP.
And at the host side (Windows/Linux/ iOS) you will need to set the socket option that allows you to send broadcast messages.

1 Like

Here are the different defines for the MAP_EMACFrameFilterSet() function.
My feeling is since we are not passing EMAC_FRMFILTER_BROADCAST so most probably it is already passing the broadcast packets ?

//*****************************************************************************
//
// These values may be passed to EMACFrameFilterSet() in the ui32FilterOpts
// parameter, and are returned by EMACFrameFilterGet().
//
//*****************************************************************************
#define EMAC_FRMFILTER_RX_ALL             0x80000000
#define EMAC_FRMFILTER_VLAN               0x00010000
#define EMAC_FRMFILTER_HASH_AND_PERFECT   0x00000400
#define EMAC_FRMFILTER_SADDR              0x00000200
#define EMAC_FRMFILTER_INV_SADDR          0x00000100
#define EMAC_FRMFILTER_PASS_MASK          (0x03 << 6)
#define EMAC_FRMFILTER_PASS_NO_CTRL       (0x00 << 6)
#define EMAC_FRMFILTER_PASS_NO_PAUSE      (0x01 << 6)
#define EMAC_FRMFILTER_PASS_ALL_CTRL      (0x02 << 6)
#define EMAC_FRMFILTER_PASS_ADDR_CTRL     (0x03 << 6)
#define EMAC_FRMFILTER_BROADCAST          0x00000020
#define EMAC_FRMFILTER_PASS_MULTICAST     0x00000010
#define EMAC_FRMFILTER_INV_DADDR          0x00000008
#define EMAC_FRMFILTER_HASH_MULTICAST     0x00000004
#define EMAC_FRMFILTER_HASH_UNICAST       0x00000002
#define EMAC_FRMFILTER_PROMISCUOUS        0x00000001

You will see the same options in all ethernet peripherals:

BROADCAST: allow UDP broadcast addresses to be received
PASS_MULTICAST : allow Multicast packets
INV_DADDR : I don’t know…
HASH_MULTICAST : define which multicast addresses should be allow by setting a hash table
HASH_UNICAST : Direct addressing with a normal IP address
PROMISCUOUS : to write a network monitor, receive everything.

You can try PROMISCUOUS to see what would be received if all doors are open.

Hi Hein,

I was finally able to diagnose the issue. As you pointed above, my home router as well as my office setup was blocking my broadcast packets reach out to the device.

Also to complicate the issue, instead of using my own C and Pthon app, I started using a terminal software unfortunately it was outdated and it would show as if it has sent out the UDP broadcast packet.

After updating the terminal software and connecting the device directly to my laptop solved the problem.

I thank you for your help and time.

You have a wonderful day.

I am using UDP for logging in many of my projects. The logging is being sent to 192.168.2.255, so I can see it on any laptop.

So at the side of FreeRTOS+TCP there shouldn’t be any problem.

Network managers do not like broadcasting: it can be “dangerous” and also it can take a way a lot of bandwidth.

In stead of broadcasting we should have a look at multicasting. Multicasting is more specific and chances odf passing through a router are bigger than a simple broadcast.

1 Like

Hi,

Actually the scenario is a bit different in our project as we will have 100 devices or more on same network and we want to query them for data using a single broadcast packet rather than sending 100 individual packets.

Thanks

And can you make sure that not all devices respond at exactly the same time, once the broadcast has been sent? If not, you’d see loads of collisions, no?