Что гарантирует tcp в linux

Обновлено: 05.07.2024

Протокол TCP является одним из важнейших протоколов связи в компьютерных сетях. В этой статье познакомимся с ним поближе.

Что такое транспортные протоколы

Транспортные протоколы (TCP и UDP) используются для передачи информации. Информация передаётся маленькими частями – сетевыми пакетами. То есть поток информации разбивается на много маленьких пакетов.

Каждый пакет состоит из заголовка и самих данных. Заголовок содержит служебную информацию, например порт источника и назначения.

Особенности TCP

Главной особенностью TCP (Transmission Control Protocol) является то, что он гарантирует доставку всех отправленных пакетов. При этом проверяется целостность пакетов и их порядок. Если пакет потерялся или испортился, то получатель запросит эти пакеты у отправителя снова. Если пакеты пришли не в том порядке, то они на принимающей стороне всё равно обработаются в правильном. Этот механизм контроля доставки накладывает дополнительную нагрузку в виде увеличения служебной информации, которую нужно передать вместе с полезными данными.

TCP делит поток информации на сегменты. В одном сегменте может быть несколько пакетов. Каждый сегмент проверяется на целостность, и если все хорошо, отправляется подтверждение передающей стороне. Таким образом подтверждается не каждый пакет, а каждый сегмент, но в сегменте может оказаться и всего лишь один пакет.

Поверх протокола TCP работают многие прикладные протоколы:

TCP пакеты передаются не просто так, а в рамках установленного соединения – которое называют TCP сессией.

Подключение можно выполнить только если вторая сторона прослушивает порт, к которому будет выполняться подключение.

Алгоритм работы TCP

Алгоритм работы TCP следующий:

  1. Используя трехкратное рукопожатие, между двумя узлами создаётся сеанс связи.
  2. При отправке пакетов узлы последовательно нумеруют их и рассчитывают контрольную сумму.
  3. Поскольку все пакеты имеют последовательные номера, то становится видно если какие-то из них отсутствуют. В этом случае отправляется запрос на повторную отправку пакета.
  4. Если для какого-то пакета не совпала контрольная сумма, то отправляется запрос на повторную отправку пакета.

При открытии даже одной веб странички создаются несколько TCP соединений для:

  • html страницы;
  • каждого CSS и JavaScript файлов;
  • каждого изображения.

И для каждого такого соединения вначале устанавливается сеанс, что замедляет передачу данных.

Заголовок TCP пакета

Заголовок TCP пакета состоит из следующих полей:

  • Порт отправителя.
  • Порт получателя.
  • Порядковый номер в сегменте (sequence number). В целях безопасности это значение генерируется случайным образом и может быть равно от 0 до 4294967295;
  • Номер подтверждения (acknowledgment number). Когда мы подтверждаем определённый пакет, в нем записывается sequence number подтверждаемого пакета.
  • Длина заголовка (data offset). В этом поле указывается длина заголовка TCP пакета и где начинаются фактические данные.
  • Зарезервированное поле. Эти биты зарезервированы для будущего использования.
  • Флаги. Необходимы для дополнительной функциональности. Например, позволяют установить или разорвать соединение, включить или выключить защиту от перегрузки сети и тому подобное.
  • Размер окна (Window Size). Указывается количество байт, считая от последнего номера подтверждения, которые готов принять отправитель данного пакета. То есть, какой у него в данный момент времени размер буфера.
  • Контрольная сумма (Checksum). Используется для проверки на наличие ошибок при приеме или передачи пакетов. Рассчитывается с учетом заголовка (кроме контрольной суммы) и самих данных.
  • Указатель срочности (Urgent pointer). Используется, если стоит флаг URG. По этому значению определяются срочные данные и они сразу же передаются приложению. Остальные данные попадают в буфер.
  • Дополнительные опции. Необязательно, но используются почти всегда.
  • Заполнение (Padding). Дополняет заголовок, пока он не закончится на 32-разрядной границе. Всегда состоит только из нулей.

Флаги в заголовке TCP

Создание TCP сессии

Для установления соединения использует трехкратное рукопожатие.

Трёхкратное рукопожатие TCP

Первый этап. Клиент отправляет на сервер пакет с флагом SYN. При этом клиент устанавливает порядковый номер сегмента на случайное значение A.

Второй этап. В ответ сервер отвечает пакетом с флагами SYN и ACK. Номер подтверждения установлен на единицу больше принятого (A+1). Поскольку сервер также будет отправлять данные, то для себя он тоже выбирает номер первого пакета, который будет другим случайным числом B.

Третий этап. Клиент отправляет ACK на сервер. Порядковый номер устанавливается равным A+1, а номер подтверждения устанавливается на B+1.

На этом этапе клиент и сервер получили подтверждение соединения и образовали двухстороннюю связь.

Передача данных в TCP

Теперь разберём пример передачи данных в уже установленном сеансе.

Обмен данными TCP

Клиент отравляет запрос к серверу. Поскольку данные поместились в один пакет TCP, он получил флаг PSH, чтобы сервер не ждал продолжение получения данных. При этом пакет получил 2 флага: ACK (подтвердил предыдущею передачу пакетов от сервера) и PSH.

В ответ на это сервер отправляет пакет ACK с номером успешно полученных данных.

Далее сервер обработал запрос и отправляет данные клиенту. Эти данные делятся на пакеты и отправляются сегментами.

Далее клиент подтверждает, что данные получены отправляя пакеты с флагом ACK.

Завершение сеанса TCP

Завершение сеанса использует четырёхкратное рукопожатие, причём каждая сторона завершает своё соединение независимо.

