aboutgitcodebugslistschat
path: root/tcp_splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'tcp_splice.c')
-rw-r--r--tcp_splice.c446
1 files changed, 235 insertions, 211 deletions
diff --git a/tcp_splice.c b/tcp_splice.c
index f048a82..4b01f1a 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -44,7 +44,6 @@
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
-#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -56,6 +55,7 @@
#include "siphash.h"
#include "inany.h"
#include "flow.h"
+#include "epoll_ctl.h"
#include "flow_table.h"
@@ -95,7 +95,7 @@ static int tcp_conn_sock_ns(const struct ctx *c, sa_family_t af);
* conn_at_sidx() - Get spliced TCP connection specific flow at given sidx
* @sidx: Flow and side to retrieve
*
- * Return: Spliced TCP connection at @sidx, or NULL of @sidx is invalid.
+ * Return: spliced TCP connection at @sidx, or NULL of @sidx is invalid.
* Asserts if the flow at @sidx is not FLOW_TCP_SPLICE.
*/
static struct tcp_splice_conn *conn_at_sidx(flow_sidx_t sidx)
@@ -105,7 +105,7 @@ static struct tcp_splice_conn *conn_at_sidx(flow_sidx_t sidx)
if (!flow)
return NULL;
- ASSERT(flow->f.type == FLOW_TCP_SPLICE);
+ assert(flow->f.type == FLOW_TCP_SPLICE);
return &flow->tcp_splice;
}
@@ -114,68 +114,56 @@ static struct tcp_splice_conn *conn_at_sidx(flow_sidx_t sidx)
* @events: Connection event flags
* @ev: Events to fill in, 0 is accepted socket, 1 is connecting socket
*/
-static void tcp_splice_conn_epoll_events(uint16_t events,
- struct epoll_event ev[])
+static uint32_t tcp_splice_conn_epoll_events(uint16_t events, unsigned sidei)
{
- unsigned sidei;
-
- flow_foreach_sidei(sidei)
- ev[sidei].events = 0;
+ uint32_t e = 0;
if (events & SPLICE_ESTABLISHED) {
- flow_foreach_sidei(sidei) {
- if (!(events & FIN_SENT(!sidei)))
- ev[sidei].events = EPOLLIN | EPOLLRDHUP;
- }
- } else if (events & SPLICE_CONNECT) {
- ev[1].events = EPOLLOUT;
+ if (!(events & FIN_SENT(!sidei)))
+ e = EPOLLIN | EPOLLRDHUP;
+ } else if (sidei == 1 && events & SPLICE_CONNECT) {
+ e = EPOLLOUT;
}
- flow_foreach_sidei(sidei)
- ev[sidei].events |= (events & OUT_WAIT(sidei)) ? EPOLLOUT : 0;
+ if (events & OUT_WAIT(sidei))
+ e |= EPOLLOUT;
+ if (events & OUT_WAIT(!sidei))
+ e &= ~EPOLLIN;
+
+ return e;
}
/**
* tcp_splice_epoll_ctl() - Add/modify/delete epoll state from connection events
- * @c: Execution context
* @conn: Connection pointer
+ * @now: Current timestamp
*
* Return: 0 on success, negative error code on failure (not on deletion)
*/
-static int tcp_splice_epoll_ctl(const struct ctx *c,
- struct tcp_splice_conn *conn)
+static int tcp_splice_epoll_ctl(struct tcp_splice_conn *conn,
+ const struct timespec *now)
{
- int m = conn->in_epoll ? EPOLL_CTL_MOD : EPOLL_CTL_ADD;
- const union epoll_ref ref[SIDES] = {
- { .type = EPOLL_TYPE_TCP_SPLICE, .fd = conn->s[0],
- .flowside = FLOW_SIDX(conn, 0) },
- { .type = EPOLL_TYPE_TCP_SPLICE, .fd = conn->s[1],
- .flowside = FLOW_SIDX(conn, 1) }
- };
- struct epoll_event ev[SIDES] = { { .data.u64 = ref[0].u64 },
- { .data.u64 = ref[1].u64 } };
-
- tcp_splice_conn_epoll_events(conn->events, ev);
-
- if (epoll_ctl(c->epollfd, m, conn->s[0], &ev[0]) ||
- epoll_ctl(c->epollfd, m, conn->s[1], &ev[1])) {
+ uint32_t events[2];
+
+ events[0] = tcp_splice_conn_epoll_events(conn->events, 0);
+ events[1] = tcp_splice_conn_epoll_events(conn->events, 1);
+
+ if (flow_epoll_set(&conn->f, EPOLL_CTL_MOD, events[0], conn->s[0], 0) ||
+ flow_epoll_set(&conn->f, EPOLL_CTL_MOD, events[1], conn->s[1], 1)) {
int ret = -errno;
- flow_err(conn, "ERROR on epoll_ctl(): %s", strerror_(errno));
+ flow_perror_ratelimit(conn, now, "ERROR on epoll_ctl()");
return ret;
}
- conn->in_epoll = true;
-
return 0;
}
/**
* conn_flag_do() - Set/unset given flag, log, update epoll on CLOSING flag
- * @c: Execution context
* @conn: Connection pointer
* @flag: Flag to set, or ~flag to unset
*/
-static void conn_flag_do(const struct ctx *c, struct tcp_splice_conn *conn,
+static void conn_flag_do(struct tcp_splice_conn *conn,
unsigned long flag)
{
if (flag & (flag - 1)) {
@@ -200,25 +188,25 @@ static void conn_flag_do(const struct ctx *c, struct tcp_splice_conn *conn,
}
if (flag == CLOSING) {
- epoll_del(c, conn->s[0]);
- epoll_del(c, conn->s[1]);
+ epoll_del(flow_epollfd(&conn->f), conn->s[0]);
+ epoll_del(flow_epollfd(&conn->f), conn->s[1]);
}
}
-#define conn_flag(c, conn, flag) \
+#define conn_flag(conn, flag) \
do { \
flow_trace(conn, "flag at %s:%i", __func__, __LINE__); \
- conn_flag_do(c, conn, flag); \
+ conn_flag_do(conn, flag); \
} while (0)
/**
* conn_event_do() - Set and log connection events, update epoll state
- * @c: Execution context
* @conn: Connection pointer
* @event: Connection event
+ * @now: Current timestamp
*/
-static void conn_event_do(const struct ctx *c, struct tcp_splice_conn *conn,
- unsigned long event)
+static void conn_event_do(struct tcp_splice_conn *conn, unsigned long event,
+ const struct timespec *now)
{
if (event & (event - 1)) {
int flag_index = fls(~event);
@@ -240,16 +228,33 @@ static void conn_event_do(const struct ctx *c, struct tcp_splice_conn *conn,
flow_dbg(conn, "%s", tcp_splice_event_str[flag_index]);
}
- if (tcp_splice_epoll_ctl(c, conn))
- conn_flag(c, conn, CLOSING);
+ if (tcp_splice_epoll_ctl(conn, now))
+ conn_flag(conn, CLOSING);
}
-#define conn_event(c, conn, event) \
+#define conn_event(conn, event, now) \
do { \
flow_trace(conn, "event at %s:%i",__func__, __LINE__); \
- conn_event_do(c, conn, event); \
+ conn_event_do(conn, event, now); \
} while (0)
+/**
+ * tcp_splice_rst() - Close spliced connection forcing RST on each side
+ * @conn: Connection pointer
+ */
+static void tcp_splice_rst(struct tcp_splice_conn *conn)
+{
+ unsigned sidei;
+
+ if (conn->flags & CLOSING)
+ return; /* Nothing to do */
+
+ /* Force RST on sockets to inform the peer */
+ flow_foreach_sidei(sidei)
+ tcp_linger0(conn, conn->s[sidei]);
+
+ conn_flag(conn, CLOSING);
+}
/**
* tcp_splice_flow_defer() - Deferred per-flow handling (clean up closed)
@@ -277,7 +282,7 @@ bool tcp_splice_flow_defer(struct tcp_splice_conn *conn)
conn->s[sidei] = -1;
}
- conn->read[sidei] = conn->written[sidei] = 0;
+ conn->pending[sidei] = 0;
}
conn->events = SPLICE_CLOSED;
@@ -291,11 +296,13 @@ bool tcp_splice_flow_defer(struct tcp_splice_conn *conn)
* tcp_splice_connect_finish() - Completion of connect() or call on success
* @c: Execution context
* @conn: Connection pointer
+ * @now: Current timestamp
*
* Return: 0 on success, -EIO on failure
*/
static int tcp_splice_connect_finish(const struct ctx *c,
- struct tcp_splice_conn *conn)
+ struct tcp_splice_conn *conn,
+ const struct timespec *now)
{
unsigned sidei;
int i = 0;
@@ -313,9 +320,11 @@ static int tcp_splice_connect_finish(const struct ctx *c,
if (conn->pipe[sidei][0] < 0) {
if (pipe2(conn->pipe[sidei], O_NONBLOCK | O_CLOEXEC)) {
- flow_err(conn, "cannot create %d->%d pipe: %s",
- sidei, !sidei, strerror_(errno));
- conn_flag(c, conn, CLOSING);
+ flow_perror_ratelimit(
+ conn, now,
+ "cannot create %d->%d pipe",
+ sidei, !sidei);
+ tcp_splice_rst(conn);
return -EIO;
}
@@ -329,7 +338,7 @@ static int tcp_splice_connect_finish(const struct ctx *c,
}
if (!(conn->events & SPLICE_ESTABLISHED))
- conn_event(c, conn, SPLICE_ESTABLISHED);
+ conn_event(conn, SPLICE_ESTABLISHED, now);
return 0;
}
@@ -338,24 +347,25 @@ static int tcp_splice_connect_finish(const struct ctx *c,
* tcp_splice_connect() - Create and connect socket for new spliced connection
* @c: Execution context
* @conn: Connection pointer
+ * @now: Current timestamp
*
* Return: 0 for connect() succeeded or in progress, negative value on error
*/
-static int tcp_splice_connect(const struct ctx *c, struct tcp_splice_conn *conn)
+static int tcp_splice_connect(const struct ctx *c, struct tcp_splice_conn *conn,
+ const struct timespec *now)
{
const struct flowside *tgt = &conn->f.side[TGTSIDE];
sa_family_t af = inany_v4(&tgt->eaddr) ? AF_INET : AF_INET6;
uint8_t tgtpif = conn->f.pif[TGTSIDE];
union sockaddr_inany sa;
- socklen_t sl;
int one = 1;
if (tgtpif == PIF_HOST)
- conn->s[1] = tcp_conn_sock(c, af);
+ conn->s[1] = tcp_conn_sock(af);
else if (tgtpif == PIF_SPLICE)
conn->s[1] = tcp_conn_sock_ns(c, af);
else
- ASSERT(0);
+ assert(0);
if (conn->s[1] < 0)
return -1;
@@ -375,19 +385,27 @@ static int tcp_splice_connect(const struct ctx *c, struct tcp_splice_conn *conn)
conn->s[1]);
}
- pif_sockaddr(c, &sa, &sl, tgtpif, &tgt->eaddr, tgt->eport);
+ pif_sockaddr(c, &sa, tgtpif, &tgt->eaddr, tgt->eport);
+
+ flow_epollid_set(&conn->f, EPOLLFD_ID_DEFAULT);
+ if (flow_epoll_set(&conn->f, EPOLL_CTL_ADD, 0, conn->s[0], 0) ||
+ flow_epoll_set(&conn->f, EPOLL_CTL_ADD, 0, conn->s[1], 1)) {
+ int ret = -errno;
+ flow_perror_ratelimit(conn, now, "Cannot register to epollfd");
+ return ret;
+ }
+
+ conn_event(conn, SPLICE_CONNECT, now);
- if (connect(conn->s[1], &sa.sa, sl)) {
+ if (connect(conn->s[1], &sa.sa, socklen_inany(&sa))) {
if (errno != EINPROGRESS) {
flow_trace(conn, "Couldn't connect socket for splice: %s",
strerror_(errno));
return -errno;
}
-
- conn_event(c, conn, SPLICE_CONNECT);
} else {
- conn_event(c, conn, SPLICE_ESTABLISHED);
- return tcp_splice_connect_finish(c, conn);
+ conn_event(conn, SPLICE_ESTABLISHED, now);
+ return tcp_splice_connect_finish(c, conn, now);
}
return 0;
@@ -398,7 +416,7 @@ static int tcp_splice_connect(const struct ctx *c, struct tcp_splice_conn *conn)
* @c: Execution context
* @af: Address family (AF_INET or AF_INET6)
*
- * Return: Socket fd in the namespace on success, -errno on failure
+ * Return: socket fd in the namespace on success, -errno on failure
*/
static int tcp_conn_sock_ns(const struct ctx *c, sa_family_t af)
{
@@ -427,15 +445,17 @@ static int tcp_conn_sock_ns(const struct ctx *c, sa_family_t af)
* @flow: flow to initialise
* @s0: Accepted (side 0) socket
* @sa: Peer address of connection
+ * @now: Current timestamp
*
* #syscalls:pasta setsockopt
*/
-void tcp_splice_conn_from_sock(const struct ctx *c, union flow *flow, int s0)
+void tcp_splice_conn_from_sock(const struct ctx *c, union flow *flow, int s0,
+ const struct timespec *now)
{
struct tcp_splice_conn *conn = FLOW_SET_TYPE(flow, FLOW_TCP_SPLICE,
tcp_splice);
- ASSERT(c->mode == MODE_PASTA);
+ assert(c->mode == MODE_PASTA);
conn->s[0] = s0;
conn->s[1] = -1;
@@ -445,189 +465,194 @@ void tcp_splice_conn_from_sock(const struct ctx *c, union flow *flow, int s0)
if (setsockopt(s0, SOL_TCP, TCP_QUICKACK, &((int){ 1 }), sizeof(int)))
flow_trace(conn, "failed to set TCP_QUICKACK on %i", s0);
- if (tcp_splice_connect(c, conn))
- conn_flag(c, conn, CLOSING);
+ if (tcp_splice_connect(c, conn, now))
+ tcp_splice_rst(conn);
FLOW_ACTIVATE(conn);
}
/**
- * tcp_splice_sock_handler() - Handler for socket mapped to spliced connection
+ * tcp_splice_forward() - Forward data in one direction using splice()
* @c: Execution context
- * @ref: epoll reference
- * @events: epoll events bitmap
+ * @conn: Connection to forward data for
+ * @fromsidei: Side to forward data from
+ * @now: Current timestamp
+ *
+ * Return: 0 on success, -1 on error (connection should be reset)
*
* #syscalls:pasta splice
*/
-void tcp_splice_sock_handler(struct ctx *c, union epoll_ref ref,
- uint32_t events)
+static int tcp_splice_forward(struct ctx *c,
+ struct tcp_splice_conn *conn, unsigned fromsidei,
+ const struct timespec *now)
{
- struct tcp_splice_conn *conn = conn_at_sidx(ref.flowside);
- unsigned evsidei = ref.flowside.sidei, fromsidei;
- uint8_t lowat_set_flag, lowat_act_flag;
- int eof, never_read;
-
- ASSERT(conn->f.type == FLOW_TCP_SPLICE);
-
- if (conn->events == SPLICE_CLOSED)
- return;
-
- if (events & EPOLLERR) {
- int err, rc;
- socklen_t sl = sizeof(err);
-
- rc = getsockopt(ref.fd, SOL_SOCKET, SO_ERROR, &err, &sl);
- if (rc)
- flow_err(conn, "Error retrieving SO_ERROR: %s",
- strerror_(errno));
- else
- flow_trace(conn, "Error event on socket: %s",
- strerror_(err));
-
- goto close;
- }
-
- if (conn->events == SPLICE_CONNECT) {
- if (!(events & EPOLLOUT))
- goto close;
- if (tcp_splice_connect_finish(c, conn))
- goto close;
- }
-
- if (events & EPOLLOUT) {
- fromsidei = !evsidei;
- conn_event(c, conn, ~OUT_WAIT(evsidei));
- } else {
- fromsidei = evsidei;
- }
-
- if (events & EPOLLRDHUP)
- /* For side 0 this is fake, but implied */
- conn_event(c, conn, FIN_RCVD(evsidei));
-
-swap:
- eof = 0;
- never_read = 1;
-
- lowat_set_flag = RCVLOWAT_SET(fromsidei);
- lowat_act_flag = RCVLOWAT_ACT(fromsidei);
+ uint8_t lowat_set_flag = RCVLOWAT_SET(fromsidei);
+ uint8_t lowat_act_flag = RCVLOWAT_ACT(fromsidei);
while (1) {
- ssize_t readlen, written, pending;
+ ssize_t readlen, written;
int more = 0;
-retry:
- readlen = splice(conn->s[fromsidei], NULL,
- conn->pipe[fromsidei][1], NULL,
- c->tcp.pipe_size,
- SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
+ do
+ readlen = splice(conn->s[fromsidei], NULL,
+ conn->pipe[fromsidei][1], NULL,
+ c->tcp.pipe_size,
+ SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
+ while (readlen < 0 && errno == EINTR);
+
+ if (readlen < 0 && errno != EAGAIN) {
+ flow_perror_ratelimit(
+ conn, now, "Splicing from %s socket",
+ pif_name(conn->f.pif[fromsidei]));
+ return -1;
+ }
+
flow_trace(conn, "%zi from read-side call", readlen);
- if (readlen < 0) {
- if (errno == EINTR)
- goto retry;
-
- if (errno != EAGAIN)
- goto close;
- } else if (!readlen) {
- eof = 1;
+
+ if (readlen <= 0) {
+ if (!readlen) /* EOF */
+ conn_event(conn, FIN_RCVD(fromsidei), now);
+
+ /* We're either blocked or at EOF on the read side, and
+ * there's nothing in the pipe so there's nothing to do
+ * write side either.
+ */
+ if (!conn->pending[fromsidei])
+ break;
} else {
- never_read = 0;
+ conn->pending[fromsidei] += readlen;
if (readlen >= (long)c->tcp.pipe_size * 90 / 100)
more = SPLICE_F_MORE;
if (conn->flags & lowat_set_flag)
- conn_flag(c, conn, lowat_act_flag);
+ conn_flag(conn, lowat_act_flag);
+ }
+
+ do
+ written = splice(conn->pipe[fromsidei][0], NULL,
+ conn->s[!fromsidei], NULL,
+ c->tcp.pipe_size,
+ SPLICE_F_MOVE | more | SPLICE_F_NONBLOCK);
+ while (written < 0 && errno == EINTR);
+
+ if (written < 0 && errno != EAGAIN) {
+ flow_perror_ratelimit(
+ conn, now, "Splicing to %s socket",
+ pif_name(conn->f.pif[!fromsidei]));
+ return -1;
}
-eintr:
- written = splice(conn->pipe[fromsidei][0], NULL,
- conn->s[!fromsidei], NULL, c->tcp.pipe_size,
- SPLICE_F_MOVE | more | SPLICE_F_NONBLOCK);
flow_trace(conn, "%zi from write-side call (passed %zi)",
written, c->tcp.pipe_size);
- /* Most common case: skip updating counters. */
- if (readlen > 0 && readlen == written) {
- if (readlen >= (long)c->tcp.pipe_size * 10 / 100)
- continue;
-
- if (conn->flags & lowat_set_flag &&
- readlen > (long)c->tcp.pipe_size / 10) {
- int lowat = c->tcp.pipe_size / 4;
-
- if (setsockopt(conn->s[fromsidei], SOL_SOCKET,
- SO_RCVLOWAT,
- &lowat, sizeof(lowat))) {
- flow_trace(conn,
- "Setting SO_RCVLOWAT %i: %s",
- lowat, strerror_(errno));
- } else {
- conn_flag(c, conn, lowat_set_flag);
- conn_flag(c, conn, lowat_act_flag);
- }
- }
+ if (written < 0)
+ break;
+ conn->pending[fromsidei] -= written;
+
+ if (!conn->pending[fromsidei] && readlen <= 0) {
+ /* Read side is EOF or EAGAIN, and we emptied the pipe.
+ * No more we can do for now.
+ */
break;
}
+ }
- conn->read[fromsidei] += readlen > 0 ? readlen : 0;
- conn->written[fromsidei] += written > 0 ? written : 0;
-
- if (written < 0) {
- if (errno == EINTR)
- goto eintr;
+ /* We need write-side wakeups if and only if we have data in the pipe to
+ * drain.
+ */
+ if (conn->pending[fromsidei])
+ conn_event(conn, OUT_WAIT(!fromsidei), now);
+ else
+ conn_event(conn, ~OUT_WAIT(!fromsidei), now);
+
+ if ((conn->events & FIN_RCVD(fromsidei)) &&
+ !(conn->events & FIN_SENT(!fromsidei)) &&
+ !conn->pending[fromsidei]) {
+ if (shutdown(conn->s[!fromsidei], SHUT_WR) < 0) {
+ flow_perror_ratelimit(conn, now, "shutdown() on %s",
+ pif_name(conn->f.pif[!fromsidei]));
+ return -1;
+ }
+ conn_event(conn, FIN_SENT(!fromsidei), now);
+ }
- if (errno != EAGAIN)
- goto close;
+ return 0;
+}
- if (conn->read[fromsidei] == conn->written[fromsidei])
- break;
+/**
+ * tcp_splice_sock_handler() - Handler for socket mapped to spliced connection
+ * @c: Execution context
+ * @ref: epoll reference
+ * @events: epoll events bitmap
+ * @now: Current timestamp
+ */
+void tcp_splice_sock_handler(struct ctx *c, union epoll_ref ref,
+ uint32_t events, const struct timespec *now)
+{
+ struct tcp_splice_conn *conn = conn_at_sidx(ref.flowside);
+ unsigned evsidei = ref.flowside.sidei;
- conn_event(c, conn, OUT_WAIT(!fromsidei));
- break;
- }
+ assert(conn->f.type == FLOW_TCP_SPLICE);
- if (never_read && written == (long)(c->tcp.pipe_size))
- goto retry;
+ if (conn->events == SPLICE_CLOSED)
+ return;
- pending = conn->read[fromsidei] - conn->written[fromsidei];
- if (!never_read && written > 0 && written < pending)
- goto retry;
+ if (events & EPOLLERR) {
+ int err, rc;
+ socklen_t sl = sizeof(err);
- if (eof)
- break;
+ rc = getsockopt(ref.fd, SOL_SOCKET, SO_ERROR, &err, &sl);
+ if (rc)
+ flow_perror_ratelimit(conn, now,
+ "Error retrieving SO_ERROR");
+ else
+ flow_dbg_ratelimit(conn, now,
+ "Error event on %s socket: %s",
+ pif_name(conn->f.pif[evsidei]),
+ strerror_(err));
+ goto reset;
}
- if (conn->read[fromsidei] == conn->written[fromsidei] && eof) {
- unsigned sidei;
-
- flow_foreach_sidei(sidei) {
- if ((conn->events & FIN_RCVD(sidei)) &&
- !(conn->events & FIN_SENT(!sidei))) {
- shutdown(conn->s[!sidei], SHUT_WR);
- conn_event(c, conn, FIN_SENT(!sidei));
- }
+ if (conn->events == SPLICE_CONNECT) {
+ if (!(events & EPOLLOUT)) {
+ flow_err_ratelimit(
+ conn, now,
+ "Unexpected events 0x%x during connect",
+ events);
+ goto reset;
}
+ if (tcp_splice_connect_finish(c, conn, now))
+ goto reset;
}
- if (CONN_HAS(conn, FIN_SENT(0) | FIN_SENT(1)))
- goto close;
+ if (events & EPOLLOUT) {
+ if (tcp_splice_forward(c, conn, !evsidei, now))
+ goto reset;
+ }
- if ((events & (EPOLLIN | EPOLLOUT)) == (EPOLLIN | EPOLLOUT)) {
- events = EPOLLIN;
+ if (events & (EPOLLIN | EPOLLRDHUP)) {
+ if (tcp_splice_forward(c, conn, evsidei, now))
+ goto reset;
+ }
- fromsidei = !fromsidei;
- goto swap;
+ if (CONN_HAS(conn, FIN_SENT(0) | FIN_SENT(1))) {
+ /* Clean close, no reset */
+ conn_flag(conn, CLOSING);
+ return;
}
- if (events & EPOLLHUP)
- goto close;
+ if (events & EPOLLHUP) {
+ flow_dbg_ratelimit(conn, now, "Hangup from %s socket",
+ pif_name(conn->f.pif[evsidei]));
+ goto reset;
+ }
return;
-close:
- conn_flag(c, conn, CLOSING);
+reset:
+ tcp_splice_rst(conn);
}
/**
@@ -703,13 +728,13 @@ static int tcp_sock_refill_ns(void *arg)
ns_enter(c);
if (c->ifi4) {
- int rc = tcp_sock_refill_pool(c, ns_sock_pool4, AF_INET);
+ int rc = tcp_sock_refill_pool(ns_sock_pool4, AF_INET);
if (rc < 0)
warn("TCP: Error refilling IPv4 ns socket pool: %s",
strerror_(-rc));
}
if (c->ifi6) {
- int rc = tcp_sock_refill_pool(c, ns_sock_pool6, AF_INET6);
+ int rc = tcp_sock_refill_pool(ns_sock_pool6, AF_INET6);
if (rc < 0)
warn("TCP: Error refilling IPv6 ns socket pool: %s",
strerror_(-rc));
@@ -747,14 +772,13 @@ void tcp_splice_init(struct ctx *c)
/**
* tcp_splice_timer() - Timer for spliced connections
- * @c: Execution context
* @conn: Connection to handle
*/
-void tcp_splice_timer(const struct ctx *c, struct tcp_splice_conn *conn)
+void tcp_splice_timer(struct tcp_splice_conn *conn)
{
unsigned sidei;
- ASSERT(!(conn->flags & CLOSING));
+ assert(!(conn->flags & CLOSING));
flow_foreach_sidei(sidei) {
if ((conn->flags & RCVLOWAT_SET(sidei)) &&
@@ -764,10 +788,10 @@ void tcp_splice_timer(const struct ctx *c, struct tcp_splice_conn *conn)
flow_trace(conn, "can't set SO_RCVLOWAT on %d",
conn->s[sidei]);
}
- conn_flag(c, conn, ~RCVLOWAT_SET(sidei));
+ conn_flag(conn, ~RCVLOWAT_SET(sidei));
}
}
flow_foreach_sidei(sidei)
- conn_flag(c, conn, ~RCVLOWAT_ACT(sidei));
+ conn_flag(conn, ~RCVLOWAT_ACT(sidei));
}