Files CCore/inc/net/EthDevice.h CCore/src/net/EthDevice.cpp
EthDevice is an abstract interface. This interface should be implemented by an Ethernet device driver class to be used as such.
struct EthDevice
{
static const Unid TypeUnid;
// static properties
virtual MACAddress getAddress() const =0;
virtual PacketFormat getTxFormat() const =0; // max_data <= MaxUInt<IPLen>
virtual PacketFormat getRxFormat() const =0; // max_data <= MaxUInt<IPLen>
// attach/detach
virtual void attach(EthProc *proc)=0;
virtual void detach()=0;
// dynamic properties
using StatInfo = EthStatInfo ;
virtual void getStat(StatInfo &ret)=0;
virtual bool getPromiscMode()=0;
virtual void setPromiscMode(bool enable)=0;
// outbound
virtual void signalOutbound()=0;
};
Methods of this interface are called asynchronously. The implementation must take all necessary measures to deal with the race condition.
The first three methods are static properties of the device. They must not be changed during the object life-time.
getAddress() returns the MAC address of the device.
getTxFormat() returns the packet format for outbound operations.
getRxFormat() returns the packet format for inbound operations.
The max_len of both packet formats must be represented by IPLen type (i.e. must not exceed 216-1).
To process the traffic a traffic processor must be attached. Only one processor may be attached at the time. While a processor is attached, it is received the inbound traffic as well as other notification events. It also serves as the source of outbound packets. It must stay alive while been attached.
attach() attaches the inbound processor.
detach() detaches the inbound processor.
The next group of methods deals with dynamic properties of the device.
getStat() returns the device statistic counters.
getPromiscMode() returns the promiscuous mode flag.
setPromiscMode() sets the promiscuous mode flag.
The last methods signals to the device, that there are some outbound packets. In response driver must extract and send out packets from the traffic processor.
signalOutbound() signals to push outbound process.
EthStatInfo is a set of statistic counters for Ethernet driver.
enum EthEvent { EthLink_Up, EthLink_Down, EthTx_Done, EthRx_Done, EthTx_BadPacketLen, EthTx_Error, EthRx_BadPacketLen, EthRx_Drop, EthRx_Broadcast, EthRx_Error, EthEventLim }; const char * GetTextDesc(EthEvent ev); using EthStatInfo = Counters<EthEvent,EthEventLim> ;
EthProc is an abstract interface of a traffic processor.
struct EthProc
{
// serialized
virtual void start()=0;
virtual void linkUp()=0;
virtual void linkDown()=0;
virtual void tick()=0; // InboundTicksPerSec
virtual void inbound(Packet<uint8,EthRxExt> packet)=0;
virtual void prepareOutbound()=0;
virtual Packet<uint8,EthTxExt> outbound()=0;
virtual void stop()=0;
};
It is a responsibility of the driver to call methods of this interface synchronously. So traffic processor don't have to protect method calls by a mutex.
start() is called once at the moment the driver is started.
linkUp() is called to inform the link is up.
linkDown() is called to inform the link is down.
tick() is called periodically with the frequence InboundTicksPerSec(10 Hz) and can be used for a protocols timeout processing.
inbound() is called to process an inbound Ethernet packet. The packet has the proper packet format (getRxFormat()) and has the attached extension of the type EthRxExt with additional information. Packet carries an Ethernet packet payload.
prepareOutbound() is called to process the outbound traffic. This method is called first as the reaction on the signalOutbound() method call. Then driver extracts and sends out packets by the calling of the method outbound().
outbound() method is used to retrieve packets from the outbound packet queue. The null packet is returned, if the queue is empty. The packet must carry Ethernet payload and must have the proper packet format (getTxFormat()). It also has the attached packet extension of the type EthTxExt with additional information.
stop() is called once at the moment the driver is stopped.
It is intended that packet formats reserve a space for Ethernet packet header and uses max_data to reflect the MTU length.
A typical implementation of the Ethernet driver would start a task for the packet processing ("Ethernet task"). It is assumed, that a traffic processor is attached first and then task is started. At that moment the method start() is called. At the proper moment a management entity should stop the task, the task calls stop() before exit. Then traffic processor is detached and may be destroyed, as well as the driver object.
This structure supplements outbound packets and used by a driver to build the Ethernet packet header. It has two fields: dst with a destination MAC address and type with an Ethernet packet type.
struct EthTxExt
{
MACAddress dst;
EthType type;
// constructors
EthTxExt() : dst(),type() {}
EthTxExt(MACAddress dst_,EthType type_) : dst(dst_),type(type_) {}
// print object
template <class P>
void print(P &out) const;
};
This structure supplements inbound packets and filled by a driver from the Ethernet packet header. It has three fields: src with a source MAC address, dst with a destination MAC address and type with an Ethernet packet type.
struct EthRxExt
{
MACAddress src;
MACAddress dst;
EthType type;
// constructors
EthRxExt() : src(),dst(),type() {}
EthRxExt(MACAddress src_,MACAddress dst_,EthType type_) : src(src_),dst(dst_),type(type_) {}
// print object
template <class P>
void print(P &out) const;
};