Завершение сеанса TCP

Когда одна из сторон хочет остановить свою половину соединения, она передаёт пакет FIN, который другая сторона подтверждает пакетом с ACK.

После того, как сторона, отправившая первый FIN, ответила с последним ACK, она ожидает некоторое время прежде чем окончательно закрыть соединение. В течение этого времени локальный порт недоступен для новых соединений.

Соединение может быть «полуоткрытым», и в этом случае одна сторона завершила свою часть, а другая — нет. Завершившая сторона больше не может отправлять какие-либо данные, но другая сторона может. Завершающая сторона должна продолжить чтение данных, пока другая сторона также не завершит свою работу.

Также возможно разорвать соединение трёхкратным рукопожатием, когда первая сторона отправляет FIN, а вторая отвечает FIN и ACK (просто объединяет 2 шага в один). Дальше первая сторона подтверждает завершение сеанса с помощью ACK.

Состояния сеанса TCP

Сеанс TCP может находится в следующих состояниях:

  • CLOSED – начальное состояние;
  • LISTEN – сервер ожидает запросы от клиента;
  • SYN-SENT – клиент хочет установить соединение с сервером и ожидает подтверждение;
  • SYN-RECEIVED – сервер получил запрос на создание сеанса, отправил ответный запрос и ожидает подтверждение;
  • ESTABLISHED – соединение установлено, идёт передача данных;
  • FIN-WAIT-1 – одна из сторон завершает соединение, отправив флаг FIN;
  • CLOSE-WAIT – другая сторона переходит в это состояние, отправив подтверждение на FIN, но продолжает передачу;
  • FIN-WAIT-2 – первый узел получил ACK, разорвал свое соединение, но еще читает данные;
  • LAST-ACK – второй узел заканчивает передачу и отправляет флаг FIN;
  • TIME-WAIT – сервер получил пакет с флагом FIN, отправил флаг ACK и ждёт некоторое время, перед окончательным закрытием соединения;
  • CLOSING – обе стороны инициировали закрытие соединения одновременно.

Вот мы и познакомились с одним из самых важных протоколов сети Интернет. Разобрались с его особенностями, алгоритмом работы. Узнали про сеансы TCP, пакеты и сегменты.

ОПИСАНИЕ
Это реализация протокола TCP, описанного в RFC793, RFC1122
и RFC2001, с расширениями NewReno и SACK. Этот протокол
предоставляет пользователю надежное полнодуплексное
потоковое соединение двух сокетов над ip(7). TCP
гарантирует доставку данных в нужном порядке и вновь
передает потерявшиеся пакеты. Для выявления ошибок
передачи протокол генерирует и проверяет контрольные суммы
пакетов. TCP не сохраняет границы записей.

Только что созданный сокет TCP не имеет локального или
удаленного адреса и не является полностью заданным. Для
создания исходящего соединения TCP с другим сокетом TCP
используйте connect(2). Для приема новых входящих
соединений сперва подключите сокет к и порту и присвойте
ему локальный адрес с помощью bind(2), а затем вызовите
listen(2) для работы сокета в режиме прослушивания. После
этого любое входящее соединение может быть принято с
помощью accept(2). Сокет, для которого были без
погрешностей вызваны accept или connect, является
полностью заданным и может передавать данные. Данные не
могут быть переданы через слушающий или еще не соединенный
сокет.

Linux 2.2 поддерживает высокопроизводительные расширения
TCP RFC1323 TCP. Они включают в себя большой размер окон
TCP для поддержки соединений с большой задержкой или
пропускной способностью. Для их использования необходимо
увеличить размеры буферов приема и передачи. Это можно
сделать глобально с помощью sysctl-вызовов
net.core.wmem_default и net.core.rmem_default , или для
каждого сокета с помощью опций SO_SNDBUF и SO_RCVBUF .
Максимальный размер буферов сокета ограничивается с
помощью глобальных sysctl-вызовов net.core.rmem_max и
net.core.wmem_max . Дополнительная информация приведена в
socket(7).

ФОРМАТЫ АДРЕСОВ
TCP построен над IP (см. ip(7)). Форматы адресов,
определенные в ip(7), относятся и к TCP. TCP поддерживает
лишь point-to-point соединение; широковещательная и
многоадресная передача не поддерживаются.

