@@ -367,6 +367,18 @@ int tipc_link_bc_peers(struct tipc_link *l)
367367 return l -> ackers ;
368368}
369369
370+ u16 link_bc_rcv_gap (struct tipc_link * l )
371+ {
372+ struct sk_buff * skb = skb_peek (& l -> deferdq );
373+ u16 gap = 0 ;
374+
375+ if (more (l -> snd_nxt , l -> rcv_nxt ))
376+ gap = l -> snd_nxt - l -> rcv_nxt ;
377+ if (skb )
378+ gap = buf_seqno (skb ) - l -> rcv_nxt ;
379+ return gap ;
380+ }
381+
370382void tipc_link_set_mtu (struct tipc_link * l , int mtu )
371383{
372384 l -> mtu = mtu ;
@@ -1135,7 +1147,10 @@ int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
11351147 if (((l -> rcv_nxt ^ tipc_own_addr (l -> net )) & 0xf ) != 0xf )
11361148 return 0 ;
11371149 l -> rcv_unacked = 0 ;
1138- return TIPC_LINK_SND_BC_ACK ;
1150+
1151+ /* Use snd_nxt to store peer's snd_nxt in broadcast rcv link */
1152+ l -> snd_nxt = l -> rcv_nxt ;
1153+ return TIPC_LINK_SND_STATE ;
11391154 }
11401155
11411156 /* Unicast ACK */
@@ -1236,7 +1251,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
12361251 rc |= tipc_link_input (l , skb , l -> inputq );
12371252 if (unlikely (++ l -> rcv_unacked >= TIPC_MIN_LINK_WIN ))
12381253 rc |= tipc_link_build_state_msg (l , xmitq );
1239- if (unlikely (rc & ~TIPC_LINK_SND_BC_ACK ))
1254+ if (unlikely (rc & ~TIPC_LINK_SND_STATE ))
12401255 break ;
12411256 } while ((skb = __skb_dequeue (defq )));
12421257
@@ -1250,10 +1265,11 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
12501265 u16 rcvgap , int tolerance , int priority ,
12511266 struct sk_buff_head * xmitq )
12521267{
1268+ struct tipc_link * bcl = l -> bc_rcvlink ;
12531269 struct sk_buff * skb ;
12541270 struct tipc_msg * hdr ;
12551271 struct sk_buff_head * dfq = & l -> deferdq ;
1256- bool node_up = link_is_up (l -> bc_rcvlink );
1272+ bool node_up = link_is_up (bcl );
12571273 struct tipc_mon_state * mstate = & l -> mon_state ;
12581274 int dlen = 0 ;
12591275 void * data ;
@@ -1281,7 +1297,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
12811297 msg_set_net_plane (hdr , l -> net_plane );
12821298 msg_set_next_sent (hdr , l -> snd_nxt );
12831299 msg_set_ack (hdr , l -> rcv_nxt - 1 );
1284- msg_set_bcast_ack (hdr , l -> bc_rcvlink -> rcv_nxt - 1 );
1300+ msg_set_bcast_ack (hdr , bcl -> rcv_nxt - 1 );
12851301 msg_set_last_bcast (hdr , l -> bc_sndlink -> snd_nxt - 1 );
12861302 msg_set_link_tolerance (hdr , tolerance );
12871303 msg_set_linkprio (hdr , priority );
@@ -1291,6 +1307,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
12911307
12921308 if (mtyp == STATE_MSG ) {
12931309 msg_set_seq_gap (hdr , rcvgap );
1310+ msg_set_bc_gap (hdr , link_bc_rcv_gap (bcl ));
12941311 msg_set_probe (hdr , probe );
12951312 tipc_mon_prep (l -> net , data , & dlen , mstate , l -> bearer_id );
12961313 msg_set_size (hdr , INT_H_SIZE + dlen );
@@ -1575,49 +1592,68 @@ void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr)
15751592
15761593/* tipc_link_bc_sync_rcv - update rcv link according to peer's send state
15771594 */
1578- void tipc_link_bc_sync_rcv (struct tipc_link * l , struct tipc_msg * hdr ,
1579- struct sk_buff_head * xmitq )
1595+ int tipc_link_bc_sync_rcv (struct tipc_link * l , struct tipc_msg * hdr ,
1596+ struct sk_buff_head * xmitq )
15801597{
15811598 u16 peers_snd_nxt = msg_bc_snd_nxt (hdr );
1599+ u16 from = msg_bcast_ack (hdr ) + 1 ;
1600+ u16 to = from + msg_bc_gap (hdr ) - 1 ;
1601+ int rc = 0 ;
15821602
15831603 if (!link_is_up (l ))
1584- return ;
1604+ return rc ;
15851605
15861606 if (!msg_peer_node_is_up (hdr ))
1587- return ;
1607+ return rc ;
15881608
15891609 /* Open when peer ackowledges our bcast init msg (pkt #1) */
15901610 if (msg_ack (hdr ))
15911611 l -> bc_peer_is_up = true;
15921612
15931613 if (!l -> bc_peer_is_up )
1594- return ;
1614+ return rc ;
15951615
15961616 /* Ignore if peers_snd_nxt goes beyond receive window */
15971617 if (more (peers_snd_nxt , l -> rcv_nxt + l -> window ))
1598- return ;
1618+ return rc ;
1619+
1620+ if (!less (to , from )) {
1621+ rc = tipc_link_retrans (l -> bc_sndlink , from , to , xmitq );
1622+ l -> stats .recv_nacks ++ ;
1623+ }
1624+
1625+ l -> snd_nxt = peers_snd_nxt ;
1626+ if (link_bc_rcv_gap (l ))
1627+ rc |= TIPC_LINK_SND_STATE ;
1628+
1629+ /* Return now if sender supports nack via STATE messages */
1630+ if (l -> peer_caps & TIPC_BCAST_STATE_NACK )
1631+ return rc ;
1632+
1633+ /* Otherwise, be backwards compatible */
15991634
16001635 if (!more (peers_snd_nxt , l -> rcv_nxt )) {
16011636 l -> nack_state = BC_NACK_SND_CONDITIONAL ;
1602- return ;
1637+ return 0 ;
16031638 }
16041639
16051640 /* Don't NACK if one was recently sent or peeked */
16061641 if (l -> nack_state == BC_NACK_SND_SUPPRESS ) {
16071642 l -> nack_state = BC_NACK_SND_UNCONDITIONAL ;
1608- return ;
1643+ return 0 ;
16091644 }
16101645
16111646 /* Conditionally delay NACK sending until next synch rcv */
16121647 if (l -> nack_state == BC_NACK_SND_CONDITIONAL ) {
16131648 l -> nack_state = BC_NACK_SND_UNCONDITIONAL ;
16141649 if ((peers_snd_nxt - l -> rcv_nxt ) < TIPC_MIN_LINK_WIN )
1615- return ;
1650+ return 0 ;
16161651 }
16171652
16181653 /* Send NACK now but suppress next one */
16191654 tipc_link_build_bc_proto_msg (l , true, peers_snd_nxt , xmitq );
16201655 l -> nack_state = BC_NACK_SND_SUPPRESS ;
1656+ return 0 ;
16211657}
16221658
16231659void tipc_link_bc_ack_rcv (struct tipc_link * l , u16 acked ,
@@ -1654,6 +1690,8 @@ void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
16541690}
16551691
16561692/* tipc_link_bc_nack_rcv(): receive broadcast nack message
1693+ * This function is here for backwards compatibility, since
1694+ * no BCAST_PROTOCOL/STATE messages occur from TIPC v2.5.
16571695 */
16581696int tipc_link_bc_nack_rcv (struct tipc_link * l , struct sk_buff * skb ,
16591697 struct sk_buff_head * xmitq )
0 commit comments