From 9f8d418cd1691711a762dc980b2ea7f1a04fffa8 Mon Sep 17 00:00:00 2001 From: zhanghongyu Date: Sun, 23 Apr 2023 20:22:18 +0800 Subject: [PATCH] forward: copy iob when broadcast forward since iob offload, ipvx_dev_forward will remove d_iob, if there are multiple devices, d_iob will be NULL when dev_forward is entered second time. and the device that receives the packet cannot process the packet after forwarding it so the iob copy is added. Signed-off-by: zhanghongyu --- net/ipforward/ipv4_forward.c | 24 ++++++++++++++++++++++++ net/ipforward/ipv6_forward.c | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/net/ipforward/ipv4_forward.c b/net/ipforward/ipv4_forward.c index 7fc7e2d61b4..23a8da7418f 100644 --- a/net/ipforward/ipv4_forward.c +++ b/net/ipforward/ipv4_forward.c @@ -341,6 +341,7 @@ int ipv4_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg) { FAR struct net_driver_s *dev = (FAR struct net_driver_s *)arg; FAR struct ipv4_hdr_s *ipv4; + FAR struct iob_s *iob; int ret; DEBUGASSERT(fwddev != NULL); @@ -360,6 +361,24 @@ int ipv4_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg) if (fwddev != dev) { + /* Backup the forward IP packet */ + + iob = iob_tryalloc(true); + if (iob == NULL) + { + nerr("ERROR: iob alloc failed when forward broadcast\n"); + return -ENOMEM; + } + + iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE); + ret = iob_clone_partial(dev->d_iob, dev->d_iob->io_pktlen, 0, + iob, 0, true, false); + if (ret < 0) + { + iob_free_chain(iob); + return ret; + } + /* Recover the pointer to the IPv4 header in the receiving device's * d_buf. */ @@ -371,9 +390,14 @@ int ipv4_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg) ret = ipv4_dev_forward(dev, fwddev, ipv4); if (ret < 0) { + iob_free_chain(iob); nwarn("WARNING: ipv4_dev_forward failed: %d\n", ret); return ret; } + + /* Restore device iob with backup iob */ + + netdev_iob_replace(dev, iob); } return OK; diff --git a/net/ipforward/ipv6_forward.c b/net/ipforward/ipv6_forward.c index 0787a7593ea..f60988da495 100644 --- a/net/ipforward/ipv6_forward.c +++ b/net/ipforward/ipv6_forward.c @@ -468,6 +468,7 @@ int ipv6_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg) { FAR struct net_driver_s *dev = (FAR struct net_driver_s *)arg; FAR struct ipv6_hdr_s *ipv6; + FAR struct iob_s *iob; int ret; DEBUGASSERT(fwddev != NULL); @@ -487,6 +488,24 @@ int ipv6_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg) if (fwddev != dev) { + /* Backup the forward IP packet */ + + iob = iob_tryalloc(true); + if (iob == NULL) + { + nerr("ERROR: iob alloc failed when forward broadcast\n"); + return -ENOMEM; + } + + iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE); + ret = iob_clone_partial(dev->d_iob, dev->d_iob->io_pktlen, 0, + iob, 0, true, false); + if (ret < 0) + { + iob_free_chain(iob); + return ret; + } + /* Recover the pointer to the IPv6 header in the receiving device's * d_buf. */ @@ -498,9 +517,14 @@ int ipv6_forward_callback(FAR struct net_driver_s *fwddev, FAR void *arg) ret = ipv6_dev_forward(dev, fwddev, ipv6); if (ret < 0) { + iob_free_chain(iob); nwarn("WARNING: ipv6_dev_forward failed: %d\n", ret); return ret; } + + /* Restore device iob with backup iob */ + + netdev_iob_replace(dev, iob); } return OK;