In ODP_PACKET_SOCKET_MMSG or ODP_PACKET_SOCKET_BASIC modes, when the same interface is opened multiple times an attempt is made to use a single socket descriptor for all instances. There are a few issues with the implementation though;
- a desciptor value of 0 is used to indicate an unused entry, but this is a valid value for a socket descriptor - the first call to odp_pktio_close() will close the socket leaving any other instances with a stale descriptor - descriptors are never removed from the raw_sockets list, so the sequence open->close->open for a single interface results in a stale descriptor Signed-off-by: Stuart Haslam <stuart.has...@arm.com> --- platform/linux-generic/odp_packet_socket.c | 56 +++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/platform/linux-generic/odp_packet_socket.c b/platform/linux-generic/odp_packet_socket.c index 0492d1e..68983eb 100644 --- a/platform/linux-generic/odp_packet_socket.c +++ b/platform/linux-generic/odp_packet_socket.c @@ -85,6 +85,7 @@ int sendmmsg(int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags) typedef struct { const char *netdev; int fd; + int refcnt; } raw_socket_t; static raw_socket_t raw_sockets[MAX_RAW_SOCKETS_NETDEVS]; @@ -136,18 +137,19 @@ static int add_raw_fd(const char *netdev, int fd) { int i; - for (i = 0; i < MAX_RAW_SOCKETS_NETDEVS; i++) { - if (raw_sockets[i].fd == 0) + for (i = 0; i < MAX_RAW_SOCKETS_NETDEVS; i++) + if (raw_sockets[i].refcnt == 0) break; - } - if (i > (MAX_RAW_SOCKETS_NETDEVS - 1)) { + if (i >= MAX_RAW_SOCKETS_NETDEVS) { ODP_ERR("too many sockets\n"); return -1; } - raw_sockets[i].fd = fd; + raw_sockets[i].fd = fd; raw_sockets[i].netdev = netdev; + raw_sockets[i].refcnt = 1; + return 0; } @@ -156,15 +158,39 @@ static int find_raw_fd(const char *netdev) int i; for (i = 0; i < MAX_RAW_SOCKETS_NETDEVS; i++) { - if (raw_sockets[i].fd == 0) - break; + if (raw_sockets[i].refcnt == 0) + continue; - if (!strcmp(raw_sockets[i].netdev, netdev)) + if (!strcmp(raw_sockets[i].netdev, netdev)) { + raw_sockets[i].refcnt++; return raw_sockets[i].fd; + } } - return 0; + + return -1; } +static int remove_raw_fd(int fd) +{ + int i; + + for (i = 0; i < MAX_RAW_SOCKETS_NETDEVS; i++) { + if (raw_sockets[i].refcnt == 0 || raw_sockets[i].fd != fd) + continue; + + raw_sockets[i].refcnt--; + + if (raw_sockets[i].refcnt == 0) { + raw_sockets[i].fd = -1; + raw_sockets[i].netdev = NULL; + return 0; + } + + return 1; + } + + return -1; +} /* * ODP_PACKET_SOCKET_BASIC: @@ -204,7 +230,7 @@ int setup_pkt_sock(pkt_sock_t *const pkt_sock, const char *netdev, odp_spinlock_lock(&raw_sockets_lock); sockfd = find_raw_fd(netdev); - if (sockfd) { + if (sockfd != -1) { pkt_sock->sockfd = sockfd; odp_spinlock_unlock(&raw_sockets_lock); return sockfd; @@ -263,7 +289,13 @@ error: */ int close_pkt_sock(pkt_sock_t *const pkt_sock) { - if (close(pkt_sock->sockfd) != 0) { + int ret; + + odp_spinlock_lock(&raw_sockets_lock); + ret = remove_raw_fd(pkt_sock->sockfd); + odp_spinlock_unlock(&raw_sockets_lock); + + if (ret == 0 && close(pkt_sock->sockfd) != 0) { perror("close_pkt_sock() - close(sockfd)"); return -1; } @@ -877,7 +909,7 @@ int close_pkt_sock_mmap(pkt_sock_mmap_t *const pkt_sock) { mmap_unmap_sock(pkt_sock); if (close(pkt_sock->sockfd) != 0) { - perror("close_pkt_sock() - close(sockfd)"); + perror("close_pkt_sock_mmap() - close(sockfd)"); return -1; } -- 2.1.1 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org http://lists.linaro.org/mailman/listinfo/lng-odp