Функции
pr_input()
и
pr_output()
определяют интерфейс взаимодействия протокол-протокол и служат для передачи данных между модулями соседних уровней. Аналогично для обмена управляющими командами между модулями протоколов используются функции
pr_ctlinput()
и
pr_ctloutput()
. Цепочка взаимодействующих протоколов производит размещение и освобождение памяти при обмене сообщениями, которые передаются посредством рассмотренных структур
mbuf
: при передаче сообщений от сети прикладному процессу за освобождение буферов
mbuf
отвечает модуль верхнего уровня и наоборот, при передаче сообщений в сеть память, занимаемая сообщением, освобождается на самом нижнем уровне.
Поле
pr_flags
определяет некоторые характеристики протокола и режим его функционирования, которые в основном относятся к уровню сокетов. Например, протоколы, предусматривающие предварительное установление связи, указывают это с помощью флага
PR_CONNREQUIRED
, не позволяя тем самым функциям сокета передавать данные модулю до создания виртуального канала. Если установлен флаг
PR_WANTRCVD
, соответствующие функции сокета будут уведомлять модуль протокола, когда прикладной процесс получает данные из буфера приема. Это может служить сигналом протоколу для отправления подтверждения о получении, а также для обновления значения окна в соответствии с освободившимся местом.
Заметим, что каждый модуль протокола имеет собственные очереди сообщений, используемые для приема и передачи данных.
Каждый сетевой интерфейс системы представлен структурой данных, показанной на рис. 6.23. Сетевой интерфейс обычно связан с соответствующим сетевым адаптером, хотя это не является обязательным условием. Например, внутренний сетевой интерфейс loopback представляет собой псевдоустройство, используемое для унифицированного взаимодействия сетевых процессов в рамках одного хоста, отладки и т.п.
Рис. 6.23. Сетевой интерфейс
Решение об использовании того или иного сетевого интерфейса для передачи сообщения базируется на таблице маршрутизации и производится модулем сетевого уровня. Интерфейс может обслуживать протоколы различных коммуникационных доменов. Соответственно, один и тот же интерфейс может иметь несколько адресов, определенных для каждого семейства протоколов. Структуры, определяющие локальный и широковещательный (broadcast) адреса интерфейса, а также сетевую маску, хранятся в виде связанного списка.
Каждый сетевой интерфейс имеет очередь, в которую помещаются сообщения для последующей передачи, выполняемой функцией
if_output()
. Интерфейс также может определить процедуры инициализации
if_init()
, сброса
if_reset()
и обработки таймера
if_watchdog()
. Последняя может использоваться для управления потенциально ненадежными устройствами или для периодического сбора статистики устройства.
Состояние интерфейса характеризуется флагами, хранящимися в поле
if_flags
. Возможные флаги приведены в табл. 6.8.
Таблица 6.8. Состояния интерфейса
Флаг | Значение |
IFF_UP
| Интерфейс доступен для использования |
IFF_BROADCAST
| Интерфейс поддерживает широковещательные адреса |
IFF_MULTICAST
| Интерфейс поддерживает групповые адреса |
IFF_DEBUG
| Интерфейс обеспечивает возможность отладки |
IFF_LOOPBACK
| Программный внутренний интерфейс |
IFF_POINTOPOINT
| Интерфейс для канала точка-точка |
IFF RUNNING
| Ресурсы интерфейса успешно размещены |
IFF_NOARP
| Интерфейс не использует протокол трансляции адреса |
Флаг
IFF_UP
свидетельствует о готовности интерфейса передавать сообщения. Если сетевой интерфейс подключен к физической сети, поддерживающей широковещательную адресацию (broadcast), например, Ethernet, для интерфейса будет установлен флаг
IFF_BROADCAST
и определен широковещательный адрес (поле
ifa_broadaddr
структуры адресов
ifaddr
для соответствующего коммуникационного домена). Если же интерфейс используется для канала точка-точка, будет установлен флаг
IFF_POINTOPOINT
и определен адрес хоста (интерфейса), расположенного на противоположном конце (поле
ifa_dstaddr
). Заметим, что эти два флага являются взаимоисключающими, a
ifa_broadaddr
и
ifa_dstaddr
являются различными именами одного и того же поля. Интерфейс устанавливает флаг
IFF_RUNNING
после размещения необходимых структур данных и отправления начального запроса на чтение устройству (например, сетевому адаптеру), с которым он ассоциирован.
Состояние интерфейса и ряд других параметров можно просмотреть с помощью команды ifconfig(1M):
$ ifconfig le0
le0: flags=863<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 194.85.160.50 netmask: ffffff00 broadcast 194.85.160.255
Легко заметить, что команда выводит значение следующих полей структуры
ifnet
для интерфейса
le0
(
if_name
):
if_flags
,
if_mtu
(Maximum Transmission Unit, MTU) определяющее максимальный размер пакета, который может быть передан по физической сети, а также значения полей структуры ifaddr: адрес интерфейса
inet
(
ifa_addr
), маску
netmask
(
ifa_netmask
) и широковещательный адрес
broadcast
(
ifa_broadaddr
).
Интерфейс хранит статистическую информацию, которая может быть использована при мониторинге сети. В частности, эта информация включает число полученных пакетов уровня канала (
if_ipackets
), количество ошибок при приеме (
if_ierrors
), число отправленных пакетов уровня канала (
if_opackets
), количество ошибок при передаче (
if_oerrors
) и число коллизий (
if_collisions
). Команда
netstat(1M) позволяет получить эту информацию для сконфигурированных интерфейсов в системе: