Tool/software:
Hello,
We are currently using SDK 8.6 and RTOS system development. When using CPSW, we want to send goose data via Ethernet. The function called is LWIPIF_LWIP_send. The goose message buffer is obtained by applying for memory function pbuf_alloc and released after sending. The current situation is that when the Ethernet cable is not connected, the memory application fails. At this time, the applied memory is NULL.This problem does not occur when I connect the network cable normally。I have questions to confirm.
1、Is the function for sending goose message used correctly?
2、If the network cable is not connected, if the transmission fails, the memory will not be released even if the function to release the memory is called.Because there is a corresponding judgment in the memory release function pbuf_free, the buffer will not be released if ref == 0 is not satisfied.why is that?
3、If sending the current goose fails, will the previously unsent data be sent after the connection is restored?
4、The return value of the send function is always ERR_OK。
How should we deal with the above situation?Is there a corresponding routine for us to use?
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) { struct pbuf *p; u16_t offset = (u16_t)layer; LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); switch (type) { case PBUF_REF: /* fall through */ case PBUF_ROM: p = pbuf_alloc_reference(NULL, length, type); break; case PBUF_POOL: { struct pbuf *q, *last; u16_t rem_len; /* remaining length */ p = NULL; last = NULL; rem_len = length; do { u16_t qlen; q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); if (q == NULL) { PBUF_POOL_IS_EMPTY(); /* free chain so far allocated */ if (p) { pbuf_free(p); } /* bail out unsuccessfully */ return NULL; } qlen = LWIP_MIN(rem_len, (u16_t)(PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset))); pbuf_init_alloced_pbuf(q, LWIP_MEM_ALIGN((void *)((u8_t *)q + SIZEOF_STRUCT_PBUF + offset)), rem_len, qlen, type, 0); LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); if (p == NULL) { /* allocated head of pbuf chain (into p) */ p = q; } else { /* make previous pbuf point to this pbuf */ last->next = q; } last = q; rem_len = (u16_t)(rem_len - qlen); offset = 0; } while (rem_len > 0); break; } case PBUF_RAM: { u16_t payload_len = (u16_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length)); mem_size_t alloc_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len); /* bug #50040: Check for integer overflow when calculating alloc_len */ if ((payload_len < LWIP_MEM_ALIGN_SIZE(length)) || (alloc_len < LWIP_MEM_ALIGN_SIZE(length))) { return NULL; } /* If pbuf is to be allocated in RAM, allocate memory for it. */ p = (struct pbuf *)mem_malloc(alloc_len); if (p == NULL) { return NULL; } pbuf_init_alloced_pbuf(p, LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)), length, length, type, 0); LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); break; } default: LWIP_ASSERT("pbuf_alloc: erroneous type", 0); return NULL; } LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); return p; } u8_t pbuf_free(struct pbuf *p) { u8_t alloc_src; struct pbuf *q; u8_t count; if (p == NULL) { LWIP_ASSERT("p != NULL", p != NULL); /* if assertions are disabled, proceed with debug output */ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("pbuf_free(p == NULL) was called.\n")); return 0; } LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); PERF_START; count = 0; /* de-allocate all consecutive pbufs from the head of the chain that * obtain a zero reference count after decrementing*/ while (p != NULL) { LWIP_PBUF_REF_T ref; SYS_ARCH_DECL_PROTECT(old_level); /* Since decrementing ref cannot be guaranteed to be a single machine operation * we must protect it. We put the new ref into a local variable to prevent * further protection. */ SYS_ARCH_PROTECT(old_level); /* all pbufs in a chain are referenced at least once */ LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); /* decrease reference count (number of pointers to pbuf) */ ref = --(p->ref); SYS_ARCH_UNPROTECT(old_level); /* this pbuf is no longer referenced to? */ if (ref == 0) { /* remember next pbuf in chain for next iteration */ q = p->next; LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); alloc_src = pbuf_get_allocsrc(p); #if LWIP_SUPPORT_CUSTOM_PBUF /* is this a custom pbuf? */ if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { struct pbuf_custom *pc = (struct pbuf_custom *)p; LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); pc->custom_free_function(p); } else #endif /* LWIP_SUPPORT_CUSTOM_PBUF */ { /* is this a pbuf from the pool? */ if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) { memp_free(MEMP_PBUF_POOL, p); /* is this a ROM or RAM referencing pbuf? */ } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) { memp_free(MEMP_PBUF, p); /* type == PBUF_RAM */ } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) { mem_free(p); } else { /* @todo: support freeing other types */ LWIP_ASSERT("invalid pbuf type", 0); } } count++; /* proceed to next pbuf */ p = q; /* p->ref > 0, this pbuf is still referenced to */ /* (and so the remaining pbufs in chain as well) */ } else { LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)ref)); /* stop walking through the chain */ p = NULL; } } PERF_STOP("pbuf_free"); /* return number of de-allocated pbufs */ return count; } err_t LWIPIF_LWIP_send(struct netif *netif, struct pbuf *p) { /* Get the pointer to the private data */ Lwip2Enet_netif_t* pInterface = (Lwip2Enet_netif_t*) netif->state; const Enet_MacPort macPort = pInterface->macPort; Lwip2Enet_TxHandle hTx = pInterface->hTx[0]; Lwip2Enet_assert(pInterface != NULL); Lwip2Enet_assert(hTx != NULL); /* * When transmitting a packet, the buffer may be deleted before transmission by the * stack. The stack implements a 'ref' feature within the buffers. The following happens * internally: * If p->ref > 1, ref--; * If p->ref == 1, free(p); * pbuf_ref(p) increments the ref. */ pbuf_ref(p); /* Enqueue the packet */ pbufQ_enQ(&hTx->readyPbufQ, p); LWIP2ENETSTATS_ADDONE(&hTx->stats.readyPbufPktEnq); /* Pass the packet to the translation layer */ Lwip2Enet_sendTxPackets(pInterface, macPort); /* Packet has been successfully transmitted or enqueued to be sent when link comes up */ return ERR_OK; }