在一文中提到了Zephyr网络传输offloading支持socket offloading API, 本文就如何将第三方socket以offloading的方式添加到zephyr中进行说明。
本文只说明如何添加,不说明第三方socket的具体实现形式,后文中以vender_ 开头的函数均为第三方socket需要porting的函数。
1.配置
配置CONFIG_NET_SOCKETS_OFFLOAD=y
,编译时会启用socket offload
2. 注册dns查询函数
按照下列函数指针的模式使用第三方socket API实现dns查询函数vender_getaddrinfo/vender_freeaddrinfo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
struct socket_dns_offload { int (*getaddrinfo)(const char *node, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res); void (*freeaddrinfo)(struct zsock_addrinfo *res); };
static int vender_getaddrinfo(const char *node, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res) { ... }
static voidvender_freeaddrinfo(struct zsock_addrinfo *res) { ... }
|
用实现的函数初始化一个socket_dns_offload结构体变量, 并注册到socket_offload中
1 2 3 4 5 6
|
const struct socket_dns_offload vender_dns_ops = { .getaddrinfo = vender_getaddrinfo, .freeaddrinfo = vender_getaddrinfo, };
socket_offload_dns_register(&vender_dns_ops);
|
3. 实现socket API
按照struct socket_op_vtable的定义使用第三方socket API实现zephyr的socket抽象,总计要实现read/write/close/ioctrl/bind/connect/listen/accept/sendto/recvfrom/getsockopt/setsockopt/sendmsg/getsockname总计14个,这里以列出read和bind示意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
struct socket_op_vtable { struct fd_op_vtable fd_vtable; int (*bind)(void *obj, const struct sockaddr *addr, socklen_t addrlen); int (*connect)(void *obj, const struct sockaddr *addr, socklen_t addrlen); int (*listen)(void *obj, int backlog); int (*accept)(void *obj, struct sockaddr *addr, socklen_t *addrlen); ssize_t (*sendto)(void *obj, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t (*recvfrom)(void *obj, void *buf, size_t max_len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); int (*getsockopt)(void *obj, int level, int optname, void *optval, socklen_t *optlen); int (*setsockopt)(void *obj, int level, int optname, const void *optval, socklen_t optlen); ssize_t (*sendmsg)(void *obj, const struct msghdr *msg, int flags); int (*getsockname)(void *obj, struct sockaddr *addr, socklen_t *addrlen); };
static ssize_t vender_read(void *obj, void *buffer, size_t count) { ... }
static int vender_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen) { ... }
|
用实现的函数初始化一个struct socket_op_vtable结构体变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
static const struct socket_op_vtable vender_socket_fd_op_vtable = { .fd_vtable = { .read = vender_read, .write = vender_write, .close = vender_close, .ioctl = vender_ioctl, }, .bind = vender_bind, .connect = vender_connect, .listen = vender_listen, .accept = vender_socket_accept, .sendto = vender_sendto, .sendmsg = vender_sendmsg, .recvfrom = vender_recvfrom, .getsockopt = vender_getsockopt, .setsockopt = vender_setsockopt, };
|
4.实现注册函数并注册
按照下列形式实现is_supported和handler,
1 2 3 4 5
|
struct net_socket_register { int family; bool (*is_supported)(int family, int type, int proto); int (*handler)(int family, int type, int proto); };
|
is_supported用于判断socket是否支持该协议族(family),socket类型(type), 和协议(proto), 例如我的第三方offload socket全部都支持就直接返回true
1 2 3 4 5
|
static bool vender_is_supported(int family, int type, int proto) { /* TODO offloading always enabled for now. */ return true; }
|
handler是用于创建socket的函数,该函数中负责将vender_socket_fd_op_vtable注册到fdtable内,实现如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
static int vender_socket_create(int family, int type, int proto) { //预定fd int fd = z_reserve_fd(); int sock;
if (fd < 0) { return -1; }
//这里是实际的vender socket操作 sock = vender_socket(family, type, proto); if (sock < 0) { z_free_fd(fd); return -1; }
//将vender_socket_fd_op_vtable注册给fd,之后zephyr的socket实现可以通过fd的vtable来调用vender_socket_fd_op_vtable中的socket API z_finalize_fd(fd, SD_TO_OBJ(sock), (const struct fd_op_vtable *) &vender_socket_fd_op_vtable);
return fd; }
|
使用下面宏进行注册,Zephyr的socket就可以调用到vender的socket实现了。
1
|
NET_SOCKET_REGISTER(vender, AF_UNSPEC, vender_is_supported, vender_socket_create);
|
以上4步做完后,zephyr中使用socket编程,最终都会调用到vender_ 这一组由第三方socket porting的API。
到底了,关注获取新文章