РАБОТА С ИНТЕРФЕЙСОМ SYSCTLS
Доступ к нижеприведенным вызовам sysctl можно получить с
помощью файлов /proc/sys/net/ipv4/* или через интерфейс
sysctl(2). Кроме того, большинство sysctl-вызовов IP
относятся и к TCP; см. ip(7).

tcp_window_scaling
Разрешить изменение размера окна TCP (RFC1323).

tcp_sack
Разрешить RFC2018 TCP Selective Acknowledgements
(выборочные подтверждения).

tcp_timestamps
Разрешить метки времени TCP (RFC1323).

tcp_fin_timeout
Указывает на количество секунд, в течение которых
необходимо ждать последний пакет FIN до
принудительного закрытия сокета. Строго говоря, это
нарушение спецификации TCP, но оно необходимо для
предотвращения атак типа "отказ доступа к сервису".

tcp_keepalive_probes
Максимальное количество посылаемых "оживляющих"
(keep-alive) проверок перед тем, как соединение
считается разорванным. "Оживляющие" пакеты
посылаются, только если включена опция SO_KEEPALIVE
сокета.

tcp_keepalive_time
Количество секунд между отстутствием передаваемых
данных и отправкой через соединение "оживляющего"
пакета. Значение по умолчанию - 10800 секунд (3
часа).

tcp_max_ka_probes
Количество "оживляющих" пакетов, посылаемых за
определенное время. Во избежание перегрузок это
значение не должно быть слишком большим.

tcp_stdurg
Начать интерпретацию поля с указателем срочных
данных TCP в строгом соответствии с RFC793. По
умолчанию используется совместимая с BSD
интерпретация указателя на неотложные данные,
определяющая первый байт после неотложных данных. В
соответствии с RFC793 указатель должен определять
последний байт неотложных данных. Запуск этой опции
может привести к проблемам во взаимодействии сетей.

tcp_retries2
Определяет, сколько раз производится повторная
передача пакета TCP, до того как соединение будет
считаться разорванным.

tcp_syn_retries
Определяет количество посылаемых удаленной стороне
начальных пакетов SYN до того, как будет возвращена
ошибка. Значение должно быть меньше 255-и. Это
ограничение - только для исходящих соединений; для
входящих количество повторных передач точно
определяется tcp_retries1.

tcp_retrans_collapse
При повторных передачах пробовать посылать
полноразмерные пакеты. Используется во избежание
ошибок некоторых стеков TCP.

ОПЦИИ СОКЕТОВ
Для считывания опций сокетов TCP используется вызов get-
sockopt(2), для установки - setsockopt(2). Значение
аргумента, принадлежащего семейству сокетов, должно быть
равно SOL_TCP. Кроме того, сокетам TCP доступны
большинство опций сокета SOL_IP. Дополнительная
информация приведена в ip(7).

TCP_NODELAY
Остановить выполнение алгоритма Nagle. Это
означает, что пакеты всегда отсылаются при первой
же возможности. При этом не возникает ненужных
задержек из-за большого количества пакетов в сети.
Ожидается целочисленный логический флаг.

TCP_MAXSEG
Установить или считывать максимальный размер
сегмента для исходящих пакетов TCP. Если эта опция
установлена до возникновения соединения, то
меняется также и значение MSS, сообщаемое другой
стороне в начальном пакете. Значения, превышающие
MTU интерфейса, игнорируются и ни на что не влияют.

TCP_CORK
Если функция запущена, то не посылать частичные
кадры. Все поставленные в очередь частичные кадры
будут отосланы, когда выполнение этой опции будет
остановлено. Это является эффективным для
подготовки заголовков перед вызовом sendfile(2) или
для оптимизации пропускной способности. Эта опция
не может совмещаться с TCP_NODELAY.

ВЫЗОВЫ IOCTL
Доступ к нижеприведенным ioctl можно получить через
ioctl(2). Синтаксис следующий:

int value;
error = ioctl(сокет_tcp, тип_ioctl, &значение);

FIONREAD or TIOCINQ
Возвращает количество непрочитанных данных в
очереди приемного буфера. Аргументом является
указатель на целое число.

SIOCATMARK
Возвращает истинное значение, если все срочные
данные уже получены программой пользователя.
Используется совместно с SO_OOBINLINE. Аргументом
является указатель на целое число, служащее
результатом проверки.

TIOCOUTQ
Возвращает количество неотправленных данных в
очереди сокета с помощью указателя на целое число.
К сожалению, реализация этого ioctl достаточно
нестабильно работает во всех известных версиях
Linux и вместо этого возвращает количество
свободного места (действительный размер буфера
минус количество байтов, использованных для
метаданных) в посылаемом запросе. Вероятно, это
будет исправлено в последующих версиях Linux. Если
вы используете TIOCOUTQ, то пожалуйста включите
тест поведения обоих этих функций для проверки их
работоспособности в последующих релизах и на других
Unix-системах.

Hекоторые приложения требуют более быстрого предупреждения
об ошибках. Это может быть выполнено с помощью уровня
SOL_IP опции IP_RECVERR сокета. Если эта опция запущена,
то все входящие ошибки немедленно передаются программе
пользователя. Используйте эту опцию осторожно: она
приводит к тому, что TCP становится более чувствительным к
сменам маршрутов и возникновению других условий, обычных
для сети.

ЗАМЕЧАНИЯ
Если во время соединения произошла ошибка записи в сокет,
то значение SIGPIPE устанавливается только при
установлении опции SO_KEEPALIVE.

TCP не имеет внепоточных данных; он имеет срочные данные.
В Linux это означает, что если другая сторона посылает
новые внепоточные данные, то старые срочные данные
вставляются в поток в качестве обычных (даже если не
установлена опция SO_OOBINLINE). Это поведение отличается
от поведения стеков BSD.

Linux по умолчанию использует совместимую с BSD
интерпретацию указателя на неотложные данные. Это
противоречит RFC1122, но необходимо для взаимодействия
сетей. Положение можно изменить с помощью sysctl-вызова
tcp_stdurg.

КОДЫ ОШИБОК
EPIPE Другая сторона неожиданно закрыла сокет, или была
произведена попытка чтения в закрытом сокете.

ETIMEDOUT
Другая сторона не подтвердила передачу данных через
определенное время.

EAFNOTSUPPORT
Переданный в sin_family тип сокета не был AF_INET.

Ошибки, определенные для ip(7) или общего уровня сокетов,
могут быть возвращены и TCP.

НАЙДЕННЫЕ ОШИБКИ
Hе все ошибки описаны.

IPv6 не описано.

Опции "прозрачного" прокси также не описаны.

ВЕРСИИ
Вызовы sysctl появились в Linux 2.2. IP_RECVERR появилась
в Linux 2.2. TCP_CORK появилось в 2.2.

Только что созданный сокет TCP не имеет локального или удаленного адреса и не является полностью определенным. Для создания исходящего соединения TCP с другим сокетом TCP используйте connect (2). Для приема новых входящих соединений сперва подключите bind (2) сокет к порту и присвойте ему локальный адрес, а затем с помощью listen (2) переведите сокет в режим прослушивания. После этого может быть принят новый сокет для каждого входящего соединения, используя accept (2). Сокет, для которого были успешно вызваны accept или connect , является полностью заданным и может передавать данные. Данные не могут быть переданы через слушающий или еще не соединенный сокет.

Linux поддерживает высокопроизводительные расширения TCP RFC1323. Они включают в себя: защиту против оболочек номеров последовательностей (PAWS), масштабируемые окна и временные метки. Масштабирование окон позволяет использовать большие (> 64Кб) окна TCP для поддержки соединений с большой задержкой или высокой пропускной способностью. Для их использования необходимо увеличить размеры буферов приема и передачи. Это можно сделать глобально с помощью переменных sysctl net.ipv4.tcp_wmem и net.ipv4.tcp_rmem, или через индивидуальные сокеты, используя опции сокетов SO_SNDBUF и SO_RCVBUF в вызове setsockopt (2).

Максимальный размер буферов сокета объявляется, используя механизмы SO_SNDBUF и SO_RCVBUF и ограничен глобальными вызовами sysctl: net.core.rmem_max и net.core.wmem_max. Заметим, что TCP в действительности размещает места в два раза больше, чем размер буфера, запрошенный в вызове setsockopt (2), поэтому последующий вызов getsockopt (2) не возвратит тот же размер буфера, что был запрошен в вызове setsockopt (2). TCP использует это для административных целей и внутренних структур ядра, а переменные sysctl отражают большие размеры, по сравнению с действительными окнами TCP. Для отдельных соединений размер буфера сокета должен быть установлен в соответствии с вызовами listen() или connect() для нормальной работы. Дополнительную информацию смотрите в socket (7).

Если запущена опция SO_OOBINLINE , то срочные данные будут помещены в обычный поток данных (и могут быть проверены с помощью ioctl-вызова SIOCATMARK ), в противном случае они могут быть получены, только если для sendmsg (2) установлен флаг MSG_OOB.

Linux 2.4 предлагает несколько изменений для улучшенной пропускной способности и масштабирования, а также для разрешения особых дополнительных возможностей, таких как поддержка для пустого копирования (zerocopy) в sendfile (2), Explicit Congestion Notification, новое управление сокетами TIME_WAIT, опции поддержки сокетов в рабочем состоянии и поддержка расширений Duplicate SACK.

ФОРМАТЫ АДРЕСОВ

Протокол TCP построен поверх протокола IP (см. ip (7)). Форматы адресов, определенные в ip (7), относятся и к TCP. TCP поддерживает только межузловые соединения (point-to-point); широковещательная и многоадресная передача не поддерживаются.

СИСТЕМНЫЕ ВЫЗОВЫ

Доступ к нижеприведенным переменным и вызовам sysctl можно получить с помощью файлов /proc/sys/net/ipv4/* или через интерфейс sysctl (2). Кроме того, большинство вызовов sysctl IP относятся и к TCP; см. ip (7). tcp_abort_on_overflow Включает сброс соединений, если слушающий сервис слишком медленно работает и не может обработать существующие или принять новые соединения. По умолчанию выключен. Это означает, что при переполнении соединение будет повторно установлено. Включайте эту опцию _только_ если вы действительно убеждены, что слушающий демон не может быть настроен для более быстрой работы. Включение этой опции может нарушить работу пользователей и клиентов вашего сервера. tcp_adv_win_scale Рассчитывает переполнение буфера по формуле bytes/2^tcp_adv_win_scale (если tcp_adv_win_scale > 0) или bytes-bytes/2^(-tcp_adv_win_scale), если оно <= 0. По умолчанию равно 2.

Буфер приема сокета - это пространство, разделяемое между приложением и ядром. TCP поддерживает часть буфера в виде окна TCP, то есть размера принимающего окна, предлагаемого другой стороне. Остаток пространства используется как "буфер приложения", используемый для изолирования сети от работ по расписанию и задержек приложения. По умочанию tcp_adv_win_scale равно 2, обозначая этим, что для буфера приложения используется четверть всего пространства. tcp_app_win Эта переменная определяет, сколько байтов окна TCP зарезервировано для буферизации.

Максимум из (window/2^tcp_app_win, mss) байтов в окне будет зарезервировано для буфера приложения. Значение 0 обозначает, что ничего не зарезервировано. По умолчанию равно 31. tcp_dsack Включает поддержку RFC2883 TCP Duplicate SACK. По умолчанию включено. tcp_ecn Включает RFC2884 Explicit Congestion Notification. По умолчанию выключено. При активации может пропасть возможность установления соединений с некоторыми узлами из-за старых маршрутизаторов (работающих с этой опцией некорректно) по пути следования к узлу. tcp_fack Включает поддержку TCP Forward Acknowledgement. По умолчанию включено. tcp_fin_timeout Указывает на количество секунд, в течение которых необходимо ждать последний пакет FIN до принудительного закрытия сокета. Строго говоря, это нарушение спецификации TCP, но оно необходимо для предотвращения атак отказа доступа к сервисам (DoS). Значение по умолчанию в ядрах 2.4 равно 80, и ниже 180 в ядрах 2.2. tcp_keepalive_intvl Количество секунд между отправками "оживляющих" (keep-alive) проверок. По умолчанию равно 75 с. tcp_keepalive_probes Максимальное количество отправляемых "оживляющих" (keep-alive) проверок перед тем, как соединение считается разорванным. Значение по умолчанию равно 9. tcp_keepalive_time Количество секунд между отстутствием передаваемых данных и отправкой через соединение "оживляющего" пакета. Значение по умолчанию - 10800 секунд (3 часа). tcp_keepalive_time Количество секунд бездействия, после которого по соединению начинает передаваться "оживляющие" пакеты TCP. Эти пакеты будут отправляться, только если включена опция сокета SO_KEEPALIVE. По умолчанию равно 7200 секунд (2 часа). Бездействующее соединение разрывается примерно после 11 минут (9 пакетов, с интервалом 75 секунд) при включенном режиме keep-alive.

low - TCP не регулирует распределение своей памяти, если число страниц ниже этого значения.

pressure - когда количество размещенных TCP страниц превышает это значение, то TCP изменяет свой метод использования памяти. Это состояние отменяется при падении количества размещенных страниц ниже значения low.

high - вообще максимальное количество страниц, размещаемых TCP. Это значение переопределяет все другие значения, указанные ядром. tcp_orphan_retries Максимальное количество попыток проверки другой стороны соединения при разрыве связи с нашей стороны. По умолчанию равно 8. tcp_reordering Максимальное число пакетов, упорядоченных в потоке пакетов TCP без того, чтобы TCP начало подразумевать потери пакетом и перешло в состояние медленного запуска. По умолчанию равно 3. Не рекомендуется менять это значение. Эта метрика упорядочивания пакетов предназначена для минимизации повторных передач, обусловленных переупорядочиванием пакетов в соединении. tcp_retrans_collapse При повторных передачах пробовать посылать полноразмерные пакеты. Включено по умолчанию. tcp_retries1 Определяет количество попыток повторной передачи пакетов по установленному соединению без подключения к этому процессу других сетевых механизмов. Как только превышено это число, то уровень сети обновляет маршрут перед каждым повтором (если это возможно). По умолчанию спецификаций RFC минимум равен 3. tcp_retries2 Максимальное количество попыток повторной передачи пакетов TCP по установленному соединению до того, как оно будет считаться разорванным. По умолчанию равно 15, что соответствует времени примерно от 13 до 30 минут, в зависимости от определенного у вас таймера повторной передачи. RFC1122 определяет минимальную границу в 100 секунд. tcp_rfc1337 Включает поведение TCP, совместимое с RFC 1337. По умолчанию выключено. Если выключено, то: если RST принимается в состоянии TIME_WAIT, то сокет закрывается немедленно, не дожидаясь конца периода TIME_WAIT. tcp_rmem Вектор из 3 целочисленных значений: [min, default, max]. Эти параметры используются TCP для регулирования размером буфера приема. TCP динамически корректирет размер буфера приема от значений по умолчанию, указанных ниже, в диапазоне этих переменных sysctl, в зависимости от количества памяти в системе.

min минимальный размер буфера приема, используемый каждый сокетом TCP. По умолчанию равен 4Кб, и может уменьшаться до PAGE_SIZE байтов в системах с малым количеством памяти. Это значение используется для того, чтобы размещения страниц памяти в режиме давления все равно были разрешены. Не используется для привязки к размеру буфера приема, объявленного через SO_RCVBUF для сокета.

default размер буфера приема по умолчанию для сокетов TCP. Значение переопределяет начальный размер убфера по умолчанию из общей переменной net.core.rmem_default для всех протоколов. По умолчанию равно 87380 байтов, может уменьшаться до 43689 в системах с малым количеством памяти. Если желательны большие размеры буферов приема, то это значение должно быть увеличено (для воздействия на все сокеты). Для разрешения больших размеров окон TCP должно быть включено net.ipv4.tcp_window_scaling (по умолчанию).

min минимальный размер буфера отправления, используемый каждый сокетом TCP. По умолчанию равен 4Кб. Это значение используется для того, чтобы размещения страниц памяти в режиме давления все равно были разрешены. Не используется для привязки к размеру буфера отправления, объявленного через SO_SNDBUF для сокета.

default размер буфера отправления по умолчанию для сокетов TCP. Значение переопределяет начальный размер убфера по умолчанию из общей переменной net.core.wmem_default для всех протоколов. По умолчанию равно 16Кб. Если желательны большие размеры буферов приема, то это значение должно быть увеличено (для воздействия на все сокеты). Для разрешения больших размеров окон TCP должно быть включено net.ipv4.tcp_window_scaling (по умолчанию).

max максимальный размер буфера отправления, используемый каждый сокетом TCP. Это значение не переопределяет глобальную переменную net.core.wmem_max . Не используется для ограничения размера буфера приема через SO_SNDBUF для каждого сокета. По умолчанию равно 128Кб. Уменьшается до 64Кб в системах с малым количеством памяти.

ОПЦИИ СОКЕТОВ

Для считывания опций сокетов TCP используется вызов getsockopt (2), для установки - setsockopt (2). Значение аргумента, принадлежащего семейству сокетов, должно быть равно SOL_TCP . Кроме того, сокетам TCP доступны большинство опций сокета SOL_IP . Дополнительная информация приведена в ip (7). TCP_CORK Если функция запущена, то не посылать частичные кадры. Все поставленные в очередь частичные кадры будут отосланы, когда выполнение этой опции будет остановлено. Это является эффективным для подготовки заголовков перед вызовом sendfile (2) или для оптимизации пропускной способности. Эта опция не может совмещаться с TCP_NODELAY . Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_DEFER_ACCEPT Позволяет слушающему просыпаться только при приходе данных на сокет. Принимает целое значение (секунды), ограничивает максимальное количество попыток TCP до закрытия этого соединения. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_INFO Используется для сбора информации об этом сокете. Ядро возвращает структуру struct tcp_info, как определено в файле /usr/include/linux/tcp.h. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_KEEPCNT Максимальное число проверок TCP, отправляемых до сброса соединения. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_KEEPIDLE Время в секундах до того, как TCP начнет отправлять тестовые пакеты на неактивном соединении, если для сокета включена опция SO_KEEPALIVE. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_KEEPINTVL Время в секундах между отдельными проверками соединения. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_LINGER2 Время жизни безродных сокетов состояния FIN_WAIT2. Эта опция может использоваться для переопределения общесистемного параметра sysctl tcp_fin_timeout на этом сокете. Не должно противоречить опции SO_LINGER уровня сокета socket (7). Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_MAXSEG Максимальный размер сегмента для исходящих пакетов TCP. Если эта опция установлена до возникновения соединения, то меняется также и значение MSS, сообщаемое другой стороне в начальном пакете. Значения, превышающие MTU интерфейса, игнорируются. TCP также будет определять минимальную и максимальную границу поверх этих значений. TCP_NODELAY Если включено, то отменить выполнение алгоритма Nagle. Это означает, что пакеты всегда отсылаются при первой же возможности, даже если к отправке назначено небольшое количество данных. Если выключено, то данные буферизуются и будут отправляться только после набора достаточно большого количества данных, при этом не отправляются постоянно небольшие пакеты с данными. Эта опция не может использоваться одновременно с опцией TCP_CORK . TCP_QUICKACK Включает режим quickack при установке или выключает при очищении. В этом режиме все уведомления отправляются немедленно, а не с некоторой задержкой в соответствии с обычными операциями TCP. Этот флаг не постоянный, он только включает или выключает режим quickack. Последующие операции с протоколом TCP будут по своему включать/выключать этот режим в зависимости от своих внутренних протоколов, настроек и факторов. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_SYNCNT Устанавливает число повторных передач SYN, отправляемых TCP до отмены попыток установки соединения. Не должно превышать 255. Эта опция не должна использоваться, если код в итоге должен быть портируемым. TCP_WINDOW_CLAMP Определяет размер предлагаемого окна в это значение. Ядро определяет минимальный размер в SOCK_MIN_RCVBUF/2. Эта опция не должна использоваться, если код в итоге должен быть портируемым.

СИСТЕМНЫЕ ВЫЗОВЫ

Доступ к нижеприведенным ioctl можно получить через ioctl (2). Синтаксис следующий:

SIOCINQ Возвращает количество несчитанных данных в очереди в буфере приема. Аргументом является указатель на целое число. Сокет должен быть в состоянии прослушивания LISTEN, иначе возвратится ошибка (EINVAL). SIOCATMARK Возвращает истинное значение, если все срочные данные уже получены программой пользователя. Используется совместно с SO_OOBINLINE . Аргументом является указатель на целое число, служащее результатом проверки. SIOCOUTQ Возвращает количество неотправленных данных в очереди буфера отправления, в передаваемом указателе на целое число. Сокет не должен быть в состоянии прослушивания LISTEN, иначе возвратится ошибка (EINVAL).

ОБРАБОТКА ОШИБОК

Hекоторые приложения требуют более быстрого предупреждения об ошибках. Это может быть выполнено с помощью уровня SOL_IP опции IP_RECVERR сокета. Если эта опция запущена, то все входящие ошибки немедленно передаются программе пользователя. Используйте эту опцию осторожно: она приводит к тому, что TCP становится более чувствительным к сменам маршрутов и возникновению других условий, обычных для сети.

ЗАМЕЧАНИЯ

Если во время соединения произошла ошибка записи в сокет, то значение SIGPIPE устанавливается только при установлении опции SO_KEEPALIVE .

TCP не имеет внепоточных данных; он имеет срочные данные. В Linux это означает, что если другая сторона посылает новые внепоточные данные, то старые срочные данные вставляются в поток в качестве обычных (даже если не установлена опция SO_OOBINLINE ). Это поведение отличается от поведения стеков BSD.

Linux по умолчанию использует совместимую с BSD интерпретацию указателя на неотложные данные. Это противоречит RFC1122, но необходимо для взаимодействия сетей. Положение можно изменить с помощью sysctl-вызова tcp_stdurg .

НАЙДЕННЫЕ ОШИБКИ

EPIPE Другая сторона неожиданно закрыла сокет, или была произведена попытка чтения в отключенном сокете. ETIMEDOUT Другая сторона не подтвердила передачу данных через определенное время. EAFNOTSUPPORT Переданный в sin_family тип сокета не был типом AF_INET .

Любые ошибки, определенные для ip (7) или общего уровня сокетов, могут быть возвращены и для TCP.

НАЙДЕННЫЕ ОШИБКИ

IPv6 не описано.

ВЕРСИИ

Поддержка для Explicit Congestion Notification, файлов zerocopy sendfile, поддержку переупорядочения и некоторые расширения SACK (DSACK) были представлены в версии 2.4. Поддержка для forward acknowledgement (FACK), циклам TIME_WAIT, опции поддержки сокетов для каждого соединения и вызовы sysctl были представлены в версии 2.3. Значения по умолчанию и описатели переменных sysctl, указанные выше, применимы для ядер 2.4 и выше.

АВТОРЫ

Это руководство было изначально написано Andi Kleen. Затем было обновлено для ядер версии 2.4 благодаря Nivedita Singhvi, с помощью Documentation/networking/ip-sysctls.txt от Alexey Kuznetsov.

СМ. ТАКЖЕ

RFC793 - спецификации TCP.
RFC1122 - требования TCP и описание алгоритма Nagle.
RFC1323 - для временных меток TCP и опций масштабируемых окон.
RFC1644 - для описания риска снятия TIME_WAIT.
RFC2481 - для описания Explicit Congestion Notification.
RFC2581 - некоторые алгоритмы управления TCP.
RFC2018 и RFC2883 - для SACK и расширений SACK.

Понимание сетевого стека Linux (1): краткое описание стека сетевых протоколов Linux

В этой серии статей описывается сетевой стек Linux, в том числе:

(4) Технология разгрузки сегментации в среде QEMU / KVM + VxLAN (принимающая сторона)

1. Сетевой путь Linux


1.1 отправитель

1.1.1 Уровень приложения

(1) Socket

Различные сетевые приложения на прикладном уровне в основном взаимодействуют со стеком сетевых протоколов пространства ядра через программный интерфейс Linux Socket. Linux Socket разработан на основе BSD Socket, является одной из важных частей операционной системы Linux и основой сетевых приложений. На иерархическом уровне он расположен на уровне приложений и представляет собой API, предоставляемый операционной системой для программистов приложений, через который приложения могут получить доступ к протоколу транспортного уровня.

  • Сокет расположен над протоколом транспортного уровня, что позволяет скрыть различия между разными сетевыми протоколами.
  • Socket - это вход в сетевое программирование. Он обеспечивает большое количество системных вызовов и составляет основную часть сетевых программ.
  • В системе Linux сокеты являются частью файловой системы, а сетевое взаимодействие можно рассматривать как чтение файлов, что делает управление сетью таким же удобным, как управление файлами.




Процесс обработки сокета UDP (источник) Процесс обработки сокета TCP (источник)

(2) Поток обработки на уровне приложений


1.1.2 Транспортный уровень

Конечная цель транспортного уровня - предоставить своим пользователям эффективные, надежные и экономичные услуги передачи данных.Основные функции включают (1) построение сегмента TCP (2) вычисление контрольной суммы (3) отправку пакета ответа (ACK) (4) Операция, гарантирующая надежность, например, скользящий отвод. Общий процесс обработки стека протоколов TCP показан на следующем рисунке:


Краткий процесс работы стека TCP:

  1. Функция tcp_sendmsg сначала проверяет статус установленного TCP-соединения, затем получает MSS соединения и запускает процесс отправки сегмента.
  2. Создайте загрузку сегмента TCP: он создает экземпляр skb структуры данных sk_buffer пакета в пространстве ядра и копирует данные пакета из буфера пространства пользователя в буфер skb.
  3. Создайте заголовок TCP.
  4. Вычислить контрольную сумму TCP (контрольную сумму) и порядковый номер (порядковый номер).
    1. Контрольная сумма TCP - это сквозная контрольная сумма, вычисляемая отправителем и затем проверяемая получателем. Его цель - обнаруживать любые изменения в заголовке TCP и данных от отправителя к получателю. Если получатель обнаруживает ошибку в контрольной сумме, сегмент TCP будет напрямую отброшен. Контрольная сумма TCP покрывает заголовок TCP и данные TCP.
    2. Требуется контрольная сумма TCP

    Краткий процесс работы стека UDP:

    1.1.3 IP-сетевой уровень - добавление заголовка и контрольной суммы, обработка маршрутизации, IP-фрагментация

    Задача сетевого уровня - выбрать подходящие узлы маршрутизации и коммутации между сетями для обеспечения своевременной передачи данных. Сетевой уровень составляет пакеты данных из кадров, предоставленных канальным уровнем.Заголовок сетевого уровня инкапсулируется в пакет, который содержит информацию о логическом адресе - сетевые адреса исходного сайта и адреса конечного сайта. В его основные задачи входит (1) обработка маршрутизации, то есть выбор следующего перехода (2) добавление IP-заголовка (3) вычисление контрольной суммы IP-заголовка, которая используется для определения того, содержит ли заголовок IP-пакета ошибку во время процесса распространения (4), если возможно, продолжить После обработки IP-фрагментации (5) получите MAC-адрес следующего перехода, установите заголовок канального уровня и затем передайте на канальный уровень для обработки.


    Базовый процесс обработки IP-стека показан на следующем рисунке:


    1.1.4 Уровень канала передачи данных

    Функционально, на основе услуги потока битов, предоставляемой физическим уровнем, устанавливается канал данных между соседними узлами, обеспечивается безошибочная передача кадров данных (Frame) по каналу посредством контроля ошибок, и выполняются действия в каждой цепи. серии. Уровень канала передачи данных обеспечивает надежную передачу на ненадежных физических носителях. Роль этого уровня включает: адресацию физических адресов, формирование кадров данных, управление потоком, обнаружение ошибок данных, повторную передачу и т. Д. На этом уровне единица данных называется кадром. Представители протоколов уровня звена данных включают: SDLC, HDLC, PPP, STP, Frame Relay и т. Д.

    С точки зрения реализации, Linux предоставляет уровень абстракции сетевого устройства, фактически это теперь linux / net / core / dev.c. Конкретные физические сетевые устройства должны реализовывать виртуальные функции в драйвере устройства (driver.c). Уровень абстракции сетевого устройства вызывает функции определенных сетевых устройств.


    1.1.5 Инкапсуляция и передача физического уровня на физическом уровне


    1.1.6 Краткое резюме


    (источник)

    1.2 Ресивер

    1.2.1 Физический уровень и уровень канала данных



    1.2.2 Сетевой уровень





    1.2.3 Транспортный уровень (TCP / UDP)

    1. Запись обработки TCP транспортного уровня находится в функции tcp_v4_rcv (находится в файле linux / net / ipv4 / tcp ipv4.c), которая выполняет проверку заголовка TCP и другую обработку.
    2. Вызовите _tcp_v4_lookup, чтобы найти открытый сокет пакета. Если его не найти, пакет будет удален. Затем проверьте состояние сокета и подключения.
    3. Если для сокета и соединения все в порядке, вызовите tcp_prequeue, чтобы пакет вошел в пользовательское пространство из ядра и поместил его в очередь приема сокета. Затем сокет будет разбужен, вызовет системный вызов и, наконец, вызовет функцию tcp_recvmsg, чтобы получить сегмент из очереди приема сокета.

    1.2.4 Уровень приемника-приложения

    1. Каждый раз, когда пользовательское приложение вызывает read или recvfrom, этот вызов будет сопоставлен с системным вызовом sys_recv в /net/socket.c и преобразован в вызов sys_recvfrom, а затем будет вызвана функция sock_recgmsg.
    2. Для сокетов INET будет вызван метод inet_recvmsg в / net / ipv4 / af inet.c, который вызовет метод получения данных соответствующего протокола.
    3. Для TCP вызовите tcp_recvmsg. Эта функция копирует данные из буфера сокета в пользовательский буфер.
    4. Для UDP любой из трех системных вызовов recv () / recvfrom () / recvmsg () может быть вызван из пользовательского пространства для получения пакета UDP, и эти системные вызовы в конечном итоге вызовут метод udp_recvmsg в ядре.


    2. Linux структура данных sk_buff struct и очередь (очередь)

    2.1 sk_buff

    2.1.1 Что такое sk_buff

    Когда сетевой пакет обрабатывается ядром, данные нижележащего протокола передаются на более высокий уровень, и при передаче данных процесс меняется на противоположный. Данные (включая заголовок и нагрузку), генерируемые различными протоколами, непрерывно передаются на нижний уровень, пока они не будут окончательно отправлены. Поскольку скорость этих операций критична для производительности сетевого уровня, ядро ​​использует специальную структуру, называемую sk_buff, файл определения которой находится вskbuffer.h. Буферы сокетов используются для обмена данными на уровне реализации сети без копирования или депакетирования пакетов данных - это значительный выигрыш в скорости. Чтобы

    • sk_buff - это основная структура данных сети Linux, и ее файл определения находится вskbuffer.h。
    • Буфер ядра сокета (skb) - это буфер, используемый сетевым стеком ядра Linux (от L2 до L4) для обработки сетевых пакетов (пакетов), его тип - sk_buffer. Проще говоря, один skb представляет пакет в сетевом стеке Linux; несколько skb, созданных сегментацией TCP, и IP-пакет хранятся в виде списка skb.
    • struct sock имеет три очереди skb (очередь sk_buffer): rx, tx и err.


    Его основные конструктивные элементы:

    2.1.2 Основная операция skb

    (1) Размещение skb = alloc_skb (len, GFP_KERNEL)


    (2) Добавить полезную нагрузку (skb_put (skb, user_data_len))


    (3) Используйте skb-> push, чтобы добавить заголовок протокола, или skb-> pull, чтобы удалить заголовок.


    2.2 Очередь драйверов, используемая сетевым стеком Linux (очередь драйверов)

    (Выдержки из этой главыQueueing in the Linux Network Stack by Dan Siemon)

    2.2.1 Очередь


    Между стеком IP и драйвером сетевого адаптера существует очередь драйверов. Обычно он реализуется как кольцевой буфер FIFO, который можно рассматривать просто как фиксированный размер. Эта очередь не содержит пакетных данных. Напротив, она сохраняет только указатель буфера ядра сокета (skb), а использование skb описано в предыдущем разделе на протяжении всей обработки сетевого стека ядра.

    Пакеты, обрабатываемые стеком IP при вводе очереди. Эти пакеты либо генерируются приложением на локальном компьютере, либо поступают на локальный компьютер и маршрутизируются. Пакеты, добавленные в очередь IP-стеком, будут извлечены драйвером сетевого устройства (драйвером оборудования) и отправлены на аппаратное устройство NIC через шину данных и переданы.

    Если TSO / GSO не используется, длина пакетов, отправленных из IP-стека в эту очередь, должна быть меньше MTU.

    2.2.2 размер skb - максимальный размер по умолчанию - NIC MTU

    Большинство сетевых карт имеют атрибут фиксированной максимальной единицы передачи (MTU), который представляет собой размер самого большого кадра, который может передать сетевое устройство. Для Ethernet значение по умолчанию составляет 1500 байт, но некоторые сети Ethernet могут поддерживать кадры jumbo размером до 9000 байт. В стеке IP-сети MTU указывает размер самого большого пакета, который может быть отправлен на NIC. Например, если приложение записывает 2000 байтов данных в сокет TCP, стеку IP необходимо создать два IP-пакета, чтобы размер каждого пакета был равен или меньше 1500 байтов. Можно видеть, что для передачи больших объемов данных относительно небольшой MTU приведет к передаче большого количества небольших пакетов в очередь драйвера. Это называется фрагментацией IP.

    На следующем рисунке показана фрагментация IP-пакета с полезной нагрузкой 1500 байтов при MTU 1000 и 600:

    Читайте также: