<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt, branch 2026_06_11.a9c61ff</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>util, passt: Close daemon-lifetime fds on exit to avoid Coverity warning</title>
<updated>2026-06-11T23:02:35+00:00</updated>
<author>
<name>Jon Maloy</name>
<email>jmaloy@redhat.com</email>
</author>
<published>2026-06-11T15:15:21+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=a9c61ffaf15347b8dfcc2347c5440e4b0e82333b'/>
<id>a9c61ffaf15347b8dfcc2347c5440e4b0e82333b</id>
<content type='text'>
conf_open_files() opens three file descriptors (fd_tap_listen,
fd_repair_listen, fd_control_listen) that are held for the entire
daemon lifetime.  Because no close() call exists for them
anywhere, Coverity flags each as INCOMPLETE_DEALLOCATOR. This is
clearly a false positive, but we still want to get rid of this
warning.

We now register the execution context in global area so that
passt_exit() can use it to close these descriptors before calling
_exit().  All exit paths (signal handler, die(), die_perror())
funnel through passt_exit(), so this covers all cases.

Signed-off-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
conf_open_files() opens three file descriptors (fd_tap_listen,
fd_repair_listen, fd_control_listen) that are held for the entire
daemon lifetime.  Because no close() call exists for them
anywhere, Coverity flags each as INCOMPLETE_DEALLOCATOR. This is
clearly a false positive, but we still want to get rid of this
warning.

We now register the execution context in global area so that
passt_exit() can use it to close these descriptors before calling
_exit().  All exit paths (signal handler, die(), die_perror())
funnel through passt_exit(), so this covers all cases.

Signed-off-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>conf, util: Disable IPv6 if explicit IPv6 socket probe fails</title>
<updated>2026-06-10T14:48:44+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2026-06-08T19:06:17+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=e1a6d9ef626aa6dbcfeef97dbbab3bd69c35b4b1'/>
<id>e1a6d9ef626aa6dbcfeef97dbbab3bd69c35b4b1</id>
<content type='text'>
In https://bugs.passt.top/show_bug.cgi?id=188, I originally reported
that if IPv6 is disabled in the kernel (for example via command line
parameter ipv6.disable=1, or disabled in build configuration), and we
attempt to forward any port, we'll exit right away after failing to
set up dual-stack listening sockets.

