Skip to content

Commit b027ba1

Browse files
committed
net/devif: Reorder ipv4_input packet classification.
Rework ipv4_input() packet classification to make the control flow clearer and keep the common local-unicast case first. This change: - handles local packets first - keeps broadcast/multicast handling in dedicated branches It also prevents broadcast and multicast packets from falling through into the unicast forward path. Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
1 parent eb4df01 commit b027ba1

1 file changed

Lines changed: 57 additions & 97 deletions

File tree

net/devif/ipv4_input.c

Lines changed: 57 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -311,140 +311,100 @@ static int ipv4_in(FAR struct net_driver_s *dev)
311311

312312
destipaddr = net_ip4addr_conv32(ipv4->destipaddr);
313313

314-
#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
315-
/* If IP broadcast support is configured, we check for a broadcast
316-
* UDP packet, which may be destined to us (even if there is no IP
317-
* address yet assigned to the device as is the case when we are
318-
* negotiating over DHCP for an address).
314+
/* Keep the common local-unicast case on the fast path, then classify
315+
* non-local packets as broadcast, multicast, or forwardable unicast.
319316
*/
320317

321-
if (ipv4->proto == IP_PROTO_UDP &&
322-
net_ipv4addr_cmp(destipaddr, INADDR_BROADCAST))
318+
if (net_ipv4addr_cmp(destipaddr, dev->d_ipaddr))
323319
{
324-
#ifdef CONFIG_NET_IPFORWARD_BROADCAST
325-
/* Forward broadcast packets */
326-
327-
ipv4_forward_broadcast(dev, ipv4);
328-
329-
/* Process the incoming packet if not forwardable */
330-
331-
if (dev->d_len > 0)
332-
#endif
320+
#ifdef CONFIG_NET_ICMP
321+
if (net_ipv4addr_cmp(dev->d_ipaddr, INADDR_ANY))
333322
{
334-
ret = udp_ipv4_input(dev);
323+
nwarn("WARNING: No IP address assigned\n");
324+
goto drop;
335325
}
336-
337-
goto done;
338-
}
339-
else
340326
#endif
341-
#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
342-
/* The address is not the broadcast address and we have been assigned a
343-
* address. So there is also the possibility that the destination address
344-
* is a sub-net broadcast address which we will need to handle just as for
345-
* the broadcast address above.
346-
*/
347-
348-
if (ipv4->proto == IP_PROTO_UDP &&
349-
net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask) &&
350-
net_ipv4addr_broadcast(destipaddr, dev->d_netmask))
327+
}
328+
else if (net_ipv4addr_cmp(destipaddr, INADDR_BROADCAST) ||
329+
(net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr,
330+
dev->d_netmask) &&
331+
net_ipv4addr_broadcast(destipaddr, dev->d_netmask)))
351332
{
352333
#ifdef CONFIG_NET_IPFORWARD_BROADCAST
353-
/* Forward broadcast packets */
354-
355334
ipv4_forward_broadcast(dev, ipv4);
356-
357-
/* Process the incoming packet if not forwardable */
358-
359-
if (dev->d_len > 0)
360335
#endif
336+
337+
#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
338+
if (ipv4->proto == IP_PROTO_UDP)
361339
{
362340
ret = udp_ipv4_input(dev);
341+
goto done;
363342
}
364-
365-
goto done;
366-
}
367-
else
368343
#endif
369-
/* Check if the packet is destined for our IP address. */
370344

371-
if (!net_ipv4addr_cmp(destipaddr, dev->d_ipaddr))
345+
#ifdef CONFIG_NET_STATISTICS
346+
g_netstats.ipv4.drop++;
347+
#endif
348+
goto drop;
349+
}
350+
else if (IN_MULTICAST(NTOHL(destipaddr)))
372351
{
373-
/* No.. This is not our IP address. Check for an IPv4 IGMP group
374-
* address
375-
*/
376-
377352
#ifdef CONFIG_NET_IGMP
378-
in_addr_t destip = net_ip4addr_conv32(ipv4->destipaddr);
379-
if (igmp_grpfind(dev, &destip) != NULL)
353+
if (igmp_grpfind(dev, &destipaddr) != NULL)
380354
{
381355
#ifdef CONFIG_NET_IPFORWARD_BROADCAST
382-
/* Forward multicast packets */
383-
384356
ipv4_forward_broadcast(dev, ipv4);
385-
386-
/* Return success if the packet was forwarded. */
387-
388-
if (dev->d_len == 0)
389-
{
390-
goto done;
391-
}
392357
#endif
393358
}
394359
else
395360
#endif
396361
{
397-
/* No.. The packet is not destined for us. */
398-
362+
#ifdef CONFIG_NET_STATISTICS
363+
g_netstats.ipv4.drop++;
364+
#endif
365+
goto drop;
366+
}
367+
}
368+
else
369+
{
399370
#ifdef CONFIG_NET_IPFORWARD
400-
/* Try to forward the packet */
371+
/* Try to forward the unicast packet. */
401372

402-
if (ipv4_forward(dev, ipv4) >= 0)
403-
{
404-
/* The packet was forwarded. Return success; d_len will
405-
* be set appropriately by the forwarding logic: Cleared
406-
* if the packet is forward via anoother device or non-
407-
* zero if it will be forwarded by the same device that
408-
* it was received on.
409-
*/
410-
411-
goto done;
412-
}
413-
else
373+
if (ipv4_forward(dev, ipv4) >= 0)
374+
{
375+
/* The packet was forwarded. Return success; d_len will
376+
* be set appropriately by the forwarding logic: Cleared
377+
* if the packet is forward via anoother device or non-
378+
* zero if it will be forwarded by the same device that
379+
* it was received on.
380+
*/
381+
382+
goto done;
383+
}
384+
else
414385
#endif
415386
#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_BINDTODEVICE)
416-
/* If the protocol specific socket option NET_BINDTODEVICE
417-
* is selected, then we must forward all UDP packets to the bound
418-
* socket.
419-
*/
387+
/* If the protocol specific socket option NET_BINDTODEVICE
388+
* is selected, then we must forward all UDP packets to the bound
389+
* socket.
390+
*/
420391

421-
if (ipv4->proto != IP_PROTO_UDP)
392+
if (ipv4->proto != IP_PROTO_UDP)
422393
#endif
423-
{
424-
/* Not destined for us and not forwardable... Drop the
425-
* packet.
426-
*/
394+
{
395+
/* Not destined for us and not forwardable... Drop the
396+
* packet.
397+
*/
427398

428-
ninfo("WARNING: Not destined for us; not forwardable... "
429-
"Dropping!\n");
399+
ninfo("WARNING: Not destined for us; not forwardable... "
400+
"Dropping!\n");
430401

431402
#ifdef CONFIG_NET_STATISTICS
432-
g_netstats.ipv4.drop++;
403+
g_netstats.ipv4.drop++;
433404
#endif
434-
goto drop;
435-
}
405+
goto drop;
436406
}
437407
}
438-
#ifdef CONFIG_NET_ICMP
439-
440-
/* In other cases, the device must be assigned a non-zero IP address. */
441-
442-
else if (net_ipv4addr_cmp(dev->d_ipaddr, INADDR_ANY))
443-
{
444-
nwarn("WARNING: No IP address assigned\n");
445-
goto drop;
446-
}
447-
#endif
448408

449409
#ifdef CONFIG_NET_IPV4_CHECKSUMS
450410
if (((dev->d_features & NETDEV_RX_CSUM) == 0)

0 commit comments

Comments
 (0)