On Sun, Jun 27, 2021 at 3:44 PM Erin Shepherd <erin.sheph...@e43.eu> wrote:
>
> Xin Long <lucien....@gmail.com> writes:
>
> > Currently, when userspace reads a datagram with a buffer that is
> > smaller than this datagram, the data will be truncated and only
> > part of it can be received by users. It doesn't seem right that
> > users don't know the datagram size and have to use a huge buffer
> > to read it to avoid the truncation.
> >
> > This patch to fix it by keeping the skb in rcv queue until the
> > whole data is read by users. Only the last msg of the datagram
> > will be marked with MSG_EOR, just as TCP/SCTP does.
>
> I agree that the current behavior is suboptimal, but:
>
>  * Isn't this the same behavior that other datagram socket types
>    exhibit? It seems like this would make TIPC behave inconsistently
>    compared to other transports
Yes, SCTP.
Do you see any reliable datagram transports not doing this?

>  * Isn't this a compatibility break with existing software? Particularly
>    existing software will not expect to receive trailers of overlong
>    datagrams
I talked to Jon about this, he seems okay with this.

>
> It feels like this behavior should be activated either with a
> setsockopt(2) call or a new MSG_* flag passed to recv
Anyway, It may not be worth a new sockopt.
I'm thinking to pass MSG_EOR into sendmsg:
  sendmsg(MSG_EOR).
to indicate we don't want the truncating msg.

When the msg flag returns with no MSG_EOR, it means there's more data to read.

Thanks.
>
> - Erin
>
> > Signed-off-by: Xin Long <lucien....@gmail.com>
> > ---
> >  net/tipc/socket.c | 30 +++++++++++++++++++++---------
> >  1 file changed, 21 insertions(+), 9 deletions(-)
> >
> > diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> > index 34a97ea36cc8..504e59838b8b 100644
> > --- a/net/tipc/socket.c
> > +++ b/net/tipc/socket.c
> > @@ -1880,6 +1880,7 @@ static int tipc_recvmsg(struct socket *sock, struct 
> > msghdr *m,
> >       bool connected = !tipc_sk_type_connectionless(sk);
> >       struct tipc_sock *tsk = tipc_sk(sk);
> >       int rc, err, hlen, dlen, copy;
> > +     struct tipc_skb_cb *skb_cb;
> >       struct sk_buff_head xmitq;
> >       struct tipc_msg *hdr;
> >       struct sk_buff *skb;
> > @@ -1903,6 +1904,7 @@ static int tipc_recvmsg(struct socket *sock, struct 
> > msghdr *m,
> >               if (unlikely(rc))
> >                       goto exit;
> >               skb = skb_peek(&sk->sk_receive_queue);
> > +             skb_cb = TIPC_SKB_CB(skb);
> >               hdr = buf_msg(skb);
> >               dlen = msg_data_sz(hdr);
> >               hlen = msg_hdr_sz(hdr);
> > @@ -1922,18 +1924,27 @@ static int tipc_recvmsg(struct socket *sock, struct 
> > msghdr *m,
> >
> >       /* Capture data if non-error msg, otherwise just set return value */
> >       if (likely(!err)) {
> > -             copy = min_t(int, dlen, buflen);
> > -             if (unlikely(copy != dlen))
> > -                     m->msg_flags |= MSG_TRUNC;
> > -             rc = skb_copy_datagram_msg(skb, hlen, m, copy);
> > +             int offset = skb_cb->bytes_read;
> > +
> > +             copy = min_t(int, dlen - offset, buflen);
> > +             rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy);
> > +             if (unlikely(rc))
> > +                     goto exit;
> > +             if (unlikely(offset + copy < dlen)) {
> > +                     if (!(flags & MSG_PEEK))
> > +                             skb_cb->bytes_read = offset + copy;
> > +             } else {
> > +                     m->msg_flags |= MSG_EOR;
> > +                     skb_cb->bytes_read = 0;
> > +             }
> >       } else {
> >               copy = 0;
> >               rc = 0;
> > -             if (err != TIPC_CONN_SHUTDOWN && connected && !m->msg_control)
> > +             if (err != TIPC_CONN_SHUTDOWN && connected && 
> > !m->msg_control) {
> >                       rc = -ECONNRESET;
> > +                     goto exit;
> > +             }
> >       }
> > -     if (unlikely(rc))
> > -             goto exit;
> >
> >       /* Mark message as group event if applicable */
> >       if (unlikely(grp_evt)) {
> > @@ -1956,9 +1967,10 @@ static int tipc_recvmsg(struct socket *sock, struct 
> > msghdr *m,
> >               tipc_node_distr_xmit(sock_net(sk), &xmitq);
> >       }
> >
> > -     tsk_advance_rx_queue(sk);
> > +     if (!skb_cb->bytes_read)
> > +             tsk_advance_rx_queue(sk);
> >
> > -     if (likely(!connected))
> > +     if (likely(!connected) || skb_cb->bytes_read)
> >               goto exit;
> >
> >       /* Send connection flow control advertisement when applicable */
> > --
> > 2.27.0
> >
> >
> >
> > _______________________________________________
> > tipc-discussion mailing list
> > tipc-discussion@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/tipc-discussion


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

Reply via email to