bpf-helpers(7)

BPF-HELPERS(7) Руководство программиста Linux BPF-HELPERS(7)

ИМЯ

BPF-HELPERS - список вспомогательных функций eBPF

ОПИСАНИЕ

Расширенная подсистема пакетных фильтров Беркли (eBPF) представляет собой программы, написанные на псевдо-ассемблерном языке, которые прикрепляются к одному из перехватчиков ядра (hooks) и запускаются в ответ на определённые события. Эта инфраструктура отличается от старой, «классической» BPF («cBPF»), некоторыми моментами, одним из которых является способность вызывать из программ специальные функции («помощники» helpers). Эти функции перечислены в белом списке помощников, который задаётся ядром.

Эти помощники используются в программах eBPF для взаимодействия с системой или рабочим контекстом. Например, они могут использоваться для печати отладочных сообщений, получения времени, прошедшего с момента загрузки системы, для взаимодействия с картами eBPF или для обработки сетевых пакетов. Так есть несколько типов программ eBPF и они не могут работать в одном контексте, каждый тип программ может вызывать только некоторую часть этих помощников.

В соответствии с правилами eBPF помощник может иметь не более пяти аргументов.

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

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

ПОМОЩНИКИ

void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
Описание
Выполняет в map поиск записи, связанной с key.
Возвращает
Значение карты, связанное с key, или NULL, если запись не найдена.

int bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
Описание
Добавляет или обновляет значение записи, связанное с key в map, равное value. Значение flags может быть одним из:
BPF_NOEXIST
Запись для key не должна существовать в карте.
BPF_EXIST
Запись для key должна существовать в карте.
BPF_ANY
Не учитывать условие существования записи для key.

Значение флага BPF_NOEXIST нельзя использовать для карт с типом BPF_MAP_TYPE_ARRAY или BPF_MAP_TYPE_PERCPU_ARRAY (все элементы всегда существуют), помощник вернул бы ошибку.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_map_delete_elem(struct bpf_map *map, const void *key)
Описание
Удаляет запись с key из map.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)
Описание
Заталкивает элемент value в map. В flags может быть одно из:

BPF_EXIST Если очередь/стек полны, то самый старый элемент удаляется, освобождая место под указанный.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_probe_read(void *dst, u32 size, const void *src)
Описание
Для программ трассировки; безопасно попытаться прочитать size байт по адресу src и сохранить данные в dst.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

u64 bpf_ktime_get_ns(void)
Описание
Возвращает время, прошедшее с момента запуска системы, в наносекундах.
Возвращает
Текущее значение ktime.

int bpf_trace_printk(const char *fmt, u32 fmt_size, ...)
Описание
Этот помощник подобен printk() и помогает в отладке. Он печатает сообщение, определяемое форматом fmt (размером fmt_size), в файл /sys/kernel/debug/tracing/trace из DebugFS, если есть. Принимает до трёх дополнительных аргументов u64 (как и для всех помощников eBPF, общее количество аргументов ограничено пятью).

Каждый раз при вызове помощника, он добавляет строку в трассировку. Формат трассировки можно изменять, и конечный результат зависит от указанных в /sys/kernel/debug/tracing/trace_options параметров (также смотрите файл README в том же каталоге). Однако, при обычных настройках строка выглядит так:

telnet-470   [001] .N.. 419421.045894: 0x00000001: <formatted msg>


Где:

  • telnet — имя текущей задачи.
  • 470 — PID текущей задачи.
  • 001 номер ЦП, на котором выполняется текущая задача.
  • В .N.. каждый символ ссылается на набор параметров (разрешены ли irq, параметры планирования, работает ли hard/softirq, уровень preempt_disabled, соответственно). N означает, что установлены TIF_NEED_RESCHED и PREEMPT_NEED_RESCHED.
  • 419421.045894 — метка времени.
  • 0x00000001 — фиктивное значение, используемое BPF как регистр указателя инструкций.
  • <formatted msg> — сообщение, отформатированное согласно fmt.



Спецификаторы преобразований, поддерживаемые fmt, похожи, но несколько ограничены, чем у printk(). Список: %d, %i, %u, %x, %ld, %li, %lu, %lx, %lld, %lli, %llu, %llx, %p, %s. Нельзя указывать модификатор (размер поля, заполнение нулями и т. п.) и помощник вернёт -EINVAL (и ничего не напечатает), если обнаружит неизвестный спецификаторы.

Также заметим, что bpf_trace_printk() медленно работает и должна использоваться только в целях отладки. Поэтому при первом использовании (точнее, при выделении буферов trace_printk()) в журнал ядра печатается блок с уведомлением (охватывающем несколько строк), в котором говорится, что данный помощник не должен «использоваться в промышленной эксплуатации». Для передачи значений в пространство пользователя нужно использовать события perf.

Возвращает
Количество байт, записанных в буфер, или отрицательный номер ошибки.

u32 bpf_get_prandom_u32(void)
Описание
Возвращает псевдослучайное число.

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

Возвращает
Случайное 32-битное беззнаковое значение.

u32 bpf_get_smp_processor_id(void)
Описание
Возвращает идентификатор SMP (симметричного мультиобрабатывающего) процессора. Заметим, что все программы выполняются с выключенным вытеснением, то есть идентификатор SMP-процессора не изменяется за всё время выполнения программы.
Возвращает
Идентификатор SMP-процессора выполняющейся программы.

int bpf_skb_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len, u64 flags)
Описание
Записывает len байт из адреса from в пакет, связанный с skb, по смещению offset. Значением flags является комбинация BPF_F_RECOMPUTE_CSUM (повторное автоматическое вычисление контрольной суммы пакета после записи байт) и BPF_F_INVALIDATE_HASH (присваивает skb->hash, skb->swhash и skb->l4hash значение 0).

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_l3_csum_replace(struct sk_buff *skb, u32 offset, u64 from, u64 to, u64 size)
Описание
Повторно вычисляет контрольную сумму заголовка 3-го уровня (например, IP) из пакета, связанного с skb. Вычисление является поступательным, поэтому помощник должен знать предыдущее значение поля заголовка, которое было изменено (from), новое значение этого поля (to) и количество байт (2 или 4) этого поля, хранящиеся в size. Или же можно сохранить различие между предыдущим и новым значениями поля заголовка в to, установив from и size равными 0. В обоих способах в offset задаётся расположение контрольной суммы IP внутри пакета.

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

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_l4_csum_replace(struct sk_buff *skb, u32 offset, u64 from, u64 to, u64 flags)
Описание
Повторно вычисляет контрольную сумму заголовка 4-го уровня (например, TCP, UDP или ICMP) из пакета, связанного с skb. Вычисление является поступательным, поэтому помощник должен знать предыдущее значение поля заголовка, которое было изменено (from), новое значение этого поля (to) и количество байт (2 или 4) этого поля, хранящиеся в младших четырёх битах flags. Или же можно сохранить различие между предыдущим и новым значениями поля заголовка в to, установив from и четыре младших бита flags равными 0. В обоих способах в offset задаётся расположение контрольной суммы IP внутри пакета. В дополнении размера поля в flags можно добавить (побитовым ИЛИ) нужные флаги. При указании BPF_F_MARK_MANGLED_0 контрольная сумма null остаётся неизменяемой (если также не указан BPF_F_MARK_ENFORCE), а чтобы обновить результат в контрольной сумме null нужно задать значение CSUM_MANGLED_0. Флаг BPF_F_PSEUDO_HDR задаёт, что контрольная сумма будет вычислена повторно на уровне псевдо-заголовка.

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

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_tail_call(void *ctx, struct bpf_map *prog_array_map, u32 index)
Описание
Это специальный помощник используется для активации «хвостового вызова», иначе говоря, прыжка в другую программу eBPF. Используется тот же кадр стека (но значения в стеке и в регистрах вызывающего недоступны вызываемому). Этот механизм позволяет образовывать цепочки программ, или для превышения максимального количества доступных инструкций eBPF, или для выполнения заданной программы в блоках условий. Из соображений безопасности существует верхний предел количества последовательных хвостовых вызовов, которые можно выполнить.

При вызове из помощника программы пытается прыгнуть в программу согласно индексу index в prog_array_map, специальной карте с типом BPF_MAP_TYPE_PROG_ARRAY, и передать ctx, указатель на контекст.

Если вызов произошёл без ошибок, то ядро сразу выполняет первую инструкцию новой программы. Это не вызов функции и возврата к старой программе никогда не происходит. Если при вызове возникла ошибка, то помощник ничего не делает и вызывающий продолжает выполнение со следующей инструкции. Вызов может завершиться ошибкой, если прыжок указывает на несуществующую программу (т. е. значение index превышает количество элементов prog_array_map), или если в этой цепочке программ достигнуто максимальное количество хвостовых вызовов. Данный предел определён в ядре макросом MAX_TAIL_CALL_CNT (недоступен в пользовательском пространстве) и в данный момент равен 32.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_clone_redirect(struct sk_buff *skb, u32 ifindex, u64 flags)
Описание
Клонирует и перенаправляет пакет, связанный с skb, в другое сетевое устройство с индексом ifindex. Для перенаправления можно использовать как входящий так и исходящий интерфейсы. В качестве отличительного признака в flags используется значение BPF_F_INGRESS (выбирается входящий путь, если флаг указан, в противном случае — исходящий). В настоящее время поддерживается только этот флаг.

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

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

u64 bpf_get_current_pid_tgid(void)
Возвращает
64-битное целое, содержащее текущий tgid и pid, создаваемое как: current_task->tgid << 32 | current_task->pid.

u64 bpf_get_current_uid_gid(void)
Возвращает
4-битное целое, содержащее текущий GID и UID, создаваемое как: current_gid << 32 | current_uid.

int bpf_get_current_comm(char *buf, u32 size_of_buf)
Описание
Копирует атрибут comm текущей задачи в buf размером size_of_buf. Атрибут comm содержит имя исполняемого файла (без пути) текущей задачи. Значение size_of_buf должно быть положительным. При успешном выполнении помощник проверяет, что buf заканчивается NUL. При ошибке заполняется нулями.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

u32 bpf_get_cgroup_classid(struct sk_buff *skb)
Описание
Возвращает classid текущей задачи, т. е. net_cls cgroup, которой принадлежит skb.

Этот помощник можно использовать на исходящих путях TC, но не на входящих.

net_cls cgroup предоставляет интерфейс для маркировки сетевых пакетов на основе пользовательского идентификатора для всего трафика, который поступает от задач, принадлежащих соответствующей cgroup. Смотрите также соответствующую документацию ядра в файле исходного кода Linux Documentation/cgroup-v1/net_cls.txt.

В ядре Linux есть две версии cgroups: cgroups v1 и cgroups v2. Они обе доступны пользователям, их можно использовать одновременно, но заметим, что net_cls cgroup есть только для cgroup v1. Это приводит к несовместимости с программами BPF, выполняющимися на cgroups, которые используют только cgroup v2 (сокет может хранить данные только для одной версии cgroups одновременно).

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_CGROUP_NET_CLASSID равным "y" или "m".

Возвращает
classid или 0 по умолчанию для ненастроенного classid.

int bpf_skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
Описание
Добавляет vlan_tci (тег управляющей информации VLAN) протокола vlan_proto в пакет, связанный с skb, а затем обновить контрольную сумму. Заметим, что если vlan_proto отличается от ETH_P_8021Q и ETH_P_8021AD, то будет считаться, что указан ETH_P_8021Q.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_vlan_pop(struct sk_buff *skb)
Описание
Удаляет заголовок VLAN из пакета, связанного с skb.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_get_tunnel_key(struct sk_buff *skb, struct bpf_tunnel_key *key, u32 size, u64 flags)
Описание
Возвращает метаданные туннеля. Этому помощнику передаётся указатель key на пустую struct bpf_tunnel_key размером size, которая будет заполнена метаданными туннеля для пакета, связанного с skb. В flags можно указать значение BPF_F_TUNINFO_IPV6, которое показывает, что туннель основан на протоколе IPv6, а не на IPv4.

Объект struct bpf_tunnel_key сводит основные параметры, используемые различными туннельными протоколами, в одну структуру. Он позволяет легко принимать решение на основе содержимого инкапсулированного заголовка, «обобщённого» в этой структуре. В частности, он содержит IP-адрес ответной стороны (IPv4 или IPv6) в key->remote_ipv4 или key->remote_ipv6. Также, эта структура предоставляет key->tunnel_id, обычно отображаемый в VNI (идентификатор виртуальной сети, Virtual Network Identifier), который можно использовать программировании с помощью помощника bpf_skb_set_tunnel_key().

Представим, что следующий код — часть программы, присоединённой к входящему интерфейсу TC, туннель GRE и что нужно фильтровать все сообщения, приходящие с ответной стороны, у которых адрес IPv4 не равен 10.0.0.1:

int ret;
struct bpf_tunnel_key key = {};
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
if (ret < 0)

return TC_ACT_SHOT; // отбрасываем пакет if (key.remote_ipv4 != 0x0a000001)
return TC_ACT_SHOT; // отбрасываем пакет return TC_ACT_OK; // пропускаем пакет


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

Его можно использовать вместе с различными туннелями, такими как VXLan, Geneve, GRE или IP в IP (IPIP).

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_set_tunnel_key(struct sk_buff *skb, struct bpf_tunnel_key *key, u32 size, u64 flags)
Описание
Заполняет метаданные туннеля в пакете, связанном с skb. Метаданные туннеля представляют собой набор значений key и size. В flags можно указать комбинацию следующих значений:
BPF_F_TUNINFO_IPV6
Задаёт, что туннель основан на протоколе IPv6, а не IPv4.
BPF_F_ZERO_CSUM_TX
Для пакетов IPv4 добавление этого флага в метаданные туннеля указывает, что не нужно вычислять контрольную сумму и присвоить ей значение ноль.
BPF_F_DONT_FRAGMENT
Добавление этого флага в метаданные туннеля указывает, что пакет не должен фрагментироваться.
BPF_F_SEQ_NUMBER
Добавление этого флага в метаданные туннеля указывает, что перед отправкой пакета в туннельный заголовок нужно добавить порядковый номер. Этот флаг был добавлен для протокола GRE, но в будущем может использоваться и для других.

Обычное использование в пути передачи:

struct bpf_tunnel_key key;

заполняем ключ … bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); bpf_clone_redirect(skb, vxlan_dev_ifindex, 0);


Также смотрите описание помощника bpf_skb_get_tunnel_key().

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

u64 bpf_perf_event_read(struct bpf_map *map, u64 flags)
Описание
Читает значение счётчика событий perf. Этот помощник использует map с типом BPF_MAP_TYPE_PERF_EVENT_ARRAY. Источник счётчика событий perf выбирается при обновлении map через файловые дескрипторы событий perf. Значение map представляет собой массив, размер которого равен количеству доступных ЦП, а каждая ячейка содержит значение для соответствующего ЦП. Получаемое значение задаётся в flags, которое содержит индекс искомого ЦП с наложенной маской BPF_F_INDEX_MASK. Или же flags можно присвоить BPF_F_CURRENT_CPU, которое показывает, что нужно получать значение для текущего ЦП.

Заметим, что в до Linux 4.13 можно быть получать только аппаратные события perf.

Кроме того, вместо bpf_perf_event_read() рекомендуется использовать новый помощник bpf_perf_event_read_value(). В старом имеются некоторые странности в ABI, например в качестве возвращаемого кода используется и значение ошибки и счётчика (что неправильно, так как эти диапазоны могут перекрываться). Эта проблема исправлена в bpf_perf_event_read_value(), а также представляется больше возможностей по сравнению с интерфейсом bpf_perf_event_read(). Дополнительную информацию смотрите в описании bpf_perf_event_read_value().

Возвращает
Значение счётчика событий perf читается из карты, или отрицательный код ошибки при невозможности.

int bpf_redirect(u32 ifindex, u64 flags)
Описание
Перенаправляет пакет в другое сетевое устройство с индексом ifindex. Этот помощник похож на bpf_clone_redirect(), но пакет не клонируется, что увеличивает производительность.

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

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

Возвращает
Для XDP при успешном выполнении помощник возвращает XDP_REDIRECT и XDP_ABORTED при ошибке. Для других типов программ при успешном выполнении возвращается TC_ACT_REDIRECT и TC_ACT_SHOT при ошибке.

u32 bpf_get_route_realm(struct sk_buff *skb)
Описание
Находит область (realm) или маршрут, то есть поле tclassid назначения для skb. Найденный идентификатор представляет собой пользовательскую метку, похожую на используемые в net_cls cgroup (смотрите описание помощника bpf_get_cgroup_classid()), но здесь эта метка хранится в маршруте (элементе назначения), а не в задаче.

