On Fri, Feb 22, 2019 at 09:45:26AM +0100, kwiecienmaciek@xxxxxxxxx wrote: > From: Maciej Kwiecien <maciej.kwiecien@xxxxxxxxx> > > hb_timer might not start at all for a particular transport because its > start is conditional. In a result a node is not sending heartbeats. > > Function sctp_transport_reset_hb_timer has two roles: > - initial start of hb_timer for a given transport, > - update expire date of hb_timer for a given transport. > The function is optimized to update timer's expire only if it is before > a new calculated one but this comparison is invalid for a timer which > has not yet started. Such a timer has expire == 0 and if a new expire > value is bigger than (MAX_JIFFIES / 2 + 2) then "time_before" macro will > fail and timer will not start resulting in no heartbeat packets send by > the node. > > This was found when association was initialized within first 5 mins > after system boot due to jiffies init value which is near to MAX_JIFFIES. > > Test kernel version: 4.9.154 (ARCH=arm) > hb_timer.expire = 0; //initialized, not started timer > new_expire = MAX_JIFFIES / 2 + 2; //or more > time_before(hb_timer.expire, new_expire) == false > > Fixes: ba6f5e33bdbb ("sctp: avoid refreshing heartbeat timer too often") > Reported-by: Marcin Stojek <marcin.stojek@xxxxxxxxx> > Tested-by: Marcin Stojek <marcin.stojek@xxxxxxxxx> > Signed-off-by: Maciej Kwiecien <maciej.kwiecien@xxxxxxxxx> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@xxxxxxxxx> > --- > net/sctp/transport.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/net/sctp/transport.c b/net/sctp/transport.c > index 033696e6f74f..ad158d311ffa 100644 > --- a/net/sctp/transport.c > +++ b/net/sctp/transport.c > @@ -207,7 +207,8 @@ void sctp_transport_reset_hb_timer(struct sctp_transport *transport) > > /* When a data chunk is sent, reset the heartbeat interval. */ > expires = jiffies + sctp_transport_timeout(transport); > - if (time_before(transport->hb_timer.expires, expires) && > + if ((time_before(transport->hb_timer.expires, expires) || > + !timer_pending(&transport->hb_timer)) && > !mod_timer(&transport->hb_timer, > expires + prandom_u32_max(transport->rto))) > sctp_transport_hold(transport); > -- > 2.14.1 >