summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/netif/spl_hal.c
diff options
context:
space:
mode:
Diffstat (limited to 'stacks/lwip_stack/lwip_src/netif/spl_hal.c')
-rw-r--r--stacks/lwip_stack/lwip_src/netif/spl_hal.c1755
1 files changed, 1755 insertions, 0 deletions
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..71d5c06
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/netif/spl_hal.c
@@ -0,0 +1,1755 @@
+/*
+*
+* 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"
+#include "nsfw_shmem_mng.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("HAL", "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_LENTH - 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.lenth = 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("HAL", "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("HAL", "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_LENTH - 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.lenth =
+ 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("HAL", "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.lenth);
+
+ if (EOK != retVal)
+ {
+ INITPOL_LOGERR("HAL", "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.lenth);
+
+ p_stackx_port_zone->stackx_one_port = mz_port_info;
+
+ INITPOL_LOGINF("HAL", "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("HAL", "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_LENTH - 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_LENTH];
+ data_com_msg *rx_msg_array = NULL;
+ retval = spl_snprintf(rx_msg_arr_name, NSFW_MEM_NAME_LENTH, "%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_shmem_mbfalloc(mp);
+
+ 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_shmem_mbffree(mbuf) < 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_LENTH - 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.if_type,
+ sizeof(p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.if_type),
+ network->nic_type_name);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR("strcpy_s failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ NSPOL_LOGINF(SC_DPDK_INFO, "if_type %s",
+ p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.if_type);
+
+ 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;
+ struct hal_netif_hw_feature 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_csum_ip == 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_csum_udp == 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_csum_tcp == 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,
+ p_port_info->linux_ip.if_type, &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("HAL", "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("HAL", "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("HAL", "spl_hal_port_setup", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+
+ return -1;
+ }
+
+ spl_hal_capa_init();
+
+ INITPOL_LOGINF("HAL", "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, (void **) &(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_shmem_mbffree((mbuf_handle) (tx_ptks[i]));
+ }
+ }
+ 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,
+ (void **) 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;
+}