diff options
author | Swarup Nayak <swarupnpvt@gmail.com> | 2018-08-13 19:23:34 +0530 |
---|---|---|
committer | Swarup Nayak <swarupnpvt@gmail.com> | 2018-08-13 19:25:27 +0530 |
commit | 7dc65518819f2b453fd2837e92c115592d8832ec (patch) | |
tree | f9119bb3624ff11af480981c9904b84c172a607c /stacks/lwip_stack | |
parent | bd6e75c243db1b384ba0882ecaf9063ec4cd70bd (diff) |
Feat : LWIP integration part1
Change-Id: Ia26c092d16579c6f845a021ba66bde106363883a
Signed-off-by: Swarup Nayak <swarupnpvt@gmail.com>
Diffstat (limited to 'stacks/lwip_stack')
60 files changed, 14551 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/api/spl_api.c b/stacks/lwip_stack/lwip_src/api/spl_api.c new file mode 100644 index 0000000..5c8af7d --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_api.c @@ -0,0 +1,51 @@ +/* +* +* 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 "nsfw_init.h" +//#include "sockets.h" +//#include <netinet/in.h> + +#include "stackx_spl_share.h" +#include "stackx/spl_api.h" +//#include "stackx/ip.h" +#include "sharedmemory.h" +#include "spl_hal.h" +#include "hal_api.h" +#include "alarm_api.h" +#include "nsfw_mt_config.h" +#include "nsfw_recycle_api.h" +#include "nstack_dmm_adpt.h" + +/* main entry for stackx */ +int +spl_main_init (void *args) +{ + (void) args; + if (init_by_main_thread () < 0) + { + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME ("STACKX_MAIN") +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_ALARM_MODULE) +NSFW_MODULE_DEPENDS (NSTACK_DMM_MODULE) +NSFW_MODULE_INIT (spl_main_init) +/* *INDENT-ON* */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_api_msg.c b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c new file mode 100644 index 0000000..9ba1e92 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c @@ -0,0 +1,3259 @@ +/* +* +* 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 "nsfw_msg.h" +#include "spl_opt.h" +#include "spl_ip_addr.h" +//#include "stackx_socket.h" +#include "cpuid.h" +//#include "sockets.h" +#include <netinet/in.h> +#include <errno.h> + +#include "stackx_prot_com.h" +#include "spl_api.h" +//#include "stackx/ip.h" +#include "sc_dpdk.h" +#include "spl_sbr.h" +//#include "maintain/spl_dfx.h" +#include "stackx_tx_box.h" +#include "spl_instance.h" +#include "spl_sockets.h" + +#include "nstack_dmm_adpt.h" + +#include "tcp.h" +#include "udp.h" +#include "pbuf.h" +#include "tcp_priv.h" +#include "init.h" +#include "timeouts.h" + +#include "stackx_pbuf_comm.h" +#include "spl_netbuf.h" +#include "spl_hal.h" +#include "sys_arch.h" +#include "tcpip.h" +#include "debug.h" +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif + +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ +extern struct tcp_pcb **const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; +extern stackx_instance *p_def_stack_instance; +extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +#define TCP_FN_NULL 0 +#define TCP_FN_DEFAULT 1 +#define TCP_FN_STACKX 2 +#define TCP_FN_MAX 3 + +struct callback_fn tcp_fn[TCP_FN_MAX] = { + {NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {NULL, spl_tcp_recv_null, NULL, NULL, NULL, NULL}, + {spl_sent_tcp, spl_recv_tcp, spl_do_connected, spl_poll_tcp, spl_err_tcp, + NULL, spl_accept_function}, +}; + +// extern int nstack_get_nstack_fd_snapshot_from_proto_fd(int proto_fd); +extern void tcp_drop_conn (spl_netconn_t * conn); +extern void unlink_pcb (struct common_pcb *cpcb); +extern struct queue *get_msgbox (int tos); + +#define SPL_SET_NONBLOCKING_CONNECT(conn, val) \ +do { \ + if (val) \ + { \ + (conn)->flags |= SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ + } \ + else \ + { \ + (conn)->flags &= ~SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ + } \ + } while (0) + +#define SPL_IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +extern int tcpip_thread_control; + +void +spl_event_callback (struct spl_netconn *conn, enum spl_netconn_evt evt, + int postFlag) +{ + NSPOL_LOGDBG (SOCK_INFO, "Get event]conn=%p,evt=%d,postFlag=%d", conn, evt, + postFlag); + /* Get socket */ + if (!conn) + { + NSPOL_LOGDBG (SOCK_INFO, "conn=NULL"); + return; + } + + switch (evt) + { + case SPL_NETCONN_EVT_RCVPLUS: + __sync_fetch_and_add (&conn->rcvevent, 1); + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLIN); + } + break; + case SPL_NETCONN_EVT_RCVMINUS: // This will never be reached + __sync_fetch_and_sub (&conn->rcvevent, 1); + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLIN); + } + break; + case SPL_NETCONN_EVT_SENDPLUS: + conn->sendevent = 1; + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLOUT); + } + break; + case SPL_NETCONN_EVT_SENDMINUS: + conn->sendevent = 0; + + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLOUT); + } + break; + case SPL_NETCONN_EVT_ERROR: + conn->errevent |= EPOLLERR; + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), conn->errevent); + conn->errevent = 0; + } + break; +#if 1 + case SPL_NETCONN_EVT_ACCEPT: + __sync_fetch_and_add (&conn->rcvevent, 1); + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLIN); + } + break; + + case SPL_NETCONN_EVT_HUP: + conn->errevent |= EPOLLHUP; + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), conn->errevent); + conn->errevent = 0; + } + break; + case SPL_NETCONN_EVT_RDHUP: + conn->errevent |= EPOLLRDHUP; + if ((conn->epoll_flag) && (postFlag)) + { + nstack_event_callback (ADDR_SHTOL (conn->epInfo), conn->errevent); + conn->errevent = 0; + } + break; +#endif + + default: + NSTCP_LOGERR ("unknown event]conn=%p,event=%d", conn, evt); + return; + } + return; +} + +u8 +get_shut_op (data_com_msg * m) +{ + if (m && m->param.module_type == MSG_MODULE_SBR + && m->param.major_type == SPL_TCPIP_NEW_MSG_API) + { + if (m->param.minor_type == SPL_API_DO_CLOSE) + return ((msg_close *) (m->buffer))->shut; + + if (m->param.minor_type == SPL_API_DO_DELCON) + return ((msg_delete_netconn *) (m->buffer))->shut; + } + + return SPL_NETCONN_SHUT_RDWR; +} + +/* + Never using head/tail to judge whether need to do enque/deque, just do enque&deque, the return val will tell you ring is full/empty or not + rtp_perf_ring never provid ring_full/ring_empty function; + one more thing the rtp_ring_enque/deque result must be checked. +*/ +err_t +accept_enqueue (spl_netconn_t * conn, void *p) +{ + if (conn == NULL) + { + NSPOL_LOGERR ("accept_enqueue: invalid input]conn=%p", conn); + return ERR_VAL; + } + + NSPOL_LOGDBG (NEW_RING_DEBUG, "accept_enqueue]conn=%p,p=%p", conn, p); + mring_handle ring = conn->recv_ring; + if (NULL == ring) + { + NSPOL_LOGERR ("conn=%p accept new conn=%p enqueue ring addr is null", + conn, p); + return ERR_VAL; + } + + err_t retVal = ERR_MEM; + int enQSucCnt = 0; + int nTryCnt = 0; + do + { + enQSucCnt = nsfw_mem_ring_enqueue (ring, (void *) p); + if (1 == enQSucCnt) + { + retVal = ERR_OK; + break; + } + else if (0 == enQSucCnt) + { + sys_sleep_ns (0, 3000); + nTryCnt++; + } + else + { + retVal = ERR_VAL; + break; + } + } + while (nTryCnt < MAX_TRY_GET_MEMORY_TIMES); + + return retVal; +} + +err_t +accept_dequeue (spl_netconn_t * lconn, void **new_buf, + u32_t timeout /*miliseconds */ ) +{ + struct timespec starttm; + struct timespec endtm; + long timediff; + long timediff_sec; + u32_t timeout_sec = timeout / 1000; + +#define FAST_SLEEP_TIME 10000 +#define SLOW_SLEEP_TIME 500000 +#define FAST_RETRY_COUNT 100 + unsigned int retry_count = 0; + + if (NULL == lconn || NULL == new_buf) + { + NSPOL_LOGERR ("accept_dequeue invalid input]conn=%p,newbuf=%p", lconn, + new_buf); + return ERR_ARG; + } + + if (timeout != 0) + { + /* Handle system time change side-effects */ + if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &starttm))) + { + //NSPOL_LOGERR("Failed to get time]errno=%d", errno); + } + } + + mring_handle ring = lconn->recv_ring; + if (ring == NULL) + { + NSPOL_LOGERR ("Get rtp_perf_ring failed]conn=%p", lconn); + return ERR_ARG; + } + + int nDequeRt; + int retVal; + while (1) + { + if ((lconn->shut_status) && (-1 != (int) timeout)) + { + retVal = ERR_VAL; + break; + } + + nDequeRt = nsfw_mem_ring_dequeue (ring, new_buf); + if (nDequeRt == 1) + { + retVal = ERR_OK; + break; + } + else if (nDequeRt == 0) + { + if ((int) timeout == -1) + { + retVal = ERR_WOULDBLOCK; + break; + } + + if (timeout != 0) + { + /* Handle system time change side-effects */ + if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &endtm))) + { + //NSPOL_LOGERR("Failed to get time, errno = %d", errno); + } + timediff_sec = endtm.tv_sec - starttm.tv_sec; + if (timediff_sec >= timeout_sec) + { + timediff = endtm.tv_nsec > starttm.tv_nsec ? + (timediff_sec * 1000) + (endtm.tv_nsec - + starttm.tv_nsec) / + USEC_TO_SEC : (timediff_sec * 1000) - + ((starttm.tv_nsec - endtm.tv_nsec) / USEC_TO_SEC); + + /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value + will be negetive if still 0.5 ms is not elapsed. this is intended and we should + not typecast to any unsigned type during this below if check */ + if (timediff > (long) timeout) + { + retVal = ERR_TIMEOUT; + break; + } + } + } + + /* reduce CPU usage in blocking mode */ + if (retry_count < FAST_RETRY_COUNT) + { + sys_sleep_ns (0, FAST_SLEEP_TIME); + retry_count++; + } + else + { + sys_sleep_ns (0, SLOW_SLEEP_TIME); + } + + continue; + } + else + { + retVal = ERR_VAL; + break; + } + } + + return retVal; +} + +err_t +sp_enqueue (struct common_pcb * cpcb, void *p) +{ + mring_handle ring = NULL; + spl_netconn_t *conn = NULL; + int enQueRet = 0; + + if (cpcb == NULL || (NULL == (conn = cpcb->conn))) + { + NSTCP_LOGERR ("conn NULL!"); + return ERR_VAL; + } + + NSPOL_LOGDBG (NEW_RING_DEBUG, "]conn=%p,buf=%p", cpcb->conn, p); + ring = conn->recv_ring; + if (NULL == ring) + { + NSPOL_LOGERR ("Get rtp_perf_ring failed]conn=%p.", conn); + return ERR_CLSD; + } + + /* clear LOOP_SEND_FLAG to indicate that this pbuf has been given to upper layer */ + struct spl_pbuf *tmpbuf = p; + while (tmpbuf) + { + tmpbuf->res_chk.u8Reserve &= ~LOOP_SEND_FLAG; + tmpbuf = tmpbuf->next; + } + + enQueRet = nsfw_mem_ring_enqueue (ring, p); + if (1 != enQueRet) + { + NS_LOG_CTRL (LOG_CTRL_RECV_QUEUE_FULL, LOGTCP, "NSTCP", NSLOG_WAR, + "ringvbox_enqueue buf is full]conn=%p.", conn); + + return ERR_MEM; + } + + return ERR_OK; +} + +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ + +static void +spl_recv_udp (void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t * ipaddr, u16_t port) +{ + struct spl_netbuf *buf; + spl_netconn_t *conn = (spl_netconn_t *) arg; + struct spl_pbuf *spb = NULL; //?? + + if (NULL == pcb) + { + NSPOL_LOGERR ("recv_udp must have a pcb argument"); + pbuf_free (p); + return; + } + + if (NULL == arg) + { + NSPOL_LOGERR ("recv_udp must have an argument"); + pbuf_free (p); + return; + } + /* //@TODO: malloc and Copy splbuf */ + struct common_pcb *cpcb = (struct common_pcb *) (conn->comm_pcb_data); + + buf = (struct spl_netbuf *) ((char *) p + sizeof (struct spl_pbuf)); + buf->p = spb; + spl_ip_addr_set (&buf->addr, ipaddr); + buf->port = port; + + err_t ret = sp_enqueue (cpcb, (void *) p); + if (ret != ERR_OK) + { + NSPOL_LOGDBG (UDP_DEBUG, "mbox post failed"); + spl_netbuf_delete (buf); + return; + } + else + { + /* Register event with callback */ + NSPOL_LOGDBG (UDP_DEBUG | LWIP_DBG_TRACE, + "recv a udp packet: and api_event"); + SPL_API_EVENT (cpcb->conn, SPL_NETCONN_EVT_RCVPLUS, 1); + } +} + +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ + +err_t +spl_recv_tcp (void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct spl_pbuf *spl_pb = NULL; + u32_t len; + + if (NULL == pcb) + { + NSTCP_LOGERR ("recv_tcp must have a pcb argument"); + pbuf_free (p); + return ERR_ARG; + } + + if (NULL == arg) + { + NSTCP_LOGERR ("must have an argument]pcb=%p", pcb); + pbuf_free (p); + return ERR_ARG; + } + + spl_netconn_t *conn = (spl_netconn_t *) arg; + + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + /* don't overwrite fatal errors! */ + (void) err; + if (p == NULL) + { + return ERR_OK; + } + + len = p->tot_len; + + u16_t proc_id = spl_get_lcore_id (); + + spl_pb = spl_pbuf_alloc_hugepage (SPL_PBUF_TRANSPORT, + p->tot_len + + g_offSetArry[SPL_PBUF_TRANSPORT], + SPL_PBUF_HUGE, proc_id, conn); + + if (!spl_pb) + { + NSPOL_LOGINF (TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return ERR_MEM; + } + + pbuf_to_splpbuf_copy (spl_pb, p); + pbuf_free (p); + + if (sp_enqueue ((struct common_pcb *) conn->comm_pcb_data, (void *) spl_pb) + != ERR_OK) + { + NSPOL_LOGDBG (TCP_DEBUG, "sp_enqueue!=ERR_OK]conn=%p", conn); + spl_pbuf_free (spl_pb); + return ERR_MEM; + } + + SPL_API_EVENT (conn, SPL_NETCONN_EVT_RCVPLUS, 1); + conn->recv_avail_prod += len; + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +err_t +spl_poll_tcp (void *arg, struct tcp_pcb * pcb) +{ + spl_netconn_t *conn = (spl_netconn_t *) arg; + struct tcp_pcb *tpcb = NULL; + + if (NULL == conn) + { + NSPOL_LOGERR ("conn==NULL"); + return ERR_VAL; + } + + if (conn->state == SPL_NETCONN_WRITE) + { + (void) do_writemore (conn); + + /* do_close_internal, can release th PCB + and connection CB. so checking NETCONN_FLAG_CHECK_WRITESPACE should not be + done after do_close_internal. anyway this flag is used with data send.(do_writemore) */ + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & SPL_NETCONN_FLAG_CHECK_WRITESPACE) + { + tpcb = (struct tcp_pcb *) conn->private_data; + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((tpcb != NULL) && (tcp_sndbuf (tpcb) > TCP_SNDLOWAT) && + (tcp_sndqueuelen (tpcb) < TCP_SNDQUEUELOWAT)) + { + conn->flags &= ~SPL_NETCONN_FLAG_CHECK_WRITESPACE; + SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1); + } + } + } + else if (conn->state == SPL_NETCONN_CLOSE) + { + (void) do_close_internal ((struct common_pcb *) conn->comm_pcb_data, 0); + } + + /* @todo: implement connect timeout here? */ + return ERR_OK; +} + +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +spl_tcp_recv_null (void *arg, struct tcp_pcb * pcb, struct pbuf * p, + err_t err) +{ + LWIP_UNUSED_ARG (arg); + + if (p != NULL) + { + tcp_recved (pcb, p->tot_len); + pbuf_free (p); + } + else if (err == ERR_OK) + { + return tcp_close (pcb); + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +err_t +spl_sent_tcp (void *arg, struct tcp_pcb * pcb, u16_t len) +{ + spl_netconn_t *conn = (spl_netconn_t *) arg; + + if (NULL == conn) + { + NSPOL_LOGERR ("conn==NULL"); + return ERR_VAL; + } + + if (conn->state == SPL_NETCONN_WRITE) + { + (void) do_writemore (conn); + } + else if (conn->state == SPL_NETCONN_CLOSE) + { + (void) do_close_internal ((struct common_pcb *) conn->comm_pcb_data, 0); + } + + /* conn is already checked for NULL above with ASSERT */ + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if (conn->snd_buf > TCP_SNDLOWAT) + { + conn->flags &= ~SPL_NETCONN_FLAG_CHECK_WRITESPACE; + if (((struct common_pcb *) conn->comm_pcb_data)->model == SOCKET_STACKX) + SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1); + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +void +spl_err_tcp (void *arg, err_t err) +{ + spl_netconn_t *conn; + enum spl_netconn_state old_state; + data_com_msg *forFree = NULL; + + struct common_pcb *cpcb; + + NSTCP_LOGINF ("Enter err_tcp."); + + conn = (spl_netconn_t *) arg; + cpcb = (struct common_pcb *) (conn->comm_pcb_data); + + old_state = conn->state; + conn->state = SPL_NETCONN_NONE; + + /* Call unlink pcb no matter what */ + unlink_pcb (cpcb); + if (old_state == SPL_NETCONN_CLOSE) + { + /* RST during close: let close return success & dealloc the netconn */ + err = ERR_OK; + SPL_NETCONN_SET_SAFE_ERR (conn, ERR_OK); + } + else + { + SPL_NETCONN_SET_SAFE_ERR (conn, err); + } + + NSTCP_LOGWAR ("inform HUP and ERROR event."); + SPL_API_EVENT (conn, SPL_NETCONN_EVT_RCVPLUS, 0); + SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 0); + SPL_API_EVENT (conn, SPL_NETCONN_EVT_ERROR, 0); + SPL_API_EVENT (conn, SPL_NETCONN_EVT_HUP, 1); + + if ((old_state == SPL_NETCONN_WRITE) || (old_state == SPL_NETCONN_CLOSE) + || (old_state == SPL_NETCONN_CONNECT)) + { + int was_nonblocking_connect = spl_netconn_is_nonblocking (conn); + SPL_SET_NONBLOCKING_CONNECT (conn, 0); + + if (!was_nonblocking_connect) + { + /* set error return code */ + if (NULL == cpcb->current_msg) + { + NSPOL_LOGERR ("conn->current_msg==NULL"); + return; + } + + /* current msg could be connect msg or write_buf_msg */ + SET_MSG_ERR (cpcb->current_msg, err); + /* signal app to exit */ + if (old_state == SPL_NETCONN_CONNECT + && !spl_netconn_is_nonblocking (conn)) + { + SYNC_MSG_ACK (cpcb->current_msg); + } + + /* no matter it's connect msg or write msg, we will no process it any more */ + cpcb->current_msg = NULL; + + /* but, if msg is write_buf_msg, then we should release the pbuf in msg */ + if (cpcb->msg_head != NULL) + { + /* current_msg should be write_buf_msg */ + msg_write_buf *tmp_msg = cpcb->msg_head; + while (tmp_msg != NULL) + { + + forFree = MSG_ENTRY (tmp_msg, data_com_msg, buffer); + spl_pbuf_free (tmp_msg->p); + tmp_msg = tmp_msg->next; + + // free msg + ASYNC_MSG_FREE (forFree); + } + cpcb->current_msg = NULL; + cpcb->msg_head = cpcb->msg_tail = NULL; + } + } + } + else + { + + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +NSTACK_STATIC void +setup_tcp (struct tcp_pcb *pcb, spl_netconn_t * conn) +{ + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + + /* callback have the same value as cpcb->conn */ + cpcb->conn = conn; + tcp_arg (pcb, (void *) conn); + tcp_recv (pcb, tcp_fn[TCP_FN_STACKX].recv_fn); + tcp_sent (pcb, tcp_fn[TCP_FN_STACKX].sent_fn); + tcp_poll (pcb, tcp_fn[TCP_FN_STACKX].poll_fn, 4); + tcp_err (pcb, tcp_fn[TCP_FN_STACKX].err_fn); + +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +err_t +spl_accept_function (void *arg, struct tcp_pcb *newpcb, err_t err) +{ + spl_netconn_t *newconn; + spl_netconn_t *lconn = (spl_netconn_t *) arg; /* listen conneciton */ + struct common_pcb *cpcb = NULL; + + NSPOL_LOGDBG (API_MSG_DEBUG, "]state=%s", + tcp_debug_state_str (newpcb->state)); + + if (lconn == NULL) + { + NSPOL_LOGERR ("accept_function: conn is NULL"); + return ERR_VAL; + } + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = ss_malloc_conn (lconn->conn_pool, SPL_NETCONN_TCP); + if (newconn == NULL) + { + NSPOL_LOGERR ("conn alloc failed"); + return ERR_MEM; + } + + cpcb = alloc_common_pcb (SPL_NETCONN_TCP); + if (cpcb == NULL) + { + return ERR_MEM; + } + + /* used by application to recycle conn */ + newconn->recycle.accept_from = lconn; + newconn->conn_pool = lconn->conn_pool; + + newconn->recv_obj = (i64) & newconn->private_data; + newconn->private_data = (i64) newpcb; + newconn->comm_pcb_data = (i64) cpcb; + + NSFW_LOGINF ("alloc accept conn]conn=%p,pcb=%p,lconn=%p", newconn, newpcb, + lconn); + newconn->shut_status = 0xFFFF; + newconn->last_err = ERR_OK; + newconn->CanNotReceive = 0; + newconn->flags = 0; + + newconn->state = SPL_NETCONN_NONE; + newconn->mss = newpcb->mss; + newconn->remote_ip.addr = newpcb->remote_ip.addr; + newconn->remote_port = newpcb->remote_port; + ss_set_local_ip (newconn, newpcb->local_ip.addr); + ss_set_local_port (newconn, newpcb->local_port); + + setup_tcp (newpcb, newconn); + newpcb->state = ESTABLISHED; + update_tcp_state (newconn, ESTABLISHED); + + /*Initialize flow control variables */ + newconn->tcp_sndbuf = CONN_TCP_MEM_DEF_LINE; + newconn->tcp_wmem_alloc_cnt = 0; + newconn->tcp_wmem_sbr_free_cnt = 0; + newconn->tcp_wmem_spl_free_cnt = 0; + newconn->snd_buf = 0; + + newconn->bind_thread_index = lconn->bind_thread_index; + ss_set_msg_box (newconn, + ss_get_instance_msg_box (newconn->bind_thread_index, 0)); + + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + NSPOL_LOGDBG (TCP_DEBUG, + "trypost]newconn=%p, tcp=%p state=%d conn state=%d ", newconn, + newpcb, newpcb->state, newconn->state); + if (accept_enqueue (lconn, (void *) newconn) != ERR_OK) + { + /* remove all references to this netconn from the pcb */ + NSPOL_LOGERR ("sp_enqueue!=ERR_OK]ring = %p", newconn->recv_ring); + + tcp_arg (newpcb, NULL); + tcp_recv (newpcb, tcp_fn[TCP_FN_NULL].recv_fn); + tcp_sent (newpcb, tcp_fn[TCP_FN_NULL].sent_fn); + tcp_poll (newpcb, tcp_fn[TCP_FN_NULL].poll_fn, 0); + tcp_err (newpcb, tcp_fn[TCP_FN_NULL].err_fn); + /* drop conn */ + tcp_drop_conn (newconn); + return ERR_MEM; + } + + SPL_API_EVENT (lconn, SPL_NETCONN_EVT_ACCEPT, 1); + /* tcp_accepted_with_return_value(newpcb); */ + + return ERR_OK; +} + +int +common_pcb_init (struct common_pcb *cpcb) +{ + // u32 threadnum = p_lwip_instance->rss_queue_id + 1;//0 for app + + cpcb->hostpid = get_sys_pid (); + + cpcb->socket = 0; + /* run and close repeatly nstackmain coredum */ + cpcb->close_progress = 0; + cpcb->model = SOCKET_STACKX; + cpcb->current_msg = NULL; + cpcb->msg_head = cpcb->msg_tail = NULL; + cpcb->write_offset = 0; + + cpcb->recv_timeout = cpcb->send_timeout = 0; + + cpcb->sk_rcvlowat = 1; + + cpcb->l4_tick = 0; + cpcb->dataSentFlag = 0; + cpcb->recv_ring_not_empty = 0; + + return 0; +} + +int +common_pcb_reset (struct common_pcb *cpcb) +{ + cpcb->conn = NULL; + cpcb->hostpid = 0; + + cpcb->socket = 0; + /* run and close repeatly nstackmain coredum */ + cpcb->close_progress = 0; + cpcb->model = 0; + cpcb->current_msg = NULL; + cpcb->msg_head = cpcb->msg_tail = NULL; + cpcb->write_offset = 0; + + cpcb->recv_timeout = cpcb->send_timeout = 0; + + cpcb->sk_rcvlowat = 0; + + cpcb->l4_tick = 0; + cpcb->dataSentFlag = 0; + cpcb->recv_ring_not_empty = 0; + + return 0; +} + +void +unlink_pcb (struct common_pcb *cpcb) +{ + if (cpcb && cpcb->conn) + { + /* whatever the private data will be reset */ + cpcb->conn->private_data = 0; + update_tcp_state (cpcb->conn, CLOSED); + } + else + { + NSPOL_LOGINF (API_MSG_DEBUG, "conn is detached already!"); + } +} + +void +unlink_recv_ring (spl_netconn_t * conn) +{ + if (conn) + conn->recv_ring_valid = 0; +} + +void +recycle_tmr (void *arg) +{ + if (arg == NULL) + { + NSPOL_LOGERR ("recycle_message is NULL!"); + } + else + { + (void) ss_recycle_conn (arg, do_try_delconn); + } +} + +/** + * Create a new pcb of a specific type. + * Called from do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +int +spl_pcb_new (msg_new_netconn * pmsg) +{ + u16_t thread_index = spl_get_lcore_id (); + struct common_pcb *cpcb = NULL; + enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4; + + /* Allocate a PCB for this connection */ + switch (SPL_NETCONNTYPE_GROUP (pmsg->type)) + { + case SPL_NETCONN_UDP: + { + struct udp_pcb *u = udp_new_ip_type (iptype); + if (u == NULL) + { + return ERR_MEM; + } + + if (pmsg->type == SPL_NETCONN_UDPNOCHKSUM) + { + udp_setflags (u, UDP_FLAGS_NOCHKSUM); + } + + cpcb = (struct common_pcb *) alloc_common_pcb (SPL_NETCONN_UDP); + if (cpcb == NULL) + { + return ERR_MEM; + } + + pmsg->conn->comm_pcb_data = (i64) cpcb; + pmsg->conn->private_data = (i64) u; + udp_recv (u, spl_recv_udp, (void *) pmsg->conn); + break; + } + + case SPL_NETCONN_TCP: + { + struct tcp_pcb *t = tcp_new_ip_type (iptype); + if (t == NULL) + { + return ERR_MEM; + } + + cpcb = alloc_common_pcb (SPL_NETCONN_TCP); + if (cpcb == NULL) + { + return ERR_MEM; + } + + pmsg->conn->comm_pcb_data = (i64) cpcb; + pmsg->conn->private_data = (i64) t; + setup_tcp (t, pmsg->conn); + break; + } + + default: + /* Unsupported netconn type, e.g. protocol disabled */ + NSPOL_LOGERR ("Unsupported netconn type!"); + return ERR_VAL; + } + + /* type and socket value for all type */ + cpcb->socket = pmsg->socket; + cpcb->conn = pmsg->conn; + cpcb->bind_thread_index = thread_index; + + /* used to find pcb when a msg is received */ + return ERR_OK; +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +int +netconn_drain (enum spl_netconn_type type, spl_netconn_t * conn) +{ + int i, n; + mring_handle ring = NULL; + void *addr[32] = { 0 }; + int not_empty = 0; + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + ring = conn->recv_ring; + do + { + /*every times get atmost 32 to release */ + n = nsfw_mem_ring_dequeuev (ring, addr, 32); + for (i = 0; i < n; i++) + { + /* if the con is UDP, buffer type also is struct spl_netbuf,it is same as RAW */ + if ((type == SPL_NETCONN_RAW) || (type == SPL_NETCONN_UDP)) + { + spl_pbuf_free ((struct spl_pbuf *) addr[i]); + if (type == SPL_NETCONN_UDP) + { + UDP_STATS_INC (udp.drop); + } + } + else + { + spl_pbuf_free ((struct spl_pbuf *) addr[i]); + } + + if (not_empty == 0) + not_empty = 1; + } + } + while (0 != n); + return not_empty; +} + +/* need free mbuf inside recv ring before free conn */ +void +free_conn_by_spl (spl_netconn_t * conn) +{ + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + + free_common_pcb (cpcb); + + (void) netconn_drain (conn->type, conn); + ss_free_conn (conn); +} + +int +do_close_finished (struct common_pcb *cpcb, u8_t close_finished, u8_t shut, + err_t err, int OpShutDown) +{ + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + spl_netconn_t *conn = cpcb->conn; + + if (!close_finished) + { + /* Closing succeeded */ + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + if (LISTEN == tpcb->state) + { + NSPOL_LOGERR ("Closing a listen pcb may not fail!"); + return ERR_VAL; + } + + tcp_sent (tpcb, tcp_fn[TCP_FN_STACKX].sent_fn); + tcp_poll (tpcb, tcp_fn[TCP_FN_STACKX].poll_fn, 1); + tcp_err (tpcb, tcp_fn[TCP_FN_STACKX].err_fn); + tcp_arg (tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + else + { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + if (cpcb->current_msg) + { + SET_MSG_ERR (cpcb->current_msg, err); + cpcb->current_msg = NULL; + } + + conn->state = SPL_NETCONN_NONE; + NSTCP_LOGINF ("release pcb]conn=%p,pcb=%p", conn, tpcb); + unlink_pcb (cpcb); + } + + return ERR_OK; +} + +NSTACK_STATIC void +reset_tcp_callback (struct tcp_pcb *tpcb, struct common_pcb *cpcb, u8 shut) +{ + spl_netconn_t *conn = cpcb->conn; + + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut & SPL_NETCONN_SHUT_RD) + { + conn->CanNotReceive = 1; + tcp_recv (tpcb, tcp_fn[TCP_FN_NULL].recv_fn); + tcp_accept (tpcb, tcp_fn[TCP_FN_NULL].accept_fn); + } + + if (shut & SPL_NETCONN_SHUT_WR) + { + tcp_sent (tpcb, tcp_fn[TCP_FN_NULL].sent_fn); + } + + if (shut == SPL_NETCONN_SHUT_RDWR) + { + tcp_poll (tpcb, tcp_fn[TCP_FN_NULL].poll_fn, 0); + tcp_err (tpcb, tcp_fn[TCP_FN_NULL].err_fn); + } +} + +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +err_t +do_close_internal (struct common_pcb *cpcb, int OpShutDown) +{ + err_t err; + u8_t shut, ucclose; + u8_t close_finished = 0; + + if (NULL == cpcb) + { + NSTCP_LOGERR ("invalid conn"); + return ERR_ARG; + } + + spl_netconn_t *conn = cpcb->conn; + if (SPL_NETCONN_TCP != cpcb->type || SPL_NETCONN_CLOSE != conn->state) + { + NSTCP_LOGERR ("conn=%p, err_type=%d, error_state=%d", + conn, cpcb->type, conn->state); + return ERR_VAL; + } + + struct tcp_pcb *tpcb = (struct tcp_pcb *) (conn->private_data); + + if (cpcb->current_msg != NULL) + shut = get_shut_op (cpcb->current_msg); + else + shut = SPL_NETCONN_SHUT_RDWR; + + /* shutting down both ends is the same as closing */ + ucclose = (shut == SPL_NETCONN_SHUT_RDWR); + + /* Set back some callback pointers */ + if (ucclose) + { + conn->CanNotReceive = 1; + tcp_arg (tpcb, conn); + } + + if (tpcb->state == LISTEN) + { + tcp_accept (tpcb, tcp_fn[TCP_FN_NULL].accept_fn); + } + else + { + reset_tcp_callback (tpcb, cpcb, shut); + } + + /* Try to close the connection */ + if (shut == SPL_NETCONN_SHUT_RDWR && !OpShutDown) + { + err = tcp_close (tpcb); + } + else + { + err = + tcp_shutdown (tpcb, shut & SPL_NETCONN_SHUT_RD, + shut & SPL_NETCONN_SHUT_WR); + } + + if (err == ERR_OK) + { + close_finished = 1; + } + else + { + if (err == ERR_MEM) + { + /* Blocking close, check the timeout */ + close_finished = 1; + if (ucclose) + { + /* in this case, we want to RST the connection */ + tcp_abort (tpcb); + err = ERR_OK; + } + } + else + { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + + err_t err1 = do_close_finished (cpcb, close_finished, + shut, err, OpShutDown); + if (err1 != ERR_OK) + { + NSTCP_LOGERR ("return err1]pcb=%p,err1=%d", tpcb, err1); + return err1; + } + return err; + + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ +} + +void +do_try_delconn (void *close_data, u32 delay_sec) +{ + msg_delete_netconn *dmsg = (msg_delete_netconn *) close_data; + data_com_msg *m = MSG_ENTRY (dmsg, data_com_msg, buffer); + struct common_pcb *cpcb = NULL; + + spl_netconn_t *conn = dmsg->conn; + + /* no receiver in some recycle cases */ + if (0 == m->param.comm_receiver) + { + if (NULL == conn) + { + NSFW_LOGERR ("release err conn!]pid=%d", dmsg->pid); + /* need to free pbufs which are attached to msg */ + do_pbuf_free (dmsg->buf); + return; + } + + cpcb = (struct common_pcb *) conn->comm_pcb_data; + } + else + { + cpcb = COMM_PRIVATE_PTR (m); + } + + /* no pcb in some recycle cases */ + if (conn->private_data == 0) + { + /* though pcb is gone, still need to clean the mbox */ + if (conn != NULL) + (void) netconn_drain (conn->type, conn); + + NSFW_LOGWAR ("release conn pcb null]pcb=%p", m->param.receiver); + /* need to free pbufs which are attached to msg */ + do_pbuf_free (dmsg->buf); + return; + } + + if (delay_sec) + { + NSFW_LOGWAR ("delay to recycle!]pcb=%p, msg=%d", cpcb, dmsg); + sys_timeout (delay_sec * 1000, recycle_tmr, dmsg); + return; + } + + do_delconn (cpcb, dmsg); + + /* after the do_delconn, the PCB maybe released, but the conn is ok */ + sys_sem_s_signal (&dmsg->conn->close_completed); + + return; +} + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_delconn (struct common_pcb *cpcb, msg_delete_netconn * dmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY (dmsg, data_com_msg, buffer); + + /*if already close, just return */ + /* run and close repeatly nstackmain coredum */ + if (1 == cpcb->close_progress) + { + SET_MSG_ERR (pmsg, ERR_OK); + return; + } + cpcb->close_progress = 1; + + /* Pbuf free should be done in network stack */ + do_pbuf_free (dmsg->buf); + + /* @todo TCP: abort running write/connect? */ + if ((conn->state != SPL_NETCONN_NONE) + && (conn->state != SPL_NETCONN_LISTEN) + && (conn->state != SPL_NETCONN_CONNECT)) + { + /* this only happens for TCP netconns */ + if (SPL_NETCONN_TCP != cpcb->type) + { + NSTCP_LOGERR ("msg->conn->type error!]conn=%p,msg->conn->type=%d", + conn, cpcb->type); + SET_MSG_ERR (pmsg, ERR_VAL); + return; + } + NSPOL_LOGINF (SOCK_INFO, "conn is not for free state]conn=%p,state=%d", + conn, conn->state); + + //need to release pcb + if (cpcb->current_msg != NULL && cpcb->msg_tail != NULL) + { + NSPOL_LOGINF (SOCK_INFO, + "conn there is data in conn->current_msg when close the conn]conn=%p,state=%d", + conn, conn->state); + (void) do_writemore (cpcb->conn); + } + } + + /* + the accpet connections waiting in listen queue will be clear in + netconn_drain. + */ + if (conn->state == SPL_NETCONN_LISTEN) + { + /* This function does nothing in original code. */ + } + else + { + /* Drain pbuf from non-listen mboxes */ + if (netconn_drain (cpcb->type, conn)) + { + cpcb->recv_ring_not_empty = 1; + + NSPOL_LOGWAR (SOCK_INFO, + "still some data leave in recv ring when close"); + } + } + + /* conn will be released outside */ + + switch (SPL_NETCONNTYPE_GROUP (cpcb->type)) + { + + case SPL_NETCONN_UDP: + { + struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data; + upcb->recv_arg = NULL; + udp_remove (upcb); + break; + } + + case SPL_NETCONN_TCP: + { + conn->state = SPL_NETCONN_CLOSE; + dmsg->shut = SPL_NETCONN_SHUT_RDWR; + cpcb->current_msg = pmsg; + + if (ERR_INPROGRESS == do_close_internal (cpcb, 0)) + { + return; + } + } + default: + break; + } + + /* tcp netconns don't come here! */ + +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IPaddress and port to bind to + */ +void +do_bind (struct common_pcb *cpcb, msg_bind * bmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY (bmsg, data_com_msg, buffer); + ip_addr_t stIpaddr; + + stIpaddr.addr = bmsg->ipaddr.addr; + + if (SPL_ERR_IS_FATAL (conn->last_err) + && ERR_CANTASSIGNADDR != conn->last_err) + { + NSTCP_LOGERR ("bind but conn has err]pcb=%p,conn=%p,err=%d", cpcb, conn, + conn->last_err); + SET_MSG_ERR (pmsg, conn->last_err); + } + else + { + if (!ip_addr_isany (&bmsg->ipaddr) + && !ip_addr_ismulticast (&bmsg->ipaddr)) + { + if (!get_netif_by_ip (bmsg->ipaddr.addr) + && !netif_check_broadcast_addr (&bmsg->ipaddr)) + { + NSPOL_LOGERR ("ip is not exist]pcb=%p,ip=%u", cpcb, + bmsg->ipaddr.addr); + SET_MSG_ERR (pmsg, ERR_CANTASSIGNADDR); + return; + } + } + + SET_MSG_ERR (pmsg, ERR_VAL); + switch (SPL_NETCONNTYPE_GROUP (cpcb->type)) + { + case SPL_NETCONN_UDP: + SET_MSG_ERR (pmsg, + udp_bind ((struct udp_pcb *) (cpcb-> + conn->private_data), + &stIpaddr, bmsg->port)); + + /* Set local Ip, willbe used during connect */ + struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data; + ss_set_local_ip (cpcb->conn, upcb->local_ip.addr); + ss_set_local_port (cpcb->conn, upcb->local_port); + NSTCP_LOGINF ("updated Ip to spl_netconn_t] %x", + upcb->local_ip.addr); + + NSUDP_LOGINF + ("udp_bind return]pcb=%p,IP=%u.%u.%u.%u,port=%u,err=%d", + (struct udp_pcb *) cpcb->conn->private_data, + &bmsg->ipaddr == NULL ? 0 : ip4_addr1_16 (&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr2_16 (&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr3_16 (&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr4_16 (&stIpaddr), bmsg->port, + GET_MSG_ERR (pmsg)); + break; + + case SPL_NETCONN_TCP: + SET_MSG_ERR (pmsg, + tcp_bind ((struct tcp_pcb *) cpcb->conn->private_data, + &stIpaddr, bmsg->port)); + + /* Set local Ip, willbe used during connect */ + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + NSTCP_LOGINF ("updated Ip to spl_netconn_t] %x", + tpcb->local_ip.addr); + ss_set_local_ip (cpcb->conn, tpcb->local_ip.addr); + ss_set_local_port (cpcb->conn, tpcb->local_port); + + NSTCP_LOGINF + ("tcp_bind return]pcb=%p,IP=%u.%u.%u.%u,port=%u,err=%d", + (struct tcp_pcb *) cpcb->conn->private_data, + &bmsg->ipaddr == NULL ? 0 : ip4_addr1_16 (&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr2_16 (&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr3_16 (&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr4_16 (&stIpaddr), bmsg->port, + GET_MSG_ERR (pmsg)); + break; + default: + break; + } + } + + conn->last_err = GET_MSG_ERR (pmsg); + NSPOL_LOGDBG (TESTSOCKET_DEBUG | LWIP_DBG_TRACE, "the msg is doing bind"); + NSTCP_LOGINF ("the msg is doing bind"); +} + +/** + * TCP callback function if a connection (opened by tcp_connect/do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +err_t +spl_do_connected (void *arg, struct tcp_pcb *pcb, err_t err) +{ + spl_netconn_t *conn = (spl_netconn_t *) arg; + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + data_com_msg *m = cpcb->current_msg; + int was_blocking; + + if (conn == NULL) + { + NSTCP_LOGERR ("conn is NULL!]arg=%p", arg); + return ERR_ARG; + } + + if (SPL_NETCONN_CONNECT != conn->state) + { + NSTCP_LOGERR ("conn->state error!]conn=%p,state=%d", conn, conn->state); + return ERR_VAL; + } + + if ((NULL == m) && (0 == spl_netconn_is_nonblocking (conn))) + { + NSTCP_LOGERR ("conn->current_msg!]conn=%p,current_msg=%p", conn, m); + return ERR_VAL; + } + + if (m != NULL) + { + SET_MSG_ERR (m, err); + } + + if ((cpcb->type == SPL_NETCONN_TCP) && (err == ERR_OK)) + { + setup_tcp (pcb, conn); + } + + ss_set_local_ip (conn, pcb->local_ip.addr); + ss_set_local_port (conn, pcb->local_port); + conn->remote_ip.addr = pcb->remote_ip.addr; + conn->remote_port = pcb->remote_port; + + conn->mss = pcb->mss; + cpcb->current_msg = NULL; + + was_blocking = !SPL_IN_NONBLOCKING_CONNECT (conn); + SPL_SET_NONBLOCKING_CONNECT (conn, 0); + conn->state = SPL_NETCONN_NONE; + SPL_NETCONN_SET_SAFE_ERR (conn, ERR_OK); + + SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1); + + if (was_blocking && m != NULL) + { + SYNC_MSG_ACK (m); + } + + return ERR_OK; +} + +int +do_internal_tcp_connect (struct common_pcb *cpcb, struct tcp_pcb *tpcb, + msg_connect * cmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY (cmsg, data_com_msg, buffer); + ip_addr_t ip_addr; + + ip_addr.addr = cmsg->ipaddr.addr; + + /* Prevent connect while doing any other action. */ + if (conn->state != SPL_NETCONN_NONE) + { + if (conn->state == SPL_NETCONN_CONNECT + || conn->state == SPL_NETCONN_WRITE) + { + if (tpcb->state != ESTABLISHED) + { + SET_MSG_ERR (pmsg, ERR_ALREADY); + } + else + { + SET_MSG_ERR (pmsg, ERR_ISCONN); + } + } + else + { + SET_MSG_ERR (pmsg, ERR_ISCONN); + } + + NSTCP_LOGINF + ("tcp_connect]pcb=%p,state=%d,remote_ip=%u.%u.%u.%u,remote_port=%u,local_ip=%u.%u.%u.%u,local_port=%u,err=%d", + tpcb, conn->state, ip4_addr1_16 (&ip_addr), ip4_addr2_16 (&ip_addr), + ip4_addr3_16 (&ip_addr), ip4_addr4_16 (&ip_addr), cmsg->port, + ip4_addr1_16 (&tpcb->local_ip), ip4_addr2_16 (&tpcb->local_ip), + ip4_addr3_16 (&tpcb->local_ip), ip4_addr4_16 (&tpcb->local_ip), + tpcb->local_port, GET_MSG_ERR (pmsg)); + } + else + { + setup_tcp (tpcb, conn); + SET_MSG_ERR (pmsg, + tcp_connect (tpcb, &ip_addr, cmsg->port, + tcp_fn[TCP_FN_STACKX].connected_fn)); + conn->mss = tpcb->mss; + SPL_API_EVENT (conn, NETCONN_EVT_SENDMINUS, 1); + SPL_API_EVENT (conn, NETCONN_EVT_RCVMINUS, 1); + + NSTCP_LOGINF + ("tcp_connect]pcb=%p,state=%d,remote_ip=%u.%u.%u.%u,remote_port=%u,local_ip=%u.%u.%u.%u,local_port=%u,err=%d", + tpcb, conn->state, ip4_addr1_16 (&ip_addr), ip4_addr2_16 (&ip_addr), + ip4_addr3_16 (&ip_addr), ip4_addr4_16 (&ip_addr), cmsg->port, + ip4_addr1_16 (&tpcb->local_ip), ip4_addr2_16 (&tpcb->local_ip), + ip4_addr3_16 (&tpcb->local_ip), ip4_addr4_16 (&tpcb->local_ip), + tpcb->local_port, GET_MSG_ERR (pmsg)); + if (GET_MSG_ERR (pmsg) == ERR_OK) + { + int nonblock = spl_netconn_is_nonblocking (conn); + SPL_SET_NONBLOCKING_CONNECT (conn, nonblock); + conn->state = SPL_NETCONN_CONNECT; + if (nonblock) + { + SET_MSG_ERR (pmsg, ERR_INPROGRESS); + } + else + { + cpcb->current_msg = pmsg; + /* sys_sem_signal() is called from do_connected (or err_tcp()), + * when the connection is established! */ + return -1; + } + } + } + + return 0; +} + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IPaddress and port to connect to + */ +void +do_connect (struct common_pcb *cpcb, msg_connect * cmsg) +{ + data_com_msg *pmsg = MSG_ENTRY (cmsg, data_com_msg, buffer); + ip_addr_t ipaddr; + + SET_MSG_ERR (pmsg, ERR_OK); + + if (cpcb == NULL) + { + /* This may happen when calling netconn_connect() a second time */ + NSTCP_LOGERR ("conn connect but conn has err]msg=%p", pmsg); + SET_MSG_ERR (pmsg, ERR_CLSD); + return; + } + + ipaddr.addr = cmsg->ipaddr.addr; + switch (SPL_NETCONNTYPE_GROUP (cpcb->type)) + { + case SPL_NETCONN_UDP: + { + struct udp_pcb *upcb = (struct udp_pcb *) (cpcb->conn->private_data); + if (ip_addr_isany (&upcb->local_ip)) + { + upcb->local_ip.addr = cmsg->local_ip.addr; + ss_set_local_ip (cpcb->conn, upcb->local_ip.addr); + } + + SET_MSG_ERR (pmsg, udp_connect (upcb, &ipaddr, cmsg->port)); + if (ERR_OK == pmsg->param.err) + { + cpcb->conn->remote_ip.addr = cmsg->ipaddr.addr; + cpcb->conn->remote_port = cmsg->port; + } + break; + } + case SPL_NETCONN_TCP: + { + struct tcp_pcb *tpcb = (struct tcp_pcb *) (cpcb->conn->private_data); + if (ip_addr_isany (&tpcb->local_ip)) + { + tpcb->local_ip.addr = cmsg->local_ip.addr; + ss_set_local_ip (cpcb->conn, tpcb->local_ip.addr); + } + + if (0 != do_internal_tcp_connect (cpcb, tpcb, cmsg)) + { + return; + } + + } + break; + default: + NSPOL_LOGERR ("Invalid netconn type]type=%d", cpcb->type); + SET_MSG_ERR (pmsg, ERR_VAL); + break; + } + + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. + Do as lwip-2.0.0. set conn->last_error here. */ + SPL_NETCONN_SET_SAFE_ERR (cpcb->conn, GET_MSG_ERR (pmsg)); +} + +/* Pbuf free should be done in network stack */ +void +do_pbuf_free (struct spl_pbuf *buf) +{ + if (buf) + { + struct spl_pbuf *pCur = buf; + while (buf) + { + pCur = buf; + buf = buf->freeNext; + spl_pbuf_free (pCur); + } + } +} + +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_listen (struct common_pcb *cpcb, msg_listen * lmsg) +{ + err_t err = ERR_OK; + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY (lmsg, data_com_msg, buffer); + + if (SPL_ERR_IS_FATAL (conn->last_err)) + { + NSTCP_LOGERR ("conn listern but conn has err]conn=%p,err=%d", + conn, conn->last_err); + SET_MSG_ERR (pmsg, conn->last_err); + } + else + { + SET_MSG_ERR (pmsg, ERR_CONN); + + if (cpcb->type == SPL_NETCONN_TCP) + { + if (conn->state == SPL_NETCONN_NONE) + { + struct tcp_pcb *lpcb; + if (((struct tcp_pcb *) (cpcb->conn->private_data))->state != + CLOSED) + { + /* connection is not closed, cannot listen */ + SET_MSG_ERR (pmsg, ERR_VAL);; + } + else + { + u8_t backlog = TCP_DEFAULT_LISTEN_BACKLOG; + + lpcb = + tcp_listen_with_backlog_and_err ((struct tcp_pcb + *) (cpcb-> + conn->private_data), + backlog, &err); + if (lpcb == NULL) + { + /* in this case, the old pcb is still allocated */ + SET_MSG_ERR (pmsg, err); + } + else + { + SET_MSG_ERR (pmsg, ERR_OK); + /* conn now is put on lpcb */ + conn->state = SPL_NETCONN_LISTEN; + + /* NOTE: pmsg->conn->comm_pcb_data == (i64)cpcb; should be already same. */ + conn->private_data = (i64) lpcb; + + tcp_arg (lpcb, conn); + tcp_accept (lpcb, tcp_fn[TCP_FN_STACKX].accept_fn); + + SPL_API_EVENT (conn, NETCONN_EVT_SENDMINUS, 1); + SPL_API_EVENT (conn, NETCONN_EVT_RCVMINUS, 1); + } + } + } + else if (conn->state == SPL_NETCONN_LISTEN) + { + SET_MSG_ERR (pmsg, ERR_OK); + } + } + NSTCP_LOGINF ("listen]conn=%p,pcb=%p,connstate=%d,err=%d", + conn, cpcb, conn->state, GET_MSG_ERR (pmsg)); + + } + +} + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_send (struct common_pcb *cpcb, msg_send_buf * smsg) +{ + struct spl_pbuf *p = smsg->p; + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + spl_netconn_t *conn = cpcb->conn; + + pbuf_set_recycle_flg (p, MBUF_HLD_BY_SPL); /* release buf hold by app on abnormal exit */ + + if (SPL_ERR_IS_FATAL (conn->last_err)) + { + SET_MSG_ERR (m, conn->last_err); + spl_pbuf_free (p); + return; + } + + switch (SPL_NETCONNTYPE_GROUP (cpcb->type)) + { + case SPL_NETCONN_UDP: + { + struct udp_pcb *upcb = (struct udp_pcb *) (cpcb->conn->private_data); + if (ip_addr_isany (&upcb->local_ip)) + { + upcb->local_ip.addr = smsg->local_ip.addr; + ss_set_local_ip (conn, smsg->local_ip.addr); + } + + //spl_ip_addr_t *destIP = &smsg->addr; + + //@TODO udp send need to update like TCP. copy pbuf here. Once testing done for TCP we'll update it here. + if (ip_addr_isany (&smsg->addr)) + { + //SET_MSG_ERR(m, udp_send(upcb, p)); + /* destIP.addr == IPADDR_ANY means it is from stackx_send + and the destination is stored in remote_ip and remote port */ + //destIP = &upcb->remote_ip; + } + else + { + //SET_MSG_ERR(m, udp_sendto(upcb, p, &smsg->addr, smsg->port)); + } + break; + } + + default: + SET_MSG_ERR (m, ERR_CONN); + break; + } + + return; +} + +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_recv (struct common_pcb *cpcb, msg_recv_buf * rmsg) +{ + data_com_msg *m = MSG_ENTRY (rmsg, data_com_msg, buffer); + SET_MSG_ERR (m, ERR_OK); + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + + if (NULL == tpcb) + { + if (rmsg->p) + { + NSPOL_LOGDBG (TCP_DEBUG, + "When pcb was freed: do recv, and free pbuf"); + spl_pbuf_free (rmsg->p); + rmsg->p = NULL; + } + + return; + } + + if (cpcb->conn->type == SPL_NETCONN_TCP) + { + /* Pbuf free should be done in network stack */ + if (rmsg->p) + { + NSPOL_LOGDBG (TCP_DEBUG, "do recv, and free pbuf"); + spl_pbuf_free (rmsg->p); + rmsg->p = NULL; + } + tcp_recved (tpcb, rmsg->len * TCP_MSS); + } +} + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +err_t +do_writemore (struct spl_netconn *conn) +{ + err_t err = ERR_OK; + u16_t len = 0, available; + u8_t write_finished = 0; + struct tcp_pcb *tpcb = (struct tcp_pcb *) conn->private_data; + common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + size_t diff; + const void *dataptr; + + if ((NULL == tpcb) || (NULL == conn) || (SPL_NETCONN_WRITE != conn->state) + || (NULL == cpcb->current_msg)) + { + NSPOL_LOGERR ("conn=NULL"); + return ERR_ARG; + } + + msg_write_buf *wmsg = (msg_write_buf *) cpcb->current_msg->buffer; +start_write: + + if (NULL == wmsg->p) + { + NSPOL_LOGERR ("wmsg->p is NULL]conn=%p,pcb=%p", conn, tpcb); + return ERR_VAL; + } + + u8_t apiflags = wmsg->apiflags; + struct spl_pbuf *current_w_pbuf = wmsg->p; + current_w_pbuf->res_chk.u8Reserve |= NEED_ACK_FLAG; + wmsg->p = current_w_pbuf->next; + current_w_pbuf->next = NULL; + + dataptr = (const u8_t *) current_w_pbuf->payload + cpcb->write_offset; + diff = current_w_pbuf->len - cpcb->write_offset; + + if (diff > 0xffffUL) + { + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } + else + { + len = (u16_t) diff; + } + + available = tcp_sndbuf (tpcb); + if (!available) + { + err = ERR_MEM; + goto err_mem; + } + + if (available < len) + { + /* don't try to write more than sendbuf */ + len = available; + apiflags |= TCP_WRITE_FLAG_MORE; + } + + err = tcp_write (tpcb, dataptr, len, apiflags); + if ((err == ERR_OK) || (err == ERR_MEM)) + { + err_mem: + if ((tcp_sndbuf (tpcb) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen (tpcb) >= TCP_SNDQUEUELOWAT)) + { + SPL_API_EVENT (conn, NETCONN_EVT_SENDMINUS, 1); + } + } + if (err == ERR_OK) + { + cpcb->write_offset += len; + tcp_output (tpcb); + + if (cpcb->write_offset == current_w_pbuf->len) + { + cpcb->write_offset = 0; + spl_pbuf_free (current_w_pbuf); + if (NULL == wmsg->p) + { + /* this message is finished */ + cpcb->write_offset = 0; + SET_MSG_ERR (cpcb->current_msg, err); + + /* go to next msg */ + data_com_msg *forFreemsg = cpcb->current_msg; + msg_write_buf *msg_head_prev = cpcb->msg_head; + cpcb->msg_head = cpcb->msg_head->next; + + /* no msg remain */ + if (cpcb->msg_head == NULL) + { + write_finished = 1; + if (cpcb->msg_tail != NULL + && msg_head_prev != cpcb->msg_tail) + { + NSPOL_LOGWAR (TCP_DEBUG, + "err maybe lost one mesg]conn=%p,pcb=%p", + conn, tpcb); + } + cpcb->msg_tail = NULL; + cpcb->current_msg = NULL; + conn->state = SPL_NETCONN_NONE; + } + else /* go to handle next message */ + { + + cpcb->current_msg = + MSG_ENTRY (cpcb->msg_head, data_com_msg, buffer); + wmsg = cpcb->msg_head; + write_finished = 0; + } + + ASYNC_MSG_FREE (forFreemsg); + } + + } + else + { + if (cpcb->write_offset > current_w_pbuf->len) + { + NSPOL_LOGERR ("Big trouble write_offset > current_w_pbuf->len"); + } + + current_w_pbuf->next = wmsg->p; + wmsg->p = current_w_pbuf; + } + if ((write_finished == 0) && (NULL != wmsg->p)) + { + goto start_write; + } + } + else if (err == ERR_MEM) + { + current_w_pbuf->next = wmsg->p; + wmsg->p = current_w_pbuf; + tcp_output (tpcb); + } + else + { + NSPOL_LOGERR ("]pcb=%p, error when send %d", tpcb, err); + write_finished = 1; + cpcb->write_offset = 0; + current_w_pbuf->next = wmsg->p; + wmsg->p = current_w_pbuf; + tcp_abort (tpcb); + return err; + } + NSTCP_LOGINF ("do_writemore finished with err %d", err); + return ERR_OK; +} + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_write (struct common_pcb *cpcb, msg_write_buf * wmsg) +{ + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + spl_netconn_t *conn = cpcb->conn; + data_com_msg *m = MSG_ENTRY (wmsg, data_com_msg, buffer); + + pbuf_set_recycle_flg (wmsg->p, MBUF_HLD_BY_SPL); /* release buf hold by app on abnormal exit */ + + int tcpState = -1; + + /* if msg->conn is null, then return */ + if (NULL == conn) + { + NSPOL_LOGERR ("Invalid param]msg->conn=%p", conn); + SET_MSG_ERR (m, ERR_VAL); + goto err_return; + } + + tcpState = tpcb->state; + + if ((SPL_ERR_IS_FATAL (conn->last_err)) + && !((ERR_CLSD == conn->last_err) && (CLOSE_WAIT == tcpState))) + { + SET_MSG_ERR (m, conn->last_err); + } + else + { + if (cpcb->type == SPL_NETCONN_TCP) + { + if (cpcb->current_msg != NULL) + { + if (NULL == cpcb->msg_head || NULL == cpcb->msg_tail) + { + /* if possible only if connect is not finished and it's + blocking, then the current_msg is connect msg. + */ + NSPOL_LOGERR ("netconn do_write msg is null]msg_type=%d", + cpcb->current_msg->param.minor_type); + goto err_return; + } + + /* only msg_write_buf will be in msg_head-msg_tail queue */ + wmsg->next = NULL; + cpcb->msg_tail->next = wmsg; + cpcb->msg_tail = wmsg; + (void) do_writemore (conn); + NSTCP_LOGINF ("do_write finished...."); + return; + } + + if (conn->state != SPL_NETCONN_NONE) + { + /* netconn is connecting, closing or in blocking write */ + NSPOL_LOGINF (TCP_DEBUG, + "msg->conn->state != SPL_NETCONN_NONE..netconn is connecting, " + "closing or in blocking write]conn=%p", conn); + SET_MSG_ERR (m, ERR_INPROGRESS); + } + /* this means we should start to process this message */ + else if (tpcb != NULL) + { + conn->state = SPL_NETCONN_WRITE; + + /* set all the variables used by do_writemore */ + if (0 != cpcb->write_offset) + { + NSPOL_LOGERR ("already writing or closing]conn=%p", conn); + goto err_return; + } + + if (0 == wmsg->len) + { + NSPOL_LOGERR ("msg->msg.w.len=0]conn=%p", conn); + goto err_return; + } + + /* record the msg will be processed */ + cpcb->current_msg = m; + if (cpcb->msg_head != NULL || cpcb->msg_tail != NULL) + { + NSPOL_LOGERR ("error maybe lost mesg]conn=%p", conn); + } + cpcb->msg_head = cpcb->msg_tail = wmsg; + wmsg->next = NULL; + cpcb->write_offset = 0; + + (void) do_writemore (conn); + + if ((conn->snd_buf) > TCP_SNDLOWAT) + { + if (cpcb->model == SOCKET_STACKX) + SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1); + } + NSTCP_LOGINF ("do_write finished %d", conn->snd_buf); + + /* for both cases: if do_writemore was called, don't ACK the APIMSG + since do_writemore ACKs it! */ + return; + } + else + { + SET_MSG_ERR (m, ERR_CONN); + } + } + else + { + SET_MSG_ERR (m, ERR_VAL); + } + } + NSTCP_LOGINF ("do_write finished"); + +err_return: + pbuf_free_safe (wmsg->p); + ASYNC_MSG_FREE (m); + + return; +} + +void +do_getsockname (struct common_pcb *cpcb, msg_getaddrname * amsg) +{ + spl_netconn_t *conn; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct sockaddr_in *paddr = (struct sockaddr_in *) &amsg->sock_addr; + + data_com_msg *m = MSG_ENTRY (amsg, data_com_msg, buffer); + + if ((NULL == cpcb) || !(conn = cpcb->conn)) + { + NSTCP_LOGERR ("failed to get sock"); + paddr->sin_family = 0; + paddr->sin_port = 0; + paddr->sin_addr.s_addr = 0; + SET_MSG_ERR (m, ERR_CONN); + return; + } + + NS_LOG_CTRL (LOG_CTRL_GETSOCKNAME, LOGTCP, "NSTCP", NSLOG_DBG, + "cpcb=%p,conn=%p,cmd=%u", cpcb, cpcb->conn, amsg->cmd); + + paddr->sin_family = AF_INET; + SET_MSG_ERR (m, ERR_OK); + + if (amsg->cmd == 0) + { + if (cpcb->type == SPL_NETCONN_TCP) + { + tcp = (struct tcp_pcb *) cpcb->conn->private_data; + /* add judgement:(NETCONN_LISTEN == conn->state) in following if words */ + /* If connect is not done in TCP then the remote address will not be there so need to update proper error code + if the application call the getpeername in TCP mode */ + if ((SPL_NETCONN_LISTEN == conn->state) + || (tcp->remote_ip.addr == 0) || (tcp->remote_port == 0)) + { + paddr->sin_family = 0; + paddr->sin_port = 0; + paddr->sin_addr.s_addr = 0; + SET_MSG_ERR (m, ERR_CONN); + } + else + { + paddr->sin_port = spl_htons (tcp->remote_port); + paddr->sin_addr.s_addr = tcp->remote_ip.addr; + } + } + else if (cpcb->type == SPL_NETCONN_UDP) + { + udp = (struct udp_pcb *) cpcb->conn->private_data; + /* If connect is not done in UDP then the remote address will not be there so need to update proper error code + if the application call the getpeername in UDP mode + */ + if ((udp->remote_ip.addr == 0) || (udp->remote_port == 0)) + { + paddr->sin_family = 0; + paddr->sin_port = 0; + paddr->sin_addr.s_addr = 0; + SET_MSG_ERR (m, ERR_CONN); + } + else + { + paddr->sin_port = spl_htons (udp->remote_port); + paddr->sin_addr.s_addr = udp->remote_ip.addr; + } + } + } + else + { + if (cpcb->type == SPL_NETCONN_TCP) + { + tcp = (struct tcp_pcb *) cpcb->conn->private_data; + paddr->sin_port = spl_htons (tcp->local_port); + paddr->sin_addr.s_addr = tcp->local_ip.addr; + } + else if (cpcb->type == SPL_NETCONN_UDP) + { + udp = (struct udp_pcb *) cpcb->conn->private_data; + paddr->sin_port = spl_htons (udp->local_port); + paddr->sin_addr.s_addr = udp->local_ip.addr; + } + } +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_close (struct common_pcb *cpcb, msg_close * cmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *m = MSG_ENTRY (cmsg, data_com_msg, buffer); + + NSTCP_LOGDBG ("msg->conn=%p,state=%d", conn, conn->state); + + /* @todo: abort running write/connect? */ + if ((conn->state != SPL_NETCONN_NONE) + && (conn->state != SPL_NETCONN_LISTEN) + && (conn->state != SPL_NETCONN_CONNECT)) + { + if (SPL_NETCONN_TCP != cpcb->type) + { + NSTCP_LOGERR ("msg->conn=%p,type=%d", conn, cpcb->type); + return; + } + NSTCP_LOGWAR ("msg->conn=%p,state=%d", conn, conn->state); + SET_MSG_ERR (m, ERR_INPROGRESS); + } + else if (cpcb->type == SPL_NETCONN_TCP) //clear codeDEX warning , CID:24336, cpcb can't be null. + { + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + + if (tpcb == NULL) + { + NSTCP_LOGERR ("tpcb null msg->conn=%p,type=%d", conn, cpcb->type); + return; + } + if ((cmsg->shut != SPL_NETCONN_SHUT_RDWR) + && (conn->state == SPL_NETCONN_LISTEN)) + { + /* LISTEN doesn't support half shutdown */ + NSTCP_LOGERR + ("LISTEN doesn't support half shutdown!]conn=%p,pcb=%p,state=%d", + conn, tpcb, conn->state); + SET_MSG_ERR (m, ERR_CONN); + } + else + { + if (cmsg->shut & SPL_NETCONN_SHUT_RD) + { + /* Drain and delete mboxes */ + (void) netconn_drain (cpcb->type, conn); + unlink_recv_ring (conn); + } + + if (((NULL != cpcb->current_msg) + && (conn->state != SPL_NETCONN_CONNECT)) + || (0 != cpcb->write_offset)) + { + NSTCP_LOGERR + ("already writing or closing]conn=%p,pcb=%p,offset=%zu,curmsg=%p", + conn, tpcb, cpcb->write_offset, cpcb->current_msg); + SET_MSG_ERR (m, ERR_CONN); + return; + } + + if (conn->state == SPL_NETCONN_CONNECT) + { + if (cpcb->current_msg != NULL + && cpcb->current_msg->param.minor_type == + SPL_API_DO_CONNECT) + { + SET_MSG_ERR (m, ERR_RST); + SYNC_MSG_ACK (cpcb->current_msg); + } + else + { + NSTCP_LOGINF + ("already in connecting]conn=%p,cpcb=%p,msg=%p", conn, + cpcb, cpcb->current_msg); + } + /* maybe need to clean cpcb->msg_head */ + } + + conn->state = SPL_NETCONN_CLOSE; + cpcb->current_msg = m; + (void) do_close_internal (cpcb, 1); + + if (SPL_NETCONN_SHUT_RD == cmsg->shut + || SPL_NETCONN_SHUT_RDWR == cmsg->shut) + { + SPL_API_EVENT (conn, SPL_NETCONN_EVT_RCVPLUS, 1); + } + + return; + } + } + else + { + SET_MSG_ERR (m, ERR_VAL); + } +} + +/*trans kerner option to stackx option*/ +int +ks_to_stk_opt (int opt) +{ + int stack_opt = opt; + switch (opt) + { + case SO_DEBUG: + stack_opt = SOF_DEBUG; + break; + case SO_ACCEPTCONN: + stack_opt = SOF_ACCEPTCONN; + break; + case SO_BROADCAST: + stack_opt = SOF_BROADCAST; + break; + case SO_KEEPALIVE: + stack_opt = SOF_KEEPALIVE; + break; + case SO_REUSEADDR: + stack_opt = SOF_REUSEADDR; + break; + case SO_DONTROUTE: + stack_opt = SOF_DONTROUTE; + break; + case SO_USELOOPBACK: + stack_opt = SOF_USELOOPBACK; + break; + case SO_OOBINLINE: + stack_opt = SOF_OOBINLINE; + break; + default: + stack_opt = opt; + break; + } + return stack_opt; +} + +void +do_get_tcpproto_getsockopt_internal (struct common_pcb *cpcb, + msg_setgetsockopt * smsg) +{ + int optname; + void *optval; + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + + optname = smsg->optname; + optval = &smsg->optval; + + switch (optname) + { + case SPL_TCP_NODELAY: + *(int *) optval = tcp_nagle_disabled (tpcb); + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,TCP_NODELAY=%s", + cpcb->socket, (*(int *) optval) ? "on" : "off"); + break; + + case SPL_TCP_KEEPIDLE: + *(int *) optval = (int) (tpcb->keep_idle / 1000); + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPIDLE=%d", + cpcb->socket, *(int *) optval); + break; + case SPL_TCP_KEEPINTVL: + *(int *) optval = (int) (tpcb->keep_intvl / 1000); + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPINTVL=%d", + cpcb->socket, *(int *) optval); + break; + case SPL_TCP_KEEPCNT: + *(int *) optval = (int) tpcb->keep_cnt; + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPCNT=%d", + cpcb->socket, *(int *) optval); + break; + + default: + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname); + SET_MSG_ERR (m, EOPNOTSUPP); + break; + } +} + +void +do_get_ipproto_getsockopt_internal (struct common_pcb *cpcb, + msg_setgetsockopt * smsg) +{ + int optname; + u32_t optlen; + void *optval; + + struct ip_pcb *ipcb = (struct ip_pcb *) (cpcb); + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + + optname = smsg->optname; + optval = &smsg->optval; + optlen = smsg->optlen; + + switch (optname) + { + case IP_TTL: + *(int *) optval = ipcb->ttl; + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,IP_TTL=%d", + cpcb->socket, *(int *) optval); + break; + case IP_TOS: + smsg->optlen = + (optlen < sizeof (u32_t)) ? sizeof (u8_t) : sizeof (u32_t); + if (smsg->optlen == sizeof (u8_t)) + { + *(u8_t *) optval = ipcb->tos; + } + else + { + *(u32_t *) optval = (u32_t) ipcb->tos; + } + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,IP_TOS=%d", + cpcb->socket, *(int *) optval); + break; + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } +} + +void +do_get_solsocket_getsockopt_internal (struct common_pcb *cpcb, + msg_setgetsockopt * smsg) +{ + int optname; + void *optval; + struct tcp_pcb *tpcb = NULL; + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + struct tcp_pcb *pcb = (struct tcp_pcb *) cpcb->conn->private_data; + + optname = smsg->optname; + optval = &smsg->optval; + + switch (optname) + { + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: + case SO_REUSEADDR: + *(int *) optval = + (ip_get_option ((struct ip_pcb *) cpcb, ks_to_stk_opt (optname))) ? 1 + : 0; + NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,optname=%d,optval=%s", + cpcb->socket, optname, (*(int *) optval ? "on" : "off")); + break; + case SO_ACCEPTCONN: + tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + if ((smsg->optlen < sizeof (int)) || (NULL == tpcb)) + { + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, + "(SOL_SOCKET, SO_ACCEPTCONN) failed]fd=%d,tcp=%p,optlen=%u", + cpcb->socket, cpcb, smsg->optlen); + break; + } + if (tpcb->state == LISTEN) + { + *(int *) optval = 1; + } + else + { + *(int *) optval = 0; + } + NSPOL_LOGDBG (SOCKETS_DEBUG, + "(SOL_SOCKET, SO_ACCEPTCONN)]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_TYPE: + switch (cpcb->type) + { + case SPL_NETCONN_RAW: + *(int *) optval = SOCK_RAW; + break; + case SPL_NETCONN_TCP: + *(int *) optval = SOCK_STREAM; + break; + case SPL_NETCONN_UDP: + *(int *) optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int *) optval = cpcb->type; + NSPOL_LOGDBG (SOCKETS_DEBUG, + "(SOL_SOCKET, SO_TYPE): unrecognized socket type]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + } /* switch (sock->conn->type) */ + NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_TYPE)]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_RCVTIMEO: + (*(struct timeval *) optval).tv_sec = + spl_netconn_get_recvtimeout (cpcb) / 1000; + (*(struct timeval *) optval).tv_usec = + (spl_netconn_get_recvtimeout (cpcb) % 1000) * 1000; + NSPOL_LOGDBG (SOCKETS_DEBUG, + "stackx_getsockopt(SOL_SOCKET, SO_RCVTIMEO)]fd=%d,sec=%ld,usec=%ld", + cpcb->socket, (*(struct timeval *) optval).tv_sec, + (*(struct timeval *) optval).tv_usec); + break; + case SO_SNDTIMEO: + (*(struct timeval *) optval).tv_sec = + spl_netconn_get_sendtimeout (cpcb) / 1000; + (*(struct timeval *) optval).tv_usec = + (spl_netconn_get_sendtimeout (cpcb) % 1000) * 1000; + NSPOL_LOGDBG (SOCKETS_DEBUG, + "(SOL_SOCKET, SO_SNDTIMEO)]fd=%dsec=%ld,usec=%ld", + cpcb->socket, (*(struct timeval *) optval).tv_sec, + (*(struct timeval *) optval).tv_usec); + break; + case SO_SNDBUF: + { + u16_t mss = (pcb->mss > TCP_MSS + || pcb->mss == 0) ? TCP_MSS : pcb->mss; + *(int *) optval = spl_netconn_get_sendbufsize (cpcb->conn) * mss; + /*If user has not configured any sendbuffer value then we should return minimum + promissed for the connection based on the flow control. */ + if (*(int *) optval == 0) + { + *(int *) optval = CONN_TCP_MEM_MIN_LINE * mss; + } + NSPOL_LOGDBG (SOCKETS_DEBUG, + "(SOL_SOCKET, SO_SNDBUF)]fd=%d,optval=%d", cpcb->socket, + *(int *) optval); + break; + } + case SO_NO_CHECK: + *(int *) optval = + (udp_flags ((struct udp_pcb *) cpcb->conn->private_data) & + UDP_FLAGS_NOCHKSUM) ? 1 : 0; + NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_NO_CHECK)fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_SNDLOWAT: + *(int *) optval = 1; + NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_SNDLOWAT)fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + + case SO_RCVLOWAT: + *(int *) optval = spl_netconn_get_reclowbufsize (cpcb); + NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_RCVLOWAT)fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_ERROR: + *(int *) optval = GET_MSG_ERR (m); + SET_MSG_ERR (m, 0); + NSPOL_LOGDBG (SOCKETS_DEBUG, "SOL_SOCKET]fd=%d,optval=%d", cpcb->socket, + *(int *) optval); + break; + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported opt]optname=%d", optname); + break; + } +} + +void +do_getsockopt_internal (struct common_pcb *cpcb, msg_setgetsockopt * smsg) +{ + int level; + + if (NULL == smsg) + { + NSTCP_LOGERR ("arg NULL"); + return; + } + + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + + level = smsg->level; + switch (level) + { + /* Level: SOL_SOCKET */ + case SOL_SOCKET: + do_get_solsocket_getsockopt_internal (cpcb, smsg); + + break; + + /* Level: IPPROTO_IP */ + case IPPROTO_IP: + do_get_ipproto_getsockopt_internal (cpcb, smsg); + + break; + /* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + do_get_tcpproto_getsockopt_internal (cpcb, smsg); + + break; + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported level]level=%d", level); + break; + } /* switch (level) */ +} + +void +do_tcpsock_setsockopt (spl_netconn_t * conn, msg_setgetsockopt * smsg) +{ + const void *optval; + int optname; + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + struct tcp_pcb *tpcb = (struct tcp_pcb *) conn->private_data; + + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + + optname = smsg->optname; + optval = &smsg->optval; + + switch (optname) + { + case SPL_TCP_NODELAY: + if (*(int *) optval) + { + tcp_nagle_disable (tpcb); + } + else + { + tcp_nagle_enable (tpcb); + } + + NSTCP_LOGDBG ("IPPROTO_TCP, TCP_NODELAY]fd=%d,optval=%s", + cpcb->socket, (*(int *) optval) ? "on" : "off"); + break; + + case SPL_TCP_KEEPIDLE: + /* CID 52121 (#2 of 3): Other violation (HW_VPP_C_FIND_OPERATORS_2_1_1_3) */ + if ((u32_t) (*(int *) optval) >= INT_MAX / 1000) + { + NSTCP_LOGWAR ("optval too big]optval=%u", + (u32_t) (*(int *) optval)); + *(int *) optval = INT_MAX / 1000; + } + + tpcb->keep_idle = 1000 * (u32_t) (*(int *) optval); + + if (tpcb->keep_idle > TCP_KEEPIDLE_DEFAULT) + { + NSTCP_LOGWAR + ("(%d, IPPROTO_TCP, SPL_TCP_KEEPIDLE. value bigger than 7200000UL so setting to default 7200000UL) requested is -> %" + U32_F " ", cpcb->socket, tpcb->keep_idle); + tpcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + } + + NSTCP_LOGDBG ("IPPROTO_TCP, SPL_TCP_KEEPIDLE](fd=%d,keep_idle=%" U32_F + " ", cpcb->socket, tpcb->keep_idle); + + /* Not required lwip_slowtmr will take care about timer. */ + break; + case SPL_TCP_KEEPINTVL: + /* CID 52121 (#1 of 3): Other violation (HW_VPP_C_FIND_OPERATORS_2_1_1_3) */ + if ((u32_t) (*(int *) optval) >= INT_MAX / 1000) + { + NSTCP_LOGWAR ("optval too big]optval=%u", + (u32_t) (*(int *) optval)); + *(int *) optval = INT_MAX / 1000; + } + + tpcb->keep_intvl = 1000 * (u32_t) (*(int *) optval); + + if (tpcb->keep_intvl > TCP_KEEPIDLE_DEFAULT) /*max timer value supported */ + { + NSTCP_LOGWAR + ("(%d, IPPROTO_TCP, SPL_TCP_KEEPINTVL. value bigger than 7200000UL so setting to default 7200000UL) requested is -> %" + U32_F " ", cpcb->socket, tpcb->keep_intvl); + tpcb->keep_intvl = TCP_KEEPIDLE_DEFAULT; + } + NSTCP_LOGDBG ("IPPROTO_TCP, SPL_TCP_KEEPINTVL]fd=%d,keep_intvl=%" U32_F + " ", cpcb->socket, tpcb->keep_intvl); + break; + case SPL_TCP_KEEPCNT: + tpcb->keep_cnt = (u32_t) (*(int *) optval); + NSTCP_LOGDBG ("IPPROTO_TCP, SPL_TCP_KEEPCNT]fd=%d,keep_cnt=%" U32_F " ", + cpcb->socket, tpcb->keep_cnt); + break; + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } +} + +void +do_ipsock_setsockopt (struct common_pcb *cpcb, msg_setgetsockopt * smsg) +{ + const void *optval; + u32_t optlen; + int optname; + + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + + struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data; + struct ip_pcb *ipcb = (struct ip_pcb *) upcb; + + optname = smsg->optname; + optval = &smsg->optval; + optlen = smsg->optlen; + + int val = 0; + int bNotAllowSet = 0; + switch (optname) + { + case IP_TTL: + ipcb->ttl = (u8_t) (*(int *) optval); + NSIP_LOGDBG ("IPPROTO_IP,IP_TTL]fd=%d,ttl=%u", cpcb->socket, ipcb->ttl); + break; + case IP_TOS: + bNotAllowSet = (cpcb->dataSentFlag != 0) + && ((SPL_NETCONN_TCP == cpcb->type) + || (SPL_NETCONN_UDP == cpcb->type) + || (SPL_NETCONN_RAW == cpcb->type)); + /*not allow set tos value when sending data */ + if (bNotAllowSet) + { + SET_MSG_ERR (m, ERR_VAL); + break; + } + + if (optlen >= sizeof (u32_t)) + { + val = (int) (*(const int *) optval); + } + else if (optlen >= sizeof (u8_t)) + { + val = (int) (*(const u8_t *) optval); + } + + if (SPL_NETCONN_TCP == cpcb->type) + { + val &= ~INET_ECN_MASK; + val |= ipcb->tos & INET_ECN_MASK; + } + ipcb->tos = (u8_t) (val); + + smsg->msg_box = (get_msgbox ((u8_t) val))->llring; + + NSIP_LOGDBG ("IPPROTO_IP,IP_TOS]]fd=%d,tos=%u", cpcb->socket, + ipcb->tos); + break; + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } +} + + /*Made seperate functions to reduce code complexity */ +void +do_setsockopt_recvtimeout_internal (const void *optval, + struct common_pcb *cpcb) +{ + if ((*(struct timeval *) optval).tv_sec < 0) + { + spl_netconn_set_recvtimeout (cpcb, 0); + } + else + { + spl_netconn_set_recvtimeout (cpcb, MAX_WAIT_TIMEOUT); + if ((*(struct timeval *) optval).tv_sec != 0 + || (*(struct timeval *) optval).tv_usec != 0) + { + if ((*(struct timeval *) optval).tv_sec < + ((MAX_WAIT_TIMEOUT / 1000) - 1)) + { + spl_netconn_set_recvtimeout (cpcb, + (*(struct timeval *) optval).tv_sec + * 1000 + + (*(struct timeval *) + optval).tv_usec / 1000); + } + } + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, + "SOL_SOCKET, SO_RCVTIMEO]conn=%p,fd=%d,optval=%d", cpcb, + cpcb->socket, cpcb->recv_timeout); +} + +void +do_setsockopt_sndtimeout_internal (const void *optval, + struct common_pcb *cpcb) +{ + if ((*(struct timeval *) optval).tv_sec < 0) + { + spl_netconn_set_sendtimeout (cpcb, 0); + } + else + { + spl_netconn_set_sendtimeout (cpcb, MAX_WAIT_TIMEOUT); + if ((*(struct timeval *) optval).tv_sec != 0 + || (*(struct timeval *) optval).tv_usec != 0) + { + if ((*(struct timeval *) optval).tv_sec < + ((MAX_WAIT_TIMEOUT / 1000) - 1)) + { + spl_netconn_set_sendtimeout (cpcb, + (*(struct timeval *) optval).tv_sec + * 1000 + + (*(struct timeval *) + optval).tv_usec / 1000); + } + } + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, + "SOL_SOCKET, SO_SNDTIMEO]conn=%p,fd=%d,optval=%d", cpcb, + cpcb->socket, cpcb->send_timeout); +} + +#define IS_TCP_PCB(cpcb) (cpcb && (cpcb->conn) && (SPL_NETCONN_TCP == cpcb->conn->type)) +NSTACK_STATIC inline void +set_opt_sol_socket (struct common_pcb *cpcb, struct tcp_pcb *pcb, + data_com_msg * m, int level, int optname, + const void *optval) +{ + switch (optname) + { + /* The option flags */ + case SO_BROADCAST: + + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + case SO_REUSEADDR: + + if (NULL == pcb) + { + NSPOL_LOGERR ("conn->pcb.ip is null"); + break; + } + + if (*(const int *) optval) + { + ip_set_option ((struct ip_pcb *) pcb, ks_to_stk_opt (optname)); + } + else + { + ip_reset_option ((struct ip_pcb *) pcb, ks_to_stk_opt (optname)); + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, "]conn=%p,fd=%d,optname=0x%x,optval=%s", + cpcb, cpcb->socket, optname, + (*(const int *) optval ? "on" : "off")); + + /* No use now, since tcp_slowtmr will take care about not sending/sending of keepalive */ + break; + + case SO_RCVLOWAT: + spl_netconn_set_reclowbufsize (cpcb, *(int *) optval); + NSPOL_LOGDBG (SOCKETS_DEBUG, + "SOL_SOCKET, SO_RCVLOWAT]conn=%p,fd=%d,optval=%d", cpcb, + cpcb->socket, cpcb->sk_rcvlowat); + break; + + case SO_RCVTIMEO: + /*to reduce code complexity */ + do_setsockopt_recvtimeout_internal (optval, cpcb); + break; + + case SO_SNDTIMEO: + /*to reduce code complexity */ + do_setsockopt_sndtimeout_internal (optval, cpcb); + break; + + case SO_SNDBUF: + { + /* udp pcb invalid access will cause coredump */ + if (!IS_TCP_PCB (cpcb)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, + "not support for non tcp socket]optname=%d, level=%d", + optname, level); + return; + } + + u16_t mss = (pcb->mss > TCP_MSS + || pcb->mss == 0) ? TCP_MSS : pcb->mss; + + if (*(int *) optval < (int) mss) + { + /*set value of one TCP_MSS */ + spl_netconn_set_sendbufsize (cpcb->conn, 1); + } + else + { + spl_netconn_set_sendbufsize (cpcb->conn, + (*(int *) optval) / (int) mss); + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, + "SOL_SOCKET, SO_SNDBUF]conn=%p,fd=%d,optval=%d", cpcb, + cpcb->socket, cpcb->conn->send_bufsize * mss); + break; + } + + case SO_NO_CHECK: + /* How udp is coming here.. ?? @TODO: May be move to someother function.? */ + /* solve segment issue when the PCB is not exist */ + if (NULL == cpcb) + { + NSPOL_LOGERR ("conn->pcb.udp is null"); + break; + } + + struct udp_pcb *upcb = (struct udp_pcb *) pcb; + + if (*(int *) optval) + { + udp_setflags (upcb, udp_flags (upcb) | UDP_FLAGS_NOCHKSUM); + } + else + { + udp_setflags (upcb, udp_flags (upcb) & ~UDP_FLAGS_NOCHKSUM); + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, + "SOL_SOCKET, SO_NO_CHECK]conn=%p,fd=%d,optval=0x%x", cpcb, + cpcb->socket, upcb->flags); + break; + + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } /* switch (optname) */ + +} + +void +do_setsockopt_internal (struct common_pcb *cpcb, msg_setgetsockopt * smsg) +{ + int level, optname; + const void *optval; + + data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer); + struct tcp_pcb *pcb = (struct tcp_pcb *) cpcb->conn->private_data; + + if (NULL == smsg) + { + NSTCP_LOGERR ("arg null!"); + return; + } + + level = smsg->level; + optname = smsg->optname; + optval = &smsg->optval; + + switch (level) + { + /* Level: SOL_SOCKET */ + case SOL_SOCKET: + set_opt_sol_socket (cpcb, pcb, m, SOL_SOCKET, optname, optval); + break; + + /* Level: IPPROTO_IP */ + case IPPROTO_IP: + + if (NULL == cpcb) + { + NSPOL_LOGERR ("conn->pcb.ip is null"); + break; + } + + do_ipsock_setsockopt (cpcb, smsg); + + break; + /* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* udp pcb invalid access will cause coredump */ + if (!IS_TCP_PCB (cpcb)) + { + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, + "not support for non tcp socket]optname=%d,level=%d", + optname, level); + return; + } + + if (NULL == cpcb) + { + NSPOL_LOGERR ("conn->pcb.tcp is null"); + break; + } + + do_tcpsock_setsockopt (cpcb->conn, smsg); + + break; + default: + SET_MSG_ERR (m, ERR_VAL); + NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]level=%d", level); + break; + } /* switch (level) */ +} + +/*app send its version info to nStackMain */ +void +do_app_touch (msg_app_touch * smsg) +{ + //write app version info to running.log + NSPOL_LOGINF (SOCKETS_DEBUG, "hostpid=%u,app_version=%s", smsg->hostpid, + smsg->app_version); +} + +void +tcp_free_accept_ring (spl_netconn_t * conn) +{ + err_t de_err = ERR_OK; + spl_netconn_t *newconn; + while (1) + { + newconn = NULL; + /* -1 means nonblocking */ + de_err = accept_dequeue (conn, (void **) &newconn, (u32_t) - 1); + if (de_err == ERR_WOULDBLOCK || newconn == NULL) + return; + + tcp_drop_conn (newconn); + } +} + +void +tcp_drop_conn (spl_netconn_t * conn) +{ + /* usually we should not access pcb by recv_obj, but no choice */ + struct tcp_pcb *pcb = (struct tcp_pcb *) conn->private_data; + + /* free conn first, even pcb is NULL */ + free_conn_by_spl (conn); + + if (pcb == NULL) + { + NSTCP_LOGWAR + ("a tcp connection in accept queue without pcb!]newconn=%p", conn); + return; + } + + /* tell peer conneciton is reset */ + NSTCP_LOGWAR ("sending RST in accept waiting queue!]pcb=%p", pcb); + + tcp_rst (pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_remove (&tcp_active_pcbs, pcb); + memp_free (MEMP_TCP_PCB, pcb); +} + +void +update_tcp_state (spl_netconn_t * conn, enum tcp_state state) +{ + spl_tcp_state_t spl_state; + + if (conn != NULL) + { + switch (state) + { + case CLOSED: + spl_state = SPL_CLOSED; + break; + case LISTEN: + spl_state = SPL_LISTEN; + break; + case SYN_SENT: + spl_state = SPL_SYN_SENT; + break; + case SYN_RCVD: + spl_state = SPL_SYN_RCVD; + break; + case ESTABLISHED: + spl_state = SPL_ESTABLISHED; + break; + case FIN_WAIT_1: + spl_state = SPL_FIN_WAIT_1; + break; + case FIN_WAIT_2: + spl_state = SPL_FIN_WAIT_2; + break; + case CLOSE_WAIT: + spl_state = SPL_CLOSE_WAIT; + break; + case CLOSING: + spl_state = SPL_CLOSING; + break; + case LAST_ACK: + spl_state = SPL_LAST_ACK; + break; + case TIME_WAIT: + spl_state = SPL_TIME_WAIT; + break; + default: + spl_state = SPL_CLOSED; + break; + } + conn->tcp_state = spl_state; + NSTCP_LOGINF ("conn=%p,private_data=%p,state=%d", conn, + conn->private_data, spl_state); + } +} + +void +do_update_pcbstate () +{ + struct tcp_pcb *tpcb; + int i; + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) + { + for (tpcb = *tcp_pcb_lists[i]; tpcb != NULL; tpcb = tpcb->next) + { + if (tpcb->callback_arg) + { + update_tcp_state ((spl_netconn_t *) tpcb->callback_arg, + tpcb->state); + } + } + } + + return; +} + +void +init_stackx_lwip () +{ + lwip_init (); + sys_timeouts_init (); + return; +} + +void +free_common_pcb (struct common_pcb *cpcb) +{ + if (res_free (&cpcb->res_chk)) + { + NSFW_LOGERR ("conn refree!]conn=%p", cpcb->conn); + return; + } + + common_pcb_reset (cpcb); + + mring_handle pool = p_def_stack_instance->cpcb_seg; + if (nsfw_mem_ring_enqueue (pool, (void *) cpcb) != 1) + { + NSSBR_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + } + return; +} + +struct common_pcb * +alloc_common_pcb (enum spl_netconn_type type) +{ + struct common_pcb *cpcb = NULL; + + if (nsfw_mem_ring_dequeue (p_def_stack_instance->cpcb_seg, (void **) &cpcb) + != 1) + { + NSSBR_LOGERR ("malloc conn failed"); + return NULL; + } + + NSFW_LOGINF ("alloc_common_pcb]cpcb=%p", cpcb); + + common_pcb_init (cpcb); + cpcb->type = type; + return cpcb; +} diff --git a/stacks/lwip_stack/lwip_src/api/spl_netbuf.c b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c new file mode 100644 index 0000000..9c682fc --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c @@ -0,0 +1,58 @@ +/* +* +* 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. +*/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + */ +//#include "sc_dpdk.h" +#include "spl_netbuf.h" + +void +spl_netbuf_delete (struct spl_netbuf *buf) +{ + if (likely (buf != NULL)) + { + spl_pbuf_free (PTR_SHTOL (struct spl_pbuf *, buf->p)); + } +} diff --git a/stacks/lwip_stack/lwip_src/api/spl_netifapi.c b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c new file mode 100644 index 0000000..ab1446a --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c @@ -0,0 +1,288 @@ +/* +* +* 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" + +#if STACKX_NETIF_API + +#include "nsfw_msg_api.h" +#include "netifapi.h" +#include <sys/socket.h> +//#include <netinet/in.h> + +#include "stackx_spl_share.h" +#include "spl_sbr.h" +#include "stackx/spl_api.h" +#include "tcpip.h" +#include "sc_dpdk.h" +#include "spl_instance.h" +#include "spl_hal.h" +#include "spl_def.h" +#include <inet.h> + +struct netifExt *gNetifExt = NULL; + +/** + * common operation for sbr message. + * + * @param msg the api_msg_msg describing the connection type + */ +int +do_halmsg (data_com_msg * m) +{ + NSPOL_LOGDBG (TESTSOCKET_DEBUG | STACKX_DBG_TRACE, + "the msg is from HAL module, minor(%u)", m->param.minor_type); + return 0; +} + +static int +_do_add_netif (data_com_msg * m) +{ + NSPOL_LOGINF (NETIF_DEBUG, "_do_add_netif\n"); + + m->param.err = ERR_OK; + msg_add_netif *_m = (msg_add_netif *) m->buffer; + _m->function (_m); + SYNC_MSG_ACK (m); + return 0; +} + +struct netif * +find_netif_by_if_name (char *if_name) +{ + + struct netifExt *netifEx = gNetifExt; + struct netif *netif = NULL; + + while (netifEx != NULL) + { + if (!(strcmp (netifEx->if_name, if_name))) + { + for (netif = netif_list; netif != NULL; netif = netif->next) + { + if (netifEx->id == netif->num) + return netif; + } + + } + netifEx = netifEx->next; + } + + return NULL; +} + +/*@TODO: May be moved to some other file ? Like HAL*/ +struct netif * +get_netif_by_ip (unsigned int ip) +{ + struct netif *netif; + + if (ip == 0) + { + return NULL; + } + + for (netif = netif_list; netif != NULL; netif = netif->next) + { + if (ip == netif->ip_addr.addr) + { + NSPOL_LOGINF (NETIF_DEBUG, "netif_find: found %x %c %c", ip, + netif->name[0], netif->name[1]); + return netif; + } + } + NSPOL_LOGINF (NETIF_DEBUG, "netif_find: Not found %x", ip); + return NULL; +} + +/* +@TODO: +*/ +struct netif * +netif_check_broadcast_addr (spl_ip_addr_t * addr) +{ + return NULL; +} + +struct netifExt * +getNetifExt (u16_t id) +{ + + struct netifExt *netifEx; + netifEx = gNetifExt; + + while (netifEx != NULL) + { + if (netifEx->id == id) + { + return netifEx; + } + netifEx = netifEx->next; + } + + return NULL; +} + +int +netifExt_add (struct netif *netif) +{ + + /* If Netif Ext already created for it then just return sucess */ + if (getNetifExt (netif->num)) + return 0; + + struct netifExt *netifEx = malloc (sizeof (struct netifExt)); + if (!netifEx) + { + return -1; + } + + if (memset (netifEx, 0, sizeof (struct netifExt)) < 0) + { + return -1; + } + + NSPOL_LOGINF (NETIF_DEBUG, "netifExt_added \n"); + + netifEx->id = netif->num; + + /* add this netif to the list */ + netifEx->next = gNetifExt; + gNetifExt = netifEx; + return 0; +} + +void +do_netifapi_netif_add (msg_add_netif * pmsg) +{ + struct netif *netif = NULL; + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gw; + + data_com_msg *m = MSG_ENTRY (pmsg, data_com_msg, buffer); + ipaddr.addr = pmsg->ipaddr->addr; + netmask.addr = pmsg->netmask->addr; + gw.addr = pmsg->gw->addr; + + NSPOL_LOGINF (NETIF_DEBUG, "do_netifapi_netif_add \n"); + netif = netif_add (pmsg->netif, + &ipaddr, + &netmask, &gw, pmsg->state, pmsg->init, pmsg->input); + + if (NULL == netif) + { + SET_MSG_ERR (m, ERR_IF); + } + else + { + + SET_MSG_ERR (m, ERR_OK); + NSPOL_LOGINF (NETIF_DEBUG, "netif created name %c%c%d\n", + netif->name[0], netif->name[1], netif->num); + pmsg->voidfunc (pmsg->netif); + add_disp_netif (pmsg->netif); + } + +} + +err_t +spl_netifapi_netif_add (struct netif *pnetif, + spl_ip_addr_t * ipaddr, + spl_ip_addr_t * netmask, + spl_ip_addr_t * gw, + void *state, + netif_init_fn init, + netif_input_fn input, netifapi_void_fn voidfunc) +{ + msg_add_netif stmsg; + + stmsg.function = do_netifapi_netif_add; + stmsg.netif = pnetif; + stmsg.ipaddr = ipaddr; + stmsg.netmask = netmask; + stmsg.gw = gw; + stmsg.state = state; + stmsg.init = init; + stmsg.input = input; + stmsg.voidfunc = voidfunc; + return tcpip_netif_add (&stmsg); +} + +int +add_netif_ip (char *netif_name, unsigned int ip, unsigned int mask) +{ + struct netif *pnetif; + int retval; + + if (get_netif_by_ip (ip)) + { + NSPOL_LOGERR ("ip is exist]IP=%s", inet_ntoa (ip)); + return -1; + } + NSPOL_LOGINF (NETIF_DEBUG, "add_netif_ip] IP=%s", inet_ntoa (ip)); + + pnetif = find_netif_by_if_name (netif_name); + if (pnetif == NULL) + { + return -1; + } + + pnetif->ip_addr.addr = ip; + pnetif->netmask.addr = mask; + + if (ip) + { + retval = etharp_request (pnetif, &pnetif->ip_addr); + + if (ERR_OK != retval) + { + NSPOL_LOGERR ("etharp_request failed]retval=%d,netif=%p,ip=%u", retval, pnetif, pnetif->ip_addr.addr); //inet_ntoa is not thread-safe, print u32 instead. + } + } + + NSPOL_LOGINF (NETIF_DEBUG, "add_netif_ip]netif_name=%s,IP=%s,mask=0x%08x", + netif_name, inet_ntoa (ip), spl_htonl (mask)); + return 0; +} + +/*lint -e438*/ +int +del_netif_ip (char *netif_name, unsigned int ip) +{ + struct netif *pnetif; + //struct netif* vnetif = NULL; + //struct netif** ref; + + pnetif = find_netif_by_if_name (netif_name); + if (NULL == pnetif) + { + return -1; + } + + NSPOL_LOGINF (NETIF_DEBUG, "del_netif_ip] IP=%s", inet_ntoa (ip)); + + pnetif->ip_addr.addr = 0; + pnetif->netmask.addr = 0; + return 0; +} + +REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_HAL, SPL_TCPIP_MSG_NETIFAPI, + do_halmsg); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_HAL, SPL_TCPIP_MSG_NETIFAPI, + NETIF_DO_ADD, _do_add_netif); + +#endif /* STACKX_NETIF_API */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_sbr.c b/stacks/lwip_stack/lwip_src/api/spl_sbr.c new file mode 100644 index 0000000..4c510a5 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_sbr.c @@ -0,0 +1,495 @@ +/* +* +* 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 "stackx_spl_share.h" +#include "spl_api.h" +#include "ip.h" +#include "spl_api_msg.h" +#include "stackx_spl_msg.h" +#include "internal_msg.h" +#include "spl_sbr.h" +#include "spl_pbuf.h" + +/** + * common operation for sbr message. + * + * @param msg the api_msg_msg describing the connection type + */ +int +do_sbrmsg (data_com_msg * m) +{ + return 0; +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +static int +_do_newconn (data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_new_netconn *_m = (msg_new_netconn *) m->buffer; + m->param.err = spl_pcb_new (_m); + + if (ERR_OK != m->param.err) + { + NSPOL_LOGERR ("pcb_new err]conn=%p,pid=%u,err=%d", _m->conn, + m->param.recycle_pid, m->param.err); + goto ERROR; + } + + NSFW_LOGINF ("alloc pcb]conn=%p,pcb=%p,pid=%u", _m->conn, + _m->conn->private_data, m->param.recycle_pid); + + /* sbr use it to set receiver after new connction */ + m->param.receiver = (i64) & _m->conn->private_data; + m->param.comm_receiver = (i64) & _m->conn->comm_pcb_data; + _m->conn->recv_obj = m->param.receiver; + + SYNC_MSG_ACK (m); + return 0; + +ERROR: + SYNC_MSG_ACK (m); + return 0; +} + +int +_do_connect (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb == NULL) + { + m->param.err = ERR_CLSD; + SYNC_MSG_ACK (m); + return 0; + } + + msg_connect *_m = (msg_connect *) m->buffer; + do_connect (cpcb, _m); + + /** + * err == ERR_OK only applies for blocking connction, so others mean + * in progress for nonblocking connection or failed to connect + * cpcb may be NULL, so don't change the order of the 2 ifs. + */ + if (m->param.err != ERR_OK || cpcb->type != SPL_NETCONN_TCP) + SYNC_MSG_ACK (m); + + return 0; +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +int +_do_close (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb != NULL) + { + msg_close *_m = (msg_close *) m->buffer; + do_close (cpcb, _m); + } + + /* if cpcb == NULL, assuming the close is okay, err = ERR_OK */ + SYNC_MSG_ACK (m); + + return 0; +} + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the data_com_msg to handle + */ +static int +_do_delconn (data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_delete_netconn *_m = (msg_delete_netconn *) m->buffer; + + if (0 == (--_m->msg_box_ref)) + { + /* the aync msg is released inside */ + ss_recycle_conn ((void *) _m, do_try_delconn); + } + + return 0; +} + +/** + * handle message to send UDP packets. + * + * @param msg the data_com_msg to handle + */ +static int +_do_send (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + msg_send_buf *_m = (msg_send_buf *) m->buffer; + if (cpcb == NULL) + { + NS_LOG_CTRL (LOG_CTRL_SEND, STACKX, "NSPOL", NSLOG_ERR, + "failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + spl_pbuf_free (_m->p); + _m->p = NULL; + ASYNC_MSG_FREE (m); + return -1; + } + + do_send (cpcb, _m); + + ASYNC_MSG_FREE (m); + + return 0; +} + +/** + * handle message to send TCP packets. + * + * @param msg the data_com_msg to handle + */ +static int +_do_write (data_com_msg * m) +{ + m->param.err = ERR_OK; + + void *tpcb = TCP_PRIVATE_PTR (m); + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + + msg_write_buf *_m = (msg_write_buf *) m->buffer; + if ((tpcb == NULL) || (cpcb == NULL)) + { + NS_LOG_CTRL (LOG_CTRL_WRITE, STACKX, "NSPOL", NSLOG_ERR, + "failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + spl_pbuf_free (_m->p); + _m->p = NULL; + ASYNC_MSG_FREE (m); + return -1; + } + + do_write (cpcb, _m); + + return 0; +} + +/** + * handle message to receive. + * + * @param msg the data_com_msg to handle + */ +static int +_do_recv (data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_recv_buf *_m = (msg_recv_buf *) m->buffer; + void *tpcb = TCP_PRIVATE_PTR (m); + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + + if ((tpcb == NULL) || (cpcb == NULL)) + { + NS_LOG_CTRL (LOG_CTRL_RECV, STACKX, "NSPOL", NSLOG_ERR, + "failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + spl_pbuf_free (_m->p); + _m->p = NULL; + ASYNC_MSG_FREE (m); + return -1; + } + + do_recv (cpcb, _m); + ASYNC_MSG_FREE (m); + return 0; +} + +/** + * handle message to bind local address. + * + * @param msg the data_com_msg to handle + */ +static int +_do_bind (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb == NULL) + { + NSPOL_LOGERR ("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK (m); + return -1; + } + + msg_bind *_m = (msg_bind *) m->buffer; + do_bind (cpcb, _m); + + SYNC_MSG_ACK (m); + + return 0; +} + +/** + * handle message to listen for new connection. + * + * @param msg the data_com_msg to handle + */ +static int +_do_listen (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb == NULL) + { + NSPOL_LOGERR ("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_CONN; + SYNC_MSG_ACK (m); + return -1; + } + + msg_listen *_m = (msg_listen *) m->buffer; + do_listen (cpcb, _m); + + /* Update since pcb may have been changed */ + //m->param.receiver = (i64)&_m->conn->private_data; + SYNC_MSG_ACK (m); + return 0; +} + +/** + * handle message to set socket option. + * + * @param msg the data_com_msg to handle + */ +static int +_do_setsockopt (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb == NULL) + { + + NSPOL_LOGERR ("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK (m); + return -1; + } + + msg_setgetsockopt *_m = (msg_setgetsockopt *) m->buffer; + do_setsockopt_internal (cpcb, _m); + + SYNC_MSG_ACK (m); + + return 0; +} + +/** + * handle message to get socket option. + * + * @param msg the data_com_msg to handle + */ +static int +_do_getsockopt (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb == NULL) + { + NSPOL_LOGERR ("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK (m); + return -1; + } + + msg_setgetsockopt *_m = (msg_setgetsockopt *) m->buffer; + do_getsockopt_internal (cpcb, _m); + + SYNC_MSG_ACK (m); + + return 0; +} + +/** + * handle message to free pbuf which never used afterwards by application. + * + * @param msg the data_com_msg to handle + */ + +static int +_do_pbuf_free (data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_free_buf *_m = (msg_free_buf *) m->buffer; + do_pbuf_free (_m->buf); + + ASYNC_MSG_FREE (m); + + return 0; +} + +static int +_do_getsock_name (data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR (m); + if (cpcb == NULL) + { + NSPOL_LOGERR ("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK (m); + return -1; + } + + msg_getaddrname *_m = (msg_getaddrname *) m->buffer; + do_getsockname (cpcb, _m); + + SYNC_MSG_ACK (m); + + return 0; +} + +/* app send its version info to nStackMain */ +static int +_do_app_touch (data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_app_touch *_m = (msg_app_touch *) m->buffer; + do_app_touch (_m); + + ASYNC_MSG_FREE (m); + return 0; +} + +/** + * process message from sbr module, all the processing function + * is registered when nstack is up. + * + * @param msg the api_msg_msg pointing to the connection + */ +int +spl_sbr_process (data_com_msg * m) +{ + if (m == NULL) + { + NSPOL_LOGERR ("message is NULL"); + return -1; + } + + return call_msg_fun (m); +} + +int +spl_unsupport_process (data_com_msg * m) +{ + NSPOL_LOGINF (TCPIP_DEBUG, "module_type=%u,major_type=%u,minor_type=%u", + m->param.module_type, m->param.major_type, + m->param.minor_type); + if (MSG_SYN_POST == m->param.op_type) + { + m->param.err = ERR_EPROTONOSUPPORT; + SYNC_MSG_ACK (m); + } + else + { + ASYNC_MSG_FREE (m); + } + + return -1; +} + +REGIST_MSG_UNSUPPORT_FUN (spl_unsupport_process); +REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + do_sbrmsg); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_NEWCONN, _do_newconn); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_CONNECT, _do_connect); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_CLOSE, _do_close); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_DELCON, _do_delconn); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_SEND, _do_send); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_WRITE, _do_write); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_RECV, _do_recv); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_BIND, _do_bind); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_LISTEN, _do_listen); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_GET_SOCK_OPT, _do_getsockopt); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_SET_SOCK_OPT, _do_setsockopt); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_PBUF_FREE, _do_pbuf_free); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_GETSOCK_NAME, _do_getsock_name); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_APP_TOUCH, _do_app_touch); /* app send its version info to nStackMain */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_tcpip.c b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c new file mode 100644 index 0000000..688c34b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c @@ -0,0 +1,1548 @@ +/* +* +* 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 <pthread.h> +#include <sched.h> +#include <signal.h> +#include "memp.h" +#include "mem.h" +#include "spl_pbuf.h" +//#include "sockets.h" +//#include <netinet/in.h> + +#include "stackx_spl_share.h" +#include "spl_api.h" +#include "spl_tcpip.h" +#include "init.h" +#include "stackx/internal_msg.h" +#include "netif/sc_dpdk.h" +#include "sharedmemory.h" +#include "stackx_instance.h" +#include "netif/common.h" +//#include "nettool/nettool.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "spl_sbr.h" +#include "spl_tcpip.h" + +#include "spl_instance.h" +#include "nsfw_mem_api.h" +#include "nsfw_msg_api.h" +#include "configuration_reader.h" + +#include "nsfw_ps_api.h" +#include "alarm_api.h" +#include "nstack_share_res.h" +#include "spl_timers.h" + +#include "etharp.h" +#include "raw.h" +#include "udp.h" +#include "tcp.h" +#include "igmp.h" +#include "memp.h" +#include "inet.h" +#include "sys_arch.h" + +#include "sys.h" + +#define NSTACK_MAIN_MAX_PARA 19 +#define NSTACK_MAIN_MIN_PARA 1 + +#define DPDK_DEFAULT_EAL_MEM_SIZE (1024) + +#define OPT_EAL_MEM_SIZE "--eal-mem-size=" + +/********************/ +/* extern variables */ +/********************/ +extern mring_handle spl_get_msg_pool (); +extern mring_handle spl_get_conn_pool (); +extern u32 spl_get_conn_num (); +extern err_t ethernet_input (struct pbuf *p, struct netif *netif); + +/* tcpip main thread sleep time, configured by user(nStackMain "-sleep" option) */ +extern int g_tcpip_thread_sleep_time; + +/* netif related */ +extern struct stackx_port_info *head_used_port_list; + +extern u32_t uStackArgIndex; + +extern int g_tcpip_thread_stat; + +/********************/ +/* global variables */ +/********************/ + +/* timer thread id */ +sys_thread_t g_timerThread_id = 0; + +/*Add an associative mapping relationship to p_stackx_instance based on lcore_id */ + +int globalArgc = 0; + +/* Set different mem args to PAL and EAL */ +char **gArgv = NULL; + +int g_dpdk_argc = 0; +char **g_dpdk_argv = NULL; + +/*The sum of the four queue processing messages does not exceed TASK_BURST*/ +static u32 g_highestMboxNum = 12; +static u32 g_mediumMboxNum = 8; +static u32 g_lowestMboxNum = 4; +static u32 g_primaryMboxNum = 8; + +/* [set ip_tos2prio size to IPTOS_TOS_MASK >> 1) + 1] */ +u8_t ip_tos2prio[(IPTOS_TOS_MASK >> 1) + 1] = { + TC_PRIO_BESTEFFORT, + ECN_OR_COST (FILLER), + TC_PRIO_BESTEFFORT, + ECN_OR_COST (BESTEFFORT), + TC_PRIO_BULK, + ECN_OR_COST (BULK), + TC_PRIO_BULK, + ECN_OR_COST (BULK), + TC_PRIO_INTERACTIVE, + ECN_OR_COST (INTERACTIVE), + TC_PRIO_INTERACTIVE, + ECN_OR_COST (INTERACTIVE), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST (INTERACTIVE_BULK), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST (INTERACTIVE_BULK) +}; + +/********************/ +/* extern functions */ +/********************/ +extern err_t ethernetif_init (struct netif *pnetif); +extern int nstack_stackx_init (int flag); +extern int nstack_rd_mng_int (int flag); +extern void tcp_sys_rmem_init (); +extern void ethernetif_packets_input (struct netif *pstnetif); + +/********************************/ +/* function forward declaration */ +/********************************/ + +static inline u32 priority_sched_mbox (struct stackx_stack *share_memory, + void **box, u32 n); +static inline char +rt_tos2priority (u8_t tos) +{ + return ip_tos2prio[IPTOS_TOS (tos) >> 1]; +} + +u64 +timer_get_threadid () +{ + return g_timerThread_id; +} + +#if (DPDK_MODULE != 1) +NSTACK_STATIC inline void +do_recv_task (struct disp_netif_list *dnlist, u16 index_task) +{ + struct netifExt *pnetifExt = NULL; + + while (dnlist) + { + struct netif *currentNetif = dnlist->netif; + dnlist = dnlist->next; + + pnetifExt = getNetifExt (currentNetif->num); + if (NULL == pnetifExt) + return; + + if (currentNetif != NULL && pnetifExt->num_packets_recv > index_task) + { + ethernetif_packets_input (currentNetif); + } + } +} + +static inline int +is_valid_sleep_time (int sleep_time) +{ +#define TCP_IP_THREAD_MAX_SLEEP_TIME 500 + if ((sleep_time < 0) || (sleep_time > TCP_IP_THREAD_MAX_SLEEP_TIME)) + { + return 0; + } + + return 1; +} + +static int +thread_init () +{ + sigset_t mask; + + if (0 != sigemptyset (&mask)) + { + NSTCP_LOGERR ("sigemptyset function call error"); + return -1; + } + + if (0 != sigaddset (&mask, SIGRTMIN)) + { + NSTCP_LOGERR ("sigaddset function call error"); + return -1; + } + + if ((pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0) + || (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)) + { + NSTCP_LOGERR ("pthread setcancel function call error"); + return -1; + } + + if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0) + { + NSPOL_LOGERR ("pthread_sigmask function call error"); + return -1; + } + + return 0; +} + +alarm_result +spl_socket_resource_check_func (void) +{ + + mring_handle conn_ring = spl_get_conn_pool (); + unsigned int rate_use = 0; + alarm_result ret_alarm; + u32 ring_size = 0, ring_not_used_count = 0; + u32 socket_num = spl_get_conn_num (); + + ring_size = nsfw_mem_ring_size (conn_ring); + + if (0 == socket_num) + { + /* assign a valid id, then return */ + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + return ret_alarm; + } + + ring_not_used_count = nsfw_mem_ring_using_count (conn_ring); + + rate_use = (ring_size - ring_not_used_count) * 100 / socket_num; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + + if (rate_use >= USEAGE_HIGHT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + NSPOL_LOGWAR (TCPIP_DEBUG, + "app using too much socket resources,the rate is bigger than 80%"); + } + else if (rate_use <= USEAGE_LOW) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_SOCKET; + + return ret_alarm; + +} + +alarm_result +spl_msg_buf_resource_check_func (void) +{ + + mring_handle msg_ring = spl_get_msg_pool (); + unsigned int rate_use = 0; + alarm_result ret_alarm; + u32 ring_size = 0, ring_not_used_count = 0; + + ring_size = nsfw_mem_ring_size (msg_ring); + + if (0 == ring_size) + { + /* assign a valid id, then return */ + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + return ret_alarm; + } + + ring_not_used_count = nsfw_mem_ring_using_count (msg_ring); + + rate_use = (ring_size - ring_not_used_count) * 100 / ring_size; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + + if (rate_use >= USEAGE_HIGHT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else if (rate_use <= USEAGE_LOW) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_MSG_BUF; + + return ret_alarm; + +} + +NSTACK_STATIC int +tcpip_thread_init () +{ + if (thread_init () != 0) + { + return -1; + } + + if (!is_valid_sleep_time (g_tcpip_thread_sleep_time)) + { + g_tcpip_thread_sleep_time = 0; + } + + alarm_para tcp_alarm_para; + tcp_alarm_para.period_alarm.time_length = 5; /* 5 second period */ + tcp_alarm_para.alarm_reason_count = 2; /*both resource */ + tcp_alarm_para.func_alarm_check_period[0] = spl_socket_resource_check_func; + tcp_alarm_para.alarm_reason_set[0] = ALARM_REASON_SOCKET; + tcp_alarm_para.func_alarm_check_period[1] = spl_msg_buf_resource_check_func; + tcp_alarm_para.alarm_reason_set[1] = ALARM_REASON_MSG_BUF; + (void) ns_reg_alarm (ALARM_EVENT_NSTACK_RESOURCE_ALARM, ALARM_PERIOD_CHECK, + &tcp_alarm_para); + + ns_send_init_alarm (ALARM_EVENT_NSTACK_RESOURCE_ALARM); + + printmeminfo (); + return 0; +} + +sys_mbox_t +get_primary_box () +{ + return &p_def_stack_instance->lstack.primary_mbox; +} + +NSTACK_STATIC inline u16 +tcpip_netif_recv (struct disp_netif_list * nif_list) +{ + + u16 num_recv_task = 0, netif_packet_num; + + struct netif *tmpnetif = NULL; + struct netifExt *pnetifExt = NULL; + + while (nif_list) + { + tmpnetif = nif_list->netif; + + netif_packet_num = spl_hal_recv (tmpnetif, 0); + pnetifExt = getNetifExt (tmpnetif->num); + if (NULL == pnetifExt) + return 0; + + /* store the packet number in each netif */ + pnetifExt->num_packets_recv = netif_packet_num; + + /** + * num_recv_task is the maximum packets of the netif among + * all the netifs. + */ + if (num_recv_task < netif_packet_num) + { + num_recv_task = netif_packet_num; + } + + nif_list = nif_list->next; + } + + return num_recv_task; +} + +NSTACK_STATIC inline void +no_task_in_one_loop () +{ +} + +#endif + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * SPL_NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +spl_tcpip_input (struct pbuf *p, struct netif *inp) +{ + err_t ret; + NSPOL_LOGINF (TCPIP_DEBUG, "PACKET]p=%p,inp=%p", (void *) p, (void *) inp); + print_pbuf_payload_info (p, false); + + /* every netif has been set NETIF_FLAG_ETHARP flag, no need else branch */ + ret = ethernet_input (p, inp); + return ret; +} + +int +_do_spl_callback_msg (data_com_msg * m) +{ + NSPOL_LOGDBG (TCPIP_DEBUG, "tcpip_thread: CALLBACK]msg=%p", (void *) m); + + m->param.err = ERR_OK; + + msg_internal_callback *callback = (msg_internal_callback *) (m->buffer); + if (!callback->function) + { + NSTCP_LOGERR ("function ptr is null in SPL_TCPIP_MSG_CALLBACK msg"); + ASYNC_MSG_FREE (m); + return 0; + } + + callback->function (callback->ctx); + ASYNC_MSG_FREE (m); + + return 0; +} + +/***************************************************************************** +* Prototype : get_msgbox +* Description : According to the socket tos value to determine which priority queue to send +* Input : struct stackx_stack *sharedmemory, struct netconn *conn, enum api_msg_type type +* Output : Queue pointer +* Return Value : Queue pointer +* Calls : +* Called By : +* +*****************************************************************************/ +struct queue * +get_msgbox (int tos) +{ + struct stackx_stack *sharedmemory = &p_def_stack_instance->lstack; + + if ((MSG_PRIO_QUEUE_NUM < 3) || (0 == tos)) + { + return &sharedmemory->primary_mbox; + } + + char prio = rt_tos2priority ((u8_t) tos); + if ((TC_PRIO_INTERACTIVE == prio)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the highest mbox....."); + return &sharedmemory->priority_mbox[0]; + } + else if ((TC_PRIO_BESTEFFORT == prio) || (TC_PRIO_INTERACTIVE_BULK == prio)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the medium mbox....."); + return &sharedmemory->priority_mbox[1]; + } + else if ((TC_PRIO_BULK == prio) || (TC_PRIO_FILLER == prio)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the lowest mbox....."); + return &sharedmemory->priority_mbox[2]; + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the primary mbox....."); + return &sharedmemory->primary_mbox; +} + +/***************************************************************************** +* Prototype : priority_sched_mbox +* Description : According to the priority from the message queue to take +* the message to deal with each cycle to take the total number of messages +* not exceed to TASK_BURST +* Input : struct stackx_stack *sharedmemory, struct netconn *conn, enum api_msg_type type +* Output : Queue pointer +* Return Value : Queue pointer +* Calls : +* Called By : +* +*****************************************************************************/ +static inline u32 +priority_sched_mbox (struct stackx_stack *share_memory, void **box, u32 n) +{ + /* high:primary:medium:low -> 3:2:2:1(total:TASK_BURST) */ + if (unlikely + ((g_highestMboxNum + g_mediumMboxNum + g_primaryMboxNum + + g_lowestMboxNum) != n)) + { + g_mediumMboxNum = n >> 2; + g_lowestMboxNum = n >> 3; + g_primaryMboxNum = n >> 2; + g_highestMboxNum = + n - g_mediumMboxNum - g_primaryMboxNum - g_lowestMboxNum; + } + + u32 highestMboxNum = g_highestMboxNum; + u32 primaryMboxNum = g_primaryMboxNum; + u32 lowestMboxNum = g_lowestMboxNum; + u32 mediumMboxNum = g_mediumMboxNum; + + u32 totalNum = 0; + u32 num = 0; + u32 oldLowestNum = 0; + + num = nsfw_mem_ring_dequeuev (share_memory->priority_mbox[0].llring, + (box + totalNum), highestMboxNum); + if (unlikely (num > highestMboxNum)) + { + num = highestMboxNum; + NSTCP_LOGERR + ("something wrong:num>highestMboxNum]num=%u,highestMboxNum=%u", num, + highestMboxNum); + } + + totalNum += num; + + u32 temp = highestMboxNum - num; + /* bisect the left number of highest */ + primaryMboxNum += (temp >> 1); + mediumMboxNum += temp - (temp >> 1); + + num = nsfw_mem_ring_dequeuev (share_memory->priority_mbox[1].llring, + (box + totalNum), mediumMboxNum); + if (unlikely (num > mediumMboxNum)) + { + num = mediumMboxNum; + NSTCP_LOGERR + ("something wrong.num>mediumMboxNum]num=%u,mediumMboxNum=%u", num, + mediumMboxNum); + } + + totalNum += num; + primaryMboxNum += mediumMboxNum - num; //occupy the left number of medium + + /* dynamically adjust g_mediumMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_mediumMboxNum; + if (0 == num) + { + g_mediumMboxNum = 1; + } + else if (num < g_mediumMboxNum) + { + g_mediumMboxNum = num; + } + else + { + g_mediumMboxNum = n >> 2; + } + + g_highestMboxNum += oldLowestNum - g_mediumMboxNum; + + num = nsfw_mem_ring_dequeuev (share_memory->primary_mbox.llring, + (box + totalNum), primaryMboxNum); + if (unlikely (num > primaryMboxNum)) + { + num = primaryMboxNum; + NSTCP_LOGERR + ("something wrong.num>primaryMboxNum]num=%u,primaryMboxNum=%u", num, + primaryMboxNum); + } + + totalNum += num; + lowestMboxNum += primaryMboxNum - num; //occupy the left number of primary + + /* dynamically adjust g_primaryMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_primaryMboxNum; + if (0 == num) + { + g_primaryMboxNum = 1; + } + else if (num < g_primaryMboxNum) + { + g_primaryMboxNum = num; + } + else + { + g_primaryMboxNum = n >> 2; + } + + g_highestMboxNum += oldLowestNum - g_primaryMboxNum; + + if (lowestMboxNum > (n - totalNum)) + { + lowestMboxNum = n - totalNum; + } + + num = nsfw_mem_ring_dequeuev (share_memory->priority_mbox[2].llring, + (box + totalNum), lowestMboxNum); + if (unlikely (num > lowestMboxNum)) + { + num = lowestMboxNum; + NSTCP_LOGERR + ("something wrong.num>lowestMboxNum]num=%u,lowestMboxNum=%u", num, + lowestMboxNum); + } + + totalNum += num; + + /* dynamically adjust g_lowestMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_lowestMboxNum; + if (0 == num) + { + g_lowestMboxNum = 1; + } + else if (num < g_lowestMboxNum) + { + g_lowestMboxNum = num; + } + else + { + g_lowestMboxNum = n >> 3; + } + + g_highestMboxNum += oldLowestNum - g_lowestMboxNum; + + return totalNum; +} + +/** + * call ltt_apimsg in STACKX TIMER THREAD + * + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return error code given back by the function that was called + */ +err_t +ltt_apimsg (sys_timeout_handler h, void *arg) +{ + data_com_msg *p_msg_entry; + sys_mbox_t mbox = get_primary_box (); + if (sys_mbox_valid (&mbox)) + { + if (-1 == spl_msg_malloc (&p_msg_entry)) + { + NSPOL_LOGERR ("ltt_apimsg:spl_msg_malloc failed."); + return -1; + } + + p_msg_entry->param.module_type = MSG_MODULE_TIMER; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_TIMER; + p_msg_entry->param.minor_type = TIMER_MSG_TIMEOUT; + p_msg_entry->param.op_type = MSG_ASYN_POST; + + sys_sem_init (&p_msg_entry->param.op_completed); + + msg_timer *tmsg = (msg_timer *) (p_msg_entry->buffer); + tmsg->act = h; + tmsg->arg = arg; + + if (msg_post (p_msg_entry, mbox->llring) < 0) + { + NSPOL_LOGERR + ("msg post is failed]module_type=%u, major_type=%u, minor_type=%u", + p_msg_entry->param.module_type, p_msg_entry->param.major_type, + p_msg_entry->param.minor_type); + spl_msg_free (p_msg_entry); + return ERR_VAL; + } + + return ERR_OK; + } + + NSPOL_LOGERR ("mbox is invalid"); + return ERR_VAL; +} + +int +_do_spl_timer_msg (data_com_msg * m) +{ + NSPOL_LOGDBG (TESTSOCKET_DEBUG | STACKX_DBG_TRACE, + "the msg is from TIMER module, minor(%u)", + m->param.minor_type); + return 0; +} + +static int +_do_timeout_handle (data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_timer *tmo_msg = (msg_timer *) m->buffer; + if (!tmo_msg->act) + { + NSTCP_LOGERR ("TIMER_MSG_TIMEOUT msg act is NULL"); + ASYNC_MSG_FREE (m); + return -1; + } + + timeout_phandler (tmo_msg->act, tmo_msg->arg); + ASYNC_MSG_FREE (m); + return 0; +} + +static int +_do_clear_timer (data_com_msg * m) +{ + NSTCP_LOGDBG ("TIMER_CLEAR API]msg=%p", (void *) m); + + msg_timer *handle = (msg_timer *) (m->buffer); + if (!handle->act) + { + NSTCP_LOGERR ("function ptr is null in TIMER_MSG_CLEAR msg"); + SET_MSG_ERR (m, ERR_VAL); + return 0; + } + + //stackxTcpPcbClearTimer((struct tcp_pcb *)handle->act, (unsigned long)handle->arg); + spl_msg_free (m); + + return 0; +} + +err_t +ltt_clearTmrmsg (void *pcb, void *arg) +{ + data_com_msg *p_msg_entry; + sys_mbox_t mbox = get_primary_box (); + if (sys_mbox_valid (&mbox)) + { + if (-1 == spl_msg_malloc (&p_msg_entry) || (NULL == p_msg_entry)) + { + NSPOL_LOGERR ("ltt_clearTmrmsg:spl_msg_malloc failed."); + return -1; + } + + p_msg_entry->param.module_type = MSG_MODULE_TIMER; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_TIMER; + p_msg_entry->param.minor_type = TIMER_MSG_CLEAR; + p_msg_entry->param.op_type = MSG_ASYN_POST; + p_msg_entry->param.receiver = 0; + sys_sem_init (&p_msg_entry->param.op_completed); + + msg_timer *tmo = (msg_timer *) (p_msg_entry->buffer); + tmo->act = pcb; + tmo->arg = arg; + + if (msg_post (p_msg_entry, mbox->llring) < 0) + { + NSPOL_LOGERR + ("msg post is failed]module_type=%u, major_type=%u, minor_type=%u", + p_msg_entry->param.module_type, p_msg_entry->param.major_type, + p_msg_entry->param.minor_type); + spl_msg_free (p_msg_entry); + return ERR_VAL; + } + + return ERR_OK; + } + + NSPOL_LOGERR ("mbox is invalid"); + return ERR_VAL; +} + +#if STACKX_NETIF_API +err_t +tcpip_netif_post (data_com_msg * m) +{ + err_t err = ERR_OK; + sys_mbox_t mbox = get_primary_box (); + + if (NULL == mbox || !sys_mbox_valid (&mbox)) + { + NSPOL_LOGERR ("mbox not initialed well"); + err = ERR_MEM; + goto err_exit; + } + + if (NULL == mbox->llring) + { + int tryCount = 0; +#define TCP_NETIF_WAITINIT_MAX_COUNT 10 + NSPOL_LOGWAR (TCPIP_DEBUG, "mbox->llring not initialed yet..."); + sys_sleep_ns (0, 100000000); + while (!mbox->llring && (++tryCount < TCP_NETIF_WAITINIT_MAX_COUNT)) + { + NSPOL_LOGWAR (TCPIP_DEBUG, "mbox->llring not initialed yet..."); + sys_sleep_ns (0, 100000000); + } + + if (NULL == mbox->llring) + { + NSPOL_LOGERR ("failed to get a valid mbox->llring"); + err = ERR_MEM; + goto err_exit; + } + } + + NSPOL_LOGINF (TCPIP_DEBUG, "post tcpip_netif_msg..."); + + if (msg_post_with_lock_rel (m, mbox->llring) < 0) + { + err = ERR_VAL; + } + else + { + err = m->param.err; + } + +err_exit: + /* it's a sync message */ + spl_msg_free (m); + return err; +} + +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_netif_add (msg_add_netif * tmp) +{ + data_com_msg *p_msg_entry = NULL; + msg_add_netif *nmsg = NULL; + + if (spl_msg_malloc (&p_msg_entry) == -1) + { + NSPOL_LOGERR ("tcpip_netifapi:spl_msg_malloc failed."); + return ERR_MEM; + } + + p_msg_entry->param.module_type = MSG_MODULE_HAL; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_NETIFAPI; + p_msg_entry->param.minor_type = NETIF_DO_ADD; + p_msg_entry->param.op_type = MSG_SYN_POST; + p_msg_entry->param.receiver = 0; + sys_sem_init (&p_msg_entry->param.op_completed); + + nmsg = (msg_add_netif *) p_msg_entry->buffer; + nmsg->function = tmp->function; + nmsg->netif = tmp->netif; + nmsg->ipaddr = tmp->ipaddr; + nmsg->netmask = tmp->netmask; + nmsg->gw = tmp->gw; + nmsg->state = tmp->state; + nmsg->init = tmp->init; + nmsg->input = tmp->input; + nmsg->voidfunc = tmp->voidfunc; + + return tcpip_netif_post (p_msg_entry); +} + +#endif /* STACKX_NETIF_API */ + +/* Added for congestion control, maybe not used end */ + +extern err_t init_ptimer (void); +extern struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM]; + +/*=========== set share config for nStackMain =============*/ +static inline mzone_handle +create_mem_zone (nsfw_mem_zone * zone_info) +{ + return nsfw_mem_zone_create (zone_info); +} + +static inline int +set_zone_info (nsfw_mem_zone * zone_info, nsfw_mem_name * name_info, u32 len) +{ + if (EOK != + MEMCPY_S (&(zone_info->stname), sizeof (nsfw_mem_name), name_info, + sizeof (nsfw_mem_name))) + { + NSPOL_DUMP_LOGERR ("create pool failed, MEMCPY_S failed."); + return -1; + } + + zone_info->length = len; + zone_info->isocket_id = NSFW_SOCKET_ANY; + + return 0; +} + +int +set_share_config () +{ + static nsfw_mem_name g_cfg_mem_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, NSTACK_SHARE_CONFIG }; + + nsfw_mem_zone zone_info; + if (set_zone_info (&zone_info, &g_cfg_mem_info, get_cfg_share_mem_size ()) < + 0) + { + return -1; + } + + mzone_handle base_cfg_mem = create_mem_zone (&zone_info); + if (NULL == base_cfg_mem) + { + NSPOL_LOGERR ("get config share mem failed."); + return -1; + } + + if (set_share_cfg_to_mem (base_cfg_mem) < 0) + { + NSPOL_LOGERR ("set share config failed."); + return -1; + } + + return 0; +} + +int +init_by_tcpip_thread () +{ + if (spl_init_app_res () != 0) + { + NSPOL_LOGERR ("spl_init_app_res failed"); + return -1; + } + + if (init_instance () != 0) + { + return -1; + } + if (tcpip_thread_init () != 0) + { + NSTCP_LOGERR ("tcpip_thread_init failed!"); + return -1; + } + + init_stackx_lwip (); + + return 0; +} + +void +spl_tcpip_thread (void *arg) +{ + g_tcpip_thread_stat = 1; + + if (init_by_tcpip_thread () != 0) + { + return; + } + + struct stackx_stack *share_memory = &p_def_stack_instance->lstack; + struct disp_netif_list **iflist = &p_def_stack_instance->netif_list; + + u32 run_count = 0; + u16 task_loop; + u16 num_recv_task = 0, num_send_timer_task = 0; + u16 index_task = 0; + int tcpip_thread_sleep_interval = g_tcpip_thread_sleep_time * 1000; + void *task_queue[TASK_BURST]; + data_com_msg *msg; + + while (1) + { + /* try to receive packet from hal layer */ + num_recv_task = tcpip_netif_recv (*iflist); + + /* try to receive message from sbr layer */ + num_send_timer_task = priority_sched_mbox (share_memory, + task_queue, TASK_BURST); + + if (num_recv_task) + { + NSPOL_LOGINF (TCPIP_DEBUG, "num_recv_task %d", num_recv_task); + } + + /* Statistics the total number of messages */ + + /* Separate statistics on socket api messages */ + /* handle the request from upper layer and lower layer one by one */ + task_loop = (num_send_timer_task > num_recv_task ? + num_send_timer_task : num_recv_task); + if (task_loop == 0) + { + no_task_in_one_loop (); + + if (run_count++ > 20) + { + sys_sleep_ns (0, tcpip_thread_sleep_interval); + } + continue; + } + + run_count = 0; + index_task = 0; + + /* at least one task to be handled */ + while (task_loop > index_task) + { + /* handle one packet from hal layer (for multi-nic case, do it for each) */ + if (num_recv_task > index_task) + { + do_recv_task (*iflist, index_task); + } + + /* handle one message from sbr layer */ + if (num_send_timer_task > index_task) + { + msg = (data_com_msg *) (task_queue[index_task]); + + spl_process (msg); + } + + do_update_pcbstate (); + + index_task++; + } + } +} + +int +create_tcpip_thread () +{ + int ret; + u64 arg = 0; + + /* main tcpip thread */ + char thread_name[32] = TCPIP_THREAD_NAME; + + sys_thread_t thread = sys_thread_new (thread_name, spl_tcpip_thread, + (void *) arg, + TCPIP_THREAD_STACKSIZE, + g_cfg_item_info[CFG_SEG_PRI] + [CFG_SEG_THREAD_PRI_PRI].value); + + cpu_set_t cpuset; + CPU_ZERO (&cpuset); /*lint !e534 */ + CPU_SET (g_nstack_bind_cpu, &cpuset); /*lint !e522 */ + ret = pthread_setaffinity_np (thread, sizeof (cpuset), &cpuset); + if (ret != 0) + { + NSPOL_LOGERR ("pthread_setaffinity_np failed]thread_name=%s,ret=%d", + TCPIP_THREAD_NAME, ret); + } + + return 0; +} + +int +create_timer_thread () +{ +#if 1 + if (init_ptimer () != ERR_OK) + { + NSPOL_LOGERR ("init_ptimer failed"); + return -1; + } + + sys_thread_t thread_timer = + sys_thread_new (PTIMER_THREAD_NAME, ptimer_thread, NULL, + TCPIP_THREAD_STACKSIZE, 0); + cpu_set_t cpuset_timer; + CPU_ZERO (&cpuset_timer); + CPU_SET (1, &cpuset_timer); + int ret = pthread_setaffinity_np (thread_timer, sizeof (cpuset_timer), + &cpuset_timer); + if (ret != 0) + { + NSPOL_LOGERR ("TCP init Timer Trhead Failed!"); + } + + g_timerThread_id = thread_timer; +#endif + return 0; +} + +int +init_ip_module_reader () +{ + output_api api = { 0 }; + api.post_to = post_ip_module_msg; + api.add_netif_ip = add_netif_ip; + api.del_netif_ip = del_netif_ip; + regist_output_api (&api); + + if (init_configuration_reader () < 0) + { + NSPOL_LOGERR ("init_configuration_reader failed"); + return -1; + } + + return 0; +} + +extern int init_unmatch_version (void); +extern int init_stackx_global_tick (void); + +int +init_by_main_thread () +{ + NSPOL_LOGINF (TCPIP_DEBUG, "init_by_main_thread start version 1.4"); + + uStackArgIndex++; + if (spl_hal_init (g_dpdk_argc, (char **) g_dpdk_argv) < 0) + { + NSPOL_LOGERR ("spl_hal_init failed"); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 1"); + + if (init_unmatch_version () != 0) + { + return -1; + } + + NSPOL_LOGINF (TCPIP_DEBUG, "stage 2"); + if (init_stackx_global_tick () != 0) + { + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 3"); + + if (spl_init_group_array () != 0) + { + NSPOL_LOGERR ("spl_init_group_array failed"); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 4"); + + if (set_share_config () != 0) + { + NSPOL_LOGERR ("set_share_config failed."); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 5"); + + if (create_timer_thread () != 0) + { + //NSPOL_LOGERR(TCPIP_DEBUG,"init_timer_thread failed."); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 6"); + + if (create_tcpip_thread () != 0) + { + NSPOL_LOGERR ("init_tcpip_thread failed."); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 7"); + + if (init_ip_module_reader () != 0) + { + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage end"); + + return 0; +} + +void +create_netif (struct stackx_port_info *p_port_info) +{ + int ret; + struct spl_ip_addr ip, mask, gw; + struct netifExt *netifEx = NULL; + struct netif *netif = malloc (sizeof (struct netif)); + if (!netif) + { + NSPOL_LOGERR ("malloc failed"); + return; + } + + if (MEMSET_S (netif, sizeof (struct netif), 0, sizeof (struct netif)) < 0) + { + NSPOL_LOGERR ("MEMSET_S failed"); + goto error; + } + + NSPOL_LOGINF (TCPIP_DEBUG, "I get netif]ip=%s,gw=%s,mask=%s,name=%c %c", + p_port_info->linux_ip.ip_addr_linux, + p_port_info->linux_ip.ip_addr_linux, + p_port_info->linux_ip.mask_linux, + netif->name[0], netif->name[1]); + + if (inet_aton (p_port_info->linux_ip.ip_addr_linux, &ip) + && inet_aton (p_port_info->linux_ip.ip_addr_linux, &gw) + && inet_aton (p_port_info->linux_ip.mask_linux, &mask)) + { + ret = + spl_netifapi_netif_add (netif, &ip, &mask, &gw, NULL, ethernetif_init, + spl_tcpip_input, netif_set_up); + if (ERR_OK != ret) + { + NSPOL_LOGERR ("netifapi_netif_add failed]ret=%d", ret); + goto error; + } +#if 1 + if (0 != netifExt_add (netif)) + return; + +#endif + netifEx = getNetifExt (netif->num); + if (NULL == netifEx) + return; + + netifEx->hdl = p_port_info->linux_ip.hdl; + ret = + STRCPY_S (netifEx->if_name, sizeof (netifEx->if_name), + p_port_info->linux_ip.if_name); + if (EOK != ret) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", ret); + goto error; + } + return; + } + +error: + free (netif); +} + +int +post_ip_module_msg (void *arg, ip_module_type Type, + ip_module_operate_type operate_type) +{ + data_com_msg *p_msg_entry; + msg_ip_module *imsg; + sys_mbox_t mbox = get_primary_box (); + + if (!mbox) + { + NSOPR_LOGERR ("get_cur_mbox failed"); + return ERR_MEM; + } + + if (sys_mbox_valid (&mbox)) + { + if (spl_msg_malloc (&p_msg_entry) == -1) + { + NSOPR_LOGERR ("ip_route_apimsg:spl_msg_malloc failed."); + return ERR_MEM; + } + + sys_sem_init (&p_msg_entry->param.op_completed); + p_msg_entry->param.module_type = MSG_MODULE_IP; + p_msg_entry->param.op_type = MSG_SYN_POST; + + imsg = (msg_ip_module *) (p_msg_entry->buffer); + imsg->arg = arg; + imsg->type = Type; + imsg->operate_type = operate_type; + + NSOPR_LOGINF ("post ip_module msg to tcpip_thread]action=%d,type=%d", + operate_type, Type); + + if (msg_post (p_msg_entry, mbox->llring) != 0) + { + NSOPR_LOGERR + ("msg_post failed,this can not happen]action=%d,type=%d", + operate_type, Type); + } + + spl_msg_free (p_msg_entry); + + return ERR_OK; + } + + NSOPR_LOGERR ("mbox is invalid"); + return ERR_VAL; +} + +int +process_ip_module_msg (void *arg, ip_module_type module_type, + ip_module_operate_type operate_type) +{ + int retval = process_configuration (arg, module_type, operate_type); + + NSOPR_LOGINF ("tcpip_thread: ip_module cmd exec over, send SYNC_MSG_ACK"); + return retval; +} + +int +init_new_network_configuration () +{ + if (spl_hal_port_init () < 0) + { + return -1; + } + + return 0; +} + +static int +_process_ip_module_msg (data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_ip_module *_m = (msg_ip_module *) m->buffer; + int ret = process_ip_module_msg (_m->arg, _m->type, _m->operate_type); + SYNC_MSG_ACK (m); + return ret; +} + +int +spl_post_msg (u16 mod, u16 maj, u16 min, u16 op, char *data, u16 data_len, + u32 src_pid) +{ + data_com_msg *p_msg_entry; + + sys_mbox_t mbox = get_primary_box (); + if (!sys_mbox_valid (&mbox)) + { + NSPOL_LOGERR + ("get mbox null!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, maj, + min, op, data, data_len); + return ERR_MEM; + } + + if (spl_msg_malloc (&p_msg_entry) == -1) + { + NSPOL_LOGERR ("get msg null!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", + mod, maj, min, op, data, data_len); + return ERR_MEM; + } + + sys_sem_init (&p_msg_entry->param.op_completed); + p_msg_entry->param.module_type = mod; + p_msg_entry->param.major_type = maj; + p_msg_entry->param.minor_type = min; + p_msg_entry->param.op_type = op; + p_msg_entry->param.src_pid = src_pid; + + int retVal; + if (NULL != data) + { + retVal = + MEMCPY_S ((char *) p_msg_entry->buffer, sizeof (p_msg_entry->buffer), + data, data_len); + if (EOK != retVal) + { + NSPOL_LOGERR ("MEMCPY_S failed %d.", retVal); + spl_msg_free (p_msg_entry); + return ERR_MEM; + } + } + + if (msg_post_with_lock_rel (p_msg_entry, mbox->llring) != 0) + { + NSPOL_LOGERR + ("post msg error!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, + maj, min, op, data, data_len); + spl_msg_free (p_msg_entry); + return ERR_MEM; + } + + if (MSG_SYN_POST == op) + { + spl_msg_free (p_msg_entry); + } + + NSOPR_LOGDBG ("post msg suc!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", + mod, maj, min, op, data, data_len); + return ERR_OK; +} + +/* +* Added by eliminate duplicated code degree, the function is moved to the public places +*adjust memory size for pal and eal mem size: this func do the following things: +*1. copy argv to gArgv and g_dpdk_argv +*2. remove OPT_EAL_MEM_SIZE option so that the rtp and rte options process won't reprt unrecognized option error. +*3. set eal mem size and pal_mem_size = mem - eal_mem_size +*/ +int +adjust_mem_arg (int argc, char *argv[]) +{ + int i = 0; + int j = 0; + int retVal; + char *tmp = NULL; + char *tmp2 = NULL; + int arg_mem_index = -1; + char *saveptr1 = NULL; + int mem_size = 0; + int mem_size_parsed = 0; // if multi -m argument is set, then only deal with the first one + int eal_mem_size = DPDK_DEFAULT_EAL_MEM_SIZE; // Default + + if ((argc < NSTACK_MAIN_MIN_PARA) || (argc > NSTACK_MAIN_MAX_PARA)) + { + NSPOL_LOGERR ("The number of parameters is incorrect"); + return -1; + } + + globalArgc = argc; + g_dpdk_argc = argc; + gArgv = (char **) malloc (sizeof (char *) * argc); + if (gArgv == NULL) + { + NSPOL_LOGERR ("Failed to alloc memory for adjust mem args\n"); + goto ERROR_INIT; + } + + g_dpdk_argv = (char **) malloc (sizeof (char *) * argc); + if (g_dpdk_argv == NULL) + { + NSPOL_LOGERR ("Failed to alloc memory for adjust mem args\n"); + goto ERROR_INIT; + } + + retVal = + MEMSET_S (gArgv, sizeof (char *) * argc, 0, sizeof (char *) * argc); + if (EOK != retVal) + { + NSPOL_LOGERR ("MEMSET_S failed %d.", retVal); + goto ERROR_INIT; + } + retVal = + MEMSET_S (g_dpdk_argv, sizeof (char *) * argc, 0, sizeof (char *) * argc); + if (EOK != retVal) + { + NSPOL_LOGERR ("MEMSET_S failed %d.", retVal); + goto ERROR_INIT; + } + + for (i = 0; i < argc; i++) + { + if (!strcmp ("-m", argv[i]) && !mem_size_parsed && (i + 1 < argc)) + { + gArgv[j] = argv[i]; + g_dpdk_argv[j] = argv[i]; + i++; + j++; + gArgv[j] = (char *) malloc (32); + g_dpdk_argv[j] = (char *) malloc (32); + /* gArgv[j] is NULL and g_dpdk_argv[j] isnot NULL, need free g_dpdk_argv[j] */ + arg_mem_index = j; + if ((!gArgv[j]) || (!g_dpdk_argv[j])) + { + NSPOL_LOGERR ("malloc failed."); + goto ERROR_PARSE_MALLOC; + } + mem_size = atoi (argv[i]); + /* add memory range check,avoid handle wrongly later begin */ + if (mem_size < 0) + { + goto ERROR_PARSE_MALLOC; + } + + j++; + mem_size_parsed = 1; + } + else + if (!strncmp (OPT_EAL_MEM_SIZE, argv[i], strlen (OPT_EAL_MEM_SIZE))) + { + tmp = strdup (argv[i]); + if (tmp == NULL) + { + goto ERROR_PARSE_MALLOC; + } + /* Always use re-entrant functions in multi-threaded environments */ + tmp2 = strtok_r (tmp, "=", &saveptr1); + tmp2 = strtok_r (NULL, "=", &saveptr1); + if (tmp2) + { + eal_mem_size = atoi (tmp2); + /* add memory range check,avoid handle wrongly later */ + if (eal_mem_size < 0) + { + free (tmp); + goto ERROR_PARSE_MALLOC; + } + } + free (tmp); + tmp = NULL; + /*remove this option since dpdk can't recognize it and may cause error. */ + /*so we should deduct the count by 1. */ + globalArgc -= 1; + g_dpdk_argc -= 1; + } + else + { + gArgv[j] = argv[i]; + g_dpdk_argv[j] = argv[i]; + j++; + } + } + + /* -m arg is set */ + if (arg_mem_index >= 0) + { + retVal = + SPRINTF_S (gArgv[arg_mem_index], 32, "%d", mem_size - eal_mem_size); + if (-1 == retVal) + { + NSPOL_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + goto ERROR_PARSE_MALLOC; + } + retVal = SPRINTF_S (g_dpdk_argv[arg_mem_index], 32, "%d", eal_mem_size); + if (-1 == retVal) + { + NSPOL_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + goto ERROR_PARSE_MALLOC; + } + } + else + { + // do nothing for no mem arg and leave it for default process of pal and eal. + } + + return 0; +ERROR_PARSE_MALLOC: + if (arg_mem_index >= 0 && gArgv[arg_mem_index]) + { + free (gArgv[arg_mem_index]); + gArgv[arg_mem_index] = NULL; + } + + if (arg_mem_index >= 0 && g_dpdk_argv[arg_mem_index]) + { + free (g_dpdk_argv[arg_mem_index]); + g_dpdk_argv[arg_mem_index] = NULL; + } + +ERROR_INIT: + if (gArgv) + { + free (gArgv); + gArgv = NULL; + globalArgc = 0; + } + + if (g_dpdk_argv) + { + free (g_dpdk_argv); + g_dpdk_argv = NULL; + g_dpdk_argc = 0; + } + + return -1; +} + +REGIST_MSG_MODULE_FUN (MSG_MODULE_IP, _process_ip_module_msg); + +REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_SPL, SPL_TCPIP_MSG_CALLBACK, + _do_spl_callback_msg); + +REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + _do_spl_timer_msg); + +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + TIMER_MSG_TIMEOUT, _do_timeout_handle); + +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + TIMER_MSG_CLEAR, _do_clear_timer); diff --git a/stacks/lwip_stack/lwip_src/common/rb_tree.c b/stacks/lwip_stack/lwip_src/common/rb_tree.c new file mode 100644 index 0000000..3dcb37a --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/rb_tree.c @@ -0,0 +1,393 @@ +/* +* +* 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 "rb_tree.h" + +static void +__rb_rotate_right (struct rb_node *node, struct rb_root *root) +{ + struct rb_node *left = node->rb_left; + struct rb_node *parent = rb_parent (node); + + if ((node->rb_left = left->rb_right)) + { + rb_set_parent (left->rb_right, node); + } + + left->rb_right = node; + + rb_set_parent (left, parent); + + if (parent) + { + if (node == parent->rb_right) + { + parent->rb_right = left; + } + else + { + parent->rb_left = left; + } + } + else + { + root->rb_node = left; + } + + rb_set_parent (node, left); +} + +static void +__rb_rotate_left (struct rb_node *node, struct rb_root *root) +{ + struct rb_node *parent = rb_parent (node); + + struct rb_node *right = node->rb_right; + + if ((node->rb_right = right->rb_left)) + { + rb_set_parent (right->rb_left, node); + } + + right->rb_left = node; + rb_set_parent (right, parent); + + if (parent) /* judge parent node */ + { + if (node == parent->rb_left) + { + parent->rb_left = right; + } + else + { + parent->rb_right = right; + } + } + else + { + root->rb_node = right; + } + + rb_set_parent (node, right); +} + +static void +__rb_erase_color (struct rb_node *rb_tree_node, + struct rb_node *rb_tree_parent, + struct rb_root *rb_tree_root) +{ + struct rb_node *rb_tree_other; + + while ((!rb_tree_node || rb_is_black (rb_tree_node)) + && (rb_tree_node != rb_tree_root->rb_node)) + { + if (rb_tree_parent == NULL) + { + break; + } + + if (rb_tree_parent->rb_left == rb_tree_node) + { + rb_tree_other = rb_tree_parent->rb_right; + if (rb_is_red (rb_tree_other)) + { + rb_set_black (rb_tree_other); + rb_set_red (rb_tree_parent); + __rb_rotate_left (rb_tree_parent, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_right; + } + + if ((!rb_tree_other->rb_left + || rb_is_black (rb_tree_other->rb_left)) + && (!rb_tree_other->rb_right + || rb_is_black (rb_tree_other->rb_right))) + { + rb_set_red (rb_tree_other); + rb_tree_node = rb_tree_parent; + rb_tree_parent = rb_parent (rb_tree_node); + } + else + { + if (!rb_tree_other->rb_right + || rb_is_black (rb_tree_other->rb_right)) + { + rb_set_black (rb_tree_other->rb_left); + rb_set_red (rb_tree_other); + __rb_rotate_right (rb_tree_other, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_right; + } + + rb_set_color (rb_tree_other, rb_color (rb_tree_parent)); + rb_set_black (rb_tree_parent); + rb_set_black (rb_tree_other->rb_right); + __rb_rotate_left (rb_tree_parent, rb_tree_root); + rb_tree_node = rb_tree_root->rb_node; + break; + } + } + else + { + rb_tree_other = rb_tree_parent->rb_left; + if (rb_is_red (rb_tree_other)) + { + rb_set_black (rb_tree_other); + rb_set_red (rb_tree_parent); + __rb_rotate_right (rb_tree_parent, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_left; + } + + if ((!rb_tree_other->rb_left + || rb_is_black (rb_tree_other->rb_left)) + && (!rb_tree_other->rb_right + || rb_is_black (rb_tree_other->rb_right))) + { + rb_set_red (rb_tree_other); + rb_tree_node = rb_tree_parent; + rb_tree_parent = rb_parent (rb_tree_node); + } + else + { + if (!rb_tree_other->rb_left + || rb_is_black (rb_tree_other->rb_left)) + { + rb_set_black (rb_tree_other->rb_right); + rb_set_red (rb_tree_other); + __rb_rotate_left (rb_tree_other, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_left; + } + + rb_set_color (rb_tree_other, rb_color (rb_tree_parent)); + rb_set_black (rb_tree_parent); + rb_set_black (rb_tree_other->rb_left); + __rb_rotate_right (rb_tree_parent, rb_tree_root); + rb_tree_node = rb_tree_root->rb_node; + break; + } + } + } + + if (rb_tree_node) + { + rb_set_black (rb_tree_node); + } +} + +void +rb_insert_color (struct rb_node *rb_tree_node, struct rb_root *rb_tree_root) +{ + struct rb_node *rb_tree_parent, *rb_tree_gparent; + + if (!rb_tree_node || !rb_tree_root) + return; + + while ((rb_tree_parent = rb_parent (rb_tree_node)) + && rb_is_red (rb_tree_parent)) + { + rb_tree_gparent = rb_parent (rb_tree_parent); + + if (rb_tree_parent == rb_tree_gparent->rb_left) + { + { + register struct rb_node *rb_tree_uncle = + rb_tree_gparent->rb_right; + if (rb_tree_uncle && rb_is_red (rb_tree_uncle)) + { + rb_set_black (rb_tree_uncle); + rb_set_black (rb_tree_parent); + rb_set_red (rb_tree_gparent); + rb_tree_node = rb_tree_gparent; + continue; + } + } + + if (rb_tree_parent->rb_right == rb_tree_node) + { + register struct rb_node *rb_tree_tmp; + __rb_rotate_left (rb_tree_parent, rb_tree_root); + rb_tree_tmp = rb_tree_parent; + rb_tree_parent = rb_tree_node; + rb_tree_node = rb_tree_tmp; + } + + rb_set_black (rb_tree_parent); + rb_set_red (rb_tree_gparent); + __rb_rotate_right (rb_tree_gparent, rb_tree_root); + } + else + { + { + register struct rb_node *rb_tree_uncle = rb_tree_gparent->rb_left; + if (rb_tree_uncle && rb_is_red (rb_tree_uncle)) + { + rb_set_black (rb_tree_uncle); + rb_set_black (rb_tree_parent); + rb_set_red (rb_tree_gparent); + rb_tree_node = rb_tree_gparent; + continue; + } + } + + if (rb_tree_parent->rb_left == rb_tree_node) + { + register struct rb_node *rb_tree_tmp; + __rb_rotate_right (rb_tree_parent, rb_tree_root); + rb_tree_tmp = rb_tree_parent; + rb_tree_parent = rb_tree_node; + rb_tree_node = rb_tree_tmp; + } + + rb_set_black (rb_tree_parent); + rb_set_red (rb_tree_gparent); + __rb_rotate_left (rb_tree_gparent, rb_tree_root); + } + } + + rb_set_black (rb_tree_root->rb_node); +} + +void +rb_erase (struct rb_node *node, struct rb_root *root) +{ + struct rb_node *child, *parent; + int color; + + if (!node || !root) + return; + + if (!node->rb_left) + { + child = node->rb_right; + } + else if (!node->rb_right) + { + child = node->rb_left; + } + else + { + struct rb_node *old = node, *left; + + node = node->rb_right; + while ((left = node->rb_left) != NULL) + { + node = left; + } + + if (rb_parent (old)) + { + if (rb_parent (old)->rb_left == old) + { + rb_parent (old)->rb_left = node; + } + else + { + rb_parent (old)->rb_right = node; + } + } + else + { + root->rb_node = node; + } + + child = node->rb_right; + parent = rb_parent (node); + color = rb_color (node); + + if (parent == old) + { + parent = node; + } + else + { + if (child) + { + rb_set_parent (child, parent); + } + + parent->rb_left = child; + + node->rb_right = old->rb_right; + rb_set_parent (old->rb_right, node); + } + + node->rb_parent_color = old->rb_parent_color; + node->rb_left = old->rb_left; + rb_set_parent (old->rb_left, node); + + goto color; + } + + parent = rb_parent (node); + color = rb_color (node); + + if (child) + { + rb_set_parent (child, parent); + } + + if (parent) + { + if (parent->rb_left == node) + { + parent->rb_left = child; + } + else + { + parent->rb_right = child; + } + } + else + { + root->rb_node = child; + } + +color: + if (color == RB_BLACK) + { + __rb_erase_color (child, parent, root); + } +} + +struct rb_node * +rb_next (const struct rb_node *node) +{ + struct rb_node *parent; + + if (!node) + return NULL; + + if (rb_parent (node) == node) + { + return NULL; + } + + if (node->rb_right) + { + node = node->rb_right; + while (node->rb_left) + { + node = node->rb_left; + } + + return (struct rb_node *) node; + } + + while ((parent = rb_parent (node)) && (node == parent->rb_right)) + { + node = parent; + } + + return parent; +} diff --git a/stacks/lwip_stack/lwip_src/common/rb_tree.h b/stacks/lwip_stack/lwip_src/common/rb_tree.h new file mode 100644 index 0000000..87174fa --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/rb_tree.h @@ -0,0 +1,112 @@ +/* +* +* 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. +*/ + +#ifndef _UNX_RBTREE_H +#define _UNX_RBTREE_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif +#include <stdint.h> +#include "types.h" +#include "common_pal_bitwide_adjust.h" + +#define rb_parent(a) ((struct rb_node *)((a)->rb_parent_color & ~3)) +#define rb_color(a) ((a)->rb_parent_color & 1) + +struct rb_node +{ + union + { + unsigned long rb_parent_color; + u64 rb_parent_color_a; + }; + +#define RB_RED 0 +#define RB_BLACK 1 + union + { + struct rb_node *rb_right; + u64 rb_right_a; + }; + + union + { + struct rb_node *rb_left; + u64 rb_left_a; + }; +}; + +#define rb_set_red(c) do { (c)->rb_parent_color &= ~1; } while (0) +#define rb_set_black(c) do { (c)->rb_parent_color |= 1; } while (0) + +/* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root +{ + union + { + struct rb_node *rb_node; + u64 rb_node_a; + }; +}; + +#define rb_is_red(e) (!rb_color(e)) +#define rb_is_black(e) rb_color(e) + +static inline void +rb_set_color (struct rb_node *rb1, int color2) +{ + rb1->rb_parent_color = (rb1->rb_parent_color & ~1) | color2; +} + +static inline void +rb_set_parent (struct rb_node *rb1, struct rb_node *pa) +{ + rb1->rb_parent_color = (rb1->rb_parent_color & 3) | (unsigned long) pa; +} + +#define RB_ROOT (struct rb_root) { NULL, } + +extern void rb_erase (struct rb_node *, struct rb_root *); + +extern void rb_insert_color (struct rb_node *, struct rb_root *); + +extern struct rb_node *rb_next (const struct rb_node *); + +#define rb_entry(ptr, type, member) container_of(ptr, type, member) + +#define RB_EMPTY_ROOT(root1) ((root1)->rb_node == NULL) +#define RB_CLEAR_NODE(node2) (rb_set_parent(node2, node2)) +#define RB_EMPTY_NODE(node1) (rb_parent(node1) == node1) + +static inline void +rb_link_node (struct rb_node *node1, struct rb_node *parent1, + struct rb_node **rb_link1) +{ + node1->rb_left = node1->rb_right = NULL; + node1->rb_parent_color = (unsigned long) parent1; + *rb_link1 = node1; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif /* _UNX_RBTREE_H */ diff --git a/stacks/lwip_stack/lwip_src/common/spl_def.h b/stacks/lwip_stack/lwip_src/common/spl_def.h new file mode 100644 index 0000000..b62d179 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/spl_def.h @@ -0,0 +1,142 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_DEF_H__ +#define __STACKX_DEF_H__ + +/* arch.h might define NULL already */ +//#include "lwip/arch.h" +#include "spl_opt.h" +#include "stackx_types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define STACKX_MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define STACKX_MIN(x, y) (((x) < (y)) ? (x) : (y)) + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define STACKX_MAKE_U16(a, b) ((a << 8) | b) +#else +#define STACKX_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef STACKX_PLATFORM_BYTESWAP +#define STACKX_PLATFORM_BYTESWAP 0 +#endif + +#ifndef STACKX_PREFIX_BYTEORDER_FUNCS + +/* workaround for naming collisions on some platforms */ + +#ifdef spl_htons +#undef spl_htons +#endif /* htons */ +#ifdef spl_htonl +#undef spl_htonl +#endif /* spl_htonl */ +#ifdef spl_ntohs +#undef spl_ntohs +#endif /* spl_ntohs */ +#ifdef spl_ntohl +#undef spl_ntohl +#endif /* spl_ntohl */ + +#define spl_htons(x) stackx_htons(x) +#define spl_ntohs(x) stackx_ntohs(x) +#define spl_htonl(x) stackx_htonl(x) +#define spl_ntohl(x) stackx_ntohl(x) +#endif /* STACKX_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define stackx_htons(x) (x) +#define stackx_ntohs(x) (x) +#define stackx_htonl(x) (x) +#define stackx_ntohl(x) (x) +#define SPL_PP_HTONS(x) (x) +#define SPL_PP_NTOHS(x) (x) +#define SPL_PP_HTONL(x) (x) +#define SPL_PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if STACKX_PLATFORM_BYTESWAP +#define stackx_htons(x) STACKX_PLATFORM_HTONS(x) +#define stackx_ntohs(x) STACKX_PLATFORM_HTONS(x) +#define stackx_htonl(x) STACKX_PLATFORM_HTONL(x) +#define stackx_ntohl(x) STACKX_PLATFORM_HTONL(x) +#else /* STACKX_PLATFORM_BYTESWAP */ + /** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +static inline u16_t +stackx_htons (u16_t x) +{ + return ((x & 0xff) << 8) | ((x & 0xff00) >> 8); +} + +static inline u16_t +stackx_ntohs (u16_t x) +{ + return stackx_htons (x); +} + + /** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +static inline u32_t +stackx_htonl (u32_t x) +{ + return ((x & 0xff) << 24) | + ((x & 0xff00) << 8) | + ((x & 0xff0000UL) >> 8) | ((x & 0xff000000UL) >> 24); +} + +static inline u32_t +stackx_ntohl (u32_t x) +{ + return stackx_htonl (x); +} +#endif /* STACKX_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define SPL_PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define SPL_PP_NTOHS(x) SPL_PP_HTONS(x) +#define SPL_PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define SPL_PP_NTOHL(x) SPL_PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_DEF_H__ */ diff --git a/stacks/lwip_stack/lwip_src/common/spl_opt.h b/stacks/lwip_stack/lwip_src/common/spl_opt.h new file mode 100644 index 0000000..98e6466 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/spl_opt.h @@ -0,0 +1,329 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_OPT_H__ +#define __STACKX_OPT_H__ + +#include "stackxopts.h" +#include "stackx_debug.h" +#include "compiling_check.h" + +#define PBUF_VLAN_HLEN 0 + +//#define SIZEOF_ETH_HDR (14) + +#ifndef STACKX_NETIF_API +#define STACKX_NETIF_API 1 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ + */ + +#define PTIMER_THREAD_NAME "ptimer_thread" + +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "spl_tcpip_thread" +#endif + +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif + +#ifndef INT_64_MAX +#define INT_64_MAX 9223372036854775807 +#endif + +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- + */ + +#ifndef STACKX_DBG_TYPES_ON +#define STACKX_DBG_TYPES_ON STACKX_DBG_ON //ON +#endif + +#ifndef INTERRUPT_DEBUG +#define INTERRUPT_DEBUG STACKX_DBG_ON //ON +#endif + +#ifndef TESTSOCKET_DEBUG +#define TESTSOCKET_DEBUG STACKX_DBG_ON //ON +#endif + +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG STACKX_DBG_ON +#endif + +#ifndef NETIF_DEBUG +#define NETIF_DEBUG STACKX_DBG_ON +#endif + +#ifndef PBUF_DEBUG +#define PBUF_DEBUG STACKX_DBG_ON +#endif + +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG STACKX_DBG_ON +#endif + +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG STACKX_DBG_ON +#endif + +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG STACKX_DBG_ON +#endif + +#ifndef NS_EPOLL_DBG +#define NS_EPOLL_DBG STACKX_DBG_ON +#endif + +#ifndef ICMP_DEBUG +#define ICMP_DEBUG STACKX_DBG_ON +#endif + +#ifndef IGMP_DEBUG +#define IGMP_DEBUG STACKX_DBG_ON +#endif + +#ifndef INET_DEBUG +#define INET_DEBUG STACKX_DBG_ON +#endif + +#ifndef IP_DEBUG +#define IP_DEBUG STACKX_DBG_ON +#endif + +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG STACKX_DBG_ON +#endif + +#ifndef RAW_DEBUG +#define RAW_DEBUG STACKX_DBG_ON +#endif + +#ifndef MEMP_DEBUG +#define MEMP_DEBUG STACKX_DBG_ON +#endif + +#ifndef SYS_DEBUG +#define SYS_DEBUG STACKX_DBG_OFF +#endif + +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_DEBUG +#define TCP_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_TEST_DEBUG +#define TCP_TEST_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_FLOW_CTL_DEBUG +#define TCP_FLOW_CTL_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG STACKX_DBG_ON +#endif + +#ifndef UDP_DEBUG +#define UDP_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG STACKX_DBG_ON +#endif + +#ifndef NEW_RING_DEBUG +#define NEW_RING_DEBUG STACKX_DBG_ON +#endif + +#ifndef PACKET_DISPATCH +#define PACKET_DISPATCH 1 +#endif + +#ifndef NETSTAT_SWITCH +#define NETSTAT_SWITCH 1 +#endif + +#ifndef DISTRIBUTOR_DEBUG + +#define DISTRIBUTOR_DEBUG STACKX_DBG_ON +#endif +#define PBUF_REF_DEBUG STACKX_DBG_ON + +#ifndef CONTEXT_TIMER_DEBUG +#define CONTEXT_TIMER_DEBUG STACKX_DBG_OFF +#endif + +#if (DISTRIBUTOR_DEBUG == STACKX_DBG_ON) +#define PD_DISTRIBUTOR_DEBUG + +#define DISTRIBUTOR_SINGLE +#ifdef DISTRIBUTOR_SINGLE + +#ifndef __STACKX_DEBUG_H__ +#define STACKX_DBG_OFF 0x80U +#define STACKX_DBG_ON 0x00U +#endif + +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG STACKX_DBG_ON +#endif +#ifndef NETIF_DEBUG +#define NETIF_DEBUG STACKX_DBG_ON +#endif +#ifndef PBUF_DEBUG +#define PBUF_DEBUG STACKX_DBG_ON +#endif +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG STACKX_DBG_ON +#endif +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG STACKX_DBG_ON +#endif +#ifndef ICMP_DEBUG +#define ICMP_DEBUG STACKX_DBG_ON +#endif +#ifndef IGMP_DEBUG +#define IGMP_DEBUG STACKX_DBG_ON +#endif +#ifndef INET_DEBUG +#define INET_DEBUG STACKX_DBG_ON +#endif +#ifndef IP_DEBUG +#define IP_DEBUG STACKX_DBG_ON +#endif +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG STACKX_DBG_ON +#endif +#ifndef RAW_DEBUG +#define RAW_DEBUG STACKX_DBG_ON +#endif +#ifndef MEMP_DEBUG +#define MEMP_DEBUG STACKX_DBG_ON +#endif +#ifndef SYS_DEBUG +#define SYS_DEBUG STACKX_DBG_ON +#endif +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_DEBUG +#define TCP_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_TEST_DEBUG +#define TCP_TEST_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG STACKX_DBG_ON +#endif +#ifndef UDP_DEBUG +#define UDP_DEBUG STACKX_DBG_ON +#endif +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG STACKX_DBG_ON +#endif + +#define SC_DPDK_INFO STACKX_DBG_ON +#define SOCK_INFO STACKX_DBG_ON +#ifndef STACKX_DBG_OFF +#define STACKX_DBG_OFF 0x00U +#endif + +#ifndef NS_EPOLL_DBG +#define NS_EPOLL_DBG STACKX_DBG_ON +#endif + +#ifndef DFX_DBG +#define DFX_DBG STACKX_DBG_ON +#endif + +#endif +#endif /* DISTRIBUTOR_DEBUG */ + +#ifndef STACKX_FLOW_CTL +#define STACKX_FLOW_CTL 0 +#endif + +#endif /* __STACKX_OPT_H__ */ diff --git a/stacks/lwip_stack/lwip_src/common/stackx_app_res.c b/stacks/lwip_stack/lwip_src/common/stackx_app_res.c new file mode 100644 index 0000000..5c30271 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_app_res.c @@ -0,0 +1,972 @@ +/* +* +* 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 "stackx_app_res.h" +#include "nstack_securec.h" +#include "common_pal_bitwide_adjust.h" +#include "nstack_log.h" +#include "stackx_common.h" +#include "nsfw_maintain_api.h" +#include "stackx_tx_box.h" +#include "nsfw_msg_api.h" +#include "nsfw_recycle_api.h" +#include "common_mem_mbuf.h" +#include "stackx_pbuf.h" +#include "nsfw_mt_config.h" +#include "nsfw_mem_api.h" +#include "spl_opt.h" +#define SPL_MAX_MSG_NUM (MBOX_RING_SIZE*8*MAX_THREAD_NUM) + +spl_app_res_group *g_spl_app_res_group = NULL; + +spl_app_res_group_array *g_res_group_array = NULL; + +#ifdef SYS_MEM_RES_STAT +mpool_handle g_app_tx_pool[SBR_TX_POOL_NUM]; +#endif + +/*************************************************** +* description: +***************************************************/ +int +spl_init_group_array () +{ + g_res_group_array = + (spl_app_res_group_array *) sbr_create_mzone (SPL_RES_GROUP_ARRAY, + sizeof + (spl_app_res_group_array)); + if (!g_res_group_array) + { + NSPOL_LOGERR ("create g_res_group_array failed"); + return -1; + } + + u32 i; + for (i = 0; i < SBR_TX_POOL_NUM; ++i) + { + g_res_group_array->pid_array[i] = 0; + } + + for (i = 0; i < MAX_THREAD_NUM; ++i) + { + g_res_group_array->res_group[i] = NULL; + } + + g_res_group_array->thread_num = 0; + return 0; +} + +/*************************************************** +* description: +***************************************************/ +int +sbr_attach_group_array () +{ + g_res_group_array = + (spl_app_res_group_array *) sbr_lookup_mzone (SPL_RES_GROUP_ARRAY); + if (!g_res_group_array) + { + NSPOL_LOGERR ("attach g_res_group_array failed"); + return -1; + } + + return 0; +} + +/*************************************************** +* description: +***************************************************/ +int +spl_add_instance_res_group (u32 thread_index, spl_app_res_group * group) +{ + if (thread_index >= MAX_THREAD_NUM) + { + NSPOL_LOGERR + ("thread_index >= MAX_THREAD_NUM]thread_index=%u, MAX_THREAD_NUM=%u", + thread_index, MAX_THREAD_NUM); + return -1; + } + + if (g_res_group_array->res_group[thread_index] != NULL) + { + NSPOL_LOGERR + ("g_res_group_array in thread_index is not NULL, this can not happen"); + return -1; + } + + g_res_group_array->res_group[thread_index] = group; + __sync_add_and_fetch (&g_res_group_array->thread_num, 1); + return 0; +} + +/*************************************************** +* description: +***************************************************/ +int +spl_add_mbox (mring_handle mbox_array[], u32 array_size) +{ + if (array_size != SPL_MSG_BOX_NUM) + { + NSPOL_LOGERR ("array_size must be %u, but not", SPL_MSG_BOX_NUM); + return -1; + } + + u32 i; + for (i = 0; i < array_size; ++i) + { + g_spl_app_res_group->mbox_array[i] = mbox_array[i]; + } + + return 0; +} + +/***************************************************************************** +* Prototype : spl_create_group +* Description : create group +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +spl_app_res_group * +spl_create_group () +{ + spl_app_res_group *group = + (spl_app_res_group *) sbr_create_mzone (SPL_APP_RES_GROUP_NAME, + sizeof (spl_app_res_group)); + if (!group) + { + NSPOL_LOGERR ("Create app_res_group zone fail]name=%s, size=%u", + SPL_APP_RES_GROUP_NAME, sizeof (spl_app_res_group)); + return NULL; + } + + group->msg_pool = NULL; + group->conn_pool = NULL; + group->conn_array = NULL; + group->recv_ring_pool = NULL; + + u32 i; + for (i = 0; i < SBR_TX_POOL_NUM; ++i) + { + group->tx_pool_array[i] = NULL; + } + + for (i = 0; i < SPL_MSG_BOX_NUM; ++i) + { + group->mbox_array[i] = NULL; + } + + group->extend_member_bit = 0; + + NSPOL_LOGINF (SC_DPDK_INFO, "Create app_res_group zone ok]name=%s, size=%u", + SPL_APP_RES_GROUP_NAME, sizeof (spl_app_res_group)); + MEM_STAT (SPL_APP_RES, SPL_APP_RES_GROUP_NAME, NSFW_SHMEM, + sizeof (spl_app_res_group)); + return group; +} + +/***************************************************************************** +* Prototype : _spl_create_ring_pool +* Description : create ring pool +* Input : char* pool_name +* char* array_name +* nsfw_mpool_type type +* Output : None +* Return Value : static inline mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +static inline mring_handle +_spl_create_ring_pool (char *pool_name, char *array_name, + nsfw_mpool_type type, u32 num, u32 ring_size) +{ + mring_handle pool = sbr_create_ring (pool_name, num - 1); + + if (!pool) + { + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "Create ring pool ok]name=%s, num=%u, size=%d", + pool_name, num, nsfw_mem_get_len (pool, NSFW_MEM_RING)); + MEM_STAT (SPL_APP_RES, pool_name, NSFW_SHMEM, + nsfw_mem_get_len (pool, NSFW_MEM_RING)); + + mring_handle *array = malloc (num * sizeof (mring_handle)); + if (!array) + { + NSPOL_LOGERR ("malloc fail]size=%u", num * sizeof (mring_handle)); + return NULL; + } + + if (sbr_create_multi_ring (array_name, ring_size - 1, num, + array, type) != 0) + { + free (array); + return NULL; + } + + NSPOL_LOGINF (SC_DPDK_INFO, + "Create multi rings ok]name=%s, ring_size=%u, ring_num=%u, total_mem=%d", + array_name, ring_size, num, + (nsfw_mem_get_len (array[0], NSFW_MEM_RING) * num)); + MEM_STAT (SPL_APP_RES, array_name, NSFW_SHMEM, + nsfw_mem_get_len (array[0], NSFW_MEM_RING) * num); + + unsigned int i = 0; + while (i < num) + { + if (nsfw_mem_ring_enqueue (pool, (void *) array[i]) != 1) + { + NSPOL_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + free (array); + return NULL; + } + + i++; + } + + free (array); + return pool; +} + +/***************************************************************************** +* Prototype : spl_create_ring_pool +* Description : create ring pool +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +spl_create_ring_pool (spl_app_res_group * group) +{ + group->recv_ring_pool = + _spl_create_ring_pool (SPL_RECV_RING_POOL_NAME, SPL_RECV_RING_ARRAY_NAME, + NSFW_MRING_SPSC, CUR_CFG_SOCKET_NUM, + SPL_MAX_RING_SIZE); + if (!group->recv_ring_pool) + { + NSPOL_LOGERR ("Create recv ring pool failed"); + return -1; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "Create recv ring pool ok]name=%s", + SPL_RECV_RING_POOL_NAME); + return 0; +} + +int +spl_force_netconn_free (void *data) +{ + spl_netconn_t *conn = (spl_netconn_t *) data; + if (TRUE == conn->res_chk.alloc_flag) + { + if (NULL != conn->recycle.accept_from) + { + return FALSE; + } + + if (TRUE != nsfw_pidinfo_empty (&conn->recycle.pid_info)) + { + return FALSE; + } + } + ss_reset_conn (conn); + (void) res_free (&conn->res_chk); + + if (nsfw_mem_ring_enqueue (ss_get_conn_pool (conn), (void *) conn) != 1) + { + NSSBR_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + } + NSFW_LOGINF ("force free conn]conn=%p", conn); + return TRUE; +} + +/***************************************************************************** +* Prototype : spl_create_netconn_pool +* Description : create netconn pool +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +spl_create_netconn_pool (spl_app_res_group * group) +{ + spl_netconn_t **conn_array = + (spl_netconn_t **) sbr_create_mzone (SPL_CONN_ARRAY_NAME, + sizeof (spl_netconn_t *) * + CUR_CFG_SOCKET_NUM); + + if (!conn_array) + { + return -1; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "Create connn_array zone ok]name=%s, size=%zu", + SPL_CONN_ARRAY_NAME, + sizeof (spl_netconn_t *) * CUR_CFG_SOCKET_NUM); + mring_handle pool = + sbr_create_pool (SPL_CONN_POOL_NAME, CUR_CFG_SOCKET_NUM - 1, + SBR_FD_NETCONN_SIZE); + + if (!pool) + { + return -1; + } + + NSPOL_LOGINF (SC_DPDK_INFO, + "Create conn_pool ok]name=%s, num=%u, total_mem=%d", + SPL_CONN_POOL_NAME, CUR_CFG_SOCKET_NUM, + nsfw_mem_get_len (pool, NSFW_MEM_SPOOL)); + + sbr_recycle_group *recycle_group = + (sbr_recycle_group *) sbr_create_mzone (SPL_RECYCLE_GROUP, + sizeof (sbr_recycle_group)); + if (!recycle_group) + { + return -1; + } + + NSPOL_LOGINF (SC_DPDK_INFO, "Create recycle_group zone ok]name=%s, size=%u", + SPL_RECYCLE_GROUP, sizeof (sbr_recycle_group)); + + recycle_group->conn_array = conn_array; + recycle_group->conn_num = spl_get_conn_num (); + recycle_group->conn_pool = pool; + recycle_group->extend_member_bit = 0; + recycle_group->msg_pool = group->msg_pool; + + spl_netconn_t *conn = NULL; + unsigned int i = 0; + while (i < CUR_CFG_SOCKET_NUM) + { + if (nsfw_mem_ring_dequeue (pool, (void **) &conn) != 1) + { + NSPOL_LOGERR ("nsfw_mem_ring_dequeue failed,this can not happen"); + return -1; + } + + ss_reset_conn (conn); + conn->recycle.group = recycle_group; + + if (nsfw_mem_ring_dequeue (group->recv_ring_pool, &conn->recv_ring) != + 1) + { + NSPOL_LOGERR ("nsfw_mem_ring_dequeue failed,this can not happen"); + return -1; + } + + conn_array[i] = conn; + + if (nsfw_mem_ring_enqueue (pool, (void *) conn) != 1) + { + NSPOL_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + return -1; + } + + i++; + } + + group->conn_pool = pool; + group->conn_array = conn_array; + + MEM_STAT (SPL_APP_RES, SPL_RECYCLE_GROUP, NSFW_SHMEM, + sizeof (sbr_recycle_group)); + MEM_STAT (SPL_APP_RES, SPL_CONN_ARRAY_NAME, NSFW_SHMEM, + sizeof (spl_netconn_t *) * CUR_CFG_SOCKET_NUM); + MEM_STAT (SPL_APP_RES, SPL_CONN_POOL_NAME, NSFW_SHMEM, + nsfw_mem_get_len (group->conn_pool, NSFW_MEM_SPOOL)); + return 0; +} + +int +spl_force_msg_free (void *data) +{ + data_com_msg *m = (data_com_msg *) data; + if (NULL == m) + { + return FALSE; + } + + NSFW_LOGINF ("force free msg]msg=%p", data); + (void) res_free (&m->param.res_chk); + m->param.recycle_pid = 0; + if (nsfw_mem_ring_enqueue (m->param.msg_from, (void *) m) != 1) + { + NSFW_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + } + return TRUE; +} + +/***************************************************************************** +* Prototype : spl_create_msg_pool +* Description : create msg pool +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +spl_create_msg_pool (spl_app_res_group * group) +{ + mring_handle pool = + sbr_create_pool (SPL_MSG_POOL_NAME, SPL_MAX_MSG_NUM - 1, MAX_MSG_SIZE); + + if (!pool) + { + return -1; + } + + data_com_msg *m = NULL; + unsigned int i = 0; + while (i < SPL_MAX_MSG_NUM) + { + if (nsfw_mem_ring_dequeue (pool, (void **) &m) != 1) + { + NSPOL_LOGERR ("nsfw_mem_ring_dequeue failed,this can not happen"); + return -1; + } + + m->param.msg_from = pool; + m->param.recycle_pid = 0; + sys_sem_init (&m->param.op_completed); + + if (nsfw_mem_ring_enqueue (pool, (void *) m) != 1) + { + NSPOL_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + return -1; + } + + i++; + } + + group->msg_pool = pool; + + NSPOL_LOGINF (SC_DPDK_INFO, + "Create app msg pool ok]name=%s, num=%u, size=%u, total_mem=%d", + SPL_MSG_POOL_NAME, SPL_MAX_MSG_NUM, MAX_MSG_SIZE, + nsfw_mem_get_len (group->msg_pool, NSFW_MEM_SPOOL)); + MEM_STAT (SPL_APP_RES, SPL_MSG_POOL_NAME, NSFW_SHMEM, + nsfw_mem_get_len (group->msg_pool, NSFW_MEM_SPOOL)); + return 0; +} + +/***************************************************************************** +* Prototype : spl_regist_recycle +* Description : regist recycle +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +spl_regist_recycle (spl_app_res_group * group) +{ + void *ret = + nsfw_recycle_reg_obj (NSFW_REC_PRO_DEFAULT, NSFW_REC_SBR_SOCKET, NULL); + + if (!ret) + { + NSSBR_LOGERR ("failed"); + return -1; + } + + if (NULL == group) + { + NSSBR_LOGERR ("g_spl_app_res_group null"); + return -1; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_SPOOL, 90, 3, 16, + CUR_CFG_SOCKET_NUM / 128, CUR_CFG_SOCKET_NUM - 1, + SBR_FD_NETCONN_SIZE, + offsetof (spl_netconn_t, res_chk), + (void *) group->conn_pool, + (void *) group->conn_pool, + spl_force_netconn_free + }; + + (void) nsfw_res_mgr_reg (&scn_cfg); + + nsfw_res_scn_cfg scn_cfg_msg = { NSFW_RES_SCAN_SPOOL, 60, 3, 16, + SPL_MAX_MSG_NUM / 128, SPL_MAX_MSG_NUM, + MAX_MSG_SIZE, + offsetof (data_com_msg, param.res_chk), + (void *) group->msg_pool, + (void *) group->msg_pool, + spl_force_msg_free + }; + (void) nsfw_res_mgr_reg (&scn_cfg_msg); + + return 0; +} + +void +spl_reg_tx_pool_mgr (mpool_handle pool_array[], u32 num) +{ + u32 loop; + for (loop = 0; loop < num; loop++) + { + (void) spl_reg_res_txrx_mgr (pool_array[loop]); // will only return 0, no need to check return value + } + + return; +} + +/***************************************************************************** +* Prototype : sbr_create_tx_pool +* Description : create tx pool,spl call this fun +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +spl_create_tx_pool (mpool_handle pool_array[], u32 array_size) +{ + data_com_msg *tx_msg_array = + (data_com_msg *) sbr_create_mzone (SBR_TX_MSG_ARRAY_NAME, + (size_t) sizeof (data_com_msg) * + SBR_TX_MSG_NUM); + + if (!tx_msg_array) + { + NSSBR_LOGERR ("Create tx_msg_array zone fail]name=%s, num=%u, size=%u", + SBR_TX_MSG_ARRAY_NAME, SBR_TX_MSG_NUM, + (size_t) sizeof (data_com_msg) * SBR_TX_MSG_NUM); + return -1; + } + + MEM_STAT (SBR_TX_POOL_NAME, SBR_TX_MSG_ARRAY_NAME, NSFW_SHMEM, + (size_t) sizeof (data_com_msg) * SBR_TX_MSG_NUM); + NSSBR_LOGINF + ("Create tx_msg_array zone ok]name=%s, ptr=%p, num=%u, size=%u", + SBR_TX_MSG_ARRAY_NAME, tx_msg_array, SBR_TX_MSG_NUM, + sizeof (data_com_msg) * SBR_TX_MSG_NUM); + + mpool_handle mp; + int ret; + char tx_pool_name[64]; + u32 loop; + for (loop = 0; loop < array_size; loop++) + { + ret = + SPRINTF_S (tx_pool_name, sizeof (tx_pool_name), "%s_%d", + SBR_TX_POOL_NAME, loop); + if (-1 == ret) + { + NSSBR_LOGERR ("SPRINTF_S failed]ret=%d", ret); + return -1; + } + + nsfw_mem_mbfpool pool_param; + if (STRCPY_S + (pool_param.stname.aname, NSFW_MEM_NAME_LENTH, tx_pool_name) != 0) + { + NSSBR_LOGERR ("STRCPY_S failed]name=%s", tx_pool_name); + return -1; + } + + pool_param.isocket_id = -1; + pool_param.stname.entype = NSFW_SHMEM; + pool_param.enmptype = NSFW_MRING_MPMC; + pool_param.uscash_size = 0; + pool_param.uspriv_size = 0; + pool_param.usdata_room = TX_MBUF_MAX_LEN; + pool_param.usnum = SBR_TX_POOL_MBUF_NUM - 1; + + mp = nsfw_mem_mbfmp_create (&pool_param); + if (!mp) + { + NSSBR_LOGERR ("Create tx_mbuf_pool fail]name=%s, num=%u, room=%u", + tx_pool_name, SBR_TX_POOL_MBUF_NUM, + pool_param.usdata_room); + return -1; + } + else + { + struct common_mem_mbuf *mbuf = NULL; + struct spl_pbuf *buf = NULL; + int i = 0; + while (i < (int) SBR_TX_POOL_MBUF_NUM) + { + mbuf = nsfw_mem_mbf_alloc (mp, NSFW_SHMEM); + if (!mbuf) + { + NSSBR_LOGERR + ("nsfw_mem_mbf_alloc failed,this can not happen"); + return -1; + } + + buf = + (struct spl_pbuf *) ((char *) mbuf + + sizeof (struct common_mem_mbuf)); + int idx = loop * (int) SBR_TX_POOL_MBUF_NUM + i; + sys_sem_init (&tx_msg_array[idx].param.op_completed); + tx_msg_array[idx].param.msg_from = NULL; + buf->msg = (void *) &tx_msg_array[idx]; + (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) + { + NSSBR_LOGERR + ("nsfw_mem_mbf_free failed,this can not happen"); + return -1; + } + + i++; + } + + pool_array[loop] = mp; +#ifdef SYS_MEM_RES_STAT + g_app_tx_pool[loop] = mp; +#endif + } + } + + spl_reg_tx_pool_mgr (pool_array, array_size); + + NSSBR_LOGINF ("Create all tx_mbuf_pool ok]pool_num=%d, total_mem=%d", + array_size, nsfw_mem_get_len (pool_array[0], + NSFW_MEM_MBUF) * array_size); + MEM_STAT (SBR_TX_POOL_NAME, SBR_TX_POOL_NAME, NSFW_SHMEM, + nsfw_mem_get_len (pool_array[0], NSFW_MEM_MBUF) * array_size); + return 0; +} + +spl_app_res_group * +spl_create_res_group () +{ + spl_app_res_group *group = spl_create_group (); + if (NULL == group) + { + NSPOL_LOGERR ("spl_create_group failed"); + return NULL; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_group ok"); + + if (spl_create_ring_pool (group) != 0) + { + NSPOL_LOGERR ("spl_create_ring_pool failed"); + return NULL; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_ring_pool ok"); + + if (spl_create_msg_pool (group) != 0) + { + NSPOL_LOGERR ("spl_create_msg_pool failed"); + return NULL; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_msg_pool ok"); + + if (spl_create_netconn_pool (group) != 0) + { + NSPOL_LOGERR ("spl_create_netconn_pool failed"); + return NULL; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_netconn_pool ok"); + + if (spl_regist_recycle (group) != 0) + { + NSPOL_LOGERR ("spl_regist_recycle failed"); + return NULL; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "spl_regist_recycle ok"); + + if (spl_create_tx_pool (group->tx_pool_array, SBR_TX_POOL_NUM) != 0) + { + NSPOL_LOGERR ("spl_create_tx_pool failed"); + return NULL; + } + + NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_tx_pool ok"); + + return group; +} + +/***************************************************************************** +* Prototype : spl_init_app_res +* Description : init app res +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +spl_init_app_res () +{ + g_spl_app_res_group = spl_create_res_group (); + if (NULL == g_spl_app_res_group) + { + NSPOL_LOGERR ("spl_create_group failed"); + return -1; + } + + return spl_add_instance_res_group (0, g_spl_app_res_group); +} + +/***************************************************************************** +* Prototype : spl_get_conn_array +* Description : get conn array +* Input : u32 pid +* Output : None +* Return Value : spl_netconn_t** +* Calls : +* Called By : +* +*****************************************************************************/ +spl_netconn_t ** +spl_get_conn_array (u32 pid) +{ + return (spl_netconn_t **) ADDR_SHTOL (g_spl_app_res_group->conn_array); +} + +/***************************************************************************** +* Prototype : spl_get_conn_pool +* Description : get conn pool +* Input : None +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +spl_get_conn_pool () +{ + return (mring_handle) ADDR_SHTOL (g_spl_app_res_group->conn_pool); +} + +/***************************************************************************** +* Prototype : spl_get_msg_pool +* Description : get msg pool +* Input : None +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +spl_get_msg_pool () +{ + return (mring_handle) ADDR_SHTOL (g_spl_app_res_group->msg_pool); +} + +/***************************************************************************** +* Prototype : spl_recycle_msg +* Description : recycle msg +* Input : void *data +* void* argv +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +spl_recycle_msg (void *data, void *argv) +{ + if (!data) + { + NSPOL_LOGERR ("data is NULL]data=%p,pid=%p", data, argv); + return -1; + } + + data_com_msg *m = (data_com_msg *) data; + u64 pid_64 = (u64) argv; + u32 pid = (u32) pid_64; + if (pid == m->param.recycle_pid) + { + ASYNC_MSG_FREE (m); + } + + return 0; +} + +/***************************************************************************** +* Prototype : spl_recycle_msg_pool +* Description : recycle msg pool +* Input : u32 pid +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +spl_recycle_msg_pool (u32 pid) +{ + mring_handle msg_pool = spl_get_msg_pool (); + if (!msg_pool) + { + NSPOL_LOGERR ("msg_pool is NULL,this can not happen]pid=%u", pid); + return; + } + + u64 pid_64 = pid; + (void) nsfw_mem_sp_iterator (msg_pool, 0, SPL_MAX_MSG_NUM, spl_recycle_msg, + (void *) pid_64); +} + +/***************************************************************************** +* Prototype : spl_get_conn_num +* Description : get conn num +* Input : None +* Output : None +* Return Value : u32 +* Calls : +* Called By : +* +*****************************************************************************/ +u32 +spl_get_conn_num () +{ + return CUR_CFG_SOCKET_NUM; +} + +/*************************************************** +* description: +***************************************************/ +int +sbr_malloc_tx_pool (u32 pid, mpool_handle pool[], u32 pool_num) +{ + int loop; + for (loop = 0; loop < SBR_TX_POOL_NUM; loop++) + { + if ((0 == g_res_group_array->pid_array[loop]) + && + __sync_bool_compare_and_swap (&g_res_group_array->pid_array[loop], + 0, pid)) + { + u32 i; + for (i = 0; i < g_res_group_array->thread_num && i < pool_num; ++i) + { + spl_app_res_group *group = + (spl_app_res_group *) + ADDR_SHTOL (g_res_group_array->res_group[i]); + pool[i] = ADDR_SHTOL (group->tx_pool_array[loop]); + } + + NSSBR_LOGINF ("get tx pool]pid=%d,loop=%d.", pid, loop); + return 0; + } + } + + for (loop = 0; loop < SBR_TX_POOL_NUM; loop++) + { + NSSBR_LOGERR ("no free pool]loop=%d,pid=%d", loop, + g_res_group_array->pid_array[loop]); + } + + return -1; +} + +/*************************************************** +* description: +***************************************************/ +void +spl_free_tx_pool (u32 pid) +{ + int loop; + for (loop = 0; loop < SBR_TX_POOL_NUM; loop++) + { + if (pid == g_res_group_array->pid_array[loop]) + { + u32 i; + for (i = 0; i < g_res_group_array->thread_num; ++i) + { + (void) + nsfw_mem_mbuf_pool_recycle (g_res_group_array->res_group + [i]->tx_pool_array[loop]); + } + + if (!__sync_bool_compare_and_swap + (&g_res_group_array->pid_array[loop], pid, 0)) + { + NSSBR_LOGERR ("free tx_pool failed]loop=%d,pid=%d", loop, pid); + } + else + { + NSSBR_LOGDBG ("free tx_pool ok]loop=%d,pid=%d", loop, pid); + } + + break; + } + } +} + +/*************************************************** +* description: +***************************************************/ +mring_handle +sbr_get_instance_conn_pool (u32 thread_index) +{ + if (thread_index >= g_res_group_array->thread_num) + { + return NULL; + } + + spl_app_res_group *group = + (spl_app_res_group *) + ADDR_SHTOL (g_res_group_array->res_group[thread_index]); + return ADDR_SHTOL (group->conn_pool); +} + +/*************************************************** +* description: +***************************************************/ +mring_handle * +ss_get_instance_msg_box (u16 thread_index, u16 idx) +{ + if (thread_index >= g_res_group_array->thread_num) + { + thread_index = 0; + } + + if (idx >= SPL_MSG_BOX_NUM) + { + idx = 0; + } + + spl_app_res_group *group = + (spl_app_res_group *) + ADDR_SHTOL (g_res_group_array->res_group[thread_index]); + return ADDR_SHTOL (group->mbox_array[idx]); +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_app_res.h b/stacks/lwip_stack/lwip_src/common/stackx_app_res.h new file mode 100644 index 0000000..435f2f6 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_app_res.h @@ -0,0 +1,103 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_APP_RES_H +#define STACKX_APP_RES_H +#include "types.h" +#include "nsfw_mem_api.h" +#include "stackxopts.h" +#include "stackx_spl_share.h" +#include "nsfw_mt_config.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SPL_RES_GROUP_ARRAY "spl_res_group_array" + +#define SPL_APP_RES "spl_app_res" +#define SPL_APP_RES_GROUP_NAME "spl_app_res_group" +#define SPL_TX_POOL_NAME "spl_tx_pool" +#define SPL_CONN_POOL_NAME "spl_conn_pool" +#define SPL_CONN_ARRAY_NAME "spl_conn_array" +#define SPL_DFX_ARRAY_NAME "spl_dfx_array" +#define SPL_MSG_POOL_NAME "spl_msg_pool" +#define SPL_RECYCLE_GROUP "spl_recycle_group" +#define SPL_RECV_RING_POOL_NAME "spl_recv_ring_pool" +#define SPL_RECV_RING_ARRAY_NAME "spl_recv_array" + +#define SBR_TX_POOL_NUM APP_POOL_NUM +#define SBR_TX_POOL_MBUF_NUM TX_MBUF_POOL_SIZE +#define SBR_TX_MSG_NUM (SBR_TX_POOL_NUM * SBR_TX_POOL_MBUF_NUM) + +#define SBR_TX_POOL_ARRAY_NAME "sbr_tx_pool_array" +#define SBR_TX_POOL_NAME "sbr_tx_pool" +#define SBR_TX_MSG_ARRAY_NAME "sbr_tx_msg_array" + +#define SPL_MAX_MSG_NUM (MBOX_RING_SIZE*8*MAX_THREAD_NUM) + +typedef struct +{ + PRIMARY_ADDR mring_handle msg_pool; + PRIMARY_ADDR mring_handle conn_pool; + PRIMARY_ADDR spl_netconn_t **conn_array; + PRIMARY_ADDR mring_handle recv_ring_pool; + PRIMARY_ADDR mpool_handle tx_pool_array[SBR_TX_POOL_NUM]; + PRIMARY_ADDR mring_handle mbox_array[SPL_MSG_BOX_NUM]; + i64 extend_member_bit; +} spl_app_res_group; + +typedef struct +{ + u32 pid_array[SBR_TX_POOL_NUM]; + PRIMARY_ADDR spl_app_res_group *res_group[MAX_THREAD_NUM]; + u16 thread_num; +} spl_app_res_group_array; + +extern spl_app_res_group *g_spl_app_res_group; +extern spl_app_res_group_array *g_res_group_array; + +/* call it main thread */ +int spl_init_group_array (); + +/* call these in tcpip thread */ +int spl_init_app_res (); +spl_netconn_t **spl_get_conn_array (u32 pid); +mring_handle spl_get_conn_pool (); +mring_handle spl_get_msg_pool (); +void spl_recycle_msg_pool (u32 pid); +u32 spl_get_conn_num (); +void spl_free_tx_pool (u32 pid); +int spl_add_mbox (mring_handle mbox_array[], u32 array_size); +int spl_add_instance_res_group (u32 thread_index, spl_app_res_group * group); + +/* call these in app */ +int sbr_malloc_tx_pool (u32 pid, mpool_handle pool[], u32 pool_num); +int sbr_attach_group_array (); +mring_handle sbr_get_instance_conn_pool (u32 thread_index); + +/* call these in app and spl */ +mring_handle *ss_get_instance_msg_box (u16 thread_index, u16 index); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common.c b/stacks/lwip_stack/lwip_src/common/stackx_common.c new file mode 100644 index 0000000..750df74 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_common.c @@ -0,0 +1,357 @@ +/* +* +* 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 <stdarg.h> +#include <stddef.h> +#include "stackx_common.h" +#include "nstack_securec.h" +#include "nstack_log.h" +#include "types.h" +#include "stackx_types.h" + +int +spl_snprintf (char *buffer, int buflen, const char *format, ...) +{ + int len; + va_list ap; + + if ((NULL == buffer) || (0 >= buflen)) + { + return -1; + } + + if (format == NULL) + { + buffer[0] = '\0'; + return -1; + } + + (void) va_start (ap, format); + len = VSNPRINTF_S (buffer, buflen, buflen - 1, format, ap); + if (-1 == len) + { + va_end (ap); + return -1; + } + + va_end (ap); + if ((len >= buflen) && (buflen > 0) && (buffer != NULL)) + { + buffer[buflen - 1] = '\0'; + } + + return len; +} + +/***************************************************************************** +* Prototype : sbr_create_mzone +* Description : create mzone +* Input : const char* name +* size_t size +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle +sbr_create_mzone (const char *name, size_t size) +{ + if (!name) + { + NSFW_LOGERR ("name is NULL"); + return NULL; + } + + mzone_handle zone; + nsfw_mem_zone param; + + param.isocket_id = -1; + param.length = size; + param.stname.entype = NSFW_SHMEM; + + if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR ("STRCPY_S failed]name=%s", name); + return NULL; + } + + zone = nsfw_mem_zone_create (¶m); + if (!zone) + { + NSFW_LOGERR ("nsfw_mem_zone_create failed]name=%s, size:%zu", name, + size); + return NULL; + } + + return zone; +} + +/***************************************************************************** +* Prototype : sbr_lookup_mzone +* Description : lookup mzone +* Input : const char* name +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle +sbr_lookup_mzone (const char *name) +{ + if (!name) + { + NSFW_LOGERR ("name is NULL"); + return NULL; + } + + mzone_handle zone; + nsfw_mem_name param; + + param.entype = NSFW_SHMEM; + param.enowner = NSFW_PROC_MAIN; + if (STRCPY_S (param.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR ("STRCPY_S failed]name=%s", name); + return NULL; + } + + zone = nsfw_mem_zone_lookup (¶m); + if (!zone) + { + NSFW_LOGERR ("nsfw_mem_zone_lookup failed]name=%s", name); + return NULL; + } + + return zone; +} + +/***************************************************************************** +* Prototype : sbr_create_pool +* Description : create pool +* Input : const char* name +* i32 num +* u16 size +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +sbr_create_pool (const char *name, i32 num, u16 size) +{ + if (!name) + { + NSFW_LOGERR ("name is NULL"); + return NULL; + } + + nsfw_mem_sppool param; + if (EOK != MEMSET_S (¶m, sizeof (param), 0, sizeof (param))) + { + NSFW_LOGERR ("memset error]name=%s", name); + return NULL; + } + + param.enmptype = NSFW_MRING_MPMC; + param.useltsize = size; + param.usnum = num; + param.stname.entype = NSFW_SHMEM; + param.isocket_id = -1; + if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR ("STRCPY_S failed]name=%s", name); + return NULL; + } + + mring_handle ring = nsfw_mem_sp_create (¶m); + if (!ring) + { + NSFW_LOGERR ("Create pool failed]name=%s, num=%d, size=%u", name, num, + size); + } + + return ring; +} + +/***************************************************************************** +* Prototype : sbr_create_ring +* Description : create ring +* Input : const char* name +* i32 num +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +sbr_create_ring (const char *name, i32 num) +{ + if (!name) + { + NSFW_LOGERR ("name is NULL"); + return NULL; + } + + nsfw_mem_mring param; + if (EOK != MEMSET_S (¶m, sizeof (param), 0, sizeof (param))) + { + NSFW_LOGERR ("memset error]name=%s", name); + return NULL; + } + + param.enmptype = NSFW_MRING_MPMC; + param.isocket_id = -1; + param.usnum = num; + param.stname.entype = NSFW_SHMEM; + + if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR ("STRCPY_S failed]name=%s", name); + return NULL; + } + + mring_handle ring = nsfw_mem_ring_create (¶m); + if (!ring) + { + NSFW_LOGERR ("Create ring failed]name=%s, num=%d", name, num); + } + + return ring; +} + +/***************************************************************************** +* Prototype : sbr_create_multi_ring +* Description : create multi ring +* Input : const char* name +* u32 ring_size +* i32 ring_num +* mring_handle* array +* nsfw_mpool_type type +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_create_multi_ring (const char *name, u32 ring_size, i32 ring_num, + mring_handle * array, nsfw_mpool_type type) +{ + if (!name) + { + NSFW_LOGERR ("name is NULL"); + return -1; + } + + if (!array) + { + NSFW_LOGERR ("array is NULL"); + return -1; + } + + nsfw_mem_mring param; + + if (EOK != MEMSET_S (¶m, sizeof (param), 0, sizeof (param))) + { + NSSBR_LOGERR ("Error to memset]name=%s", name); + return -1; + } + + param.enmptype = type; + param.stname.entype = NSFW_SHMEM; + if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSSBR_LOGERR ("STRCPY_S failed]name=%s", name); + return -1; + } + + param.usnum = ring_size; + param.isocket_id = -1; + if (nsfw_mem_sp_ring_create (¶m, array, ring_num) != 0) + { + NSSBR_LOGERR ("Create ring pool failed]name=%s, ring_num=%d", name, + ring_num); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_lookup_ring +* Description : lookup ring +* Input : const char* name +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +sbr_lookup_ring (const char *name) +{ + nsfw_mem_name param; + + param.entype = NSFW_SHMEM; + param.enowner = NSFW_PROC_MAIN; + if (STRCPY_S (param.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR ("STRCPY_S failed]name=%s", name); + return NULL; + } + + mring_handle ring = nsfw_mem_ring_lookup (¶m); + if (!ring) + { + NSFW_LOGERR ("lookup ring failed]name=%s", name); + } + + return ring; +} + +int +sbr_timeval2msec (struct timeval *pTime, u64 * msec) +{ + if ((pTime->tv_sec < 0) || (pTime->tv_usec < 0)) + { + NSFW_LOGERR ("time->tv_sec is nagative"); + return -1; + } + + if (STACKX_MAX_U64_NUM / 1000 < (u64_t) pTime->tv_sec) + { + NSFW_LOGERR ("tout.tv_sec is too large]tout.tv_sec=%lu", pTime->tv_sec); + return -1; + } + + u64 sec2msec = 1000 * pTime->tv_sec; + u64 usec2msec = pTime->tv_usec / 1000; + + if (STACKX_MAX_U64_NUM - sec2msec < usec2msec) + { + NSFW_LOGERR + ("nsec2msec plus sec2usec is too large]usec2msec=%lu,usec2msec=%lu", + usec2msec, sec2msec); + return -1; + } + + *msec = sec2msec + usec2msec; + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common.h b/stacks/lwip_stack/lwip_src/common/stackx_common.h new file mode 100644 index 0000000..1df97d5 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_common.h @@ -0,0 +1,44 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_COMMON_H +#define STACKX_COMMON_H +#include "nsfw_mem_api.h" +//#include "lwip/cc.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +int spl_snprintf (char *buffer, int buflen, const char *format, ...); +mzone_handle sbr_create_mzone (const char *name, size_t size); +mzone_handle sbr_lookup_mzone (const char *name); +mring_handle sbr_create_pool (const char *name, i32 num, u16 size); +mring_handle sbr_create_ring (const char *name, i32 num); +int sbr_create_multi_ring (const char *name, u32 ring_size, i32 ring_num, + mring_handle * array, nsfw_mpool_type type); +mring_handle sbr_lookup_ring (const char *name); +int sbr_timeval2msec (struct timeval *pTime, u64 * msec); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h b/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h new file mode 100644 index 0000000..d2d01e5 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h @@ -0,0 +1,146 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_COMMON_OPT_H +#define STACKX_COMMON_OPT_H +#include <sys/ioctl.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef O_NONBLOCK +#define O_NONBLOCK 0X800 /* nonblocking I/O */ +#endif + +#if !defined (FIONREAD) || !defined (FIONBIO) +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */ +#define _IO(x, y) (((x) << 8) | (y) | IOC_VOID) +#define _IOR(x, y, t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#define _IOW(x, y, t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#endif + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) +#endif + +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) +#endif + +#ifndef F_GETFL +#define F_GETFL 3 +#endif + +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +#ifndef SPL_SHUT_RD +#define SPL_SHUT_RD 0 +#define SPL_SHUT_WR 1 +#define SPL_SHUT_RDWR 2 +#endif + +/* Flags for struct netconn.flags (u8_t) */ + +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define SPL_NETCONN_FLAG_WRITE_DELAYED 0x01 + +/** Should this netconn avoid blocking? */ +#define SPL_NETCONN_FLAG_NON_BLOCKING 0x02 + +/** Was the last connect action a non-blocking one? */ +#define SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 + +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define SPL_NETCONN_FLAG_NO_AUTO_RECVED 0x08 + +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define SPL_NETCONN_FLAG_CHECK_WRITESPACE 0x10 + +/* For the netconn API, these values are use as a bitmask! */ +#define SPL_NETCONN_SHUT_RD 1 +#define SPL_NETCONN_SHUT_WR 2 +#define SPL_NETCONN_SHUT_RDWR (SPL_NETCONN_SHUT_RD | SPL_NETCONN_SHUT_WR) +#define STACKX_TIMER_THREAD_SUPPORT 1 + +/* Flags for netconn_write (u8_t) */ +#define SPL_NETCONN_NOFLAG 0x00 +#define SPL_NETCONN_NOCOPY 0x00 +#define SPL_NETCONN_COPY 0x01 +#define SPL_NETCONN_MORE 0x02 +#define SPL_NETCONN_DONTBLOCK 0x04 + +#define SPL_TCP_NODELAY 0x01 +#define SPL_TCP_KEEPALIVE 0x02 +#define SPL_TCP_KEEPIDLE 0x04 +#define SPL_TCP_KEEPINTVL 0x05 +#define SPL_TCP_KEEPCNT 0x06 +#define SPL_TCP_LINGER2 0x08 +#define SPL_TCP_DEFER_ACCEPT 0x09 + +typedef enum spl_netconn_type +{ + SPL_NETCONN_INVALID = 0, + SPL_NETCONN_TCP = 0x10, + SPL_NETCONN_UDP = 0x20, + SPL_NETCONN_UDPLITE = 0x21, + SPL_NETCONN_UDPNOCHKSUM = 0x22, + SPL_NETCONN_RAW = 0x40, +} spl_netconn_type_t; + +typedef enum spl_netconn_state +{ + SPL_NETCONN_NONE, + SPL_NETCONN_WRITE, + SPL_NETCONN_LISTEN, + SPL_NETCONN_CONNECT, + SPL_NETCONN_CLOSE, +} spl_netconn_state_t; + +typedef enum spl_tcp_state +{ + SPL_CLOSED = 0, + SPL_LISTEN = 1, + SPL_SYN_SENT = 2, + SPL_SYN_RCVD = 3, + SPL_ESTABLISHED = 4, + SPL_FIN_WAIT_1 = 5, + SPL_FIN_WAIT_2 = 6, + SPL_CLOSE_WAIT = 7, + SPL_CLOSING = 8, + SPL_LAST_ACK = 9, + SPL_TIME_WAIT = 10 +} spl_tcp_state_t; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_debug.h b/stacks/lwip_stack/lwip_src/common/stackx_debug.h new file mode 100644 index 0000000..7c6395e --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_debug.h @@ -0,0 +1,70 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_DEBUG_H__ +#define __STACKX_DEBUG_H__ + +//#include "lwip/arch.h" +#include <pthread.h> + +#include <sys/syscall.h> + +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** lower two bits indicate dbug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define STACKX_DBG_LEVEL_ALL 0x00 +#define STACKX_DBG_LEVEL_OFF STACKX_DBG_LEVEL_ALL /* compatibility define only */ +#define STACKX_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define STACKX_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define STACKX_DBG_LEVEL_SEVERE 0x03 +#define STACKX_DBG_MASK_LEVEL 0x00 + +/** flag to enable that dbug message */ +#define STACKX_DBG_ON NS_LOG_STACKX_ON + +/** flag to disable that dbug message */ +#define STACKX_DBG_OFF NS_LOG_STACKX_OFF + +/** flag for indicating a tracing_message (to follow program flow) */ +#define STACKX_DBG_TRACE NS_LOG_STACKX_TRACE + +/** flag for indicating a state dbug message (to follow module states) */ +#define STACKX_DBG_STATE NS_LOG_STACKX_STATE + +/** flag for indicating newly added code, not thoroughly tested yet */ +#define STACKX_DBG_FRESH NS_LOG_STACKX_FRESH + +/** flag for to halt after printing this dbug message */ +#define STACKX_DBG_HALT NS_LOG_STACKX_HALT + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_DEBUG_H__ */ diff --git a/stacks/lwip_stack/lwip_src/common/stackx_err.h b/stacks/lwip_stack/lwip_src/common/stackx_err.h new file mode 100644 index 0000000..1d0fc20 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_err.h @@ -0,0 +1,68 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_ERR_H +#define STACKX_ERR_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ + +#define SPL_ERR_IS_FATAL(e) ((e) < ERR_ISCONN) + +#define ERR_ABRT -10 /* Connection aborted. */ +#define ERR_RST -11 /* Connection reset. */ +#define ERR_CLSD -12 /* Connection closed. */ +#define ERR_CONN -13 /* Not connected. */ + +#define ERR_ARG -14 /* Illegal argument. */ + +#define ERR_IF -15 /* Low-level netif error */ +#define ERR_ALREADY -16 /* previous connect attemt has not yet completed */ +#define ERR_PROTOTYPE -17 /* prototype error or some other generic error. + the operation is not allowed on current socket */ + +#define ERR_CALLBACK -18 /* callback error */ +#define ERR_CANTASSIGNADDR -19 /* Cannot assign requested address */ +#define ERR_CONTAINER_ID -20 /*Illegal container id */ +#define ERR_NOTSOCK -21 /*not a socket */ + +#define ERR_CLOSE_WAIT -22 /*closed in established state */ + +#define ERR_EPROTONOSUPPORT -23 /* Protocol not supported */ + +#define ERR_FAULTRECOVERY -24 /*SPL just recovered from a fatal fault */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c new file mode 100644 index 0000000..306bcaf --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c @@ -0,0 +1,280 @@ +/* +* +* 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 <stdint.h> +#include <stddef.h> +#include "stackx_ip_addr.h" +#include "nstack_log.h" +#include "spl_def.h" + +/* Here for now until needed in other places in stackx*/ +#ifndef isprint +#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IPaddress in ascii represenation (e.g. "127.0.0.1") + * @return ipaddress in network order + */ +u32 +spl_ipaddr_addr (const char *cp) +{ + spl_ip_addr_t val; + + if (spl_ipaddr_aton (cp, &val)) + { + return ip4_addr_get_u32 (&val); + } + + return (SPL_IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broad cast address. + * + * @param cp IPaddress in ascii represenation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ipaddress in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +spl_ipaddr_aton (const char *cp, spl_ip_addr_t * addr) +{ + u32 val; + u8 base; + char c; + u32 parts[4]; + u32 *pp = parts; + + if (cp == NULL) + { + return 0; + } + + c = *cp; + for (;;) + { + /* + * Get number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit (c)) + { + return (0); + } + + val = 0; + base = 10; + if (c == '0') + { + c = *++cp; + if ((c == 'x') || (c == 'X')) + { + base = 16; + c = *++cp; + } + else + { + base = 8; + } + } + + for (;;) + { + if (isdigit (c)) + { + val = (val * base) + (int) (c - '0'); + c = *++cp; + } + else if ((base == 16) && isxdigit (c)) + { + val = (val << 4) | (int) (c + 10 - (islower (c) ? 'a' : 'A')); + c = *++cp; + } + else + { + break; + } + } + + if (c == '.') + { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + { + return (0); + } + + *pp++ = val; + c = *++cp; + } + else + { + break; + } + } + + /* + * Check for trailing characters. + */ + if ((c != '\0') && !isspace (c)) + { + return (0); + } + + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) + { + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) + { + return (0); + } + + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + { + return (0); + } + + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + { + return (0); + } + + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + NSPOL_LOGERR ("unhandled"); + + return (0); + } + + if (addr) + { + ip4_addr_set_u32 (addr, spl_htonl (val)); + } + + return (1); +} + +/** + * Convert numeric IPaddress into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ipaddress in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char * +spl_ipaddr_ntoa (const spl_ip_addr_t * addr) +{ + static char str[16]; + + return spl_ipaddr_ntoa_r (addr, str, 16); +} + +/** + * Same as spl_ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ipaddress in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +spl_ipaddr_ntoa_r (const spl_ip_addr_t * addr, char *buf, int buflen) +{ + u32 s_addr; + char inv[3]; + char *rp; + u8 *ap; + u8 rem; + u8 n; + u8 i; + int len = 0; + + s_addr = ip4_addr_get_u32 (addr); + + rp = buf; + ap = (u8 *) & s_addr; + for (n = 0; n < 4; n++) + { + i = 0; + do + { + rem = *ap % (u8) 10; + *ap /= (u8) 10; + inv[i++] = '0' + rem; + } + while (*ap); + + while (i--) + { + if (len++ >= buflen) + { + return NULL; + } + + *rp++ = inv[i]; + } + + if (len++ >= buflen) + { + return NULL; + } + + *rp++ = '.'; + ap++; + } + + *--rp = 0; + return buf; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h new file mode 100644 index 0000000..9f2dc07 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h @@ -0,0 +1,82 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_IP_ADDR_H +#define STACKX_IP_ADDR_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +typedef struct spl_ip_addr +{ + u32 addr; +} spl_ip_addr_t; + +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) + +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) + +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define SPL_IPADDR_NONE ((u32)0xffffffffUL) + +/** Set address to IPADDR_ANY (no need for spl_htonl()) */ +#define spl_ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) + +/** Set complete address to zero */ +#define spl_ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) + +/** IPv4 only: set the IPaddress given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) + +/** IPv4 only: get the IPaddress as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) + +/** For backwards compatibility */ +#define spl_ip_ntoa(ipaddr) spl_ipaddr_ntoa(ipaddr) + +u32 spl_ipaddr_addr (const char *cp); +int spl_ipaddr_aton (const char *cp, spl_ip_addr_t * addr); + +/** returns ptr to static buffer; not reentrant! */ +char *spl_ipaddr_ntoa (const spl_ip_addr_t * addr); +char *spl_ipaddr_ntoa_r (const spl_ip_addr_t * addr, char *buf, int buflen); + +#define spl_inet_addr(cp) spl_ipaddr_addr(cp) +#define spl_inet_aton(cp, paddr) spl_ipaddr_aton(cp, (spl_ip_addr_t*)(paddr)) +#define spl_inet_ntoa(paddr) spl_ipaddr_ntoa((spl_ip_addr_t*)&(paddr)) +#define spl_inet_ntoa_r(addr, buf, buflen) spl_ipaddr_ntoa_r((spl_ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h b/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h new file mode 100644 index 0000000..6ca2598 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h @@ -0,0 +1,146 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_IP_TOS_H +#define STACKX_IP_TOS_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_LOWCOST 0x02 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_MINCOST IPTOS_LOWCOST +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_ROUTINE 0x00 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) + +#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3) + +#define TC_PRIO_BESTEFFORT 0 +#define TC_PRIO_FILLER 1 +#define TC_PRIO_BULK 2 +#define TC_PRIO_INTERACTIVE_BULK 4 +#define TC_PRIO_INTERACTIVE 6 +#define TC_PRIO_CONTROL 7 +#define TC_PRIO_MAX 15 + +#define ECN_OR_COST(class ) TC_PRIO_ ## class + +static u8 stackx_ip_tos2prio[(IPTOS_TOS_MASK >> 1) + 1] = { + TC_PRIO_BESTEFFORT, + ECN_OR_COST (FILLER), + TC_PRIO_BESTEFFORT, + ECN_OR_COST (BESTEFFORT), + TC_PRIO_BULK, + ECN_OR_COST (BULK), + TC_PRIO_BULK, + ECN_OR_COST (BULK), + TC_PRIO_INTERACTIVE, + ECN_OR_COST (INTERACTIVE), + TC_PRIO_INTERACTIVE, + ECN_OR_COST (INTERACTIVE), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST (INTERACTIVE_BULK), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST (INTERACTIVE_BULK) +}; + +static inline char +stackx_rt_tos2priority (u8 tos) +{ + return stackx_ip_tos2prio[IPTOS_TOS (tos) >> 1]; +} + +typedef enum +{ + STACKX_PRIM, + STACKX_HIGH, + STACKX_MEDIUM, + STACKX_LOW +} stackx_prio; + +static inline stackx_prio +stackx_get_prio (u8 tos) +{ + if (0 == tos) + { + return STACKX_PRIM; + } + char prio = stackx_rt_tos2priority (tos); + if ((TC_PRIO_INTERACTIVE == prio)) + { + return STACKX_HIGH; + } + else if ((TC_PRIO_BESTEFFORT == prio) || (TC_PRIO_INTERACTIVE_BULK == prio)) + { + return STACKX_MEDIUM; + } + else if ((TC_PRIO_BULK == prio) || (TC_PRIO_FILLER == prio)) + { + return STACKX_LOW; + } + + return STACKX_PRIM; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h b/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h new file mode 100644 index 0000000..a8be1a7 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h @@ -0,0 +1,43 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_NETBUF_H +#define STACKX_NETBUF_H +#include "stackx_pbuf.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct spl_netbuf +{ + struct spl_pbuf *p; + spl_ip_addr_t addr; + u16 port; +} spl_netbuf; + +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_fromport(buf) ((buf)->port) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c new file mode 100644 index 0000000..c176a4b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c @@ -0,0 +1,223 @@ +/* +* +* 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 "stackx_spl_share.h" +#include "stackx_pbuf.h" +#include "common_mem_mbuf.h" +#include "nstack_securec.h" +#include "nsfw_maintain_api.h" +#include "stackx_tcp_opt.h" +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif + +/***************************************************************************** +* Prototype : sbr_malloc_pbuf +* Description : malloc spl_pbuf,use it in app +* Input : mpool_handle mp +* u16 len +* u32 mbuf_data_size +* u16 offset +* Output : None +* Return Value : struct pbuf* +* Calls : +* Called By : +* +*****************************************************************************/ +struct spl_pbuf * +sbr_malloc_pbuf (mpool_handle mp, u16 len, u32 mbuf_data_size, u16 offset) +{ + if ((len < offset) || (len > mbuf_data_size)) + { + NSSBR_LOGERR ("len is invalid]len=%u", len); + return NULL; + } + + struct common_mem_mbuf *mbuf = NULL; + struct spl_pbuf *buf = NULL; + + mbuf = nsfw_mem_mbf_alloc (mp, NSFW_SHMEM); + if (unlikely (mbuf == NULL)) + { + NS_LOG_CTRL (LOG_CTRL_HUGEPAGE_ALLOC_FAIL, LOGSBR, "NSSBR", NSLOG_WAR, + "alloc mbuf failed"); + return NULL; + } + + mbuf->data_len = len; + mbuf->next = NULL; + mbuf->nb_segs = 1; + mbuf->pkt_len = len; + buf = (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf)); + res_alloc (&buf->res_chk); + buf->next = 0; + void *tmp = common_pktmbuf_mtod (mbuf, void *); + buf->payload = (void *) (ADDR_LTOSH (tmp) + offset); + buf->tot_len = len - offset; + buf->len = len - offset; + buf->type = SPL_PBUF_HUGE; + buf->flags = 0; + buf->freeNext = NULL; + buf->conn_a = 0; + buf->proto_type = SPL_PBUF_PROTO_NONE; + NSSBR_LOGDBG ("malloc pbuf ok]buf=%p,PRIMARY_ADDR=%p", buf, + ADDR_LTOSH (buf)); + return buf; +} + +u32_t +spl_pbuf_copy_partial (struct spl_pbuf * buf, void *dataptr, u32_t len, + u32_t offset) +{ + struct spl_pbuf *p = buf; + u32_t buf_copy_len; + u32_t copied_total = 0; + char *databuf = (char *) dataptr; + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; len != 0 && p != NULL; + p = PTR_SHTOL (struct spl_pbuf *, p->next_a)) + { + if (offset != 0 && offset >= p->len) + { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } + else if (p->len - offset > len) + { + /* copy from this buffer. maybe only partially. */ + (void) common_memcpy (databuf, ADDR_SHTOL (p->payload_a + offset), + len); + copied_total += len; + break; + } + else + { + buf_copy_len = p->len - offset; + /* copy the necessary parts of the buffer */ + (void) common_memcpy (databuf, ADDR_SHTOL (p->payload_a + offset), + buf_copy_len); + + copied_total += buf_copy_len; + databuf += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + + return copied_total; +} + +int +spl_tx_force_buf_free (void *data) +{ + struct common_mem_mbuf *mbuf = data; + if (NULL == mbuf) + { + return FALSE; + } + + struct spl_pbuf *p_buf = + (struct spl_pbuf *) (((char *) mbuf) + sizeof (struct common_mem_mbuf)); + u8 tempflag = p_buf->res_chk.u8Reserve; + if ((mbuf->refcnt == 0) || (tempflag & DPDK_SEND_FLAG)) + { + return FALSE; + } + + NSFW_LOGINF ("free mbuf]%p", data); + (void) nsfw_mem_mbf_free ((mbuf_handle) mbuf, NSFW_SHMEM); + return TRUE; +} + +int +spl_force_buf_free (void *data) +{ + struct common_mem_mbuf *mbuf = data; + + if (NULL == mbuf || (mbuf->refcnt == 0)) + { + return FALSE; + } + + NSFW_LOGINF ("free mbuf]%p", data); + (void) nsfw_mem_mbf_free ((mbuf_handle) mbuf, NSFW_SHMEM); + return TRUE; +} + +int +spl_reg_res_tx_mgr (mpool_handle * pool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) pool; + if (NULL == mp) + { + return 0; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16, + mp->size / 128, mp->size, + mp->elt_size, + sizeof (struct common_mem_mbuf) + offsetof (struct spl_pbuf, res_chk), + mp, + mp->pool_data, + spl_tx_force_buf_free + }; + (void) nsfw_res_mgr_reg (&scn_cfg); + return 0; +} + +int +spl_reg_res_rxmt_mgr (mpool_handle * pool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) pool; + if (NULL == mp) + { + return 0; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16, + mp->size / 128, mp->size, + mp->elt_size, + sizeof (struct common_mem_mbuf) + offsetof (struct spl_pbuf, res_chk), + mp, + mp->pool_data, + spl_tx_force_buf_free + }; /*Can use same function for time */ + (void) nsfw_res_mgr_reg (&scn_cfg); + return 0; +} + +int +spl_reg_res_txrx_mgr (mpool_handle * pool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) pool; + if (NULL == mp) + { + return 0; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16, + mp->size / 128, mp->size, + mp->elt_size, + sizeof (struct common_mem_mbuf) + offsetof (struct spl_pbuf, res_chk), + mp, + mp->pool_data, + spl_force_buf_free + }; + (void) nsfw_res_mgr_reg (&scn_cfg); + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h new file mode 100644 index 0000000..60f1772 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h @@ -0,0 +1,82 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_PBUF_H +#define STACKX_PBUF_H + +#include "common_mem_base_type.h" +#include "common_mem_mbuf.h" +#include "nsfw_mem_api.h" +#include "stackx_pbuf_comm.h" +#ifdef HAL_LIB +#else +#include "common_pal_bitwide_adjust.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NEED_ACK_FLAG 0x01 /* This spl_pbuf may have multiple references. */ +#define PBUF_FREE_FLAG 0x04 /* This spl_pbuf has been free. */ +#define DPDK_SEND_FLAG 0x10 /* This spl_pbuf has been sent to DPDK. */ +#define LOOP_SEND_FLAG 0x40 /* This spl_pbuf has been looped to IP layer and not received by app layer yet. */ + +struct spl_pbuf *sbr_malloc_pbuf (mpool_handle mp, u16 len, + u32 mbuf_data_size, u16 offset); +void sbr_free_pbuf (struct spl_pbuf *p); +u32 spl_pbuf_copy_partial (struct spl_pbuf *p, void *dataptr, u32_t len, + u32_t offset); +int spl_reg_res_txrx_mgr (mpool_handle * pool); +int spl_reg_res_tx_mgr (mpool_handle * pool); + +/* release buf hold by app on abnormal exit */ +/* + *For TX mbuf: recycle_flg can be: MBUF_UNUSED, MBUF_HLD_BY_APP, MBUF_HLD_BY_SPL. + *For TX mbuf: recycle_flg can be: MBUF_UNSUED, app pid. + */ +static inline void +pbuf_set_recycle_flg (struct spl_pbuf *p, uint32_t flg) +{ + uint32_t *recycle_flg; + struct spl_pbuf *q = p; + struct common_mem_mbuf *m; + + while (q != NULL) + { + m = + (struct common_mem_mbuf *) ((char *) q - + sizeof (struct common_mem_mbuf)); +#ifdef HAL_LIB +#else + recycle_flg = + (uint32_t *) ((char *) (m->buf_addr) + RTE_PKTMBUF_HEADROOM - + sizeof (uint32_t)); +#endif + *recycle_flg = flg; + q = (struct spl_pbuf *) ADDR_SHTOL (q->next_a); + } +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h b/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h new file mode 100644 index 0000000..6a21312 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h @@ -0,0 +1,109 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_PBUF_COMM_H +#define STACKX_PBUF_COMM_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SPL_PBUF_TRANSPORT_HLEN 20 +#define SPL_PBUF_UDP_HLEN 8 +#define SPL_PBUF_IP_HLEN 20 + +#define SPL_PBUF_VLAN_HLEN 0 + +#ifndef SPL_PBUF_LINK_HLEN +#define SPL_PBUF_LINK_HLEN (14 + SPL_PBUF_VLAN_HLEN) +#endif + +typedef enum spl_pbuf_layer +{ + SPL_PBUF_TRANSPORT, + SPL_PBUF_UDP, + SPL_PBUF_IP, + SPL_PBUF_LINK, + SPL_PBUF_RAW, + SPL_PBUF_MAX_LAYER, +} spl_pbuf_layer; + +typedef enum spl_pbuf_type +{ + SPL_PBUF_RAM, /* pbuf data is stored in RAM */ + SPL_PBUF_ROM, /* pbuf data is stored in ROM */ + SPL_PBUF_REF, /* pbuf comes from the pbuf pool */ + SPL_PBUF_POOL, /* pbuf payload refers to RAM */ + SPL_PBUF_HUGE /* pbuf is stored in HugePage memory in struct common_mem_mbuf */ +} spl_pbuf_type; + +enum spl_pbuf_proto +{ + SPL_PBUF_PROTO_NONE, + SPL_PBUF_TCP_SEND, + SPL_PBUF_TCP_RECV +} spl_pbuf_proto; + +typedef struct spl_pbuf +{ + /** next pbuf in singly linked pbuf chain */ + union + { + struct spl_pbuf *next; + u64 next_a; + }; + + /** pointer to the actual data in the buffer */ + union + { + void *payload; + u64 payload_a; + }; + + union + { + void *msg; + u64 msg_a; + }; + + union + { + void *conn; + u64 conn_a; + }; + + struct spl_pbuf *freeNext; // This pointer will point to next pbuf you want to free in stackx + + u32 tot_len; + u32 len; + int proto_type; + u16 ref; + u8 type; + u8 flags; + nsfw_res res_chk; + +} spl_pbuf; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h b/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h new file mode 100644 index 0000000..119c26a --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h @@ -0,0 +1,239 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_SPL_MSG_H +#define STACKX_SPL_MSG_H +#include "nsfw_msg.h" +#include "stackx_ip_addr.h" +#include "stackx_spl_share.h" +#include "stackx_common_opt.h" +#include <sys/socket.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +enum spl_tcpip_msg_type +{ + SPL_TCPIP_NEW_MSG_API, +#if STACKX_TIMER_THREAD_SUPPORT + SPL_TCPIP_MSG_TIMER, +#endif +#if STACKX_NETIF_API + SPL_TCPIP_MSG_NETIFAPI, +#endif + SPL_TCPIP_MSG_CALLBACK, + SPL_TCPIP_MSG_IP_MODULE, + + SPL_TCPIP_MSG_MAX, //the number of enum + SPL_TCPIP_MSG_BOTTOM = MAX_MAJOR_TYPE //the max number of enum +}; + +enum api_msg_type +{ + SPL_API_DO_NEWCONN = 0, + SPL_API_DO_DELCON, + SPL_API_DO_RECV, + SPL_API_DO_GETADDR, + SPL_API_DO_BIND, + SPL_API_DO_CONNECT, + SPL_API_DO_LISTEN, + SPL_API_DO_CLOSE, + SPL_API_DO_SET_SOCK_OPT, + SPL_API_DO_GET_SOCK_OPT, + SPL_API_DO_SEND, + SPL_API_DO_WRITE, + SPL_API_DO_POST, + SPL_API_DO_SHOW, + SPL_API_DO_EXTREN_SOCK_SET, + SPL_API_DO_ENABLE_TRACE, + SPL_API_GET_PROTOCOL, + SPL_API_DO_IOCTL_OPT, + SPL_API_DO_GETSOCK_NAME, + SPL_API_DO_DUMP_L4, + SPL_API_DO_PBUF_FREE, + SPL_API_DO_APP_TOUCH, /* app send its version info to nStackMain */ + + SPL_API_MSG_MAX, //the number of enum + SPL_API_MSG_BOTTOM = MAX_MINOR_TYPE //the max number of enum +}; + +/* TODO: move thes to apporpriate file */ +#define TCP_RTO_MAX ((unsigned)(120*1000)) /* 120s */ +#define TCP_RTO_MIN ((unsigned)(200)) /* 200ms */ + +#define TCP_TIMEOUT_INIT ((unsigned)(1*1000)) /* RFC6298 2.1 initial RTO value */ +#define CONN_TCP_MEM_MIN_LINE ((TX_MBUF_POOL_SIZE)/1024) //conn level : min value of send_buf +#define CONN_TCP_MEM_DEF_LINE ((TX_MBUF_POOL_SIZE)/128) //conn level : default value of send_buf +#define CONN_TCP_MEM_MAX_LINE ((TX_MBUF_POOL_SIZE)/12) + +#define SOF_DEBUG 0x01U +#define SOF_ACCEPTCONN 0x02U +#define SOF_DONTROUTE 0x10U +#define SOF_USELOOPBACK 0x40U +#define SOF_LINGER 0x80U +#define SOF_OOBINLINE 0x0100U +#define SOF_REUSEPORT 0x0200U + +/* General structure for calling APIs*/ +typedef struct api_param_t +{ + data_com_msg *m; + i64 comm_private_data; +} api_param; + +/* SPL_API_DO_SEND */ +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *p; + spl_ip_addr_t local_ip; + spl_ip_addr_t addr; + spl_ip_addr_t srcAddr; + u16 port; + u16 srcPort; + u16 toport_chksum; + u8 tos; + u8 pad; + u8 flags; + i64 extend_member_bit; +} msg_send_buf; + +/* SPL_API_DO_BIND */ +typedef struct +{ + spl_ip_addr_t ipaddr; + u16 port; + i64 extend_member_bit; +} msg_bind; + +/* SPL_API_DO_CLOSE */ +typedef struct +{ + long time_started; + u8 shut; + i64 extend_member_bit; +} msg_close; + +/* SPL_API_DO_CONNECT */ +typedef struct +{ + spl_ip_addr_t local_ip; + spl_ip_addr_t ipaddr; + u16 port; + i64 extend_member_bit; +} msg_connect; + +/* SPL_API_DO_DELCON */ +typedef struct +{ + PRIMARY_ADDR struct spl_netconn *conn; + PRIMARY_ADDR struct spl_pbuf *buf; + long time_started; + pid_t pid; + u8 shut; + u8 msg_box_ref; /* use it for priority */ + u8 notify_omc; /* bool */ + i64 extend_member_bit; +} msg_delete_netconn; + +/* SPL_API_DO_WRITE */ +typedef struct msg_write_buf_T +{ + PRIMARY_ADDR struct spl_pbuf *p; + struct msg_write_buf_T *next; + size_t len; + u8 apiflags; + i64 extend_member_bit; +} msg_write_buf; + +/* SPL_API_DO_LISTEN */ +typedef struct +{ + mring_handle conn_pool; + u8 backlog; + i64 extend_member_bit; +} msg_listen; + +/* SPL_API_DO_NEWCONN */ +typedef struct +{ + PRIMARY_ADDR struct spl_netconn *conn; + spl_netconn_type_t type; + u8 proto; + int socket; + i64 extend_member_bit; +} msg_new_netconn; + +/* SPL_API_DO_RECV */ +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *p; + u32 len; + i64 extend_member_bit; +} msg_recv_buf; + +/* SPL_API_DO_GETSOCK_NAME */ +typedef struct +{ + struct sockaddr sock_addr; + u8 cmd; + i64 extend_member_bit; +} msg_getaddrname; + +/* SPL_API_DO_GET_SOCK_OPT,SPL_API_DO_SET_SOCK_OPT */ +typedef struct +{ + int level; + int optname; + PRIMARY_ADDR mring_handle msg_box; /* IP_TOS, spl will get new msg box for app */ + union + { + int int_optval; + //struct in_addr inaddr_optval; + //struct linger _linger; + struct timeval timeval_optval; + //ipmreq ipmreq_optval; //Multicast support later + } optval; + + u32 optlen; + i64 extend_member_bit; +} msg_setgetsockopt; + +/* SPL_API_DO_PBUF_FREE */ +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *buf; + i64 extend_member_bit; +} msg_free_buf; + +/* app send its version info to nStackMain */ +#define NSTACK_VERSION_LEN 128 +/* SPL_API_DO_APP_TOUCH */ +typedef struct +{ + u32_t hostpid; + char app_version[NSTACK_VERSION_LEN]; +} msg_app_touch; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c new file mode 100644 index 0000000..4fa91d8 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c @@ -0,0 +1,198 @@ +/* +* +* 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 "stackx_spl_msg.h" +#include "stackx_spl_share.h" +#include "nstack_log.h" +#include "nsfw_msg_api.h" +#include "nsfw_recycle_api.h" + +/***************************************************************************** +* Prototype : ss_reset_conn_recycle +* Description : reset conn recycle +* Input : netconn_recycle* recycle +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_reset_conn_recycle (netconn_recycle * recycle) +{ + recycle->accept_from = NULL; + recycle->is_listen_conn = 0; + (void) nsfw_pidinfo_init (&recycle->pid_info); + recycle->fork_ref = 0; + recycle->delay_msg = NULL; + recycle->delay_flag = SS_DELAY_STOPPED; +} + +/***************************************************************************** +* Prototype : ss_reset_conn +* Description : reset conn +* Input : spl_netconn_t* conn +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +ss_reset_conn (spl_netconn_t * conn) +{ + conn->recv_obj = 0; + conn->private_data = 0; + conn->msg_box = NULL; + conn->snd_buf = 0; + conn->epoll_flag = 0; + conn->recv_avail_prod = 0; + conn->recv_avail_cons = 0; + conn->rcvevent = 0; + conn->state = SPL_NETCONN_NONE; + conn->sendevent = 0; + conn->errevent = 0; + conn->shut_status = 0xFFFF; + conn->flags = 0; + conn->last_err = 0; + conn->CanNotReceive = 0; + conn->bind_thread_index = 0; + conn->tcp_sndbuf = 0; + conn->tcp_wmem_alloc_cnt = 0; + conn->tcp_wmem_sbr_free_cnt = 0; + conn->tcp_wmem_spl_free_cnt = 0; + conn->mss = 0; + conn->remote_port = 0; + conn->remote_ip.addr = 0; + conn->local_ip.addr = 0; + conn->local_port = 0; + conn->type = SPL_NETCONN_INVALID; + conn->tcp_state = SPL_CLOSED; + ss_reset_conn_recycle (&conn->recycle); + conn->extend_member_bit = 0; + conn->epInfo = NULL; +} + +/***************************************************************************** +* Prototype : ss_init_conn +* Description : init conn +* Input : spl_netconn_t* conn +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_init_conn (spl_netconn_t * conn, mring_handle pool, + spl_netconn_type_t type) +{ + res_alloc (&conn->res_chk); + + conn->type = type; + conn->recycle.fork_ref = 1; + conn->recv_ring_valid = 1; + sys_sem_init (&conn->close_completed); + NSSBR_LOGINF ("malloc conn ok]conn=%p,pool=%p", conn, pool); +} + +/***************************************************************************** +* Prototype : ss_malloc_conn +* Description : malloc conn, only used in spl +* Input : mring_handle pool +* netconn_type_t type +* Output : None +* Return Value : spl_netconn_t* +* Calls : +* Called By : +* +*****************************************************************************/ +spl_netconn_t * +ss_malloc_conn (mring_handle pool, spl_netconn_type_t type) +{ + spl_netconn_t *conn = NULL; + + if (nsfw_mem_ring_dequeue (pool, (void **) &conn) != 1) + { + NSSBR_LOGERR ("malloc conn failed"); + return NULL; + } + + ss_init_conn (conn, pool, type); + return conn; +} + +/***************************************************************************** +* Prototype : ss_malloc_conn_app +* Description : malloc conn, only used in app +* Input : mring_handle pool +* netconn_type_t type +* Output : None +* Return Value : spl_netconn_t* +* Calls : +* Called By : +* +*****************************************************************************/ +spl_netconn_t * +ss_malloc_conn_app (mring_handle pool, spl_netconn_type_t type) +{ + spl_netconn_t *conn = NULL; + + if (nsfw_mem_ring_dequeue (pool, (void **) &conn) != 1) + { + NSSBR_LOGERR ("malloc conn failed"); + return NULL; + } + + if (ss_add_pid (conn, get_sys_pid ()) < 0) + { + NSSBR_LOGERR ("ss_add_pid failed]conn=%p", conn); + } + + ss_init_conn (conn, pool, type); + return conn; +} + +/***************************************************************************** +* Prototype : ss_free_conn +* Description : free conn +* Input : spl_netconn_t* conn +* mring_handle pool +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +ss_free_conn (spl_netconn_t * conn) +{ + ss_reset_conn (conn); + + if (res_free (&conn->res_chk)) + { + NSFW_LOGERR ("conn refree!]conn=%p", conn); + return; + } + + mring_handle pool = ss_get_conn_pool (conn); + if (nsfw_mem_ring_enqueue (pool, (void *) conn) != 1) + { + NSSBR_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen"); + } + + NSSBR_LOGINF ("free conn ok]conn=%p,pool=%p", conn, pool); +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h new file mode 100644 index 0000000..3b0c9f9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h @@ -0,0 +1,478 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_SPL_SHARE_H +#define STACKX_SPL_SHARE_H +#include "types.h" +#include "common_mem_api.h" +#include "nsfw_mem_api.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_ip_addr.h" +#include <sys/types.h> +#include "spl_opt.h" +#include "stackx_ip_tos.h" +#include "stackx_common_opt.h" +#include "stackx_tx_box.h" +#include "pidinfo.h" +//#include "stackx_dfx_api.h" +#include "compiling_check.h" +#include "nsfw_msg.h" +#include "stackx_spl_msg.h" +#include "hal_api.h" +#include "stackx_types.h" +#include <errno.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MSG_PRIO_QUEUE_NUM 3 +COMPAT_PROTECT (MSG_PRIO_QUEUE_NUM, 3); + +#define SPL_MSG_BOX_NUM (MSG_PRIO_QUEUE_NUM + 1) + +#define SBR_FD_NETCONN_SIZE (256 * 3) +COMPAT_PROTECT (SBR_FD_NETCONN_SIZE, 256 * 3); + +#define SS_NETCONN_SIZE (256 * 2) +#define SBR_FD_SIZE (SBR_FD_NETCONN_SIZE - SS_NETCONN_SIZE) + +typedef struct +{ + PRIMARY_ADDR mring_handle msg_pool; + PRIMARY_ADDR mring_handle conn_pool; + PRIMARY_ADDR struct spl_netconn **conn_array; + u32 conn_num; + i64 extend_member_bit; +} sbr_recycle_group; + +typedef enum +{ + SS_DELAY_STARTED, + SS_DELAY_STOPPING, + SS_DELAY_STOPPED, + SS_DELAY_AGAIN +} ss_delay_flag; + +typedef enum +{ + NORMAL_RECV_RING = 0, + CUSTOM_RECV_RING = 1, +} recv_ring_type; + +typedef struct +{ + PRIMARY_ADDR sbr_recycle_group *group; + PRIMARY_ADDR struct spl_netconn *accept_from; /* for recycle fd in listen */ + void *delay_msg; + nsfw_pidinfo pid_info; + volatile i16 fork_ref; + i8 is_listen_conn; + i8 delay_flag; +} netconn_recycle; + +typedef struct spl_netconn +{ + i64 recv_obj; + i64 comm_pcb_data; /* only used by spl */ + i64 private_data; /* only used by spl */ + PRIMARY_ADDR mring_handle msg_box; + PRIMARY_ADDR mring_handle recv_ring; + volatile u32 snd_buf; + volatile i32 epoll_flag; + /*here using prod/cons to instead recv_avail, avoid atomic oper. */ + volatile u32_t recv_avail_prod; /*the product of recv_avail */ + volatile u32_t recv_avail_cons; /*the consume of recv_avail */ + volatile i32 rcvevent; + spl_netconn_state_t state; + u16 sendevent; + u16 errevent; + volatile u16 shut_status; + u8 flags; + i8 last_err; + u8 CanNotReceive; + u8 recv_ring_valid; + u16 bind_thread_index; + u16 mss; + sys_sem_st close_completed; + mring_handle conn_pool; /* where the conn in pcb is from */ + + void *epInfo; + + /* The following shared field access rules: protocol stack process + * is responsible for writing, socket api process read only + */ + i32 send_bufsize; + i32 tcp_sndbuf; + u32 tcp_wmem_alloc_cnt; + u32 tcp_wmem_sbr_free_cnt; + volatile u32 tcp_wmem_spl_free_cnt; + u16 remote_port; + u16 local_port; + spl_ip_addr_t remote_ip; + spl_ip_addr_t local_ip; + spl_netconn_type_t type; + spl_tcp_state_t tcp_state; + + /* for recycle */ + netconn_recycle recycle; + nsfw_res res_chk; + i64 extend_member_bit; +} spl_netconn_t; /* sizeof(spl_netconn_t) need < SS_NETCONN_SIZE */ +SIZE_OF_TYPE_PLUS8_NOT_LARGER_THAN (spl_netconn_t, SS_NETCONN_SIZE); + +typedef struct +{ + /** + * it will increase after every restart which used for + * tell different runnings. + */ + u32 running_ref_no; + + /* only increased when fault to restart */ + u32 fault_ref_no; + + /* the procedures before upgrade are finished successfully */ + u32 prepare_upgrade_done; + +} spl_init_info_t; + +typedef struct netifExt +{ + struct netifExt *next; + u16_t id; + char if_name[HAL_MAX_NIC_NAME_LEN]; + hal_hdl_t hdl; + u16_t num_packets_recv; +} netifExt; + +static inline mring_handle +ss_get_msg_pool (spl_netconn_t * sh) +{ + sbr_recycle_group *group = + (sbr_recycle_group *) ADDR_SHTOL (sh->recycle.group); + return ADDR_SHTOL (group->msg_pool); +} + +static inline mring_handle +ss_get_conn_pool (spl_netconn_t * sh) +{ + sbr_recycle_group *group = + (sbr_recycle_group *) ADDR_SHTOL (sh->recycle.group); + return ADDR_SHTOL (group->conn_pool); +} + +static inline int +ss_is_nonblock_flag (spl_netconn_t * sh) +{ + return (sh->flags & SPL_NETCONN_FLAG_NON_BLOCKING) != 0; +} + +static inline int +ss_get_nonblock_flag (spl_netconn_t * sh) +{ + return ss_is_nonblock_flag (sh) ? O_NONBLOCK : 0; +} + +static inline void +ss_set_nonblock_flag (spl_netconn_t * sh, u32 flag) +{ + if (flag) + { + sh->flags |= SPL_NETCONN_FLAG_NON_BLOCKING; + } + else + { + sh->flags &= ~SPL_NETCONN_FLAG_NON_BLOCKING; + } +} + +static inline int +ss_get_last_errno (spl_netconn_t * sh) +{ + return sh->last_err; +} + +static inline i32 +ss_get_recv_event (spl_netconn_t * sh) +{ + return sh->rcvevent; +} + +static inline int +ss_can_not_recv (spl_netconn_t * sh) +{ + return sh->CanNotReceive; +} + +static inline int +ss_is_shut_rd (spl_netconn_t * sh) +{ + int status = sh->shut_status; + return ((SPL_SHUT_RD == status) || (SPL_SHUT_RDWR == status)); +} + +static inline void +ss_set_shut_status (spl_netconn_t * sh, u16 how) +{ + sh->shut_status = how; +} + +static inline u16 +ss_get_shut_status (spl_netconn_t * sh) +{ + return sh->shut_status; +} + +static inline void +ss_sub_recv_event (spl_netconn_t * sh) +{ + __sync_fetch_and_sub (&sh->rcvevent, 1); +} + +static inline void +ss_add_recv_event (spl_netconn_t * sh) +{ + __sync_fetch_and_add (&sh->rcvevent, 1); +} + +static inline i64 +ss_get_recv_obj (spl_netconn_t * sh) +{ + return sh->recv_obj; +} + +static inline i64 +ss_get_private_data (spl_netconn_t * sh) +{ + return sh->private_data; +} + +static inline i64 +ss_get_comm_private_data (spl_netconn_t * sh) +{ + return sh->comm_pcb_data; +} + +static inline int +ss_recv_ring_valid (spl_netconn_t * sh) +{ + return sh->recv_ring_valid; +} + +static inline mring_handle +ss_get_recv_ring (spl_netconn_t * sh) +{ + return (mring_handle) ADDR_SHTOL (sh->recv_ring); +} + +static inline void +ss_set_send_event (spl_netconn_t * sh, u16 value) +{ + sh->sendevent = value; +} + +static inline int +ss_is_noautorecved_flag (spl_netconn_t * sh) +{ + return (sh->flags & SPL_NETCONN_FLAG_NO_AUTO_RECVED) != 0; +} + +static inline int +ss_get_noautorecved_flag (spl_netconn_t * sh) +{ + return ss_is_noautorecved_flag (sh) ? SPL_NETCONN_FLAG_NO_AUTO_RECVED : 0; +} + +static inline void +ss_set_noautorecved_flag (spl_netconn_t * sh, u8 flag) +{ + if (flag) + { + sh->flags |= SPL_NETCONN_FLAG_NO_AUTO_RECVED; + } + else + { + sh->flags &= ~SPL_NETCONN_FLAG_NO_AUTO_RECVED; + } +} + +static inline void +ss_set_state (spl_netconn_t * sh, spl_netconn_state_t state) +{ + sh->state = state; +} + +static inline int +ss_is_write_state (spl_netconn_t * sh) +{ + return (SPL_NETCONN_WRITE == sh->state); +} + +static inline int +ss_is_listen_state (spl_netconn_t * sh) +{ + return (SPL_NETCONN_LISTEN == sh->state); +} + +static inline void +ss_sub_recv_avail (spl_netconn_t * sh, int value) +{ + sh->recv_avail_cons += value; +} + +static inline i32 +ss_get_recv_avail (spl_netconn_t * sh) +{ + return sh->recv_avail_prod - sh->recv_avail_cons; +} + +static inline u16 +ss_get_mss (spl_netconn_t * sh) +{ + return sh->mss; +} + +static inline spl_ip_addr_t * +ss_get_remote_ip (spl_netconn_t * sh) +{ + return &(sh->remote_ip); +} + +static inline u16 +ss_get_remote_port (spl_netconn_t * sh) +{ + return sh->remote_port; +} + +static inline spl_tcp_state_t +ss_get_tcp_state (spl_netconn_t * sh) +{ + return sh->tcp_state; +} + +static inline u16 +ss_get_bind_thread_index (spl_netconn_t * sh) +{ + return sh->bind_thread_index; +} + +static inline void +ss_set_bind_thread_index (spl_netconn_t * sh, u16 bind_thread_index) +{ + sh->bind_thread_index = bind_thread_index; +} + +static inline void +ss_set_msg_box (spl_netconn_t * sh, mring_handle box) +{ + sh->msg_box = (mring_handle) ADDR_LTOSH (box); +} + +static inline mring_handle +ss_get_msg_box (spl_netconn_t * sh) +{ + return (mring_handle) ADDR_SHTOL (sh->msg_box); +} + +static inline spl_ip_addr_t * +ss_get_local_ip (spl_netconn_t * sh) +{ + return &sh->local_ip; +} + +static inline void +ss_set_local_ip (spl_netconn_t * sh, u32 addr) +{ + if (!sh) + { + return; + } + sh->local_ip.addr = addr; +} + +static inline u16 +ss_get_local_port (spl_netconn_t * sh) +{ + return sh->local_port; +} + +static inline void +ss_set_local_port (spl_netconn_t * sh, u16 local_port) +{ + sh->local_port = local_port; +} + +static inline void +ss_set_accept_from (spl_netconn_t * sh, spl_netconn_t * accept_from) +{ + sh->recycle.accept_from = accept_from; +} + +static inline void +ss_set_is_listen_conn (spl_netconn_t * sh, i8 is_listen_conn) +{ + sh->recycle.is_listen_conn = is_listen_conn; +} + +static inline i32 +ss_dec_fork_ref (spl_netconn_t * sh) +{ + return __sync_sub_and_fetch (&sh->recycle.fork_ref, 1); +} + +static inline int +ss_add_pid (spl_netconn_t * sh, pid_t pid) +{ + return nsfw_add_pid (&sh->recycle.pid_info, pid); +} + +static inline int +ss_del_pid (spl_netconn_t * sh, pid_t pid) +{ + return nsfw_del_pid (&sh->recycle.pid_info, pid); +} + +static inline int +ss_is_pid_exist (spl_netconn_t * sh, pid_t pid) +{ + return nsfw_pid_exist (&sh->recycle.pid_info, pid); +} + +static inline int +ss_is_pid_array_empty (spl_netconn_t * sh) +{ + return nsfw_pidinfo_empty (&sh->recycle.pid_info); +} + +spl_netconn_t *ss_malloc_conn (mring_handle pool, spl_netconn_type_t type); +spl_netconn_t *ss_malloc_conn_app (mring_handle pool, + spl_netconn_type_t type); +void ss_free_conn (spl_netconn_t * conn); +void ss_reset_conn (spl_netconn_t * conn); + +typedef void (*ss_close_conn_fun) (void *close_data, u32 delay_sec); +int ss_recycle_conn (void *close_data, ss_close_conn_fun close_conn); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h b/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h new file mode 100644 index 0000000..cac3dcb --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h @@ -0,0 +1,42 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_TCP_OPT_H__ +#define __STACKX_TCP_OPT_H__ + +#include "spl_opt.h" + +/* TCP Options flags */ +#define TF_ACK_DELAY ((u32_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u32_t)0x02U) /* Immediate ACK. */ +#define TF_WINDOWSCALING ((u32_t)0x40U) /* Window scaling option enabled */ +#define TF_INFR ((u32_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u32_t)0x08U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((u32_t)0x10U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((u32_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u32_t)0x100U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u32_t)0x80U) + +/* TCP segment Options flags */ +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_OPTS_WS (u8_t)0x08U /* Include window scaling option. */ + +#define STACKX_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + \ + (flags & TF_SEG_OPTS_WS ? 4 : 0) +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c new file mode 100644 index 0000000..74673ad --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c @@ -0,0 +1,64 @@ +/* +* +* 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 "stackxopts.h" +#include "nstack_log.h" +#include "stackx_tx_box.h" +#include "nsfw_mt_config.h" + +#define MZ_STACKX_RING_NAME "VppTCP_Ring" +#define MZ_STACKX_PRIORITY_RING_NAME "VppTCP_Priority%u_Ring" + +/* + * Given the stackx ring name template above, get the queue name + */ +const char * +get_stackx_ring_name () +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char rbuffer[sizeof (MZ_STACKX_RING_NAME) + 16]; + + int retVal = + spl_snprintf (rbuffer, sizeof (rbuffer) - 1, MZ_STACKX_RING_NAME); + + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return rbuffer; +} + +const char * +get_stackx_priority_ring_name (unsigned priority) +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char prbuffer[sizeof (MZ_STACKX_PRIORITY_RING_NAME) + 32]; + + int retVal = spl_snprintf (prbuffer, sizeof (prbuffer) - 1, + MZ_STACKX_PRIORITY_RING_NAME, priority); + + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return prbuffer; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h new file mode 100644 index 0000000..edfba5c --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h @@ -0,0 +1,39 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_TX_BOX_H +#define STACKX_TX_BOX_H +#include "sys/types.h" +#include "nsfw_mem_api.h" +#include "stackx_common.h" +#include "nsfw_mt_config.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +const char *get_stackx_ring_name (); +const char *get_stackx_priority_ring_name (unsigned priority); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_types.h b/stacks/lwip_stack/lwip_src/common/stackx_types.h new file mode 100644 index 0000000..6c78a20 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_types.h @@ -0,0 +1,68 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_TYPES_H +#define STACKX_TYPES_H + +#include <sys/time.h> +#include <sys/types.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#if 1 +#ifndef STACKX_MAX_S16_NUM +#define STACKX_MAX_S16_NUM ((s16_t)0x7fff) +#endif + +#ifndef STACKX_MAX_U16_NUM +#define STACKX_MAX_U16_NUM ((u16_t)0xFfff) +#endif + +#ifndef STACKX_MAX_U32_NUM +#define STACKX_MAX_U32_NUM ((u32_t)0xffffffff) +#endif + +#ifndef STACKX_MAX_S32_NUM +#define STACKX_MAX_S32_NUM ((s32_t)0x7fffffff) +#endif + +#ifndef STACKX_MAX_U64_NUM +#define STACKX_MAX_U64_NUM ((u64_t)0xffffffffffffffff) +#endif + +#ifndef STACKX_MAX_S64_NUM +#define STACKX_MAX_S64_NUM ((s64_t)0x7fffffffffffffff) +#endif +#endif + +#if 1 +typedef uint64_t u64_t; +typedef int64_t s64_t; + +typedef uint32_t u32_t; +typedef int32_t s32_t; + +typedef uint16_t u16_t; +typedef int16_t s16_t; + +typedef uint8_t u8_t; +typedef int8_t s8_t; + +typedef uintptr_t mem_ptr_t; +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackxopts.h b/stacks/lwip_stack/lwip_src/common/stackxopts.h new file mode 100644 index 0000000..15fc6b8 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackxopts.h @@ -0,0 +1,53 @@ +/* +* +* 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. +*/ + +#ifndef STACKX_OPTS_H +#define STACKX_OPTS_H + +struct memory_statics +{ + char name[120]; + long size; +}; + +extern u32 g_type; +extern struct memory_statics memory_used_size[80]; + +#define DPDK_MEMORY_COUNT(memory, len)\ +{\ + if (g_type < MAX_MEMORY_USED_SIZE)\ + {\ + const char * ptr_memory = memory;\ + if (ptr_memory && EOK != STRCPY_S(memory_used_size[g_type].name, sizeof(memory_used_size[g_type].name), ptr_memory))\ + {\ + NSPOL_LOGERR("STRCPY_S failed.");\ + }\ + memory_used_size[g_type].size =(long) len;\ + g_type++;\ + }\ +} + +#define SPL_MAX_UDP_MSG_LEN (0xFFFF -28) +#define RECV_MAX_POOL 4 +#define MAX_TRY_GET_MEMORY_TIMES 4 +#define MAX_MEMORY_USED_SIZE 80 +#define SPL_IP_HLEN 20 +#define SPL_TCP_HLEN 20 +#define SPL_TCP_MAX_OPTION_LEN 40 +#define SPL_FRAME_MTU 1500 +#define SPL_TCP_SEND_MAX_SEG_PER_MSG 5 + +#endif diff --git a/stacks/lwip_stack/lwip_src/core/global_tick.c b/stacks/lwip_stack/lwip_src/core/global_tick.c new file mode 100644 index 0000000..ee180c9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/global_tick.c @@ -0,0 +1,48 @@ +/* +* +* 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 "nsfw_mem_api.h" +#include "nstack_share_res.h" +#include "nstack_securec.h" + +extern nstack_tick_info_t g_nstack_timer_tick; + +int +init_stackx_global_tick (void) +{ + nsfw_mem_zone mzone; + + if (STRCPY_S + (mzone.stname.aname, NSFW_MEM_NAME_LENGTH, NSTACK_GLOBAL_TICK_SHM) != 0) + { + NSPOL_LOGERR ("STRCPY_S fail"); + return -1; + } + + mzone.stname.entype = NSFW_SHMEM; + mzone.isocket_id = -1; + mzone.length = sizeof (uint64_t); + mzone.ireserv = 0; + + g_nstack_timer_tick.tick_ptr = (uint64_t *) nsfw_mem_zone_create (&mzone); + if (NULL == g_nstack_timer_tick.tick_ptr) + { + NSPOL_LOGERR ("Failed to create global timer tick memory"); + return -1; + } + + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/core/spl_pbuf.c b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c new file mode 100644 index 0000000..03e30ed --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c @@ -0,0 +1,597 @@ +/* +* +* 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 "spl_pbuf.h" +#include "stackx_pbuf.h" + +#include "stackx_spl_share.h" +#include "spl_api.h" + +#include "nsfw_maintain_api.h" +#include "netif/sc_dpdk.h" +#include <common_mem_mbuf.h> + +#include <string.h> +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_instance.h" + +#include "sys.h" +#include "mem.h" +#include "memp.h" +//#include "sockets.h" +//#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct spl_pbuf)) +u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +u16_t g_offSetArry[SPL_PBUF_MAX_LAYER] = + { PBUF_TRANSPORT_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN, + SPL_PBUF_UDP_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN, + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN, + SPL_PBUF_LINK_HLEN, + 0 +}; + +inline struct spl_pbuf * +spl_pbuf_alloc_hugepage (spl_pbuf_layer layer, u16_t length, + spl_pbuf_type Type, u16_t proc_id, void *net_conn) +{ + struct spl_pbuf *p; + u16_t offset; + u16_t count = 0; + spl_netconn_t *conn = (spl_netconn_t *) net_conn; + + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, + "spl_pbuf_alloc_hugepage]length=%" U16_F, length); + + /* determine header offset */ + if (likely (layer < SPL_PBUF_MAX_LAYER)) + { + offset = g_offSetArry[layer]; + } + else + { + NSPOL_LOGERR ("spl_pbuf_alloc_hugepage: bad pbuf layer"); + return NULL; + } + + if (unlikely (length < offset || Type != SPL_PBUF_HUGE)) + { + NSPOL_LOGERR ("input is invalid!]length=%u, Type = %d", length, Type); + return NULL; + } + + p = spl_mbuf_malloc (length, SPL_PBUF_HUGE, &count); + + if (p == NULL) + { + /* last_log_prt_time and unprint_log_count indeed have multi-thread issue, + * but their values don't have precision requirement. No risk. */ + NS_LOG_CTRL (LOG_CTRL_HUGEPAGE_ALLOC_FAIL, STACKX, "NSPOL", NSLOG_ERR, + "pbuf_alloc_huge: Could not allocate PBUF for SPL_PBUF_HUGE"); + + return NULL; + } + + if (conn) + { + p->conn_a = ADDR_LTOSH (conn); + } + else + { + p->conn_a = 0; + } + + p->tot_len -= offset; + p->len -= offset; + p->next_a = 0; + + p->payload_a = p->payload_a + offset; + + p->proto_type = SPL_PBUF_PROTO_NONE; + + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, + "pbuf_alloc]length=%" U16_F ",p=%p", length, (void *) p); + return p; +} + +inline int +spl_pbuf_internal_copy (struct spl_pbuf *dst, struct spl_pbuf *src) +{ + u32_t dst_len = dst->len; + u32_t src_len = src->len; + u32_t dst_pos = 0; + u32_t src_pos = 0; + while (dst != NULL && src != NULL) + { + if (dst_len > src_len) + { + if (NULL == + common_memcpy (PTR_SHTOL (char *, dst->payload_a) + dst_pos, + PTR_SHTOL (char *, src->payload_a) + src_pos, + src_len)) + { + NSPOL_LOGERR ("rte_memcpy error"); + return -1; + } + + dst_len -= src_len; + dst_pos += src_len; + src = ADDR_SHTOL (src->next_a); + src_len = src != NULL ? src->len : 0; + src_pos = 0; + } + else if (dst_len < src_len) + { + if (NULL == + common_memcpy (PTR_SHTOL (char *, dst->payload_a) + dst_pos, + PTR_SHTOL (char *, src->payload_a) + src_pos, + dst_len)) + { + NSPOL_LOGERR ("rte_memcpy error"); + return -1; + } + + src_len -= dst_len; + src_pos += dst_len; + dst = ADDR_SHTOL (dst->next_a); + dst_len = dst != NULL ? dst->len : 0; + dst_pos = 0; + } + else + { + if (NULL == + common_memcpy (PTR_SHTOL (char *, dst->payload_a) + dst_pos, + PTR_SHTOL (char *, src->payload_a) + src_pos, + dst_len)) + { + NSPOL_LOGERR ("rte_memcpy error"); + return -1; + } + + src = ADDR_SHTOL (src->next_a); + src_len = src != NULL ? src->len : 0; + src_pos = 0; + dst = ADDR_SHTOL (dst->next_a); + dst_len = dst != NULL ? dst->len : 0; + dst_pos = 0; + } + } + return 0; +} + +void +spl_pbuf_realloc (struct spl_pbuf *p, u32_t new_len) +{ + if (NULL != p && p->type == SPL_PBUF_HUGE) + { + p->tot_len = new_len; + p->len = new_len; + return; + } +} + +void +spl_pbuf_free (struct spl_pbuf *p) +{ + struct spl_pbuf *q; + u8_t count = 0; + + NSPOL_LOGINF (PBUF_DEBUG, "Freeing PBF %p", p); + + if (unlikely (p == NULL || p->type != SPL_PBUF_HUGE)) + { + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_LEVEL_SERIOUS, + "input param illegal]p=%p, type=%d", p, p ? p->type : -1); + return; + } + + (void) count; + + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + do + { + /* remember next pbuf in chain for next iteration */ + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, + "spl_pbuf_free: deallocating]buf=%p", (void *) p); + q = (struct spl_pbuf *) ADDR_SHTOL (p->next_a); + if (res_free (&p->res_chk)) + { + //NSPOL_LOGERR("res_free failed]p=%p", p); + } + + count++; + { + pbuf_set_recycle_flg (p, MBUF_UNUSED); /* release buf hold by app on abnormal exit */ + spl_mbuf_free ((char *) p - sizeof (struct common_mem_mbuf)); + p->res_chk.u8Reserve |= PBUF_FREE_FLAG; + } + + /* proceed to next pbuf */ + p = q; + } + while (p != NULL); + + /* return number of de-allocated pbufs */ + return; +} + +void +spl_pbuf_cat (struct spl_pbuf *h, struct spl_pbuf *t) +{ + struct spl_pbuf *p; + + if (h == NULL || t == NULL) + { + NSPOL_LOGERR ("pbuf_cat: h=NULL||t=NULL!!"); + return; + } + + for (p = h; p->next_a != 0; p = PTR_SHTOL (struct spl_pbuf *, p->next_a)) + { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + + if (0 != p->next_a) + { + NSPOL_LOGERR + ("pbuf_cat: p is not the last pbuf of the first chain, p->next_a != 0"); + return; + } + + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + + /* chain last pbuf of head (p) with first of tail (t) */ + p->next_a = (uint64_t) ADDR_LTOSH_EXT (t); + + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +err_t +spl_pbuf_copy (struct spl_pbuf * p_to, struct spl_pbuf * p_from) +{ + u32_t offset_to = 0; + u32_t offset_from = 0; + u32_t len = 0; + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, "pbuf_copy]p_to=%p,p_from=%p", + (void *) p_to, (void *) p_from); + + if (! + ((p_to != NULL) && (p_from != NULL) + && (p_to->tot_len >= p_from->tot_len))) + { + NSPOL_LOGERR ("pbuf_copy: target not big enough to hold source"); + return ERR_ARG; + } + + do + { + if (p_to == NULL) + { + NSPOL_LOGERR ("pbuf_copy: target pbuf not exist: p_to == NULL!!"); + return ERR_ARG; + } + + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) + { + + len = p_from->len - offset_from; + } + else + { + + len = p_to->len - offset_to; + } + + if (EOK != + MEMMOVE_S ((u8_t *) ADDR_SHTOL (p_to->payload_a) + offset_to, len, + (u8_t *) ADDR_SHTOL (p_from->payload_a) + offset_from, + len)) + { + NSPOL_LOGERR ("MEMMOVE_S failed"); + return ERR_MEM; + } + + offset_to += len; + offset_from += len; + if (offset_to > p_to->len) + { + NSPOL_LOGERR + ("pbuf_copy: target offset not match: offset_to > p_to->len."); + return ERR_VAL; + } + if (offset_to == p_to->len) + { + offset_to = 0; + p_to = (struct spl_pbuf *) ADDR_SHTOL (p_to->next_a); + } + + if (offset_from >= p_from->len) + { + /* on to next p_from (if any) */ + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, + "pbuf_copy: source offset not match: offset_from >= p_from->len"); + offset_from = 0; + p_from = (struct spl_pbuf *) ADDR_SHTOL (p_from->next_a); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) + { + if ((p_from->next_a != 0)) + { + NSPOL_LOGERR ("pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) + { + /* don't copy more than one packet! */ + if ((p_to->next_a != 0)) + { + NSPOL_LOGERR ("pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + } + while (p_from); + + NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, + "pbuf_copy: end of chain reached."); + return ERR_OK; +} + +err_t +splpbuf_to_pbuf_copy (struct pbuf * p_to, struct spl_pbuf * p_from) +{ + u32_t offset_to = 0; + u32_t offset_from = 0; + u32_t len = 0; + + NSPOL_LOGINF (NETIF_DEBUG, "splpbuf_to_pbuf_copy"); + + if (! + ((p_to != NULL) && (p_from != NULL) + && (p_to->tot_len >= p_from->tot_len))) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy: target not big enough to hold source"); + return ERR_ARG; + } + NSPOL_LOGINF (PBUF_DEBUG, + "splpbuf_to_pbuf_copy]p_to=%p [type %d tot_len %d], p_from=%p [type %d tot_len %d]", + (void *) p_to, p_to->type, p_to->tot_len, (void *) p_from, + p_from->type, p_from->tot_len); + do + { + NSPOL_LOGINF (NETIF_DEBUG, "copying...."); + if (p_to == NULL) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy: target not big enough to hold source p_to len [%d] p_from len [%d]", + p_to->tot_len, p_from->tot_len); + return ERR_ARG; + } + + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) + { + + len = p_from->len - offset_from; + } + else + { + + len = p_to->len - offset_to; + } + + if (EOK != MEMMOVE_S ((u8_t *) p_to->payload + offset_to, + len, + (u8_t *) ADDR_SHTOL (p_from->payload_a) + + offset_from, len)) + { + NSPOL_LOGERR ("MEMMOVE_S failed"); + return ERR_MEM; + } + + offset_to += len; + offset_from += len; + if (offset_to > p_to->len) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy: target offset not match: offset_to > p_to->len."); + return ERR_VAL; + } + if (offset_to == p_to->len) + { + offset_to = 0; + p_to = p_to->next; + + NSPOL_LOGINF (NETIF_DEBUG, + "splpbuf_to_pbuf_copy: p_to next %p", p_to); + } + + if (offset_from >= p_from->len) + { + /* on to next p_from (if any) */ + NSPOL_LOGINF (NETIF_DEBUG, + "splpbuf_to_pbuf_copy: source offset not match: offset_from >= p_from->len"); + offset_from = 0; + p_from = (struct spl_pbuf *) ADDR_SHTOL (p_from->next_a); + NSPOL_LOGINF (NETIF_DEBUG, + "splpbuf_to_pbuf_copy: pfrom next %p", p_from); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) + { + if ((p_from->next_a != 0)) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) + { + /* don't copy more than one packet! */ + if ((p_to->next != NULL)) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + } + while (p_from); + + NSPOL_LOGDBG (NETIF_DEBUG, "splpbuf_to_pbuf_copy: end of chain reached."); + return ERR_OK; +} + +err_t +pbuf_to_splpbuf_copy (struct spl_pbuf * p_to, struct pbuf * p_from) +{ + int offset = 0; + void *data = NULL; + + do + { + data = (u8_t *) (p_to->payload_a) + offset; + memcpy (data, (u8_t *) p_from->payload, p_from->len); + offset = offset + p_from->len; + if (offset >= 2048) + { + NSPOL_LOGERR ("More thank 2K size"); + return ERR_MEM; + } + p_from = p_from->next; + } + while (p_from != NULL); + + return ERR_OK; +} + +struct pbuf * +spl_convert_spl_pbuf_to_pbuf (struct spl_pbuf *p_from) +{ + struct pbuf *p_to = NULL; + + p_to = pbuf_alloc (PBUF_RAW, p_from->tot_len, PBUF_POOL); + if (p_to) + { + splpbuf_to_pbuf_copy (p_to, p_from); + } + return p_to; +} + +spl_pbuf_layer +get_pbuf_layer_from_pbuf_payload (struct pbuf * buf) +{ + + struct eth_hdr *ethhdr; + spl_pbuf_layer layer = SPL_PBUF_TRANSPORT; + u16_t type; + + if (buf->len <= SIZEOF_ETH_HDR) + { + NSPOL_LOGINF (PBUF_DEBUG, + "get_pbuf_layer_from_payload failed. length is wrong"); + return layer; + } + ethhdr = (struct eth_hdr *) buf->payload; + type = spl_htons (ethhdr->type); + + NSPOL_LOGINF (PBUF_DEBUG, "packet type %x", type); + + switch (type) + { + case ETHTYPE_IP: + layer = SPL_PBUF_IP; + break; + case ETHTYPE_ARP: + layer = SPL_PBUF_LINK; + break; + default: + layer = SPL_PBUF_TRANSPORT; + break; + } + + return layer; +} + +void +print_pbuf_payload_info (struct pbuf *buf, bool send) +{ + + struct eth_hdr *ethhdr; + u16_t type; + + if (buf->len <= SIZEOF_ETH_HDR) + { + NSPOL_LOGINF (PBUF_DEBUG, + "get_pbuf_layer_from_payload failed. length is wrong"); + return; + } + ethhdr = (struct eth_hdr *) buf->payload; + type = spl_htons (ethhdr->type); + + if (send) + { + NSPOL_LOGINF (PBUF_DEBUG, "send packet start type %x len %d *****", + type, buf->len); + } + else + { + NSPOL_LOGINF (PBUF_DEBUG, + "receive packet start type %x len %d ########", type, + buf->len); + } + + switch (type) + { + case ETHTYPE_IP: + NSPOL_LOGINF (TCPIP_DEBUG, "ip packet len %d tot len %d type %x", + buf->len, buf->tot_len, type); + struct ip_hdr *ip = + (struct ip_hdr *) ((char *) buf->payload + SIZEOF_ETH_HDR); + NSPOL_LOGINF (PBUF_DEBUG, "ip packet src %x dest %x proto %d", ip->src, + ip->dest, ip->_proto); + break; + case ETHTYPE_ARP: + NSPOL_LOGINF (TCPIP_DEBUG, "arp packet len %d tot len %d type %x", + buf->len, buf->tot_len, type); + break; + default: + NSPOL_LOGINF (TCPIP_DEBUG, "other packet len %d tot len %d type %x", + buf->len, buf->tot_len, type); + break; + } + return; +} diff --git a/stacks/lwip_stack/lwip_src/core/spl_timers.c b/stacks/lwip_stack/lwip_src/core/spl_timers.c new file mode 100644 index 0000000..50582fc --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/spl_timers.c @@ -0,0 +1,608 @@ +/* +* +* 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 "opt.h" +#include "nsfw_mem_api.h" +#include "def.h" +#include "sc_dpdk.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nstack_share_res.h" + +#include <time.h> +#include <signal.h> +#include <pthread.h> +#include <syscall.h> +#include "nsfw_ps_api.h" +#include "spl_timers.h" +#include "common_mem_api.h" + +extern sys_thread_t g_timerThread_id; + +/*Since the range of the dpdk read TSC value is u64_t, it changes*/ + +#ifndef typecheck +#define typecheck(type, x) \ +({ type __dummy; \ + typeof(x)__dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ + }) +#endif + +#ifndef time_after_eq +#define time_after_eq(a, b) \ +(typecheck(unsigned long, a) \ + && typecheck(unsigned long, b) \ + && ((long)(a) - (long)(b) >= 0)) +#endif + +#define MIN_TIME_PICE 50 +#define MICRO_PER_SECOND 1000 +#define NANO_PER_MICROSECOND 1000000 +#define NANO_PER_SECOND 1000000000 + +#define PTIMER_MSG_BUFFER_SIZE 4096 + +#define PTIMER_STATE_INACTIVE 0x00 +#define PTIMER_STATE_ENQUEUED 0x01 +#define gettid() syscall(__NR_gettid) + +#define TIMER_CONTEXT_NAME "TIMER_CONTEXT_NAME" + +static timer_t lazy_tim; +static timer_t lazy_tim_retry; +static struct ptimer_base ptimer; +static sys_sem_t ptimer_lock; + +extern void recycle_tmr (struct ptimer_node *tmo); + +extern nstack_tick_info_t g_nstack_timer_tick; + +/* + *************************** + * rb_tree wrapper function* + *************************** + */ +NSTACK_STATIC void +remove_ptimer (struct ptimer_node *tmo, struct ptimer_base *base) +{ + if (tmo == NULL) + { + NSPOL_LOGERR ("input parameter tmo is null"); + return; + } + if (!(tmo->state & PTIMER_STATE_ENQUEUED)) + { + NSPOL_LOGWAR (TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING, + "the timer state is: PTIMER_STATE_INACTIVE, no need to remove!"); + return; + } + + if (base->first == &tmo->node) + { + base->first = rb_next (&tmo->node); + } + + rb_erase (&tmo->node, &base->active); + + tmo->state = PTIMER_STATE_INACTIVE; +} + +NSTACK_STATIC struct ptimer_node * +search_ptimer (struct ptimer_msg *msg) +{ + if (msg == NULL) + { + NSPOL_LOGERR ("input parameter msg is null"); + return NULL; + } + if (msg->node) + { + return msg->node; + } + + return NULL; + +} + +err_t +del_ptimer (struct ptimer_msg * msg) +{ + struct ptimer_node *tmo; + + tmo = search_ptimer (msg); + if (tmo) + { + remove_ptimer (tmo, &ptimer); + NSPOL_LOGDBG (TIMERS_DEBUG, "del]thread=%u,ptimer_node=%p", tmo->index, + tmo); + return ERR_OK; + } + + NSPOL_LOGERR ("ptime_node not found!!"); + return ERR_VAL; +} + +/* + * Ptimer inserted into rb_tree + * @param node: the ptimer node pointer + * @param base: the ptimer root_base pointer + */ +NSTACK_STATIC void +enqueue_ptimer (struct ptimer_node *tmo, struct ptimer_base *base) +{ + struct rb_node **linknode; + struct rb_node *parent = NULL; + struct ptimer_node *entry; + int leftmost = 1; + if (tmo == NULL || base == NULL) + { + NSPOL_LOGERR ("input parameter is null"); + return; + } + + if ((tmo->state & PTIMER_STATE_ENQUEUED)) + { + NSPOL_LOGWAR (TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING, + "the timer state is: PTIMER_STATE_ENQUEUED"); + return; + } + + linknode = &base->active.rb_node; + while (*linknode) + { + parent = *linknode; + entry = rb_entry (parent, struct ptimer_node, node); + //XXX: do by the equal case is all of price of the large case + if (time_after_eq (entry->abs_nsec, tmo->abs_nsec)) + { + linknode = &(*linknode)->rb_left; + } + else + { + linknode = &(*linknode)->rb_right; + leftmost = 0; + } + } + + /* + * Insert the timer to the rb_tree and check whether it + * replaces the first pending timer + */ + if (leftmost) + { + base->first = &tmo->node; + } + + rb_link_node (&tmo->node, parent, linknode); + rb_insert_color (&tmo->node, &base->active); + NSPOL_LOGDBG (TIMERS_DEBUG, "enqueue]thread=%u,ptimer_node=%p", tmo->index, + tmo); + tmo->state |= PTIMER_STATE_ENQUEUED; +} + +void +launch_tmr (timer_t * tim, u64_t nsec) +{ + struct itimerspec vtim; + + vtim.it_value.tv_sec = (nsec) / NANO_PER_SECOND; + vtim.it_value.tv_nsec = (nsec) % NANO_PER_SECOND; + vtim.it_interval.tv_sec = 0; + vtim.it_interval.tv_nsec = 0; + + if (timer_settime (*tim, 0, &vtim, NULL) < 0) + { + NSPOL_LOGERR ("add_ptimer:timer_settime failed"); + } + +} + +/* + * add ptimer to rb_tree + * @param tmo: the ptimer node pointer + */ +void +add_ptimer (struct ptimer_node *tmo) +{ + if (tmo == NULL) + { + NSPOL_LOGERR ("input parameter is null"); + return; + } + enqueue_ptimer (tmo, &ptimer); + + if (ptimer.first == &tmo->node) + { + launch_tmr (&lazy_tim, tmo->info.msec * NANO_PER_MICROSECOND); + } +} + +#if 1 +/* + * cond signal ,send a ptimer message + * @param type: the message type + * @param handler: timeout handler + * @param node: the ptimer node pointer + */ +void +regedit_ptimer (enum msg_type Type, sys_timeout_handler handler, + struct ptimer_node *node) +{ + (void) handler; + (void) pthread_mutex_lock (&ptimer.lock); + if (ptimer.tail == NULL) + { + (void) pthread_mutex_unlock (&ptimer.lock); + NSPOL_LOGERR ("ptimer.tail is null"); + free (node); + node = NULL; + return; + } + ptimer.tail->msg_type = Type; + ptimer.tail->node = node; + ptimer.tail = ptimer.tail->next; + if (ptimer.head == ptimer.tail) + { + (void) pthread_mutex_unlock (&ptimer.lock); + NSPOL_LOGERR ("ptimer.head equal to ptimer.tail"); + return; + } + + (void) pthread_kill (g_timerThread_id, SIGRTMIN + 2); + + (void) pthread_mutex_unlock (&ptimer.lock); + return; +} +#endif +/* + * deal with the timeout signal + * + */ +void +deal_timeout_sig (void) +{ + struct ptimer_node *tmo; + struct timespec now; + unsigned long abs_nsec; + err_t err; + int retval; + if (ptimer.first == NULL) + { + NSPOL_LOGERR ("ptimer.first=NULL!!"); + return; + } + tmo = rb_entry (ptimer.first, struct ptimer_node, node); + retval = clock_gettime (CLOCK_MONOTONIC, &now); + if (0 != retval) + { + NSPOL_LOGERR ("clock_gettime failed]retval=%d,errno=%d", retval, errno); + } + abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec; + + // deal with all timeout point + while (time_after_eq (abs_nsec, tmo->abs_nsec)) + { + remove_ptimer (tmo, &ptimer); + + if (tmo->info.flags & PTIMER_ONESHOT) + { + } + else + { + //re-entry periodic ptimer + tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec + + tmo->info.msec * NANO_PER_MICROSECOND; + add_ptimer (tmo); + } + + //send timeout message + NSPOL_LOGDBG (INTERRUPT_DEBUG, + "ptimer happened to thread_index]index=%u", tmo->index); + if ((err = ltt_apimsg (tmo->info._phandle, (void *) tmo))) + { + NSPOL_LOGWAR (TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING, + "send timeout message failed!]errno=%d", err); + } + + if (ptimer.first == NULL) + { + NSPOL_LOGERR ("deal_timeout_sig: ptimer.first == NULL!!"); + return; + } + tmo = rb_entry (ptimer.first, struct ptimer_node, node); + } + + if (tmo->abs_nsec <= abs_nsec) + { + NSPOL_LOGERR ("tmo->abs_nsec is smaller than abs_nsec"); + return; + } + + NSPOL_LOGDBG (TIMERS_DEBUG, "TIMERSIGNAL : Launch timer for]time=%ul", + tmo->abs_nsec - abs_nsec); + launch_tmr (&lazy_tim, tmo->abs_nsec - abs_nsec); //timer interupted eveny 50ms instand by tmo->abs_nsec +} + +/* + * timeout signal handle function + * @param v: unused argument + */ +/*ptimer is already protected and used*/ + +NSTACK_STATIC void +timeout_sigaction (int sig) +{ + (void) sig; + if (!sys_arch_sem_trywait (&ptimer_lock)) + { + launch_tmr (&lazy_tim_retry, + (MIN_TIME_PICE / 5) * NANO_PER_MICROSECOND); + return; + } + + deal_timeout_sig (); + + sys_sem_signal (&ptimer_lock); + + return; +} + +/* + * initialize the ptimer buffer and timing mechanism + */ +err_t +init_ptimer (void) +{ + int i, retval; + struct sigevent timer_event; + struct sigevent timer_event1; + struct ptimer_msg *ptr; + + if (pthread_mutex_init (&ptimer.lock, NULL)) + { + NSPOL_LOGERR ("pthread_mutex_init failed"); + return ERR_MEM; + } + /*codex fix */ + if (ERR_MEM == sys_sem_new (&ptimer_lock, 1)) + { + NSPOL_LOGERR ("init_ptimer: sys_sem_new failure"); + return ERR_MEM; + } + + ptimer.active.rb_node = NULL; + ptimer.first = NULL; + + ptr = + (struct ptimer_msg *) malloc (PTIMER_MSG_BUFFER_SIZE * + sizeof (struct ptimer_msg)); + if (!ptr) + { + NSPOL_LOGERR ("init_ptimer: malloc ptimer buffer failed!"); + return ERR_MEM; + } + + int ret = + MEMSET_S (ptr, (PTIMER_MSG_BUFFER_SIZE * sizeof (struct ptimer_msg)), + 0, (PTIMER_MSG_BUFFER_SIZE * sizeof (struct ptimer_msg))); + if (EOK != ret) + { + free (ptr); + NSPOL_LOGERR ("init_ptimer: MEMSET_S ptimer buffer failed]ret=%d", ret); + return ERR_MEM; + } + + for (i = 0; i < PTIMER_MSG_BUFFER_SIZE - 1; i++) + { + ptr[i].next = &ptr[(i + 1)]; + ptr[(i + 1)].prev = &ptr[i]; + } + + ptr[i].next = &ptr[0]; + ptr[0].prev = &ptr[i]; + ptimer.head = ptimer.tail = &ptr[0]; + retval = + MEMSET_S (&timer_event, sizeof (struct sigevent), 0, + sizeof (struct sigevent)); + if (EOK != retval) + { + free (ptr); + ptr = NULL; + NSPOL_LOGERR ("MEMSET_S failed]ret=%d", retval); + return ERR_VAL; + } + timer_event.sigev_notify = SIGEV_SIGNAL; + timer_event.sigev_signo = SIGRTMIN; + timer_event.sigev_value.sival_ptr = (void *) &lazy_tim; + timer_event1 = timer_event; + timer_event1.sigev_value.sival_ptr = (void *) &lazy_tim_retry; + + if (timer_create (CLOCK_MONOTONIC, &timer_event, &lazy_tim) < 0) + { + free (ptr); + ptr = NULL; + NSPOL_LOGERR ("ptimer_init: timer_create failed!"); + return ERR_VAL; + } + + if (timer_create (CLOCK_MONOTONIC, &timer_event1, &lazy_tim_retry) < 0) + { + free (ptr); + ptr = NULL; + NSPOL_LOGERR ("ptimer_init: timer_create failed!"); + return ERR_VAL; + } + + return ERR_OK; +} + +NSTACK_STATIC err_t +process_timeout_msg (struct ptimer_msg * msg) +{ + struct ptimer_node *tmo = msg->node; + struct timespec now; + + switch (msg->msg_type) + { + case SYS_PTIMEROUT_MSG: + if (tmo) + { + int retval = clock_gettime (CLOCK_MONOTONIC, &now); + if (0 != retval) + { + NSPOL_LOGERR ("clock_gettime failed]retval=%d,errno=%d", retval, + errno); + } + tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec + + tmo->info.msec * NANO_PER_MICROSECOND; + add_ptimer (tmo); + } + else + { + NSPOL_LOGERR ("process_timeout_msg: rb_node is NULL!"); + return ERR_MEM; + } + + break; + case SYS_UNPTIMEROUT_MSG: + if (del_ptimer (msg) != ERR_OK) + { + NSPOL_LOGERR + ("process_timeout_msg: can not find the timeout event(oops)!"); + } + + break; + default: + NSPOL_LOGERR + ("process_timeout_msg: oops! lwip timeout_thread receive unacquainted message!"); + break; + } + + return ERR_OK; +} + +void +ptimer_thread (void *arg) +{ + LWIP_UNUSED_ARG (arg); + int sig, ret = -1; + sigset_t waitset; + sigset_t oset; + struct ptimer_msg *msg; + + if (0 != sigemptyset (&waitset)) + { + NSTCP_LOGERR ("sigemptyset function call error"); + return; + } + + if (0 != sigaddset (&waitset, SIGRTMIN)) + { + NSTCP_LOGERR ("sigaddset function call error"); + return; + } + + if (0 != sigaddset (&waitset, SIGRTMIN + 2)) + { + NSTCP_LOGERR ("sigaddset function call error"); + return; + } + + (void) pthread_sigmask (SIG_BLOCK, &waitset, &oset); + + (void) pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + (void) pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + NSPOL_LOGDBG (TIMERS_DEBUG, "ptimer: init done !"); + + if (!g_nstack_timer_tick.tick_ptr) + { + NSTCP_LOGERR ("g_nstack_timer_tick not inited"); + return; + } + (void) gettimeofday (&g_nstack_timer_tick.ref_time, NULL); + g_nstack_timer_tick.interval = 100; + *g_nstack_timer_tick.tick_ptr = 0; + g_nstack_timer_tick.ref_tick = 0; + while (1) + { + ret = sigwait (&waitset, &sig); + (void) nsfw_thread_chk (); // will only return TRUE, no need to check return value + if (ret != -1) + { + /* for timer expirt handle */ + if (SIGRTMIN == sig) + { + timeout_sigaction (sig); + continue; + } + } + else + { + continue; + } + + while (1) + { + (void) pthread_mutex_lock (&ptimer.lock); + if (ptimer.head == ptimer.tail) + { + (void) pthread_mutex_unlock (&ptimer.lock); + break; + } + + msg = ptimer.head; + ptimer.head = ptimer.head->next; + (void) pthread_mutex_unlock (&ptimer.lock); + + sys_arch_sem_wait (&ptimer_lock, 0); + + if (process_timeout_msg (msg) != ERR_OK) + { + NSPOL_LOGERR ("oops: ptimer_thread panic!"); + } + + sys_sem_signal (&ptimer_lock); + } + } +} + +void +timeout_phandler (void *act, void *arg) +{ + struct ptimer_node *tmo = arg; + if (act == NULL) + { + NSPOL_LOGERR ("input parameter arg is null"); + return; + } + + NSPOL_LOGINF (TIMERS_DEBUG, "Timer expire @timeout_phandler Handle %p", + tmo->info._phandle); + if (tmo->info.flags & PTIMER_ONESHOT) + { + sys_timeout_handler handle = act; + handle (tmo->info.ctx); + return; + } + else + { + NSPOL_LOGINF (TIMERS_DEBUG, + "Timer expire error @timeout_phandler Handle %p", + tmo->info._phandle); + } +} diff --git a/stacks/lwip_stack/lwip_src/core/unmatch_version.c b/stacks/lwip_stack/lwip_src/core/unmatch_version.c new file mode 100644 index 0000000..6c8cad3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/unmatch_version.c @@ -0,0 +1,59 @@ +/* +* +* 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 "nsfw_mem_api.h" +#include "nstack_share_res.h" +#include "nstack_securec.h" + +char *g_nstack_ver_info = NULL; + +int +init_unmatch_version (void) +{ + int ret; + nsfw_mem_zone mzone; + + ret = + STRCPY_S (mzone.stname.aname, NSFW_MEM_NAME_LENGTH, NSTACK_VERSION_SHM); + if (EOK != ret) + { + NSPOL_LOGERR ("STRCPY_S fail]ret=%d", ret); + return -1; + } + mzone.stname.entype = NSFW_SHMEM; + mzone.isocket_id = -1; + mzone.length = + NSTACK_VERSION_LEN + MAX_UNMATCH_VER_CNT * sizeof (unmatch_ver_info_t); + mzone.ireserv = 0; + + char *version = (char *) nsfw_mem_zone_create (&mzone); + if (NULL == version) + { + NSPOL_LOGERR ("Failed to create unmatch_version memory"); + return -1; + } + + ret = STRCPY_S (version, NSTACK_VERSION_LEN, NSTACK_VERSION); + if (EOK != ret) + { + NSPOL_LOGERR ("STRCPY_S NSTACK_VERSION fail]ret=%d", ret); + return -1; + } + + g_nstack_ver_info = version; + + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h b/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h new file mode 100644 index 0000000..0c88139 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h @@ -0,0 +1,64 @@ +/* +* +* 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. +*/ + +#ifndef _NSTACK_CONFIG_COMMON_H_ +#define _NSTACK_CONFIG_COMMON_H_ + +#include "ip_module_api.h" + +#define MAX_IP_MODULE_BUFF_SIZE 1024*1024 + +/* ip module config types */ +#define IP_MODULE_TYPE_IP "ip" +#define IP_MODULE_TYPE_NETWORK "network" +#define IP_MODULE_TYPE_PORT "port" +#define IP_MODULE_TYPE_SETLOG "setlog" +#define IP_MODULE_TYPE_SNAPSHOT "snapshot" +#define IP_MODULE_TYPE_SETTRACE "settrace" + +#define TCP_MODULE_TYPE_SET_OOS_LEN "ooslen" + +#define IP_MODULE_NAME "./nStackCtrl: " +#define IP_MODULE_INVALID_ARGUMENT_S "invalid argument -- \"%s\"\n" +#define IP_MODULE_MORE_OPTION "need more options -- " +#define IP_MODULE_LESS_OPTION "no need option -- " + +/* Error codes */ +#define IP_MODULE_OK 0 +#define IP_MODULE_DATA_ERROR 1 +#define IP_MODULE_DATA_NOT_EXIST 2 + +struct config_param +{ + int action; + char type[IP_MODULE_LENGTH_256]; + char name[IP_MODULE_LENGTH_256]; + char value[IP_MODULE_LENGTH_64]; + char container_id[IP_MODULE_LENGTH_256]; + int error; + + char error_desc[NSCRTL_ERRBUF_LEN]; + + u64 traceid; +}; + +struct config_data +{ + struct config_param param; + char json_buff[MAX_IP_MODULE_BUFF_SIZE - sizeof (struct config_param)]; +}; + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h b/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h new file mode 100644 index 0000000..779ace8 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h @@ -0,0 +1,26 @@ +/* +* +* 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. +*/ + +#ifndef _CONFIGURATION_READER_H +#define _CONFIGURATION_READER_H +#include <semaphore.h> +#include "config_common.h" + +struct config_data *get_config_data (); +int get_str_value (const char *arg); +int setlog_level_value (const char *param, const char *value); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h b/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h new file mode 100644 index 0000000..e83c607 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h @@ -0,0 +1,39 @@ +/* +* +* 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. +*/ + +#ifndef _CONTAINER_IP_H +#define _CONTAINER_IP_H +#include "ip_module_api.h" +#include "json.h" + +struct ip_action_param +{ + char container_id[IP_MODULE_LENGTH_256]; + char port_name[IP_MODULE_LENGTH_256]; +}; + +void free_container (struct container_ip *container, bool_t only_free); +struct container_port *parse_port_obj (struct json_object *port_obj); +struct container_ip *parse_container_ip_json (char *param); +int add_container (struct container_ip *container); +struct container_ip *get_container_by_container_id (char *container_id); + +int del_port (char *container_id, char *port_name); +struct container_port *get_port (char *container_id, char *port_name); +struct container_port *get_port_from_container (struct container_port *port); +int getIpCfgAll (char *jsonBuf, size_t size); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h b/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h new file mode 100644 index 0000000..488e13e --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h @@ -0,0 +1,222 @@ +/* +* +* 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. +*/ + +#ifndef _IP_MODULE_API_H_ +#define _IP_MODULE_API_H_ +#include "types.h" + +typedef int bool_t; +#define IP_MODULE_TRUE 1 +#define IP_MODULE_FALSE 0 +#define IP_MODULE_LENGTH_32 32 +#define IP_MODULE_LENGTH_64 64 +#define IP_MODULE_LENGTH_256 256 +#define IP_MODULE_LENGTH_1024 1024 +#define IP_MODULE_SUBNET_MASK_LEN IP_MODULE_LENGTH_32 +#define IP_MODULE_MAX_NAME_LEN IP_MODULE_LENGTH_256 +#define IP_MODULE_PORT_JSON_LEN (2048 * 2) +#define IP_MODULE_NETWORK_JSON_LEN (2048 * 2) +#define MAX_NETWORK_COUNT IP_MODULE_LENGTH_64 +#define MAX_NETWORK_IP_COUNT IP_MODULE_LENGTH_1024 +#define MAX_NETWORK_NUM (MAX_NETWORK_COUNT * 2) +COMPAT_PROTECT (MAX_NETWORK_NUM, 128); +#define MAX_PORT_NUM (MAX_NETWORK_IP_COUNT * 2) +COMPAT_PROTECT (MAX_PORT_NUM, 2048); +#define NSCRTL_ERRBUF_LEN IP_MODULE_LENGTH_256 + +#define INVALID_EXPIRE_TIME 0x7FFFFFFF +#define NSTACLCTRL_MAX_TRY_TIMES 60 + +/*sockaddr_un.sun_path is an array of 108 bytes*/ +#define IP_MODULE_MAX_PATH_LEN 108 + +typedef enum enumADERRCODE +{ + NSCRTL_OK = 0, + NSCRTL_ERR, + NSCRTL_RD_NOT_EXIST, + NSCRTL_RD_EXIST = 3, + NSCRTL_INPUT_ERR, + NSCRTL_STATUS_ERR, + NSCRTL_NETWORK_COUNT_EXCEED, + NSCRTL_IP_COUNT_EXCEED, + NSCRTL_FREE_ALL_PORT, //when all ports in container were deleted, need to free container. + + NSCRTL_MAX_ERR = 127 +} NSCRTL_ERR_CODE; + +#define NSOPR_SET_ERRINFO(_errno, fmt, ...) \ + {\ + struct config_data* cf_data = get_config_data(); \ + if (cf_data)\ + {\ + size_t len_error_desc = strlen(cf_data->param.error_desc); \ + cf_data->param.error = _errno; \ + if ((_errno != NSCRTL_OK) && (len_error_desc < NSCRTL_ERRBUF_LEN))\ + {\ + if (-1 == (SNPRINTF_S(cf_data->param.error_desc + len_error_desc, \ + NSCRTL_ERRBUF_LEN - len_error_desc, NSCRTL_ERRBUF_LEN - len_error_desc - 1, fmt, ## __VA_ARGS__)))\ + {\ + NSOPR_LOGERR("SNPRINTF_S failed]"); \ + } \ + } \ + } \ + } \ + +struct ref_nic +{ + struct ref_nic *next; + char nic_name[IP_MODULE_MAX_NAME_LEN]; +}; + +struct phy_net +{ + struct ref_nic *header; + char bond_name[IP_MODULE_MAX_NAME_LEN]; + int bond_mode; +}; + +struct container_port_ip_cidr +{ + struct container_port_ip_cidr *next; + unsigned int ip; + unsigned int mask_len; +}; + +struct container_multicast_id +{ + struct container_multicast_id *next; + unsigned int ip; +}; + +typedef struct +{ + char port_json[IP_MODULE_PORT_JSON_LEN]; +} port_buffer; + +struct container_port +{ + struct container_port *next; + struct container_port_ip_cidr *ip_cidr_list; + struct container_multicast_id *multicast_list; + char port_name[IP_MODULE_MAX_NAME_LEN]; + port_buffer *buffer; +}; + +#define get_port_json(obj) obj->buffer->port_json + +struct container_ip +{ + struct container_ip *next; + struct container_port *ports_list; + char container_id[IP_MODULE_MAX_NAME_LEN]; +}; + +struct container_list +{ + struct container_ip *header; +}; + +struct ip_subnet +{ + struct ip_subnet *next; + unsigned int subnet; + unsigned int mask_len; +}; + +typedef struct +{ + char network_json[IP_MODULE_NETWORK_JSON_LEN]; +} network_buffer; + +struct network_configuration +{ + struct network_configuration *next; + struct phy_net *phy_net; + struct ip_subnet *ip_subnet; + char network_name[IP_MODULE_MAX_NAME_LEN]; + char type_name[IP_MODULE_MAX_NAME_LEN]; + network_buffer *buffer; +}; + +#define get_network_json(obj) obj->buffer->network_json + +struct network_list +{ + struct network_configuration *header; +}; + +void ip_subnet_print (struct ip_subnet *subnet); +bool_t is_in_same_network (unsigned int src_ip, unsigned int dst_ip); +bool_t is_ip_match_netif (unsigned int ip, char *netif_name); +bool_t is_ip_exist (unsigned int ip); +struct network_configuration *get_network_list (); +inline struct network_configuration *get_network_by_ip_with_tree (unsigned int + ip); + +/* "type" option */ +typedef enum +{ + IP_MODULE_NETWORK, + IP_MODULE_IP, + IP_MODULE_NETWORK_ALL, + IP_MODULE_IP_ALL, + IP_MODULE_ALL, +} ip_module_type; + +/* "action" option */ +typedef enum +{ + IP_MODULE_OPERATE_NULL, + IP_MODULE_OPERATE_ADD, + IP_MODULE_OPERATE_DEL, + IP_MODULE_OPERATE_QUERY, + IP_MODULE_OPERATE_SET, + IP_MODULE_GET_VERSION, + IP_MODULE_QUERY_NET, + IP_MODULE_MAX, //new type should be added before IP_MODULE_MAX + IP_MODULE_BOTTOM = 0xFFFFFFFF +} ip_module_operate_type; + +typedef int (*post_to_fn) (void *arg, ip_module_type type, + ip_module_operate_type operate_type); +typedef int (*add_netif_ip_fn) (char *netif_name, unsigned int ip, + unsigned int mask); +typedef int (*del_netif_ip_fn) (char *netif_name, unsigned int ip); + +typedef struct +{ + post_to_fn post_to; + add_netif_ip_fn add_netif_ip; + del_netif_ip_fn del_netif_ip; +} output_api; + +void regist_output_api (output_api * api); +output_api *get_output_api (); +int init_configuration_reader (); +int process_post (void *arg, ip_module_type type, + ip_module_operate_type operate_type); +int process_configuration (void *arg, ip_module_type type, + ip_module_operate_type operate_type); + +port_buffer *malloc_port_buffer (); +void free_port_buffer (port_buffer * buffer); +network_buffer *malloc_network_buffer (); +void free_network_buffer (network_buffer * buffer); +int get_network_json_data (); +int get_ip_json_data (); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/network.h b/stacks/lwip_stack/lwip_src/include/ip_module/network.h new file mode 100644 index 0000000..117b71c --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/network.h @@ -0,0 +1,36 @@ +/* +* +* 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. +*/ + +#ifndef _NETWORK_H +#define _NETWORK_H +#include "ip_module_api.h" + +void free_network_configuration (struct network_configuration *network, + bool_t only_free); +struct network_configuration *parse_network_obj (struct json_object + *network_obj); +struct network_configuration *parse_network_json (char *param, + struct network_configuration + *network_list); +int add_network_configuration (struct network_configuration + *network_configuration); +struct network_configuration *get_network_by_name (char *name); +struct network_configuration *get_network_by_nic_name (char *name); +int del_network_by_name (char *name); +int get_network_all (char *jsonBuf, size_t size); +int nic_already_init (const char *nic_name); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h b/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h new file mode 100644 index 0000000..ef0ac37 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h @@ -0,0 +1,77 @@ +/* +* +* 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. +*/ + +#ifndef __TRP_RB_TREE_H__ +#define __TRP_RB_TREE_H__ + +typedef void *trp_key_t; +typedef void *trp_data_t; + +#define RB_RED 0 +#define RB_BLACK 1 + +typedef int (*key_compare) (trp_key_t left, trp_key_t right); // return > 0 left > right, return 0 left = right, return < 0 left < right + +typedef struct trp_rb_node +{ + struct trp_rb_node *rb_parent; + struct trp_rb_node *rb_right; + struct trp_rb_node *rb_left; + key_compare key_compare_fn; + trp_key_t key; + trp_data_t data; + unsigned int color; +} trp_rb_node_t; + +typedef struct trp_rb_root +{ + struct trp_rb_node *rb_node; +} trp_rb_root_t; + +int trp_rb_insert (trp_key_t, trp_data_t, trp_rb_root_t *, key_compare); +int trp_rb_insert_allow_same_key (trp_key_t, trp_data_t, trp_rb_root_t *, + key_compare); +void trp_rb_erase (trp_key_t, trp_rb_root_t *, key_compare key_compare_fn); +void trp_rb_erase_with_data (trp_key_t key, trp_data_t data, + trp_rb_root_t * root, int count, + key_compare key_compare_fn); + +static inline trp_rb_node_t * +trp_rb_search (trp_key_t key, trp_rb_root_t * root, + key_compare key_compare_fn) +{ + trp_rb_node_t *node = root->rb_node; + int ret; + while (node) + { + ret = key_compare_fn (node->key, key); + if (0 < ret) + { + node = node->rb_left; + } + else if (0 > ret) + { + node = node->rb_right; + } + else + { + return node; + } + } + + return NULL; +} +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h b/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h new file mode 100644 index 0000000..ae5c31f --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h @@ -0,0 +1,162 @@ +/* +* +* 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. +*/ + +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "spl_opt.h" +#include "spl_def.h" +#include "ip_module_api.h" +#include "stackx_ip_addr.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +/* Forward declaration to not include netif.h */ +struct netif; +#if BYTE_ORDER == BIG_ENDIAN + +/** Set an IPaddress given by the four byte-parts */ +#define SPL_IP4_ADDR(ipaddr, a, b, c, d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else + +/** Set an IPaddress given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define SPL_IP4_ADDR(ipaddr, a, b, c, d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** memcpy-like copying of IPaddresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) MEMCPY_S(dest, sizeof(ip_addr_t), src, sizeof(ip_addr_t)) +#endif + +/** Copy IPaddress - faster than spl_ip_addr_set: no NULL check */ +#define spl_ip_addr_copy(dest, src) ((dest).addr = (src).addr) + +/** Safely copy one IPaddress to another (src may be NULL) */ +#define spl_ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) + +/** Safely copy one IPaddress to another and change byte order + * from host- to network-order. */ +#define spl_ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + htonl((src)->addr))) + +/** Get the network address by combining host address with netmask */ +#define spl_ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IPaddress 1 + * @arg addr2 IPaddress 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define spl_ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) + +/* && ((dest)->addr & tmp->netmask.addr) == (tmp->ip_addr.addr & tmp->netmask.addr) */ +/* add "netif = netif->root; \"*/ +#define ip_net_netif_cmp( dest, netif) ({ \ + netif = netif->root; \ + struct netif* tmp = netif; \ + int find = 0; \ + while(tmp) \ + { \ + if (is_in_same_network((dest)->addr, tmp->ip_addr.addr)) \ + { \ + netif->ip_addr.addr = tmp->ip_addr.addr; \ + netif->netmask.addr = tmp->netmask.addr; \ + find = 1; \ + break; \ + } \ + if (netif->is_out) \ + { \ + break; \ + } \ + tmp = tmp->vnext; \ + } \ + (!!find); \ + }) + +/* Check if netif match dest , if not , find one and swap */ +/* add "netif = netif->root; \"*/ + +#define ip_addr_netif_cmp_and_swap( dest, pnetif) ({ \ + pnetif = pnetif->root; \ + struct netif* tmp = pnetif; \ + int find = 0; \ + while(tmp) \ + { \ + if ((dest)->addr == tmp->ip_addr.addr) \ + { \ + pnetif->ip_addr.addr = tmp->ip_addr.addr; \ + pnetif->netmask.addr = tmp->netmask.addr; \ + find = 1; \ + break; \ + } \ + if (pnetif->is_out) \ + { \ + break; \ + } \ + tmp = tmp->vnext; \ + } \ + (!!find); \ + }) + +#define ip_addr_netif_cmp( dest, pnetif) ({ \ + pnetif = pnetif->root; \ + struct netif* tmp = pnetif; \ + int find = 0; \ + while(tmp) \ + { \ + if ((dest)->addr == tmp->ip_addr.addr) \ + { \ + find = 1; \ + break; \ + } \ + tmp = tmp->vnext; \ + } \ + (!!find); \ + }) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/common.h b/stacks/lwip_stack/lwip_src/include/netif/common.h new file mode 100644 index 0000000..45e9c8f --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/common.h @@ -0,0 +1,233 @@ +/* +* +* 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. +*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ +#include <stddef.h> /* for size_t */ +#include "stackx_common.h" +#include "netif.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +//yyq + +/* define common names for structures shared between server and client */ + +#define MP_STACKX_INSTANCE_POLL_NAME "VppTCP_instance_poll" +#define MP_STACKX_PORT_ZONE "VppTCP_stackx_port_zone" +#define MP_STACKX_PORT_INFO "VppTCP_stackx_port_info" +#define MP_MEMPOLL_RX_NAME "VppTCP_MBUF_%u_%u_RX" +#define MP_MEMPOLL_RXMSG_NAME "VppTCP_MSG_%u_%u_RX" +#define MP_MEMPOLL_TX_NAME "VppTCP_MBUF_TX" +#define MP_MEMPOLL_SEG_NAME "VppTCP_MBUF_SEG" +#define MP_STACKX_MSG_NAME "VppTCP_msg" +#define MP_STACKX_RING_NAME "VppTCP_%u_ring" +#define MP_STACKX_LRING_NAME "VppTCP_%u_lring" + +#define MP_STACKX_BIT_SET_NAME "%s_bit_set" + +#define MP_STACKX_SOCKET_FREE_LIST_NAME "VppTCP_socket_list" + +#define MP_NETIF_LIST_NAME "VppTCP_Netif_list" + +/* + move sharemem create from App to nstackMain +advice rename app_tx_mbuf to VppTCP_APP_TXBUF_POOL +*/ +#define MP_STACKX_APP_TXBUF_POOL "app_tx_mbuf" + +#define MP_MEMPOLL_TCP_BUFF_NAME "VppTCP_MBUF_%u_TCP_BUFF" + +extern int spl_snprintf (char *buffer, int buflen, const char *format, ...); + +/*According to the number of network cards, the establishment of recv lring, + *each separate, each proc_id each NIC queue independent lring + */ +static inline const char * +get_mempoll_rx_name (unsigned proc_id, unsigned nic_id) +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) + * the id may reach 65535, need add more space*/ + static char buffer[sizeof (MP_MEMPOLL_RX_NAME) + 32]; + + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_RX_NAME, proc_id, nic_id); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_mempoll_rxmsg_name (unsigned proc_id, unsigned nic_id) +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) + * the id may reach 65535, need add more space*/ + static char buffer[sizeof (MP_MEMPOLL_RXMSG_NAME) + 32]; + + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_RXMSG_NAME, proc_id, nic_id); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_mempoll_ring_name (unsigned proc_id) +{ + static char buffer[sizeof (MP_STACKX_RING_NAME) + 16]; + + int retVal = + spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_RING_NAME, proc_id); + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_mempoll_lring_name (unsigned proc_id) +{ + static char buffer[sizeof (MP_STACKX_LRING_NAME) + 16]; + + int retVal = + spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_LRING_NAME, proc_id); + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_mempoll_msg_name () +{ + static char buffer[sizeof (MP_STACKX_MSG_NAME) + 16]; + + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_MSG_NAME); + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_mempoll_tx_name () +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char buffer[sizeof (MP_MEMPOLL_TX_NAME) + 16]; + + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_TX_NAME); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_mempoll_seg_name () +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char buffer[sizeof (MP_MEMPOLL_SEG_NAME) + 16]; + + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_SEG_NAME); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_memStatusBitSet_name (const char *name, unsigned int num) +{ + static char buffer[64]; + + int retVal = + spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_BIT_SET_NAME "%d", + name, num); + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_memNameWithProc (const char *name) +{ + static char buffer[64]; + + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, "%s", name); + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char * +get_memInstancePoll_name (unsigned int type) +{ + static char buffer[sizeof (MP_STACKX_INSTANCE_POLL_NAME) + 32]; + int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, "%s" "%d", + MP_STACKX_INSTANCE_POLL_NAME, type); + if (-1 == retVal) + { + NSPOL_LOGERR ("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h b/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h new file mode 100644 index 0000000..bcf4129 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h @@ -0,0 +1,103 @@ +/* +* +* 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. +*/ + +#ifndef _KNI_PROC_H_ +#define _KNI_PROC_H_ +#include <rte_kni.h> +#include <rte_mempool.h> +#include <rte_mbuf.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define KNI_MAX_KTHREAD 32 + +/* the kni is runned on the lcore from below on */ +#define DEFAULT_KNI_LCORE_BASE 24 + +/* Structure of kni para */ +struct disp_kni_para +{ + u8_t queue_id; + u8_t port_id; +}; + +/* + * Structure of port parameters + */ +struct kni_port_params +{ + uint8_t port_id; /* Port ID */ + unsigned lcore_rx; /* lcore ID for RX */ + unsigned lcore_tx; /* lcore ID for TX */ + uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */ + uint32_t nb_kni; /* Number of KNI devices to be created */ + unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */ + struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */ + struct rte_mempool *kni_pktmbuf_pool; + u8_t ip_reconfigured; +} __rte_cache_aligned; + +/* Structure type for storing kni interface specific stats */ +struct kni_interface_stats +{ + /* number of pkts received from NIC, and sent to KNI */ + uint64_t rx_packets; + + /* number of pkts received from NIC, but failed to send to KNI */ + uint64_t rx_dropped; + + /* number of pkts received from KNI, and sent to NIC */ + uint64_t tx_packets; + + /* number of pkts received from KNI, but failed to send to NIC */ + uint64_t tx_dropped; +}; + +/* External interface for initilizing KNI subsystem */ +int kni_proc_init (enum rte_proc_type_t proc_type, int proc_id, u32_t pmask, + struct kni_port_params **kni_para); + +int kni_proc_init_secondary (int proc_id, int port_id); +/* External interface for destroy KNI subsystem */ +void kni_proc_free (void); + +/* External interface for kni tx thread entry */ +void kni_tx_thread_cycle (void *arg); + +int kni_config_net (void); +void kni_handler_eth_operate_request (int port); + +/* External interface for commiting packet to kni device */ +void kni_dispatch_to_kernel (uint8_t port_id, + struct rte_mbuf *pkts_burst[], uint8_t nb_rx); + +/* the lcore kni tx/rx thread run on */ +unsigned kni_get_tx_lcore (uint8_t port_id); +unsigned kni_get_rx_lcore (uint8_t port_id); + +void init_kni (void); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /*#ifndef _KNI_PROC_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h b/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h new file mode 100644 index 0000000..99c3bc6 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h @@ -0,0 +1,80 @@ +/* +* +* 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. +*/ + +#ifndef SC_DPDK_H_ +#define SC_DPDK_H_ + +#include <pbuf.h> +#include <sharedmemory.h> + +#include "lwip/etharp.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NSTACK_CONFIG_SHM "nstack_config" + +#define MBUF_DATA_SIZE 2048 +#define MBUF_SIZE (MBUF_DATA_SIZE + sizeof(struct common_mem_mbuf) + COMMON_PKTMBUF_HEADROOM) + +extern int g_nstack_bind_cpu; + +inline uint16_t spl_mbuf_refcnt_update (void *mbuf, int16_t value); +struct stack_proc_content *get_stack_proc_content (); + +inline int spl_msg_malloc (data_com_msg ** p_msg_entry); +#define spl_msg_free(p_msg_entry) msg_free(p_msg_entry) +struct spl_pbuf *spl_mbuf_malloc (uint16_t len, spl_pbuf_type type, + u16_t * count); + +inline void spl_mbuf_free (void *mbuf); + +inline int spl_set_lcore_id (unsigned dest_lcore_id); + +static inline unsigned +spl_get_lcore_id () +{ + unsigned core_id = 0; + +#if (DPDK_MODULE != 1) +#ifdef HAL_LIB +#else + core_id = rte_lcore_id (); +#endif + if (core_id >= MAX_THREAD_NUM) + { + core_id = 0; + } +#endif + + return core_id; +} + +int set_share_config (); + +int init_instance (); + +void printmeminfo (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif /* SERVER_DPDK_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h b/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h new file mode 100644 index 0000000..0a92ea0 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h @@ -0,0 +1,148 @@ +/* +* +* 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. +*/ + +#ifndef SHAREDMEMORY_H_ +#define SHAREDMEMORY_H_ +#include "stackxopts.h" +#include <sys/types.h> +#include <semaphore.h> +//#include "stackx/raw.h" +#include "tcp.h" +#include "udp.h" +//#include "stackx/ip.h" +#include "spl_err.h" +#include "list.h" +#include "arch/queue.h" +#include "spl_opt.h" +#include "stackx/spl_ip_addr.h" + +#include "stackx/spl_api.h" +#include <arch/sys_arch.h> +#include "common_mem_api.h" +//#include "stackx/memp.h" +#include "stackx_instance.h" + +#include "hal_api.h" +#ifdef HAL_LIB +#else +#include "rte_ring.h" +#endif + +/** Description for a task waiting in select */ +struct stackx_select_cb +{ + /** Pointer to the next waiting task */ + union + { + struct stackx_select_cb *next; + PTR_ALIGN_TYPE next_a; + }; + + /** Pointer to the previous waiting task */ + union + { + struct stackx_select_cb *prev; + PTR_ALIGN_TYPE prev_a; + }; + + /** semaphore to wake up a task waiting for select */ + //sys_sem_t sem; + union + { + sys_sem_t_v1 sem; + PTR_ALIGN_TYPE sem_a; + }; + + /** readset passed to select */ + fd_set readset; + + /** writeset passed to select */ + fd_set writeset; + + /** unimplemented: exceptset passed to select */ + fd_set exceptset; + + /** don't signal the same semaphore twice: set to 1 when signalled */ + volatile int sem_signalled; + + uint8_t pad_64bit[4]; +}; +/** From epoll.h: Definition of struct stackx_sock and stackx_select_cb ---------End*/ + +enum tcp_run_type +{ + TCP_MUTIPL_INSTANCE = 0, + TCP_MASTER_WORKER, + TCP_DISTRIBUTOR_WORKER, + TCP_RUN_TO_COMPETE, + TCP_PROC_TYPE_END +}; + +enum proc_run_type +{ + PROC_MAIN_RUN_TYPE = 0, + PROC_BACKUP_RUN_TYPE, + PROC_RUN_TYPE_END +}; + +struct linux_port_info +{ + char if_name[HAL_MAX_NIC_NAME_LEN]; + char ip_addr_linux[18]; //uint32_t ip_addr_linux; + char mask_linux[18]; //uint32_t mask_linux; + char bcast_linux[18]; //uint32_t bcast_linux; + char mac_addr[20]; //struct ether_addr mac_addr; + hal_hdl_t hdl; +}; + +struct stackx_port_info +{ + struct stackx_port_info *next_use_port; + struct linux_port_info linux_ip; +}; + +struct stackx_port_zone +{ + unsigned int port_num; + unsigned int bonded_port_num; + struct stackx_port_info *stackx_one_port; +}; + +struct select_cb_entry +{ + struct stackx_select_cb select_cb; + + union + { + sem_t semForSelect; + ALIGN_TYPE pad_64bit[4]; + }; + + union + { + struct select_cb_entry *pre_empty_entry; + PTR_ALIGN_TYPE pre_empty_entry_a; + }; + + union + { + struct select_cb_entry *next_empty_entry; + PTR_ALIGN_TYPE next_empty_entry_a; + }; + +}; + +#endif /* SHAREDMEMORY_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h b/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h new file mode 100644 index 0000000..ca56663 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h @@ -0,0 +1,114 @@ +/* +* +* 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. +*/ + +#ifndef SPL_HAL_H_ +#define SPL_HAL_H_ + +#include "hal_api.h" +#include "netif.h" +#include "nsfw_maintain_api.h" +#include "stackx_spl_share.h" +#include "stackx_pbuf_comm.h" +#include "netifapi.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +int spl_hal_init (int argc, char *argv[]); +int spl_hal_port_init (); + +int spl_hal_stats_display (struct netif *pnetif, char *str, u32_t len, + char *json, u32_t json_len); + +err_t spl_hal_output (struct netif *netif, struct pbuf *buf); +void spl_hal_input (struct netif *netif, struct spl_pbuf **buf); + +inline u16_t spl_hal_recv (struct netif *netif, u8_t id); + +int spl_hal_tx_ip_cksum_enable (); +int spl_hal_tx_udp_cksum_enable (); +int spl_hal_tx_tcp_cksum_enable (); + +u32 spl_hal_is_nic_exist (const char *name); + +int spl_hal_is_bond_netif (struct netif *pnetif); + +static inline void +spl_do_dump (struct spl_pbuf *p, u16 direction) +{ + struct spl_pbuf *q = p; + while (q) + { + ntcpdump (q->payload, q->len, direction); + q = q->next; + } +} + +/* information of bond*/ +#define MAX_BOND_PORT_NUM 4 + +/* information of one bond port */ +struct bond_set +{ + char bond_port_name[HAL_MAX_NIC_NAME_LEN]; + char slave_ports[HAL_MAX_SLAVES_PER_BOND][HAL_MAX_NIC_NAME_LEN]; + u8_t slave_port_cnt; +}; + +#define NETIF_ETH_ADDR_LEN 6 + +/* information of all bond ports */ +struct bond_ports_info +{ + u8_t cnt; + struct bond_set ports[MAX_BOND_PORT_NUM]; +}; + +struct ether_addr +{ + u8_t addr_bytes[NETIF_ETH_ADDR_LEN]; + +}; + +struct netif *get_netif_by_ip (unsigned int ip); +struct netif *netif_check_broadcast_addr (spl_ip_addr_t * addr); +struct netifExt *getNetifExt (u16_t id); +int netifExt_add (struct netif *netif); + +int add_netif_ip (char *netif_name, unsigned int ip, unsigned int mask); +int del_netif_ip (char *netif_name, unsigned int ip); + +err_t spl_netifapi_netif_add (struct netif *pnetif, + spl_ip_addr_t * ipaddr, + spl_ip_addr_t * netmask, + spl_ip_addr_t * gw, + void *state, + netif_init_fn init, + netif_input_fn input, + netifapi_void_fn voidfunc); +struct netif *find_netif_by_if_name (char *if_name); +void ethernetif_packets_input (struct netif *pstnetif); +err_t ethernetif_init (struct netif *pnetif); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif /* SPL_HAL_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h b/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h new file mode 100644 index 0000000..584ab06 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h @@ -0,0 +1,90 @@ +/* +* +* 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. +*/ + +#ifndef __internal_msg_h__ +#define __internal_msg_h__ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#include "nsfw_msg.h" +#include "netif.h" +#include "lwip/netifapi.h" +#include "ip_module_api.h" + +enum netif_msg_type +{ + NETIF_DO_ADD, + NETIF_MSG_API_MAX = MAX_MINOR_TYPE +}; + +/* NETIF_DO_ADD */ +typedef struct msg_add_netif_T +{ + void (*function) (struct msg_add_netif_T * m); + struct netif *netif; + spl_ip_addr_t *ipaddr; + spl_ip_addr_t *netmask; + spl_ip_addr_t *gw; + void *state; + netif_init_fn init; + netif_input_fn input; + netifapi_void_fn voidfunc; + /* no need to extend member */ +} msg_add_netif; + +typedef struct +{ + ip_module_type type; + ip_module_operate_type operate_type; + void *arg; +} msg_ip_module; + +typedef struct msg_internal_callback_T +{ + void (*function) (void *ctx); + void *ctx; +} msg_internal_callback; + +enum timer_msg_type +{ + TIMER_MSG_TIMEOUT, + TIMER_MSG_CLEAR, + TIMER_MSG_MAX = MAX_MINOR_TYPE +}; + +typedef struct msg_timer_T +{ + void *act; + void *arg; +} msg_timer; + +enum mt_msg_type +{ + MT_MSG_VER_MGR, + MT_MSG_MAX = MAX_MINOR_TYPE +}; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __internal_msg_h__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h new file mode 100644 index 0000000..ea63e90 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h @@ -0,0 +1,276 @@ +/* +* +* 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. +*/ + +#ifndef __SPL_API_H__ +#define __SPL_API_H__ + +#include "opt.h" +#include "common_mem_base_type.h" +#include <stddef.h> /* for size_t */ +#include "arch/queue.h" +#include "arch/sys_arch.h" +#include "arch/atomic_32.h" +#include "stackx_common_opt.h" +#include "stackx_spl_share.h" + +/* From lwip */ +#include "api.h" +#include "sys.h" +#include "sys_arch.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MAX_WAIT_TIMEOUT 0x7FFFFFFF + +/* Throughout this file, IPaddresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for struct netconn.flags (u8_t) */ + +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define SPL_NETCONN_FLAG_WRITE_DELAYED 0x01 + +/** Should this netconn avoid blocking? */ +#define SPL_NETCONN_FLAG_NON_BLOCKING 0x02 + +/** Was the last connect action a non-blocking one? */ +#define SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 + +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define SPL_NETCONN_FLAG_NO_AUTO_RECVED 0x08 + +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +// #define NETCONN_FLAG_CHECK_WRITESPACE 0x10 + +enum stackx_model +{ + SOCKET_STACKX = 0, + CALLBACK_STACKX +}; + +enum callback_type +{ + API_ACCEPT_EVENT = 0xF0, + API_RECV_EVENT, + API_SEND_EVENT, + API_CLOSE_EVENT +}; +#if 1 +/** Use to inform the callback function about changes */ +enum spl_netconn_evt +{ + SPL_NETCONN_EVT_RCVPLUS, + SPL_NETCONN_EVT_RCVMINUS, + SPL_NETCONN_EVT_SENDPLUS, + SPL_NETCONN_EVT_SENDMINUS, + SPL_NETCONN_EVT_ERROR, + SPL_NETCONN_EVT_HUP, + SPL_NETCONN_EVT_RDHUP, + SPL_NETCONN_EVT_AGAIN, + SPL_NETCONN_EVT_ACCEPT +}; +#endif +enum +{ + INET_ECN_NOT_ECT = 0, + INET_ECN_ECT_1 = 1, + INET_ECN_ECT_0 = 2, + INET_ECN_CE = 3, + INET_ECN_MASK = 3, +}; + +#define SPL_NETCONNTYPE_GROUP(t) (t & 0xF0) +#define SPL_NETCONNTYPE_DATAGRAM(t) (t & 0xE0) + +/* forward-declare some structs to avoid to include their headers */ +typedef struct common_pcb +{ + enum stackx_model model; + + int socket; + + /** type of the netconn (TCP, UDP or RAW) */ + enum spl_netconn_type type; + + /* share memory between sbr and stackx */ + spl_netconn_t *conn; + + u16 bind_thread_index; + u8 close_progress; + u8 recv_ring_not_empty; + + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. + */ + data_com_msg *current_msg; + + msg_write_buf *msg_head; + msg_write_buf *msg_tail; + + size_t write_offset; + + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; + + /* timeout to wait for send buffer writtable */ + int send_timeout; + + int sk_rcvlowat; + + //DFX stat for connection packet + /* dfx_conn_t dfx; */ + + /*store the hostpid info for release */ + uint32_t hostpid; + u8_t l4_tick; /* if is odd number, use l4 ring first */ + u8_t dataSentFlag; + + nsfw_res res_chk; +} common_pcb; + +/** A callback prototype to inform about events for a netconn */ +//typedef void (*netconn_callback)(struct spl_netconn *, enum netconn_evt, u16_t len); + +/* Though these callback pointers are not set and referenced in nStack Core, still +the padding is required since the structure will be used in netconn and it needs +padding across 32-bit and 64-bit architecture */ +typedef struct +{ + union + { + int (*accept_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE accept_event_a; + }; + + union + { + int (*recv_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE recv_event_a; + }; + union + { + int (*send_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE send_event_a; + }; + union + { + int (*close_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE close_event_a; + }; +} callback_funcation; + +union ring_addr_u +{ + void *ring_addr; + PTR_ALIGN_TYPE ring_addr_a; +}; + +struct mem_manage +{ + volatile uint32_t current_read; + volatile uint32_t current_write; + union ring_addr_u ring_addr[RECV_MAX_POOL]; + union ring_addr_u l4_ring; /* recv ring for l4 */ + //void *ring_addr[RECV_MAX_POOL]; +}; + +/* Pbuf free should be done in network stack */ +struct spl_netconn_recvbuf_recoder +{ + struct spl_pbuf *head; + struct spl_pbuf *tail; + int totalLen; +}; + +/** Register an Network connection event */ +void spl_event_callback (spl_netconn_t * conn, enum spl_netconn_evt evt, + int postFlag); + +#define SPL_API_EVENT(c, e, p) spl_event_callback(c, e, p) + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define SPL_NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ + } while (0); + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define spl_netconn_set_nonblocking(conn, val) do { if (val) { \ + (conn)->flags |= SPL_NETCONN_FLAG_NON_BLOCKING; \ + } else { \ + (conn)->flags &= ~SPL_NETCONN_FLAG_NON_BLOCKING; }} while (0) + +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define spl_netconn_is_nonblocking(conn) (((conn)->flags & SPL_NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define spl_netconn_set_noautorecved(conn, val) do { if (val) { \ + (conn)->flags |= SPL_NETCONN_FLAG_NO_AUTO_RECVED; \ + } else { \ + (conn)->flags &= ~SPL_NETCONN_FLAG_NO_AUTO_RECVED; }} while (0) + +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define spl_netconn_get_noautorecved(conn) (((conn)->flags & SPL_NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +/** Set the receive timeout in milliseconds */ +#define spl_netconn_set_recvtimeout(cpcb, timeout) ((cpcb)->recv_timeout = (timeout)) + +/** Get the receive timeout in milliseconds */ +#define spl_netconn_get_recvtimeout(cpcb) ((cpcb)->recv_timeout) + +/** Set the send timeout in milliseconds */ +#define spl_netconn_set_sendtimeout(cpcb, timeout) ((cpcb)->send_timeout = (timeout)) + +/** Get the send timeout in milliseconds */ +#define spl_netconn_get_sendtimeout(cpcb) ((cpcb)->send_timeout) + +#define spl_netconn_set_sendbufsize(conn, sendbufsize) ((conn)->send_bufsize = (sendbufsize)) + +/* "man 7 socket" information + SO_SNDBUF + Sets or _gets the maximum socket send buffer in bytes. The kernel doubles + this value (to allow space for bookkeeping overhead) when it is set using + setsockopt(2), and this doubled value is returned by getsockopt(2). +*/ +#define spl_netconn_get_sendbufsize(conn) (2 *((conn)->send_bufsize)) + +#define spl_netconn_set_reclowbufsize(cpcb, recvlowbufsize) ((cpcb)->sk_rcvlowat = ((recvlowbufsize) > 0) ? recvlowbufsize : 1) +#define spl_netconn_get_reclowbufsize(cpcb) ((cpcb)->sk_rcvlowat) + +extern int spl_post_msg (u16 mod, u16 maj, u16 min, u16 op, char *data, + u16 data_len, u32 src_pid); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_API_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h new file mode 100644 index 0000000..94b681e --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h @@ -0,0 +1,129 @@ +/* +* +* 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. +*/ + +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include <stddef.h> +#include <net/if.h> +#include <sys/ioctl.h> + +#include "nsfw_msg.h" +#include "spl_opt.h" +#include "spl_ip_addr.h" +#include "spl_err.h" +#include "spl_api.h" +//#include "sockets.h" +#include "stackx_spl_share.h" +#include "stackx_spl_msg.h" + +/* From lwip */ +#include "tcp.h" +#include "udp.h" +#include "sys.h" + +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +struct callback_fn +{ + tcp_sent_fn sent_fn; + tcp_recv_fn recv_fn; + tcp_connected_fn connected_fn; + tcp_poll_fn poll_fn; + tcp_err_fn err_fn; + tcp_err_fn close_fn; + tcp_accept_fn accept_fn; +}; + +#ifdef HAL_LIB +#else +typedef enum _mbuf_recyle_flg +{ + MBUF_UNUSED = 0, + MBUF_HLD_BY_APP = 1, + MBUF_HLD_BY_SPL = 2, +} mbuf_recycle_flg; +#endif + +err_t sp_enqueue (struct common_pcb *cpcb, void *p); +err_t accept_dequeue (spl_netconn_t * lconn, void **new_buf, + u32_t timeout /*miliseconds */ ); +err_t accept_enqueue (spl_netconn_t * conn, void *p); +void free_conn_by_spl (spl_netconn_t * conn); +void unlink_pcb (struct common_pcb *cpcb); +void do_try_delconn (void *close_data, u32 delay_sec); +void do_delconn (struct common_pcb *cpcb, msg_delete_netconn * msg); +void do_bind (struct common_pcb *cpcb, msg_bind * msg); +void do_pbuf_free (struct spl_pbuf *buf); +void do_connect (struct common_pcb *cpcb, msg_connect * msg); +void do_listen (struct common_pcb *cpcb, msg_listen * msg); +void do_send (struct common_pcb *cpcb, msg_send_buf * msg); +void do_recv (struct common_pcb *cpcb, msg_recv_buf * msg); +void do_write (struct common_pcb *cpcb, msg_write_buf * msg); +void do_getaddr (struct common_pcb *cpcb, msg_getaddrname * msg); +void do_close (struct common_pcb *cpcb, msg_close * msg); +void do_getsockopt_internal (struct common_pcb *cpcb, + msg_setgetsockopt * smsg); +void do_setsockopt_internal (struct common_pcb *cpcb, + msg_setgetsockopt * smsg); +void do_getsockname (struct common_pcb *cpcb, msg_getaddrname * amsg); +int netconn_drain (enum spl_netconn_type t, spl_netconn_t * conn); +int spl_pcb_new (msg_new_netconn * m); +void do_app_touch (msg_app_touch * smsg); +int do_close_finished (struct common_pcb *cpcb, u8_t close_finished, + u8_t shut, err_t err, int OpShutDown); +err_t do_writemore (struct spl_netconn *conn); +err_t do_close_internal (struct common_pcb *cpcb, int OpShutDown); + +u8 get_shut_op (data_com_msg * m); +int ks_to_stk_opt (int opt); +void update_tcp_state (spl_netconn_t * conn, enum tcp_state state); + +err_t spl_poll_tcp (void *arg, struct tcp_pcb *pcb); +err_t spl_recv_tcp (void *arg, struct tcp_pcb *pcb, struct pbuf *p, + err_t err); +err_t spl_sent_tcp (void *arg, struct tcp_pcb *pcb, u16_t len); +void spl_err_tcp (void *arg, err_t err); +err_t spl_tcp_recv_null (void *arg, struct tcp_pcb *pcb, struct pbuf *p, + err_t err); +err_t spl_do_connected (void *arg, struct tcp_pcb *pcb, err_t err); +err_t spl_accept_function (void *arg, struct tcp_pcb *newpcb, err_t err); + +struct common_pcb *alloc_common_pcb (); +void free_common_pcb (struct common_pcb *cpcb); +int common_pcb_init (struct common_pcb *cpcb); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h new file mode 100644 index 0000000..a0188be --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h @@ -0,0 +1,40 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_ERR_H__ +#define __STACKX_ERR_H__ + +#include "spl_opt.h" +#include "lwip/arch.h" +#include "stackx_err.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef s8_t err_t; + +/* Definitions for error constants. */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h new file mode 100644 index 0000000..697c67d --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h @@ -0,0 +1,30 @@ +/* +* +* 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. +*/ + +#ifndef _SPL_INSTANCE_H_ +#define _SPL_INSTANCE_H_ +#include "nsfw_msg_api.h" +#include "stackx_instance.h" + +extern stackx_instance *p_def_stack_instance; + +int spl_process (data_com_msg * m); + +void add_disp_netif (struct netif *netif); +void do_update_pcbstate (); +void init_stackx_lwip (); + +#endif /* _SPL_INSTANCE_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h new file mode 100644 index 0000000..cd2e1bf --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h @@ -0,0 +1,52 @@ +/* +* +* 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. +*/ + +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "spl_opt.h" +#include "spl_pbuf.h" +#include "spl_ip_addr.h" +#include "common_mem_base_type.h" +#include "common_mem_pal.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_netbuf.h" +#include <sys/uio.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <errno.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** This spl_netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 + +/** This spl_netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +void spl_netbuf_delete (struct spl_netbuf *buf); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h new file mode 100644 index 0000000..01fe242 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h @@ -0,0 +1,173 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_PBUF_H__ +#define __STACKX_PBUF_H__ + +#include "cc.h" + +#include "common_mem_base_type.h" +#include "stackx_pbuf_comm.h" +#include "common_mem_mbuf.h" + +#ifdef HAL_LIB +#else +#include "common_pal_bitwide_adjust.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +/** indicates this pbuf is loop buf .*/ +#define PBUF_FLAG_LOOPBUF 0x08U + +#define PBUF_SET_LOOP_FLAG(buf) ((buf)->flags |= PBUF_FLAG_LOOPBUF) +#define PBUF_IS_LOOP_BUF(buf) ((buf)->flags & PBUF_FLAG_LOOPBUF) + +/*Add 1 parameter, the last one, indicating which dpdk_malloc + *should be allocated from the pool; non-PBUF_ALLOC type regardless of this parameter*/ +struct spl_pbuf *spl_pbuf_alloc_hugepage (spl_pbuf_layer l, u16_t length, + spl_pbuf_type type, + u16_t thread_index, void *net_conn); +struct pbuf *spl_convert_spl_pbuf_to_pbuf (struct spl_pbuf *p_from); +err_t pbuf_to_splpbuf_copy (struct spl_pbuf *p_to, struct pbuf *p_from); +err_t splpbuf_to_pbuf_copy (struct pbuf *p_to, struct spl_pbuf *p_from); +spl_pbuf_layer get_pbuf_layer_from_pbuf_payload (struct pbuf *buf); +void print_pbuf_payload_info (struct pbuf *buf, bool send); + +static inline u8_t +spl_pbuf_header (struct spl_pbuf *p, s16_t header_size_increment) +{ + u8_t pbuf_ret; + /* header max len is tcp len+ ip len: 0xf*4+PBUF_IP_HLEN */ + if (unlikely + (((header_size_increment) < 0 && (-(header_size_increment)) > p->len) + || (header_size_increment > 0 + && (header_size_increment) >= (0xf * 4 + SPL_PBUF_IP_HLEN)))) + { + pbuf_ret = 1; + } + else + { + p->payload_a = p->payload_a - (header_size_increment); + p->len += (header_size_increment); + p->tot_len += (header_size_increment); + pbuf_ret = 0; + } + return pbuf_ret; +} + +void spl_pbuf_realloc (struct spl_pbuf *p, u32_t size); + +void spl_pbuf_cat (struct spl_pbuf *head, struct spl_pbuf *tail); +void spl_pbuf_free (struct spl_pbuf *p); + +#define pbuf_free_safe(x)\ +{\ + spl_pbuf_free((x));\ + (x) = NULL;\ +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ +static inline u16_t +spl_pbuf_clen (struct spl_pbuf *p) +{ + u16_t len = 0; + while (p != NULL) + { + ++len; + p = (struct spl_pbuf *) ADDR_SHTOL (p->next_a); + } + return len; +} + +static inline u16_t +mbuf_count (struct spl_pbuf *p) +{ + u16_t count = 0; + struct spl_pbuf *buf = p; + struct common_mem_mbuf *mbuf; + while (buf) + { + mbuf = + (struct common_mem_mbuf *) ((char *) buf - + sizeof (struct common_mem_mbuf)); + while (mbuf) + { + count++; +#ifdef HAL_LIB +#else + mbuf = mbuf->next; +#endif + } + buf = (struct spl_pbuf *) ADDR_SHTOL (buf->next_a); //buf->next; + } + return count; +} + +static inline u16_t +mbuf_count_in_one_pbuf (struct spl_pbuf *p) +{ + + u16_t cnt = 0; + struct common_mem_mbuf *mbuf; + if (NULL == p) + { + NSPOL_LOGERR ("Invalid param : p(null) !"); + return 0; + } + + mbuf = + (struct common_mem_mbuf *) ((char *) p - sizeof (struct common_mem_mbuf)); + + /* no need to check mbuf itself */ +#ifdef HAL_LIB +#else + if (!mbuf->next) +#endif + return 1; + + while (mbuf) + { + ++cnt; +#ifdef HAL_LIB +#else + mbuf = mbuf->next; +#endif + } + + return cnt; +} + +inline int pbuf_internal_copy (struct spl_pbuf *dst, struct spl_pbuf *src); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_PBUF_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h new file mode 100644 index 0000000..a4d6ccc --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h @@ -0,0 +1,33 @@ +/* +* +* 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. +*/ + +#ifndef _SPL_SBR_H_ +#define _SPL_SBR_H_ +#include "nsfw_msg_api.h" +#include "tcp.h" +#include "udp.h" +//#include "stackx/raw.h" +#define COMM_PRIVATE_PTR(m) \ + ((m->param.receiver) ? ((struct common_pcb *)m->param.comm_receiver) : 0) +#define TCP_PRIVATE_PTR(m) \ + ((m->param.receiver) ? (*(struct tcp_pcb **)m->param.receiver) : 0) +#define UDP_PRIVATE_PTR(m) \ + ((m->param.receiver) ? (*(struct udp_pcb **)m->param.receiver) : 0) +/*#define RAW_PRIVATE_PTR(m) \ + ((m->param.receiver) ? (*(void *)m->param.receiver) : 0) */ + +int spl_sbr_process (data_com_msg * m); +#endif /* _SPL_SBR_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h new file mode 100644 index 0000000..278bb02 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h @@ -0,0 +1,252 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_SOCKETS_H__ +#define __STACKX_SOCKETS_H__ + +#include <errno.h> +#include <stddef.h> /* for size_t */ +#include "arch/sys_arch.h" +#include "sys/socket.h" +#include <errno.h> +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef socklen_t +#define socklen_t u32_t +#endif + +#define SET_STACKP_ERRNO(err) (errno = (err)) //thread-local errno + +#ifndef set_errno +#define set_errno(err) SET_STACKP_ERRNO(err) +#endif + +#define sock_set_errno(sk, e) do { \ + (sk)->err = (e); \ + if ((sk)->err != 0) \ + set_errno((sk)->err); \ + } while (0) + +#ifndef __BITS_SOCKET_H +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info storing */ +#define SO_REUSEADDR 0x0002 +#endif + +#define SO_DONTROUTE 5 //0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 6 //0x0020 /* permit to send and to receive broad cast messages*/ +#define SO_KEEPALIVE 9 //0x0008 gaussdb /* keep connections alive */ +#define SO_OOBINLINE 10 //0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_LINGER 13 //0x0080 /* linger on close if data present */ +#define SO_REUSEPORT 15 /* Unimplemented: allow local address & port reuse */ +#define SO_ACCEPTCONN 30 //0x0002 /* socket has had listen() */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_TYPE 3 /* get socket type */ +#define SO_ERROR 4 +#define SO_SNDBUF 7 /* send buffer size */ +#define SO_RCVBUF 8 /* receive buffer size */ +#define SO_NO_CHECK 11 /* don't create UDP checksum */ +#define SO_RCVLOWAT 18 /* receive low-water mark */ +#define SO_SNDLOWAT 19 /* send low-water mark */ +#define SO_RCVTIMEO 20 /* receive timeout */ +#define SO_SNDTIMEO 21 /* Unimplemented: send timeout */ + +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 1 //0xfff + +#ifndef __BITS_SOCKET_H + +#define AF_UNSPEC 0 +#define PF_UNSPEC AF_UNSPEC +#define AF_INET 2 +#define PF_INET AF_INET + +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 + +#define IPPROTO_IP 0 + +#define MSG_PEEK 0x02 +#define MSG_WAITALL 0x100 +#define MSG_OOB 0x01 +#define MSG_DONTWAIT 0x40 +#define MSG_MORE 0x8000 +#endif + +#define IP_TOS 1 +#define IP_TTL 2 + +#define RCV_WND 0x21 +#define RCV_ANN_WND 0x22 +#define INIT_CWND 0x23 +#define THRESHOLD_FACTOR 0x24 +#define TMR_INTERVAL 0x25 + +/* + * Options and types for UDP multicast traffic handling + */ +#ifndef __BITS_SOCKET_H +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 +#endif + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_LOWCOST 0x02 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_MINCOST IPTOS_LOWCOST +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_ROUTINE 0x00 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) + +#if !defined (FIONREAD) || !defined (FIONBIO) +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */ + +#define _IO(x, y) (((x) << 8) | (y) |IOC_VOID ) + +#define _IOR(x, y, t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) + +#define _IOW(x, y, t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) +#endif + +/*unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) +#define SIOCGHIWAT _IOR('s', 1, unsigned long) +#define SIOCSLOWAT _IOW('s', 2, unsigned long) +#define SIOCGLOWAT _IOR('s', 3, unsigned long) +#ifndef __BITS_SOCKET_H +#define SIOCATMARK _IOR('s', 7, unsigned long) +#endif +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 0X800 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY O_NONBLOCK /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0x80000 /* set close_on_exec */ +#endif +#ifndef __BITS_SOCKET_H +#define SOCK_CLOEXEC O_CLOEXEC +#endif +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif +#ifndef SHUT_RD +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 +#endif + +struct pollfd +{ + + int fd; /* file descriptor */ + short events; /* wait event */ + short revents; /* actual event happened */ +}; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_SOCKETS_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h new file mode 100644 index 0000000..0f885d6 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h @@ -0,0 +1,80 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_TCPIP_H__ +#define __STACKX_TCPIP_H__ + +#include "spl_opt.h" +#include "stackx/spl_ip_addr.h" +#include "tcp.h" + +#define USEAGE_LOW 60 +#define USEAGE_HIGHT 80 +#define USEAGE_INVALID 0xFF + +/*** Put into stackx_instance ********* + +************************************/ +#include "stackx/spl_api_msg.h" +#include "netifapi.h" +#include "stackx/spl_pbuf.h" +#include "stackx/spl_api.h" +#include "sys.h" +#include "netif.h" +#include "ip_module_api.h" +#include "internal_msg.h" +#include "pbuf.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** Function prototype for send timeout message */ +err_t ltt_apimsg (sys_timeout_handler h, void *arg); + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn) (void *arg); + +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn) (void *ctx); + +int init_by_main_thread (); +int init_by_tcpip_thread (); +err_t spl_tcpip_input (struct pbuf *p, struct netif *inp); + +int post_ip_module_msg (void *arg, ip_module_type type, + ip_module_operate_type operate_type); +int process_ip_module_msg (void *arg, ip_module_type type, + ip_module_operate_type operate_type); +int init_new_network_configuration (); + +#if STACKX_NETIF_API +err_t tcpip_netif_add (msg_add_netif * tmp); +#endif /* STACKX_NETIF_API */ + +err_t ltt_clearTmrmsg (void *pcb, void *arg); + +sys_mbox_t get_primary_box (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_TCPIP_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h new file mode 100644 index 0000000..4809b2b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h @@ -0,0 +1,108 @@ +/* +* +* 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. +*/ + +#ifndef __SPL_TIMERS_H__ +#define __SPL_TIMERS_H__ + +#include "opt.h" +#include "common_mem_base_type.h" + +typedef void (*sys_timeout_handler) (void *arg); + +#include "rb_tree.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ + +/* + * ************************************************************************* + * PTIMER defined 2013/3/15 + * ************************************************************************* + */ +#define PTIMER_DEFAULT 0x00 /* periodic mode */ +#define PTIMER_ONESHOT 0x01 +#define PTIMER_USER_DEF 0x02 + +enum msg_type +{ + SYS_PTIMEROUT_MSG, + SYS_UNPTIMEROUT_MSG, +}; + +struct msg_context +{ + unsigned long msec; + union + { + sys_timeout_handler handle; + } action; +#define _act_category action.act_category +#define _phandle action.handle + u32_t flags; /* oneshot|user_def|... */ + void *ctx; /* pcb ptr */ +}; + +struct ptimer_node +{ + struct rb_node node; + unsigned long abs_nsec; + struct msg_context info; + unsigned long state; + u16_t index; /* store a lwip thread message box id */ +}; + +struct ptimer_msg +{ + enum msg_type msg_type; + struct ptimer_node *node; + struct ptimer_msg *next, *prev; +}; + +struct ptimer_base +{ + struct rb_root active; + struct rb_node *first; /* point the recently timeout */ + pthread_mutex_t lock; + pthread_cond_t cond; + struct ptimer_msg *head, *tail; +}; + +/* + * ***************************************************** + * ptimer E-N-D + * ***************************************************** + */ +void ptimer_thread (void *arg); +void timeout_phandler (void *act, void *arg); +void regedit_ptimer (enum msg_type type, sys_timeout_handler handler, + struct ptimer_node *node); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_TIMERS_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h b/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h new file mode 100644 index 0000000..679d2ac --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h @@ -0,0 +1,91 @@ +/* +* +* 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. +*/ + +#ifndef __STACKX_INSTANCE_H__ +#define __STACKX_INSTANCE_H__ + +#include "stackx/spl_tcpip.h" +#include "netif.h" +#include "lwip/ip4_frag.h" +#include "stackx/spl_pbuf.h" +#include "arch/sys_arch.h" +#include "arch/queue.h" +#include "stackx_tx_box.h" +#include "nsfw_msg.h" +#include "stackx_app_res.h" +#include "ip_module_api.h" +#include "tcp.h" +#include "udp.h" + +#define PKT_BURST 32 + +#define TASK_BURST 16 + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MAX_NETBUFS 1024*2 //define for C10M + +#define TOTAL_MSG_QUEUE_NUM (MSG_PRIO_QUEUE_NUM+1) /* three priority queue and one primary queue */ + +struct stackx_stat +{ + struct rti_queue primary_stat; //primary box stat + u64_t extend_member_bit; +}; + +struct stackx_stack +{ + struct queue primary_mbox; + struct queue priority_mbox[MSG_PRIO_QUEUE_NUM]; //0-highest; 1-medium; 2-lowest + //stackx_apis stackx_api; +}; + +struct disp_netif_list +{ + struct disp_netif_list *next; + struct netif *netif; +}; + +typedef struct stackx_instance +{ + uint16_t rss_queue_id; + + mpool_handle mp_tx; + //mring_handle mp_seg; + mring_handle cpcb_seg; + mring_handle lmsg_pool; + + struct stackx_stack lstack; + struct stackx_stat lstat; //point to p_stackx_table->lstat[i]; + + /** + * Header of the input packet currently being processed. + */ + /* global variables */ + struct disp_netif_list *netif_list; +} stackx_instance; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_INSTANCE_H__ */ |