Поиск этого идентификатора работает с исходящим перехватчиком (hook) clsact TC (смотрите также tc-bpf(8)) или общеупотребительными классовыми исходящими qdisc, но не на входящих путях TC. В случае с исходящим перехватчиком clsact TC имеется преимущество, так как внутри элемент назначения ещё не был отброшен в пути передачи. Поэтому не нужно искусственно хранить элемент назначения через netif_keep_dst(), как в classful qdisc, до тех пор, пока не освобождён skb.

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_IP_ROUTE_CLASSID.

Возвращает
Область маршрута для пакета, связанного с skb или 0, если не найдена.

int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
Описание
Записывает неструктурированные кусок data в специальное событие BPF perf, хранящееся в map с типом BPF_MAP_TYPE_PERF_EVENT_ARRAY. Это событие perf должно иметь следующие атрибуты: PERF_SAMPLE_RAW для sample_type, PERF_TYPE_SOFTWARE для type и PERF_COUNT_SW_BPF_OUTPUT для config.

Значение flags используется для указания индекса в map, по которому должно быть записано значение с наложенной маской BPF_F_INDEX_MASK. Или же в flags можно задать BPF_F_CURRENT_CPU для указания того, что должен использоваться индекс текущего ядра ЦП.

Записываемое значение размером size передаётся через стек eBPF и на него указывает data.

Помощнику также требуется передать контекст программы ctx.

В пользовательском пространстве программе, которая будет читать значения, нужно вызвать perf_event_open() при событии perf (или для одного или для всех ЦП) и сохранить файловый дескриптор в map. Это нужно сделать до того как программа eBPF может послать в него данные. Пример показан в файле samples/bpf/trace_output_user.c из дерева исходного кода ядра Linux (программа eBPF приведена в файле samples/bpf/trace_output_kern.c).

У bpf_perf_event_output() большая производительность чем у bpf_trace_printk() для обмена данными с пользовательским пространством и он больше подходит для передачи потока данных из программ eBPF.

Заметим, что этот помощник не ограничен в применении только трассировкой и может использоваться также с программами, подключаемыми к TC или XDP, где позволяет передавать данные слушателям в пользовательском пространстве. Данными могут быть:

  • Только выборочные структуры,
  • Только пакетная полезная нагрузка или
  • оба сразу.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, void *to, u32 len)
Описание
Предназначен для облегчения загрузки данных из пакета. Он загружает len байт с адреса offset из пакета, связанного с skb, в буфер, на который указывает to.

Начиная с Linux 4.7, использование этого помощника, большей частью заменено «прямым доступом к пакету», который позволяет управлять данными пакета через skb->data и skb->data_end, указывающими на первый байт данных пакета и байт, находящийся после последнего байта пакета данных, соответственно. Однако, помощник всё ещё полезен, если нужно прочитать большое количество данных за раз из пакета в стек eBPF.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags)
Описание
Проходит по пользовательскому стеку или стеку ядра и возвращает его id. Для этого помощнику нужен ctx — указатель на контекст, в котором выполняется трассирующая программа, и указатель на map с типом BPF_MAP_TYPE_STACK_TRACE.

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

BPF_F_USER_STACK
Проходить по стеку пользовательского пространства, а не по стеку ядра.
BPF_F_FAST_STACK_CMP
Сравнивать стеки только по хешу.
BPF_F_REUSE_STACKID
Если два разных хеша стеков указывают на один stackid, отбросить старый.

Возвращаемый id стека представляет собой 32-битное длинное целое, которое в дальнейшем можно объединить с другими данными (включая id других стеков) и используется как ключ к картам. Он может быть полезен для генерации различных графиков (например, flame или off-cpu).

Для прохода по стеку этот помощник производительнее bpf_probe_read(), который можно использовать с развёрнутыми циклами, но это не эффективно и потребляет много инструкций eBPF. Напротив, bpf_get_stackid() может проходить до PERF_MAX_STACK_DEPTH кадров ядра и пользовательского стека. Заметим, что это ограничение можно изменить программой sysctl, и его нужно вручную увеличивать при профилировании длинных пользовательских стеков (например, от программ Java). Для этого выполните:

# sysctl kernel.perf_event_max_stack=<новое значение>


Возвращает
При успешном выполнении возвращает положительный или null id стека и отрицательное значение при ошибке.

s64 bpf_csum_diff(__be32 *from, u32 from_size, __be32 *to, u32 to_size, __wsum seed)
Описание
Сравнивает контрольную сумму различия неструктурированного буфера, на который указывает from и имеет размер from_size (должен быть кратен 4), с неструктурированным буфером, на который указывает to и имеет размер to_size (тоже примечание). К значению можно добавить необязательный seed (каскадируется, затравка может поступать из предыдущего вызова помощника).

Может использоваться несколькими способами:

  • Если from_size == 0, to_size > 0 и seed равно контрольной сумме — при заталкивании новых данных.
  • Если from_size > 0, to_size == 0 и seed равно контрольной сумме — при удалении данных из пакета.
  • Если from_size > 0, to_size > 0 и seed равно 0 — вычисляет разницу. Заметим, что from_size и to_size могут быть не равны.

Этот помощник можно использовать совместно с bpf_l3_csum_replace() и bpf_l4_csum_replace(), которым можно передавать различие, вычисленное bpf_csum_diff().

Возвращает
Результат контрольной суммы или отрицательный код ошибки.

int bpf_skb_get_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size)
Описание
Возвращает метаданные параметров туннеля для пакета, связанного с skb, и сохраняет неструктурированные данные параметров туннеля в буфер opt размером size.

Этот помощник можно использовать с устройствами инкапсуляции, которые могут работать в режиме «сбора метаданных» (подробности приведены в замечании к bpf_skb_get_tunnel_key()). В качестве примера можно привести совместное использование с протоколом инкапсуляции Geneve, где может вталкивать (с помощью помощника bpf_skb_get_tunnel_opt()) и получать произвольные TLV (заголовки Тип-Длина-Значение) из программы eBPF. Таким способом можно изменять эти заголовки полностью.

Возвращает
Размер возвращаемых данных.

int bpf_skb_set_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size)
Описание
Изменяет метаданные параметров туннеля для пакета, связанного с skb на данные параметров из неструктурированного буфера opt размером size.

Также смотрите описание помощника bpf_skb_get_tunnel_opt().

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_change_proto(struct sk_buff *skb, __be16 proto, u64 flags)
Описание
Изменяет протокол в skb на proto. Пока поддерживается переход с IPv4 на IPv6 и с IPv6 на IPv4. Этот помощник делает всю черновую работу, включая изменение размера сокетного буфера. Программе eBPF нужно заполнить новые заголовки, если есть, с помощью skb_store_bytes() и пересчитать контрольные суммы с помощью bpf_l3_csum_replace() и bpf_l4_csum_replace(). Основным предназначением этого помощника является выполнение операций NAT64 вне программы eBPF.

Внутри, тип GSO помечается как подозрительный, из-за чего механизм GSO/GRO проверяется эти заголовки и повторно вычисляет сегменты. Также подстраивается размер цели GSO.

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_change_type(struct sk_buff *skb, u32 type)
Описание
Изменяет тип пакета у пакета, связанного с skb. При этом только skb->pkt_type присваивается type, если программа eBPF не имеет прав записи в skb->pkt_type вне этого помощника. При таком использовании помощник позволяет правильно обработать ошибки.

В основном, он применяется для изменения входящего skb*s на **PACKET_HOST* программным методом, а не, например, с помощью перезаписи через redirect(..., BPF_F_INGRESS).

Заметим, что type может быть равен только определённым значениям. В настоящее время это:

PACKET_HOST
Пакет для нас.
PACKET_BROADCAST
Послать пакет всем.
PACKET_MULTICAST
Послать пакет группе.
PACKET_OTHERHOST
Послать пакет кому-то ещё.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_under_cgroup(struct sk_buff *skb, struct bpf_map *map, u32 index)
Описание
Проверяет, является ли skb потомком cgroup2, хранящейся в map с типом BPF_MAP_TYPE_CGROUP_ARRAY с индексом index.
Возвращает
Возвращаемое значение зависит от результата проверки и может быть:
  • 0, если skb не прошло проверку причастности к cgroup2.
  • 1, если skb прошло проверку причастности к cgroup2.
  • Отрицательный код ошибки при её возникновении.


u32 bpf_get_hash_recalc(struct sk_buff *skb)
Описание
Возвращает хеш пакета, skb->hash. Если он отсутствует, например, если хеш очищен при искажении (mangling), то это хеш вычисляется заново. В последствии к хешу можно обращаться непосредственно, через skb->hash.

