genode/repos/os/include/net/internet_checksum.h
Martin Stein 9a37ccfe29 nic_router: incremental L4 checksum updates
The checksums for forwarded/routed UDP, TCP and ICMP, used to be always
re-calculated from scratch in the NIC router although the router changes only
a few packet fields. This commit replaces the old approach whereever sensible
with an algorithm for incremental checksum updates suggested in RFC 1071.
The goal is to improve router performance.

Ref #4555
2022-08-10 13:33:02 +02:00

92 lines
2.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* \brief Computing the Internet Checksum (conforms to RFC 1071)
* \author Martin Stein
* \date 2018-03-23
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NET__INTERNET_CHECKSUM_H_
#define _NET__INTERNET_CHECKSUM_H_
/* Genode includes */
#include <net/ipv4.h>
#include <base/stdint.h>
namespace Net {
/**
* This struct helps avoiding the following compiler warning when using
* the internet checksum functions on packet classes (like
* Net::Ipv4_packet):
*
* warning: converting a packed Net::[PACKET_CLASS] pointer
* (alignment 1) to a const uint16_t {aka const short
* unsigned int} pointer (alignment 2) may result in an
* unaligned pointer value
*
* Apparently, the 'packed' attribute normally used on packet classes sets
* the alignment of the packet class to 1. However, for the purpose of the
* internet-checksum functions, we can assume that the packet data has no
* alignment. This is expressed by casting the packet-object pointer to a
* Packed_uint16 pointer instead of a uint16_t pointer.
*/
struct Packed_uint16
{
Genode::uint16_t value;
} __attribute__((packed));
Genode::uint16_t internet_checksum(Packed_uint16 const *data_ptr,
Genode::size_t data_sz);
Genode::uint16_t
internet_checksum_pseudo_ip(Packed_uint16 const *data_ptr,
Genode::size_t data_sz,
Genode::uint16_t ip_data_sz_be,
Ipv4_packet::Protocol ip_prot,
Ipv4_address &ip_src,
Ipv4_address &ip_dst);
/**
* Accumulating modifier for incremental updates of internet checksums
*/
class Internet_checksum_diff
{
private:
signed long _value { 0 };
public:
/**
* Update modifier according to a data update in the target region
*
* PRECONDITIONS
*
* * The pointers must refer to data that is at an offset inside
* the checksum'd region that is a multiple of 2 bytes (16 bits).
*/
void add_up_diff(Packed_uint16 const *new_data_ptr,
Packed_uint16 const *old_data_ptr,
Genode::size_t data_sz);
/**
* Update this modifier by adding up another modifier
*/
void add_up_diff(Internet_checksum_diff const &icd);
/**
* Return the given checksum with this modifier applied
*/
Genode::uint16_t apply_to(signed long sum) const;
};
}
#endif /* _NET__INTERNET_CHECKSUM_H_ */