summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSander Vrijders <sander.vrijders@ugent.be>2018-10-03 15:32:22 +0200
committerDimitri Staessens <dimitri.staessens@ugent.be>2018-10-03 15:55:52 +0200
commit937adca2a718b160b6d42bb8a3f28d96321fdb49 (patch)
tree8bb9fc76d36676cf18d52349081d8e067a38f16b
parentc9a54ee6b45c8566cf2d24f9763907451b50f7c1 (diff)
downloadouroboros-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 <sander.vrijders@ugent.be> Signed-off-by: Dimitri Staessens <dimitri.staessens@ugent.be>
-rw-r--r--src/ipcpd/eth/eth.c20
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(&eth_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(&eth_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(&eth_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(&eth_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 *) &eth_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;
}