diff options
Diffstat (limited to 'stacks/lwip_stack/lwip_src/netif')
-rw-r--r-- | stacks/lwip_stack/lwip_src/netif/ethernetif.c | 167 | ||||
-rw-r--r-- | stacks/lwip_stack/lwip_src/netif/sc_dpdk.c | 574 | ||||
-rw-r--r-- | stacks/lwip_stack/lwip_src/netif/spl_hal.c | 1753 |
3 files changed, 2494 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/netif/ethernetif.c b/stacks/lwip_stack/lwip_src/netif/ethernetif.c new file mode 100644 index 0000000..6a3e810 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/netif/ethernetif.c @@ -0,0 +1,167 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "spl_opt.h" + +#include "spl_def.h" +#include "mem.h" +#include "stackx/spl_pbuf.h" +//#include <stackx/stats.h> +//#include "sockets.h" +#include <netinet/in.h> + +#include "stackx_spl_share.h" +#include "stackx/spl_api.h" +#include "lwip/etharp.h" + +#include <sc_dpdk.h> +#include "sc_dpdk.h" + +#include "cpuid.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "hal_api.h" + +#include "sys.h" + +#define IFNAME0 'e' +#define IFNAME1 'n' + +struct ethernetif +{ + struct eth_addr *ethaddr; + +}; + +#if (DPDK_MODULE != 1) +NSTACK_STATIC void +low_level_init (struct netif *pnetif) +{ + struct ether_addr eth_addr; + + struct netifExt *pnetifExt = NULL; + NSPOL_LOGINF (NETIF_DEBUG, "low_level_init \n"); + + pnetifExt = getNetifExt (pnetif->num); + if (NULL == pnetifExt) + return; + + hal_get_macaddr (pnetifExt->hdl, ð_addr); + NSPOL_LOGINF (SC_DPDK_INFO, + "low_level_init: Port %s, MAC : %02X:%02X:%02X:%02X:%02X:%02X", + pnetifExt->if_name, eth_addr.addr_bytes[0], + eth_addr.addr_bytes[1], eth_addr.addr_bytes[2], + eth_addr.addr_bytes[3], eth_addr.addr_bytes[4], + eth_addr.addr_bytes[5]); + + pnetif->hwaddr_len = 6; + pnetif->hwaddr[0] = eth_addr.addr_bytes[0]; //0x00; + pnetif->hwaddr[1] = eth_addr.addr_bytes[1]; //0x1b; + pnetif->hwaddr[2] = eth_addr.addr_bytes[2]; //0x21; + pnetif->hwaddr[3] = eth_addr.addr_bytes[3]; //0x6b; + pnetif->hwaddr[4] = eth_addr.addr_bytes[4]; //0x24; + pnetif->hwaddr[5] = eth_addr.addr_bytes[5]; //0x40; + pnetif->mtu = SPL_FRAME_MTU; + + /* don't set SPL_NETIF_FLAG_ETHARP if this device is not an ethernet one */ + pnetif->flags = + NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + pnetif->flags |= NETIF_FLAG_IGMP; + +} +#endif + +#if (DPDK_MODULE != 1) + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to spl_netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if privatedata couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init (struct netif * pnetif) +{ + struct ethernetif *eth_netif; + + if (NULL == pnetif) + { + NSPOL_LOGERR ("netif=NULL"); + return ERR_VAL; + } + NSPOL_LOGINF (NETIF_DEBUG, "ethernetif_init \n"); + + eth_netif = (struct ethernetif *) malloc (sizeof (struct ethernetif)); + if (eth_netif == NULL) + { + NSPOL_LOGERR ("ethernetif_init: out of memory"); + return ERR_MEM; + } + + pnetif->state = eth_netif; + pnetif->name[0] = IFNAME0; + pnetif->name[1] = IFNAME1; + + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + pnetif->output = etharp_output; + pnetif->linkoutput = spl_hal_output; + + eth_netif->ethaddr = (struct eth_addr *) &(pnetif->hwaddr[0]); + + // Add extra netif information here + if (0 != netifExt_add (pnetif)) + { + return ERR_VAL; + } + + /* initialize the hardware */ + low_level_init (pnetif); + NSPOL_LOGINF (NETIF_DEBUG, + "ethernetif_init complete ifname [%c][%c][%d] \n", + pnetif->name[0], pnetif->name[1], pnetif->num); + + return ERR_OK; +} + +void +ethernetif_packets_input (struct netif *pstnetif) +{ + struct spl_pbuf *p = NULL; + spl_hal_input (pstnetif, &p); + + /* no packet could be read, silently ignore this */ + if (p != NULL + && pstnetif->input (spl_convert_spl_pbuf_to_pbuf (p), + pstnetif) != ERR_OK) + { + NSPOL_LOGERR ("netif->input failed]p=%p, netif=%p", p, pstnetif); + } + + /* Free the spl pbuf */ + spl_pbuf_free (p); +} +#endif +//#endif /* 0 */ diff --git a/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c b/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c new file mode 100644 index 0000000..95f3eec --- /dev/null +++ b/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c @@ -0,0 +1,574 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "sc_dpdk.h" +#include "common_mem_mbuf.h" +#include "netif/common.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nsfw_msg_api.h" +#include "nsfw_maintain_api.h" +#include "nsfw_recycle_api.h" +#include "stackx_app_res.h" +#include "stackx_pbuf.h" +#ifdef SYS_MEM_RES_STAT +#include "memp.h" +#endif +#include "spl_instance.h" +#ifdef HAL_LIB +#else +#include "rte_memzone.h" +#endif + +#define SPL_MEM_MODULE "spl_mem_module" + +#define TMR_TICK_LENGTH TCP_TMR_INTERVAL /* define the tick length */ + +u32_t uStackArgIndex = 0; +int stackx_core_mask = 40; + +int g_nstack_bind_cpu = 0; +int g_tcpip_thread_sleep_time = 0; + +extern int sbr_create_tx_pool (); +extern int stackx_stat_zone_create (); + +#define GLOBAL_STACK_CORE_ARG "-c" +#define GLOBAL_STACK_CORE_BINE "-bind_cpu" + +u32 g_type; +struct memory_statics memory_used_size[80]; + +void +printmeminfo () +{ + unsigned int i = 0; + long size = 0; + + NSPOL_LOGDBG (SC_DPDK_INFO, + "*************************************************************"); + for (i = 0; i < g_type; i++) + { + NSPOL_LOGDBG (SC_DPDK_INFO, "%s : %ld", memory_used_size[i].name, + memory_used_size[i].size); + size += memory_used_size[i].size; + } + + size += (g_type * sizeof (struct common_mem_memzone)); + NSPOL_LOGDBG (SC_DPDK_INFO, "total size %ld", size); + NSPOL_LOGDBG (SC_DPDK_INFO, + "*************************************************************"); +} + +void +print_call_stack () +{ +} + +/* Parse the argument given in the command line of the application */ +void +smp_parse_stack_args (int argc, char **argv) +{ + int i = 0; + + const unsigned int global_core_length = 2; //GLOBAL_STACK_CORE_ARG "-c" string length is 2 + + for (i = uStackArgIndex + 1; i < argc; i++) + { + if ((i + 1) < argc) + { + if (strncmp (argv[i], "-sleep", 6) == 0) //compare "-sleep" string, length is 6 + { + g_tcpip_thread_sleep_time = atoi (argv[++i]); + NSPOL_LOGDBG (SC_DPDK_INFO, "g_tcpip_thread_sleep_time=%d", + g_tcpip_thread_sleep_time); + continue; + } + + if (strncmp (argv[i], GLOBAL_STACK_CORE_ARG, global_core_length) == + 0) + { + stackx_core_mask = atoi (argv[++i]); + if (stackx_core_mask < 1) + { + NSPOL_LOGDBG (SC_DPDK_INFO, + "Invalid Args:core_mask can't be less than 1,input value is:%s", + argv[i]); + } + + continue; + } + + if (strncmp + (argv[i], GLOBAL_STACK_CORE_BINE, + sizeof (GLOBAL_STACK_CORE_BINE)) == 0) + { + if (argv[++i]) + { + g_nstack_bind_cpu = atoi (argv[i]); + } + + if (g_nstack_bind_cpu < 0) + { + g_nstack_bind_cpu = 0; + } + + continue; + } + } + else + { + NSPOL_LOGDBG (SC_DPDK_INFO, "Invalid args:%s miss value ", argv[i]); //now ,only support this format ,others maybe supported in future + } + } + + return; +} + +mpool_handle +create_tx_mbuf_pool () +{ + mpool_handle mbf_pool_handle = NULL; + + nsfw_mem_mbfpool mbuf_pool; + + mbuf_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf (mbuf_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + get_mempoll_tx_name ()); + if (retval < 0) + { + NSPOL_LOGERR ("spl_snprintf failed"); + return NULL; + } + + mbuf_pool.usnum = TX_MBUF_POOL_SIZE - 1; + mbuf_pool.uscash_size = 0; + mbuf_pool.uspriv_size = 0; + mbuf_pool.usdata_room = TX_MBUF_MAX_LEN; + mbuf_pool.isocket_id = SOCKET_ID_ANY; + mbuf_pool.enmptype = NSFW_MRING_SPSC; + mbf_pool_handle = nsfw_mem_mbfmp_create (&mbuf_pool); + if (NULL == mbf_pool_handle) + { + NSPOL_LOGERR ("create_tx_mbuf_pool failed]name=%s, num=%u, room=%u", + mbuf_pool.stname.aname, mbuf_pool.usnum, + mbuf_pool.usdata_room); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, + "tx_mempool_malloc=%p, num=%u, room=%u, total_mem=%d", + mbf_pool_handle, TX_MBUF_POOL_SIZE, mbuf_pool.usdata_room, + nsfw_mem_get_len (mbf_pool_handle, NSFW_MEM_MBUF)); + DPDK_MEMORY_COUNT ((get_mempoll_tx_name ()), + nsfw_mem_get_len (mbf_pool_handle, NSFW_MEM_MBUF)); + MEM_STAT (SPL_MEM_MODULE, "spl_mbuf_pool", NSFW_SHMEM, + nsfw_mem_get_len (mbf_pool_handle, NSFW_MEM_MBUF)); + + return mbf_pool_handle; +} + +mring_handle +create_segment_pool () +{ + nsfw_mem_sppool seg_pool; + seg_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf (seg_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + get_mempoll_seg_name ()); + if (retval < 0) + { + NSPOL_LOGERR ("spl_snprintf failed"); + return NULL; + } + + seg_pool.usnum = 16; + seg_pool.useltsize = sizeof (struct common_pcb); + seg_pool.isocket_id = SOCKET_ID_ANY; + seg_pool.enmptype = NSFW_MRING_SPSC; + + mring_handle seg_mp_handle = nsfw_mem_sp_create (&seg_pool); + if (NULL == seg_mp_handle) + { + NSPOL_LOGERR + ("create_segment_pool common failed]name=%s, num=%u, size=%u", + seg_pool.stname.aname, SPL_MEMP_NUM_TCP_SEG, seg_pool.useltsize); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, + "common seg_mempool_malloc=%p, num=%u, size=%u, total_mem=%d", + seg_mp_handle, SPL_MEMP_NUM_TCP_SEG, seg_pool.useltsize, + nsfw_mem_get_len (seg_mp_handle, NSFW_MEM_SPOOL)); + DPDK_MEMORY_COUNT ((get_mempoll_seg_name ()), + nsfw_mem_get_len (seg_mp_handle, NSFW_MEM_SPOOL)); + MEM_STAT (SPL_MEM_MODULE, "spl_seg_pool", NSFW_SHMEM, + nsfw_mem_get_len (seg_mp_handle, NSFW_MEM_SPOOL)); + return seg_mp_handle; +} + +mring_handle +create_msg_pool () +{ + nsfw_mem_sppool msg_pool; + msg_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf (msg_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + get_mempoll_msg_name ()); + if (retval < 0) + { + NSPOL_LOGERR ("spl_snprintf fail"); + return NULL; + } + + msg_pool.usnum = TX_MSG_POOL_SIZE; + msg_pool.useltsize = sizeof (data_com_msg); + msg_pool.isocket_id = SOCKET_ID_ANY; + msg_pool.enmptype = NSFW_MRING_MPMC; + mring_handle msg_mp_handle = nsfw_mem_sp_create (&msg_pool); + + if (NULL == msg_mp_handle) + { + NSPOL_LOGERR ("create_msg_pool failed]name=%s, num=%u, size=%u", + msg_pool.stname.aname, TX_MSG_POOL_SIZE, + msg_pool.useltsize); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, + "msg_pool_malloc=%p, num=%u, size=%u, total_mem=%d", + msg_mp_handle, TX_MSG_POOL_SIZE, msg_pool.useltsize, + nsfw_mem_get_len (msg_mp_handle, NSFW_MEM_SPOOL)); + DPDK_MEMORY_COUNT ((get_mempoll_msg_name ()), + nsfw_mem_get_len (msg_mp_handle, NSFW_MEM_SPOOL)); + MEM_STAT (SPL_MEM_MODULE, "spl_msg_pool", NSFW_SHMEM, + nsfw_mem_get_len (msg_mp_handle, NSFW_MEM_SPOOL)); + return msg_mp_handle; +} + +mring_handle +create_primary_box () +{ + nsfw_mem_mring mbox_pool; + mbox_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf (mbox_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + get_stackx_ring_name ()); + if (retval < 0) + { + NSPOL_LOGERR ("spl_snprintf failed"); + return NULL; + } + + mbox_pool.usnum = MBOX_RING_SIZE - 1; + mbox_pool.isocket_id = SOCKET_ID_ANY; + mbox_pool.enmptype = NSFW_MRING_MPSC; + mring_handle mbox_handle = nsfw_mem_ring_create (&mbox_pool); + if (NULL == mbox_handle) + { + NSPOL_LOGERR ("create_primary_mbox failed]name=%s, num=%u", + mbox_pool.stname.aname, mbox_pool.usnum + 1); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "primary_mbox_malloc=%p, num=%u, total_mem=%d", + mbox_handle, MBOX_RING_SIZE, + (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING))); + DPDK_MEMORY_COUNT ((get_stackx_ring_name ()), + (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING))); + MEM_STAT (SPL_MEM_MODULE, "primary_mbox_ring", NSFW_SHMEM, + (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING))); + return mbox_handle; +} + +mring_handle +create_priority_box (u32 prio) +{ + nsfw_mem_mring mbox_pool; + mbox_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf (mbox_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + get_stackx_priority_ring_name (prio)); + if (retval < 0) + { + NSPOL_LOGERR ("spl_snprintf failed"); + return NULL; + } + + mbox_pool.usnum = MBOX_RING_SIZE - 1; + mbox_pool.isocket_id = SOCKET_ID_ANY; + mbox_pool.enmptype = NSFW_MRING_MPSC; + mring_handle mbox_handle = nsfw_mem_ring_create (&mbox_pool); + if (NULL == mbox_handle) + { + NSPOL_LOGERR ("Create priority mbox fail]name=%s, num=%u", + mbox_pool.stname.aname, mbox_pool.usnum + 1); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "prio=%u, mbox=%p, num=%u, total_mem=%d", prio, + mbox_handle, MBOX_RING_SIZE, + (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING))); + DPDK_MEMORY_COUNT ((get_stackx_priority_ring_name (prio)), + (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING))); + MEM_STAT (SPL_MEM_MODULE, mbox_pool.stname.aname, NSFW_SHMEM, + (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING))); + return mbox_handle; + +} + +int +init_instance () +{ + int ret; + p_def_stack_instance = + (stackx_instance *) malloc (sizeof (stackx_instance)); + if (NULL == p_def_stack_instance) + { + NSPOL_LOGERR ("malloc failed"); + return -1; + } + + ret = MEMSET_S (p_def_stack_instance, sizeof (stackx_instance), 0, + sizeof (stackx_instance)); + if (EOK != ret) + { + NSPOL_LOGERR ("MEMSET_S failed]ret=%d", ret); + return -1; + } + + p_def_stack_instance->rss_queue_id = 0; + p_def_stack_instance->netif_list = NULL; + p_def_stack_instance->mp_tx = create_tx_mbuf_pool (); + if (!p_def_stack_instance->mp_tx) + { + return -1; + } + + (void) spl_reg_res_tx_mgr (p_def_stack_instance->mp_tx); // will only return 0, no need to check return value + + /* Modified above code to hold common_pcb */ + p_def_stack_instance->cpcb_seg = create_segment_pool (); + if (!p_def_stack_instance->cpcb_seg) + { + return -1; + } + + p_def_stack_instance->lmsg_pool = create_msg_pool (); + if (!p_def_stack_instance->lmsg_pool) + { + return -1; + } + + mring_handle mbox_array[SPL_MSG_BOX_NUM] = { NULL }; + p_def_stack_instance->lstack.primary_mbox.llring = create_primary_box (); + if (!p_def_stack_instance->lstack.primary_mbox.llring) + { + return -1; + } + mbox_array[0] = p_def_stack_instance->lstack.primary_mbox.llring; + + u32 m = 0; + while (m < MSG_PRIO_QUEUE_NUM) + { + p_def_stack_instance->lstack.priority_mbox[m].llring = + create_priority_box (m); + if (!p_def_stack_instance->lstack.priority_mbox[m].llring) + { + return -1; + } + mbox_array[m + 1] = + p_def_stack_instance->lstack.priority_mbox[m].llring; + m++; + } + + (void) spl_add_mbox (mbox_array, SPL_MSG_BOX_NUM); + + g_nsfw_rti_primary_stat = &p_def_stack_instance->lstat.primary_stat; //save to g_nsfw_rti_primary_stat(this is a SH addr) + return 0; +} + +void +spl_free_msgs_in_box (mring_handle r) +{ + i32 count = 0, i = 0; + + void **msgs = NULL; + data_com_msg *m = NULL; + + while ((count = nsfw_mem_ring_dequeuev (r, msgs, 32)) > 0) + { + /* drop all of them */ + if (msgs == NULL) + break; + + for (i = 0; i < count; i++) + { + m = (data_com_msg *) msgs[i]; + if (m->param.op_type == MSG_ASYN_POST) + ASYNC_MSG_FREE (m); + else + SYNC_MSG_ACK (m); + } + } +} + +inline int +spl_msg_malloc (data_com_msg ** p_msg_entry) +{ + mring_handle msg_pool = NULL; + int rslt; + stackx_instance *instance = p_def_stack_instance; + msg_pool = instance->lmsg_pool; + if (!msg_pool) + { + NSPOL_LOGERR ("msg_pool is NULL"); + return -1; + } + + rslt = nsfw_mem_ring_dequeue (msg_pool, (void **) p_msg_entry); + if ((rslt == 0) || (*p_msg_entry == NULL)) + { + NSPOL_LOGERR ("failed to get msg from ring"); + return -1; + } + + res_alloc (&(*p_msg_entry)->param.res_chk); + + (*p_msg_entry)->param.msg_from = msg_pool; + (*p_msg_entry)->param.err = ERR_OK; + return 0; +} + +struct spl_pbuf * +spl_mbuf_malloc (uint16_t len, spl_pbuf_type Type, u16_t * count) +{ + struct common_mem_mbuf *mbuf = NULL; + struct common_mem_mbuf *mbuf_first = NULL; + struct common_mem_mbuf *mbuf_tail = NULL; + struct spl_pbuf *buf = NULL; + struct spl_pbuf *first = NULL; + struct spl_pbuf *tail = NULL; + + mpool_handle mp = NULL; + + mp = p_def_stack_instance->mp_tx; + if (mp == NULL) + { + return NULL; /*if mp is NULL when init app will Inform */ + } + + while (len > 0) + { + mbuf = (struct common_mem_mbuf *) nsfw_mem_mbf_alloc (mp, NSFW_SHMEM); + if (unlikely (mbuf == NULL)) + { + if (mbuf_first != NULL) + { + if (res_free + (& + (((struct spl_pbuf *) ((char *) mbuf_first + + sizeof (struct + common_mem_mbuf)))->res_chk))) + { + NSPOL_LOGERR ("res_free failed"); + } + spl_mbuf_free (mbuf_first); + } + + return NULL; + } + + uint16_t alloc = TX_MBUF_MAX_LEN; + if (len < TX_MBUF_MAX_LEN) + { + alloc = len; + } + + (*count)++; + mbuf->data_len = alloc; + mbuf->next = NULL; + buf = + (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf)); + res_alloc (&buf->res_chk); + + buf->next_a = 0; + buf->payload_a = ADDR_LTOSH_EXT (common_pktmbuf_mtod (mbuf, void *)); + buf->tot_len = len; + buf->len = alloc; + buf->type = Type; + buf->flags = 0; + + buf->freeNext = NULL; + + buf->conn_a = 0; + + if (first == NULL) + { + first = buf; + mbuf_first = mbuf; + tail = buf; + mbuf_tail = mbuf; + mbuf_first->nb_segs = 1; + mbuf_first->pkt_len = alloc; + } + else + { + /* Already there is a check for the return value of rtp_pktmbuf_alloc, + hence not an issue */ + + tail->next_a = ADDR_LTOSH_EXT (buf); + tail = buf; +#ifdef HAL_LIB +#else + mbuf_tail->next = mbuf; +#endif + mbuf_tail = mbuf; + + mbuf_first->pkt_len = (mbuf_first->pkt_len + mbuf->data_len); + mbuf_first->nb_segs++; + + } + + len -= alloc; + } + + return first; +} + +/* + * Ring distribution function: protocol stack once a packet processing, so there is no use of bulk package + * @param buf pbuf means * @param packet_inport the packet from which the port to enter, for the configuration table with the ip comparison + * @ Protocol stack add location: ip.c-> ip_input () -> (if (netif == NULL) branch) + * @ Return value: 0 for the send into * 0 for the transmission failed: send the original failure 1, + * err = -20 did not match to the client, err = -1Ring full, overflow, will release the package +*/ + +inline void +spl_mbuf_free (void *mbuf) +{ + (void) nsfw_mem_mbf_free ((mbuf_handle) mbuf, NSFW_SHMEM); +} + +inline uint16_t +spl_mbuf_refcnt_update (void *mbuf, int16_t value) +{ + common_mbuf_refcnt_set ((struct common_mem_mbuf *) mbuf, + common_mbuf_refcnt_read ((struct common_mem_mbuf *) + mbuf) + value); + return 1; +} diff --git a/stacks/lwip_stack/lwip_src/netif/spl_hal.c b/stacks/lwip_stack/lwip_src/netif/spl_hal.c new file mode 100644 index 0000000..5f69a9d --- /dev/null +++ b/stacks/lwip_stack/lwip_src/netif/spl_hal.c @@ -0,0 +1,1753 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "sys_arch.h" +#include "netif.h" +#include "spl_sockets.h" +//#include <netinet/in.h> + +#include "stackx_spl_share.h" +#include "stackx_pbuf.h" +#include "spl_api.h" +#include "sharedmemory.h" +//#include "nettool.h" +#include "lwip/etharp.h" +#include "ip_module_api.h" +#include "sc_dpdk.h" +#include "nstack_log.h" +#include "common.h" +#include "nstack_securec.h" +//#include "ip.h" +#include "configuration_reader.h" +#include "spl_hal.h" +#include "nsfw_maintain_api.h" +#include "stackx_common.h" +#include "spl_instance.h" +#include <netinet/in.h> +#include "prot/tcp.h" + +extern u32_t g_mbuf_size[MAX_THREAD_NUM]; +extern u32_t uStackArgIndex; +extern void smp_parse_stack_args (int argc, char **argv); +extern void spl_do_dump (struct spl_pbuf *p, u16 direction); + +#define SPL_HAL_SEND_TRY 100000 + +#define SPL_HAL_MODULE "SPL_HAL_MODULE" +extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +/* structure to store the rx and tx packets. Put two per cache line as ports + * used in pairs */ +struct port_stats +{ + unsigned rx; + unsigned tx; + unsigned drop; + u64_t rx_size; + u64_t tx_size; + u64_t recv_last_cycles; + u64_t send_last_cycles; +} __attribute__ ((aligned (COMMON_CACHE_LINE_SIZE / 2))); + +struct port_capa +{ + u32_t tx_ipv4_cksum_offload; + u32_t tx_udp_cksum_offload; + u32_t tx_tcp_cksum_offload; +}; + +struct rx_pkts +{ + u16_t num; + u16_t index; + struct common_mem_mbuf *pkts[PKT_BURST]; +}; + +struct tx_pkts +{ + u16_t num; + struct common_mem_mbuf *pkts[PKT_BURST]; +}; + +struct port_pkts +{ + struct rx_pkts rx; + struct tx_pkts tx; +}; + +struct psd_header +{ + u32_t src_addr; /* IPaddress of source host. */ + u32_t dst_addr; /* IPaddress of destination host(s). */ + u8_t zero; /* zero. */ + u8_t proto; /* L4 protocol type. */ + u16_t len; /* L4 length. */ +} __attribute__ ((__packed__)); + +NSTACK_STATIC unsigned num_ports_NIC = 0; +NSTACK_STATIC unsigned num_ports_NIC_start = 0; + +struct stackx_port_info *head_used_port_list; +struct stackx_port_zone *p_stackx_port_zone = NULL; + +struct bond_ports_info bond_ports_array = {.cnt = 0 }; + +static u8_t bond_ports_array_cnt_start = 0; + +static struct port_capa spl_hal_capa = { 0 }; + +static struct port_pkts spl_hal_pkts[HAL_MAX_NIC_NUM]; + +NSTACK_STATIC inline u16_t +get_ipv4_16b_sum (u16_t * ptr16, u32_t nr) +{ + u32_t sum = 0; + + while (nr > 1) + { + sum += *ptr16; + nr -= sizeof (u16_t); + ptr16++; + + if (sum > UINT16_MAX) + { + sum -= UINT16_MAX; + } + } + + /* If length is in odd bytes */ + if (nr) + { + sum += *((u8_t *) ptr16); + } + + sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); + sum &= 0x0ffff; + return (u16_t) sum; +} + +NSTACK_STATIC inline u16_t +get_ipv4_bswap16 (u16_t x) +{ + return (u16_t) (((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8)); +} + +NSTACK_STATIC inline u16_t +get_ipv4_psd_sum (struct ip_hdr * iphdr, u64_t ol_flags) +{ + struct psd_header psd_hdr; + + psd_hdr.src_addr = iphdr->src.addr; + psd_hdr.dst_addr = iphdr->dest.addr; + psd_hdr.zero = 0; + psd_hdr.proto = iphdr->_proto; + + if (ol_flags & PKT_TX_TCP_SEG) + { + psd_hdr.len = 0; + } + else + { + psd_hdr.len = get_ipv4_bswap16 ((get_ipv4_bswap16 (iphdr->_len) + - sizeof (struct ip_hdr))); + } + + return get_ipv4_16b_sum ((u16_t *) & psd_hdr, sizeof (struct psd_header)); +} + +/* should be called after head_used_port_list is initialized */ +NSTACK_STATIC hal_hdl_t +get_port_hdl_by_name (const char *name) +{ + unsigned int i = 0; + struct stackx_port_info *p = p_stackx_port_zone->stackx_one_port; + + while (i < p_stackx_port_zone->port_num) + { + if (!strncasecmp (p->linux_ip.if_name, name, strlen (name))) + { + return p->linux_ip.hdl; + } + + p = &p_stackx_port_zone->stackx_one_port[++i]; + } + + NSPOL_LOGERR ("failed to find port id]name=%s", name); + return hal_get_invalid_hdl (); +} + +NSTACK_STATIC struct stackx_port_info * +get_port_info_by_name (const char *name) +{ + struct stackx_port_info *p = p_stackx_port_zone->stackx_one_port; + unsigned int i = 0; + + while (i < p_stackx_port_zone->port_num) + { + if (!strncasecmp (p->linux_ip.if_name, name, strlen (name))) + { + return p; + } + + p = &p_stackx_port_zone->stackx_one_port[++i]; + } + + return NULL; +} + +NSTACK_STATIC int +del_port_in_port_list (const char *name) +{ + struct stackx_port_info *inf = head_used_port_list; + struct stackx_port_info *prev = NULL; + + while (inf) + { + if (!strncasecmp (inf->linux_ip.if_name, name, strlen (name))) + { + if (prev != NULL) + { + prev->next_use_port = inf->next_use_port; + } + else + { + head_used_port_list = inf->next_use_port; + } + + break; + } + + prev = inf; + inf = inf->next_use_port; + } + + return 0; +} + +extern void create_netif (struct stackx_port_info *p_port_info); + +NSTACK_STATIC int +add_port_in_port_list (struct stackx_port_info *p) +{ + char *name; + struct stackx_port_info *inf = head_used_port_list; + struct stackx_port_info *prev = NULL; + + name = p->linux_ip.if_name; + + while (inf) + { + if (!strncasecmp (inf->linux_ip.if_name, name, strlen (name))) + { + NSPOL_LOGERR ("ERROR: add an existing port!"); + return -1; + } + + prev = inf; + inf = inf->next_use_port; + } + + if (prev == NULL) + { + head_used_port_list = p; + } + else + { + prev->next_use_port = p; + } + + p->next_use_port = NULL; + create_netif (p); + return 0; +} + +/* Queries the link status of a port and prints it to screen */ +NSTACK_STATIC void +report_port_link_status (struct stackx_port_info *p) +{ + /* get link status */ + u32 status; + + status = hal_link_status (p->linux_ip.hdl); + + if (status) + { + NSPOL_LOGINF (SC_DPDK_INFO, "Port=%s: Link Up", p->linux_ip.if_name); + } + else + { + NSPOL_LOGINF (SC_DPDK_INFO, "Port=%s: Link Down", p->linux_ip.if_name); + } +} + +int +spl_hal_ether_etoa (const unsigned char *e, int e_len, char *a, int a_len) +{ + char *c = a; + int i; + int retVal; + + if (!e || !a || e_len < 0) + return -1; + + if (e_len > NETIF_ETH_ADDR_LEN) + e_len = NETIF_ETH_ADDR_LEN; + + if (a_len < e_len * 3) + return -1; + + for (i = 0; i < e_len; i++) + { + if (i) + { + *c++ = ':'; + } + retVal = SPRINTF_S (c, a_len - (c - a), "%02x", e[i] & 0xff); + if (-1 == retVal) + { + NSPOL_LOGERR ("SPRINTF_S failed]ret=%d.", retVal); + return -1; + } + c = c + retVal; + } + + return 0; +} + +NSTACK_STATIC inline void +spl_hal_buf_convert (struct common_mem_mbuf *mbuf, struct spl_pbuf **buf) +{ + struct common_mem_mbuf *before = NULL; + struct spl_pbuf *last = NULL; + struct spl_pbuf *first = NULL; + struct spl_pbuf *tmp = NULL; + + while (mbuf != NULL) + { + //dpdk 2.1 + tmp = + (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf)); + res_alloc (&tmp->res_chk); + tmp->payload = common_pktmbuf_mtod (mbuf, void *); + tmp->tot_len = mbuf->pkt_len; + tmp->len = mbuf->data_len; + tmp->type = SPL_PBUF_HUGE; + tmp->proto_type = SPL_PBUF_PROTO_NONE; + tmp->next = NULL; + tmp->flags = 0; + + if (first == NULL) + { + first = tmp; + last = first; + } + else + { + /* Always the "if(first == NULL)" code segment is executed and then + "else" segment code is executed, so the "last" variable is not + NULL always when "else" case is executed */ + last->next = tmp; + last = tmp; + } + + before = mbuf; + mbuf = mbuf->next; + + before->next = NULL; + } + + *buf = first; +} + +NSTACK_STATIC int +spl_hal_port_zone_init () +{ + int retVal; + nsfw_mem_zone create_port_zone; + nsfw_mem_zone create_port_info; + struct stackx_port_info *mz_port_info; + INITPOL_LOGINF ("RTP", "spl_hal_port_zone_init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + + if ((CUR_CFG_HAL_PORT_NUM < 1) + || (SIZE_MAX / sizeof (struct stackx_port_info) < CUR_CFG_HAL_PORT_NUM)) + { + NSPOL_LOGERR ("malloc parameter incorrect]max_linux_port=%u", + CUR_CFG_HAL_PORT_NUM); + return -1; + } + + if (spl_snprintf + (create_port_zone.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + MP_STACKX_PORT_ZONE) < 0) + { + NSPOL_LOGERR ("spl_snprintf fail"); + + return -1; + } + + create_port_zone.stname.entype = NSFW_SHMEM; + create_port_zone.isocket_id = SOCKET_ID_ANY; + create_port_zone.length = sizeof (struct stackx_port_zone); + create_port_zone.ireserv = 0; + p_stackx_port_zone = + (struct stackx_port_zone *) nsfw_mem_zone_create (&create_port_zone); + + if (NULL == p_stackx_port_zone) + { + INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init", + "Cannot create memory zone for MP_STACKX_PORT_ZONE information", + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + common_exit (EXIT_FAILURE, + "Cannot create memory zone for MP_STACKX_PORT_ZONE information"); + } + + retVal = + MEMSET_S (p_stackx_port_zone, sizeof (struct stackx_port_zone), 0, + sizeof (struct stackx_port_zone)); + + if (EOK != retVal) + { + INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init", "MEMSET_S return fail", + retVal, MODULE_INIT_FAIL); + nsfw_mem_zone_release (&create_port_zone.stname); + return -1; + } + + if (spl_snprintf + (create_port_info.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + MP_STACKX_PORT_INFO) < 0) + { + NSPOL_LOGERR ("VSNPRINTF_S fail"); + return -1; + } + + create_port_info.stname.entype = NSFW_SHMEM; + create_port_info.isocket_id = SOCKET_ID_ANY; + create_port_info.length = + CUR_CFG_HAL_PORT_NUM * sizeof (struct stackx_port_info); + create_port_info.ireserv = 0; + mz_port_info = + (struct stackx_port_info *) nsfw_mem_zone_create (&create_port_info); + + if (NULL == mz_port_info) + { + INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init", + "Cannot create memory zone for MP_STACKX_PORT_INFO information", + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + common_exit (EXIT_FAILURE, + "Cannot create memory zone for MP_STACKX_PORT_INFO information"); + } + + retVal = + MEMSET_S (mz_port_info, create_port_info.length, 0, + create_port_info.length); + + if (EOK != retVal) + { + INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init", "MEMSET_S return fail", + retVal, MODULE_INIT_FAIL); + nsfw_mem_zone_release (&create_port_info.stname); + nsfw_mem_zone_release (&create_port_zone.stname); + return -1; + } + + MEM_STAT (SPL_HAL_MODULE, create_port_zone.stname.aname, NSFW_SHMEM, + create_port_info.length); + + p_stackx_port_zone->stackx_one_port = mz_port_info; + + INITPOL_LOGINF ("RTP", "spl_hal_port_zone_init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + + return 0; +} + +int +spl_hal_init (int argc, char *argv[]) +{ + int retval = -1; + int idx_init; + + NSPOL_LOGINF (SC_DPDK_INFO, "spl_hal_init start"); + + /* Get nstack args */ + smp_parse_stack_args (argc, argv); + + if (0 == uStackArgIndex) + { + NSPOL_LOGERR ("uStackArgIndex is 0, can lead to long loop]"); + return retval; + } + + /* Init DPDK */ + argc = uStackArgIndex--; + INITPOL_LOGINF ("RTP", "hal_init_global", NULL_STRING, LOG_INVALID_VALUE, + MODULE_INIT_START); + + for (idx_init = 0; idx_init < argc; idx_init++) + { + NSPOL_LOGINF (SC_DPDK_INFO, + "hal_init_global]idx_init=%d,argv[idx_init]=%s", idx_init, + argv[idx_init]); + } + + retval = hal_init_global (argc, argv); + + if (0 != retval) + { + NSPOL_LOGERR ("call hal_init_global fail]retval = %d", retval); + return -1; + } + + retval = hal_init_local (); + + if (0 != retval) + { + NSPOL_LOGERR ("call hal_init_local fail]retval = %d", retval); + return -1; + } + + retval = spl_hal_port_zone_init (); + if (0 != retval) + { + NSPOL_LOGERR ("call hal_init_local fail]retval = %d", retval); + return -1; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "Finished Process Init"); + + return 0; + +} + +static inline int +spl_hal_rx_mbuf_free (void *data, void *arg) +{ + struct spl_pbuf *tmp = NULL; + struct common_mem_mbuf *mbuf = (struct common_mem_mbuf *) data; + (void) arg; + + tmp = (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf)); + if (tmp->res_chk.alloc_flag == TRUE) + return 1; + + if (common_mbuf_refcnt_read (mbuf) == 0) + return 1; + + NSPOL_LOGDBG (SC_DPDK_INFO, "rx_pool init in fault case: free mbuf=%p", + mbuf); + spl_mbuf_free (mbuf); + return 0; +} + +struct common_mem_mempool * +spl_hal_rx_pool_create (int nic_id, int queue_id, int start_type) +{ + int retval; + struct common_mem_mempool *mp; + nsfw_mem_mbfpool create_mbuf_pool; + nsfw_mem_name lookup_mbuf_pool; + struct common_mem_ring *ring; + + if (start_type == 1) + { + create_mbuf_pool.stname.entype = NSFW_SHMEM; + create_mbuf_pool.uscash_size = 0; + create_mbuf_pool.uspriv_size = 0; + create_mbuf_pool.isocket_id = SOCKET_ID_ANY; + create_mbuf_pool.enmptype = NSFW_MRING_SPSC; + + retval = + spl_snprintf (create_mbuf_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, + "%s", get_mempoll_rx_name (queue_id, nic_id)); + + if (-1 == retval) + { + NSPOL_LOGERR ("spl_snprintf fail"); + return NULL; + } + + create_mbuf_pool.usnum = RX_MBUF_POOL_SIZE - 1; + /*performance, rx buf cap is special, ((size - HEADROOM) >> 10) <<10, see ixgbe_dev_rx_init; + if want cap size == TX_MBUF_MAX_LEN, must let data_root=TX_MBUF_MAX_LEN+COMMON_PKTMBUF_HEADROOM and + TX_MBUF_MAX_LEN must N*1024; + */ + create_mbuf_pool.usdata_room = + TX_MBUF_MAX_LEN + COMMON_PKTMBUF_HEADROOM; + + NSPOL_LOGDBG (SC_DPDK_INFO, "hal_rx_pool.usnum=%u, usdata_room=%u", + create_mbuf_pool.usnum, create_mbuf_pool.usdata_room); + + mp = + (struct common_mem_mempool *) + nsfw_mem_mbfmp_create (&create_mbuf_pool); + + if (mp == NULL) + { + NSPOL_LOGERR ("nsfw_mem_mbfmp_create fail"); + return NULL; + } + + MEM_STAT (SPL_HAL_MODULE, create_mbuf_pool.stname.aname, NSFW_SHMEM, + nsfw_mem_get_len (mp, NSFW_MEM_MBUF)); + NSPOL_LOGDBG (SC_DPDK_INFO, "create:thread=%d,nic_id=%d,mp=%p,size=%d", + queue_id, nic_id, mp, nsfw_mem_get_len (mp, + NSFW_MEM_MBUF)); + + char rx_msg_arr_name[NSFW_MEM_NAME_LENGTH]; + data_com_msg *rx_msg_array = NULL; + retval = spl_snprintf (rx_msg_arr_name, NSFW_MEM_NAME_LENGTH, "%s", + get_mempoll_rxmsg_name (queue_id, nic_id)); + + if (-1 != retval) + { + rx_msg_array = (data_com_msg *) sbr_create_mzone (rx_msg_arr_name, + (size_t) + sizeof + (data_com_msg) * + RX_MBUF_POOL_SIZE); + } + + if (!rx_msg_array) + { + NSSBR_LOGERR + ("Create rx_msg_array zone fail]name=%s, num=%u, size=%zu", + rx_msg_arr_name, RX_MBUF_POOL_SIZE, + (size_t) sizeof (data_com_msg) * RX_MBUF_POOL_SIZE); + } + else + { + /*bind msg to pbuf */ + MEM_STAT (SPL_HAL_MODULE, rx_msg_arr_name, NSFW_SHMEM, + (size_t) sizeof (data_com_msg) * RX_MBUF_POOL_SIZE); + NSSBR_LOGINF + ("Create rx_msg_array zone ok]name=%s, ptr=%p, num=%u, size=%zu", + rx_msg_arr_name, rx_msg_array, RX_MBUF_POOL_SIZE, + sizeof (data_com_msg) * RX_MBUF_POOL_SIZE); + + struct common_mem_mbuf *mbuf = NULL; + struct spl_pbuf *buf = NULL; + u32 loop = 0; + + for (; loop < RX_MBUF_POOL_SIZE; loop++) + { + mbuf = nsfw_mem_mbf_alloc (mp, NSFW_SHMEM); + + if (!mbuf) + { + /* alloc failed , still can work, no prebind success just not so faster */ + NSSBR_LOGERR + ("nsfw_mem_mbf_alloc failed,this can not happen"); + break; + } + + buf = + (struct spl_pbuf *) ((char *) mbuf + + sizeof (struct common_mem_mbuf)); + sys_sem_init (&rx_msg_array[loop].param.op_completed); + rx_msg_array[loop].param.msg_from = NULL; + buf->msg = (void *) &rx_msg_array[loop]; + (void) res_free (&buf->res_chk); //no need to check return value, as it will do free operation depends on alloc_flag + + if (nsfw_mem_mbf_free (mbuf, NSFW_SHMEM) < 0) + { + /* free failed , still can work, no prebind work just not so faster */ + NSSBR_LOGERR + ("nsfw_mem_mbf_free failed,this can not happen"); + break; + } + } + + } + + } + else + { + retval = + spl_snprintf (lookup_mbuf_pool.aname, NSFW_MEM_NAME_LENGTH - 1, "%s", + get_mempoll_rx_name (queue_id, nic_id)); + + if (-1 == retval) + { + NSPOL_LOGERR ("spl_snprintf fail"); + return NULL; + } + + lookup_mbuf_pool.entype = NSFW_SHMEM; + lookup_mbuf_pool.enowner = NSFW_PROC_MAIN; + mp = + (struct common_mem_mempool *) + nsfw_mem_mbfmp_lookup (&lookup_mbuf_pool); + + if (mp == NULL) + { + NSPOL_LOGERR ("nsfw_mem_mbfmp_lookup fail, name=%s, try to create", + lookup_mbuf_pool.aname); + return spl_hal_rx_pool_create (nic_id, queue_id, 1); + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "lookup:thread=%d,nic_id=%d,mp=%p,size=%d", + queue_id, nic_id, mp, nsfw_mem_get_len (mp, + NSFW_MEM_MBUF)); + + /*We have to recycle RX mbufs hold by DPDK when fault recovering of upgrading nstack */ + if (start_type == 3 || start_type == 2) + { + ring = (struct common_mem_ring *) (mp->pool_data); + NSPOL_LOGINF (SC_DPDK_INFO, + "BEFORE clear rx_mpool]prod.head=%u, prod.tail=%u, " + "cons.head=%u, cons.tail=%u", ring->prod.head, + ring->prod.tail, ring->cons.head, ring->cons.tail); + + if (nsfw_mem_mbuf_iterator (mp, 0, mp->size, + spl_hal_rx_mbuf_free, NULL) < 0) + { + NSPOL_LOGERR ("nsfw_mem_mbuf_iterator return fail"); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, + "AFTER clear rx_mpool]prod.head=%u, prod.tail=%u, " + "cons.head=%u, cons.tail=%u", ring->prod.head, + ring->prod.tail, ring->cons.head, ring->cons.tail); + } + + } + + return mp; + +} + +int +spl_hal_bond_config (struct network_configuration *network) +{ + struct phy_net *phynet = network->phy_net; + struct ref_nic *phead = phynet->header; + static u8_t bond_index = 0; /* for auto-generating bond_name */ + unsigned int check_bond = 0, check_name; + int retVal; + u8_t j, k, idx = 0; + + /* get bond info from network configuration */ + if (phynet->bond_mode != -1 && bond_ports_array.cnt < MAX_BOND_PORT_NUM) + { + struct ref_nic *phead_bond = phead; + char *name = phynet->bond_name; + struct bond_set *s = &bond_ports_array.ports[bond_ports_array.cnt]; + + while (phead_bond != NULL) + { + /* check slave name, repeated slave nic cannot be added to bond set. */ + check_name = 0; + + for (j = 0; j < idx; j++) + { + if (strcmp (s->slave_ports[j], phead_bond->nic_name) == 0) + { + check_name = 1; + break; + } + } + + if (check_name) + { + break; + } + + /* if this nic has been added to a bond_set, ignore it */ + check_bond = 0; + + for (k = 0; k < bond_ports_array.cnt && !check_bond; k++) + { + for (j = 0; + j < bond_ports_array.ports[k].slave_port_cnt + && !check_bond; j++) + { + if (strcmp + (bond_ports_array.ports[k].slave_ports[j], + phead_bond->nic_name) == 0) + { + check_bond = 1; + + if (name[0] == 0) + { + retVal = + STRNCPY_S (name, IP_MODULE_MAX_NAME_LEN, + bond_ports_array. + ports[k].bond_port_name, + strlen (bond_ports_array. + ports[k].bond_port_name)); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRNCPY_S failed]ret=%d.", + retVal); + return -1; + } + } + + if (strcmp + (name, + bond_ports_array.ports[k].bond_port_name) != 0) + { + NSOPR_SET_ERRINFO (-1, "%s init failed!\n", name); + NSPOL_LOGERR + ("%s init failed! %s in both %s and %s", name, + phead_bond->nic_name, name, + bond_ports_array.ports[k].bond_port_name); + return -1; + } + } + } + } + + if (check_bond == 1) + { + break; + } + + /* copy slave ports name to bond array */ + retVal = + STRNCPY_S (s->slave_ports[idx], HAL_MAX_NIC_NAME_LEN, + phead_bond->nic_name, strlen (phead_bond->nic_name)); + + if (EOK != retVal) + { + NSPOL_LOGERR ("STRNCPY_S failed]ret=%d.", retVal); + return -1; + } + + idx++; + phead_bond = phead_bond->next; + + if (idx >= HAL_MAX_SLAVES_PER_BOND) + { + break; + } + } + + if (check_bond == 0) + { + if (name[0] == 0) + { + /* if bond_name is a empty string, generate a new bond name */ + retVal = + SPRINTF_S (name, HAL_MAX_NIC_NAME_LEN, "bond%u_auto", + bond_index++); + + if (-1 == retVal) + { + NSPOL_LOGERR ("SPRINTF_S failed]ret=%d.", retVal); + return -1; + } + } + + /* copy bond_name to bond array */ + retVal = + STRNCPY_S (s->bond_port_name, HAL_MAX_NIC_NAME_LEN, name, + strlen (name)); + + if (EOK != retVal) + { + NSPOL_LOGERR ("STRNCPY_S failed]ret=%d.", retVal); + return -1; + } + + s->slave_port_cnt = idx; + bond_ports_array.cnt++; + NSPOL_LOGINF (SC_DPDK_INFO, + "bond_ports_array.cnt=%u,slave_port_cnt=%u", + bond_ports_array.cnt, s->slave_port_cnt); + } + } + + return 0; +} + +int +spl_hal_port_config (unsigned int *port_num) +{ + int retVal; + unsigned int check; + struct phy_net *phynet; + + struct network_configuration *network = get_network_list (); + + if (!network) + { + NSPOL_LOGERR ("fail to get_provider_node"); + return -1; + } + + unsigned int port_index = p_stackx_port_zone->port_num; + + while (network && (phynet = network->phy_net)) + { + struct ref_nic *phead = phynet->header; + NSPOL_LOGINF (SC_DPDK_INFO, "network=%p,network_name=%s", network, + network->network_name); + + if (spl_hal_bond_config (network) < 0) + { + NSPOL_LOGERR ("spl_hal_bond_config fail."); + return -1; + } + + while (phead != NULL) + { + /* check if the NIC is inited */ + for (check = 0; check < port_index; ++check) + { + if (strcmp + (p_stackx_port_zone->stackx_one_port[check]. + linux_ip.if_name, phead->nic_name) == 0) + { + break; + } + } + + if (check != port_index) + { + phead = phead->next; + continue; + } + + /* check if the number of VF exceeds MAX_VF_NUM */ + if (port_index >= MAX_VF_NUM + p_stackx_port_zone->bonded_port_num) + { + NSOPR_SET_ERRINFO (-1, "Support Only %d VF. %s init failed!\n", + MAX_VF_NUM, phead->nic_name); + NSPOL_LOGERR ("Support Only %d VF. %s init failed!", MAX_VF_NUM, + phead->nic_name); + NSOPR_SET_ERRINFO (-1, "Add network %s failed!\n", + network->network_name); + break; + } + + if (strlen (phead->nic_name) >= + sizeof (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name) - 1 + || strlen (phead->nic_name) <= 3) + { + NSPOL_LOGERR ("Invalid configuration"); + return -1; + } + + retVal = + STRCPY_S (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name, + sizeof (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name), + phead->nic_name); + + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "if_name %s", + p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name); + retVal = + STRCPY_S (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.ip_addr_linux, + sizeof (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip. + ip_addr_linux), "0.0.0.0"); + + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + retVal = + STRCPY_S (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.mask_linux, + sizeof (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip. + mask_linux), "0.0.0.0"); + + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + retVal = + STRCPY_S (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.bcast_linux, + sizeof (p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip. + bcast_linux), "0.0.0.0"); + + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + ++port_index; + NSPOL_LOGINF (SC_DPDK_INFO, "port_index=%u", port_index); + + if (CUR_CFG_HAL_PORT_NUM <= port_index + bond_ports_array.cnt) + { + // TODO: Invalid configuration received, return immediately + NSPOL_LOGERR + ("Insufficient nStack configuration when compared to configuration from network.json"); + return -1; + } + + /* [TA33636] [2017-04-11] Do not need provider.json */ + if (phynet->bond_mode == + -1 /*&& strncmp(network->network_name, "provider", 8) != 0 */ ) + { + break; + } + else + { + phead = phead->next; + } + } + + network = network->next; + } + + *port_num = port_index; + + return ERR_OK; +} + +void +spl_hal_capa_init () +{ + u32_t ipv4_cksum_offload = 1; + u32_t udp_cksum_offload = 1; + u32_t tcp_cksum_offload = 1; + hal_netif_capa_t info = { 0 }; + struct stackx_port_info *p_port_info = head_used_port_list; + + while (p_port_info) + { + hal_get_capability (p_port_info->linux_ip.hdl, &info); + + if ((info.tx_offload_capa & HAL_ETH_TX_OFFLOAD_IPV4_CKSUM) == 0) + { + ipv4_cksum_offload = 0; + + NSPOL_LOGDBG (SC_DPDK_INFO, "Port %s TX_OFFLOAD_IPV4_CKSUM Disable", + p_port_info->linux_ip.if_name); + } + + if ((info.tx_offload_capa & HAL_ETH_TX_OFFLOAD_UDP_CKSUM) == 0) + { + udp_cksum_offload = 0; + + NSPOL_LOGDBG (SC_DPDK_INFO, "Port %s TX_OFFLOAD_UDP_CKSUM Disable", + p_port_info->linux_ip.if_name); + } + + if ((info.tx_offload_capa & HAL_ETH_TX_OFFLOAD_TCP_CKSUM) == 0) + { + tcp_cksum_offload = 0; + + NSPOL_LOGDBG (SC_DPDK_INFO, "Port %s TX_OFFLOAD_TCP_CKSUM Disable", + p_port_info->linux_ip.if_name); + } + + p_port_info = p_port_info->next_use_port; + } + + spl_hal_capa.tx_ipv4_cksum_offload = ipv4_cksum_offload; + spl_hal_capa.tx_udp_cksum_offload = udp_cksum_offload; + spl_hal_capa.tx_tcp_cksum_offload = tcp_cksum_offload; + + NSPOL_LOGINF (SC_DPDK_INFO, + "ipv4_cksum_offload(%u),udp_cksum_offload(%u),tcp_cksum_offload(%u)", + ipv4_cksum_offload, udp_cksum_offload, tcp_cksum_offload); + +} + +NSTACK_STATIC void +spl_hal_bond_info_init (hal_hdl_t hdl, struct bond_set *s, + struct stackx_port_info *p) +{ +#define MAX_MAC_STR_LEN 20 + char mac_string[MAX_MAC_STR_LEN]; + int retVal; + struct ether_addr addr; + + p->linux_ip.hdl = hdl; + + struct stackx_port_info *slave_port; + slave_port = get_port_info_by_name (s->slave_ports[0]); + + if (slave_port == NULL) + { + NSPOL_LOGERR ("get_port_info_by_name failed]bond_port_name=%s", + s->bond_port_name); + return; + } + + /* check the lenght of bond_port_name */ + retVal = + STRCPY_S (p->linux_ip.if_name, sizeof (p->linux_ip.if_name), + s->bond_port_name); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal); + return; + } + + hal_get_macaddr (hdl, &addr); + retVal = + spl_hal_ether_etoa (addr.addr_bytes, sizeof (addr.addr_bytes), mac_string, + sizeof (mac_string)); + if (retVal < 0) + { + NSPOL_LOGERR ("spl_hal_ether_etoa failed]ret=%d", retVal); + return; + } + + retVal = + STRCPY_S (p->linux_ip.mac_addr, sizeof (p->linux_ip.mac_addr), + mac_string); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal); + return; + } + + retVal = + STRCPY_S (p->linux_ip.ip_addr_linux, sizeof (p->linux_ip.ip_addr_linux), + slave_port->linux_ip.ip_addr_linux); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal); + return; + } + + retVal = + STRCPY_S (p->linux_ip.mask_linux, sizeof (p->linux_ip.mask_linux), + slave_port->linux_ip.mask_linux); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal); + return; + } + + retVal = + STRCPY_S (p->linux_ip.bcast_linux, sizeof (p->linux_ip.bcast_linux), + slave_port->linux_ip.bcast_linux); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal); + return; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "===== the bond port info ======"); + NSPOL_LOGINF (SC_DPDK_INFO, "bond port name=%s", p->linux_ip.if_name); + NSPOL_LOGINF (SC_DPDK_INFO, "bond port mac=%s", p->linux_ip.mac_addr); + NSPOL_LOGINF (SC_DPDK_INFO, "bond port ip=%s", p->linux_ip.ip_addr_linux); + NSPOL_LOGINF (SC_DPDK_INFO, "bond port netmask=%s", p->linux_ip.mask_linux); + NSPOL_LOGINF (SC_DPDK_INFO, "bond port broad_cast addr=%s", + p->linux_ip.bcast_linux); + +} + +NSTACK_STATIC int +spl_hal_bond_start (void) +{ + u8_t i, j = 0; + struct stackx_port_info *bond_port = NULL; + hal_hdl_t hdl; + hal_hdl_t slave_hdl[HAL_MAX_SLAVES_PER_BOND]; + + NSPOL_LOGINF (SC_DPDK_INFO, "bond_ports_array.cnt=%u", + bond_ports_array.cnt); + + for (i = bond_ports_array_cnt_start; i < bond_ports_array.cnt; i++) + { + struct bond_set *s = &bond_ports_array.ports[i]; + NSPOL_LOGINF (SC_DPDK_INFO, "i=%u,bond_port_name=%s", i, + s->bond_port_name); + + u8_t slave_num = 0; + for (j = 0; j < s->slave_port_cnt; j++) + { + NSPOL_LOGINF (SC_DPDK_INFO, "s->slave_ports[%u]=%s", j, + s->slave_ports[j]); + hdl = get_port_hdl_by_name (s->slave_ports[j]); + + if (!hal_is_valid (hdl)) + { + continue; + } + + slave_hdl[slave_num++] = hdl; + + /* here we didn't release the port mem allocated in p_stackx_port_zone */ + del_port_in_port_list (s->slave_ports[j]); + } + + hdl = hal_bond (s->bond_port_name, slave_num, slave_hdl); + + if (!hal_is_valid (hdl)) + { + NSPOL_LOGERR ("hal_bond fail: bond_name =%s", s->bond_port_name); + return -1; + } + + bond_port = + &p_stackx_port_zone->stackx_one_port[p_stackx_port_zone->port_num]; + num_ports_NIC++; + p_stackx_port_zone->port_num++; + p_stackx_port_zone->bonded_port_num++; + + spl_hal_bond_info_init (hdl, s, bond_port); + add_port_in_port_list (bond_port); + + } + + bond_ports_array_cnt_start = bond_ports_array.cnt; + return 0; +} + +/* + * Initialises a given port using global settings and with the rx buffers + * coming from the mbuf_pool passed as parameter + */ + +NSTACK_STATIC inline int +spl_hal_port_start (uint16_t nic_id, struct stackx_port_info *p_port_info, + u16_t num_queues) +{ + u16_t num_queues_request, q; + hal_hdl_t hdl; + struct common_mem_mempool *mp; + hal_netif_config_t conf; +#define MAX_MAC_STR_LEN 20 + char mac_string[MAX_MAC_STR_LEN]; + int retVal; + struct ether_addr addr; + + // change the queues number per configuration. + // even we only receive packets from one rx queue when dispatch mode is on, the tx queue + // shoule set to the queues number requested. + num_queues_request = num_queues; + if (num_queues_request > HAL_ETH_MAX_QUEUE_NUM) + { + NSPOL_LOGERR + ("no enougth queue num for thread!]num_queues_request=%u,MAX_QUEUE_NUM=%u", + num_queues_request, HAL_ETH_MAX_QUEUE_NUM); + return -1; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "# Initialising index=%s... ", + p_port_info->linux_ip.if_name); + /* used to have fflush,no use code ,remove it. */ + + conf.bit.hw_vlan_filter = 1; + conf.bit.hw_vlan_strip = 1; + + conf.rx.queue_num = num_queues_request; + conf.tx.queue_num = num_queues_request; + + for (q = 0; q < num_queues_request; q++) + { + mp = + (struct common_mem_mempool *) spl_hal_rx_pool_create (nic_id, q, 1); + + if (mp == NULL) + { + NSPOL_LOGERR + ("spl_hal_rx_pool_create fail]mp=NULL,nic_id=%u,if_name=%s", + nic_id, p_port_info->linux_ip.if_name); + return -1; + } + + (void) spl_reg_res_txrx_mgr ((mpool_handle *) mp); // will only return 0, no need to check return value + conf.rx.ring_pool[q] = mp; + conf.rx.ring_size[q] = HAL_RX_RING_SIZE; + conf.tx.ring_size[q] = HAL_TX_RING_SIZE; + } + + hdl = hal_create (p_port_info->linux_ip.if_name, &conf); + + if (!hal_is_valid (hdl)) + { + NSPOL_LOGERR ("hal_create fail]if_name =%s", + p_port_info->linux_ip.if_name); + return -1; + } + + p_port_info->linux_ip.hdl = hdl; + + /* add mac address */ + hal_get_macaddr (hdl, &addr); + retVal = + spl_hal_ether_etoa (addr.addr_bytes, sizeof (addr.addr_bytes), mac_string, + sizeof (mac_string)); + if (retVal < 0) + { + NSPOL_LOGERR ("spl_hal_ether_etoa failed]ret=%d", retVal); + return -1; + } + + retVal = + STRCPY_S (p_port_info->linux_ip.mac_addr, + sizeof (p_port_info->linux_ip.mac_addr), mac_string); + if (EOK != retVal) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal); + return -1; + } + + return 0; +} + +NSTACK_STATIC int +spl_hal_port_setup () +{ + unsigned int i; + struct stackx_port_info *p_port_info = NULL; + + INITPOL_LOGINF ("RTP", "spl_hal_port_setup", NULL_STRING, LOG_INVALID_VALUE, + MODULE_INIT_START); + + for (i = num_ports_NIC_start; i < num_ports_NIC; i++) + { + p_port_info = &(p_stackx_port_zone->stackx_one_port[i]); + + if (spl_hal_port_start (i, p_port_info, (u16_t) 1) < 0) + { + NSPOL_LOGERR ("Error initialising]nic_id=%u", i); + + INITPOL_LOGERR ("RTP", "spl_hal_port_setup", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + + return -1; + } + else + { + report_port_link_status (p_port_info); + add_port_in_port_list (p_port_info); + } + } + + if (spl_hal_bond_start () < 0) + { + NSPOL_LOGERR ("bond port init failed!"); + + INITPOL_LOGERR ("RTP", "spl_hal_port_setup", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + + return -1; + } + + spl_hal_capa_init (); + + INITPOL_LOGINF ("RTP", "spl_hal_port_setup", NULL_STRING, LOG_INVALID_VALUE, + MODULE_INIT_SUCCESS); + + return 0; + +} + +int +spl_hal_port_init () +{ + int retval; + unsigned int i, port_num = 0; + + int port_num_start = p_stackx_port_zone->port_num; + num_ports_NIC_start = num_ports_NIC; + + //Read network info + INITPOL_LOGINF ("IP", "spl_hal_port_config", NULL_STRING, LOG_INVALID_VALUE, + MODULE_INIT_START); + retval = spl_hal_port_config (&port_num); + + if (retval != ERR_OK) + { + INITPOL_LOGERR ("IP", "spl_hal_port_config", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + return -1; + } + + p_stackx_port_zone->port_num = port_num; + + NSPOL_LOGINF (SC_DPDK_INFO, "port_num=%u", port_num); + INITPOL_LOGINF ("IP", "spl_hal_port_config", NULL_STRING, LOG_INVALID_VALUE, + MODULE_INIT_SUCCESS); + + if (port_num_start == p_stackx_port_zone->port_num) + { + NSPOL_LOGERR ("No new NIC find."); + return 0; + } + + //Get ports num + for (i = port_num_start; i < p_stackx_port_zone->port_num; i++) + { + if (p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name[0] != 0) + { + /* right now hard coded, */ + int eth_num = + atoi (p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name + + 3); + + num_ports_NIC++; + + NSPOL_LOGDBG (SC_DPDK_INFO, "port_mask=%d ,eth_name=%s", eth_num, + p_stackx_port_zone->stackx_one_port[i]. + linux_ip.if_name); + } + } + + if (num_ports_NIC > HAL_MAX_NIC_NUM) + { + NSPOL_LOGERR ("just support one eth"); + common_exit (EXIT_FAILURE, "just surport one eth"); + } + + if (num_ports_NIC == num_ports_NIC_start) + { + NSPOL_LOGERR ("No new NIC find."); + return 0; + } + + retval = spl_hal_port_setup (); + + if (retval == -1) + { + return -1; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "Finished Process Init."); + + return 1; +} + +inline NSTACK_STATIC void +spl_hal_send (struct netif *pnetif) +{ + u16_t i, sent = 0; + struct netifExt *pnetifExt = NULL; + u16_t netif_id = pnetif->num; + u16_t tx_num = spl_hal_pkts[netif_id].tx.num; + struct common_mem_mbuf **tx_ptks = spl_hal_pkts[netif_id].tx.pkts; + + for (i = 0; i < tx_num; i++) + { + (void) + res_free (& + (((struct spl_pbuf *) (((char *) tx_ptks[i]) + + sizeof (struct + common_mem_mbuf)))->res_chk)); + } + + int _retry = 0; + + pnetifExt = getNetifExt (pnetif->num); + if (NULL == pnetifExt) + return; + + do + { + sent += + hal_send_packet (pnetifExt->hdl, 0, &(tx_ptks[sent]), tx_num - sent); + _retry++; + + if (_retry > SPL_HAL_SEND_TRY) + { + NSPOL_LOGERR ("send loop %d times but dpdk send data fail ", + SPL_HAL_SEND_TRY); + break; + } + } + while (unlikely (sent != tx_num)); + + if (unlikely (sent != tx_num)) + { + for (i = sent; i < tx_num; i++) + { + (void) nsfw_mem_mbf_free ((mbuf_handle) (tx_ptks[i]), NSFW_SHMEM); + } + } + for (i = 0; i < tx_num; i++) + { + /* set dpdk_send flag */ + ((struct spl_pbuf *) (((char *) tx_ptks[i]) + + sizeof (struct common_mem_mbuf)))-> + res_chk.u8Reserve |= DPDK_SEND_FLAG; + } + + spl_hal_pkts[netif_id].tx.num = 0; + +} + +inline u16_t +spl_hal_recv (struct netif *pnetif, u8_t id) +{ + u16_t netif_id, rx_c = 0; + struct netifExt *pnetifExt = NULL; + + netif_id = pnetif->num; + + pnetifExt = getNetifExt (pnetif->num); + if (NULL == pnetifExt) + return 0; + + rx_c = + hal_recv_packet (pnetifExt->hdl, 0, spl_hal_pkts[netif_id].rx.pkts, + PKT_BURST); + + if (rx_c <= 0) + { + return 0; + } + + spl_hal_pkts[netif_id].rx.num = rx_c; + spl_hal_pkts[netif_id].rx.index = 0; + + return rx_c; +} + +/*needflush set 1 has pbuf release problem, ref maybe set 0 before release*/ +NSTACK_STATIC inline void +spl_hal_set_cksum (struct spl_pbuf *buf, struct common_mem_mbuf *mbuf) +{ + + //need to be careful, special when small packet oversize + if (buf->tot_len > mbuf->pkt_len) + { + NSPOL_LOGWAR (SC_DPDK_INFO, + "small packet OVERSIZE]pbuf_len=%u,mbuf_len=%u", buf->len, + mbuf->pkt_len); + mbuf->pkt_len = buf->len; + } + + if (!spl_hal_tx_ip_cksum_enable () || !spl_hal_tx_tcp_cksum_enable () + || !spl_hal_tx_udp_cksum_enable ()) + { + struct tcp_hdr *t_hdr; + struct udp_hdr *u_hdr; + u16_t flag_offset; + u64_t ol_flags = (mbuf->ol_flags); //& (~PKT_TX_L4_MASK)); + + struct eth_hdr *ethhdr = (struct eth_hdr *) ((char *) buf->payload); + + if (ethhdr->type == 8) + { + struct ip_hdr *iphdr = + (struct ip_hdr *) ((char *) buf->payload + + sizeof (struct eth_hdr)); + + if (!spl_hal_tx_ip_cksum_enable ()) + { + ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM; + iphdr->_chksum = 0; + } + + flag_offset = spl_ntohs (iphdr->_offset); + + /*ip frag, only the first packet has udp or tcp head */ + if (0 == (flag_offset & IP_OFFMASK)) + { + switch (iphdr->_proto) + { + case IPPROTO_TCP: + if (!spl_hal_tx_tcp_cksum_enable ()) + { + t_hdr = + (struct tcp_hdr *) ((char *) buf->payload + + sizeof (struct eth_hdr) + + sizeof (struct ip_hdr)); + t_hdr->chksum = get_ipv4_psd_sum (iphdr, ol_flags); + ol_flags |= PKT_TX_TCP_CKSUM; + } + + break; + + case IPPROTO_UDP: + { + if ((mbuf->ol_flags & PKT_TX_UDP_CKSUM) == + PKT_TX_UDP_CKSUM) + { + u_hdr = (struct udp_hdr *) ((char *) buf->payload + sizeof (struct eth_hdr) + sizeof (struct ip_hdr)); //l2_len + l3_len); + u_hdr->chksum = + get_ipv4_psd_sum (iphdr, mbuf->ol_flags); + } + } + + break; + + default: + + break; + } + } + mbuf->l2_len = sizeof (struct eth_hdr); //l2_len; + mbuf->l3_len = sizeof (struct ip_hdr); + mbuf->ol_flags = ol_flags; + } + } +} + +/*needflush set 1 has pbuf release problem, ref maybe set 0 before release*/ +err_t +spl_hal_output (struct netif *pnetif, struct pbuf *buf) +{ + u16_t netif_id, idx; + struct common_mem_mbuf *mbuf; + struct spl_pbuf *spbuf = NULL; + //spl_pbuf_layer layer = SPL_PBUF_TRANSPORT; + //u16_t offset; + + if (!p_def_stack_instance) + { + NSPOL_LOGERR ("p_def_stack_instance is NULL"); + return -1; + } + + u16_t proc_id = spl_get_lcore_id (); + + NSPOL_LOGINF (SC_DPDK_INFO, "spl_hal_output. len %d totlen %d", buf->len, + buf->tot_len); + print_pbuf_payload_info (buf, true); + + if (buf->tot_len > DEF_MBUF_DATA_SIZE) + { + NSPOL_LOGINF (TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return ERR_MEM; + + } + spbuf = spl_pbuf_alloc_hugepage (SPL_PBUF_RAW, + buf->tot_len, + SPL_PBUF_HUGE, proc_id, NULL); + + if (!spbuf) + { + NSPOL_LOGINF (TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return ERR_MEM; + } + + if (ERR_OK != pbuf_to_splpbuf_copy (spbuf, buf)) + { + NSPOL_LOGERR ("pbuf to splpbuf copy failed"); + return -1; + } + + mbuf = + (struct common_mem_mbuf *) ((char *) spbuf - + sizeof (struct common_mem_mbuf)); + + if (spbuf->tot_len > mbuf->pkt_len) + { + NSPOL_LOGWAR (SC_DPDK_INFO, + "small packet OVERSIZE]pbuf_len=%u,mbuf_len=%u", + spbuf->len, mbuf->pkt_len); + mbuf->pkt_len = spbuf->len; + } + + spl_hal_set_cksum (spbuf, mbuf); + + netif_id = pnetif->num; + idx = spl_hal_pkts[netif_id].tx.num++; + spl_hal_pkts[netif_id].tx.pkts[idx] = mbuf; + spl_do_dump (spbuf, DUMP_SEND); + spl_hal_send (pnetif); + + return 0; +} + +void +spl_hal_input (struct netif *pnetif, struct spl_pbuf **buf) +{ + u16_t netif_id; + + struct common_mem_mbuf *mbuf; + + netif_id = pnetif->num; + + if (likely + (spl_hal_pkts[netif_id].rx.num > spl_hal_pkts[netif_id].rx.index)) + { + mbuf = spl_hal_pkts[netif_id].rx.pkts[spl_hal_pkts[netif_id].rx.index]; + spl_hal_pkts[netif_id].rx.index++; + spl_hal_buf_convert (mbuf, buf); + spl_do_dump (*buf, DUMP_RECV); + } + else + { + NSPOL_LOGERR + ("recv from spl_dev has a problem]pnetif=%p, num=%u, index=%u", + pnetif, spl_hal_pkts[netif_id].rx.num, + spl_hal_pkts[netif_id].rx.index); + *buf = NULL; + } + return; +} + +int +spl_hal_tx_ip_cksum_enable () +{ + return !spl_hal_capa.tx_ipv4_cksum_offload; +} + +int +spl_hal_tx_udp_cksum_enable () +{ + return !spl_hal_capa.tx_udp_cksum_offload; +} + +int +spl_hal_tx_tcp_cksum_enable () +{ + return !spl_hal_capa.tx_tcp_cksum_offload; +} + +u32 +spl_hal_is_nic_exist (const char *name) +{ + return hal_is_nic_exist (name); +} + +int +spl_hal_is_bond_netif (struct netif *pnetif) +{ + int i; + struct bond_set *s; + struct netifExt *pnetifExt = NULL; + + pnetifExt = getNetifExt (pnetif->num); + if (NULL == pnetifExt) + return 0; + + for (i = 0; i < bond_ports_array.cnt; i++) + { + s = &bond_ports_array.ports[i]; + if (!strncmp + (pnetifExt->if_name, s->bond_port_name, HAL_MAX_NIC_NAME_LEN)) + { + return 1; + } + } + + return 0; +} |