#include #include #include #include #include #include "sk_udp.h" static struct sk_app_instance * sk_default_app_instance; static struct sk_instance * sk_default_instance; void sk_default_instance_set(struct sk_instance * instance, struct sk_app_instance * app_instance) { sk_default_instance = instance; sk_default_app_instance = app_instance; } int marsio_socket(int family, int type, int protocol) { if (unlikely(family != AF_INET && family != AF_INET6)) return -EINVAL; if (unlikely(type != SOCK_DGRAM)) return -EINVAL; assert(sk_default_app_instance != NULL); struct sk_ucb * ucb = sk_ucb_create(sk_default_app_instance); if (unlikely(ucb == NULL)) return -1; return sk_ucb_get_index(ucb); } int marsio_connect(int fd, const struct sockaddr * addr, socklen_t addrlen) { if (addr->sa_family != AF_INET) return -EINVAL; struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)addr; assert(sk_default_app_instance != NULL); struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, fd); if (unlikely(ucb == NULL)) return -EINVAL; return sk_ucb_connect(ucb, sockaddr_in); } int marsio_bind(int fd, const struct sockaddr * addr, socklen_t addrlen) { if (addr->sa_family != AF_INET) return -EINVAL; struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)addr; assert(sk_default_app_instance != NULL); struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, fd); if (unlikely(ucb == NULL)) return -EINVAL; return sk_ucb_bind(ucb, sockaddr_in); } #define SK_UDP_MAGIC_CHECK 0 #ifdef __GNUC__ #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) *__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type,member));}) #else #define container_of(ptr, type,member) \ ((type *)((char *)(ptr) - offsetof(type, member))) #endif /* UDP报文缓冲区,同一链表上的缓冲区表示同一个UDP报文 */ struct marsio_udp_buff { /* 缓冲区起始地址 */ void * start; /* 缓冲区长度 */ unsigned int len; /* 下一块缓冲区地址 */ struct marsio_udp_buff * next; /* 下一个包起始地址 */ struct marsio_udp_buff * next_pkt; }; struct internal_udp_buff { #if SK_UDP_MAGIC_CHECK char magic_0[2]; #endif struct rte_mbuf * mbuf; #if SK_UDP_MAGIC_CHECK char magic_1[2]; #endif struct marsio_udp_buff buff; }; /* 以下函数为兼容MARSIO-3版本的实现,新功能应不使用以下函数 */ /* BUFF结构互相转换函数 */ static inline struct marsio_udp_buff * __buff_from_internal_buff(struct internal_udp_buff * in_buff) { return &(in_buff->buff); } static inline struct internal_udp_buff * __internal_buff_from_buff(struct marsio_udp_buff * buff) { return container_of(buff, struct internal_udp_buff, buff); } static inline struct rte_mbuf * __mbuf_from_buff(struct marsio_udp_buff * buff) { return __internal_buff_from_buff(buff)->mbuf; } struct marsio_udp_buff * marsio_udp_alloc() { struct rte_mbuf * mbuf = rte_pktmbuf_alloc(sk_default_app_instance->def_direct_pktmbuf_pool); if (unlikely(mbuf == NULL)) return NULL; uint8_t ctrlzone_id = sk_default_app_instance->instance->ctrlzone_id_soqinfo; struct internal_udp_buff * in_buff = (struct internal_udp_buff *)mr_buffer_ctrlzone(mbuf, ctrlzone_id); assert(in_buff != NULL); in_buff->mbuf = mbuf; in_buff->buff.start = rte_pktmbuf_mtod(mbuf, void *); in_buff->buff.len = mbuf->buf_len - mbuf->data_off; in_buff->buff.next = NULL; in_buff->buff.next_pkt = NULL; return __buff_from_internal_buff(in_buff); } void marsio_udp_free(struct marsio_udp_buff * udp_buff) { struct rte_mbuf * mbuf = __mbuf_from_buff(udp_buff); rte_pktmbuf_free(mbuf); return; } /* 根据UDP Buff结构构建串接的MBUF结构*/ static inline struct rte_mbuf * update_rte_mbuf(struct marsio_udp_buff * buff_head) { struct marsio_udp_buff * now_buff_head = buff_head; struct rte_mbuf * mbuf_chain_head = __mbuf_from_buff(buff_head); // 第一个包初始化 mbuf_chain_head->pkt_len = buff_head->len; mbuf_chain_head->data_len = buff_head->len; mbuf_chain_head->nb_segs = 1; // 根据BUFF结构构建MBUF链表 while (now_buff_head != NULL) { #if SK_UDP_MAGIC_CHECK struct internal_udp_buff * __check_in_buff = __internal_buff_from_buff(now_buff_head); __magic_check(__check_in_buff); #endif struct rte_mbuf * mbuf_now = __mbuf_from_buff(now_buff_head); if (mbuf_now != mbuf_chain_head) rte_pktmbuf_chain(mbuf_chain_head, mbuf_now); now_buff_head = now_buff_head->next; } return mbuf_chain_head; } static ssize_t __udp_sendto_burst(int marsio_fd, struct marsio_udp_buff * buff[], unsigned int nr_buff, int flags, struct sockaddr * to, socklen_t addrlen) { // 查找当前的FD对应的UCB struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, marsio_fd); if (unlikely(ucb == NULL)) return -EINVAL; // 地址转换,MBUF转换 struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)to; if (unlikely(sockaddr_in->sin_family != AF_INET)) return -EINVAL; struct rte_mbuf * mbufs[MR_BURST_MAX]; for(int i = 0; i < nr_buff; i++) { mbufs[i] = update_rte_mbuf(buff[i]); } // 查询目的Destinfo struct sk_destinfo * destinfo = sk_ucb_destinfo_get(ucb); if (destinfo != NULL) goto send; destinfo = sk_destinfo_create_by_route(sk_default_app_instance, sockaddr_in->sin_addr); if (unlikely(destinfo == NULL)) goto errout; send: return sk_udp_send_burst(sk_default_app_instance, flags, destinfo, mbufs, nr_buff, 0); errout: return 0; } ssize_t marsio_udp_sendto_chain(int marsio_fd, struct marsio_udp_buff * chain_head, int nb_buff, int flags, struct sockaddr * to[], socklen_t addrlen[], int nb_sockaddrs) { int nb_chain_pkts = 0; struct marsio_udp_buff * buff_array[MR_BURST_MAX]; if (unlikely(nb_buff > RTE_DIM(buff_array))) return -ENOBUFS; for (struct marsio_udp_buff * __head = chain_head; __head != NULL; __head = __head->next_pkt) { buff_array[nb_chain_pkts++] = __head; } // 不支持大于1的目标地址 if (nb_sockaddrs > 1) return -EINVAL; return __udp_sendto_burst(marsio_fd, buff_array, nb_chain_pkts, flags, to[0], addrlen[0]); }