nuttx/net/utils/net_ipchksum.c

209 lines
6.6 KiB
C
Raw Normal View History

/****************************************************************************
* net/utils/net_ipchksum.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <assert.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/ip.h>
#include "utils/utils.h"
#ifdef CONFIG_NET
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
#define IPv6BUF ((FAR struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ipv4_upperlayer_chksum
*
* Description:
* Perform the checksum calculation over the IPv4, protocol headers, and
* data payload as necessary.
*
* Input Parameters:
* dev - The network driver instance. The packet data is in the d_buf
* of the device.
* proto - The protocol being supported
*
* Returned Value:
* The calculated checksum
*
****************************************************************************/
#if !defined(CONFIG_NET_ARCH_CHKSUM) && defined(CONFIG_NET_IPv4)
uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto)
{
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
uint16_t upperlen;
uint16_t iphdrlen;
uint16_t sum;
/* Get the IP header length (accounting for possible options). */
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
/* The length reported in the IPv4 header is the length of both the IPv4
* header and the payload that follows the header. We need to subtract
* the size of the IPv4 header to get the size of the payload.
*/
upperlen = (((uint16_t)(ipv4->len[0]) << 8) + ipv4->len[1]) - iphdrlen;
/* Verify some minimal assumptions */
This commit attempts remove some long standard confusion in naming and some actual problems that result from the naming confusion. The basic problem is the standard MTU does not include the size of the Ethernet header. For clarity, I changed the naming of most things called MTU to PKTSIZE. For example, CONFIG_NET_ETH_MTU is now CONFIG_NET_ETH_PKTSIZE. This makes the user interface a little hostile. People thing of an MTU of 1500 bytes, but the corresponding packet is really 1514 bytes (including the 14 byte Ethernet header). A more friendly solution would configure the MTU (as before), but then derive the packet buffer size by adding the MAC header length. Instead, we define the packet buffer size then derive the MTU. The MTU is not common currency in networking. On the wire, the only real issue is the MSS which is derived from MTU by subtracting the IP header and TCP header sizes (for the case of TCP). Now it is derived for the PKTSIZE by subtracting the IP header, the TCP header, and the MAC header sizes. So we should be all good and without the recurring 14 byte error in MTU's and MSS's. Squashed commit of the following: Trivial update to fix some spacing issues. net/: Rename several macros containing _MTU to _PKTSIZE. net/: Rename CONFIG_NET_SLIP_MTU to CONFIG_NET_SLIP_PKTSIZE and similarly for CONFIG_NET_TUN_MTU. These are not the MTU which does not include the size of the link layer header. These are the full size of the packet buffer memory (minus any GUARD bytes). net/: Rename CONFIG_NET_6LOWPAN_MTU to CONFIG_NET_6LOWPAN_PKTSIZE and similarly for CONFIG_NET_TUN_MTU. These are not the MTU which does not include the size of the link layer header. These are the full size of the packet buffer memory (minus any GUARD bytes). net/: Rename CONFIG_NET_ETH_MTU to CONFIG_NET_ETH_PKTSIZE. This is not the MTU which does not include the size of the link layer header. This is the full size of the packet buffer memory (minus any GUARD bytes). net/: Rename the file d_mtu in the network driver structure to d_pktsize. That value saved there is not the MTU. The packetsize is the memory large enough to hold the maximum packet PLUS the size of the link layer header. The MTU does not include the link layer header.
2018-07-04 22:10:40 +02:00
if (upperlen > NETDEV_PKTSIZE(dev))
{
return 0;
}
/* First sum pseudo-header.
*
* IP protocol and length fields. This addition cannot carry.
*/
sum = upperlen + proto;
/* Sum IP source and destination addresses. */
sum = chksum(sum, (FAR uint8_t *)&ipv4->srcipaddr, 2 * sizeof(in_addr_t));
/* Sum IP payload data. */
sum = chksum(sum, &dev->d_buf[iphdrlen + NET_LL_HDRLEN(dev)], upperlen);
return (sum == 0) ? 0xffff : HTONS(sum);
}
#endif /* CONFIG_NET_ARCH_CHKSUM */
/****************************************************************************
* Name: ipv6_upperlayer_chksum
*
* Description:
* Perform the checksum calculation over the IPv6, protocol headers, and
* data payload as necessary.
*
* Input Parameters:
* dev - The network driver instance. The packet data is in the d_buf
* of the device.
* proto - The protocol being supported
* iplen - The size of the IPv6 header. This may be larger than
* IPv6_HDRLEN the IPv6 header if IPv6 extension headers are
* present.
*
* Returned Value:
* The calculated checksum
*
****************************************************************************/
#if !defined(CONFIG_NET_ARCH_CHKSUM) && defined(CONFIG_NET_IPv6)
uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev,
uint8_t proto, unsigned int iplen)
{
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
uint16_t upperlen;
uint16_t sum;
DEBUGASSERT(dev != NULL && iplen >= IPv6_HDRLEN);
/* The length reported in the IPv6 header is the length of the payload
* that follows the header. If extension heders are present, then this
* size includes the size of the IPv6 extension headers.
*/
upperlen = ((uint16_t)ipv6->len[0] << 8) + ipv6->len[1];
/* Adjust for the presence of any extension headers */
upperlen -= (iplen - IPv6_HDRLEN);
/* Verify some minimal assumptions */
This commit attempts remove some long standard confusion in naming and some actual problems that result from the naming confusion. The basic problem is the standard MTU does not include the size of the Ethernet header. For clarity, I changed the naming of most things called MTU to PKTSIZE. For example, CONFIG_NET_ETH_MTU is now CONFIG_NET_ETH_PKTSIZE. This makes the user interface a little hostile. People thing of an MTU of 1500 bytes, but the corresponding packet is really 1514 bytes (including the 14 byte Ethernet header). A more friendly solution would configure the MTU (as before), but then derive the packet buffer size by adding the MAC header length. Instead, we define the packet buffer size then derive the MTU. The MTU is not common currency in networking. On the wire, the only real issue is the MSS which is derived from MTU by subtracting the IP header and TCP header sizes (for the case of TCP). Now it is derived for the PKTSIZE by subtracting the IP header, the TCP header, and the MAC header sizes. So we should be all good and without the recurring 14 byte error in MTU's and MSS's. Squashed commit of the following: Trivial update to fix some spacing issues. net/: Rename several macros containing _MTU to _PKTSIZE. net/: Rename CONFIG_NET_SLIP_MTU to CONFIG_NET_SLIP_PKTSIZE and similarly for CONFIG_NET_TUN_MTU. These are not the MTU which does not include the size of the link layer header. These are the full size of the packet buffer memory (minus any GUARD bytes). net/: Rename CONFIG_NET_6LOWPAN_MTU to CONFIG_NET_6LOWPAN_PKTSIZE and similarly for CONFIG_NET_TUN_MTU. These are not the MTU which does not include the size of the link layer header. These are the full size of the packet buffer memory (minus any GUARD bytes). net/: Rename CONFIG_NET_ETH_MTU to CONFIG_NET_ETH_PKTSIZE. This is not the MTU which does not include the size of the link layer header. This is the full size of the packet buffer memory (minus any GUARD bytes). net/: Rename the file d_mtu in the network driver structure to d_pktsize. That value saved there is not the MTU. The packetsize is the memory large enough to hold the maximum packet PLUS the size of the link layer header. The MTU does not include the link layer header.
2018-07-04 22:10:40 +02:00
if (upperlen > NETDEV_PKTSIZE(dev))
{
return 0;
}
/* The checksum is calculated starting with a pseudo-header of IPv6 header
* fields according to the IPv6 standard, which consists of the source
* and destination addresses, the packet length and the next header field.
*/
sum = upperlen + proto;
/* Sum IP source and destination addresses. */
sum = chksum(sum, (FAR uint8_t *)&ipv6->srcipaddr,
2 * sizeof(net_ipv6addr_t));
/* Sum IP payload data. */
sum = chksum(sum, &dev->d_buf[NET_LL_HDRLEN(dev) + iplen], upperlen);
return (sum == 0) ? 0xffff : HTONS(sum);
}
#endif /* CONFIG_NET_ARCH_CHKSUM */
/****************************************************************************
* Name: ipv4_chksum
*
* Description:
* Calculate the IPv4 header checksum of the packet header in d_buf.
*
* The IPv4 header checksum is the Internet checksum of the 20 bytes of
* the IPv4 header.
*
* If CONFIG_NET_ARCH_CHKSUM is defined, then this function must be
* provided by architecture-specific logic.
*
* Returned Value:
* The IPv4 header checksum of the IPv4 header in the d_buf buffer.
*
****************************************************************************/
#if defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_ARCH_CHKSUM)
uint16_t ipv4_chksum(FAR struct net_driver_s *dev)
{
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
uint16_t iphdrlen;
uint16_t sum;
/* Get the IP header length (accounting for possible options). */
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
sum = chksum(0, &dev->d_buf[NET_LL_HDRLEN(dev)], iphdrlen);
return (sum == 0) ? 0xffff : HTONS(sum);
}
#endif /* CONFIG_NET_ARCH_CHKSUM */
#endif /* CONFIG_NET */