Skip to content

Sending 5 x 3KB Packets via GSO - "Message too long/Invalid argument" Error #582

@xs-411

Description

@xs-411

Hi,
I'm trying to send 5 packets, each of size 3KB, using Generic Segmentation Offload (GSO) in a UDP socket. However, I'm encountering an error: "Message too long". I suspect there might be an issue with how I'm using GSO. Here is a simplified version of my client code:

#ifdef __linux__

#ifndef UDP_SEGMENT
#define UDP_SEGMENT 103
#endif

static void send_packets_gso(int fd, quicly_address_t *dest, quicly_address_t *src, struct iovec *packets, size_t num_packets,
                             uint8_t ecn)
{
    struct iovec vec = {.iov_base = (void *)packets[0].iov_base,
                        .iov_len = packets[num_packets - 1].iov_base + packets[num_packets - 1].iov_len - packets[0].iov_base};
    char cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(uint16_t)) /* UDP_SEGMENT */ +
                 CMSG_SPACE(sizeof(int)) /* IP_TOS */];
    struct msghdr mess = {
        .msg_name = dest,
        .msg_namelen = quicly_get_socklen(&dest->sa),
        .msg_iov = &vec,
        .msg_iovlen = 1,
        .msg_control = cmsgbuf,
    };

    if (src != NULL && src->sa.sa_family != AF_UNSPEC)
        set_srcaddr(&mess, src);
    if (num_packets != 1) {
        struct cmsghdr *cmsg = (struct cmsghdr *)((char *)mess.msg_control + mess.msg_controllen);
        cmsg->cmsg_level = SOL_UDP;
        cmsg->cmsg_type = UDP_SEGMENT;
        cmsg->cmsg_len = CMSG_LEN(sizeof(uint16_t));
        *(uint16_t *)CMSG_DATA(cmsg) = packets[0].iov_len;
        mess.msg_controllen += CMSG_SPACE(sizeof(uint16_t));
    }
    set_ecn(&mess, ecn);
    assert(mess.msg_controllen <= sizeof(cmsgbuf));
    if (mess.msg_controllen == 0)
        mess.msg_control = NULL;

    int ret;
    while ((ret = sendmsg(fd, &mess, 0)) == -1 && errno == EINTR)
        ;
    if (ret == -1)
        perror("sendmsg failed");
    if (ret > 0) {
        printf("send successfully. ret = %d\n", ret);
    }
}

#endif

static int send_pending(int fd, quicly_conn_t *conn)
{
    quicly_address_t dest, src;
    struct iovec packets[MAX_BURST_PACKETS];
    uint8_t buf[MAX_BURST_PACKETS * quicly_get_context(conn)->transport_params.max_udp_payload_size];
    size_t num_packets = MAX_BURST_PACKETS;
    int ret;
    if ((ret = quicly_send(conn, &dest, &src, packets, &num_packets, buf, sizeof(buf))) == 0 && num_packets != 0) {

        num_packets = 5;
        struct iovec new_packets[num_packets];
        size_t packet_size = 3072; // 3 KB per packet
        char *packet_data = malloc(packet_size * num_packets);
        for (size_t i = 0; i < num_packets; i++) {
            new_packets[i].iov_base = packet_data + (i * packet_size);
            new_packets[i].iov_len = packet_size;
            memset(new_packets[i].iov_base, 'A' + i, packet_size);  // fill the buffer with different data
        }
        send_packets_gso(fd, &dest, &src, new_packets, num_packets, quicly_send_get_ecn_bits(conn));

    }
    return ret;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions