Стек сетевых протоколов linux

Для системного администратора

Анатомия сетевого стека в Linux

Одна из величайших возможностей операционной системы Linux® — ее сетевой стек. Он является производной стека BSD и хорошо оснащен добротным набором интерфейсов, которые варьируются от протоколо-независимых (protocol agnostic), таких как интерфейс уровня общих сокетов или уровня устройств, до специальных интерфейсов конкретных сетевых протоколов. В этой статье исследуется структура сетевого стека Linux с точки зрения его уровней, а также рассматриваются некоторые из основных структур.

Введение в протоколы

В то время как формальное введение в работу в сети отсылает нас к модели взаимодействия открытых систем (OSI — Open Systems Interconnection), это введение в основной сетевой стек в Linux использует четырехуровневую модель, известную как модель Интернет (Internet model) (смотрите рисунок 1).

Рисунок 1. Интернет-модель сетевого стека

Внизу стека располагается канальный уровень. Канальный уровень относится к драйверам устройств, обеспечивающим доступ к физическому уровню, который может состоять из многочисленных сред, таких как последовательные каналы или устройства Ethernet. Над канальным находится сетевой уровень, который отвечает за направление пакетов по назначению. Следующий уровень под названием транспортный отвечает за одноранговые (peer-to-peer) коммуникации (например, в пределах хоста). Сетевой уровень управляет связью между хостами, а транспортный — взаимодействием между конечными точками внутри этих хостов. Наконец, существует прикладной уровень, который обычно является семантическим и понимает перемещенные данные. К примеру, протокол передачи гипертекста (HTTP — Hypertext Transfer Protocol) перемещает запросы и ответы для содержимого Web между сервером и клиентом.

В сущности, уровни сетевого стека проходят под более узнаваемыми названиями. На канальном уровне вы найдете Ethernet, наиболее распространенную высокоскоростную среду. К более старым протоколам канального уровня относятся такие последовательные протоколы, как Internet-протокол для последовательной линии (SLIP — Serial Line Internet Protocol), Compressed SLIP (CSLIP) и Point-to-Point Protocol (PPP). Наиболее распространенным протоколом сетевого уровня является Internet Protocol (IP), но существуют и другие, которые удовлетворяют другим нуждам, такие как Протокол управляющих сообщений Internet (ICMP — Internet Control Message Protocol) и Протокол разрешения адресов (ARP — Address Resolution Protocol). На транспортном уровне это Протокол управления передачей (TCP — Transmission Control Protocol) и Протокол пользовательских датаграмм (UDP — User Datagram Protocol). Наконец, прикладной уровень включает в себя множество привычных нам протоколов, в том числе HTTP, стандартный Web-протокол, и SMTP (Simple Mail Transfer Protocol), протокол передачи электронной почты.

Архитектура базовой сети

Теперь перейдем к архитектуре сетевого стека Linux и посмотрим, как он реализует модель Internet. На рисунке 2 представлен высокоуровневый вид сетевого стека Linux. Наверху располагается уровень пользовательского пространства или прикладной уровень, который определяет пользователей сетевого стека. Внизу находятся физические устройства, которые обеспечивают возможность соединения с сетями (последовательные или высокоскоростные сети, как Ethernet). В центре, или в пространстве ядра, — сетевая подсистема, которая находится в центре внимания данной статьи. Через внутреннюю часть сетевого стека проходят буферы сокетов (sk_buffs), которые перемещают данные пакета между источниками и получателями. Кратко будет показана структура sk_buff.


Рисунок 2. Высокоуровневая архитектура сетевого стека Linux

Во-первых, вам предлагается краткий обзор основных элементов сетевой подсистемы Linux с подробностями в следующих разделах. Наверху (смотрите рисунок 2) находится система под названием интерфейс системного вызова. Она просто дает способ приложениям из пользовательского пространства получать доступ к сетевой подсистеме ядра. Следующим идет протоколо-независимый (protocol agnostic) уровень, который предоставляет общий способ работы с нижестоящими протоколами транспортного уровня. Дальше следуют фактические протоколы, к которым в системе Linux относятся встроенные протоколы TCP, UDP и, конечно же, IP. Следующий — еще один независимый уровень, который обеспечивает общий интерфейс к отдельным доступным драйверам устройств и от них, сопровождаемый в конце самими этими драйверами.

