#ifndef __MTCP_API_H_ #define __MTCP_API_H_ #include #include #include #ifndef UNUSED #define UNUSED(x) (void)x #endif #ifndef INPORT_ANY #define INPORT_ANY (uint16_t)0 #endif typedef unsigned char byte; #ifdef __cplusplus extern "C" { #endif /** mTCP context */ struct mtcp_context { int cpu; }; typedef struct mtcp_context *mctx_t; /** mTCP signal handler type */ typedef void (*mtcp_sighandler_t)(int); /** Socket types */ enum socket_type { /** unused */ MOS_SOCK_UNUSED, /* listening socket type */ /** regular mTCP connection listen socket */ MOS_SOCK_STREAM_LISTEN, /** MOS proxy socket listening socket */ /* (pending implementation) */ MOS_SOCK_PROXY_LISTEN, /** MOS monitor socket listening socket */ MOS_SOCK_MONITOR_STREAM, /* stream socket type */ /** regular mTCP connection socket */ MOS_SOCK_STREAM, /** MOS proxy socket */ /* (pending implementation) */ MOS_SOCK_PROXY, /** MOS monitor socket */ MOS_SOCK_MONITOR_STREAM_ACTIVE, /** MOS monitor socket (raw, stateless) */ MOS_SOCK_MONITOR_RAW, /* for epoll */ MOS_SOCK_EPOLL, /* for pipe */ MOS_SOCK_PIPE, }; /* Configurable mTCP attributes * This is automatically generated by mOS core after the * mtcp_init() function call. You can change this option * in your program using mtcp_get/set_conf(). */ struct mtcp_conf { /** Maximum length of application name */ #define APP_NAME_LEN 40 /** Maximum concurrently runable application */ #define MOS_APP 20 int num_cores; /**< number of cores to use */ int max_concurrency; /**< number of concurrent flows per core*/ uint64_t cpu_mask; int max_num_buffers; /**< number of socket buffers */ int rcvbuf_size; /**< size of receive buffer */ int sndbuf_size; /**< size of send buffer */ int tcp_timewait; /**< time wait time in sec */ int tcp_timeout; /**< timeout in sec, -1 for not to check timeout */ #define MOS_APP_ARGC 20 uint64_t app_cpu_mask[MOS_APP]; char *app_argv[MOS_APP][MOS_APP_ARGC]; int app_argc[MOS_APP]; int num_app; /**< number of registered apps */ }; /* Target to modify */ struct app_context { mctx_t mctx; /**< mTCP context */ int socket_id; /**< listing socket ID */ struct conn_filter *cf; int ep_id; }; /* Application need to specify those parameters. */ /* NOTE: This structure is not used in mos_release 0.2a * This structure will be used by embedded mOS application using * mOS server. */ struct app_ops { /** Initialization function which is called for only once per each * application */ void (*app_init)(int argc, char **argv); /** Initialization function which is called for each CPU core */ void (*thread_init)(mctx_t mctx, void **app_ctx); /** Function contains code which will be executed after initialization * phase */ void (*run)(mctx_t mctx, void **app_ctx); /* is the application enabled at the moment? */ int enable; }; /** Initialize mOS context with parameters mentioned in the config file * @param [in] config_file: location of config file * @return 0 on success, -1 on error * * Setting dpdk devices, interface, load configuration from config file, * routing table, arp table, etc. */ int mtcp_init(const char *config_file); /** Destroy the global mOS context * @return 0 on success, -1 on error */ int mtcp_destroy(); /** Load current mtcp configuration in *conf * @param [out] conf: configurations * @return 0 on success, -1 on error */ int mtcp_getconf(struct mtcp_conf *conf); /** Update mOS base with parameters mentioned in *conf * @param [in] conf: configurations to set * @return 0 on success, -1 on error */ int mtcp_setconf(const struct mtcp_conf *conf); /** Bind a thread to a specific CPU core * @param [in] cpu: CPU ID * @return 0 on success, -1 on error */ int mtcp_core_affinitize(int cpu); /** Create mOS/mtcp context thread based on the parameters passed * by mtcp_init() & mtcp_setconf() functions * @param [in] cpu: Core id to affinitize new mtcp thread * @return mtcp context, NULL on error */ mctx_t mtcp_create_context(int cpu); /** Destory mtcp context that was created by mOS/mTCP thread * @param [in] mctx: mtcp context * @return 0 on success, -1 on error */ int mtcp_destroy_context(mctx_t mctx); /** Register signal handler (mtcp_sighandler_t handler ) * for int signum * @param [in] signum: Signal number to handle * @param [in] handler: Handler function * @return Same handler as input */ mtcp_sighandler_t mtcp_register_signal(int signum, mtcp_sighandler_t handler); /** Create pipe * @param [in] mctx: mtcp context * @param [out] pipeid: created pipe * @return 0 on success, -1 on error */ int mtcp_pipe(mctx_t mctx, int pipeid[2]); /** Get socket options * *
    * *
  1. Please see http://mos.kaist.edu/man/mtcp_getsockopt.html for * the further informations.
  2. * *
  3. MOS_FRAGINFO_CLIBUF and MOS_FRAGINFO_SVRBUF \n * Gives back offsets to fragments (non-contiguous data segments) currently * stored in client’s TCP ring buffer. The optval is an array of * `struct tcp_ring_fragment` * where offset flow data starting from client’s TCP SYN sequence number, * and len is the length of the tcp_ring_fragment. The optval holds the size * of the array (in terms of the number of elements).
  4. * *
  5. MOS_INFO_CLIBUF and MOS_INFO_SVRBUF \n * Returns meta-data regarding the client’s TCP ring buffer. This information * is returned in the form of optval which is passed as struct tcp_buf_info.
  6. * *
  7. MOS_TCP_STATE_CLI and MOS_TCP_STATE_SVR \n * Returns the current emulated state of the client. The optval argument is * a pointer to an int whereas the optlen argument contains the sizeof(int). * The optval returns a value of type enum tcpstate which can carry any one * of the following states.
  8. *
