Skip to content

Commit

Permalink
pkg/lwip: add support for netdev_driver_t::confirm_send
Browse files Browse the repository at this point in the history
  • Loading branch information
maribu committed Apr 30, 2024
1 parent 9462ab5 commit 28f412f
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 14 deletions.
109 changes: 96 additions & 13 deletions pkg/lwip/contrib/netdev/lwip_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@
#include "netif/etharp.h"
#include "netif/lowpan6.h"
#include "thread.h"
#include "thread_flags.h"
#include "utlist.h"

#define ENABLE_DEBUG 0
#include "debug.h"

#define LWIP_NETDEV_NAME "lwip_netdev_mux"
#define LWIP_NETDEV_PRIO (THREAD_PRIORITY_MAIN - 4)
#define LWIP_NETDEV_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#define LWIP_NETDEV_MSG_TYPE_EVENT 0x1235
#define LWIP_NETDEV_MSG_TYPE_EVENT 0x1235

#define ETHERNET_IFNAME1 'E'
#define ETHERNET_IFNAME2 'T'
Expand All @@ -52,6 +54,7 @@
#define WPAN_IFNAME2 'P'

event_queue_t lwip_event_queue = { 0 };
#define THREAD_FLAG_LWIP_TX_DONE (1U << 11)

static kernel_pid_t _pid = KERNEL_PID_UNDEF;
static WORD_ALIGNED char _stack[LWIP_NETDEV_STACKSIZE];
Expand All @@ -76,6 +79,19 @@ static void _event_cb(netdev_t *dev, netdev_event_t event);
static void *_event_loop(void *arg);
static void _isr(event_t *ev);

bool is_netdev_legacy_api(netdev_t *netdev)
{
static_assert(IS_USED(MODULE_NETDEV_NEW_API) || IS_USED(MODULE_NETDEV_LEGACY_API),
"used netdev misses dependency to netdev_legacy_api");
if (!IS_USED(MODULE_NETDEV_NEW_API)) {
return true;
}
if (!IS_USED(MODULE_NETDEV_LEGACY_API)) {
return false;
}
return (netdev->driver->confirm_send == NULL);
}

err_t lwip_netdev_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
Expand Down Expand Up @@ -254,6 +270,65 @@ err_t lwip_netdev_init(struct netif *netif)
return res;
}

#if (IS_USED(MODULE_NETDEV_NEW_API))
static err_t _common_link_output(struct netif *netif, netdev_t *netdev, iolist_t *iolist)
{
lwip_netif_dev_acquire(netif);

if (is_netdev_legacy_api(netdev)) {
err_t res = (netdev->driver->send(netdev, iolist) > 0) ? ERR_OK : ERR_BUF;
lwip_netif_dev_release(netif);
return res;
}

unsigned irq_state;
lwip_netif_t *compat_netif = container_of(netif, lwip_netif_t, lwip_netif);

irq_state = irq_disable();
compat_netif->thread_doing_tx = thread_get_active();
irq_restore(irq_state);

if (netdev->driver->send(netdev, iolist) < 0) {
lwip_netif_dev_release(netif);
irq_state = irq_disable();
compat_netif->thread_doing_tx = NULL;
irq_restore(irq_state);
return ERR_IF;
}

/* block until TX completion is signaled from IRQ */
thread_flags_wait_any(THREAD_FLAG_LWIP_TX_DONE);

irq_state = irq_disable();
compat_netif->thread_doing_tx = NULL;
irq_restore(irq_state);

int retval;
while (-EAGAIN == (retval = netdev->driver->confirm_send(netdev, NULL))) {
/* this should not happen, as the driver really only should emit the
* TX done event when it is actually done. But better be safe than
* sorry */
DEBUG_PUTS("[lwip_netdev] confirm_send() returned -EAGAIN\n");
}

lwip_netif_dev_release(netif);

if (retval < 0) {
return ERR_IF;
}

return ERR_OK;
}
#else /* only old API */
static err_t _common_link_output(struct netif *netif, netdev_t *netdev, iolist_t *iolist)
{
lwip_netif_dev_acquire(netif);
err_t res = (netdev->driver->send(netdev, iolist) > 0) ? ERR_OK : ERR_BUF;
lwip_netif_dev_release(netif);
return res;
}
#endif

