summaryrefslogtreecommitdiff
path: root/src/ipcpd
diff options
context:
space:
mode:
authorSander Vrijders <[email protected]>2018-10-03 15:32:22 +0200
committerDimitri Staessens <[email protected]>2018-10-03 15:55:52 +0200
commit937adca2a718b160b6d42bb8a3f28d96321fdb49 (patch)
tree8bb9fc76d36676cf18d52349081d8e067a38f16b /src/ipcpd
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 <[email protected]> Signed-off-by: Dimitri Staessens <[email protected]>
Diffstat (limited to 'src/ipcpd')
-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;
}