847 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			847 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
#include "iot_pkt.h"
 | 
						|
#include "iot_mem_pool.h"
 | 
						|
#include "iot_module.h"
 | 
						|
#include "iot_errno.h"
 | 
						|
#include "iot_dbglog_api.h"
 | 
						|
#include "iot_dbglog.h"
 | 
						|
#include "iot_config.h"
 | 
						|
#include "iot_io.h"
 | 
						|
#include "iot_system_api.h"
 | 
						|
 | 
						|
typedef struct _iot_pkt_global {
 | 
						|
    uint32_t pool_cnt : 16,
 | 
						|
        req_cnt : 16;
 | 
						|
    iot_pkt_config_t config;
 | 
						|
    iot_mem_pool_t *pool[IOT_PKT_POOL_MAX];
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
    os_mutex_h mutex;
 | 
						|
#endif
 | 
						|
#if PLC_MEM_ALLOC_STAT > 1
 | 
						|
    uint16_t efficiency[IOT_PKT_POOL_MAX];
 | 
						|
#endif
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
    os_mutex_h free_callback_lock;
 | 
						|
#endif
 | 
						|
} iot_pkt_global_t;
 | 
						|
 | 
						|
static iot_pkt_global_t *p_pkt_glb = NULL;
 | 
						|
 | 
						|
