All of lore.kernel.org
 help / color / mirror / Atom feed
* 1. incoming ax25 session cleanup and 2. re-sending DISC
@ 2022-05-27 10:48 Thomas Osterried
  2022-05-27 12:03 ` Dave van der Locht
  0 siblings, 1 reply; 2+ messages in thread
From: Thomas Osterried @ 2022-05-27 10:48 UTC (permalink / raw)
  To: linux-hams; +Cc: Basil Gunn, David S. Miller, Duoming Zhou

Hello,

now after we fixed the ax25 timer stuff, here's are proposals for
I.  fix for incoming session cleanup in ax25_disconnect() in ax25_subr.c
II. fix for disconnect behavior

I)

Situation:
  Incoming connection request from remote site.
  Session established.
  Remote site disconnects.

  bpq0: fm DL9SAU-4 to DL9SAU-1 ctl SABM+ 10:38:06.374299 
  bpq0: fm DL9SAU-1 to DL9SAU-4 ctl UA- 10:38:06.375592 
  bpq0: fm DL9SAU-4 to DL9SAU-1 ctl DISC+ 10:39:00.500327 
  bpq0: fm DL9SAU-1 to DL9SAU-4 ctl UA- 10:39:00.529162 

netstat --ax25:
Active AX.25 sockets
Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
DL9SAU-4   DL9SAU-1   ???     LISTENING    000/000  0       0     


That incoming session had no connection to a socket (-> ax25->sk is 0), and this is ok.

Cause:
ax25_subr.c:
ax25_disconnect() stops heartbeat timer:
  if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY)) {
    ax25_stop_heartbeat(ax25);
  }

Soultion:
  if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY)) {
    ax25_stop_heartbeat(ax25);
  }


History:

1. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ax25?id=da278622bf04f8ddb14519a2b8214e108ef26101
added ax25_stop_heartbeat(
   -> This introduced the long standing problem with ex-sessions in listening state.

2. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ax25?id=4a7d99ea1b27734558feb6833f180cd38a159940
added
   if (!sock_flag(ax25->sk, SOCK_DESTROY)) {
      ax25_stop_heartbeat(ax25);
which should fix the problem (
    "A socket connection made in ax.25 is not closed when session is completed.
    The heartbeat timer is stopped prematurely and this is where the socket gets closed.
    Allow heatbeat timer to run to close socket. Symptom occurs in kernels >= 4.2.0".
).
[This fixed many cases of listening state ex-sessions, but not all].
Furhermore: this patch caused segfault if ax25->sk is NULL. -> next patch:

3. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ax25?id=8a367e74c0120ef68c8c70d5a025648c96626df
  if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))

=> Incoming sessions with no associated ax25->sk are still (after patch #1) affected
by the problem that ax25_stop_heartbeat() is stopped and nothing cleans them up.


Incoming ax25 sessions with sk == NULL are normal, if i.e. IP mode VC is used.
heartbeat timer is needed for normal session cleanup, i.e. after receiving DISC.
Because running ax25-session cleanup did not made problems (sessions with userspace
sockets, or ip-over-ax25 sessions), I argue that the motivation for patch #1 in
the history was a panic in combination with socket-cleanups.



-> fix:

diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 3a476e4f6cd0..9ff98f46dc6b 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -268,7 +268,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
                del_timer_sync(&ax25->t3timer);
                del_timer_sync(&ax25->idletimer);
        } else {
-               if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
+               if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY))
                        ax25_stop_heartbeat(ax25);
                ax25_stop_t1timer(ax25);
                ax25_stop_t2timer(ax25);


II)

And another problem was introduced by patch #2 4a7d99ea1b27734558feb6833f180cd38a159940 mentioned above:
ax25_std_timer.c ax25_std_heartbeat_expiry() and ax25_ds_timer.c ax25_ds_heartbeat_expiry() got this in the patch:
	  case AX25_STATE_0:
	+ case AX25_STATE_2:

AX25_STATE_2 in the AX.25 state machine is "Awaiting release state".
If we send DISC (userspace), we should send DISC until we receive a UA or DM,
or sent DISC+ again until t1 expiry.
(On RF, it's not guaranteed, the first packet reaches it's destination.)


With AX25_STATE0 and AX25_STATE_2:
# call -r bpq0 dl9sau-4 &
# listen -a &
# killall call
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:32:02.400597
# netstat --ax25
Active AX.25 sockets
Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q

=> only one DISC is sent. Session is cleaned up immediately.




With only 
  case AX25_STATE_0:
we get the correct behavior again:

# call -r bpq0 dl9sau-4 &
# listen -a &
# killall call
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:15:50.755054 
# netstat --ax25
Active AX.25 sockets
Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
DL9SAU-4   DL9SAU-1   bpq0    DISC SENT    000/000  0       0   
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:15:59.977987 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:16:18.409427 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:16:47.082513 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:17:23.946644 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:18:09.010498 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:19:04.312174 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:20:07.788591 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:21:21.516020 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:22:43.436212 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:24:13.547179 
bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:25:53.907982 

# netstat --ax25
Active AX.25 sockets
Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
# 


=> patches:

diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index b17da41210cb..17c2db85f24f 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -35,7 +35,6 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25)
 
        switch (ax25->state) {
        case AX25_STATE_0:
-       case AX25_STATE_2:
                /* Magic here: If we listen() and a new link dies before it
                   is accepted() it isn't 'dead' so doesn't get removed. */
                if (!sk || sock_flag(sk, SOCK_DESTROY) ||


and


diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index c4f8adbf8144..35eaeef7c5c1 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -98,7 +98,6 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
        switch (ax25->state) {
 
        case AX25_STATE_0:
-       case AX25_STATE_2:
                /* Magic here: If we listen() and a new link dies before it
                   is accepted() it isn't 'dead' so doesn't get removed. */
                if (!sk || sock_flag(sk, SOCK_DESTROY) ||



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: 1. incoming ax25 session cleanup and 2. re-sending DISC
  2022-05-27 10:48 1. incoming ax25 session cleanup and 2. re-sending DISC Thomas Osterried
@ 2022-05-27 12:03 ` Dave van der Locht
  0 siblings, 0 replies; 2+ messages in thread
