mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-28 01:28:53 +00:00
9a37ccfe29
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
121 lines
3.1 KiB
C++
121 lines
3.1 KiB
C++
/*
|
|
* \brief User datagram protocol.
|
|
* \author Stefan Kalkowski
|
|
* \date 2010-08-19
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2010-2017 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 _UDP_H_
|
|
#define _UDP_H_
|
|
|
|
/* Genode */
|
|
#include <base/exception.h>
|
|
#include <base/stdint.h>
|
|
#include <net/port.h>
|
|
#include <util/endian.h>
|
|
#include <net/ethernet.h>
|
|
#include <net/ipv4.h>
|
|
|
|
namespace Net { class Udp_packet; }
|
|
|
|
|
|
/**
|
|
* Data layout of this class conforms to an UDP packet (RFC 768)
|
|
*
|
|
* UDP-header-format:
|
|
*
|
|
* -----------------------------------------------------------------------
|
|
* | source-port | destination-port | length | checksum |
|
|
* | 2 bytes | 2 bytes | 2 bytes | 2 bytes |
|
|
* -----------------------------------------------------------------------
|
|
*/
|
|
class Net::Udp_packet
|
|
{
|
|
private:
|
|
|
|
/***********************
|
|
** UDP header fields **
|
|
***********************/
|
|
|
|
Genode::uint16_t _src_port;
|
|
Genode::uint16_t _dst_port;
|
|
Genode::uint16_t _length;
|
|
Genode::uint16_t _checksum;
|
|
unsigned _data[0];
|
|
|
|
public:
|
|
|
|
template <typename T>
|
|
T const &data(Size_guard &size_guard) const
|
|
{
|
|
size_guard.consume_head(sizeof(T));
|
|
return *(T const *)(_data);
|
|
}
|
|
|
|
template <typename T>
|
|
T &data(Size_guard &size_guard)
|
|
{
|
|
size_guard.consume_head(sizeof(T));
|
|
return *(T *)(_data);
|
|
}
|
|
|
|
template <typename T, typename SIZE_GUARD>
|
|
T &construct_at_data(SIZE_GUARD &size_guard)
|
|
{
|
|
size_guard.consume_head(sizeof(T));
|
|
return *Genode::construct_at<T>(_data);
|
|
}
|
|
|
|
template <typename SIZE_GUARD>
|
|
void memcpy_to_data(void const *src_base,
|
|
Genode::size_t src_size,
|
|
SIZE_GUARD &size_guard)
|
|
{
|
|
size_guard.consume_head(src_size);
|
|
Genode::memcpy(_data, src_base, src_size);
|
|
}
|
|
|
|
void update_checksum(Ipv4_address ip_src,
|
|
Ipv4_address ip_dst);
|
|
|
|
void update_checksum(Internet_checksum_diff const &icd);
|
|
|
|
bool checksum_error(Ipv4_address ip_src,
|
|
Ipv4_address ip_dst) const;
|
|
|
|
|
|
/***************
|
|
** Accessors **
|
|
***************/
|
|
|
|
Port src_port() const { return Port(host_to_big_endian(_src_port)); }
|
|
Port dst_port() const { return Port(host_to_big_endian(_dst_port)); }
|
|
Genode::uint16_t length() const { return host_to_big_endian(_length); }
|
|
Genode::uint16_t checksum() const { return host_to_big_endian(_checksum); }
|
|
|
|
void length(Genode::uint16_t v) { _length = host_to_big_endian(v); }
|
|
void src_port(Port p) { _src_port = host_to_big_endian(p.value); }
|
|
void dst_port(Port p) { _dst_port = host_to_big_endian(p.value); }
|
|
void src_port_big_endian(Genode::uint16_t v) { _src_port = v; }
|
|
void dst_port_big_endian(Genode::uint16_t v) { _dst_port = v; }
|
|
|
|
void src_port(Port p, Internet_checksum_diff &icd);
|
|
void dst_port(Port p, Internet_checksum_diff &icd);
|
|
|
|
|
|
/*********
|
|
** log **
|
|
*********/
|
|
|
|
void print(Genode::Output &output) const;
|
|
|
|
} __attribute__((packed));
|
|
|
|
#endif /* _UDP_H_ */
|