Интерфейс системного вызова

Интерфейс системного вызова может быть описан в двух ракурсах. Когда сетевой вызов производится пользователем, он мультиплексируется через системный вызов в ядро. Это заканчивается как вызов sys_socketcall в ./net/socket.c, который потом демультиплексирует вызов намеченной цели. Другой ракурс интерфейса системного вызова — использование нормальных файловых операций для сетевого ввода/вывода (I/O). Например, обычные операции чтения и записи могут быть выполнены на сетевом сокете (который представляется файловым дескриптором как нормальный файл). Поэтому пока существуют операции, специфичные для работы в сети (создание сокета вызовом socket, связывание его с дескриптором вызовом connect и так далее), есть также и некоторое количество стандартных файловых операций, которые применяются к сетевым объектам, как к обычным файлам. Наконец, интерфейс системного вызова предоставляет средства для передачи управления между приложением в пользовательском пространстве и ядром.

Протоколо-независимый интерфейс (Protocol agnostic interface)

Уровень сокетов является протоколо-независимым (protocol agnostic) интерфейсом, который предоставляет набор стандартных функций для поддержки ряда различных протоколов. Этот уровень не только поддерживает обычные TCP- и UDP-протоколы, но также и IP, raw Ethernet и другие транспортные протоколы, такие как Протокол управления передачей потоков данных (SCTP — Stream Control Transmission Protocol).

Взаимодействие через сетевой стек происходит посредством сокета. Структура сокета в Linux — struct sock, определенная в linux/include/net/sock.h. Эта большая структура содержит все необходимые состояния отдельного сокета, включая определенный протокол, используемый сокетом, и операции, которые можно над ним совершать.

Сетевая подсистема знает о доступных протоколах из специальной структуры, которая определяет ее возможности. Каждый протокол содержит структуру под названием proto (она находится в linux/include/net/sock.h). Эта структура определяет отдельные операции сокета, которые могут выполняться из уровня сокетов на транспортный уровень (например, как создать сокет, как установить соединение с сокетом, как закрыть сокет и т.д.).

Сетевые протоколы

Раздел сетевых протоколов определяет отдельные доступные сетевые протоколы (такие как TCP, UDP и так далее). Они инициализируются в начале дня в функции inet_init в linux/net/ipv4/af_inet.c (так как TCP и UDP относятся к семейству протоколов inet). Функция inet_init регистрирует каждый из встроенных протоколов, использующих функцию proto_register. Эта функция определена в linux/net/core/sock.c, и кроме добавления протокола в список действующих, если требуется, может выделять один или более slab-кэшей.

Читайте также:  Линукс минт где диски

Можно увидеть, как отдельные протоколы идентифицируют сами себя посредством структуры proto в файлах tcp_ipv4.c, udp.c и raw.c, в linux/net/ipv4/. Каждая из этих структур протоколов отображается в виде типа и протокола в inetsw_array, который приписывает встроенные протоколы их операциям. Структура inetsw_array и его связи показаны на рисунке 3. Каждый из протоколов в этом массиве инициализируется в начале дня в inetsw вызовом inet_register_protosw из inet_init. Функция inet_init также инициализирует различные модули inet, такие как ARP, ICMP, IP-модули и TCP и UDP-модули.

Рисунок 3. Структура массива Internet-протокола

Обратите внимание на рисунке 3, что структура proto определяет транспортные методы сокета, в то время как структура proto_ops — общие. Дополнительные протоколы можно добавить в переключатель протоколов inetsw с помощью вызова inet_register_protosw. Например, SCTP добавляет себя вызовом sctp_init в linux/net/sctp/protocol.c.

