crypto_sync: sync_crypto_write_no_delay to flush TCP after critical packets.

Avoid that 200ms loss.  We don't want to disable nagle generally,
since it's great for gossip and other traffic; we just want to push at
critical times.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-08-09 10:00:30 +09:30 committed by Christian Decker
parent 71575b2115
commit db22d2366e
2 changed files with 52 additions and 0 deletions

View File

@ -7,6 +7,9 @@
#include <common/utils.h>
#include <errno.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <wire/wire.h>
#include <wire/wire_sync.h>
@ -48,6 +51,51 @@ void sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES)
#endif
}
/* We're happy for the kernel to batch update and gossip messages, but a
* commitment message, for example, should be instantly sent. There's no
* great way of doing this, unfortunately.
*
* Setting TCP_NODELAY on Linux flushes the socket, which really means
* we'd want to toggle on then off it *after* sending. But Linux has
* TCP_CORK. On FreeBSD, it seems (looking at source) not to, so
* there we'd want to set it before the send, and reenable it
* afterwards. Even if this is wrong on other non-Linux platforms, it
* only means one extra packet.
*/
void sync_crypto_write_no_delay(struct crypto_state *cs, int fd,
const void *msg TAKES)
{
int val;
int opt;
const char *optname;
static bool complained = false;
#ifdef TCP_CORK
opt = TCP_CORK;
optname = "TCP_CORK";
#elif defined(TCP_NODELAY)
opt = TCP_NODELAY;
optname = "TCP_NODELAY";
#else
#error "Please report platform with neither TCP_CORK nor TCP_NODELAY?"
#endif
val = 1;
if (setsockopt(fd, IPPROTO_TCP, opt, &val, sizeof(val)) != 0) {
/* This actually happens in testing, where we blackhole the fd */
if (!complained) {
status_broken("setsockopt %s=1: %s",
optname,
strerror(errno));
complained = true;
}
}
sync_crypto_write(cs, fd, msg);
val = 0;
setsockopt(fd, IPPROTO_TCP, opt, &val, sizeof(val));
}
u8 *sync_crypto_read(const tal_t *ctx, struct crypto_state *cs, int fd)
{
u8 hdr[18], *enc, *dec;

View File

@ -9,6 +9,10 @@ struct crypto_state;
/* Exits with peer_failed_connection_lost() if write fails. */
void sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES);
/* Same, but disabled nagle for this message. */
void sync_crypto_write_no_delay(struct crypto_state *cs, int fd,
const void *msg TAKES);
/* Exits with peer_failed_connection_lost() if can't read packet. */
u8 *sync_crypto_read(const tal_t *ctx, struct crypto_state *cs, int fd);