- Timer checked, found no (obvious) bugs
- Dynmem mutex added - IP reassembler fixed - More explanation added in comments to the PacketSieve
This commit is contained in:
parent
b8e1a4fe57
commit
c165389369
20
dynmem.c
20
dynmem.c
@ -3,20 +3,28 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#if !defined(ETHLIB_MEMORY_POOL_ATTRIBUTES)
|
#if !defined(ETHLIB_MEMORY_POOL_ATTRIBUTES)
|
||||||
static uint8_t sDynMemPool[ETHLIB_MEMORY_POOL_TOTAL_SIZE];
|
static uint8_t sDynMemPool[ETHLIB_MEMORY_POOL_TOTAL_SIZE];
|
||||||
#else
|
#else
|
||||||
static uint8_t sDynMemPool[ETHLIB_MEMORY_POOL_TOTAL_SIZE] __attribute__((ETHLIB_MEMORY_POOL_ATTRIBUTES));
|
static uint8_t sDynMemPool[ETHLIB_MEMORY_POOL_TOTAL_SIZE] __attribute__((ETHLIB_MEMORY_POOL_ATTRIBUTES));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static ETHLIB_OS_MTX_TYPE dynmem_mtx;
|
||||||
|
|
||||||
void dynmem_init() {
|
void dynmem_init() {
|
||||||
|
ETHLIB_OS_MTX_CREATE(&dynmem_mtx);
|
||||||
E.mp = mp_init(sDynMemPool, ETHLIB_MEMORY_POOL_TOTAL_SIZE);
|
E.mp = mp_init(sDynMemPool, ETHLIB_MEMORY_POOL_TOTAL_SIZE);
|
||||||
ASSERT_NULL(E.mp);
|
ASSERT_NULL(E.mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * dynmem_alloc_(uint32_t size) {
|
void *dynmem_alloc_(uint32_t size) {
|
||||||
return mp_alloc(E.mp, size);
|
ETHLIB_OS_MTX_LOCK(&dynmem_mtx);
|
||||||
|
void * p = mp_alloc(E.mp, size);
|
||||||
|
ETHLIB_OS_MTX_UNLOCK(&dynmem_mtx);
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dynmem_free_(const void * ptr) {
|
void dynmem_free_(const void *ptr) {
|
||||||
mp_free(E.mp, (const uint8_t *)ptr);
|
ETHLIB_OS_MTX_LOCK(&dynmem_mtx);
|
||||||
|
mp_free(E.mp, (const uint8_t *) ptr);
|
||||||
|
ETHLIB_OS_MTX_UNLOCK(&dynmem_mtx);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ EthInterface *ethintf_new(EthIODef *io) {
|
|||||||
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);
|
||||||
|
|
||||||
ethIntf->ipra = ipra_new();
|
ethIntf->ipra = ipra_new(ethIntf);
|
||||||
|
|
||||||
ethIntf->capabilities = 0;
|
ethIntf->capabilities = 0;
|
||||||
|
|
||||||
|
@ -25,6 +25,19 @@ PcktSieve* packsieve_new(EthInterface *intf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void packsieve_input(PcktSieve *sieve, const RawPckt *rawPckt) {
|
void packsieve_input(PcktSieve *sieve, const RawPckt *rawPckt) {
|
||||||
|
/* First we acquire the packet class and see if we know the way how of its processing at all.
|
||||||
|
*
|
||||||
|
* 1.: Get packet descriptor, decide, if we can process this kind of packet or not.
|
||||||
|
* 2.: Fill in common header fields, and chain in the header if possible.
|
||||||
|
* 3.: Parse the packet header (extract fields etc.).
|
||||||
|
* 4.: Fetch the contained packet class.
|
||||||
|
* 5.: Skip the header if found, make the respective pointer to point on the payload.
|
||||||
|
* 6.: Make the just processed contained packet the container for the processing of the next iteration.
|
||||||
|
*
|
||||||
|
* Next, we search the sieve tree if there was such a layer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
// extract fields
|
// extract fields
|
||||||
uint8_t *data = rawPckt->payload;
|
uint8_t *data = rawPckt->payload;
|
||||||
uint32_t size = rawPckt->size;
|
uint32_t size = rawPckt->size;
|
||||||
@ -38,7 +51,7 @@ void packsieve_input(PcktSieve *sieve, const RawPckt *rawPckt) {
|
|||||||
int procRet;
|
int procRet;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// get packet descriptor
|
// [1.] get packet descriptor
|
||||||
PcktClassDesc *cdesc = packreg_get_by_class(E.pcktReg, ownClass, containerClass);
|
PcktClassDesc *cdesc = packreg_get_by_class(E.pcktReg, ownClass, containerClass);
|
||||||
if (cdesc == NULL) {
|
if (cdesc == NULL) {
|
||||||
break;
|
break;
|
||||||
@ -55,48 +68,54 @@ void packsieve_input(PcktSieve *sieve, const RawPckt *rawPckt) {
|
|||||||
cdesc->cacheSize = hdrSize; // retain cache size
|
cdesc->cacheSize = hdrSize; // retain cache size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make header to point on cache area
|
||||||
header = (PcktHeaderElement*) cdesc->cacheArea;
|
header = (PcktHeaderElement*) cdesc->cacheArea;
|
||||||
|
|
||||||
|
// [2.] write header fields
|
||||||
memset(header, 0, hdrSize);
|
memset(header, 0, hdrSize);
|
||||||
header->props.ownPacketClass = ownClass;
|
header->props.ownPacketClass = ownClass;
|
||||||
header->props.propSize = cdesc->propertySize;
|
header->props.propSize = cdesc->propertySize;
|
||||||
header->prev = lastHeader;
|
header->prev = lastHeader;
|
||||||
if (lastHeader) {
|
if (lastHeader) { // if a previous header exists, then fill-in the next field
|
||||||
lastHeader->next = header;
|
lastHeader->next = header;
|
||||||
}
|
}
|
||||||
if (outermostHeader == NULL) {
|
if (outermostHeader == NULL) { // if no previous headers are chained, then it's the first one...
|
||||||
outermostHeader = header;
|
outermostHeader = header; // and make it the outermost header
|
||||||
}
|
}
|
||||||
|
|
||||||
// call parsing function
|
// [3.] call parsing function
|
||||||
PcktProcFnPassbackData pb;
|
PcktProcFnPassbackData pb;
|
||||||
procRet = cdesc->procFun(data + offset, size - offset, header, sieve->intf, &pb);
|
procRet = cdesc->procFun(data + offset, size - offset, header, sieve->intf, &pb);
|
||||||
switch (procRet) {
|
switch (procRet) { // execute further action based on the return value of the parsing function
|
||||||
case PROC_FN_RET_REPRST:
|
case PROC_FN_RET_REPRST: // replace packet and restart processing
|
||||||
dynmem_free(data); // release previous packet data
|
dynmem_free(data); // release previous packet data
|
||||||
data = pb.p; // store new packet data
|
data = pb.p; // store new packet data passed back in pb
|
||||||
size = pb.u;
|
size = pb.u;
|
||||||
mrd = pb.b;
|
mrd = pb.b;
|
||||||
// NO BREAK!
|
// NO BREAK!
|
||||||
case PROC_FN_RET_ABORT:
|
case PROC_FN_RET_ABORT: // abort packet processing
|
||||||
goto header_release;
|
goto header_release;
|
||||||
// GOTO :D!
|
// GOTO :D!
|
||||||
break;
|
break;
|
||||||
case PROC_FN_RET_OK:
|
case PROC_FN_RET_OK: // no extra processing steps
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [4.] get the contained packet class
|
||||||
uint16_t containedClass = header->props.containedPacketClass;
|
uint16_t containedClass = header->props.containedPacketClass;
|
||||||
if (containedClass != 0) {
|
if (containedClass != 0) {
|
||||||
containerClass = ownClass;
|
containerClass = ownClass;
|
||||||
//dynmem_free(props);
|
//dynmem_free(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [5.] adjust offsets based on the just processed header (skip header)
|
||||||
offset += header->props.headerSize;
|
offset += header->props.headerSize;
|
||||||
header->props.accumulatedOffset = offset;
|
header->props.accumulatedOffset = offset;
|
||||||
header->props.bytesToEnd = size - header->props.accumulatedOffset;
|
header->props.bytesToEnd = size - header->props.accumulatedOffset;
|
||||||
header->props.hdrInsFn = cdesc->hdrInsFn;
|
header->props.hdrInsFn = cdesc->hdrInsFn;
|
||||||
|
|
||||||
|
// [6.] advance deeper in the packet
|
||||||
ownClass = containedClass;
|
ownClass = containedClass;
|
||||||
lastHeader = header;
|
lastHeader = header;
|
||||||
} while ((ownClass != 0) && lastHeader->props.validityOK);
|
} while ((ownClass != 0) && lastHeader->props.validityOK);
|
||||||
@ -119,18 +138,19 @@ void packsieve_input(PcktSieve *sieve, const RawPckt *rawPckt) {
|
|||||||
packet.time_ns = rawPckt->ext.rx.time_ns;
|
packet.time_ns = rawPckt->ext.rx.time_ns;
|
||||||
|
|
||||||
// lookup headers in the sieve
|
// lookup headers in the sieve
|
||||||
PcktHeaderElement *headerIter = outermostHeader;
|
PcktHeaderElement *headerIter = outermostHeader; // place iterator on the outermost header
|
||||||
PcktSieveLayer *layer = &sieve->layer0; // innermost matched sieve layer
|
PcktSieveLayer *layer = &sieve->layer0; // innermost matched sieve layer
|
||||||
bool found = true; // first structure is always an Ethernet-frame
|
bool found = true; // first structure is always an Ethernet-frame
|
||||||
while (found && headerIter) {
|
while (found && headerIter) {
|
||||||
PcktSieveLayer *nodeIter = layer->nodes;
|
PcktSieveLayer *nodeIter = layer->nodes; // select the frames nodes
|
||||||
found = false;
|
found = false; // assume that the layer is not found
|
||||||
while (nodeIter && !found) {
|
// iteration on SUBnodes! (so on the first layer...)
|
||||||
found |= nodeIter->matchAny || nodeIter->filtFn(&nodeIter->filtCond, &headerIter->props, &headerIter->next->props, sieve->intf); // specific or general match
|
while (nodeIter && !found) { // look for a matching layer until it's found, or until we have exhausted the nodes
|
||||||
if (found) {
|
found |= nodeIter->matchAny || nodeIter->filtFn(&nodeIter->filtCond, &headerIter->props, &headerIter->next->props, sieve->intf); // specific or general match based on current and next header
|
||||||
|
if (found) { // if layer is found...
|
||||||
layer = nodeIter; // advance in the sieve tree
|
layer = nodeIter; // advance in the sieve tree
|
||||||
PcktHeaderElement *containedHeader = headerIter;
|
PcktHeaderElement *containedHeader = headerIter; // select header corresponding to current layer
|
||||||
if (headerIter->next != NULL) {
|
if (headerIter->next != NULL) { // make contained header to point on contained packet header if exists
|
||||||
containedHeader = containedHeader->next; // advance on headers
|
containedHeader = containedHeader->next; // advance on headers
|
||||||
}
|
}
|
||||||
if (layer->cbFn != NULL) { // if defined, invoke layer callback function
|
if (layer->cbFn != NULL) { // if defined, invoke layer callback function
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
#include "../../../dynmem.h"
|
#include "../../../dynmem.h"
|
||||||
#include "../../../global_state.h"
|
#include "../../../global_state.h"
|
||||||
|
|
||||||
IPv4Assembler *ipra_new() {
|
IPv4Assembler *ipra_new(EthInterface * intf) {
|
||||||
IPv4Assembler *ipra = (IPv4Assembler *) dynmem_alloc(sizeof(IPv4Assembler));
|
IPv4Assembler *ipra = (IPv4Assembler *) dynmem_alloc(sizeof(IPv4Assembler));
|
||||||
ipra->chains = NULL;
|
ipra->chains = NULL;
|
||||||
|
ipra->intf = intf;
|
||||||
return ipra;
|
return ipra;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,8 +187,8 @@ bool ipra_try_reassemble(IPv4Assembler *ipra, uint16_t id, uint8_t **payload, ui
|
|||||||
// release chain
|
// release chain
|
||||||
ipra_remove_chain(ipra, id);
|
ipra_remove_chain(ipra, id);
|
||||||
|
|
||||||
insert_ethernet_header(p, pcktHdrLe->prev, NULL);
|
insert_ethernet_header(p, pcktHdrLe->prev, ipra->intf);
|
||||||
insert_ipv4_header(p + ETH_ETHERNET_HEADER_SIZE, pcktHdrLe, NULL);
|
insert_ipv4_header(p + ETH_ETHERNET_HEADER_SIZE, pcktHdrLe, ipra->intf);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,14 @@ typedef struct FragChainDesc_ {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FragChainDesc * chains; ///< Linked list of fragment chains
|
FragChainDesc * chains; ///< Linked list of fragment chains
|
||||||
|
struct EthInterface_ * intf; ///< Interface instantiated this reassembler
|
||||||
} IPv4Assembler;
|
} IPv4Assembler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new IPv4 packet reassembler.
|
* Create new IPv4 packet reassembler.
|
||||||
* @return pointer to newly allocated assembler
|
* @return pointer to newly allocated assembler
|
||||||
*/
|
*/
|
||||||
IPv4Assembler * ipra_new();
|
IPv4Assembler * ipra_new(struct EthInterface_ * intf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input packet packet fragment.
|
* Input packet packet fragment.
|
||||||
@ -42,7 +43,7 @@ void ipra_input(IPv4Assembler * ipra, const IPv4Props * ipProps, const uint8_t *
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to reassembly packet.
|
* Attempt to reassemble a packet.
|
||||||
* @param ipra pointer to IPv4 reassembly object
|
* @param ipra pointer to IPv4 reassembly object
|
||||||
* @param id packet sequence identification
|
* @param id packet sequence identification
|
||||||
* @param payload pointer to uint8_t* pointer; filled only on successful reassembly
|
* @param payload pointer to uint8_t* pointer; filled only on successful reassembly
|
||||||
|
31
timer.c
31
timer.c
@ -7,8 +7,6 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// FIXME nagyon bugos vagyok! Help me! :)
|
|
||||||
|
|
||||||
int64_t time_to_us(const TimePoint *t) {
|
int64_t time_to_us(const TimePoint *t) {
|
||||||
return (int64_t)t->s * 1000000 + (int64_t)t->us;
|
return (int64_t)t->s * 1000000 + (int64_t)t->us;
|
||||||
}
|
}
|
||||||
@ -65,29 +63,30 @@ static void timer_update_nearest_alarm(Timer *tmr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t t_c_us = time_to_us(&tmr->time);
|
int64_t t_c_us = time_to_us(&tmr->time); // current time in microseconds
|
||||||
int64_t min_delta_t_us = 0;
|
int64_t min_delta_t_us = 0; // minimal time difference
|
||||||
|
|
||||||
AlarmAssignment *nearest = NULL;
|
AlarmAssignment *nearest = NULL; // nearest alarm
|
||||||
for (uint32_t i = 0; i < tmr->maxSched; i++) {
|
for (uint32_t i = 0; i < tmr->maxSched; i++) {
|
||||||
int64_t t_i_us = time_to_us(&(tmr->alarms[i].time));
|
AlarmAssignment * iter = tmr->alarms + i;
|
||||||
if ((nearest == NULL) && (tmr->alarms[i].id != 0)) {
|
int64_t t_i_us = time_to_us(&(iter->time));
|
||||||
nearest = tmr->alarms + i;
|
if ((nearest == NULL) && (iter->id != 0)) { // if it's the first one
|
||||||
|
nearest = iter;
|
||||||
min_delta_t_us = t_i_us - t_c_us;
|
min_delta_t_us = t_i_us - t_c_us;
|
||||||
} else {
|
} else { // if it's not the first one
|
||||||
int64_t delta_t_us = t_i_us - t_c_us;
|
int64_t delta_t_us = t_i_us - t_c_us; // calculate time difference
|
||||||
if (delta_t_us < min_delta_t_us) {
|
if (delta_t_us < min_delta_t_us) {
|
||||||
min_delta_t_us = delta_t_us;
|
min_delta_t_us = delta_t_us; // replace minimum
|
||||||
nearest = tmr->alarms + i;
|
nearest = iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmr->nextAlarm = nearest;
|
tmr->nextAlarm = nearest; // replace next alarm
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t timer_sched(Timer *tmr, const TimePoint *t, TimerAlarmCb cb, AlarmUserData params) {
|
uint32_t timer_sched(Timer *tmr, const TimePoint *t, TimerAlarmCb cb, AlarmUserData params) {
|
||||||
if (tmr->nSched == tmr->maxSched) { // if cannot schedule more alarm
|
if (tmr->nSched == tmr->maxSched) { // if no more alarm can be scheduled
|
||||||
return TIMER_SCHED_FAILED;
|
return TIMER_SCHED_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ uint32_t timer_sched(Timer *tmr, const TimePoint *t, TimerAlarmCb cb, AlarmUserD
|
|||||||
// replace nearest if needed
|
// replace nearest if needed
|
||||||
if (tmr->nSched > 1) {
|
if (tmr->nSched > 1) {
|
||||||
timer_update_nearest_alarm(tmr);
|
timer_update_nearest_alarm(tmr);
|
||||||
} else {
|
} else { // this is merely for optimization
|
||||||
tmr->nextAlarm = slot;
|
tmr->nextAlarm = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +157,7 @@ void timer_tick(Timer *tmr, int64_t us) {
|
|||||||
/*t_us += us;
|
/*t_us += us;
|
||||||
time_from_us(&tmr->time, t_us);*/
|
time_from_us(&tmr->time, t_us);*/
|
||||||
|
|
||||||
int64_t t_us = timer_get_time_us(tmr);
|
int64_t t_us = timer_get_time_us(tmr); // convert time to microseconds
|
||||||
|
|
||||||
if ((tmr->nSched > 0) && (tmr->nextAlarm != NULL)) {
|
if ((tmr->nSched > 0) && (tmr->nextAlarm != NULL)) {
|
||||||
int64_t t_alarm = time_to_us(&(tmr->nextAlarm->time));
|
int64_t t_alarm = time_to_us(&(tmr->nextAlarm->time));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user