Перемещение данных для сокетов происходит при помощи основной структуры под названием буфер сокета (sk_buff). В sk_buff содержатся данные пакета и данные о состоянии, которые охватывают несколько уровней стека протокола. Каждый отправленный или полученный пакет представлен в sk_buff. Структура sk_buff определяется в linux/include/linux/skbuff.h и показана на рисунке 4.

Рисунок 4. Буфер сокета и его связи с другими структурами

Как можно заметить, несколько структур sk_buff для данного соединения могут быть связаны вместе. Каждая из них идентифицирует структуру устройства (net_device), которому пакет посылается или от которого получен. Так как каждый пакет представлен в sk_buff, заголовки пакетов удобно определены набором указателей (th, iph и mac для Управления доступом к среде (заголовок Media Access Control или MAC). Поскольку структуры sk_buff являются центральными в организации данных сокета, для управления ими был создан ряд функций поддержки. Существуют функции для создания, разрушения, клонирования и управления очередностью sk_buff.

Буферы сокетов разработаны таким образом, чтобы связываться друг с другом для данного сокета и включать большой объем информации, в том числе ссылки на заголовки протоколов, временные метки (когда пакет был отправлен или получен) и соответствующее устройство.


Устройство-независимый интерфейс (Device agnostic interface)

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

Прежде всего, драйверы устройств могут регистрировать и разрегистрировать себя в ядре вызовом register_netdevice или unregister_netdevice. Вызывающая команда сначала заполняет структуру net_device, а затем передает ее для регистрации. Ядро вызывает свою функцию init (если она определена), выполняет несколько проверок исправности, создает запись sysfs и потом добавляет новое устройство в список устройств (связанный список устройств, активных в ядре). Структуру net_device можно найти в linux/include/linux/netdevice.h. Некоторые функции находятся в linux/net/core/dev.c.

Для отправления sk_buff из уровня протокола устройству используется функция dev_queue_xmit. Она ставит в очередь sk_buff для возможной пересылки соответствующим драйвером устройства (устройством, определенным при помощи net_device или указателя sk_buff->dev в sk_buff). Структура dev содержит метод под названием hard_start_xmit, который хранит функцию драйвера для инициализации передачи sk_buff.

Получение пакета выполняется традиционно при помощи netif_rx. Когда драйвер устройства более низкого уровня получает пакет (содержащийся внутри выделенного sk_buff), sk_buff идет выше, на сетевой уровень, с помощью вызова netif_rx. Эта функция затем ставит sk_buff в очередь на более высокий уровень протоколов для дальнейшей обработки при помощи netif_rx_schedule. Функции dev_queue_xmit и netif_rx находятся в linux/net/core/dev.c.

Наконец, для взаимодействия с устройство-независимым уровнем (dev) в ядро был введен новый интерфейс прикладных программ (NAPI). Его используют некоторые драйверы, но подавляющее большинство все еще пользуется более старым интерфейсом получения кадров (по грубой оценке шесть из семи). NAPI может давать лучшую производительность при больших нагрузках, избегая при этом прерываний при каждом входящем кадре.

Драйверы устройств

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

Во время инициализации драйвер устройства выделяет место для структуры net_device, а затем инициализирует ее необходимыми подпрограммами. Одна из них, с названием dev->hard_start_xmit, определяет, как верхний уровень должен поставить в очередь sk_buff для передачи. Ей передается sk_buff. Работа этой функции зависит от оборудования, но обычно пакет, описываемый в sk_buff, перемещается в так называемое “аппаратное кольцо” (hardware ring) или “очередь” (queue). Поступление кадра, как описано на устройство-независимом уровне, использует интерфейс netif_rx или netif_receive_skb для NAPI-совместимого сетевого драйвера. Драйвер NAPI накладывает ограничения на возможности базового оборудования.

После того как драйвер устройства настроил свои интерфейсы в структуре dev, вызов register_netdevice делает ее доступной для использования. В linux/drivers/net можно найти драйверы, характерные для сетевых устройств.

Идем дальше

Исходный код Linux — прекрасный способ узнать о конструкции драйверов для множества типов устройств, включая драйверы сетевых устройств. Вы обнаружите различия в конструкции и использовании доступных API ядра, но каждый будет полезен либо инструкциями, либо как отправная точка для нового драйвера. Остальной код в сетевом стеке стандартен и используется, пока не потребуется новый протокол. Но даже тогда реализации TCP (для потокового протокола) или UDP (для протокола на основе передачи сообщений) служат полезными моделями для начала новой разработки.

Автор: М. Тим Джонс, инженер-консультант, Emulex
Взято с ibm developerworks

Источник

Русские Блоги

Стек сетевых протоколов ядра Linux

оглавление

Каталог статей

Предисловие

В этой статье в основном описываются принципы работы стека сетевых протоколов ядра Linux. Она предназначена для обучающих записей и предназначена только для справки. Большой объем контента поступает из сети. Подробности см. В списке справочных статей.

NOTE: В этой статье рассматриваются две версии ядра Linux 1.2.13 и 2.6.32.

Предыдущий список

Инкапсуляция и распространение сообщений с данными

Пакет: Когда приложение использует протокол TCP для передачи данных, данные сначала поступают в стек протоколов базовой сети, а затем проходят через каждый уровень набора протоколов TCP / IP один за другим, пока не будут отправлены в сеть в виде потока битов. . Для каждого уровня соответствующая информация заголовка протокола инкапсулируется для полученных данных (иногда добавляется хвостовая информация). Единица данных, передаваемая из протокола TCP в протокол IP, называется сегментом сообщения TCP или сокращенно сегментом TCP. Блок данных, который IP передает на уровень канала данных, называется дейтаграммой IP, а битовый поток, окончательно переданный через Ethernet, называется кадром.

Читайте также:  Sidecar mac os ��� ��������

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

Стек сетевых протоколов ядра Linux

Многоуровневая структура стека протоколов


Уровень логической абстракции

  • Физический слой: В основном предоставляют различные подключенные физические устройства, такие как различные сетевые карты, последовательные порты и т. Д.
  • Связующий слой: В основном предоставляют драйверы для различных интерфейсных карт, которые обращаются к физическому уровню, например драйверы сетевых карт.
  • Сетевой уровень: Он отвечает за передачу пакетов сетевых данных в нужное место.Самым важным протоколом сетевого уровня является протокол IP в дополнение к таким протоколам, как ICMP, ARP и RARP.
  • Транспортный уровень: Обеспечивает сквозные соединения между приложениями, в основном протоколами TCP и UDP.
  • Уровень приложения: Как следует из названия, он в основном предоставляется прикладной программой и используется для выполнения семантической интерпретации «уровня интерфейса взаимодействия человека с компьютером» передаваемых данных, таких как HTTP, SMTP, FTP и другие протоколы.

Уровень реализации стека протоколов

  • Аппаратный уровень (аппаратное обеспечение физического устройства): Также известен как уровень драйвера, который предоставляет интерфейс для подключения аппаратных устройств.
  • Независимый от устройства интерфейс: Также известный как уровень интерфейса устройства, он предоставляет абстрактный интерфейс для драйверов, который не имеет ничего общего с конкретными устройствами. Целью этого уровня является, в основном, унификация интерфейса между драйверами различных интерфейсных карт и уровнем сетевого протокола. Он разделяет функции различных драйверов на несколько специальных действий, таких как открытие, закрытие, инициализация и т. Д. Этот уровень может экранировать различные драйверы на нижнем уровне.
  • Сетевые протоколы: Соответствует IP-уровню и транспортному уровню. Несомненно, это ядро ​​всего стека сетевых протоколов ядра. Этот уровень в основном реализует различные сетевые протоколы, наиболее важными из которых, конечно же, являются IP, ICMP, ARP, RARP, TCP, UDP и т. Д.
  • Независимый от протокола уровень (интерфейс, не зависящий от протокола), Также известный как уровень интерфейса протокола, по сути является уровнем СОКЕТА. Цель этого уровня — защитить многие типы сетевых протоколов на уровне сетевых протоколов (в основном, протоколы TCP и UDP, конечно, включая RAW IP, SCTP и т. Д.), Чтобы обеспечить простой и единообразный интерфейс для вышеуказанной системы. слой вызова для вызова. Проще говоря, независимо от того, какой протокол использует наш прикладной уровень, мы должны установить СОКЕТ через интерфейс системного вызова.Этот СОКЕТ на самом деле представляет собой огромную структуру сокета, которая связана с уровнем сетевого протокола ниже для защиты различных сетевых протоколов. Часть данных представлена ​​на прикладном уровне через интерфейс системного вызова.
    • BSD(Berkeley Software Distribution)socket: Уровень сокетов BSD предоставляет унифицированный интерфейс работы СОКЕТА и тесно связан со структурой сокетов.
    • INET (относится ко всем сетям, поддерживающим протокол IP) сокет: Уровень сокета INET, вызывающий унифицированный интерфейс протокола уровня IP, тесно связанный со структурой сокета.
  • Уровень интерфейса системного вызоваПо сути, это библиотека вызова интерфейса для приложений пользовательского пространства, которая предоставляет интерфейсы для приложений пользовательского пространства для использования сетевых служб.

Структура данных стека протоколов

  • msghdr: Описывает формат сообщения, передаваемый с уровня приложения, включая важную информацию, такую ​​как адрес пользовательского пространства и тег сообщения.
  • iovec: Описывает начальную позицию адреса пользовательского пространства.
  • file: Структура, описывающая атрибуты файла, соответствующие дескриптору файла один к одному.
  • file_operations: Структуры, связанные с файловыми операциями, включая read() 、 write() 、 open() 、 ioctl() Подождите.
  • socket: Структура операции сокета BSD, предоставляемая для прикладного уровня, не зависит от протокола.Основная функция заключается в обеспечении унифицированной операции сокета для прикладного уровня.
  • sock: Sock сетевого уровня, который определяет независимые от протокола операции, представляет собой унифицированную структуру сетевого уровня, и на этой основе транспортный уровень реализует inet_sock.
  • sock_common: Наименьший сетевой уровень представляет структуру.
  • inet_sock: Структура уровня представления, расширение, сделанное на sock, используется для представления общей структуры транспортного уровня семейства протоколов inet над сетевым уровнем.
  • udp_sock: Транспортный уровень Протокол UDP выделенная структура sock, расширенная на транспортном уровне inet_sock.
  • proto_ops: Интерфейс от уровня сокета BSD к интерфейсу уровня inet_sock, в основном используется для управления структурой сокета.
  • proto: Унифицированный интерфейс от уровня inet_sock к работе транспортного уровня, в основном используется для работы со структурой sock.
  • net_proto_family: Используется для идентификации и регистрации семейства протоколов. Общие семейства протоколов — IPv4 и IPv6.
  • softnet_data: Ядро выделяет такое пространство данных softnet_data для каждого процессора. У каждого CPU есть такая очередь для приема пакетов данных.
  • sk_buff: Опишите атрибуты структуры кадра, включая сокет, время прибытия, устройство прибытия, размер заголовка каждого уровня, запись маршрутизации следующей станции, длину кадра, контрольную сумму и т. Д.
  • sk_buff_head: Структура очереди пакетов данных.
  • net_device: Эта огромная структура описывает все атрибуты, данные и другую информацию сетевого устройства.
  • inet_protosw: Зарегистрируйте интерфейс вызывающей операции уровня сокетов на уровне IP.
  • inetsw_array: Вызовы уровня сокета Интерфейсы операций уровня IP регистрируются в этом массиве.
  • sock_type: Тип розетки.
  • IPPROTO: ID типа протокола транспортного уровня.
  • net_protocol: Интерфейс, используемый протоколом транспортного уровня для регистрации и приема пакетов на уровне IP.
  • packet_type: Структура кадра данных Ethernet, включая тип и метод обработки кадра Ethernet.
  • rtable: Структура таблицы маршрутизации, описывающая полную форму таблицы маршрутизации.
  • rt_hash_bucket: Кэш таблицы маршрутизации.
  • dst_entry: Интерфейс назначения пакета, который описывает ключевую информацию маршрутизации, такую ​​как выход и выход из пакета и следующий переход.
  • napi_struct: Структура расписания NAPI. NAPI — это технология, используемая в Linux для повышения эффективности сетевой обработки. Ее основная концепция — не использовать прерывания для чтения данных. Вместо этого он сначала использует прерывания для пробуждения службы приема данных, а затем использует опрос для опроса данных. . Технология NAPI подходит для обработки высокоскоростных пакетов данных небольшой длины.
Читайте также:  Настройка linux для web разработки

Процесс инициализации стека сетевых протоколов

Это нужно начинать с процесса загрузки ядра. Когда ядро ​​завершает самораспаковывающийся процесс, оно входит в процесс запуска ядра. Этот процесс является первым в программе arch / mips / kernel / head.S, которая отвечает за область данных (BBS), таблицу описания прерываний (IDT ) и таблица описания сегментов (GDT).), таблица страниц и инициализация регистра, функция входа ядра определяется в программе. kernel_entry() 、 kernel_entry() Функция представляет собой ассемблерный код, связанный с архитектурой. Сначала она инициализирует сегмент стека ядра для подготовки к первому процессу создания системы, затем использует цикл для очистки сегмента неинициализированных данных образа ядра до нуля и, наконец, переходит к start_kernel() Код, связанный с оборудованием, инициализируется в функции для завершения создания среды ядра Linux.