Вызов bpf_set_hash_invalid(), изменение прототипа пакета с помощью bpf_skb_change_proto(), или вызов bpf_skb_store_bytes() с BPF_F_INVALIDATE_HASH приводят к очистке хеша и активируют новое вычисление при следующем вызове bpf_get_hash_recalc().

Возвращает
32-битный хеш.

u64 bpf_get_current_task(void)
Возвращает
Указатель на структуру текущей задачи.

int bpf_probe_write_user(void *dst, const void *src, u32 len)
Описание
Пытается безопасным способом записать len байт из буфера src в память dst. Это работает только для нитей в пользовательском контексте и dst должен быть корректным адресом пользовательского пространства.

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

Учтите, что это свойство является экспериментальным и может обрушить систему и выполняющиеся программы. Поэтому когда присоединяется программа eBPF, использующая этот помощник, в журнал ядра печатается предупреждение с PID и именем процесса.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_current_task_under_cgroup(struct bpf_map *map, u32 index)
Описание
Проверяет, выполняется ли тест в контексте заданного поднабора иерархии cgroup2. Тестируемый cgroup2 задаётся в map, имеет тип BPF_MAP_TYPE_CGROUP_ARRAY и индекс index.
Возвращает
Возвращаемое значение зависит от результата проверки и может быть:
  • 0, если задача skb принадлежит cgroup2.
  • 1, если задача skb не принадлежит cgroup2.
  • Отрицательный код ошибки при её возникновении.


int bpf_skb_change_tail(struct sk_buff *skb, u32 len, u64 flags)
Описание
Изменяет размер (обрезает или расширяет) пакета, связанного с skb, на новый len. Значения flags зарезервированы для использования в будущем и должны быть равны нулю.

По замыслу, помощник выполняет необходимую работу по изменению размера пакет, затем программа eBPF перезаписывает остальное через помощников bpf_skb_store_bytes(), bpf_l3_csum_replace(), bpf_l3_csum_replace() и других. Этот помощник является инструментом для медленного пути и предназначен для ответов управляющими сообщениями. Из-за нацелевания на медленный путь, сам помощник можно было делать медленным: он неявным образом преобразует к линейному виду, извлекает копии и удаляет нагрузку из skb.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_pull_data(struct sk_buff *skb, u32 len)
Описание
Стягивает в нелинейные данные, если skb является нелинейной и не вся длина len является частью линейного раздела. Делает len байт из skb доступными для чтения и записи. Если len равно нулю, то skb стягивается полностью.

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

При прямом доступе к пакету тест доступа по этим смещениям внутри границ пакета (до skb->data_end) завершится ошибкой, если смещения некорректны, или если запрашиваемые данные находятся в нелинейной части skb. При ошибке программа может просто завершить работу или, в случае нелинейного буфера, использовать помощник, чтобы сделать данные доступными. Помощник bpf_skb_load_bytes() — первое средство для доступа к данным. Также можно использовать bpf_skb_pull_data для стягивания нелинейных частей в одну, а затем повторить тест и получить доступ к данным.

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

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

s64 bpf_csum_update(struct sk_buff *skb, __wsum csum)
Описание
Добавляет контрольную сумму csum в skb->csum, если драйвер вставлял контрольную сумму для всего пакета в этом поле. В противном случае возвращается ошибка. Этот помощник предназначен для совместной работы с bpf_csum_diff(), в случае, когда контрольную сумму нужно обновить после прямой записи в пакет.
Возвращает
При успешном выполнении — контрольная сумма или отрицательный код ошибки.

void bpf_set_hash_invalid(struct sk_buff *skb)
Описание
Делает текущий skb->hash недействительным. Это можно использовать после искажения (mangling) заголовков через прямой доступ к пакету, чтобы показать, что хэш устарел и активировать пересчёт в следующий раз, когда ядро попытается обратиться к этому хэшу или когда будет вызван помощник bpf_get_hash_recalc().

int bpf_get_numa_node_id(void)
Описание
Возвращает id текущего узла NUMA. Основным предназначением помощника является выбор сокетов локального узла NUMA, когда программа присоединяется к сокетам посредством параметра SO_ATTACH_REUSEPORT_EBPF (смотрите также socket(7)), но помощник доступен и другим типам программ eBPF, например bpf_get_smp_processor_id().
Возвращает
ID текущего узла NUMA.

int bpf_skb_change_head(struct sk_buff *skb, u32 len, u64 flags)
Описание
Увеличивает место под заголовок пакета, связанного с skb и делает соответствующее смещение заголовка MAC, добавляя len байт пространства. Автоматически расширяет и переразмещает память как нужно.

Этот помощник также можно использовать в skb на уровне 3, чтобы затолкнуть заголовок MAC для перенаправления в устройство уровня 2.

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_xdp_adjust_head(struct xdp_buff *xdp_md, int delta)
Описание
Подгоняет (перемещает) xdp_md->data на delta байт. Заметим, что можно использовать отрицательное значение delta. Этот помощник можно использовать при подготовке пакета к вталкиванию и выталкиванию заголовков.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
Описание
Копирует строку с NUL в конце с опасного адреса unsafe_ptr в dst. В значении size нужно учитывать конечный байт NUL. Если длина строки меньше size, то цель не дополняется байтами NUL. Если длина строки больше size, то копируется size-1 байт, а в последний байт записывается NUL.

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

SEC("kprobe/sys_open")
void bpf_sys_open(struct pt_regs *ctx)

char buf[PATHLEN]; // PATHLEN равно 256
int res = bpf_probe_read_str(buf, sizeof(buf),
ctx->di);
// Заполняем buf, например, для отдачи в
// пространство пользователя через bpf_perf_event_output();
// можно использовать res (длину строки) как размер
// события после проверки её границ.


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

Другим полезным применением является разбор отдельных аргументов процесса или переменных окружения посредством прохода через current->mm->arg_start и current->mm->env_start: используя этот помощник и возвращаемое значение можно быстро обойти область памяти от правого смещения.

Возвращает
При успешном выполнении — только положительная длина строки, включая конечный символ NUL. При ошибке — отрицательное значение.

u64 bpf_get_socket_cookie(struct sk_buff *skb)
Описание
Если struct sk_buff, указывающая на skb, содержит известный сокет, то возвращает куки (cookie, генерируется ядром) сокета. Если куки ещё не назначена, то генерируется новая куки. После генерации куки сокета не меняется на всём протяжении жизни сокета. Этот помощник полезен для слежения за статистикой сетевого трафика отдельных сокетов, так как предоставляет уникальный идентификатор сокета в каждом пространстве имён.
Возвращает
При успешном выполнении — 8-байтовое длинное неуменьшающееся число, или 0, если в skb отсутствует поле сокета.

u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx)
Описание
Эквивалентен помощнику bpf_get_socket_cookie(), имеющему параметр skb, вместо которого принимает сокет из контекста struct bpf_sock_addr.
Возвращает
При успешном выполнении — 8-байтовое длинное неуменьшающееся число.

u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx)
Описание
Эквивалентен помощнику bpf_get_socket_cookie(), имеющему параметр skb, вместо которого принимает сокет из контекста struct bpf_sock_ops.
Возвращает
При успешном выполнении — 8-байтовое длинное неуменьшающееся число.

u32 bpf_get_socket_uid(struct sk_buff *skb)
Возвращает
Возвращает UID владельца сокета, связанного с skb. Если значение сокета равно NULL, или если это не полный сокет (т. е., если это сокет time-wait или request), то возвращает значение overflowuid (заметим, что overflowuid также может действующим UID значением сокета).

u32 bpf_set_hash(struct sk_buff *skb, u32 hash)
Описание
Присваивает значение hash полному хэшу skb (поле skb->hash).
Возвращает

int bpf_setsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen)
Описание
Эмулирует вызов setsockopt() для сокета, связанного с bpf_socket, который должен быть полным сокетом. Должны быть заданы уровень level, на котором располагается параметр, и и имя optname, подробности смотрите в setsockopt(2). Значение параметра optlen задаётся в optval.

В действительности этот помощник реализует поднабор setsockopt(). Он поддерживает следующие уровни level:

  • SOL_SOCKET, который поддерживает следующие optname: SO_RCVBUF, SO_SNDBUF, SO_MAX_PACING_RATE, SO_PRIORITY, SO_RCVLOWAT, SO_MARK.
  • IPPROTO_TCP, который поддерживает следующие optname: TCP_CONGESTION, TCP_BPF_IW, TCP_BPF_SNDCWND_CLAMP.
  • IPPROTO_IP, который поддерживает optname IP_TOS.
  • IPPROTO_IPV6, который поддерживает optname IPV6_TCLASS.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_adjust_room(struct sk_buff *skb, s32 len_diff, u32 mode, u64 flags)
Описание
Расширяет или сужает место под данные в пакете, связанном с skb, на len_diff и в соответствии с выбранным режимом mode.

На данный момент поддерживается только один режим:

BPF_ADJ_ROOM_NET: изменить пространство на сетевом уровне (пространство добавляется или удаляется после заголовка 3 уровня).

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_redirect_map(struct bpf_map *map, u32 key, u64 flags)
Описание
Перенаправляет пакет в конечную точку, на которую указывает key в map. В зависимости от её типа, в map могут содержаться ссылки на сетевые устройства (для пересылки пакетов через другие порты), или ЦП (для перенаправления кадров XDP в другой ЦП; на момент написания это реализовано только для родных XDP (с поддержкой драйверов)).

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

При использовании перенаправления пакетов в сетевые устройства этот помощник предоставляет более высокую производительность чем bpf_redirect(). Это стало возможным из-за различия в нижележащих механизмах, например, bpf_redirect_map() пытается отправить пакет в устройство «оптом».

Возвращает
При успешном выполнении — XDP_REDIRECT, XDP_ABORTED — при ошибке.

int bpf_sk_redirect_map(struct bpf_map *map, u32 key, u64 flags)
Описание
Перенаправляет пакет в сокет, на который указывает key в map (тип BPF_MAP_TYPE_SOCKMAP). Для перенаправления могут использоваться как входящий так и исходящий интерфейсы. В качестве отличительного признака в flags используется значение BPF_F_INGRESS (выбирается входящий путь, если флаг указан, в противном случае — исходящий). В настоящее время поддерживается только этот флаг.
Возвращает
При успешном выполнении — SK_PASS, SK_DROP — при ошибке.

int bpf_sock_map_update(struct bpf_sock_ops *skops, struct bpf_map *map, void *key, u64 flags)
Описание
Добавляет или обновляет элемент, ссылающийся на сокет, в map. В качестве нового значение элемента, связанного с key, используется skops. Значением flags может быть одно из:
BPF_NOEXIST
Запись для key не должна существовать в карте.
BPF_EXIST
Запись для key должна существовать в карте.
BPF_ANY
Не учитывать условие существования записи для key.

Если map содержит программы eBPF (анализатор и решение), то они будут наследоваться сокетом, который добавляется. Если сокет уже присоединён к программам eBPF, то возвращается ошибка.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_xdp_adjust_meta(struct xdp_buff *xdp_md, int delta)
Описание
Изменяет адрес, указанный в xdp_md->data_meta, на значение delta (положительное или отрицательное). Заметим, что эта операция изменяет адрес, хранящийся в xdp_md->data, поэтому последний должен быть загружен только после того, как был вызван помощник.

Использование поля xdp_md->data_meta необязательно и программам оно не требуется. Когда пакет обрабатывается с помощью XDP (например, фильтром DoS), перед передачей в стек вместе с ним возможно втолкнуть дополнительные метаданные и гарантируется, что входящая программа eBPF, подключённая как классификатор TC к тому же устройству, сможет подобрать их для дальнейшей пост-обработки. Так как TC работает с буферами сокетов, остаётся возможность задать из XDP указатели mark или priority, или другие указатели для буфера сокета. Такое рабочее программируемое и универсальное пространство предоставляет большую гибкость, поскольку пользователь может хранить любые метаданных какие захочет.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_perf_event_read_value(struct bpf_map *map, u64 flags, struct bpf_perf_event_value *buf, u32 buf_size)
Описание
Читает значение счётчика событий perf и сохраняет его в buf размером buf_size. Этот помощник использует map с типом BPF_MAP_TYPE_PERF_EVENT_ARRAY. Источник счётчика событий perf выбирается при обновлении map через файловые дескрипторы событий perf. Значение map представляет собой массив, размер которого равен количеству доступных ЦП, а каждая ячейка содержит значение для соответствующего ЦП. Получаемое значение задаётся в flags, которое содержит индекс искомого ЦП с наложенной маской BPF_F_INDEX_MASK. Или же flags можно присвоить BPF_F_CURRENT_CPU, которое показывает, что нужно получать значение для текущего ЦП.

Этот помощник работает почти также как bpf_perf_event_read(), но не возвращает значение, а помещает его в структуру buf. Это позволяет получать дополнительные данные,в частности, копируется время включения и выполнения (в buf->enabled иbuf->running, соответственно). В общем, рекомендуется использовать bpf_perf_event_read_value() вместо bpf_perf_event_read(), у которого есть проблемы с ABI и который имеет меньше возможностей.

Эти значения существенны, так как аппаратные счётчики PMU (Performance Monitoring Unit) — ограниченный ресурс. Когда открыто больше PMU (на основе событий perf), чем доступно счётчиков, ядро будет мультиплексировать эти события; при этом каждое событие получает определённый процент (но не всё) времени PMU. Если возникает мультиплексирование, количество выборок или значение счетчика не будет отражать происходящее, по сравнению, если бы мультиплексирования не было. Это затрудняет сравнение между несколькими запусками. Обычно, значение счётчика нужно нормализовать перед сравнением с другими экспериментами. Это выполняется следующим образом:

normalized_counter = counter * t_enabled / t_running


Где t_enabled — время включения события и t_running — время выполнения события, начиная с последней нормализации. Времена включения и выполнения накапливаются с момента открытия события perf. Для получения масштабирующего множителя между двумя вызовами программы eBPF пользователь может использовать ID ЦП в качестве ключа (типично при использовании массива perf) для запоминания предыдущего значения и выполнить вычисление внутри программы eBPF.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_perf_prog_read_value(struct bpf_perf_event_data *ctx, struct bpf_perf_event_value *buf, u32 buf_size)
Описание
Для программы eBPF, присоединённой к событию perf, возвращает значение счётчика события, связанного с ctx, и записывает его в структуру, на которую указывает buf и размер buf_size. Время включения и выполнения также записываются в структуру (смотрите описание помощника bpf_perf_event_read_value()).
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_getsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen)
Описание
Эмулирует вызов getsockopt() для сокета, связанного с bpf_socket, который должен быть полным сокетом. Должны быть заданы уровень level, на котором располагается параметр, и и имя optname, подробности смотрите в getsockopt(2). Возвращаемое значение записывается в структуру, на которую указывает opval, и имеющая размер optlen.

В действительности этот помощник реализует поднабор getsockopt(). Он поддерживает следующие уровни level:

  • IPPROTO_TCP, который поддерживает optname TCP_CONGESTION.
  • IPPROTO_IP, который поддерживает optname IP_TOS.
  • IPPROTO_IPV6, который поддерживает optname IPV6_TCLASS.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_override_return(struct pt_reg *regs, u64 rc)
Описание
Используется для вставки ошибки; этот помощник использует kprobes для перезаписи возвращаемого значения тестируемой (probed) функции и изменяет её на rc. С первым аргументом — контекст regs — работает kprobe.

Этот помощник изменяет PC (программный счётчик) на перезаписываемую функцию, которая выполняется вместо изначальной тестируемой функции. Это означает, что тестируемая функция вообще не выполняется. Заменяющая функция просто возвращает требуемое значение.

Этот помощник является потенциальным нарушителем безопасности и поэтому подвергнут ограничениям. Он доступен только, если ядро скомпилировано с параметром настройки CONFIG_BPF_KPROBE_OVERRIDE и при этом работает только с функциями, помеченными ALLOW_ERROR_INJECTION в коде ядре.

Также помощник доступен только на архитектурах, имеющих параметр CONFIG_FUNCTION_ERROR_INJECTION. На момент написания справки, только архитектура x86 поддерживает данное свойство.

Возвращает

int bpf_sock_ops_cb_flags_set(struct bpf_sock_ops *bpf_sock, int argval)
Описание
Пытается присвоить значение argval полю bpf_sock_ops_cb_flags для полного сокета TCP, связанного с bpf_sock_ops.

Основным предназначением этого поля является определение, вызывать ли программы eBPF с типом BPF_PROG_TYPE_SOCK_OPS в различных случаях из кода TCP. Программа такого типа может менять это значение для каждого соединения, если нужно, после установления соединения. Это поле доступно для прямого чтения, но данный помощник нужно использовать, чтобы получить ошибку обновления, если программа eBPF пытается назначить обратный вызов, который не поддерживается в текущем ядре.

Поддерживаемые значения обратных вызовов, которые можно объединять в argval:

  • BPF_SOCK_OPS_RTO_CB_FLAG (истекло время повторной передачи)
  • BPF_SOCK_OPS_RETRANS_CB_FLAG (повторная передача)
  • BPF_SOCK_OPS_STATE_CB_FLAG (изменение состояния TCP)

Вот некоторые примеры, когда может вызываться такая программа eBPF:

  • При возникновении RTO.
  • При повторной посылке пакета.
  • При завершении соединения.
  • При посылке пакета.
  • При получении пакета.

Возвращает
Код -EINVAL, если сокет не является полным сокетом TCP; в противном случае возвращается положительное число, содержащее биты, которые не могут быть установлены (то есть 0, если установлены все требуемые биты).

int bpf_msg_redirect_map(struct sk_msg_buff *msg, struct bpf_map *map, u32 key, u64 flags)
Описание
Этот помощник используется в программах, которые описывают политики на уровне сокета. Если сообщению msg разрешено проходить дальше (т. е., если решающая программа eBPF вернула SK_PASS), то оно перенаправляется в сокет, на который указывает индекс keykey в map (с типом BPF_MAP_TYPE_SOCKMAP). Для перенаправления можно использовать как входящий так и исходящий интерфейсы. В качестве отличительного признака в flags используется значение BPF_F_INGRESS (выбирается входящий путь, если флаг указан, в противном случае — исходящий). В настоящее время поддерживается только этот флаг.
Возвращает
При успешном выполнении — SK_PASS, SK_DROP — при ошибке.

int bpf_msg_apply_bytes(struct sk_msg_buff *msg, u32 bytes)
Описание
Для политик сокетов; выносит решение программе eBPF о следующих bytes (количество байт) сообщения msg.

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

  • Одиночный системный вызов sendmsg() или sendfile() содержит несколько логических сообщений, которые программа eBPF хочет прочитать и для которых нужно принять решение.
  • Программа eBPF заботится о чтении только первых bytes из msg. Если сообщение содержит больше полезной нагрузки, то для всех байт приходится настраиваить параметры и вызывать программу eBPF в цикле, хотя решение уже известно, что приводит к ненужным затратам.

При вызове из программы eBPF, помощник настраивает внутренний счётчик в инфраструктуре BPF, который используется для выборки последнего решения для следующих bytes. Если значение bytes меньше, чем текущих данных, полученных из системного вызова sendmsg() или sendfile(), то будут посланы первые bytes и программа eBPF выполнится повторно с указателем на начало данных, описывающим байт номер bytes + 1. Если значение bytes больше текущих обрабатываемых данных, то следующее решение eBPF будет применено к нескольких вызовам sendmsg() или sendfile(), пока не израсходуются все bytes.

Заметим, что если сокет закрыт с значением внутреннего счётчика отличным от нуля, то это не проблема, так как данные не буферизуются для bytes и пошлются сразу при получении.

Возвращает

int bpf_msg_cork_bytes(struct sk_msg_buff *msg, u32 bytes)
Описание
Для политик сокетов; предотвращает выполнение программы eBPF, выносящей решение для сообщения msg до тех пор, пока не наберётся количество байт bytes.

Это можно использовать, когда для принятия решения нужно определённое количество байт, даже если данные распределены между несколькими вызовами sendmsg() или sendfile(). Можно представить крайний случай, когда пользователь вызывает sendmsg() несколько раз разбивания сообщение по 1 байту. Очевидно, что это плохо сказывается на производительности, хотя и работает. Если программе eBPF для проверки заголовка нужно bytes байт, то помощник можно использовать для задержки вызова программы eBPF до тех пор, пока не будет накоплено нужное количество bytes.

Возвращает

int bpf_msg_pull_data(struct sk_msg_buff *msg, u32 start, u32 end, u64 flags)
Описание
Для политик сокетов; вытягивает нелинейные данные в msg из пользовательского пространства и изменяет указатели msg->data и msg->data_end на start и end байтового смещения в msg, соответственно.

Если программа имеет тип BPF_PROG_TYPE_SK_MSG и выполняется для msg, то она может обрабатывать только данные, для которых уже настроены указатели (data, data_end). Для перехватчиков sendmsg(), это, вероятно, первый элемент scatterlist. Но для вызовов полагающихся на обработчик sendpage (например, sendfile()), это будет диапазон (0, 0), так как данные совместно используются с пространством пользователя и по умолчанию стремятся избегать разрешать пользовательскому пространству изменять данные во время (или после) принятия решения eBPF. Этот помощник можно использовать для вытягивания данных и настройки указателей начала и конца на заданные значения. Данные будут скопированы при необходимости (т. е., если данные нелинейные и если указатели начала и конца не указывают на ту же часть).

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

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_bind(struct bpf_sock_addr *ctx, struct sockaddr *addr, int addr_len)
Описание
Привязывает сокет, связанный с ctx, с адресом, на который указывает addr, с длиной addr_len. Это позволяет создавать исходящее соединение с желаемого IP-адреса, что может быть полезно, например, когда все процессы внутри cgroup должны использовать единый IP-адрес на узле с несколькими настроенными IP.

Этот помощник работает с IPv4 и IPv6, сокетами TCP и UDP. Домен (addr->sa_family) должен быть AF_INET (или AF_INET6). Поиск свободного порта для привязки может быть затратным, поэтому помощник не разрешает привязку к порту: addr->sin_port (или sin6_port, соответственно) должны быть равны нулю.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_xdp_adjust_tail(struct xdp_buff *xdp_md, int delta)
Описание
Изменяет (перемещает) xdp_md->data_end на delta байт. Возможно только уменьшить пакет при записи, поэтому значение delta должно быть отрицательным integer.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_skb_get_xfrm_state(struct sk_buff *skb, u32 index, struct bpf_xfrm_state *xfrm_state, u32 size, u64 flags)
Описание
Получает состояние XFRM (инфраструктура преобразования IP, смотрите ip-xfrm(8)) по index «пути безопасности» XFRM для skb.

Полученное состояние сохраняется в struct bpf_xfrm_state, на который указывает xfrm_state, и с длиной size.

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_XFRM.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_get_stack(struct pt_regs *regs, void *buf, u32 size, u64 flags)
Описание
Возвращает пользовательский и ядерный стек в буфер, предоставляемый программой bpf. Для этого помощнику требуется ctx — указатель на контекст выполнения трассирующей программы. Для сохранения stacktrace программа bpf предоставляет buf с неотрицательным size.

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

BPF_F_USER_STACK
Проходить по стеку пользовательского пространства, а не по стеку ядра.
BPF_F_USER_BUILD_ID
Собирать buildid+смещение вместо ips пользовательского стека, доступен только, если также указан BPF_F_USER_STACK.

Помощник bpf_get_stack() может собирать до PERF_MAX_STACK_DEPTH ядерных и пользовательских кадров, что требует значительно большего размера буфера. Заметим, что это ограничение можно изменять программой sysctl, и что его нужно вручную увеличивать, если нужно отсматривать длинные пользовательские стеки (например, стеки программ Java). Для этого выполните:

# sysctl kernel.perf_event_max_stack=<новое значение>


Возвращает
При успешном выполнении — неотрицательное значение, меньшее или равное size; при ошибке — отрицательный код.

int bpf_skb_load_bytes_relative(const struct sk_buff *skb, u32 offset, void *to, u32 len, u32 start_header)
Описание
Этот помощник похож на bpf_skb_load_bytes() тем, что предоставляет простой способ загрузки len байт из смещения offset в пакете, связанном с skb, в буфер, на который указывает to. Отличие от bpf_skb_load_bytes() в том, что имеется пятый аргумент start_header, позволяющий выбрать базовое начальное смещение. Значением start_header может быть одно из:
BPF_HDR_START_MAC
Базовое смещение для загрузки данных из заголовка mac skb.
BPF_HDR_START_NET
Базовое смещение для загрузки данных из заголовка сети skb.

В общем случае, «прямой доступ к пакету» является предпочтительным методом доступа к данным пакета, однако, этот помощник иногда полезен в сокетных фильтрах, где skb->data не всегда указывает на начало заголовка mac и «прямой доступ к пакету» недоступен.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_fib_lookup(void *ctx, struct bpf_fib_lookup *params, int plen, u32 flags)
Описание
Выполняет поиск FIB в таблицах ядра по параметрам из params. Если что-то найдено и результат отражает пакет, который будет пересылаться, то в соседних таблицах ищется следующий переход (nexthop). Если он найден (т. е., находка FIB пересылается и определён следующий переход), то в ipv4_dst или ipv6_dst возвращается адрес следующего перехода для семейств, в smac — адрес mac исходящего устройства, в dmac — адрес mac следующего перехода, в rt_metric — метрика из маршрута (только IPv4/IPv6) и в ifindex — индекс устройства следующего перехода из поиска FIB.

В аргументе plen указывается размер передаваемой структуры. В аргументе flags может быть комбинация одного и более следующих значений:

BPF_FIB_LOOKUP_DIRECT
Выполнять прямой табличный поиск, а не полный поиск с помощью правил FIB.
BPF_FIB_LOOKUP_OUTPUT
Выполнять поиск с исходящей стороны (по умолчанию входящей).

Для программ XDP тип ctx равен struct xdp_md, а для программ tc cls_act — struct sk_buff.

Возвращает
  • < 0, если какой-то из входных параметров некорректен
  • При успешном выполнении возвращает 0 (пакет переслан, следующий переход существует)
  • Если > 0, то это один из кодов BPF_FIB_LKUP_RET_, объясняющий почему пакет не переслан или требуется помощь из полного стека


int bpf_sock_hash_update(struct bpf_sock_ops_kern *skops, struct bpf_map *map, void *key, u64 flags)
Описание
Добавляет или обновляет элемент, ссылающийся на сокет, в sockhash map. В качестве нового значение элемента, связанного с key, используется skops. Значением flags может быть одно из:
BPF_NOEXIST
Запись для key не должна существовать в карте.
BPF_EXIST
Запись для key должна существовать в карте.
BPF_ANY
Не учитывать условие существования записи для key.

Если map содержит программы eBPF (анализатор и решение), то они будут наследоваться сокетом, который добавляется. Если сокет уже присоединён к программам eBPF, то возвращается ошибка.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_msg_redirect_hash(struct sk_msg_buff *msg, struct bpf_map *map, void *key, u64 flags)
Описание
Этот помощник используется в программах, которые описывают политики на уровне сокета. Если сообщению msg разрешено проходить дальше (т. е., если решающая программа eBPF вернула SK_PASS), то оно перенаправляется в сокет, на который указывает хэш key в map (с типом BPF_MAP_TYPE_SOCKHASH). Для перенаправления можно использовать как входящий так и исходящий интерфейсы. В качестве отличительного признака в flags используется значение BPF_F_INGRESS (выбирается входящий путь, если флаг указан, в противном случае — исходящий). В настоящее время поддерживается только этот флаг.
Возвращает
При успешном выполнении — SK_PASS, SK_DROP — при ошибке.

int bpf_sk_redirect_hash(struct sk_buff *skb, struct bpf_map *map, void *key, u64 flags)
Описание
Этот помощник используется в программах, которые описывают политики на уровне сокета skb. Если sk_buff skb разрешено проходить дальше (т. е., если решающая программа eBPF вернула SK_PASS), то оно перенаправляется в сокет, на который указывает хэш key в map (с типом BPF_MAP_TYPE_SOCKHASH). Для перенаправления можно использовать как входящий так и исходящий интерфейсы. В качестве отличительного признака в flags используется значение BPF_F_INGRESS (выбирается входящий путь, если флаг указан, в противном случае — исходящий). В настоящее время поддерживается только этот флаг.
Возвращает
При успешном выполнении — SK_PASS, SK_DROP — при ошибке.

int bpf_lwt_push_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len)
Описание
Формирует пакет, связанный с skb, с заголовком протокола уровня 3. Этот заголовок помещается в буфер по адресу hdr размером len байт. Значение type задаёт протокол заголовка и может быть одним из:
BPF_LWT_ENCAP_SEG6
Инкапсуляция IPv6 с заголовком посегментной маршрутизации (Segment Routing Header, struct ipv6_sr_hdr). В hdr содержится только SRH, заголовок IPv6 вычисляется ядром.
BPF_LWT_ENCAP_SEG6_INLINE
Работает только, если в skb содержится пакет IPv6. Вставляет заголовок посегментной маршрутизации (Segment Routing Header, struct ipv6_sr_hdr) в заголовок IPv6.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_lwt_seg6_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len)
Описание
Сохраняет len байт, начиная с адреса from в пакет, связанный с skb, по смещению offset. С помощью этого помощника можно изменять только флаги, тег и TLV в самом внешнем заголовке IPv6 посегментной маршрутизации (Segment Routing Header).

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_lwt_seg6_adjust_srh(struct sk_buff *skb, u32 offset, s32 delta)
Описание
Изменяет размер пространства, выделенного для TLV в самом внешнем заголовке IPv6 посегментной маршрутизации из пакета, связанного с skb в расположении offset, на delta байт. Допускаются только расположения после сегментов. Значение delta может быть как положительным (для увеличения), так и отрицательным (для уменьшения).

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_lwt_seg6_action(struct sk_buff *skb, u32 action, void *param, u32 param_len)
Описание
Применяет действие с типом action посегментной маршрутизации IPv6 в пакету, связанному с skb. Каждое действие учитывает параметр, содержащейся по адресу param и длиной param_len байт. Значение action может быть одним из:
SEG6_LOCAL_ACTION_END_X
Действие End.X: конечная точка (endpoint) с кроссированием на 3 уровне. Тип param: struct in6_addr.
SEG6_LOCAL_ACTION_END_T
Действие End.T: конечная точка с заданной таблицей поиска IPv6. Тип param: int.
SEG6_LOCAL_ACTION_END_B6
Действие End.B6: конечная точка привязана к политике SRv6. Тип параметра: struct ipv6_sr_hdr.
SEG6_LOCAL_ACTION_END_B6_ENCAP
Действие End.B6.Encap: конечная точка привязана к политике инкапсуляции SRv6. Тип параметра: struct ipv6_sr_hdr.

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

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle)
Описание
Этот помощник используется в программах, реализующих декодирование IR, для сообщения об успешном декодировании значения нажатой клавиши scancode, toggle в заданном protocol. Скан-код будет преобразован в код клавиши с помощью карты клавиш rc, и записывается в виде входного события о нажатой клавише. После паузы генерируется событие об отпускании клавиши. Этот период может быть продлён повторным вызовом bpf_rc_keydown() с теми же значениями или вызовом bpf_rc_repeat().

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

Значение ctx должно указывать на выборку lirc, переданную программе.

Значение protocol это номер декодируемого протокола (предопределённые значение смотрите в enum rc_proto).

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_BPF_LIRC_MODE2 равным "y".

Возвращает

int bpf_rc_repeat(void *ctx)
Описание
Этот помощник используется в программах, реализующих декодирование IR, для сообщения об успешном декодировании сообщения о повторно нажатой клавише. Он задерживает генерацию события об отпускании клавиши для сгенериванного ранее события нажатия клавиши.

В некоторых протоколах IR, например NEC, есть специальное сообщение IR для повтора последней клавиши, чтобы показать, что клавиша остаётся нажатой.

Значение ctx должно указывать на выборку lirc, переданную программе.

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_BPF_LIRC_MODE2 равным "y".

Возвращает

uint64_t bpf_skb_cgroup_id(struct sk_buff *skb)
Описание
Возвращает идентификатор cgroup v2 сокета, связанного с skb. Он, приблизительно, похож на помощник bpf_get_cgroup_classid() для cgroup v1, предоставляющий тег resp., который можно сравнивать или использовать для поиска в картах, например при реализации политики. Идентификатор cgroup v2 заданного пути в иерархии отражается в пользовательском пространстве через программный интерфейс f_handle, используемого для получения этого же 64-битного идентификатора.

Этот помощник можно использовать на выходящем пути TC, но не на входящем, и он доступен только, если ядро было скомпилировано с параметром настройки CONFIG_SOCK_CGROUP_DATA.

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

u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level)
Описание
Возвращает идентификатор cgroup v2, которая является предком cgroup, связанной с skb на уровне ancestor_level. Корневая cgroup расположена на уровне ancestor_level равным нулю и каждый шаг вниз по иерархии увеличивает значение уровня. Если ancestor_level == уровню cgroup, связанной с skb, то возвращаемое значение будет равно возвращаемому bpf_skb_cgroup_id().

Помощник полезен при реализации политик на основе cgroup, которые стоят в иерархии выше, чем непосредственная cgroup, связанная с skb.

Формат возвращаемого идентификатора и ограничения помощника такие же как у bpf_skb_cgroup_id().

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

u64 bpf_get_current_cgroup_id(void)
Возвращает
64-битное целое, содержащее идентификатор текущей cgroup, на основе cgroup, в которой выполняется текущая задача.

void* get_local_storage(void *map, u64 flags)
Описание
Возвращает указатель на область локального хранилища. Тип и размер локального хранилища задаётся аргументом map. Значение flags зависит от типа карты, и должно быть равно 0 для локального хранилища cgroup.

В зависимости от типа программы BPF область локального хранилища может совместно использоваться несколькими работающими одновременно экземплярами программы BPF.

Пользователь самостоятельно должен решать вопросы синхронизации. Например, для изменения общих данных использовать инструкцию BPF_STX_XADD.

Возвращает
Указатель на область локального хранилища.

int bpf_sk_select_reuseport(struct sk_reuseport_md *reuse, struct bpf_map *map, void *key, u64 flags)
Описание
Выбирает сокет SO_REUSEPORT из BPF_MAP_TYPE_REUSEPORT_ARRAY map. Проверяется, что выбранный сокет совпадает с входящим запросом в буфере сокета.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
Описание
Ищет сокет TCP, который совпадает с tuple, возможно, в дочернем сетевом пространстве имён netns. Возвращаемое значение нужно проверять и если оно не равно NULL, то освобождать с помощью bpf_sk_release().

Значение ctx должно указывать на контекст программы, например, на skb или сокета (в зависимости от используемого перехватчика (hook)). Оно используется для определения основного сетевого пространства имён, в котором нужно искать.

Значение tuple_size должно быть одним из:

sizeof(tuple->ipv4)
Искать сокет IPv4.
sizeof(tuple->ipv6)
Искать сокет IPv6.

Если netns — отрицательное знаковое 32-битное целое, то поиск будет производиться в таблице netns, связанной с ctx. Для перехватчиков TC, это будет netns устройства в skb. Для перехватчиков сокетов это будет netns сокета. Если netns — любое другое знаковое 32-битное значение, большее или равное нулю, то им задаётся идентификатор netns, относительно netns, связанного с ctx. Значения netns вне диапазона 32-битных целых зарезервированы для использования в будущем.

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_NET.

Возвращает
Указатель на struct bpf_sock, или NULL при ошибке. Для сокетов с параметром reuseport возвращается struct bpf_sock из reuse->socks[] используя хэш кортежа (tuple).

struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
Описание
Ищет сокет UDP, который совпадает с tuple, возможно, в дочернем сетевом пространстве имён netns. Возвращаемое значение нужно проверять и если оно не равно NULL, то освобождать с помощью bpf_sk_release().

Значение ctx должно указывать на контекст программы, например, на skb или сокета (в зависимости от используемого перехватчика (hook)). Оно используется для определения основного сетевого пространства имён, в котором нужно искать.

Значение tuple_size должно быть одним из:

sizeof(tuple->ipv4)
Искать сокет IPv4.
sizeof(tuple->ipv6)
Искать сокет IPv6.

Если netns — отрицательное знаковое 32-битное целое, то поиск будет производиться в таблице netns, связанной с ctx. Для перехватчиков TC, это будет netns устройства в skb. Для перехватчиков сокетов это будет netns сокета. Если netns — любое другое знаковое 32-битное значение, большее или равное нулю, то им задаётся идентификатор netns, относительно netns, связанного с ctx. Значения netns вне диапазона 32-битных целых зарезервированы для использования в будущем.

Все значения flags зарезервированы для использования в будущем и должны быть равны нулю.

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_NET.

Возвращает
Указатель на struct bpf_sock, или NULL при ошибке. Для сокетов с параметром reuseport возвращается struct bpf_sock из reuse->socks[] используя хэш кортежа (tuple).

int bpf_sk_release(struct bpf_sock *sock)
Описание
Освобождает ссылку, удерживаемую sock. Значение sock должно быть не-NULL указателем, который был получен из bpf_sk_lookup_xxx().
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_map_pop_elem(struct bpf_map *map, void *value)
Описание
Выталкивает элемент из map.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_map_peek_elem(struct bpf_map *map, void *value)
Описание
Возвращает элемент из map не удаляя.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags)
Описание
Для сокетных политик, вставляет len байт в msg по смещению start.

Если программа типа BPF_PROG_TYPE_SK_MSG выполняется для msg, то в msg можно вставлять метаданные или параметры. Позднее они могут быть прочитаны и использованы перехватчиком BPF на нижних уровнях.

Этот помощник может завершиться ошибкой при нехватке памяти (ошибка malloc); при этом программы BPF получат соответствующую ошибку и им её нужно обработать.

Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags)
Описание
Удаляет pop байт из msg, начиная с байта по адресу start. В некоторых случаях может приводить к ошибкам ENOMEM, если из-за заполненности кольцевого буфера требуется выделение и копирование. Однако, помощник, по возможности, будет пытаться избегать выделения. Также могут возникать ошибки из-за некорректных входных параметров: адрес start не относится к нагрузке msg и/или слишком большое значение pop.
Возвращает
При успешном выполнении 0 и отрицательное значение при ошибке.

int bpf_rc_pointer_rel(void *ctx, s32 rel_x, s32 rel_y)
Описание
Этот помощник используется в программах, реализующих декодирование IR, для сообщения об успешном декодировании перемещения указателя.

Значение ctx должно указывать на выборку lirc, переданную программе.

Этот помощник доступен только, если ядро скомпилировано с параметром настройки CONFIG_BPF_LIRC_MODE2 равным "y".

Возвращает


ПРИМЕРЫ

В этой справочной странице перечислены примеры использования большинства помощников eBPF, которые доступны в исходном коде ядра Linux:

  • samples/bpf/
  • tools/testing/selftests/bpf/

ЛИЦЕНЗИЯ

Программы eBPF могут иметь собственную лицензию, передаваемую вместе с инструкциями байткода в ядро при загрузке программы. Формат этой строки совпадает с используемым в модулях ядра (могут использоваться двойные лицензии, например «Dual BSD/GPL»). Некоторые вспомогательные функции доступны только программам, которые совместимы с GNU Privacy License (GPL).

Для использования таких помощников, программа eBPF должна загружаться с строкой правильной лицензии, передаваемой (через attr) системный вызов bpf(); обычно, она транслируется из кода на C программы, содержащей подобную строку:

char ____license[] __attribute__((section("license"), used)) = "GPL";


РЕАЛИЗАЦИЯ

Эта справочная страница предназначена для описания существующих вспомогательных функций eBPF. В данный момент подсистема BPF часто меняется. Добавляются новые программы eBPF и типы карт, а также новые вспомогательные функции. Некоторые помощники иногда делают доступными дополнительные типы программ. Таким образом, несмотря на усилия сообщества, эта страница может уже устареть. Если вы хотите самостоятельно проверить, существует ли помощник в ядре, или какие типы программ они поддерживают, вот некоторые файлы дерева ядра, которые могут быть интересны:

  • include/uapi/linux/bpf.h — основной заголовочный файл BPF. Он содержит полный список всех вспомогательных функций, а также много других определений BPF, включая большинство флагов, структур или констант, используемых помощниками.
  • В net/core/filter.c содержатся определения большинства вспомогательных функций, относящихся к сети, и список типов программ, в которых их можно использовать.
  • В kernel/trace/bpf_trace.c содержится большинство помощников, относящихся к трассирующим программам.
  • В kernel/bpf/verifier.c содержатся функции, используемые для проверки корректности типов карт eBPF для заданной вспомогательной функции.
  • В каталоге kernel/bpf/ содержатся другие файлы, в которых определены дополнительные помощники (для cgroups, sockmaps и т. п.).

Совместимость помощника и типа программы, обычно, можно определить из файлов определения помощников. Ищите объекты struct bpf_func_proto и возвращающие их функции: эти функции содержат списки помощников, которые может вызывать определённый тип программы. Заметим, что метка default: в switch ... case используется для фильтрации помощников, которые могут вызывать другие функции, тем самым сами обращающиеся к дополнительным помощникам. Требование лицензии GPL также описаны в этих struct bpf_func_proto.

Совместимость между вспомогательными функциями и типами карт можно найти в функции check_map_func_compatibility() в файле kernel/bpf/verifier.c.

Вспомогательные функции, не проверяющие указатели data и data_end при сетевой обработке, перечислены в функции bpf_helper_changes_pkt_data() в файле net/core/filter.c.

СМОТРИТЕ ТАКЖЕ

bpf(2), cgroups(7), ip(8), perf_event_open(2), sendmsg(2), socket(7), tc-bpf(8)

2019-03-06 Linux