mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 22:23:16 +00:00
bd501404db
* Adds methods for copying raw data to the data field of Ethernet frames and UDP packets. This is used in the port to wrap the higher-layer packet data prepared by the contrib code with the additionally required headers before sending it at a network session. * Adds a method to cast raw data to an IPv4 packet. This is required in the port in order to check values in stand-alone IP packets produced by the contrib code before sending them at a network session. * Adds methods for setting UDP ports given big endian port values without having to convert to little endian in the app and then back to big endian in the net lib. Ref #4397
179 lines
4.2 KiB
C++
179 lines
4.2 KiB
C++
/*
|
|
* \brief Ethernet 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 _NET__ETHERNET_H_
|
|
#define _NET__ETHERNET_H_
|
|
|
|
/* Genode includes */
|
|
#include <base/exception.h>
|
|
#include <util/string.h>
|
|
#include <util/construct_at.h>
|
|
#include <util/endian.h>
|
|
#include <net/mac_address.h>
|
|
#include <net/size_guard.h>
|
|
|
|
namespace Net
|
|
{
|
|
class Ethernet_frame;
|
|
|
|
template <Genode::size_t DATA_SIZE>
|
|
class Ethernet_frame_sized;
|
|
}
|
|
|
|
|
|
/**
|
|
* Data layout of this class conforms to the Ethernet II frame
|
|
* (IEEE 802.3).
|
|
*
|
|
* Ethernet-frame-header-format:
|
|
*
|
|
* ----------------------------------------------------------
|
|
* | destination mac address | source mac address | ethertype |
|
|
* | 6 bytes | 6 bytes | 2 bytes |
|
|
* ----------------------------------------------------------
|
|
*/
|
|
class Net::Ethernet_frame
|
|
{
|
|
public:
|
|
|
|
enum Size {
|
|
ADDR_LEN = 6, /* MAC address length in bytes */
|
|
};
|
|
|
|
static Mac_address broadcast() { return Mac_address((Genode::uint8_t)0xff); }
|
|
|
|
private:
|
|
|
|
Genode::uint8_t _dst[ADDR_LEN]; /* destination mac address */
|
|
Genode::uint8_t _src[ADDR_LEN]; /* source mac address */
|
|
Genode::uint16_t _type; /* encapsulated protocol */
|
|
unsigned _data[0]; /* encapsulated data */
|
|
|
|
public:
|
|
|
|
enum { MIN_SIZE = 64 };
|
|
|
|
/**
|
|
* Id representing encapsulated protocol.
|
|
*/
|
|
enum class Type : Genode::uint16_t {
|
|
IPV4 = 0x0800,
|
|
ARP = 0x0806,
|
|
};
|
|
|
|
template <typename T>
|
|
T const &data(Size_guard &size_guard) const
|
|
{
|
|
size_guard.consume_head(sizeof(T));
|
|
T const &obj = *(T *)(_data);
|
|
|
|
/* Ethernet may have a tail whose size must be considered */
|
|
Genode::size_t const max_obj_sz = size_guard.unconsumed() + sizeof(T);
|
|
size_guard.consume_tail(max_obj_sz - obj.size(max_obj_sz));
|
|
return obj;
|
|
}
|
|
|
|
template <typename T>
|
|
T &data(Size_guard &size_guard)
|
|
{
|
|
size_guard.consume_head(sizeof(T));
|
|
T &obj = *(T *)(_data);
|
|
|
|
/* Ethernet may have a tail whose size must be considered */
|
|
Genode::size_t const max_obj_sz = size_guard.unconsumed() + sizeof(T);
|
|
size_guard.consume_tail(max_obj_sz - obj.size(max_obj_sz));
|
|
return obj;
|
|
}
|
|
|
|
template <typename T>
|
|
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);
|
|
}
|
|
|
|
static Ethernet_frame &construct_at(void *base,
|
|
Size_guard &size_guard)
|
|
{
|
|
size_guard.consume_head(sizeof(Ethernet_frame));
|
|
return *Genode::construct_at<Ethernet_frame>(base);
|
|
}
|
|
|
|
static Ethernet_frame &cast_from(void *base,
|
|
Size_guard &size_guard)
|
|
{
|
|
size_guard.consume_head(sizeof(Ethernet_frame));
|
|
return *(Ethernet_frame *)base;
|
|
}
|
|
|
|
|
|
/***************
|
|
** Accessors **
|
|
***************/
|
|
|
|
Mac_address dst() const { return Mac_address((void *)_dst); }
|
|
Mac_address src() const { return Mac_address((void *)_src); }
|
|
Type type() const { return (Type)host_to_big_endian(_type); }
|
|
|
|
void dst(Mac_address v) { v.copy(&_dst); }
|
|
void src(Mac_address v) { v.copy(&_src); }
|
|
void type(Type type) { _type = host_to_big_endian((Genode::uint16_t)type); }
|
|
|
|
|
|
/*********
|
|
** log **
|
|
*********/
|
|
|
|
void print(Genode::Output &output) const;
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
template <Genode::size_t DATA_SIZE>
|
|
class Net::Ethernet_frame_sized : public Ethernet_frame
|
|
{
|
|
private:
|
|
|
|
enum {
|
|
HS = sizeof(Ethernet_frame),
|
|
DS = DATA_SIZE + HS >= MIN_SIZE ? DATA_SIZE : MIN_SIZE - HS,
|
|
};
|
|
|
|
Genode::uint8_t _data[DS];
|
|
Genode::uint32_t _checksum;
|
|
|
|
public:
|
|
|
|
Ethernet_frame_sized(Mac_address dst_in, Mac_address src_in,
|
|
Type type_in)
|
|
:
|
|
Ethernet_frame()
|
|
{
|
|
dst(dst_in);
|
|
src(src_in);
|
|
type(type_in);
|
|
}
|
|
|
|
} __attribute__((packed));
|
|
|
|
#endif /* _NET__ETHERNET_H_ */
|