EthInterface: notifications

- queues have been replaced by OS queues
- serving plain interrupts is replaced by queuing events
This commit is contained in:
Wiesner András 2023-10-31 12:01:34 +01:00
parent 903258a796
commit 754b43c51a
2 changed files with 92 additions and 41 deletions

View File

@ -4,37 +4,33 @@
#include "eth_interface.h" #include "eth_interface.h"
#include "dynmem.h" #include "dynmem.h"
#include "utils.h"
#include "etherlib_options.h"
#include "etherlib/prefab/conn_blocks/ethernet_connblock.h" #include "etherlib/prefab/conn_blocks/ethernet_connblock.h"
#include "etherlib_options.h"
#include "utils.h"
static int ethintf_llrecv(EthIODef * io, const RawPckt * pckt) { typedef enum {
ethinf_receive((EthInterface *) io->tag, pckt); ETH_IIE_RECV_NOTIFY = 0,
ETH_IIE_LINK_CHG_NOTIFY,
ETH_IIE_TRANSMIT_NOTIFY,
ETH_IIE_UNKNOWN = 0xFFFF
} EthIntfInternalEvent;
static int ethintf_llrecv(EthIODef *io, const RawPckt *pckt) {
ethinf_receive((EthInterface *)io->tag, pckt);
return 0; return 0;
} }
static int ethintf_llrxnotify(EthIODef * io) { static int ethintf_llrxnotify(EthIODef *io) {
ethinf_notify((EthInterface *) io->tag); ethinf_push_notification((EthInterface *)io->tag, ETH_IIE_RECV_NOTIFY, 0);
return 0; return 0;
} }
static int ethinf_lllinkchg(EthIODef * io, int ls) { static int ethinf_lllinkchg(EthIODef *io, int ls) {
EthInterface * intf = (EthInterface *) io->tag; ethinf_push_notification((EthInterface *)io->tag, ETH_IIE_LINK_CHG_NOTIFY, (uint16_t)ls);
ethinf_set_link_state(intf, ls);
if (intf->dhcp != NULL) {
if (ls) { // if link is on
dhcp_start(intf->dhcp);
} else { // if link is off
dhcp_stop(intf->dhcp);
}
}
MSG("Link state: %d\n", ls);
return 0; return 0;
} }
static void ethintf_register(EthInterface * intf) { static void ethintf_register(EthInterface *intf) {
intf->ioDef->tag = intf; intf->ioDef->tag = intf;
intf->ioDef->llRxStore = ethintf_llrecv; intf->ioDef->llRxStore = ethintf_llrecv;
intf->ioDef->llRxNotify = ethintf_llrxnotify; intf->ioDef->llRxNotify = ethintf_llrxnotify;
@ -42,10 +38,10 @@ static void ethintf_register(EthInterface * intf) {
} }
// interface processing thread // interface processing thread
static ThreadReturnType task_ethintf (ThreadParamType param); static ThreadReturnType task_ethintf(ThreadParamType param);
EthInterface *ethintf_new(EthIODef * io) { EthInterface *ethintf_new(EthIODef *io) {
EthInterface * ethIntf = (EthInterface *)dynmem_alloc(sizeof(EthInterface)); EthInterface *ethIntf = (EthInterface *)dynmem_alloc(sizeof(EthInterface));
ASSERT_NULL(ethIntf); ASSERT_NULL(ethIntf);
memset(&ethIntf->sieve.layer0, 0, sizeof(PcktSieveLayer)); memset(&ethIntf->sieve.layer0, 0, sizeof(PcktSieveLayer));
ethIntf->sieve.intf = ethIntf; ethIntf->sieve.intf = ethIntf;
@ -58,7 +54,9 @@ EthInterface *ethintf_new(EthIODef * io) {
ethIntf->txQ = mq_create(ETHLIB_DEF_MQ_SIZE); ethIntf->txQ = mq_create(ETHLIB_DEF_MQ_SIZE);
ethIntf->rxQ = mq_create(ETHLIB_DEF_MQ_SIZE); ethIntf->rxQ = mq_create(ETHLIB_DEF_MQ_SIZE);
ETHLIB_OS_SEM_CREATE(&ethIntf->rxSem, ETHLIB_DEF_MQ_SIZE);
ETHLIB_OS_QUEUE_CREATE(ethIntf->eventQ, ETHLIB_DEF_MQ_SIZE, uint32_t);
// ETHLIB_OS_SEM_CREATE(&ethIntf->eventSem, ETHLIB_DEF_MQ_SIZE);
ETHLIB_OS_THREAD_DEFINE(task_ethintf, osPriorityHigh, 512, ethIntf); ETHLIB_OS_THREAD_DEFINE(task_ethintf, osPriorityHigh, 512, ethIntf);
ETHLIB_OS_THREAD_CREATE(task_ethintf, ethIntf); ETHLIB_OS_THREAD_CREATE(task_ethintf, ethIntf);
@ -75,16 +73,46 @@ EthInterface *ethintf_new(EthIODef * io) {
return ethIntf; return ethIntf;
} }
static ThreadReturnType task_ethintf (ThreadParamType param) { static ThreadReturnType task_ethintf(ThreadParamType param) {
EthInterface * intf = (EthInterface *) param; EthInterface *intf = (EthInterface *)param;
while (true) { while (true) {
ETHLIB_OS_SEM_WAIT(&intf->rxSem); // fetch notification
uint16_t event_code = ETH_IIE_UNKNOWN;
uint16_t event_data;
ethinf_pull_notification(intf, &event_code, &event_data);
// act accordingly...
switch (event_code) {
case ETH_IIE_RECV_NOTIFY: {
intf->ioDef->llRxRead(intf->ioDef); // read packets, will invoke RxStore intf->ioDef->llRxRead(intf->ioDef); // read packets, will invoke RxStore
while (mq_avail(intf->rxQ) > 0) { while (mq_avail(intf->rxQ) > 0) {
RawPckt rawPckt = mq_top(intf->rxQ); RawPckt rawPckt = mq_top(intf->rxQ);
mq_pop(intf->rxQ); mq_pop(intf->rxQ);
packsieve_input(&intf->sieve, &rawPckt); packsieve_input(&intf->sieve, &rawPckt);
} }
} break;
case ETH_IIE_LINK_CHG_NOTIFY: {
bool ls = event_data;
ethinf_set_link_state(intf, ls);
if (intf->dhcp != NULL) {
if (ls) { // if link is on
dhcp_start(intf->dhcp);
} else { // if link is off
dhcp_stop(intf->dhcp);
}
}
MSG("Link state: %d\n", ls);
} break;
case ETH_IIE_TRANSMIT_NOTIFY: {
intf->ioDef->llTxTrigger(intf->ioDef, intf->txQ);
} break;
default:
MSG("UNKNOWN event!\n");
break;
}
} }
} }
@ -98,12 +126,23 @@ void ethinf_receive(EthInterface *intf, const RawPckt *rawPckt) {
void ethinf_transmit(EthInterface *intf, const RawPckt *rawPckt) { void ethinf_transmit(EthInterface *intf, const RawPckt *rawPckt) {
mq_push(intf->txQ, rawPckt); // push packet onto the message queue mq_push(intf->txQ, rawPckt); // push packet onto the message queue
ethinf_push_notification(intf, ETH_IIE_TRANSMIT_NOTIFY, 0); // notify processing thread of the peding transmit
intf->ioDef->llTxTrigger(intf->ioDef, intf->txQ);
} }
void ethinf_notify(EthInterface *intf) { void ethinf_push_notification(EthInterface *intf, uint16_t event_code, uint16_t event_data) {
ETHLIB_OS_SEM_POST(&intf->rxSem); uint32_t cpd = (event_data << 16) | event_code; // create event compound
ETHLIB_OS_QUEUE_PUSH(intf->eventQ, cpd);
}
void ethinf_pull_notification(EthInterface *intf, uint16_t *event_code, uint16_t *event_data) {
uint32_t cpd;
cpd = ETHLIB_OS_QUEUE_POP(intf->eventQ); // wait for event semaphore
// retrieve event code and data
*event_code = cpd & 0xFFFF;
*event_data = (cpd >> 16) & 0xFFFF;
//MSG("EC: %d\n", *event_code);
} }
void ethinf_set_capabilities(EthInterface *intf, uint32_t cap) { void ethinf_set_capabilities(EthInterface *intf, uint32_t cap) {

View File

@ -9,6 +9,7 @@
#include "arp_cache.h" #include "arp_cache.h"
#include "connection_block.h" #include "connection_block.h"
#include "msg_queue.h" #include "msg_queue.h"
#include "gen_queue.h"
#include "prefab/conn_blocks/ipv4/ip_assembler.h" #include "prefab/conn_blocks/ipv4/ip_assembler.h"
#include "prefab/packet_parsers/dhcp.h" #include "prefab/packet_parsers/dhcp.h"
@ -48,7 +49,7 @@ typedef void (*EthIntfEvtCb)(struct EthInterface_ * intf);
typedef enum { typedef enum {
ETH_EVT_LINK_CHANGE = 0, ETH_EVT_LINK_CHANGE = 0,
ETH_EVT_IP_CHANGE = 1 ETH_EVT_IP_CHANGE = 1,
} EthIntfEvIndex; } EthIntfEvIndex;
/** /**
@ -76,7 +77,8 @@ typedef struct EthInterface_ {
ConnBlock arpCb; ///< ARP connection block ConnBlock arpCb; ///< ARP connection block
MsgQueue * txQ; ///< Transmit queue MsgQueue * txQ; ///< Transmit queue
MsgQueue * rxQ; ///< Receive queue MsgQueue * rxQ; ///< Receive queue
ETHLIB_OS_SEM_TYPE rxSem; ///< Receive queue semaphore ETHLIB_OS_QUEUE_TYPE eventQ; ///< Event queue
//ETHLIB_OS_SEM_TYPE eventSem; ///< Event queue semaphore
IPv4Assembler * ipra; ///< IPv4 reassembler IPv4Assembler * ipra; ///< IPv4 reassembler
EthIntfEventCbTable evtCbTable; ///< Event callback table EthIntfEventCbTable evtCbTable; ///< Event callback table
bool linkState; ///< Interface link state bool linkState; ///< Interface link state
@ -96,11 +98,21 @@ EthInterface *ethintf_new(EthIODef * io);
void ethinf_receive(EthInterface *intf, const RawPckt *rawPckt); void ethinf_receive(EthInterface *intf, const RawPckt *rawPckt);
/** /**
* Notify interface of a received, buffered packet, which needs transferred * Notify interface of some event occured (e.g. a received, buffered packet, which needs to get
* from the low level Ethernet-driver. * transferred from the low level Ethernet-driver, a link change occured etc.)
* @param intf Pointer to Ethernet-interface * @param intf Pointer to Ethernet-interface
* @param event_code Event code
* @param event_data Event data
*/ */
void ethinf_notify(EthInterface *intf); void ethinf_push_notification(EthInterface *intf, uint16_t event_code, uint16_t event_data);
/**
* Pull formerly pushed notification from the event queue.
* @param intf Pointer to Ethernet-interface
* @param event_code pointer to event code
* @param event_data pointer to event data
*/
void ethinf_pull_notification(EthInterface *intf, uint16_t * event_code, uint16_t * event_data);
/** /**
* Transmit packet. * Transmit packet.