diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index 23a3f2f5e5d8a..f4a08cf6eeca6 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -442,6 +442,7 @@ struct net_driver_s /* Remember the outgoing fragments waiting to be sent */ #ifdef CONFIG_NET_IPFRAG + uint8_t d_ipfrag_reassembled; /* Current packet is reassembled by IPFRAG */ struct iob_queue_s d_fragout; #endif diff --git a/net/ipforward/ipv6_forward.c b/net/ipforward/ipv6_forward.c index 18d7a941ad763..f8b53eaef2807 100644 --- a/net/ipforward/ipv6_forward.c +++ b/net/ipforward/ipv6_forward.c @@ -390,11 +390,17 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev, } else if (ret == PACKET_NOT_FORWARDED) { - /* Verify that the full packet will fit within the forwarding devices - * MTU. We provide no support for fragmenting forwarded packets. + /* Verify that the full packet will fit within the forwarding device's + * MTU. Normal IPv6 forwarding does not fragment oversized packets, + * but packets reassembled locally for NAT66/IPFILTER may be split + * again by the egress IPFRAG path. */ - if (NET_LL_HDRLEN(fwddev) + dev->d_len > NETDEV_PKTSIZE(fwddev)) + if (NET_LL_HDRLEN(fwddev) + dev->d_len > NETDEV_PKTSIZE(fwddev) +#ifdef CONFIG_NET_IPFRAG + && !dev->d_ipfrag_reassembled +#endif + ) { nwarn("WARNING: Packet > MTU... Dropping\n"); ret = -EFBIG; diff --git a/net/ipfrag/ipv6_frag.c b/net/ipfrag/ipv6_frag.c index 5ae861cd9a1a4..c27f731bb0214 100644 --- a/net/ipfrag/ipv6_frag.c +++ b/net/ipfrag/ipv6_frag.c @@ -469,6 +469,8 @@ int32_t ipv6_fragin(FAR struct net_driver_s *dev) FAR struct ip_fragsnode_s *node = NULL; FAR struct ip_fraglink_s *fraginfo = NULL; bool restartwdog; + uint8_t reassembled; + int32_t ret; if (dev->d_len != dev->d_iob->io_pktlen) { @@ -521,7 +523,12 @@ int32_t ipv6_fragin(FAR struct net_driver_s *dev) kmm_free(node); - return ipv6_input(dev); + reassembled = dev->d_ipfrag_reassembled; + dev->d_ipfrag_reassembled = true; + ret = ipv6_input(dev); + dev->d_ipfrag_reassembled = reassembled; + + return ret; } nxmutex_unlock(&g_ipfrag_lock); diff --git a/net/netdev/netdev_register.c b/net/netdev/netdev_register.c index e92e0d992b1f3..3bbe6f10bbbee 100644 --- a/net/netdev/netdev_register.c +++ b/net/netdev/netdev_register.c @@ -427,6 +427,10 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype) dev->d_polltype = 0; +#ifdef CONFIG_NET_IPFRAG + dev->d_ipfrag_reassembled = false; +#endif + nxrmutex_init(&dev->d_lock); /* We need exclusive access for the following operations */