- add tag to CBD

- DHCP state separated
- link change handler added
- timer mutex added
This commit is contained in:
Wiesner András 2023-10-15 12:17:37 +02:00
parent ab8d45932f
commit e4d27454cd
9 changed files with 224 additions and 57 deletions

View File

@ -50,6 +50,26 @@ bool cbdt_get_connection_block(CbdTable *cbdt, cbd d, ConnBlock *connBlock) {
return true; return true;
} }
bool cbdt_set_tag(CbdTable *cbdt, cbd d, PcktSieveLayerTag tag) {
ConnBlock connBlock;
if (cbdt_get_connection_block(cbdt, d, &connBlock)) {
connBlock.sieveLayer->tag = tag;
return true;
} else {
return false;
}
}
bool cbdt_get_tag(CbdTable * cbdt, cbd d, PcktSieveLayerTag * tag) {
ConnBlock connBlock;
if (cbdt_get_connection_block(cbdt, d, &connBlock)) {
*tag = connBlock.sieveLayer->tag;
return true;
} else {
return false;
}
}
void cbdt_report(const CbdTable *cbdt) { void cbdt_report(const CbdTable *cbdt) {
INFO("CBDT listing (%d/%d):\n---------------\n\n", cbdt->level, cbdt->maxEntries); INFO("CBDT listing (%d/%d):\n---------------\n\n", cbdt->level, cbdt->maxEntries);

View File

@ -52,6 +52,24 @@ void cbdt_release(CbdTable * cbdt, cbd d);
*/ */
bool cbdt_get_connection_block(CbdTable * cbdt, cbd d, ConnBlock * connBlock); bool cbdt_get_connection_block(CbdTable * cbdt, cbd d, ConnBlock * connBlock);
/**
* Set connection block sieve tag.
* @param cbdt pointer to CBDT
* @param d CBD value
* @param tag tag getting stored
* @return operation successful (d was valid)
*/
bool cbdt_set_tag(CbdTable * cbdt, cbd d, PcktSieveLayerTag tag);
/**
* Retrieve connection block sieve tag.
* @param cbdt pointer to CBDT
* @param d CBD value
* @param tag pointer to area where tag is written
* @return operation successful (d was valid)
*/
bool cbdt_get_tag(CbdTable * cbdt, cbd d, PcktSieveLayerTag * tag);
/** /**
* Print report on connection block descriptors. * Print report on connection block descriptors.
* @param cbdt pointer to CBD table * @param cbdt pointer to CBD table

View File

@ -18,10 +18,17 @@ static int ethintf_llrxnotify(EthIODef * io) {
return 0; return 0;
} }
static int ethinf_lllinkchg(EthIODef * io, int ls) {
ethinf_set_link_state((EthInterface *) io->tag, ls);
MSG("Link state: %d\n", ls);
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;
intf->ioDef->llLinkChg = ethinf_lllinkchg;
} }
// interface processing thread // interface processing thread
@ -49,6 +56,12 @@ EthInterface *ethintf_new(EthIODef * io) {
ethIntf->capabilities = 0; ethIntf->capabilities = 0;
ethIntf->dhcp = NULL;
memset(&ethIntf->evtCbTable, 0, sizeof(EthIntfEventCbTable));
ethIntf->linkState = false;
return ethIntf; return ethIntf;
} }
@ -87,3 +100,25 @@ void ethinf_notify(EthInterface *intf) {
void ethinf_set_capabilities(EthInterface *intf, uint32_t cap) { void ethinf_set_capabilities(EthInterface *intf, uint32_t cap) {
intf->capabilities = cap; intf->capabilities = cap;
} }
void ethinf_set_event_callback(EthInterface *intf, EthIntfEvIndex idx, EthIntfEvtCb cb) {
((EthIntfEvtCb *)((&(intf->evtCbTable))))[idx] = cb;
}
void ethinf_trigger_event(EthInterface *intf, EthIntfEvIndex idx) {
EthIntfEvtCb cb = ((EthIntfEvtCb *)((&(intf->evtCbTable))))[idx];
if (cb != NULL) {
cb(intf);
}
}
void ethinf_set_link_state(EthInterface *intf, bool ls) {
if (intf->linkState != ls) { // trigger event only if state has actually changed
intf->linkState = ls;
ethinf_trigger_event(intf, ETH_EVT_LINK_CHANGE);
}
}
bool ethinf_get_link_state(EthInterface *intf) {
return intf->linkState;
}

View File

@ -1,6 +1,8 @@
#ifndef ETHERLIB_ETH_INTERFACE_H #ifndef ETHERLIB_ETH_INTERFACE_H
#define ETHERLIB_ETH_INTERFACE_H #define ETHERLIB_ETH_INTERFACE_H
#include <stdbool.h>
#include "packet_sieve.h" #include "packet_sieve.h"
#include "prefab/packet_parsers/packet_parsers.h" #include "prefab/packet_parsers/packet_parsers.h"
#include "prefab/packet_parsers/ipv4_types.h" #include "prefab/packet_parsers/ipv4_types.h"
@ -9,6 +11,7 @@
#include "msg_queue.h" #include "msg_queue.h"
#include "prefab/conn_blocks/ipv4/ip_assembler.h" #include "prefab/conn_blocks/ipv4/ip_assembler.h"
#include "etherlib_options.h" #include "etherlib_options.h"
#include "etherlib/prefab/packet_parsers/dhcp.h"
/** /**
* Ethernet interface low level definition. * Ethernet interface low level definition.
@ -38,6 +41,23 @@ typedef enum {
ETHINF_CAP_ALL_RX_TX_CHECKSUM_OFFLOADS = 0b11111, ETHINF_CAP_ALL_RX_TX_CHECKSUM_OFFLOADS = 0b11111,
} EthIntfCap; } EthIntfCap;
struct EthInterface_;
typedef void (*EthIntfEvtCb)(struct EthInterface_ * intf);
typedef enum {
ETH_EVT_LINK_CHANGE = 0,
ETH_EVT_IP_CHANGE = 1
} EthIntfEvIndex;
/**
* Ethernet interface event callback table
*/
typedef struct {
EthIntfEvtCb linkChange; ///< Link change event
EthIntfEvtCb ipChange; ///< IP-address changed
} EthIntfEventCbTable;
/** /**
* Ethernet interface representation. * Ethernet interface representation.
*/ */
@ -46,6 +66,7 @@ typedef struct EthInterface_ {
EthIODef * ioDef; ///< Low-level IO definitions EthIODef * ioDef; ///< Low-level IO definitions
EthernetAddress mac; ///< Ethernet address EthernetAddress mac; ///< Ethernet address
uint32_t capabilities; ///< Ethernet interface capabilities uint32_t capabilities; ///< Ethernet interface capabilities
DhcpState * dhcp; ///< DHCP control block (allocated only, if DHCP operation is initiated)
ip4_addr ip; ///< IP address ip4_addr ip; ///< IP address
ip4_addr router; ///< Router IP address ip4_addr router; ///< Router IP address
ip4_addr netmask; ///< Subnet mask ip4_addr netmask; ///< Subnet mask
@ -56,6 +77,8 @@ typedef struct EthInterface_ {
MsgQueue * rxQ; ///< Receive queue MsgQueue * rxQ; ///< Receive queue
ETHLIB_OS_SEM_TYPE rxSem; ///< Receive queue semaphore ETHLIB_OS_SEM_TYPE rxSem; ///< Receive queue semaphore
IPv4Assembler * ipra; ///< IPv4 reassembler IPv4Assembler * ipra; ///< IPv4 reassembler
EthIntfEventCbTable evtCbTable; ///< Event callback table
bool linkState; ///< Interface link state
} EthInterface; } EthInterface;
/** /**
@ -90,4 +113,32 @@ void ethinf_transmit(EthInterface *intf, const RawPckt *rawPckt);
*/ */
void ethinf_set_capabilities(EthInterface *intf, uint32_t cap); void ethinf_set_capabilities(EthInterface *intf, uint32_t cap);
/**
* Set Ethernet event callback.
* @param intf pointer to Ethernet interface
* @param idx index of Ethernet event
* @param cb callback function pointer
*/
void ethinf_set_event_callback(EthInterface * intf, EthIntfEvIndex idx, EthIntfEvtCb cb);
/**
* Trigger Ethernet event.
* @param intf pointer to Ethernet interface
* @param idx index of Ethernet interface event
*/
void ethinf_trigger_event(EthInterface * intf, EthIntfEvIndex idx);
/**
* Set link state.
* @param intf pointer to Ethernet interface
* @param ls link state
*/
void ethinf_set_link_state(EthInterface * intf, bool ls);
/**
* Get link state.
* @param intf pointer to Ethernet interface
*/
bool ethinf_get_link_state(EthInterface * intf);
#endif //ETHERLIB_ETH_INTERFACE_H #endif //ETHERLIB_ETH_INTERFACE_H

View File

@ -10,15 +10,6 @@
#include "../conn_blocks/udp_connblock.h" #include "../conn_blocks/udp_connblock.h"
#include "../../global_state.h" #include "../../global_state.h"
static struct {
DhcpState state;
void *buf;
cbd desc;
uint32_t tranId;
EthInterface *intf;
ETHLIB_OS_MTX_TYPE procMtx;
} s;
static const uint8_t DHCP_MAGIC_COOKIE[] = {99, 130, 83, 99}; static const uint8_t DHCP_MAGIC_COOKIE[] = {99, 130, 83, 99};
#define SNAME_LEN (64) #define SNAME_LEN (64)
@ -124,9 +115,9 @@ static const DhcpOption *dhcp_get_option(const DhcpOption *opts, DhcpOptionId id
return NULL; return NULL;
} }
static void dhcp_send(const DhcpProps *props, const DhcpOption *opts) { static void dhcp_send(DhcpState * s, const DhcpProps *props, const DhcpOption *opts) {
// construct body // construct body
uint8_t *buf = (uint8_t *) s.buf; uint8_t *buf = (uint8_t *) s->buf;
memset(buf, 0, DHCP_MIN_PACKET_SIZE); memset(buf, 0, DHCP_MIN_PACKET_SIZE);
FILL_BYTE_ADVANCE(buf, &(props->op)); FILL_BYTE_ADVANCE(buf, &(props->op));
FILL_BYTE_ADVANCE(buf, &(props->htype)); FILL_BYTE_ADVANCE(buf, &(props->htype));
@ -155,7 +146,7 @@ static void dhcp_send(const DhcpProps *props, const DhcpOption *opts) {
// dhcp_option_insert_end(&buf); // dhcp_option_insert_end(&buf);
// send packet // send packet
udp_sendto(s.desc, s.buf, DHCP_MIN_PACKET_SIZE, IPv4_ANY_ADDR, DHCP_SERVER_PORT); udp_sendto(s->desc, s->buf, DHCP_MIN_PACKET_SIZE, IPv4_ANY_ADDR, DHCP_SERVER_PORT);
} }
static void dhcp_parse(const uint8_t *buf, DhcpProps *props, DhcpOption **opts) { static void dhcp_parse(const uint8_t *buf, DhcpProps *props, DhcpOption **opts) {
@ -196,15 +187,15 @@ static void dhcp_parse(const uint8_t *buf, DhcpProps *props, DhcpOption **opts)
#define IPv4_ADDR_TO_BE_BYTES(addr) ((addr) & 0xFF), (((addr) >> 8) & 0xFF), (((addr) >> 16) & 0xFF), (((addr) >> 24) & 0xFF), #define IPv4_ADDR_TO_BE_BYTES(addr) ((addr) & 0xFF), (((addr) >> 8) & 0xFF), (((addr) >> 16) & 0xFF), (((addr) >> 24) & 0xFF),
#define HWADDR_TO_BE_BYTES(hwa) (hwa)[0], (hwa)[1], (hwa)[2], (hwa)[3], (hwa)[4], (hwa)[5], #define HWADDR_TO_BE_BYTES(hwa) (hwa)[0], (hwa)[1], (hwa)[2], (hwa)[3], (hwa)[4], (hwa)[5],
static void dhcp_discover() { static void dhcp_discover(DhcpState * s) {
s.tranId = rand(); s->tranId = rand();
DhcpProps props = {0}; DhcpProps props = {0};
props.op = DHCP_BOOTREQUEST; props.op = DHCP_BOOTREQUEST;
props.htype = DHCP_HW_TYPE_ETHERNET; props.htype = DHCP_HW_TYPE_ETHERNET;
props.hlen = 6; props.hlen = 6;
props.hops = 0; props.hops = 0;
props.xid = s.tranId; props.xid = s->tranId;
props.secs = 0; props.secs = 0;
props.flags = 0; props.flags = 0;
props.ciaddr = 0; props.ciaddr = 0;
@ -212,24 +203,24 @@ static void dhcp_discover() {
props.siaddr = 0; props.siaddr = 0;
props.giaddr = 0; props.giaddr = 0;
memcpy(props.chaddr, s.intf->mac, ETH_HW_ADDR_LEN); memcpy(props.chaddr, s->intf->mac, ETH_HW_ADDR_LEN);
DhcpOption optEnd = {DHCP_OPT_End, 0, NULL}; DhcpOption optEnd = {DHCP_OPT_End, 0, NULL};
uint16_t maxSize = 1500; // TODO... uint16_t maxSize = 1500; // TODO...
DhcpOption maxMsgSize = {DHCP_OPT_MaxMsgSize, 2, &optEnd, {UINT16_TO_BE_BYTES(maxSize)}}; DhcpOption maxMsgSize = {DHCP_OPT_MaxMsgSize, 2, &optEnd, {UINT16_TO_BE_BYTES(maxSize)}};
DhcpOption msgType = {DHCP_OPT_MsgType, 1, &maxMsgSize, {DHCPDISCOVER}}; DhcpOption msgType = {DHCP_OPT_MsgType, 1, &maxMsgSize, {DHCPDISCOVER}};
dhcp_send(&props, &msgType); dhcp_send(s, &props, &msgType);
} }
void dhcp_request(ip4_addr reqAddr, ip4_addr dhcpServerAddr) { void dhcp_request(DhcpState * s, ip4_addr reqAddr, ip4_addr dhcpServerAddr) {
DhcpProps props = {0}; DhcpProps props = {0};
props.op = DHCP_BOOTREQUEST; props.op = DHCP_BOOTREQUEST;
props.htype = DHCP_HW_TYPE_ETHERNET; props.htype = DHCP_HW_TYPE_ETHERNET;
props.hlen = 6; props.hlen = 6;
props.hops = 0; props.hops = 0;
props.xid = s.tranId; props.xid = s->tranId;
props.secs = 0; props.secs = 0;
props.flags = 0; props.flags = 0;
props.ciaddr = 0; props.ciaddr = 0;
@ -237,7 +228,7 @@ void dhcp_request(ip4_addr reqAddr, ip4_addr dhcpServerAddr) {
props.siaddr = 0; props.siaddr = 0;
props.giaddr = 0; props.giaddr = 0;
memcpy(props.chaddr, s.intf->mac, ETH_HW_ADDR_LEN); memcpy(props.chaddr, s->intf->mac, ETH_HW_ADDR_LEN);
uint16_t maxSize = 1500; // TODO... uint16_t maxSize = 1500; // TODO...
@ -245,20 +236,20 @@ void dhcp_request(ip4_addr reqAddr, ip4_addr dhcpServerAddr) {
DhcpOption paramReq = {DHCP_OPT_ParamReqList, 4, &optEnd, {1, 3, 6, 51}}; // TODO... DhcpOption paramReq = {DHCP_OPT_ParamReqList, 4, &optEnd, {1, 3, 6, 51}}; // TODO...
DhcpOption reqIp = {DHCP_OPT_RequestedIpAddress, 4, &paramReq, {IPv4_ADDR_TO_BE_BYTES(reqAddr)}}; DhcpOption reqIp = {DHCP_OPT_RequestedIpAddress, 4, &paramReq, {IPv4_ADDR_TO_BE_BYTES(reqAddr)}};
DhcpOption serverIp = {DHCP_OPT_ServerId, 4, &reqIp, {IPv4_ADDR_TO_BE_BYTES(dhcpServerAddr)}}; DhcpOption serverIp = {DHCP_OPT_ServerId, 4, &reqIp, {IPv4_ADDR_TO_BE_BYTES(dhcpServerAddr)}};
DhcpOption clId = {DHCP_OPT_ClientIdentifier, 7, &serverIp, {DHCP_HW_TYPE_ETHERNET, HWADDR_TO_BE_BYTES(s.intf->mac)}}; DhcpOption clId = {DHCP_OPT_ClientIdentifier, 7, &serverIp, {DHCP_HW_TYPE_ETHERNET, HWADDR_TO_BE_BYTES(s->intf->mac)}};
DhcpOption maxMsgSize = {DHCP_OPT_MaxMsgSize, 2, &clId, {UINT16_TO_BE_BYTES(maxSize)}}; DhcpOption maxMsgSize = {DHCP_OPT_MaxMsgSize, 2, &clId, {UINT16_TO_BE_BYTES(maxSize)}};
DhcpOption msgType = {DHCP_OPT_MsgType, 1, &maxMsgSize, {DHCPREQUEST}}; DhcpOption msgType = {DHCP_OPT_MsgType, 1, &maxMsgSize, {DHCPREQUEST}};
dhcp_send(&props, &msgType); dhcp_send(s, &props, &msgType);
} }
static void dhcp_process(DhcpProps *props, DhcpOption *opts) { static void dhcp_process(DhcpState * s, DhcpProps *props, DhcpOption *opts) {
ETHLIB_OS_MTX_LOCK(&s.procMtx); // LOCK! ETHLIB_OS_MTX_LOCK(&s->procMtx); // LOCK!
switch (s.state) { switch (s->state) {
case DHCP_INIT: case DHCP_INIT:
dhcp_discover(); // send discover message dhcp_discover(s); // send discover message
s.state = DHCP_SELECTING; s->state = DHCP_SELECTING;
break; break;
case DHCP_SELECTING: { case DHCP_SELECTING: {
const DhcpOption *msgType = dhcp_get_option(opts, DHCP_OPT_MsgType); const DhcpOption *msgType = dhcp_get_option(opts, DHCP_OPT_MsgType);
@ -268,10 +259,10 @@ static void dhcp_process(DhcpProps *props, DhcpOption *opts) {
ip4_addr serverAddr; ip4_addr serverAddr;
FETCH_DWORD(&serverAddr, serverIdentifier->value); FETCH_DWORD(&serverAddr, serverIdentifier->value);
ip4_addr addrOffer = props->yiaddr; ip4_addr addrOffer = props->yiaddr;
dhcp_request(addrOffer, serverAddr); dhcp_request(s, addrOffer, serverAddr);
} }
s.state = DHCP_REQUESTING; s->state = DHCP_REQUESTING;
} }
} }
break; break;
@ -282,16 +273,16 @@ static void dhcp_process(DhcpProps *props, DhcpOption *opts) {
//dhcp_discover(); //dhcp_discover();
//s.state = DHCP_SELECTING; //s.state = DHCP_SELECTING;
} else if (msgType == DHCPACK) { } else if (msgType == DHCPACK) {
s.intf->ip = props->yiaddr; // fetch ip address s->intf->ip = props->yiaddr; // fetch ip address
opt = dhcp_get_option(opts, DHCP_OPT_Router); // get gateway/router address opt = dhcp_get_option(opts, DHCP_OPT_Router); // get gateway/router address
FETCH_DWORD(&(s.intf->router), opt->value); FETCH_DWORD(&(s->intf->router), opt->value);
opt = dhcp_get_option(opts, DHCP_OPT_SubnetMask); // get subnet mask opt = dhcp_get_option(opts, DHCP_OPT_SubnetMask); // get subnet mask
FETCH_DWORD(&(s.intf->netmask), opt->value); FETCH_DWORD(&(s->intf->netmask), opt->value);
opt = dhcp_get_option(opts, DHCP_OPT_DomainNameServer); // get DNS opt = dhcp_get_option(opts, DHCP_OPT_DomainNameServer); // get DNS
FETCH_DWORD(&(s.intf->dns), opt->value); FETCH_DWORD(&(s->intf->dns), opt->value);
opt = dhcp_get_option(opts, DHCP_OPT_IPAddrLeaseTime); // fetch Lease Time opt = dhcp_get_option(opts, DHCP_OPT_IPAddrLeaseTime); // fetch Lease Time
uint32_t dhcpLeaseTime_s; uint32_t dhcpLeaseTime_s;
@ -302,17 +293,20 @@ static void dhcp_process(DhcpProps *props, DhcpOption *opts) {
MSG("DHCP done!\n"); MSG("DHCP done!\n");
MSG("IP: "); MSG("IP: ");
PRINT_IPv4(s.intf->ip); PRINT_IPv4(s->intf->ip);
MSG("\nRouter: "); MSG("\nRouter: ");
PRINT_IPv4(s.intf->router); PRINT_IPv4(s->intf->router);
MSG("\nNetmask: "); MSG("\nNetmask: ");
PRINT_IPv4(s.intf->netmask); PRINT_IPv4(s->intf->netmask);
MSG("\nDNS: "); MSG("\nDNS: ");
PRINT_IPv4(s.intf->dns); PRINT_IPv4(s->intf->dns);
MSG("\nLease time: %u s\n", dhcpLeaseTime_s); MSG("\nLease time: %u s\n", dhcpLeaseTime_s);
MSG("\n"); MSG("\n");
s.state = DHCP_BOUND; s->state = DHCP_BOUND;
// call event callback
ethinf_trigger_event(s->intf, ETH_EVT_IP_CHANGE);
} }
} }
break; break;
@ -320,7 +314,7 @@ static void dhcp_process(DhcpProps *props, DhcpOption *opts) {
break; break;
} }
ETHLIB_OS_MTX_UNLOCK(&s.procMtx); // RELEASE! ETHLIB_OS_MTX_UNLOCK(&s->procMtx); // RELEASE!
} }
static int dhcp_resp_cb(const Pckt *pckt, PcktSieveLayerTag tag) { static int dhcp_resp_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
@ -328,22 +322,30 @@ static int dhcp_resp_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
DhcpOption *opts = NULL; DhcpOption *opts = NULL;
dhcp_parse(pckt->payload, &props, &opts); dhcp_parse(pckt->payload, &props, &opts);
dhcp_process(&props, opts); DhcpState * s = (DhcpState *) tag.p;
dhcp_process(s, &props, opts);
dhcp_free_opt_chain(opts); dhcp_free_opt_chain(opts);
return 0; return 0;
} }
void dhcp_start() { void dhcp_start(DhcpState * s) {
s.state = DHCP_INIT; s->state = DHCP_INIT;
dhcp_process(NULL, NULL); dhcp_process(s, NULL, NULL);
} }
void dhcp_initiate(EthInterface *intf) { void dhcp_initiate(EthInterface *intf) {
ETHLIB_OS_MTX_CREATE(&s.procMtx); DhcpState * s = (DhcpState *) dynmem_alloc(sizeof(DhcpState));
s.state = DHCP_INIT;
s.buf = dynmem_alloc(DHCP_MIN_PACKET_SIZE); ETHLIB_OS_MTX_CREATE(&s->procMtx);
s.desc = udp_new_connblock(intf, IPv4_ANY_ADDR, DHCP_CLIENT_PORT, dhcp_resp_cb); s->state = DHCP_INIT;
s.intf = intf; s->buf = dynmem_alloc(DHCP_MIN_PACKET_SIZE);
s->desc = udp_new_connblock(intf, IPv4_ANY_ADDR, DHCP_CLIENT_PORT, dhcp_resp_cb);
PcktSieveLayerTag tag; // store pointer to DHCP state into UDP connection block tag
tag.p = (void *)s;
cbdt_set_tag(E.cbdt, s->desc, tag);
s->intf = intf;
intf->dhcp = s;
} }

View File

@ -2,7 +2,9 @@
#define ETHERLIB_DHCP_H #define ETHERLIB_DHCP_H
#include <stdint.h> #include <stdint.h>
#include "../../eth_interface.h" //#include "../../eth_interface.h"
#include "etherlib/cbd_table.h"
#include "etherlib_options.h"
typedef struct { typedef struct {
uint8_t op; ///< Operations uint8_t op; ///< Operations
@ -33,7 +35,7 @@ typedef enum {
DHCP_REBINDING, DHCP_REBINDING,
DHCP_BOUND, DHCP_BOUND,
DHCP_RENEWING DHCP_RENEWING
} DhcpState; } DhcpFSMState;
/** /**
* DHCP id codes. * DHCP id codes.
@ -47,15 +49,27 @@ typedef enum {
#define DHCP_CLIENT_PORT (68) #define DHCP_CLIENT_PORT (68)
#define DHCP_SERVER_PORT (67) #define DHCP_SERVER_PORT (67)
struct EthInterface_;
typedef struct {
DhcpFSMState state; ///< DHCP state machine state
void *buf; ///< Pointer to packet an allocated packet buffer
cbd desc; ///< UDP connection block descriptor
uint32_t tranId; ///< Transaction ID
struct EthInterface_ *intf; ///< Pointer to corresponding Ethernet interface
ETHLIB_OS_MTX_TYPE procMtx; ///< Mutex protecting the state machine
} DhcpState;
/** /**
* Initiate DHCP on interface * Initiate DHCP on interface
* @param intf interface * @param intf interface
*/ */
void dhcp_initiate(EthInterface * intf); void dhcp_initiate(struct EthInterface_ * intf);
/** /**
* * Start DHCP operation.
* @param s pointer to DhcpState structure
*/ */
void dhcp_start(); void dhcp_start(DhcpState * s);
#endif //ETHERLIB_DHCP_H #endif //ETHERLIB_DHCP_H

30
timer.c
View File

@ -26,6 +26,7 @@ Timer *timer_new(uint32_t maxSched) {
Timer * tmr = (Timer *) dynmem_alloc(sizeof(Timer) + maxSched * sizeof(AlarmAssignment)); Timer * tmr = (Timer *) dynmem_alloc(sizeof(Timer) + maxSched * sizeof(AlarmAssignment));
ASSERT_NULL(tmr); ASSERT_NULL(tmr);
ETHLIB_OS_MTX_CREATE(&tmr->tabMtx);
tmr->maxSched = maxSched; tmr->maxSched = maxSched;
tmr->nSched = 0; tmr->nSched = 0;
tmr->nextAlarm = NULL; tmr->nextAlarm = NULL;
@ -87,6 +88,8 @@ uint32_t timer_sched(Timer * tmr, const TimePoint * t, TimerAlarmCb cb, AlarmUse
return TIMER_SCHED_FAILED; return TIMER_SCHED_FAILED;
} }
ETHLIB_OS_MTX_LOCK(&(tmr->tabMtx));
// if we can schedule get the first unused block // if we can schedule get the first unused block
AlarmAssignment * slot = timer_get_alarm_by_id(tmr, 0); AlarmAssignment * slot = timer_get_alarm_by_id(tmr, 0);
@ -106,6 +109,10 @@ uint32_t timer_sched(Timer * tmr, const TimePoint * t, TimerAlarmCb cb, AlarmUse
tmr->nextAlarm = slot; tmr->nextAlarm = slot;
} }
timer_report(tmr);
ETHLIB_OS_MTX_UNLOCK(&(tmr->tabMtx));
return slot->id; return slot->id;
} }
@ -116,11 +123,15 @@ uint32_t timer_sched_rel(Timer * tmr, int64_t us, TimerAlarmCb cb, AlarmUserData
} }
void timer_unsched(Timer * tmr, uint32_t id) { void timer_unsched(Timer * tmr, uint32_t id) {
ETHLIB_OS_MTX_LOCK(&(tmr->tabMtx));
AlarmAssignment * alarm = timer_get_alarm_by_id(tmr, id); AlarmAssignment * alarm = timer_get_alarm_by_id(tmr, id);
if (alarm != NULL) { if (alarm != NULL) {
memset(alarm, 0, sizeof(AlarmAssignment)); memset(alarm, 0, sizeof(AlarmAssignment));
tmr->nSched--; tmr->nSched--;
} }
ETHLIB_OS_MTX_UNLOCK(&(tmr->tabMtx));
} }
void timer_set_time(Timer *tmr, const TimePoint *t) { void timer_set_time(Timer *tmr, const TimePoint *t) {
@ -146,11 +157,15 @@ void timer_tick(Timer * tmr, int64_t us) {
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));
while (((t_alarm - t_us) <= 0) && (tmr->nSched > 0)) { while (((t_alarm - t_us) <= 0) && (tmr->nSched > 0)) {
// invoke callback if (ETHLIB_OS_MTX_LOCK(&(tmr->tabMtx)) != 0) {
if (tmr->nextAlarm->cb != NULL) { return; // break from the loop, since we cannot lock the mutex
tmr->nextAlarm->cb(tmr, tmr->nextAlarm->params);
} }
timer_report(tmr);
// fetch alarm (obtain a COPY)
AlarmAssignment alarm = *(tmr->nextAlarm);
// clear alarm descriptor // clear alarm descriptor
memset(tmr->nextAlarm, 0, sizeof(AlarmAssignment)); memset(tmr->nextAlarm, 0, sizeof(AlarmAssignment));
@ -159,11 +174,20 @@ void timer_tick(Timer * tmr, int64_t us) {
// update nearest alarm // update nearest alarm
timer_update_nearest_alarm(tmr); timer_update_nearest_alarm(tmr);
ETHLIB_OS_MTX_UNLOCK(&(tmr->tabMtx));
// invoke callback
if (alarm.cb != NULL) {
alarm.cb(tmr, alarm.params);
}
if (tmr->nextAlarm != NULL) { if (tmr->nextAlarm != NULL) {
t_alarm = time_to_us(&(tmr->nextAlarm->time)); t_alarm = time_to_us(&(tmr->nextAlarm->time));
} }
} }
} }
} }
void timer_report(const Timer * tmr) { void timer_report(const Timer * tmr) {

View File

@ -4,6 +4,8 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <etherlib_options.h>
/** /**
* A single point in time * A single point in time
*/ */
@ -61,6 +63,7 @@ typedef struct {
* Timer class * Timer class
*/ */
typedef struct Timer_ { typedef struct Timer_ {
ETHLIB_OS_MTX_TYPE tabMtx; ///< Mutex protecting the scheduling table
TimePoint time; ///< Absolute time TimePoint time; ///< Absolute time
AlarmAssignment * nextAlarm; ///< Nearest alarm AlarmAssignment * nextAlarm; ///< Nearest alarm
uint32_t maxSched; ///< Maximum number of scheduled alarms uint32_t maxSched; ///< Maximum number of scheduled alarms

View File

@ -39,7 +39,7 @@
#define IPv4(a,b,c,d) ((a) | (b << 8) | (c << 16) | (d << 24)) #define IPv4(a,b,c,d) ((a) | (b << 8) | (c << 16) | (d << 24))
#define PRINT_IPv4(ip) MSG("%u.%u.%u.%u", (ip & 0xFF), ((ip >> 8) & 0xFF), ((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)) #define PRINT_IPv4(ip) MSG("%u.%u.%u.%u", (ip & 0xFF), ((ip >> 8) & 0xFF), ((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF))
#define PRINT_HWADDR(hwaddr) MSG("%02x:%02x:%02x:%02x:%02x:%02x", (hwaddr)[0], (hwaddr)[1], (hwaddr)[2], (hwaddr)[3], (hwaddr)[4], (hwaddr)[5]); #define PRINT_HWADDR(hwaddr) MSG("%02x:%02x:%02x:%02x:%02x:%02x", (hwaddr)[0], (hwaddr)[1], (hwaddr)[2], (hwaddr)[3], (hwaddr)[4], (hwaddr)[5])
#define ASSERT_BAD_ALIGN(p) if ((size_t)(p) & 0b11) ERROR("Bad memory alignment in function '%s' in file '%s' on line %d!\n", __func__, __FILE__, __LINE__) #define ASSERT_BAD_ALIGN(p) if ((size_t)(p) & 0b11) ERROR("Bad memory alignment in function '%s' in file '%s' on line %d!\n", __func__, __FILE__, __LINE__)
#define ASSERT_NULL(p) if ((p) == NULL) ERROR("NULL in function '%s' in file '%s' on line %d!\n", __func__, __FILE__, __LINE__) #define ASSERT_NULL(p) if ((p) == NULL) ERROR("NULL in function '%s' in file '%s' on line %d!\n", __func__, __FILE__, __LINE__)