The original instance of that issue is now fixed for pasta by commit
75dcbc300bf0 ("pasta: Warn, disable matching IP version if not
supported, in local mode") together with the new implementation of
the rule forwarding table, starting from commit b223bec48213 ("fwd,
tcp, udp: Set up listening sockets based on forward table"), because
we first parse forwarding options, then probe for IPv6 support in the
target namespace (and disable IPv6 as a result), and finally bind
sockets once we already know that IPv6 support is disabled.

But we don't do that when invoked as passt, because we have no target
namespace and hence no probing for IPv6 support whatsoever.

Add IPv6 to the socket features we test in sock_probe_features(), and,
if we fail to create an IPv6 socket for whatever reason (which might
include security policies as well), disable IPv6 support altogether,
so that we won't attempt to use dual-stack sockets for port forwarding
either.

Note that the probe comes without any sort of debug message, because
at this point we haven't parsed the configuration yet, and we would
therefore print that regardless of the selected logging level and
other options, including --ipv4-only, which would be rather confusing.
I doubt we'll miss this kind of message though, IPv6 support being
disabled is anyway obvious from the initial configuration dump.

Reported-by: Chi Cuong HA &lt;ChiCuong.HA@amadeus.com&gt;
Reported-by: Romain Geissler &lt;romain.geissler@amadeus.com&gt;
Link: https://bugs.passt.top/show_bug.cgi?id=188
Fixes: 4ddd59bc6085 ("conf: Separate local mode for each IP version, don't enable disabled IP version")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In https://bugs.passt.top/show_bug.cgi?id=188, I originally reported
that if IPv6 is disabled in the kernel (for example via command line
parameter ipv6.disable=1, or disabled in build configuration), and we
attempt to forward any port, we'll exit right away after failing to
set up dual-stack listening sockets.

The original instance of that issue is now fixed for pasta by commit
75dcbc300bf0 ("pasta: Warn, disable matching IP version if not
supported, in local mode") together with the new implementation of
the rule forwarding table, starting from commit b223bec48213 ("fwd,
tcp, udp: Set up listening sockets based on forward table"), because
we first parse forwarding options, then probe for IPv6 support in the
target namespace (and disable IPv6 as a result), and finally bind
sockets once we already know that IPv6 support is disabled.

But we don't do that when invoked as passt, because we have no target
namespace and hence no probing for IPv6 support whatsoever.

Add IPv6 to the socket features we test in sock_probe_features(), and,
if we fail to create an IPv6 socket for whatever reason (which might
include security policies as well), disable IPv6 support altogether,
so that we won't attempt to use dual-stack sockets for port forwarding
either.

Note that the probe comes without any sort of debug message, because
at this point we haven't parsed the configuration yet, and we would
therefore print that regardless of the selected logging level and
other options, including --ipv4-only, which would be rather confusing.
I doubt we'll miss this kind of message though, IPv6 support being
disabled is anyway obvious from the initial configuration dump.

Reported-by: Chi Cuong HA &lt;ChiCuong.HA@amadeus.com&gt;
Reported-by: Romain Geissler &lt;romain.geissler@amadeus.com&gt;
Link: https://bugs.passt.top/show_bug.cgi?id=188
Fixes: 4ddd59bc6085 ("conf: Separate local mode for each IP version, don't enable disabled IP version")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Improve EOF and read stall exit conditions</title>
<updated>2026-06-05T07:46:52+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-06-05T00:34:16+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=21f4d13c4cd4db24b65926265c98d5f41f0c6a9b'/>
<id>21f4d13c4cd4db24b65926265c98d5f41f0c6a9b</id>
<content type='text'>
At the end of our loop we have a conditional 'break' that exits if we're
at EOF on the read side and have nothing left in the pipe.  This makes
sense: at EOF there's nothing left to do read-side and with nothing in the
pipe there's nothing to do write side either.

The same is true if the read side hit an EAGAIN and the pipe is empty:
there's nothing we can do (for now) read side, and with an empty pipe
nothing write side either.  So, generalise the condition to exit on either
EOF or EAGAIN read side.

Furthermore, if the read side is at EOF or EAGAIN and there's already
nothing in the pipe before the write-side splice(), then that write side
splice() can't accomplish anything, so exit the loop early in that case
avoiding a harmless but unnecessary write-splice().

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
[sbrivio: Minor comment fix]
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
At the end of our loop we have a conditional 'break' that exits if we're
at EOF on the read side and have nothing left in the pipe.  This makes
sense: at EOF there's nothing left to do read-side and with nothing in the
pipe there's nothing to do write side either.

The same is true if the read side hit an EAGAIN and the pipe is empty:
there's nothing we can do (for now) read side, and with an empty pipe
nothing write side either.  So, generalise the condition to exit on either
EOF or EAGAIN read side.

Furthermore, if the read side is at EOF or EAGAIN and there's already
nothing in the pipe before the write-side splice(), then that write side
splice() can't accomplish anything, so exit the loop early in that case
avoiding a harmless but unnecessary write-splice().

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
[sbrivio: Minor comment fix]
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>passt, tcp: Inline CALL_PROTO_HANDLER() and merge tcp_timer()</title>
<updated>2026-06-04T04:45:09+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-06-02T13:17:08+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=31d0893d47e3d147b3a1597bbede7de65281a62f'/>
<id>31d0893d47e3d147b3a1597bbede7de65281a62f</id>
<content type='text'>
Since 260075bde769 ("tcp, udp, fwd: Run all port scanning from a
single timer"), CALL_PROTO_HANDLER() has only one user (tcp), so
inline it at the call site and remove the macro.

Merge tcp_timer() into tcp_defer_handler(), moving the timer interval
check there, matching the pattern used by flow_defer_handler() and
fwd_scan_ports_timer().

The weak declaration and null check for tcp_defer_handler are also
dropped as the function is always defined.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Since 260075bde769 ("tcp, udp, fwd: Run all port scanning from a
single timer"), CALL_PROTO_HANDLER() has only one user (tcp), so
inline it at the call site and remove the macro.

Merge tcp_timer() into tcp_defer_handler(), moving the timer interval
check there, matching the pattern used by flow_defer_handler() and
fwd_scan_ports_timer().

The weak declaration and null check for tcp_defer_handler are also
dropped as the function is always defined.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Remove questionable "optimisation" of pending bytes tracking</title>
<updated>2026-06-04T04:35:29+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-28T05:02:12+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=2420ad2f8f86494f9318ceaeea391502ee947095'/>
<id>2420ad2f8f86494f9318ceaeea391502ee947095</id>
<content type='text'>
We have a special path that avoids updating conn-&gt;pending when the amounts
read and written are equal.  This has a conceptual complexity cost, in
particular, it means that conn-&gt;pending[] is not accurate to its normal
meaning for a section of the loop body.

conn-&gt;pending[] shares a cacheline with conn-&gt;pipe[] and conn-&gt;s[], so it's
almost certainly cache-hot.  It's questionable that avoiding the update
of pending even outweighs the extra conditional branch, let alone saves
anything of significance.  Remove it.

This allows us to move the updates to conn-&gt;pending closer to the actual
splice() calls, making it easier to reason about its value.  It also lets
us move the conn-&gt;pending updates so they can piggy back on existing tests
rather than needing a conditional expression to avoid clobbering it when
splice() returns -1 (EAGAIN).

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We have a special path that avoids updating conn-&gt;pending when the amounts
read and written are equal.  This has a conceptual complexity cost, in
particular, it means that conn-&gt;pending[] is not accurate to its normal
meaning for a section of the loop body.

conn-&gt;pending[] shares a cacheline with conn-&gt;pipe[] and conn-&gt;s[], so it's
almost certainly cache-hot.  It's questionable that avoiding the update
of pending even outweighs the extra conditional branch, let alone saves
anything of significance.  Remove it.

This allows us to move the updates to conn-&gt;pending closer to the actual
splice() calls, making it easier to reason about its value.  It also lets
us move the conn-&gt;pending updates so they can piggy back on existing tests
rather than needing a conditional expression to avoid clobbering it when
splice() returns -1 (EAGAIN).

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Simplify / correct OUT_WAIT flag handling</title>
<updated>2026-06-04T04:35:26+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-28T05:02:11+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=4ccb2eebaa024a42cc4d5ba0112ade67666a3446'/>
<id>4ccb2eebaa024a42cc4d5ba0112ade67666a3446</id>
<content type='text'>
We set the OUT_WAIT flag if we stop forwarding due to EAGAIN, but there's
still data in the pipe.  That ensures we wake up when the output socket has
room to drain the pipe into.

We clear the OUT_WAIT flag when we complete forwarding on an EPOLLOUT
event, but that's not quite right.  Even though it's called on an EPOLLOUT,
tcp_splice_forward() could, in principle empty the pipe, but also read
enough new data from the other side to fill it again.  That would set
OUT_WAIT internally, but it would be cleared after returning meaning
we could miss a necessary wakeup.

The condition on whether we need write side wakeups is actually fairly
simple: we need them if and only if we return to the main loop with data
in the pipe.  Maintain that in a single place - right after we exit the
forwarding loop in tcp_splice_forward().

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We set the OUT_WAIT flag if we stop forwarding due to EAGAIN, but there's
still data in the pipe.  That ensures we wake up when the output socket has
room to drain the pipe into.

We clear the OUT_WAIT flag when we complete forwarding on an EPOLLOUT
event, but that's not quite right.  Even though it's called on an EPOLLOUT,
tcp_splice_forward() could, in principle empty the pipe, but also read
enough new data from the other side to fill it again.  That would set
OUT_WAIT internally, but it would be cleared after returning meaning
we could miss a necessary wakeup.

The condition on whether we need write side wakeups is actually fairly
simple: we need them if and only if we return to the main loop with data
in the pipe.  Maintain that in a single place - right after we exit the
forwarding loop in tcp_splice_forward().

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Simplify shutdown(2) handling</title>
<updated>2026-06-04T04:35:23+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-28T05:02:10+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=cd61ad02d4181e8fa34e2bcb8f8436fd9a64714b'/>
<id>cd61ad02d4181e8fa34e2bcb8f8436fd9a64714b</id>
<content type='text'>
At the end of tcp_splice_forward(), we check for half-closed connections
in either direction and propagate the FIN to the other side with a
shutdown(2).

However, it's unnecessary to check both directions: a FIN from side X will
cause an EPOLLRDUP on side X's socket, which will trigger
tcp_splice_forward() from side X to side !X.  Likewise for the other side.
So we only need to check for "forward" FIN propagation.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
At the end of tcp_splice_forward(), we check for half-closed connections
in either direction and propagate the FIN to the other side with a
shutdown(2).

However, it's unnecessary to check both directions: a FIN from side X will
cause an EPOLLRDUP on side X's socket, which will trigger
tcp_splice_forward() from side X to side !X.  Likewise for the other side.
So we only need to check for "forward" FIN propagation.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Remove goto from forwarding loop</title>
<updated>2026-06-04T04:35:21+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-28T05:02:09+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=987ac99098480d403b8aa922736c239a4aa6de1b'/>
<id>987ac99098480d403b8aa922736c239a4aa6de1b</id>
<content type='text'>
The forwarding look in tcp_splice_forward() has a retry label that we goto
in some cases.  However, the only difference between a 'goto retry' and
a 'continue' is that the 'continue' will reset the 'more' variable to 0.

The fist goto retry only occurs if never_read is set, which can only be
the case if we never changed 'more' in the first place, so is strictly
equivalent to a continue.  In the second case, 'more' can be set though.

'more' is set by a heuristic that if we're able to read most of a pipe's
worth of data at once, there's probably more coming, so we should prepare
the write-side for that.  However, on a goto retry we have a new read side
splice.  If this time we *don't* get most of a pipe's worth of data, that
suggests that contrary to expectations from the previous loop we have now
temporarily run out of input data and so SPLICE_F_MORE is no longer
a good guess for the next write side splice().  In other words, the second
read-splice() gives us better data for the heuristic than keeping our guess
from the first one, so resetting 'more' is valuable.

So, we could replace both gotos with continues.  But they're already at the
end the loop body, so a continue is a no-op.  Just remove them.  That, in
turn removes the need for the never_read variable.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The forwarding look in tcp_splice_forward() has a retry label that we goto
in some cases.  However, the only difference between a 'goto retry' and
a 'continue' is that the 'continue' will reset the 'more' variable to 0.

The fist goto retry only occurs if never_read is set, which can only be
the case if we never changed 'more' in the first place, so is strictly
equivalent to a continue.  In the second case, 'more' can be set though.

'more' is set by a heuristic that if we're able to read most of a pipe's
worth of data at once, there's probably more coming, so we should prepare
the write-side for that.  However, on a goto retry we have a new read side
splice.  If this time we *don't* get most of a pipe's worth of data, that
suggests that contrary to expectations from the previous loop we have now
temporarily run out of input data and so SPLICE_F_MORE is no longer
a good guess for the next write side splice().  In other words, the second
read-splice() gives us better data for the heuristic than keeping our guess
from the first one, so resetting 'more' is valuable.

So, we could replace both gotos with continues.  But they're already at the
end the loop body, so a continue is a no-op.  Just remove them.  That, in
turn removes the need for the never_read variable.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Improve EOF exit condition for the loop</title>
<updated>2026-06-04T04:35:18+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-28T05:02:08+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=4a6187008f1ac3db2e221b3b21151f4d72fa8821'/>
<id>4a6187008f1ac3db2e221b3b21151f4d72fa8821</id>
<content type='text'>
In tcp_splice_forward() we exit the forwarding loop if we have an EOF on
the read side.  However, this potentially leaves data in the pipe, even if
the write side hasn't yet blocked.  It's not clear to me whether this could
leave data indefinitely in the pipe with no events to keep it moving,
but it's not clear to me that it couldn't either.

Stay in the loop until either the write side blocks or we've emptied
the pipe.

Secondly, this test is after several tests on how much we wrote which
might also cause a retry.  However, if we've reached EOF and the pipe is
empty, there's nothing more to do, regardless of how much we wrote, so
we should exit, regardless of those conditions.  So move this exit test
above the retry conditions.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In tcp_splice_forward() we exit the forwarding loop if we have an EOF on
the read side.  However, this potentially leaves data in the pipe, even if
the write side hasn't yet blocked.  It's not clear to me whether this could
leave data indefinitely in the pipe with no events to keep it moving,
but it's not clear to me that it couldn't either.

Stay in the loop until either the write side blocks or we've emptied
the pipe.

Secondly, this test is after several tests on how much we wrote which
might also cause a retry.  However, if we've reached EOF and the pipe is
empty, there's nothing more to do, regardless of how much we wrote, so
we should exit, regardless of those conditions.  So move this exit test
above the retry conditions.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp_splice: Simplify EPOLLRDHUP / eof / FIN handling</title>
<updated>2026-06-04T04:35:16+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-28T05:02:07+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=1d475b1dbf22dac4a9fda3ebb444b0343392c5c3'/>
<id>1d475b1dbf22dac4a9fda3ebb444b0343392c5c3</id>
<content type='text'>
There are two ways we can tell one of our sockets has received a FIN.  We
can either see an EPOLLRDHUP epoll event, or we can get a zero-length read
(EOF) on the socket.  We currently use both, in a mildly confusing way:
we only set the FIN_RCVD() flag based on the EPOLLRDHUP event, but then
some other close out logic is based on seeing an EOF.

Simplify this by setting the flag based on only the EOF.  To make sure we
don't miss an event if we get an EPOLLRDHUP with no data, we trigger the
forwarding path for EPOLLRDHUP as well as EPOLLIN.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
There are two ways we can tell one of our sockets has received a FIN.  We
can either see an EPOLLRDHUP epoll event, or we can get a zero-length read
(EOF) on the socket.  We currently use both, in a mildly confusing way:
we only set the FIN_RCVD() flag based on the EPOLLRDHUP event, but then
some other close out logic is based on seeing an EOF.

Simplify this by setting the flag based on only the EOF.  To make sure we
don't miss an event if we get an EPOLLRDHUP with no data, we trigger the
forwarding path for EPOLLRDHUP as well as EPOLLIN.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