* * @param [in] mctx: mtcp context * @param [in] sock: socket id * @param [in] level: SOL_MONSOCKET * @param [in] optname: __variable__ * @param [out] optval: value of getting option * @param [out] optlen: length of getting option * @return Zero on success, -1 on error */ int mtcp_getsockopt(mctx_t mctx, int sock, int level, int optname, void *optval, socklen_t *optlen); /** Set socket options * *
    * *
  1. MOS_CLIBUF and MOS_SVRBUF \n * Dynamically adjust the size of the TCP receive ring buffer of the * emulated client/server stack. The optval contains the size of the buffer * that needs to be set as int, while optlen is equal to sizeof(int).
  2. * *
  3. MOS_CLIOVERLAP and MOS_SVROVERLAP \n * Dynamically determine the policy on content overlap (e.g., overwriting * with the retransmitted payload or not) for the client-side buffer. The * optval can be either MOS_OVERLAP_POLICY_FIRST (to take the first data * and never overwrite the buffer) or MOS_OVERLAP_POLICY_LAST (to always * update the buffer with the last data), and optlen is equal to sizeof(int).
  4. * *
  5. MOS_STOP_MON \n * Dynamically stop monitoring a flow for the specific side. This option can * be used only with a MOS_SOCK_MONITOR_ACTIVE socket, which is given as a * parameter in callback functions for every flow. The optval contains a side * variable (MOS_SIDE_CLI, MOS_SIDE_SVR, or MOS_SIDE_BOTH), while optlen is * equal to sizeof(int).
  6. * *
* * @param [in] mctx: mtcp context * @param [in] sock: socket id * @param [in] level: SOL_MONSOCKET * @param [in] optname: __variable__ * @param [in] optval: value of setting option * @param [in] optlen: length of setting option * @return Zero on success, -1 on error */ int mtcp_setsockopt(mctx_t mctx, int sock, int level, int optname, const void *optval, socklen_t optlen); /** Set socket as nonblock * @param [in] mctx: mtcp context * @param [in] sock: socket id * @return Zero on success, -1 on error * * DEPRECATED */ int mtcp_setsock_nonblock(mctx_t mctx, int sock); /** Control socket * @param [in] mctx: mtcp context * @param [in] sock: socket id * @param [in] request: requested operation * @param [in,out] argp: pointer to argument * @return Zero on success, -1 on error * * Operations | Description * ---------- | ----------- * FIONREAD | number of data bytes in receive buffer * FIONBIO | for non-blocking I/O */ int mtcp_ioctl(mctx_t mctx, int sock, int request, void *argp); /** Create a socket * @param [in] mctx: mtcp context * @param [in] domain: AF_INET, Not used * @param [in] type: Any of the following keyword * - MOS_SOCK_STREAM (End TCP) * - MOS_SOCK_MONITOR_RAW (Packet-level monitor) * - MOS_SOCK_MONITOR_STREAM (Flow-level monitor) * (MOS_SOCK_PROXY: To be supported) * @param [in] protocol: NULL, Not used * @return Zero on success, -1 on error */ int mtcp_socket(mctx_t mctx, int domain, int type, int protocol); /** Bind a socket, same as `bind()` * @return Zero on success, -1 on error */ int mtcp_bind(mctx_t mctx, int sock, const struct sockaddr *addr, socklen_t addrlen); /** Listen a listening socket, same as `listen()` * @return Zero on success, -1 on error * * Only MOS_SOCK_LISTENER, MOS_SOCK_PROXY are allowed */ int mtcp_listen(mctx_t mctx, int sock, int backlog); /** Accept new flow, same as `accept()` * @param [in] mctx: mtcp context * @param [in] sock: socket id for MOS_SOCK_STREAM * @param [in] addr: address of the peer host(s) * @param [in] addrlen: length of `addr` * @return Zero on success, -1 on error */ int mtcp_accept(mctx_t mctx, int sock, struct sockaddr *addr, socklen_t *addrlen); /** Initialize RSS pool for decide appropriate port numbers * @param [in] mctx: mtcp context * @param [in] saddr_base: source IP address base * @param [in] num_addr: number of source IP address to use * @param [in] daddr: destination IP address * @param [in] dport: destination port number * @return Zero on success, -1 on error * * w.r.t source IP addr, destination IP addr, destination port */ int mtcp_init_rss(mctx_t mctx, in_addr_t saddr_base, int num_addr, in_addr_t daddr, in_addr_t dport); /** Connect new flow, same as `connect()` * @return Zero on success, -1 on error */ int mtcp_connect(mctx_t mctx, int sock, const struct sockaddr *addr, socklen_t addrlen); /** Close flow, same as `close()` * @return Zero on success, -1 on error */ int mtcp_close(mctx_t mctx, int sock); /** Abort flow by sending RST * @return Zero on success, -1 on error * * Different from `mtcp_close()` which processes 4way handshake by FIN */ int mtcp_abort(mctx_t mctx, int sock); /** Returns the current address to which the socket sockfd is bound * @param [in] mctx: mtcp context * @param [in] addr: address buffer to be filled * @param [in] addrlen: amount of space pointed to by addr * @return 0 on success, -1 on error */ int mtcp_getsockname(mctx_t mctx, int sock, struct sockaddr *addr, socklen_t *addrlen); /** Read byte stream from flow, same as `recv()` * For now, it can only accept flags 0 (default aka mtcp_read()) & MSG_PEEK * @return number of bytes read on success, -1 on error */ ssize_t mtcp_recv(mctx_t mctx, int sockid, char *buf, size_t len, int flags); /** Read byte stream from flow, same as `read()` * @return number of bytes read on success, -1 on error */ ssize_t mtcp_read(mctx_t mctx, int sock, char *buf, size_t len); /* readv should work in atomic */ /** Read byte stream from flow in vector, same as `readv()` * @return number of bytes read on success, -1 on error */ ssize_t mtcp_readv(mctx_t mctx, int sock, const struct iovec *iov, int numIOV); /** Write byte stream to flow, same as `write()` * @return number of bytes write on success, -1 on error */ ssize_t mtcp_write(mctx_t mctx, int sock, const char *buf, size_t len); /* writev should work in atomic */ /** Write byte stream to flow in vector, same as `writev()` * @return number of bytes write on success, -1 on error */ ssize_t mtcp_writev(mctx_t mctx, int sock, const struct iovec *iov, int numIOV); /** Get concurrent flow count of the underlying mtcp manager context (per-thread) * @param [in] mctx: mtcp context * @return concurrent flow count */ uint32_t mtcp_get_connection_cnt(mctx_t mctx); #ifdef __cplusplus }; #endif #endif /* __MTCP_API_H_ */