static inline void __iot_pkt_reset(iot_pkt_t* buf, uint32_t size)
 | 
						|
{
 | 
						|
    buf->head = (uint8_t*)buf + sizeof(iot_pkt_t);
 | 
						|
    buf->data = buf->head;
 | 
						|
    buf->tail = buf->head;
 | 
						|
 | 
						|
    buf->end = buf->head + size;
 | 
						|
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
    iot_list_head_t *entry;
 | 
						|
    entry = (iot_list_head_t *)&(buf->entry);
 | 
						|
    iot_list_init(entry);
 | 
						|
 | 
						|
    buf->free_func = NULL;
 | 
						|
    buf->param = NULL;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#if IOT_PKT_INFO_DUMP_DEBUG
 | 
						|
void iot_pkt_dump_info(void)
 | 
						|
{
 | 
						|
    uint32_t toltal_cnt, buf_size, free_cnt, i;
 | 
						|
 | 
						|
    for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
        toltal_cnt = p_pkt_glb->config.pool_cfg[i].count;
 | 
						|
        buf_size = p_pkt_glb->config.pool_cfg[i].size;
 | 
						|
        free_cnt = iot_mem_pool_get_freenum(p_pkt_glb->pool[i]);
 | 
						|
        iot_printf("PKT:%d-%d/%d. ", buf_size, free_cnt, toltal_cnt);
 | 
						|
    }
 | 
						|
    iot_printf("\n");
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* according to MID, get the pool owner mask */
 | 
						|
static inline uint32_t iot_pkt_get_target_owner(module_id_t module_id)
 | 
						|
{
 | 
						|
    uint32_t owner = 0;
 | 
						|
 | 
						|
    if (IOT_CLI_MID == module_id)
 | 
						|
    {
 | 
						|
        owner= PKT_OWNER_IOT;
 | 
						|
    }
 | 
						|
    else if ((module_id >= PLC_MID_BASE) && (module_id < NB_MID_BASE))
 | 
						|
    {
 | 
						|
        owner = PKT_OWNER_PLC;
 | 
						|
    }
 | 
						|
    else if ((module_id >= NB_MID_BASE) && (module_id < OS_RISCV_BASE))
 | 
						|
    {
 | 
						|
        owner = PKT_OWNER_NB;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        owner = PKT_OWNER_PLC;
 | 
						|
    }
 | 
						|
    return owner;
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_init(const iot_pkt_config_t *cfg)
 | 
						|
{
 | 
						|
    uint16_t size, count;
 | 
						|
    uint32_t i, j, owner;
 | 
						|
    iot_mem_pool_t *tmp_pool;
 | 
						|
    iot_pkt_config_t *config;
 | 
						|
 | 
						|
    p_pkt_glb = os_mem_malloc(IOT_PKT_MID, sizeof(*p_pkt_glb));
 | 
						|
    IOT_ASSERT(p_pkt_glb);
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
    if (NULL == (p_pkt_glb->mutex = os_create_mutex(IOT_PKT_MID))) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
    if (NULL ==
 | 
						|
        (p_pkt_glb->free_callback_lock = os_create_mutex(IOT_PKT_MID))) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    config = &p_pkt_glb->config;
 | 
						|
 | 
						|
    for (i = 0; i < IOT_PKT_POOL_MAX; i++) {
 | 
						|
        if (cfg->pool_cfg[i].count == 0)
 | 
						|
            break;
 | 
						|
        config->pool_cfg[i].size = cfg->pool_cfg[i].size;
 | 
						|
        config->pool_cfg[i].count = cfg->pool_cfg[i].count;
 | 
						|
        config->pool_cfg[i].owner = cfg->pool_cfg[i].owner;
 | 
						|
    }
 | 
						|
    p_pkt_glb->pool_cnt = i;
 | 
						|
    IOT_ASSERT(p_pkt_glb->pool_cnt);
 | 
						|
    p_pkt_glb->req_cnt = 0;
 | 
						|
 | 
						|
    for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
        if (config->pool_cfg[i].count) {
 | 
						|
            iot_mem_pool_new(IOT_PKT_MID, config->pool_cfg[i].count,
 | 
						|
                 sizeof(iot_pkt_t) + config->pool_cfg[i].size,
 | 
						|
                 &p_pkt_glb->pool[i], 1);
 | 
						|
            IOT_ASSERT(p_pkt_glb->pool[i]);
 | 
						|
#if PLC_MEM_ALLOC_STAT
 | 
						|
            iot_printf("data buf: %d, num %d x size %d = %d bytes, owner = 0x%X, "
 | 
						|
                    "@0x%x, align_size:%d\n", \
 | 
						|
            i, config->pool_cfg[i].count, \
 | 
						|
                sizeof(iot_pkt_t) + config->pool_cfg[i].size,
 | 
						|
                config->pool_cfg[i].count * \
 | 
						|
                (sizeof(iot_pkt_t) + config->pool_cfg[i].size),
 | 
						|
                config->pool_cfg[i].owner, p_pkt_glb->pool[i],\
 | 
						|
                iot_mem_pool_get_align_size(p_pkt_glb->pool[i]));
 | 
						|
#endif
 | 
						|
        } else {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* sort the pkt size pool from least to largest */
 | 
						|
    for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
        for (j = i + 1; j < p_pkt_glb->pool_cnt; j++) {
 | 
						|
            if (config->pool_cfg[i].size > config->pool_cfg[j].size) {
 | 
						|
                size = config->pool_cfg[i].size;
 | 
						|
                count = config->pool_cfg[i].count;
 | 
						|
                owner = config->pool_cfg[i].owner;
 | 
						|
                tmp_pool = p_pkt_glb->pool[i];
 | 
						|
                config->pool_cfg[i].size = config->pool_cfg[j].size;
 | 
						|
                config->pool_cfg[i].count = config->pool_cfg[j].count;
 | 
						|
                config->pool_cfg[i].owner = config->pool_cfg[j].owner;
 | 
						|
                p_pkt_glb->pool[i] = p_pkt_glb->pool[j];
 | 
						|
                config->pool_cfg[j].size = size;
 | 
						|
                config->pool_cfg[j].count = count;
 | 
						|
                config->pool_cfg[j].owner = owner;
 | 
						|
                p_pkt_glb->pool[j] = tmp_pool;
 | 
						|
            } else if (config->pool_cfg[i].size == config->pool_cfg[j].size) {
 | 
						|
                IOT_ASSERT(0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#if IOT_PKT_DEBUG
 | 
						|
 | 
						|
iot_pkt_t* iot_pkt_mem_alloc(uint32_t size, module_id_t module_id,
 | 
						|
    uint8_t init_mem, const char *file_name, uint32_t line_num)
 | 
						|
{
 | 
						|
    uint32_t i, n, next, module_owner;
 | 
						|
    iot_pkt_t* result = NULL;
 | 
						|
    iot_pkt_t* printf_buf = NULL;
 | 
						|
    iot_mem_pool_entry_t* p_entry = NULL;
 | 
						|
    if (size == 0) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    module_owner = iot_pkt_get_target_owner(module_id);
 | 
						|
    for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
        if (size <= p_pkt_glb->config.pool_cfg[i].size) {
 | 
						|
            if (p_pkt_glb->config.pool_cfg[i].owner & module_owner)
 | 
						|
            {
 | 
						|
                result = iot_mem_pool_alloc(p_pkt_glb->pool[i]);
 | 
						|
                if (result) {
 | 
						|
                    result->file_name = file_name;
 | 
						|
                    result->line_num = line_num;
 | 
						|
                    __iot_pkt_reset(result, p_pkt_glb->config.pool_cfg[i].size);
 | 
						|
                    if (init_mem) {
 | 
						|
                        os_mem_set(result->head, 0,
 | 
						|
                            (result->end - result->head));
 | 
						|
                    }
 | 
						|
                    goto out;
 | 
						|
                } else {
 | 
						|
                    iot_printf("%s in Line %d ----buf_size:%d, pool_size:%d, "
 | 
						|
                        "this pool use up\n", file_name, line_num, size,
 | 
						|
                        p_pkt_glb->config.pool_cfg[i].size);
 | 
						|
                    p_entry = p_pkt_glb->pool[i]->entries;
 | 
						|
                    next = p_pkt_glb->pool[i]->align_block_word_size;
 | 
						|
                    if (p_entry != NULL) {
 | 
						|
                        for (n = 0; n < p_pkt_glb->pool[i]->num; n++) {
 | 
						|
                            printf_buf = (iot_pkt_t*)p_entry;
 | 
						|
                            iot_printf("%s in Line %d ----pool_size:%d, "
 | 
						|
                                "addr = [0x%08X]\n", printf_buf->file_name,
 | 
						|
                                printf_buf->line_num,
 | 
						|
                                p_pkt_glb->config.pool_cfg[i].size, printf_buf);
 | 
						|
                            p_entry = p_entry + next;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
#else /* IOT_PKT_DEBUG */
 | 
						|
 | 
						|
iot_pkt_t* iot_pkt_mem_alloc(uint32_t size, module_id_t module_id,
 | 
						|
    uint8_t init_mem)
 | 
						|
{
 | 
						|
    uint32_t i = 0, module_owner;
 | 
						|
    iot_pkt_t* result = NULL;
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
    uint32_t ast_ra = 0;
 | 
						|
    RISC_GET_REG_RA(ast_ra);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (size == 0) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    module_owner = iot_pkt_get_target_owner(module_id);
 | 
						|
    for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
        if (size <= p_pkt_glb->config.pool_cfg[i].size) {
 | 
						|
            if ( p_pkt_glb->config.pool_cfg[i].owner & module_owner) {
 | 
						|
                result = iot_mem_pool_alloc(p_pkt_glb->pool[i]);
 | 
						|
                if (result) {
 | 
						|
                    __iot_pkt_reset(result,
 | 
						|
                        p_pkt_glb->config.pool_cfg[i].size);
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
                    iot_printf("pkt_alloc:@%x,ra:0x%x\n", \
 | 
						|
                        (uint32_t)result, ast_ra);
 | 
						|
                    os_acquire_mutex(p_pkt_glb->mutex);
 | 
						|
                    iot_pkt_check_end_overwrite(result);
 | 
						|
                    os_release_mutex(p_pkt_glb->mutex);
 | 
						|
#endif
 | 
						|
                    if (init_mem) {
 | 
						|
                        os_mem_set(result->head, 0,
 | 
						|
                            (result->end - result->head));
 | 
						|
                    }
 | 
						|
#if PLC_MEM_ALLOC_STAT > 1
 | 
						|
                    /* 1/8 avg efficiency contribution for this time */
 | 
						|
                    p_pkt_glb->efficiency[i] = \
 | 
						|
                        (p_pkt_glb->efficiency[i] - \
 | 
						|
                            (p_pkt_glb->efficiency[i] >> 3)) + \
 | 
						|
                            ((size & 0xffff) >> 3);
 | 
						|
#endif
 | 
						|
                    goto out;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
#if PLC_MEM_ALLOC_STAT > 1
 | 
						|
    if ((++p_pkt_glb->req_cnt & IOTPKT_STAT_DISPLAY_FREQ) \
 | 
						|
        == IOTPKT_STAT_DISPLAY_FREQ)
 | 
						|
    {
 | 
						|
        for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
            iot_printf("pu%dpm%d/%d:e%d/%d;",
 | 
						|
            p_pkt_glb->pool[i]->num - p_pkt_glb->pool[i]->free_num,
 | 
						|
            p_pkt_glb->pool[i]->max_num,
 | 
						|
            p_pkt_glb->pool[i]->num, p_pkt_glb->efficiency[i],
 | 
						|
            (p_pkt_glb->pool[i]->align_block_word_size << 2));
 | 
						|
        }
 | 
						|
        iot_printf("\n");
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_PKT_DEBUG */
 | 
						|
 | 
						|
uint32_t iot_pkt_set_free_callback(iot_pkt_t *buf,
 | 
						|
    iot_pkt_free_func_t free_callback, void *param)
 | 
						|
{
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
    if (buf) {
 | 
						|
        buf->free_func = free_callback;
 | 
						|
        buf->param = param;
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
#else
 | 
						|
    (void)buf;
 | 
						|
    (void)free_callback;
 | 
						|
    (void)param;
 | 
						|
#endif
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_get_free_callback(iot_pkt_t *buf,
 | 
						|
    iot_pkt_free_func_t *free_callback, void **param)
 | 
						|
{
 | 
						|
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
    if (buf && buf->free_func) {
 | 
						|
        *free_callback = buf->free_func;
 | 
						|
        *param = buf->param;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    (void)buf;
 | 
						|
    *free_callback = NULL;
 | 
						|
    *param = NULL;
 | 
						|
}
 | 
						|
 | 
						|
static void iot_pkt_exe_free_callback(iot_pkt_t *buf, uint8_t state)
 | 
						|
{
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
    uint32_t ret;
 | 
						|
    iot_list_head_t *entry = (iot_list_head_t *)&(buf->entry);
 | 
						|
 | 
						|
    os_acquire_mutex(p_pkt_glb->free_callback_lock);
 | 
						|
    ret = iot_list_empty(entry);
 | 
						|
    if (!ret) {
 | 
						|
        iot_list_del(entry);
 | 
						|
    }
 | 
						|
    os_release_mutex(p_pkt_glb->free_callback_lock);
 | 
						|
 | 
						|
    if (ret && buf->free_func) {
 | 
						|
        buf->free_func(buf->param, state);
 | 
						|
    }
 | 
						|
#else
 | 
						|
    (void)buf;
 | 
						|
    (void)state;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_free(iot_pkt_t* buf)
 | 
						|
{
 | 
						|
    iot_pkt_free_tx_done(buf, IOT_PKT_STATE_UNKNOWN);
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_free_tx_done(iot_pkt_t* buf, uint8_t state)
 | 
						|
{
 | 
						|
    uint32_t i, buf_len;
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
    uint32_t ast_ra = 0;
 | 
						|
    RISC_GET_REG_RA(ast_ra);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (buf == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    buf_len = iot_pkt_block_len(buf, IOT_PKT_BLOCK_ALL);
 | 
						|
 | 
						|
    for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
        if (buf_len == p_pkt_glb->config.pool_cfg[i].size) {
 | 
						|
            iot_pkt_exe_free_callback(buf, state);
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
            iot_printf("pkt_free@%x,ra:0x%x\n", (uint32_t)buf, ast_ra);
 | 
						|
            os_acquire_mutex(p_pkt_glb->mutex);
 | 
						|
            iot_pkt_check_end_overwrite(buf);
 | 
						|
            /* init the tail and end value for debug. */
 | 
						|
            buf->tail = NULL;
 | 
						|
            buf->end = NULL;
 | 
						|
            iot_mem_pool_free(p_pkt_glb->pool[i], buf);
 | 
						|
            os_release_mutex(p_pkt_glb->mutex);
 | 
						|
#else
 | 
						|
            iot_mem_pool_free(p_pkt_glb->pool[i], buf);
 | 
						|
#endif
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (i >= p_pkt_glb->pool_cnt) {
 | 
						|
        uint32_t ret;
 | 
						|
        /* buffer corrupted */
 | 
						|
        iot_printf("pkt 0x%x not found with len %d\n", buf, buf_len);
 | 
						|
        iot_pkt_exe_free_callback(buf, state);
 | 
						|
        for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | 
						|
            ret = iot_mem_pool_force_free(p_pkt_glb->pool[i], buf);
 | 
						|
            if (ret == ERR_OK) {
 | 
						|
                goto out;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t** iot_pkt_dataptr_addr(iot_pkt_t* buf)
 | 
						|
{
 | 
						|
    if (buf) {
 | 
						|
        return (&buf->data);
 | 
						|
    }
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* iot_pkt_reserve(iot_pkt_t* buf, uint32_t size)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && buf->tail + size <= buf->end) {
 | 
						|
        buf->data += size;
 | 
						|
        buf->tail += size;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* iot_pkt_put(iot_pkt_t* buf, uint32_t size)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && buf->tail + size <= buf->end) {
 | 
						|
        buf->tail += size;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* iot_pkt_shrink(iot_pkt_t* buf, uint32_t size)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && buf->tail - size >= buf->data) {
 | 
						|
        buf->tail -= size;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* iot_pkt_push(iot_pkt_t* buf, uint32_t size)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && buf->data - size >= buf->head) {
 | 
						|
        buf->data -= size;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* iot_pkt_pull(iot_pkt_t* buf, uint32_t size)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && buf->data + size <= buf->tail) {
 | 
						|
        buf->data += size;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* IRAM_ATTR iot_pkt_set_data(iot_pkt_t* buf, void* new_data)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && (uint8_t*)new_data >= buf->head
 | 
						|
        && (uint8_t*)new_data <= buf->tail) {
 | 
						|
        buf->data = (uint8_t*)new_data;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* IRAM_ATTR iot_pkt_set_tail(iot_pkt_t* buf, void* new_tail)
 | 
						|
{
 | 
						|
    if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    if (buf && (uint8_t*)new_tail >= buf->data
 | 
						|
                && (uint8_t*)new_tail <= buf->end) {
 | 
						|
        buf->tail = (uint8_t*)new_tail;
 | 
						|
 | 
						|
        return buf->data;
 | 
						|
    }
 | 
						|
    IOT_ASSERT(0);
 | 
						|
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t* IRAM_ATTR iot_pkt_block_ptr(iot_pkt_t* buf, uint8_t block_type)
 | 
						|
{
 | 
						|
    if (buf == NULL) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    void* result = NULL;
 | 
						|
    switch (block_type)
 | 
						|
    {
 | 
						|
    case IOT_PKT_BLOCK_ALL:
 | 
						|
    case IOT_PKT_BLOCK_HEAD:
 | 
						|
        result = buf->head;
 | 
						|
        break;
 | 
						|
    case IOT_PKT_BLOCK_DATA:
 | 
						|
        result = buf->data;
 | 
						|
        break;
 | 
						|
    case IOT_PKT_BLOCK_TAIL:
 | 
						|
        result = buf->tail;
 | 
						|
        break;
 | 
						|
    case IOT_PKT_BLOCK_END:
 | 
						|
        result = buf->end;
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t IRAM_ATTR iot_pkt_block_len(iot_pkt_t* buf, uint8_t block_type)
 | 
						|
{
 | 
						|
    if (buf == NULL) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    uint32_t len = 0;
 | 
						|
    switch (block_type)
 | 
						|
    {
 | 
						|
    case IOT_PKT_BLOCK_ALL:
 | 
						|
        len = buf->end - buf->head;
 | 
						|
        break;
 | 
						|
    case IOT_PKT_BLOCK_HEAD:
 | 
						|
        len = buf->data - buf->head;
 | 
						|
        break;
 | 
						|
    case IOT_PKT_BLOCK_DATA:
 | 
						|
        len = buf->tail - buf->data;
 | 
						|
        break;
 | 
						|
    case IOT_PKT_BLOCK_TAIL:
 | 
						|
        len = buf->end - buf->tail;
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
 | 
						|
    return len;
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_reset(iot_pkt_t *buf)
 | 
						|
{
 | 
						|
    os_mem_set(buf->head, 0, (buf->end - buf->head));
 | 
						|
    buf->data = buf->tail = buf->head;
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_cpy(iot_pkt_t *dst, iot_pkt_t *src)
 | 
						|
{
 | 
						|
    if ((dst->end - dst->head) < (src->tail - src->head)) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    } else {
 | 
						|
        dst->data = dst->head + (src->data - src->head);
 | 
						|
        dst->tail = dst->data + (src->tail - src->data);
 | 
						|
        os_mem_cpy(dst->data, src->data, (src->tail - src->data));
 | 
						|
 | 
						|
#if IOT_PKT_FREE_CALLBACK_ENABLE
 | 
						|
        iot_list_head_t *src_entry, *dst_entry;
 | 
						|
        src_entry = (iot_list_head_t *)&(src->entry);
 | 
						|
        dst_entry = (iot_list_head_t *)&(dst->entry);
 | 
						|
        os_acquire_mutex(p_pkt_glb->free_callback_lock);
 | 
						|
        iot_list_add(dst_entry, src_entry);
 | 
						|
        os_release_mutex(p_pkt_glb->free_callback_lock);
 | 
						|
 | 
						|
        if (src->free_func) {
 | 
						|
            dst->free_func = src->free_func;
 | 
						|
            dst->param = src->param;
 | 
						|
        }
 | 
						|
#endif
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_cpy_with_head(iot_pkt_t *dst, iot_pkt_t *src)
 | 
						|
{
 | 
						|
    iot_pkt_cpy(dst, src);
 | 
						|
    os_mem_cpy(dst->head, src->head, (src->data - src->head));
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_pkt_list_block_data_len(iot_pkt_ls *pkt_list)
 | 
						|
{
 | 
						|
    uint32_t toltal_len = 0;
 | 
						|
    iot_pkt_ls *lst = pkt_list;
 | 
						|
 | 
						|
    while(lst)
 | 
						|
    {
 | 
						|
        if(lst->pkt)
 | 
						|
            toltal_len += iot_pkt_block_len(lst->pkt, IOT_PKT_BLOCK_DATA);
 | 
						|
        lst = lst->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return toltal_len;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_pkt_list_item_count(iot_pkt_ls *pkt_list)
 | 
						|
{
 | 
						|
    uint32_t cnt = 0;
 | 
						|
    iot_pkt_ls *lst = pkt_list;
 | 
						|
 | 
						|
    while(lst)
 | 
						|
    {
 | 
						|
        cnt ++;
 | 
						|
        lst = lst->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return cnt;
 | 
						|
}
 | 
						|
 | 
						|
void iot_pkt_list_free_every_pkt_mem(iot_pkt_ls *pkt_list)
 | 
						|
{
 | 
						|
    iot_pkt_ls *lst = pkt_list;
 | 
						|
 | 
						|
    while(lst)
 | 
						|
    {
 | 
						|
        if(lst->pkt)
 | 
						|
        {
 | 
						|
            iot_pkt_free(lst->pkt);
 | 
						|
            lst->pkt = NULL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_pkt_pktpool_status(uint8_t pool_idx, uint32_t* bufsz, \
 | 
						|
    uint32_t* freenum, uint32_t* totalnum)
 | 
						|
{
 | 
						|
    if ((pool_idx >= IOT_PKT_POOL_MAX) || (bufsz == NULL) ||
 | 
						|
        (freenum == NULL) || (totalnum == NULL))
 | 
						|
    {
 | 
						|
           return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    *bufsz =  p_pkt_glb->config.pool_cfg[pool_idx].size;
 | 
						|
    *freenum = iot_mem_pool_get_freenum(p_pkt_glb->pool[pool_idx]);
 | 
						|
    *totalnum = p_pkt_glb->config.pool_cfg[pool_idx].count;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void mem_dump(uint32_t *word_ptr, uint32_t word_cnt)
 | 
						|
{
 | 
						|
    for (uint32_t j = 0; j < (word_cnt >> 2); j++) {
 | 
						|
        iot_printf("0x%08x:", word_ptr + (j << 2));
 | 
						|
        for (uint32_t i = 0; i < 4; i++)
 | 
						|
        {
 | 
						|
            iot_printf("0x%08x ", *(word_ptr + (j << 2) + i));
 | 
						|
        }
 | 
						|
        iot_printf("\n");
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mem_dump_byte(uint8_t *byte_ptr, uint32_t byte_cnt)
 | 
						|
{
 | 
						|
    uint32_t i, j;
 | 
						|
    for (i = 0; i < byte_cnt; ) {
 | 
						|
        iot_printf("0x%08x:", (uint32_t)byte_ptr + i);
 | 
						|
        for (j = 0; j < 8; j++) {
 | 
						|
            if ((i + j) >= byte_cnt) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            iot_printf("0x%02x ", byte_ptr[i + j]);
 | 
						|
        }
 | 
						|
        iot_printf("\n");
 | 
						|
        i += j;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_pkt_validation(iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    if (!iot_data_addr_legal(
 | 
						|
             (uint32_t) iot_pkt_block_ptr(pkt,
 | 
						|
                 IOT_PKT_BLOCK_HEAD))
 | 
						|
        || !iot_data_addr_legal(
 | 
						|
             (uint32_t) iot_pkt_block_ptr(pkt,
 | 
						|
                 IOT_PKT_BLOCK_DATA))
 | 
						|
        || !iot_data_addr_legal(
 | 
						|
             (uint32_t) iot_pkt_block_ptr(pkt,
 | 
						|
                 IOT_PKT_BLOCK_TAIL))
 | 
						|
        || !iot_data_addr_legal(
 | 
						|
             (uint32_t) iot_pkt_block_ptr(pkt,
 | 
						|
                 IOT_PKT_BLOCK_END)))
 | 
						|
    {
 | 
						|
        iot_printf("iot_pkt overwrite found @0x%x, "
 | 
						|
            "4 pointers' are: 0x%x, 0x%x, 0x%x, 0x%x\n",
 | 
						|
            pkt,
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD),
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA),
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL),
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_END));
 | 
						|
        iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_ERR,
 | 
						|
            IOT_MAC_RX_OVERWRITE_ID, 5, pkt,
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD),
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA),
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL),
 | 
						|
            iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_END));
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#if DEBUG_PKT_OVERWRITE
 | 
						|
 | 
						|
uint32_t iot_pkt_check_end_overwrite(iot_pkt_t *buf)
 | 
						|
{
 | 
						|
    uint32_t align_size = 0;
 | 
						|
    uint32_t pool_num, size, count;
 | 
						|
    uint32_t head_addr, data_addr, tail_addr, end_addr;
 | 
						|
    uint32_t last_pkt_addr;
 | 
						|
 | 
						|
    if (!buf) {
 | 
						|
        iot_printf("pkt_check invalid\n");
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    size = iot_pkt_block_len(buf, IOT_PKT_BLOCK_ALL);
 | 
						|
    for (pool_num = 0; pool_num < p_pkt_glb->pool_cnt; ) {
 | 
						|
        if (size == p_pkt_glb->config.pool_cfg[pool_num].size) {
 | 
						|
            align_size = iot_mem_pool_get_align_size(p_pkt_glb->pool[pool_num]);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        ++pool_num;
 | 
						|
    }
 | 
						|
 | 
						|
    if (align_size == 0) {
 | 
						|
        iot_printf("pkt_check not found pool\n");
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* calculation the actual next pkt */
 | 
						|
    iot_pkt_t *pkt = (iot_pkt_t *)((uint32_t)buf + align_size);
 | 
						|
 | 
						|
    size = iot_mem_pool_get_align_size(p_pkt_glb->pool[pool_num]);
 | 
						|
    count = p_pkt_glb->config.pool_cfg[pool_num].count;
 | 
						|
    /* get this pool last pkt addr */
 | 
						|
    last_pkt_addr = (uint32_t)p_pkt_glb->pool[pool_num]->entries \
 | 
						|
        + (size * (count - 1));
 | 
						|
 | 
						|
    /* the next pkt is the next pool first pkt.
 | 
						|
     * but each pool address is discontinuous.
 | 
						|
     */
 | 
						|
    if ((uint32_t)pkt > last_pkt_addr) {
 | 
						|
        pool_num++; // set pool to next pool num
 | 
						|
        /* next pool's pkt size = 0, means current pool is last pool.
 | 
						|
         * don't need to check the next pkt. */
 | 
						|
        if (0 == p_pkt_glb->config.pool_cfg[pool_num].size) {
 | 
						|
            return ERR_OK;
 | 
						|
        }
 | 
						|
        pkt = (iot_pkt_t *)p_pkt_glb->pool[pool_num]->entries;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!pkt) {
 | 
						|
        iot_printf("pkt_check buf=0x%x, last=0x%x\n",
 | 
						|
            (uint32_t)buf, (uint32_t)last_pkt_addr);
 | 
						|
        //align_size * 2 / 4
 | 
						|
        IOT_ASSERT_DUMP(0, (uint32_t *)buf, align_size >> 1);
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* get this pkt's head/data/tail/end address */
 | 
						|
    head_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD);
 | 
						|
    data_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | 
						|
    tail_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL);
 | 
						|
    end_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_END);
 | 
						|
 | 
						|
    if (((0 == head_addr) || iot_data_addr_legal(head_addr))
 | 
						|
        && ((uint32_t)IOT_MEM_POOL_POISON == data_addr)
 | 
						|
        && !tail_addr
 | 
						|
        && !end_addr) {
 | 
						|
        /* the next pkt not allocated ,not need check.
 | 
						|
         * for the not allocated pkt:
 | 
						|
         * pkt->head is the pool block's head, the value is NULL or
 | 
						|
         *      next_pool_block_ptr.
 | 
						|
         * pkt->data must be IOT_MEM_POOL_POISON
 | 
						|
         * pkt->tail and pkt->end must be NULL
 | 
						|
         * for the allocated pkt, the head/data/tail/end must be valid address.
 | 
						|
         */
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    /* next pkt */
 | 
						|
    if (ERR_OK != iot_pkt_validation(pkt)) {
 | 
						|
        //align_size * 2 / 4
 | 
						|
        iot_printf("pkt_end_overwrite:0x%x-0x%x\n",
 | 
						|
            (uint32_t)buf, (uint32_t)pkt);
 | 
						|
        IOT_ASSERT_DUMP(0, (uint32_t *)buf, align_size >> 1);
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#else /* DEBUG_PKT_OVERWRITE */
 | 
						|
 | 
						|
uint32_t iot_pkt_check_end_overwrite(iot_pkt_t *buf)
 | 
						|
{
 | 
						|
    (void)buf;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* DEBUG_PKT_OVERWRITE */
 | 
						|
 |