Commit 9fac978e authored by Leonardo Lai's avatar Leonardo Lai

bugfix: failed to receive packets on INADDR_ANY

parent d61b436e
...@@ -7,10 +7,13 @@ ...@@ -7,10 +7,13 @@
// the IPs bound to that port (typically one, but can be many) // the IPs bound to that port (typically one, but can be many)
// //
#include <arpa/inet.h> // inet_ntop
#include <netinet/in.h> // INADDR_ANY #include <netinet/in.h> // INADDR_ANY
#include "udpdk_bind_table.h" #include "udpdk_bind_table.h"
#include "udpdk_shmalloc.h" #include "udpdk_shmalloc.h"
#define RTE_LOGTYPE_BTABLE RTE_LOGTYPE_USER1
const void *bind_info_alloc = NULL; const void *bind_info_alloc = NULL;
list_t **sock_bind_table; list_t **sock_bind_table;
...@@ -34,13 +37,14 @@ int btable_get_free_port(void) ...@@ -34,13 +37,14 @@ int btable_get_free_port(void)
return i; return i;
} }
} }
RTE_LOG(WARNING, BTABLE, "Failed to find a free port\n");
return -1; return -1;
} }
/* Verify if binding the pair (ip, port) is possible, provided the /* Verify if binding the pair (ip, port) is possible, provided the
* options and the previous bindings. * options and the previous bindings.
*/ */
static inline int btable_can_bind(struct in_addr ip, int port, int opts) static inline bool btable_can_bind(struct in_addr ip, int port, int opts)
{ {
bool reuse_addr = opts & SO_REUSEADDR; bool reuse_addr = opts & SO_REUSEADDR;
bool reuse_port = opts & SO_REUSEPORT; bool reuse_port = opts & SO_REUSEPORT;
...@@ -52,7 +56,7 @@ static inline int btable_can_bind(struct in_addr ip, int port, int opts) ...@@ -52,7 +56,7 @@ static inline int btable_can_bind(struct in_addr ip, int port, int opts)
bool oth_reuseport; bool oth_reuseport;
if (sock_bind_table[port] == NULL) { if (sock_bind_table[port] == NULL) {
return 0; return true;
} }
ip_new = ip.s_addr; ip_new = ip.s_addr;
...@@ -81,11 +85,7 @@ static inline int btable_can_bind(struct in_addr ip, int port, int opts) ...@@ -81,11 +85,7 @@ static inline int btable_can_bind(struct in_addr ip, int port, int opts)
} }
list_iterator_destroy(it); list_iterator_destroy(it);
if (can_bind) { return can_bind;
return 0;
} else {
return -1;
}
} }
int btable_add_binding(int s, struct in_addr ip, int port, int opts) int btable_add_binding(int s, struct in_addr ip, int port, int opts)
...@@ -95,6 +95,9 @@ int btable_add_binding(int s, struct in_addr ip, int port, int opts) ...@@ -95,6 +95,9 @@ int btable_add_binding(int s, struct in_addr ip, int port, int opts)
// Check if binding this pair is allowed // Check if binding this pair is allowed
if (!btable_can_bind(ip, port, opts)) { if (!btable_can_bind(ip, port, opts)) {
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ip, buf, sizeof(buf));
RTE_LOG(WARNING, BTABLE, "Cannot bind socket %d to %s:%d\n", s, buf, ntohs(port));
return -1; return -1;
} }
......
...@@ -312,6 +312,8 @@ static inline void reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queu ...@@ -312,6 +312,8 @@ static inline void reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queu
uint16_t udp_dst_port; uint16_t udp_dst_port;
unsigned long ip_dst_addr; unsigned long ip_dst_addr;
int sock_id; int sock_id;
bool delivered_once = false;
bool delivered_last = false;
rxq = &qconf->rx_queue; rxq = &qconf->rx_queue;
...@@ -360,26 +362,39 @@ static inline void reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queu ...@@ -360,26 +362,39 @@ static inline void reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queu
// Find the sock_ids corresponding to the UDP dst port (L4 switching) and enqueue the packet to its queue // Find the sock_ids corresponding to the UDP dst port (L4 switching) and enqueue the packet to its queue
list_t *binds = btable_get_bindings(udp_dst_port); list_t *binds = btable_get_bindings(udp_dst_port);
if (binds == NULL) { if (binds == NULL) {
RTE_LOG(WARNING, POLLBODY, "Dropping packet for port %d: no socket bound\n", udp_dst_port); RTE_LOG(WARNING, POLLBODY, "Dropping packet for port %d: no socket bound\n", ntohs(udp_dst_port));
return; return;
} }
list_iterator_t *it = list_iterator_new(binds, LIST_HEAD); list_iterator_t *it = list_iterator_new(binds, LIST_HEAD);
list_node_t *node; list_node_t *node;
while ((node = list_iterator_next(it))) { while ((node = list_iterator_next(it))) {
// TODO hand non trivial cases (see below) unsigned long ip_oth = ((struct bind_info *)(node->val))->ip_addr.s_addr;
/* bool oth_reuseaddr = ((struct bind_info *)(node->val))->reuse_addr;
if dest unicast and not REUSEPORT (LIKELY), enqueue and break bool oth_reuseport = ((struct bind_info *)(node->val))->reuse_port;
if dest unicast and SO_REUSEPORT, should load balance // TODO the semantic should be more complex actually:
if dest broadcast and SO_REUSEADDR o SO_REUSEPORT, enqueue and continue // if dest unicast and SO_REUSEPORT, should load balance
*/ // if dest broadcast and SO_REUSEADDR or SO_REUSEPORT, should deliver to all
if (ip_dst_addr == ((struct bind_info *)(node->val))->ip_addr.s_addr) { // If matching
break; if (likely((ip_dst_addr == ip_oth) || (ip_oth == INADDR_ANY))) {
// Deliver to this socket
enqueue_rx_packet(((struct bind_info *)(node->val))->sockfd, m);
delivered_once = true;
// If other socket may exist on the same port, keep scanning
if (oth_reuseaddr || oth_reuseport) {
m = rte_pktmbuf_clone(m, rxq->pool);
delivered_last = false;
continue;
} else {
delivered_last = true;
break;
}
} }
} }
if (node != NULL) { if (!delivered_last) {
enqueue_rx_packet(((struct bind_info *)(node->val))->sockfd, m); rte_pktmbuf_free(m);
} else { }
RTE_LOG(WARNING, POLLBODY, "Dropping packet for port %d: no socket matching\n", udp_dst_port); if (!delivered_once) {
RTE_LOG(WARNING, POLLBODY, "Dropped packet to port %d: no socket matching\n", ntohs(udp_dst_port));
} }
list_iterator_destroy(it); list_iterator_destroy(it);
} }
......
...@@ -218,7 +218,6 @@ static int bind_validate_args(int sockfd, const struct sockaddr *addr, socklen_t ...@@ -218,7 +218,6 @@ static int bind_validate_args(int sockfd, const struct sockaddr *addr, socklen_t
int udpdk_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int udpdk_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{ {
int ret;
unsigned short port; unsigned short port;
const struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; const struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
...@@ -229,8 +228,7 @@ int udpdk_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) ...@@ -229,8 +228,7 @@ int udpdk_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
// Try to bind the socket // Try to bind the socket
port = addr_in->sin_port; port = addr_in->sin_port;
ret = btable_add_binding(sockfd, addr_in->sin_addr, port, exch_zone_desc->slots[sockfd].so_options); if (btable_add_binding(sockfd, addr_in->sin_addr, port, exch_zone_desc->slots[sockfd].so_options) < 0) {
if (ret != -1) {
errno = EADDRINUSE; errno = EADDRINUSE;
RTE_LOG(ERR, SYSCALL, "Failed to bind because port %d is already in use\n", ntohs(port)); RTE_LOG(ERR, SYSCALL, "Failed to bind because port %d is already in use\n", ntohs(port));
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment