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:
parent
71575b2115
commit
db22d2366e
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue