Архитектура BPF и UNIX

BPF, или Berkley Packet Filter (пакетный фильтр Беркли), описанный Стивеном МакКейном и Ван Якобсоном (McCane and Jacobson 1993) – это архитектура ядра для захвата пакетов, созданная для работы с ядрами ОС UNIX.

BPF представляет собой драйвер устройства, который может использоваться приложениями ОС UNIX для передачи и приема пакетов, передаваемых по сети, напрямую через сетевой интерфейс (сетевой адаптер, модем) высокоэффективным методом. С другой стороны, BPF – не совсем обычный драйвер, поскольку он не управляет сетевым адаптером, а взаимодействует с его драйвером.

BPF состоит из двух основных элементов: сетевая ловушка (network tap) и пакетный фильтр (packet filter). Сетевая ловушка – это петлевая функция, являющаяся частью кода BPF, однако не вызываемая самим BPF. Ее вызывает драйвер сетевого адаптера, когда принимает очередной входящий пакет. Драйвер адаптера должен вызывать сетевую ловушку для каждого поступившего пакета, в противном случае BPF не будет нормально работать с этим адаптером. Сетевая ловушка копирует поступившие пакеты и передает их копии приложению верхнего уровня, каковым для нее является пакетный фильтр.

Пакетный фильтр – это заданная пользователем функция с бинарным результатом, устанавливаемым относительно входящего пакета. Если значение функции TRUE, ядро передает копию входящего пакета приложению верхнего уровня, если FALSE – входящий пакет игнорируется. Практически все приложения, использующие BPF, подавляют большинство входящих пакетов, поэтому производительность фильтра определяет производительность приложения.

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

На рис.1 показано взаимодействие BPF с операционной системой.

BPF назначает фильтр и два буфера на каждый процесс, запросивший его функции. Фильтр создается приложением и передается в BPF путем вызова функций IOCTL. Оба буфера постоянно размещены в BPF, и их размер составляет обычно 4 кБ. Первый буфер (store buffer – буфер сохранения) используется для приема данных от адаптера, второй (hold buffer – буфер задержки) используется для копирования пакетов для приложений. Если буфер сохранения заполнен, а буфер задержки пуст, BPF меняет их местами.

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

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

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

Входящий пакет игнорируется фильтром также в том случае, если буфер сохранения заполнен, а буфер задержки недоступен (т.е. приложение считывает из него данные).

Приложение взаимодействует с драйвером BPF при помощи библиотеки захвата пакетов, называемой libpcap (packet capture library). Для получения принятых пакетов из буфера задержки приложение вызывает системную функцию считывания. Если буфер задержки заполнен (или истекло время ожидания), BPF копирует содержимое буфера в память приложения и передает ему управление. Приложение способно принять более одного пакета за один раз. Для выделения границ блоков принятых данных BPF снабжает их заголовком, содержащим время приема и размер блока, а также концевиком для синхронизации блоков данных.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: