Игнорировать MTU пути на Linux при отправке пакетов UDP - PullRequest
1 голос
/ 11 июля 2020

Я реализую DPLPMTUD , и я хочу, чтобы ядро ​​Linux не возвращало -1 с помощью errno = EMSGSIZE, когда я отправляю пакет UDP, длина которого превышает MTU локального интерфейса. Я хочу избежать боли, связанной с обработкой ошибок при отправке нескольких дейтаграмм (особенно при использовании sendmmsg(2)), каждая из которых, возможно, принадлежит другому соединению. Я бы предпочел, чтобы ядро ​​отбрасывало пакет и позволяло приложению DPLPMTUD logi c вычислить MTU.

ip(7) говорит следующее:

              It is possible to implement RFC 4821 MTU probing with SOCK_DGRAM
              or SOCK_RAW sockets by  setting  a  value  of  IP_PMTUDISC_PROBE
              (available  since Linux 2.6.22).  This is also particularly use‐
              ful for diagnostic tools such as tracepath(8) that wish  to  de‐
              liberately send probe packets larger than the observed Path MTU.

Все же установив это вариант не дает желаемого эффекта. Вот код, иллюстрирующий проблему:

/* emsgsize.c: test whether IP_PMTUDISC_PROBE suppresses EMSGSIZE
 *
 * Usage: emsgsize packet_size
 */

#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

#define CHECK(w_, s_) do { if ((s_) < 0) { perror(w_); return 1; }} while (0)

/* Payload */
static unsigned char data[64 * 1024];

int
main (int argc, char **argv)
{
    int fd, on, s, size;
    struct sockaddr_in si;
    ssize_t sent;

    if (argc != 2)
    {
        fprintf(stderr, "usage: emsgsize size\n");
        return 1;
    }
    size = atoi(argv[1]);

    memset(&si, 0, sizeof(si));
    si.sin_family = AF_INET;

    fd = socket(si.sin_family, SOCK_DGRAM, 0);
    CHECK("socket", fd);

    s = bind(fd, (struct sockaddr *) &si, sizeof(si));
    CHECK("bind", s);

    /* This is supposed to suppress sendmsg(2) returning -1 with
     * errno = EMSGSIZE, see ip(7):
     *
     "        It is possible to implement RFC 4821 MTU probing with SOCK_DGRAM
     "        or SOCK_RAW sockets by  setting  a  value  of  IP_PMTUDISC_PROBE
     "        (available  since Linux 2.6.22).  This is also particularly use-
     "        ful for diagnostic tools such as tracepath(8) that wish  to  de-
     "        liberately send probe packets larger than the observed Path MTU.
     */
    on = IP_PMTUDISC_PROBE;
    s = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &on, sizeof(on));
    CHECK("setsockopt", s);

    memset(&si, 0, sizeof(si));
    si.sin_family = AF_INET;
    si.sin_port = htons(12345); /* Destination does not matter */
    s = inet_pton(AF_INET, "127.0.0.1", &si.sin_addr);
    CHECK("inet_pton", s);
    sent = sendto(fd, data, (size_t) size, 0, (struct sockaddr *) &si,
                                                            sizeof(si));
    CHECK("sendto", sent);

    return 0;
}

Когда я отправляю пакеты, превышающие MTU, sendto() выше возвращает -1, а errno устанавливается на EMSGSIZE - именно то, что я хочу чтобы избежать.

Есть ли способ делать то, что я хочу?

...