From: Dave van der Locht @ 2022-05-27 12:03 UTC (permalink / raw)
  To: Thomas Osterried; +Cc: linux-hams, Basil Gunn, David S. Miller, Duoming Zhou

Hi all,

Following recent developments from the sideline. After many years
dealing with (and reporting / discussing) these issues there seems to
be coming a solution finally.
Many thanks! Will be appreciated by many people.

73! Dave van der Locht

Op vr 27 mei 2022 om 13:46 schreef Thomas Osterried <thomas@osterried.de>:
>
> Hello,
>
> now after we fixed the ax25 timer stuff, here's are proposals for
> I.  fix for incoming session cleanup in ax25_disconnect() in ax25_subr.c
> II. fix for disconnect behavior
>
> I)
>
> Situation:
>   Incoming connection request from remote site.
>   Session established.
>   Remote site disconnects.
>
>   bpq0: fm DL9SAU-4 to DL9SAU-1 ctl SABM+ 10:38:06.374299
>   bpq0: fm DL9SAU-1 to DL9SAU-4 ctl UA- 10:38:06.375592
>   bpq0: fm DL9SAU-4 to DL9SAU-1 ctl DISC+ 10:39:00.500327
>   bpq0: fm DL9SAU-1 to DL9SAU-4 ctl UA- 10:39:00.529162
>
> netstat --ax25:
> Active AX.25 sockets
> Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
> DL9SAU-4   DL9SAU-1   ???     LISTENING    000/000  0       0
>
>
> That incoming session had no connection to a socket (-> ax25->sk is 0), and this is ok.
>
> Cause:
> ax25_subr.c:
> ax25_disconnect() stops heartbeat timer:
>   if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY)) {
>     ax25_stop_heartbeat(ax25);
>   }
>
> Soultion:
>   if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY)) {
>     ax25_stop_heartbeat(ax25);
>   }
>
>
> History:
>
> 1. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ax25?id=da278622bf04f8ddb14519a2b8214e108ef26101
> added ax25_stop_heartbeat(
>    -> This introduced the long standing problem with ex-sessions in listening state.
>
> 2. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ax25?id=4a7d99ea1b27734558feb6833f180cd38a159940
> added
>    if (!sock_flag(ax25->sk, SOCK_DESTROY)) {
>       ax25_stop_heartbeat(ax25);
> which should fix the problem (
>     "A socket connection made in ax.25 is not closed when session is completed.
>     The heartbeat timer is stopped prematurely and this is where the socket gets closed.
>     Allow heatbeat timer to run to close socket. Symptom occurs in kernels >= 4.2.0".
> ).
> [This fixed many cases of listening state ex-sessions, but not all].
> Furhermore: this patch caused segfault if ax25->sk is NULL. -> next patch:
>
> 3. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ax25?id=8a367e74c0120ef68c8c70d5a025648c96626df
>   if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
>
> => Incoming sessions with no associated ax25->sk are still (after patch #1) affected
> by the problem that ax25_stop_heartbeat() is stopped and nothing cleans them up.
>
>
> Incoming ax25 sessions with sk == NULL are normal, if i.e. IP mode VC is used.
> heartbeat timer is needed for normal session cleanup, i.e. after receiving DISC.
> Because running ax25-session cleanup did not made problems (sessions with userspace
> sockets, or ip-over-ax25 sessions), I argue that the motivation for patch #1 in
> the history was a panic in combination with socket-cleanups.
>
>
>
> -> fix:
>
> diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
> index 3a476e4f6cd0..9ff98f46dc6b 100644
> --- a/net/ax25/ax25_subr.c
> +++ b/net/ax25/ax25_subr.c
> @@ -268,7 +268,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
>                 del_timer_sync(&ax25->t3timer);
>                 del_timer_sync(&ax25->idletimer);
>         } else {
> -               if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
> +               if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY))
>                         ax25_stop_heartbeat(ax25);
>                 ax25_stop_t1timer(ax25);
>                 ax25_stop_t2timer(ax25);
>
>
> II)
>
> And another problem was introduced by patch #2 4a7d99ea1b27734558feb6833f180cd38a159940 mentioned above:
> ax25_std_timer.c ax25_std_heartbeat_expiry() and ax25_ds_timer.c ax25_ds_heartbeat_expiry() got this in the patch:
>           case AX25_STATE_0:
>         + case AX25_STATE_2:
>
> AX25_STATE_2 in the AX.25 state machine is "Awaiting release state".
> If we send DISC (userspace), we should send DISC until we receive a UA or DM,
> or sent DISC+ again until t1 expiry.
> (On RF, it's not guaranteed, the first packet reaches it's destination.)
>
>
> With AX25_STATE0 and AX25_STATE_2:
> # call -r bpq0 dl9sau-4 &
> # listen -a &
> # killall call
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:32:02.400597
> # netstat --ax25
> Active AX.25 sockets
> Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
>
> => only one DISC is sent. Session is cleaned up immediately.
>
>
>
>
> With only
>   case AX25_STATE_0:
> we get the correct behavior again:
>
> # call -r bpq0 dl9sau-4 &
> # listen -a &
> # killall call
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:15:50.755054
> # netstat --ax25
> Active AX.25 sockets
> Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
> DL9SAU-4   DL9SAU-1   bpq0    DISC SENT    000/000  0       0
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:15:59.977987
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:16:18.409427
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:16:47.082513
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:17:23.946644
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:18:09.010498
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:19:04.312174
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:20:07.788591
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:21:21.516020
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:22:43.436212
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:24:13.547179
> bpq0: fm DL9SAU-1 to DL9SAU-4 ctl DISC+ 12:25:53.907982
>
> # netstat --ax25
> Active AX.25 sockets
> Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
> #
>
>
> => patches:
>
> diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
> index b17da41210cb..17c2db85f24f 100644
> --- a/net/ax25/ax25_std_timer.c
> +++ b/net/ax25/ax25_std_timer.c
> @@ -35,7 +35,6 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25)
>
>         switch (ax25->state) {
>         case AX25_STATE_0:
> -       case AX25_STATE_2:
>                 /* Magic here: If we listen() and a new link dies before it
>                    is accepted() it isn't 'dead' so doesn't get removed. */
>                 if (!sk || sock_flag(sk, SOCK_DESTROY) ||
>
>
> and
>
>
> diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
> index c4f8adbf8144..35eaeef7c5c1 100644
> --- a/net/ax25/ax25_ds_timer.c
> +++ b/net/ax25/ax25_ds_timer.c
> @@ -98,7 +98,6 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
>         switch (ax25->state) {
>
>         case AX25_STATE_0:
> -       case AX25_STATE_2:
>                 /* Magic here: If we listen() and a new link dies before it
>                    is accepted() it isn't 'dead' so doesn't get removed. */
>                 if (!sk || sock_flag(sk, SOCK_DESTROY) ||
>
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-05-27 12:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-27 10:48 1. incoming ax25 session cleanup and 2. re-sending DISC Thomas Osterried
2022-05-27 12:03 ` Dave van der Locht

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.