IP forwarding design simplication; might save some memory. Also fix some compile issues introduce with last commit in MULTINIC configration.

This commit is contained in:
Gregory Nutt
2017-07-06 16:19:10 -06:00
parent 6c5e0d870c
commit b5d7187df6
10 changed files with 127 additions and 136 deletions
+8 -16
View File
@@ -75,26 +75,18 @@ void devif_forward(FAR struct forward_s *fwd)
unsigned int offset;
int ret;
DEBUGASSERT(fwd != NULL && fwd->f_dev != NULL);
DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL);
offset = NET_LL_HDRLEN(fwd->f_dev);
/* Copy the saved L2 + L3 header */
/* Copy the IOB chain that contains the L3L3 headers and any data payload */
DEBUGASSERT(offset + fwd->f_hdrsize <= NET_DEV_MTU(fwd->f_dev));
memcpy(&fwd->f_dev->d_buf[offset], &fwd->f_hdr, fwd->f_hdrsize);
offset += fwd->f_hdrsize;
DEBUGASSERT(fwd->f_iob->io_pktlen >= fwd->f_hdrsize);
DEBUGASSERT(offset + fwd->f_iob->io_pktlen <= NET_DEV_MTU(fwd->f_dev));
ret = iob_copyout(&fwd->f_dev->d_buf[offset], fwd->f_iob,
fwd->f_iob->io_pktlen, 0);
/* Copy the IOB chain that contains the payload */
if (fwd->f_iob != NULL && fwd->f_iob->io_pktlen > 0)
{
DEBUGASSERT(offset + fwd->f_iob->io_pktlen <= NET_DEV_MTU(fwd->f_dev));
ret = iob_copyout(&fwd->f_dev->d_buf[offset], fwd->f_iob,
fwd->f_iob->io_pktlen, 0);
DEBUGASSERT(ret == fwd->f_iob->io_pktlen);
offset += fwd->f_iob->io_pktlen;
}
DEBUGASSERT(ret == fwd->f_iob->io_pktlen);
offset += fwd->f_iob->io_pktlen;
fwd->f_dev->d_sndlen = offset;
}
+4 -3
View File
@@ -73,6 +73,8 @@
# define CONFIG_NET_IPFORWARD_NSTRUCT 4
#endif
#define FWD_HEADER(fwd) (FAR union fwd_iphdr_u *)((fwd)->f_iob->io_data)
/****************************************************************************
* Public Types
****************************************************************************/
@@ -158,10 +160,9 @@ struct forward_s
{
FAR struct forward_s *f_flink; /* Supports a singly linked list */
FAR struct net_driver_s *f_dev; /* Forwarding device */
FAR struct iob_s *f_iob; /* IOBs containing the data payload */
FAR struct iob_s *f_iob; /* IOB chain containing the packet */
FAR struct devif_callback_s *f_cb; /* Reference to callback instance */
union fwd_iphdr_u f_hdr; /* Copy of original L2+L3 headers */
union fwd_conn_u f_conn; /* Protocol-specific connectin struct */
union fwd_conn_u f_conn; /* Protocol-specific connection struct */
uint8_t f_hdrsize; /* The size of the L2+L3 headers */
};
+28 -45
View File
@@ -267,8 +267,6 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev,
FAR struct ipv4_hdr_s *ipv4)
{
FAR struct forward_s *fwd = NULL;
FAR uint8_t *payload;
unsigned int paysize;
int hdrsize;
int ret;
@@ -318,73 +316,58 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev,
goto errout_with_fwd;
}
/* Save the entire L2 and L3 headers in the state structure */
/* The L2/L3 headers must fit within one, contiguous IOB. */
if (hdrsize > sizeof(union fwd_iphdr_u))
if (hdrsize > CONFIG_IOB_BUFSIZE)
{
nwarn("WARNING: Header is too big for pre-allocated structure\n");
ret = -E2BIG;
goto errout_with_fwd;
}
memcpy(&fwd->f_hdr.ipv4, ipv4, hdrsize);
fwd->f_hdrsize = hdrsize;
/* Decrement the TTL in the copy of the IPv4 header (retaining the
* original TTL in the source). If it decrements to zero, then drop
* the packet.
/* Try to allocate the head of an IOB chain. If this fails, the
* packet will be dropped; we are not operating in a context
* where waiting for an IOB is a good idea
*/
ret = ipv4_decr_ttl(&fwd->f_hdr.ipv4.l2);
if (ret < 1)
fwd->f_iob = iob_tryalloc(false);
if (fwd->f_iob == NULL)
{
nwarn("WARNING: Hop limit exceeded... Dropping!\n");
ret = -EMULTIHOP;
nwarn("WARNING: iob_tryalloc() failed\n");
ret = -ENOMEM;
goto errout_with_fwd;
}
/* Use the L2 + L3 header size to determine start and size of the data
* payload.
*
* Remember that the size of the L1 header has already been subtracted
* from dev->d_len.
*/
payload = (FAR uint8_t *)ipv4 + hdrsize;
paysize = dev->d_len - hdrsize;
/* If there is a payload, then copy it into an IOB chain.
/* Copy the L2/L3 headers plus any following payload into an IOB chain.
* iob_trycopin() will not wait, but will fail there are no available
* IOBs.
*
* REVISIT: Consider an alternative design that does not require data
* copying. This would require a pool of d_buf's that are managed by
* the network rather than the network device.
*/
if (paysize > 0)
ret = iob_trycopyin(fwd->f_iob, (FAR const uint8_t *)ipv4,
dev->d_len, 0, false);
if (ret < 0)
{
/* Try to allocate the head of an IOB chain. If this fails, the
* packet will be dropped; we are not operating in a context
* where waiting for an IOB is a good idea
*/
nwarn("WARNING: iob_trycopyin() failed: %d\n", ret);
goto errout_with_iobchain;
}
fwd->f_iob = iob_tryalloc(false);
if (fwd->f_iob == NULL)
{
nwarn("WARNING: iob_tryalloc() failed\n");
ret = -ENOMEM;
goto errout_with_fwd;
}
/* Decrement the TTL in the copy of the IPv4 header (retaining the
* original TTL in the source to handle the broadcast case). If the
* TLL decrements to zero, then do not forward the packet.
*/
/* Copy the packet data payload into an IOB chain. iob_trycopin() will
* not wait, but will fail there are no available IOBs.
*/
ret = iob_trycopyin(fwd->f_iob, payload, paysize, 0, false);
if (ret < 0)
{
nwarn("WARNING: iob_trycopyin() failed: %d\n", ret);
goto errout_with_iobchain;
}
ret = ipv4_decr_ttl((FAR struct ipv4_hdr_s *)fwd->f_iob->io_data);
if (ret < 1)
{
nwarn("WARNING: Hop limit exceeded... Dropping!\n");
ret = -EMULTIHOP;
goto errout_with_iobchain;
}
/* Then set up to forward the packet according to the protocol.
+28 -47
View File
@@ -381,9 +381,6 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
}
else if (ret == PACKET_NOT_FORWARDED)
{
FAR uint8_t *payload;
unsigned int paysize;
/* Verify that the full packet will fit within the forwarding devices
* MTU. We provide no support for fragmenting forwarded packets.
*/
@@ -430,74 +427,58 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
goto errout_with_fwd;
}
/* Save the entire L2 and L3 headers in the state structure */
/* The L2/L3 headers must fit within one, contiguous IOB. */
if (hdrsize > sizeof(union fwd_iphdr_u))
if (hdrsize > CONFIG_IOB_BUFSIZE)
{
nwarn("WARNING: Header is too big for pre-allocated structure\n");
ret = -E2BIG;
goto errout_with_fwd;
}
memcpy(&fwd->f_hdr.ipv6, ipv6, hdrsize);
fwd->f_hdrsize = hdrsize;
/* Decrement the TTL in the copy of the IPv6 header (retaining the
* original TTL in the source). If it decrements to zero, then drop
* the packet.
/* Try to allocate the head of an IOB chain. If this fails, the
* packet will be dropped; we are not operating in a context where
* waiting for an IOB is a good idea
*/
ret = ipv6_decr_ttl(&fwd->f_hdr.ipv6.l2);
if (ret < 1)
fwd->f_iob = iob_tryalloc(false);
if (fwd->f_iob == NULL)
{
nwarn("WARNING: Hop limit exceeded... Dropping!\n");
ret = -EMULTIHOP;
nwarn("WARNING: iob_tryalloc() failed\n");
ret = -ENOMEM;
goto errout_with_fwd;
}
/* Use the L2 + L3 header size to determine start and size of the data
* payload.
*
* Remember that the size of the L1 header has already been subtracted
* from dev->d_len.
*/
payload = (FAR uint8_t *)ipv6 + hdrsize;
paysize = dev->d_len - hdrsize;
/* If there is a payload, then copy it into an IOB chain.
/* Copy the L2/L3 headers plus any following payload into an IOB
* chain. iob_trycopin() will not wait, but will fail there are no
* available IOBs.
*
* REVISIT: Consider an alternative design that does not require data
* copying. This would require a pool of d_buf's that are managed by
* the network rather than the network device.
*/
if (paysize > 0)
ret = iob_trycopyin(fwd->f_iob, (FAR const uint8_t *)ipv6,
dev->d_len, 0, false);
if (ret < 0)
{
/* Try to allocate the head of an IOB chain. If this fails,
* the packet will be dropped; we are not operating in a
* context where waiting for an IOB is a good idea
*/
nwarn("WARNING: iob_trycopyin() failed: %d\n", ret);
goto errout_with_iobchain;
}
fwd->f_iob = iob_tryalloc(false);
if (fwd->f_iob == NULL)
{
nwarn("WARNING: iob_tryalloc() failed\n");
ret = -ENOMEM;
goto errout_with_fwd;
}
/* Decrement the TTL in the copy of the IPv6 header (retaining the
* original TTL in the sourcee to handle the broadcast case). If the
* TTL decrements to zero, then do not forward the packet.
*/
/* Copy the packet data payload into an IOB chain.
* iob_trycopin() will not wait, but will fail there are no
* available IOBs.
*/
ret = iob_trycopyin(fwd->f_iob, payload, paysize, 0, false);
if (ret < 0)
{
nwarn("WARNING: iob_trycopyin() failed: %d\n", ret);
goto errout_with_iobchain;
}
ret = ipv6_decr_ttl((FAR struct ipv6_hdr_s *)fwd->f_iob->io_data);
if (ret < 1)
{
nwarn("WARNING: Hop limit exceeded... Dropping!\n");
ret = -EMULTIHOP;
goto errout_with_iobchain;
}
/* Then set up to forward the packet according to the protocol.