EtherLib/eth_interface.c
Wiesner András ab8d45932f Timestamping and bunch of bugfix and optimization
- Timestamping management added
- Errors due to reading uninitialized data in ARP fixed
- EthInterface reworked, incoming packet notification and payload readout separated (through which fixing concurrent access problems)
- RX and TX offloads added
- Capability to add a packet sieve layer without prior registration of specific packet class added (this makes it possible to register arbitrary EtherType connection blocks, for example)
2023-04-27 09:38:26 +02:00

90 lines
2.6 KiB
C

//
// Created by epagris on 2022.10.20..
//
#include "eth_interface.h"
#include "dynmem.h"
#include "utils.h"
#include "etherlib_options.h"
#include "etherlib/prefab/conn_blocks/ethernet_connblock.h"
static int ethintf_llrecv(EthIODef * io, const RawPckt * pckt) {
ethinf_receive((EthInterface *) io->tag, pckt);
return 0;
}
static int ethintf_llrxnotify(EthIODef * io) {
ethinf_notify((EthInterface *) io->tag);
return 0;
}
static void ethintf_register(EthInterface * intf) {
intf->ioDef->tag = intf;
intf->ioDef->llRxStore = ethintf_llrecv;
intf->ioDef->llRxNotify = ethintf_llrxnotify;
}
// interface processing thread
static void * ethinf_proc_thread(void * param);
EthInterface *ethintf_new(EthIODef * io) {
EthInterface * ethIntf = (EthInterface *)dynmem_alloc(sizeof(EthInterface));
ASSERT_NULL(ethIntf);
memset(&ethIntf->sieve.layer0, 0, sizeof(PcktSieveLayer));
ethIntf->sieve.intf = ethIntf;
ethIntf->sieve.layer0.connBReportFn = ethernet_print_report;
ethIntf->ioDef = io;
ethIntf->ip = 0;
ethIntf->arpc = arpc_new(ethIntf, ETHLIB_ARPCACHE_SIZE);
ASSERT_NULL(ethIntf->arpc);
ethintf_register(ethIntf);
ethIntf->txQ = 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_THREAD_DEFINE(ethinf_proc_thread, ethrx, osPriorityHigh, 4096, ethIntf);
ETHLIB_OS_THREAD_CREATE(ethrx, ethIntf);
ethIntf->ipra = ipra_new();
ethIntf->capabilities = 0;
return ethIntf;
}
static void * ethinf_proc_thread(void * param) {
EthInterface * intf = (EthInterface *) param;
while (true) {
ETHLIB_OS_SEM_WAIT(&intf->rxSem);
intf->ioDef->llRxRead(intf->ioDef, intf->rxQ); // read packets
while (mq_avail(intf->rxQ) > 0) {
RawPckt rawPckt = mq_top(intf->rxQ);
mq_pop(intf->rxQ);
packsieve_input(&intf->sieve, &rawPckt);
}
}
return NULL;
}
void ethinf_receive(EthInterface *intf, const RawPckt *rawPckt) {
bool pushOK = mq_push(intf->rxQ, rawPckt);
if (!pushOK) {
dynmem_free(rawPckt->payload);
ERROR("Input queue full, packet dropped!\n");
}
}
void ethinf_transmit(EthInterface *intf, const RawPckt *rawPckt) {
mq_push(intf->txQ, rawPckt); // push packet onto the message queue
intf->ioDef->llTxTrigger(intf->ioDef, intf->txQ);
}
void ethinf_notify(EthInterface *intf) {
ETHLIB_OS_SEM_POST(&intf->rxSem);
}
void ethinf_set_capabilities(EthInterface *intf, uint32_t cap) {
intf->capabilities = cap;
}