From 937adca2a718b160b6d42bb8a3f28d96321fdb49 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 3 Oct 2018 15:32:22 +0200 Subject: ipcpd: Use non-blocking socket in Ethernet IPCP Since the Ethernet IPCP now has multiple reader threads it was possible that both exit the select call, which caused one of the two threads to block on the recv call. This makes the socket non-blocking so that the recv call simply fails. Signed-off-by: Sander Vrijders Signed-off-by: Dimitri Staessens --- src/ipcpd/eth/eth.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c index 05dd9ac7..44ef3756 100644 --- a/src/ipcpd/eth/eth.c +++ b/src/ipcpd/eth/eth.c @@ -991,7 +991,6 @@ static void * eth_ipcp_sdu_writer(void * o) while (true) { fevent(eth_data.np1_flows, fq, NULL); - pthread_rwlock_rdlock(ð_data.flows_lock); while ((fd = fqueue_next(fq)) >= 0) { if (ipcp_flow_read(fd, &sdb)) { log_dbg("Bad read from fd %d.", fd); @@ -1005,6 +1004,8 @@ static void * eth_ipcp_sdu_writer(void * o) log_dbg("Failed to allocate header."); ipcp_sdb_release(sdb); } + + pthread_rwlock_rdlock(ð_data.flows_lock); #if defined(BUILD_ETH_DIX) deid = eth_data.fd_to_ef[fd].r_eid; #elif defined(BUILD_ETH_LLC) @@ -1015,6 +1016,8 @@ static void * eth_ipcp_sdu_writer(void * o) eth_data.fd_to_ef[fd].r_addr, MAC_SIZE); + pthread_rwlock_unlock(ð_data.flows_lock); + eth_ipcp_send_frame(r_addr, #if defined(BUILD_ETH_DIX) deid, @@ -1025,7 +1028,6 @@ static void * eth_ipcp_sdu_writer(void * o) len); ipcp_sdb_release(sdb); } - pthread_rwlock_unlock(ð_data.flows_lock); } pthread_cleanup_pop(true); @@ -1202,6 +1204,7 @@ static int eth_ipcp_bootstrap(const struct ipcp_config * conf) #endif #if defined(HAVE_RAW_SOCKETS) int qdisc_bypass = 1; + int flags; #endif assert(conf); assert(conf->type == THIS_TYPE); @@ -1368,6 +1371,17 @@ static int eth_ipcp_bootstrap(const struct ipcp_config * conf) return -1; } + flags = fcntl(eth_data.s_fd, F_GETFL, 0); + if (flags < 0) { + log_err("Failed to get flags."); + goto fail_device; + } + + if (fcntl(eth_data.s_fd, F_SETFL, flags | O_NONBLOCK)) { + log_err("Failed to set socket non-blocking."); + goto fail_device; + } + if (setsockopt(eth_data.s_fd, SOL_PACKET, PACKET_QDISC_BYPASS, &qdisc_bypass, sizeof(qdisc_bypass))) { log_info("Qdisc bypass not supported."); @@ -1375,7 +1389,7 @@ static int eth_ipcp_bootstrap(const struct ipcp_config * conf) if (bind(eth_data.s_fd, (struct sockaddr *) ð_data.device, sizeof(eth_data.device))) { - log_err("Failed to bind socket to interface"); + log_err("Failed to bind socket to interface."); goto fail_device; } -- cgit v1.2.3