#ifdef MODULE_NETDEV_ETH
static err_t _eth_link_output(struct netif *netif, struct pbuf *p)
{
Expand Down Expand Up @@ -282,10 +357,7 @@ static err_t _eth_link_output(struct netif *netif, struct pbuf *p)
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
lwip_netif_dev_acquire(netif);
err_t res = (netdev->driver->send(netdev, iolist) >= 0) ? ERR_OK : ERR_BUF;
lwip_netif_dev_release(netif);
return res;
return _common_link_output(netif, netdev, iolist);
}
#endif

Expand All @@ -299,10 +371,7 @@ static err_t _ieee802154_link_output(struct netif *netif, struct pbuf *p)
.iol_len = (p->len - IEEE802154_FCS_LEN), /* FCS is written by driver */
};

lwip_netif_dev_acquire(netif);
err_t res = (netdev->driver->send(netdev, &pkt) >= 0) ? ERR_OK : ERR_BUF;
lwip_netif_dev_release(netif);
return res;
return _common_link_output(netif, netdev, &pkt);
}
#endif

Expand Down Expand Up @@ -331,10 +400,7 @@ static err_t _slip_link_output(struct netif *netif, struct pbuf *p)
.iol_len = p->len,
};

lwip_netif_dev_acquire(netif);
err_t res = (netdev->driver->send(netdev, &pkt) >= 0) ? ERR_OK : ERR_BUF;
lwip_netif_dev_release(netif);
return res;
return _common_link_output(netif, netdev, &pkt);
}
#endif

Expand Down Expand Up @@ -369,9 +435,24 @@ static void _event_cb(netdev_t *dev, netdev_event_t event)

switch (event) {
case NETDEV_EVENT_ISR:
DEBUG_PUTS("[lwip_netdev] NETDEV_EVENT_ISR");
event_post(&lwip_event_queue, &compat_netif->ev_isr);
break;
#if (IS_USED(MODULE_NETDEV_NEW_API))
case NETDEV_EVENT_TX_COMPLETE:
DEBUG_PUTS("[lwip_netdev] NETDEV_EVENT_TX_COMPLETE");
{
unsigned irq_state = irq_disable();
thread_t *target = compat_netif->thread_doing_tx;
irq_restore(irq_state);
if (target) {
thread_flags_set(target, THREAD_FLAG_LWIP_TX_DONE);
}
}
break;
#endif
case NETDEV_EVENT_RX_COMPLETE:
DEBUG_PUTS("[lwip_netdev] NETDEV_EVENT_RX_COMPLETE");
{
struct pbuf *p = _get_recv_pkt(dev);
if (p == NULL) {
Expand All @@ -385,10 +466,12 @@ static void _event_cb(netdev_t *dev, netdev_event_t event)
}
break;
case NETDEV_EVENT_LINK_UP:
DEBUG_PUTS("[lwip_netdev] NETDEV_EVENT_LINK_UP");
/* Will wake up DHCP state machine */
netifapi_netif_set_link_up(netif);
break;
case NETDEV_EVENT_LINK_DOWN:
DEBUG_PUTS("[lwip_netdev] NETDEV_EVENT_LINK_DOWN");
netifapi_netif_set_link_down(netif);
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion pkg/lwip/contrib/sys_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg,
return res;
}

static kernel_pid_t lwip_tcpip_thread = KERNEL_PID_UNDEF;
kernel_pid_t lwip_tcpip_thread = KERNEL_PID_UNDEF;
static kernel_pid_t lwip_lock_thread;

void sys_mark_tcpip_thread(void) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/lwip/include/arch/sys_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ static inline void sys_mbox_set_invalid(sys_mbox_t *mbox)

typedef kernel_pid_t sys_thread_t; /**< Platform specific thread type */

extern kernel_pid_t lwip_tcpip_thread; /**< PID of the lwIP TCP/IP thread */

/**
* @name Functions for locking/unlocking core to assure thread safety.
* @{
Expand Down
3 changes: 3 additions & 0 deletions pkg/lwip/include/lwip/netif/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ typedef struct {
#ifdef MODULE_BHP_EVENT
bhp_event_t bhp; /**< IPC Bottom Half Processor */
#endif
#if (IS_USED(MODULE_NETDEV_NEW_API))
thread_t *thread_doing_tx; /**< The thread currently doing TX */
#endif
} lwip_netif_t;

/**
Expand Down

0 comments on commit 28f412f

Please sign in to comment.