diff --git a/examples/rp2040/pico-w5500/CMakeLists.txt b/examples/rp2040/pico-w5500/CMakeLists.txt index 2d1e1199..c554cf74 100644 --- a/examples/rp2040/pico-w5500/CMakeLists.txt +++ b/examples/rp2040/pico-w5500/CMakeLists.txt @@ -18,6 +18,6 @@ pico_enable_stdio_uart(firmware 1) add_definitions(-DMG_ARCH=MG_ARCH_RP2040) add_definitions(-DMG_ENABLE_TCPIP=1) add_definitions(-DMG_ENABLE_PACKED_FS=1) -add_definitions(-DMG_ENABLE_MBEDTLS=1) +add_definitions(-DMG_ENABLE_MBEDTLS=0) # TODO(cpq): enable add_definitions(-DMG_ENABLE_CUSTOM_RANDOM=1) add_definitions(-DMG_ENABLE_FILE=0) diff --git a/mongoose.c b/mongoose.c index 7e0dc78c..7a0971c9 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6060,6 +6060,13 @@ size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op) { #endif +/* + * Todo + * This driver doesn't support 10M line autoconfiguration yet. + * Packets aren't sent if the link negociated 10M line. + * todo: MAC back auto reconfiguration. + */ + #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT1020) struct imx_rt1020_enet { volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3], ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR, RESERVED6[15], TCR, RESERVED7[7], PALR, PAUR, OPD, TXIC0, TXIC1, TXIC2, RESERVED8, RXIC0, RXIC1, RXIC2, RESERVED9[3], IAUR, IALR, GAUR, GALR, RESERVED10[7], TFWR, RESERVED11[14], RDSR, TDSR, MRBR[2], RSFL, RSEM, RAEM, RAFL, TSEM, TAEM, TAFL, TIPG, FTRL, RESERVED12[3], TACC, RACC, RESERVED13[15], RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT, RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG, RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255, RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2048, RMON_T_GTE2048, RMON_T_OCTETS, IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL, IEEE_T_DEF, IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR, IEEE_T_SQE, IEEE_T_FDXFC, IEEE_T_OCTETS_OK, RESERVED14[3], RMON_R_PACKETS, RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN, RMON_R_UNDERSIZE, RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB, RESERVED15, RMON_R_P64, RMON_R_P65TO127, RMON_R_P128TO255, RMON_R_P256TO511, RMON_R_P512TO1023, RMON_R_P1024TO2047, RMON_R_GTE2048, RMON_R_OCTETS, IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, IEEE_R_FDXFC, IEEE_R_OCTETS_OK, RESERVED16[71], ATCR, ATVR, ATOFF, ATPER, ATCOR, ATINC, ATSTMP, RESERVED17[122], TGSR, TCSR0, TCCR0, TCSR1, TCCR1, TCSR2, TCCR2, TCSR3; @@ -6237,8 +6244,6 @@ static bool mg_tcpip_driver_imxrt1020_init(struct mg_tcpip_if *ifp) { // RX Descriptor activation ENET->RDAR = BIT(24); // Activate Receive Descriptor - - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -6291,8 +6296,11 @@ void ENET_IRQHandler(void) { else { // Frame received, loop for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever if (rx_buffer_descriptor[s_rt1020_rxno].control & BIT(15)) break; // exit when done - uint32_t len = (rx_buffer_descriptor[s_rt1020_rxno].length); - mg_tcpip_qwrite(rx_buffer_descriptor[s_rt1020_rxno].buffer, len > 4 ? len - 4 : len, s_ifp); + // Process if CRC OK and frame not truncated + if (!(rx_buffer_descriptor[s_rt1020_rxno].control & (BIT(2) | BIT(0)))) { + uint32_t len = (rx_buffer_descriptor[s_rt1020_rxno].length); + mg_tcpip_qwrite(rx_buffer_descriptor[s_rt1020_rxno].buffer, len > 4 ? len - 4 : len, s_ifp); + } rx_buffer_descriptor[s_rt1020_rxno].control |= BIT(15); // Inform DMA RX is empty if (++s_rt1020_rxno >= ENET_RXBD_NUM) s_rt1020_rxno = 0; } @@ -6310,7 +6318,7 @@ static bool mg_tcpip_driver_imxrt1020_up(struct mg_tcpip_if *ifp) { // API struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = { - mg_tcpip_driver_imxrt1020_init, mg_tcpip_driver_imxrt1020_tx, mg_tcpip_driver_rx, + mg_tcpip_driver_imxrt1020_init, mg_tcpip_driver_imxrt1020_tx, NULL, mg_tcpip_driver_imxrt1020_up}; #endif @@ -6470,7 +6478,6 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) { ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) | ((uint32_t) ifp->mac[2] << 16) | ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -6532,9 +6539,9 @@ void ETH_IRQHandler(void) { ETH->DMARPDR = 0; // and resume RX } -struct mg_tcpip_driver mg_tcpip_driver_stm32 = { - mg_tcpip_driver_stm32_init, mg_tcpip_driver_stm32_tx, mg_tcpip_driver_rx, - mg_tcpip_driver_stm32_up}; +struct mg_tcpip_driver mg_tcpip_driver_stm32 = {mg_tcpip_driver_stm32_init, + mg_tcpip_driver_stm32_tx, NULL, + mg_tcpip_driver_stm32_up}; #endif #ifdef MG_ENABLE_LINES @@ -6745,7 +6752,6 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) { ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) | ((uint32_t) ifp->mac[2] << 16) | ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -6813,7 +6819,7 @@ void ETH_IRQHandler(void) { } struct mg_tcpip_driver mg_tcpip_driver_stm32h = { - mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, mg_tcpip_driver_rx, + mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, NULL, mg_tcpip_driver_stm32h_up}; #endif @@ -7000,8 +7006,6 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) { ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; // NOTE(scaprile) There are 3 additional slots for filtering, disabled by // default. This also applies to the STM32 driver (at least for F7) - - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -7067,9 +7071,9 @@ void EMAC0_IRQHandler(void) { EMAC->EMACRXPOLLD = 0; // and resume RX } -struct mg_tcpip_driver mg_tcpip_driver_tm4c = { - mg_tcpip_driver_tm4c_init, mg_tcpip_driver_tm4c_tx, mg_tcpip_driver_rx, - mg_tcpip_driver_tm4c_up}; +struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init, + mg_tcpip_driver_tm4c_tx, NULL, + mg_tcpip_driver_tm4c_up}; #endif #ifdef MG_ENABLE_LINES @@ -7298,53 +7302,9 @@ struct pkt { struct dhcp *dhcp; }; -static void q_copyin(struct queue *q, const uint8_t *buf, size_t len, - size_t head) { - size_t left = q->len - head; - memcpy(&q->buf[head], buf, left < len ? left : len); - if (left < len) memcpy(q->buf, &buf[left], len - left); -} - -static void q_copyout(struct queue *q, uint8_t *buf, size_t len, size_t tail) { - size_t left = q->len - tail; - memcpy(buf, &q->buf[tail], left < len ? left : len); - if (left < len) memcpy(&buf[left], q->buf, len - left); -} - -static bool q_write(struct queue *q, const void *buf, size_t len) { - bool success = false; - size_t left = (q->len - q->head + q->tail - 1) % q->len; - if (len + sizeof(size_t) <= left) { - q_copyin(q, (uint8_t *) &len, sizeof(len), q->head); - q_copyin(q, (uint8_t *) buf, len, (q->head + sizeof(size_t)) % q->len); - q->head = (q->head + sizeof(len) + len) % q->len; - success = true; - } - return success; -} - -static inline size_t q_avail(struct queue *q) { - size_t n = 0; - if (q->tail != q->head) q_copyout(q, (uint8_t *) &n, sizeof(n), q->tail); - return n; -} - -static size_t q_read(struct queue *q, void *buf) { - size_t n = q_avail(q); - if (n > 0) { - q_copyout(q, (uint8_t *) buf, n, (q->tail + sizeof(n)) % q->len); - q->tail = (q->tail + sizeof(n) + n) % q->len; - } - return n; -} - -static struct mg_str mkstr(void *buf, size_t len) { - struct mg_str str = {(char *) buf, len}; - return str; -} - static void mkpay(struct pkt *pkt, void *p) { - pkt->pay = mkstr(p, (size_t) (&pkt->raw.ptr[pkt->raw.len] - (char *) p)); + pkt->pay = + mg_str_n((char *) p, (size_t) (&pkt->raw.ptr[pkt->raw.len] - (char *) p)); } static uint32_t csumup(uint32_t sum, const void *buf, size_t len) { @@ -7960,9 +7920,17 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { if (ifp->ip == 0 && expired_1000ms) tx_dhcp_discover(ifp); // Read data from the network - size_t len = ifp->driver->rx((void *) ifp->rx.ptr, ifp->rx.len, ifp); - if (len) { - mg_tcpip_rx(ifp, (void *) ifp->rx.ptr, len); + if (ifp->driver->rx != NULL) { // Polling driver. We must call it + size_t len = + ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp); + if (len > 0) mg_tcpip_rx(ifp, ifp->recv_queue.buf, len); + } else { // Interrupt-based driver. Fills recv queue itself + char *buf; + size_t len = mg_queue_next(&ifp->recv_queue, &buf); + if (len > 0) { + mg_tcpip_rx(ifp, buf, len); + mg_queue_del(&ifp->recv_queue, len); + } } // Process timeouts @@ -7993,20 +7961,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { // somewhere fast. Note that newlib's malloc is not thread safe, thus use // our lock-free queue with preallocated buffer to copy data and return asap void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp) { - if (q_write(&ifp->queue, buf, len)) { + char *p; + if (mg_queue_book(&ifp->recv_queue, &p, len) >= len) { + memcpy(p, buf, len); + mg_queue_add(&ifp->recv_queue, len); ifp->nrecv++; } else { ifp->ndrop++; } } -size_t mg_tcpip_qread(void *buf, struct mg_tcpip_if *ifp) { - return q_read(&ifp->queue, buf); -} - size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) { - return mg_tcpip_qread((void *) ifp->rx.ptr, ifp); - (void) len, (void) buf; + (void) buf, (void) len, (void) ifp; + return 0; } void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { @@ -8021,10 +7988,10 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { if (ifp->driver->init && !ifp->driver->init(ifp)) { MG_ERROR(("driver init failed")); } else { - size_t maxpktsize = 1540; - ifp->rx.ptr = (char *) calloc(1, maxpktsize), ifp->rx.len = maxpktsize; - ifp->tx.ptr = (char *) calloc(1, maxpktsize), ifp->tx.len = maxpktsize; - if (ifp->queue.len) ifp->queue.buf = (uint8_t *) calloc(1, ifp->queue.len); + size_t framesize = 1540; + ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize; + ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192; + ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size); ifp->timer_1000ms = mg_millis(); mgr->priv = ifp; ifp->mgr = mgr; @@ -8038,7 +8005,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { } void mg_tcpip_free(struct mg_tcpip_if *ifp) { - free((char *) ifp->rx.ptr); + free(ifp->recv_queue.buf); free((char *) ifp->tx.ptr); } diff --git a/mongoose.h b/mongoose.h index 6b6cfd56..6bc4bce9 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1502,6 +1502,7 @@ void mg_rpc_list(struct mg_rpc_req *r); + struct mg_tcpip_if; // MIP network interface struct mg_tcpip_driver { @@ -1511,27 +1512,17 @@ struct mg_tcpip_driver { bool (*up)(struct mg_tcpip_if *); // Up/down status }; -// Receive queue - single producer, single consumer queue. Interrupt-based -// drivers copy received frames to the queue in interrupt context. -// mg_tcpip_poll() function runs in event loop context, reads from the queue -struct queue { - uint8_t *buf; - size_t len; - volatile size_t tail, head; -}; - // Network interface struct mg_tcpip_if { uint8_t mac[6]; // MAC address. Must be set to a valid MAC uint32_t ip, mask, gw; // IP address, mask, default gateway - struct mg_str rx; // Output (TX) buffer - struct mg_str tx; // Input (RX) buffer + struct mg_str tx; // Output (TX) buffer bool enable_dhcp_client; // Enable DCHP client bool enable_dhcp_server; // Enable DCHP server struct mg_tcpip_driver *driver; // Low level driver void *driver_data; // Driver-specific data struct mg_mgr *mgr; // Mongoose event manager - struct queue queue; // Set queue.len for interrupt based drivers + struct mg_queue recv_queue; // Receive queue // Internal state, user can use it but should not change it uint8_t gwmac[6]; // Router's MAC @@ -1560,7 +1551,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_stm32; extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; -extern struct mg_tcpip_driver mg_tcpip_driver_imxrt1020; +extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; // Drivers that require SPI, can use this SPI abstraction struct mg_tcpip_spi { diff --git a/src/tcpip/driver_nxpimxrt1020.c b/src/tcpip/driver_nxpimxrt1020.c index 5a677d52..7eaec4a5 100644 --- a/src/tcpip/driver_nxpimxrt1020.c +++ b/src/tcpip/driver_nxpimxrt1020.c @@ -184,8 +184,6 @@ static bool mg_tcpip_driver_imxrt1020_init(struct mg_tcpip_if *ifp) { // RX Descriptor activation ENET->RDAR = BIT(24); // Activate Receive Descriptor - - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -260,7 +258,7 @@ static bool mg_tcpip_driver_imxrt1020_up(struct mg_tcpip_if *ifp) { // API struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = { - mg_tcpip_driver_imxrt1020_init, mg_tcpip_driver_imxrt1020_tx, mg_tcpip_driver_rx, + mg_tcpip_driver_imxrt1020_init, mg_tcpip_driver_imxrt1020_tx, NULL, mg_tcpip_driver_imxrt1020_up}; #endif diff --git a/src/tcpip/driver_stm32.c b/src/tcpip/driver_stm32.c index a1f19d84..0cb74cb4 100644 --- a/src/tcpip/driver_stm32.c +++ b/src/tcpip/driver_stm32.c @@ -150,7 +150,6 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) { ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) | ((uint32_t) ifp->mac[2] << 16) | ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -212,7 +211,7 @@ void ETH_IRQHandler(void) { ETH->DMARPDR = 0; // and resume RX } -struct mg_tcpip_driver mg_tcpip_driver_stm32 = { - mg_tcpip_driver_stm32_init, mg_tcpip_driver_stm32_tx, mg_tcpip_driver_rx, - mg_tcpip_driver_stm32_up}; +struct mg_tcpip_driver mg_tcpip_driver_stm32 = {mg_tcpip_driver_stm32_init, + mg_tcpip_driver_stm32_tx, NULL, + mg_tcpip_driver_stm32_up}; #endif diff --git a/src/tcpip/driver_stm32h.c b/src/tcpip/driver_stm32h.c index e332c026..5c5b3d20 100644 --- a/src/tcpip/driver_stm32h.c +++ b/src/tcpip/driver_stm32h.c @@ -203,7 +203,6 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) { ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) | ((uint32_t) ifp->mac[2] << 16) | ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -271,6 +270,6 @@ void ETH_IRQHandler(void) { } struct mg_tcpip_driver mg_tcpip_driver_stm32h = { - mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, mg_tcpip_driver_rx, + mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, NULL, mg_tcpip_driver_stm32h_up}; #endif diff --git a/src/tcpip/driver_tm4c.c b/src/tcpip/driver_tm4c.c index dcc21b15..f7a5d937 100644 --- a/src/tcpip/driver_tm4c.c +++ b/src/tcpip/driver_tm4c.c @@ -178,8 +178,6 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) { ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; // NOTE(scaprile) There are 3 additional slots for filtering, disabled by // default. This also applies to the STM32 driver (at least for F7) - - if (ifp->queue.len == 0) ifp->queue.len = 8192; return true; } @@ -245,7 +243,7 @@ void EMAC0_IRQHandler(void) { EMAC->EMACRXPOLLD = 0; // and resume RX } -struct mg_tcpip_driver mg_tcpip_driver_tm4c = { - mg_tcpip_driver_tm4c_init, mg_tcpip_driver_tm4c_tx, mg_tcpip_driver_rx, - mg_tcpip_driver_tm4c_up}; +struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init, + mg_tcpip_driver_tm4c_tx, NULL, + mg_tcpip_driver_tm4c_up}; #endif diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index 85c2f3d2..5273f608 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -128,53 +128,9 @@ struct pkt { struct dhcp *dhcp; }; -static void q_copyin(struct queue *q, const uint8_t *buf, size_t len, - size_t head) { - size_t left = q->len - head; - memcpy(&q->buf[head], buf, left < len ? left : len); - if (left < len) memcpy(q->buf, &buf[left], len - left); -} - -static void q_copyout(struct queue *q, uint8_t *buf, size_t len, size_t tail) { - size_t left = q->len - tail; - memcpy(buf, &q->buf[tail], left < len ? left : len); - if (left < len) memcpy(&buf[left], q->buf, len - left); -} - -static bool q_write(struct queue *q, const void *buf, size_t len) { - bool success = false; - size_t left = (q->len - q->head + q->tail - 1) % q->len; - if (len + sizeof(size_t) <= left) { - q_copyin(q, (uint8_t *) &len, sizeof(len), q->head); - q_copyin(q, (uint8_t *) buf, len, (q->head + sizeof(size_t)) % q->len); - q->head = (q->head + sizeof(len) + len) % q->len; - success = true; - } - return success; -} - -static inline size_t q_avail(struct queue *q) { - size_t n = 0; - if (q->tail != q->head) q_copyout(q, (uint8_t *) &n, sizeof(n), q->tail); - return n; -} - -static size_t q_read(struct queue *q, void *buf) { - size_t n = q_avail(q); - if (n > 0) { - q_copyout(q, (uint8_t *) buf, n, (q->tail + sizeof(n)) % q->len); - q->tail = (q->tail + sizeof(n) + n) % q->len; - } - return n; -} - -static struct mg_str mkstr(void *buf, size_t len) { - struct mg_str str = {(char *) buf, len}; - return str; -} - static void mkpay(struct pkt *pkt, void *p) { - pkt->pay = mkstr(p, (size_t) (&pkt->raw.ptr[pkt->raw.len] - (char *) p)); + pkt->pay = + mg_str_n((char *) p, (size_t) (&pkt->raw.ptr[pkt->raw.len] - (char *) p)); } static uint32_t csumup(uint32_t sum, const void *buf, size_t len) { @@ -790,9 +746,17 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { if (ifp->ip == 0 && expired_1000ms) tx_dhcp_discover(ifp); // Read data from the network - size_t len = ifp->driver->rx((void *) ifp->rx.ptr, ifp->rx.len, ifp); - if (len) { - mg_tcpip_rx(ifp, (void *) ifp->rx.ptr, len); + if (ifp->driver->rx != NULL) { // Polling driver. We must call it + size_t len = + ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp); + if (len > 0) mg_tcpip_rx(ifp, ifp->recv_queue.buf, len); + } else { // Interrupt-based driver. Fills recv queue itself + char *buf; + size_t len = mg_queue_next(&ifp->recv_queue, &buf); + if (len > 0) { + mg_tcpip_rx(ifp, buf, len); + mg_queue_del(&ifp->recv_queue, len); + } } // Process timeouts @@ -823,20 +787,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { // somewhere fast. Note that newlib's malloc is not thread safe, thus use // our lock-free queue with preallocated buffer to copy data and return asap void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp) { - if (q_write(&ifp->queue, buf, len)) { + char *p; + if (mg_queue_book(&ifp->recv_queue, &p, len) >= len) { + memcpy(p, buf, len); + mg_queue_add(&ifp->recv_queue, len); ifp->nrecv++; } else { ifp->ndrop++; } } -size_t mg_tcpip_qread(void *buf, struct mg_tcpip_if *ifp) { - return q_read(&ifp->queue, buf); -} - size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) { - return mg_tcpip_qread((void *) ifp->rx.ptr, ifp); - (void) len, (void) buf; + (void) buf, (void) len, (void) ifp; + return 0; } void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { @@ -851,10 +814,10 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { if (ifp->driver->init && !ifp->driver->init(ifp)) { MG_ERROR(("driver init failed")); } else { - size_t maxpktsize = 1540; - ifp->rx.ptr = (char *) calloc(1, maxpktsize), ifp->rx.len = maxpktsize; - ifp->tx.ptr = (char *) calloc(1, maxpktsize), ifp->tx.len = maxpktsize; - if (ifp->queue.len) ifp->queue.buf = (uint8_t *) calloc(1, ifp->queue.len); + size_t framesize = 1540; + ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize; + ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192; + ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size); ifp->timer_1000ms = mg_millis(); mgr->priv = ifp; ifp->mgr = mgr; @@ -868,7 +831,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { } void mg_tcpip_free(struct mg_tcpip_if *ifp) { - free((char *) ifp->rx.ptr); + free(ifp->recv_queue.buf); free((char *) ifp->tx.ptr); } diff --git a/src/tcpip/tcpip.h b/src/tcpip/tcpip.h index 3f60cb1f..8c042619 100644 --- a/src/tcpip/tcpip.h +++ b/src/tcpip/tcpip.h @@ -2,6 +2,7 @@ #include "arch.h" #include "net.h" +#include "queue.h" struct mg_tcpip_if; // MIP network interface @@ -12,27 +13,17 @@ struct mg_tcpip_driver { bool (*up)(struct mg_tcpip_if *); // Up/down status }; -// Receive queue - single producer, single consumer queue. Interrupt-based -// drivers copy received frames to the queue in interrupt context. -// mg_tcpip_poll() function runs in event loop context, reads from the queue -struct queue { - uint8_t *buf; - size_t len; - volatile size_t tail, head; -}; - // Network interface struct mg_tcpip_if { uint8_t mac[6]; // MAC address. Must be set to a valid MAC uint32_t ip, mask, gw; // IP address, mask, default gateway - struct mg_str rx; // Output (TX) buffer - struct mg_str tx; // Input (RX) buffer + struct mg_str tx; // Output (TX) buffer bool enable_dhcp_client; // Enable DCHP client bool enable_dhcp_server; // Enable DCHP server struct mg_tcpip_driver *driver; // Low level driver void *driver_data; // Driver-specific data struct mg_mgr *mgr; // Mongoose event manager - struct queue queue; // Set queue.len for interrupt based drivers + struct mg_queue recv_queue; // Receive queue // Internal state, user can use it but should not change it uint8_t gwmac[6]; // Router's MAC @@ -61,7 +52,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_stm32; extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; -extern struct mg_tcpip_driver mg_tcpip_driver_imxrt1020; +extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; // Drivers that require SPI, can use this SPI abstraction struct mg_tcpip_spi { diff --git a/test/fuzz.c b/test/fuzz.c index 66cfbbc1..2468f554 100644 --- a/test/fuzz.c +++ b/test/fuzz.c @@ -81,8 +81,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mg_tcpip_rx(&mif, pkt, size); mg_mgr_free(&mgr); free(pkt); - free((char *) mif.rx.ptr); - free((char *) mif.tx.ptr); + mg_tcpip_free(&mif); } return 0; diff --git a/test/mip_test.c b/test/mip_test.c index 626d6d79..b796e48a 100644 --- a/test/mip_test.c +++ b/test/mip_test.c @@ -17,36 +17,6 @@ static int s_num_tests = 0; } \ } while (0) -static void test_queue(void) { - static uint8_t - buf[sizeof(size_t) + sizeof(uint16_t) + 3]; // fit 1 element but not 2 - uint16_t val = 1234; - static struct queue q = {buf, sizeof(buf), 0, 0}; - - // Write to an empty queue, and read back - ASSERT(q_avail(&q) == 0); - ASSERT(q_write(&q, &val, sizeof(val)) == true); - ASSERT(q_avail(&q) == sizeof(val)); - ASSERT(q.head > q.tail); - // Only one element may fit - ASSERT(q_write(&q, &val, sizeof(val)) == false); - val = 0; - ASSERT(q_read(&q, &val) == sizeof(val)); - ASSERT(val == 1234); - ASSERT(q_avail(&q) == 0); - - // Second write - wrap over the buffer boundary - ASSERT(q_write(&q, &val, sizeof(val)) == true); - ASSERT(q_avail(&q) == sizeof(val)); - ASSERT(q.head < q.tail); - // Only one element may fit - ASSERT(q_write(&q, &val, sizeof(val)) == false); - val = 0; - ASSERT(q_read(&q, &val) == sizeof(val)); - ASSERT(val == 1234); - ASSERT(q_avail(&q) == 0); -} - static void test_statechange(void) { char tx[1540]; struct mg_tcpip_if iface; @@ -79,7 +49,6 @@ static void test_poll(void) { } int main(void) { - test_queue(); test_statechange(); test_poll(); printf("SUCCESS. Total tests: %d\n", s_num_tests);