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 <zhanghongyu@xiaomi.com>
This commit is contained in:
parent
bd122915f0
commit
9f8d418cd1
2 changed files with 48 additions and 0 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue