Hi John,
I think this one should solve the problem. Pease try it when you are back from 
vacation, and give feedback.

BR
///jon


> -----Original Message-----
> From: Jon Maloy [mailto:jon.ma...@ericsson.com]
> Sent: Friday, 30 September, 2016 18:07
> To: tipc-discussion@lists.sourceforge.net; Parthasarathy Bhuvaragan
> <parthasarathy.bhuvara...@ericsson.com>; Ying Xue
> <ying....@windriver.com>; ri...@highwind.se; Jon Maloy
> <jon.ma...@ericsson.com>
> Cc: ma...@donjonn.com; thompa....@gmail.com
> Subject: [PATCH net 1/1] tipc: fix broadcast link synchronization problem
> 
> In commit 2d18ac4ba745 ("tipc: extend broadcast link initialization
> criteria") we tried to fix a problem with the initial synchronization
> of broadcast link acknowledge values. Unfortunately that solution is
> not sufficient to solve the issue.
> 
> We have seen it happen that LINK_PROTOCOL/STATE packets with a valid
> non-zero unicast acknowledge number may bypass BCAST_PROTOCOL
> initialization, NAME_DISTRIBUTOR and other STATE packets with invalid
> broadcast acknowledge numbers, leading to premature opening of the
> broadcast link. When the bypassed packets finally arrive, they are
> inadvertently accepted, and the already correctly initialized
> acknowledge number in the broadcast receive link is overwritten by
> the invalid (zero) value of the said packets. After this the broadcast
> link goes stale.
> 
> We now fix this by identifying packets where we know the acknowledge
> value is or may be invalid, and then ignoring those values.
> 
> For BCAST_PROTOCOL and NAME_DISTRIBUTOR packets this identification is
> easy; their broadcast acknowledge value is always zero, while false
> positives are far between and harmless.
> 
> For LINK_PROTOCOL/STATE packets we cannot accept false positives, so
> we have to claim an unused bit in the header to indicate that the value
> is invalid. This minor protocol change is fully backwards compatible.
> 
> Reported-by: John Thompson <thompa....@gmail.com>
> Signed-off-by: Jon Maloy <jon.ma...@ericsson.com>
> ---
>  net/tipc/bcast.c | 17 ++++++++++++-----
>  net/tipc/bcast.h |  3 ++-
>  net/tipc/msg.h   | 10 ++++++++++
>  net/tipc/node.c  |  2 +-
>  4 files changed, 25 insertions(+), 7 deletions(-)
> 
> diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
> index 753f774..62d2dfd 100644
> --- a/net/tipc/bcast.c
> +++ b/net/tipc/bcast.c
> @@ -247,15 +247,22 @@ int tipc_bcast_rcv(struct net *net, struct tipc_link *l,
> struct sk_buff *skb)
>   *
>   * RCU is locked, no other locks set
>   */
> -void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked)
> +void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
> +                     struct tipc_msg *hdr)
>  {
>       struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq;
> +     int usr = msg_user(hdr);
> +     u16 bc_ack = msg_bcast_ack(hdr);
>       struct sk_buff_head xmitq;
> 
> +     /* Ignore bc acks sent by peer before bcast synch point was received */
> +     if (!bc_ack && ((usr == BCAST_PROTOCOL) || (usr ==
> NAME_DISTRIBUTOR)))
> +             return;
> +
>       __skb_queue_head_init(&xmitq);
> 
>       tipc_bcast_lock(net);
> -     tipc_link_bc_ack_rcv(l, acked, &xmitq);
> +     tipc_link_bc_ack_rcv(l, bc_ack, &xmitq);
>       tipc_bcast_unlock(net);
> 
>       tipc_bcbase_xmit(net, &xmitq);
> @@ -279,11 +286,11 @@ int tipc_bcast_sync_rcv(struct net *net, struct 
> tipc_link
> *l,
>       __skb_queue_head_init(&xmitq);
> 
>       tipc_bcast_lock(net);
> -     if (msg_type(hdr) == STATE_MSG) {
> +     if (msg_type(hdr) != STATE_MSG) {
> +             tipc_link_bc_init_rcv(l, hdr);
> +     } else if (!msg_bc_ack_invalid(hdr)) {
>               tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), &xmitq);
>               rc = tipc_link_bc_sync_rcv(l, hdr, &xmitq);
> -     } else {
> -             tipc_link_bc_init_rcv(l, hdr);
>       }
>       tipc_bcast_unlock(net);
> 
> diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
> index 5ffe344..855d53c 100644
> --- a/net/tipc/bcast.h
> +++ b/net/tipc/bcast.h
> @@ -55,7 +55,8 @@ void tipc_bcast_dec_bearer_dst_cnt(struct net *net, int
> bearer_id);
>  int  tipc_bcast_get_mtu(struct net *net);
>  int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list);
>  int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff 
> *skb);
> -void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked);
> +void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
> +                     struct tipc_msg *hdr);
>  int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
>                       struct tipc_msg *hdr);
>  int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
> diff --git a/net/tipc/msg.h b/net/tipc/msg.h
> index c3832cd..ef37e49 100644
> --- a/net/tipc/msg.h
> +++ b/net/tipc/msg.h
> @@ -714,6 +714,16 @@ static inline void msg_set_peer_stopping(struct tipc_msg
> *m, u32 s)
>       msg_set_bits(m, 5, 13, 0x1, s);
>  }
> 
> +static inline bool msg_bc_ack_invalid(struct tipc_msg *m)
> +{
> +     return msg_bits(m, 5, 14, 0x1);
> +}
> +
> +static inline void msg_set_bc_ack_invalid(struct tipc_msg *m, bool invalid)
> +{
> +     msg_set_bits(m, 5, 14, 0x1, invalid);
> +}
> +
>  static inline char *msg_media_addr(struct tipc_msg *m)
>  {
>       return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET];
> diff --git a/net/tipc/node.c b/net/tipc/node.c
> index 7ef14e2..9d2f4c2 100644
> --- a/net/tipc/node.c
> +++ b/net/tipc/node.c
> @@ -1535,7 +1535,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, 
> struct
> tipc_bearer *b)
>       if (unlikely(usr == LINK_PROTOCOL))
>               tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq);
>       else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack))
> -             tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack);
> +             tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr);
> 
>       /* Receive packet directly if conditions permit */
>       tipc_node_read_lock(n);
> --
> 2.7.4


------------------------------------------------------------------------------
_______________________________________________
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to