diff options
author | Sander Vrijders <[email protected]> | 2018-10-03 15:32:22 +0200 |
---|---|---|
committer | Dimitri Staessens <[email protected]> | 2018-10-03 15:55:52 +0200 |
commit | 937adca2a718b160b6d42bb8a3f28d96321fdb49 (patch) | |
tree | 8bb9fc76d36676cf18d52349081d8e067a38f16b /src/ipcpd/eth/eth.c | |
parent | c9a54ee6b45c8566cf2d24f9763907451b50f7c1 (diff) | |
download | ouroboros-937adca2a718b160b6d42bb8a3f28d96321fdb49.tar.gz ouroboros-937adca2a718b160b6d42bb8a3f28d96321fdb49.zip |
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 <[email protected]>
Signed-off-by: Dimitri Staessens <[email protected]>
Diffstat (limited to 'src/ipcpd/eth/eth.c')
-rw-r--r-- | src/ipcpd/eth/eth.c | 20 |
1 files 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; } |