#include #include #include #include #include #include #include #include static inline int is_same_subnet(struct in_addr a_addr, struct in_addr b_addr, struct in_addr mask) { in_addr_t in_addr_a = a_addr.s_addr; in_addr_t in_addr_b = b_addr.s_addr; in_addr_t in_addr_mask = mask.s_addr; return (in_addr_a & in_addr_mask) == (in_addr_b & in_addr_mask); } /* ======================================================================================= */ static int sendpath_vdev_l2_construct(struct mr_sendpath * sendpath, struct rte_mbuf * mbuf[], unsigned int nr_mbuf) { struct __mr_sendpath_vdev * _sendpath = container_of(sendpath, struct __mr_sendpath_vdev, _father); for (int i = 0; i < nr_mbuf; i++) { struct rte_ether_hdr * ether_hdr = (struct rte_ether_hdr *)rte_pktmbuf_prepend(mbuf[i], sizeof(struct rte_ether_hdr)); MR_VERIFY_2(ether_hdr != NULL, "Not enough space for ethernet header in mbufs. "); #if RTE_VERSION_NUM(21, 11, 0, 0) <= RTE_VERSION ether_hdr->src_addr = _sendpath->src_eth_addr; ether_hdr->dst_addr = _sendpath->dst_eth_addr; #else ether_hdr->s_addr = _sendpath->src_eth_addr; ether_hdr->d_addr = _sendpath->dst_eth_addr; #endif ether_hdr->ether_type = htons(RTE_ETHER_TYPE_IPV4); } return 0; } static int sendpath_vdev_option_get(struct mr_instance * instance, struct mr_sendpath * sendpath, int opt, va_list va_list) { return 0; } static int sendpath_vdev_option_set(struct mr_instance * instance, struct mr_sendpath * sendpath, int opt, va_list va_list) { if (opt == MR_SENDPATH_OPT_BUILD_L2) { unsigned int enable = va_arg(va_list, unsigned int); sendpath->fn_l2_construct = enable ? sendpath_vdev_l2_construct : NULL; } else if (opt == MR_SENDPATH_OPT_HOOK_PREBUILD) { sendpath->fn_prebuild_hook = va_arg(va_list, void *); sendpath->prebuild_hook_args = va_arg(va_list, void *); } else if (opt == MR_SENDPATH_OPT_HOOK_POSTBUILD) { sendpath->fn_postbuild_hook = va_arg(va_list, void *); sendpath->postbuild_hook_args = va_arg(va_list, void *); } else { MR_ERROR("Invalided opt type in %s()", __FUNCTION__); return -EINVAL; } return 0; } static void sendpath_vdev_destory(struct mr_sendpath * sendpath) { struct __mr_sendpath_vdev * _sendpath = container_of(sendpath, struct __mr_sendpath_vdev, _father); free(_sendpath); } static struct mr_sendpath * sendpath_vdev_create(struct mr_instance * instance, int type, va_list va_list) { /* 第一个传入参数:目标虚设备句柄 */ struct mr_vdev * dest_vdev = va_arg(va_list, struct mr_vdev *); struct __mr_sendpath_vdev * _sendpath = malloc(sizeof(struct __mr_sendpath_vdev)); memset(_sendpath, 0, sizeof(struct __mr_sendpath_vdev)); /* Parameters */ _sendpath->_father.target_vdi = dest_vdev->vdi; _sendpath->_father.vdev = dest_vdev; _sendpath->_father.can_use = 1; _sendpath->_father.instance = instance; /* Callback Functions */ _sendpath->_father.fn_destory = sendpath_vdev_destory; _sendpath->_father.fn_option_set = sendpath_vdev_option_set; _sendpath->_father.fn_option_get = sendpath_vdev_option_get; return &_sendpath->_father; } static struct mr_sendpath * sendpath_route_create(struct mr_instance * instance, int type, va_list va_list) { return NULL; } /* ======================================================================================== */ /* \brief 创建SendPath的统一入口函数。 采用可变参数函数。根据创建类型的不同,传输参数的类型和数量也不同。 (_1_) type = MR_SENDPATH_DEV struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type = MR_SENDPATH_VDEV, struct mr_vdev * vdev); (_2_) type = MR_SENDPATH_ROUTE_NORMAL struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type = MR_SENDPATH_ROUTE_NORMAL, struct in_addr in_addr); (_3_) type = MR_SENDPATH_ROUTE_SPEC_DEV struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type = MR_SENDPATH_ROUTE_SPEC_DEV, struct mr_vdev * vdev, struct in_addr in_addr); \return Sendpath object handler */ struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type, ...) { va_list ptr_arg; struct mr_sendpath * sendpath = 0; va_start(ptr_arg, type); switch (type) { case MR_SENDPATH_VDEV: sendpath = sendpath_vdev_create(instance, type, ptr_arg); break; case MR_SENDPATH_ROUTE_NORMAL: case MR_SENDPATH_ROUTE_SPEC_DEV: sendpath = sendpath_route_create(instance, type, ptr_arg); break; default: MR_ERROR("Invalided sendpath type in creating sendpath, Failed. "); sendpath = NULL; } va_end(ptr_arg); return sendpath; } int marsio_sendpath_option_set(struct mr_instance * instance, struct mr_sendpath * sendpath, int opt, ...) { va_list ptr_arg; int ret = 0; va_start(ptr_arg, opt); if (sendpath->fn_option_set) ret = sendpath->fn_option_set(instance, sendpath, opt, ptr_arg); va_end(ptr_arg); return ret; } int marsio_sendpath_option_get(struct mr_instance * instance, struct mr_sendpath * sendpath, int opt, ...) { va_list ptr_arg; int ret = 0; va_start(ptr_arg, opt); if (sendpath->fn_option_get) ret = sendpath->fn_option_get(instance, sendpath, opt, ptr_arg); va_end(ptr_arg); return ret; } void marsio_sendpath_destory(struct mr_sendpath * sendpath) { if (sendpath->fn_destory != NULL) sendpath->fn_destory(sendpath); assert(sendpath->fn_destory != NULL); } /* 以下函数用于保持兼容性 */ struct mr_sendpath * marsio_sendpath_create_by_droute(struct mr_vdev * dest_device, struct in_addr addr) { return marsio_sendpath_create(dest_device->instance, MR_SENDPATH_ROUTE_SPEC_DEV, dest_device, addr); } struct mr_sendpath * marsio_sendpath_create_by_route(struct mr_instance * instance, struct in_addr addr) { return marsio_sendpath_create(instance, MR_SENDPATH_ROUTE_NORMAL, addr); } struct mr_sendpath * marsio_sendpath_create_by_vdev(struct mr_vdev * dest_device) { return marsio_sendpath_create(dest_device->instance, MR_SENDPATH_VDEV, dest_device); }