start_kenrel() Настоящий процесс инициализации ядра, определенный в init / main.c, начинается здесь. Функция start_kerenl() Будет вызван ряд функций инициализации, таких как: инициализация платформы, инициализация памяти, инициализация прерывания, инициализация прерывания, инициализация планирования процесса, инициализация буфера, чтобы завершить настройки всех аспектов самого ядра, цель состоит в том, чтобы наконец установить в основном полная среда ядра Linux.

start_kernel() Основные функции и отношения между вызовами следующие:

start_kernel() Будет выполнено в течение socket_init() Для завершения инициализации стека протоколов реализация выглядит следующим образом:


sock_init() Содержит работу по инициализации стека протоколов ядра:

  • sock_init: Инициализировать кеш sk_buff SLAB, зарегистрировать файловую систему SOCKET.
  • net_inuse_init: Кэш выделяется для каждого процессора.
  • proto_init: Создайте файл протоколов в домене / proc / net и зарегистрируйте соответствующие функции работы с файлами.
  • net_dev_init: Установить структуру данных, относящуюся к сетевому устройству, в / proc / sys, и разрешить сетевой карте отправлять и получать прерывания; инициализировать очередь приема пакетов данных (softnet_data) для каждого ЦП, обратный вызов приема пакетов; регистрировать локальные операции кольцевой проверки и регистрировать по умолчанию операции с сетевым устройством.
  • inet_init: Зарегистрируйте метод создания СОКЕТА семейства протоколов INET и зарегистрируйте основные методы приема пакетов для интерфейсов TCP, UDP, ICMP и IGMP. Создайте файл proc для семейства протоколов IPv4. Эта функция является основной функцией регистрации стека протоколов:
    • rc = proto_register(&udp_prot, 1); : Зарегистрируйте протокол UDP уровня INET и выделите для него быстрый кеш.
    • (void)sock_register(&inet_family_ops); : Кому static const struct net_proto_family *net_families[NPROTO] В структуре регистрируется набор операций семейства протоколов INET (в основном создание сокетов INET).
    • inet_add_protocol(&udp_protocol, IPPROTO_UDP) : Кому externconst struct net_protocol *inet_protos[MAX_INET_PROTOS] Структура регистрирует набор операций UDP транспортного уровня.
    • static struct list_head inetsw[SOCK_MAX]; for (r = &inetsw[0]; r : Инициализировать массив типа СОКЕТ, в котором хранится массив связанного списка, каждый элемент — связанный список, соединение использует тот же протокол типа СОКЕТ и набор операций.
    • for (q = inetsw_array; q :
      • inet_register_protosw(q); : Набор операций вызова, зарегистрированных в протоколе sock.
    • arp_init(); : Запустить поддержку протокола ARP.
    • ip_init(); : Включить поддержку протокола IP.
    • udp_init(); : Запустить поддержку протокола UDP.
    • dev_add_pack(&ip_packet_type); : Кому ptype_base[PTYPE_HASH_SIZE]; Зарегистрируйте набор операций протокола IP.
    • socket.c Предоставляемый интерфейс системного вызова.


Выполнить после завершения инициализации стека протоколов dev_init() Продолжить инициализацию устройства.

Процесс создания сокета

Обзор процесса получения стека протоколов

Уровень оборудования и уровень, независимый от устройств: Оборудование контролирует физический носитель и получает данные.Когда полученные данные заполняют буфер, оборудование генерирует прерывание.После создания прерывания система переходит к подпрограмме обслуживания прерывания. В подпрограмме обслуживания прерывания данные будут скопированы из аппаратного буфера в буфер пространства ядра и упакованы в структуру данных (sk_buff), а затем будет вызвана функция интерфейса на уровень драйвера. netif_rx() Отправьте пакет данных на аппаратно-независимый уровень. Эта функция реализована в net / inet / dev.c с использованием технологии bootom half. Принцип этой технологии заключается в искусственном разделении обработчика прерывания на две части. Верхняя часть представляет собой задачу с высокими требованиями к реальному времени, а вторая Половина части может быть завершена позже, так что вы можете сэкономить время обработки программы прерывания и улучшить производительность системы в целом.

NOTE: Файл dev.c играет важную роль в реализации всего стека протоколов. Он соединяет аппаратный уровень под ним и уровень сетевого протокола над ним. Его можно назвать модулем канального уровня или реализацией независимого от устройства слой.

Уровень сетевого протокола: Взяв дейтаграмму IP в качестве примера, она будет вызываться при переходе с уровня, независимого от устройства, на уровень сетевого протокола. ip_rcv() . Эта функция вызовет функцию обработки соответствующего протокола в соответствии с протоколом транспортного уровня, используемым в заголовке IP. UDP-переписка udp_rcv() , TCP корреспонденция tcp_rcv() , ICMP-переписка icmp_rcv() , Переписка IGMP igmp_rcv() . Чтобы tcp_rcv() Например, структура sock, соответствующая всем сокетам, использующим протокол TCP, вешается в массив sock_array структуры proto, представленной глобальной переменной tcp_prot, с использованием метода вставки с номером локального порта в качестве индекса. Так когда tcp_rcv() После получения пакета данных, после завершения необходимой проверки и обработки, он будет использовать номер порта назначения в заголовке протокола TCP в качестве индекса и получит правильную очередь структуры sock в массиве sock_array структуры sock, соответствующей tcp_prot, и затем дополните его. Просмотрите очередь с другими условиями для запроса соответствующей структуры sock. После получения соответствующей структуры sock повесьте пакет данных в очередь кеша в структуре sock (на которую указывает поле receive_queue в структуре sock), тем самым завершив окончательный прием пакета данных.

NOTE: Хотя ICMP и IGMP здесь обычно классифицируются как протоколы сетевого уровня, они фактически инкапсулированы в протокол IP и рассматриваются как транспортный уровень.

Независимый от протокола уровень и уровень интерфейса системных вызовов: Когда пользователю необходимо получить данные, сначала получите структуру сокета и структуру sock в соответствии с индексом дескриптора файла, а затем прочтите пакет данных из очереди recieve_queue, на которую указывает структура sock, и скопируйте пакет данных в пространство пользователя. буфер. Данные полностью передаются с оборудования в пользовательское пространство. Это также завершает полную передачу снизу вверх.

Источник

Оцените статью