#networking #routes #linux-kernel
Вопрос:
Если я правильно понял, то в предыдущих версиях ядра Linux (например, в версии 2) есть два различных указателей функций В dst_entry
(а именно: input
а output
) для того, чтобы обеспечить следующий сценарий (возможно, были некоторые другие сценарии, которые требуют этого): во время «выхода» из IP-пакета, определяется как предназначенные для текущего хоста, output
имеет значение ip_output
и input
имеет значение ip_local_deliver
. Причина input
, установленная в этом сценарии, заключается в том, что мы знаем, что пакет будет «доставлен нам обратно», и на пути «входа» у нас теперь будет rtable
запись уже кэширована, и мы можем напрямую вызвать указатель input
функции. Правильно ли я это понял?
Однако, из того, что я мог видеть, в текущей версии ядра Linux (5) существуют разные записи кэша для пути «выход» и «вход» (т. Е. Запись кэша, установленная во время пути «выход», будет получена только во время будущего пути «выход», и то же самое для пути «вход»). Эти записи nhc_pcpu_rth_output
(для «выхода») и nhc_rth_input
(для «входа») находятся внутри fib_nh_common
.
Скорее всего, есть сценарий, которого мне не хватает, который включает в себя настройку output
функции во время «входа», а затем ее использование в будущем во время пути «выхода» или наоборот.
Я был бы очень признателен, если бы кто-нибудь мог указать причину наличия двух разных указателей функций внутри dst_entry
( input
и output
) в текущей версии ядра Linux.
Спасибо.
Комментарии:
1. @JustinIurman Благодарю вас за ваш ответ. Я прочитал код больше и подумал о двух сценариях, в которых требуется установить оба
input
иoutput
на одном и том жеdst_entry
. Первый сценарий, перенаправление пакетов : IP-пакет поступает на интерфейс; маршрутизация определяет, что он не предназначен для этого хоста, поэтому его необходимо перенаправить;input
устанавливаетсяip_forward
иoutput
устанавливаетсяip_output
(ip_forward
в конечном итоге вызоветoutput
). Второй сценарий, отправка пакета на текущий хост :output
установленip_output
иinput
установленip_local_deliver
. [продолжение]2. Когда пакет «возвращается» из интерфейса обратной связи, в нем уже
dst
заполнена структура (проверка выполняется внутри ip_input.c , внутриip_rcv_finish_core
:if (!skb_valid_dst(skb)) ...
, поэтомуinput
функцию можно вызвать без необходимости повторять весь процесс маршрутизации. Правильно ли я теперь это понимаю?3. Ваш первый сценарий верен, а не ваш второй. Действительно, между ними нет никакой разницы. На самом деле, когда пакет предназначен для локального хоста,
input
будет установлено значениеip6_input
(я возьму IPv6 в качестве примера, потому что я более знаком с ним, но он должен быть очень похож на IPv4) иoutput
не будет использоваться, так как в этом случае он бесполезен. В качестве резюме, когда пакет будет отправлен хосту,input
будетip6_input
(который затем вызоветip6_protocol_deliver_rcu
). Если пакет не для хоста,input
будетip6_forward
иoutput
будетip6_output
.4. @JustinIurman Еще раз спасибо вам за ваш ответ! Извините, мне следовало быть более конкретным. Для моего второго сценария, отправки пакета на текущий хост , я имел в виду ситуацию, в которой один хост отправляет пакет самому себе (например, он отправляет пакет на 127.0.0.1, в случае, если это адрес интерфейса обратной связи). Учитывая это уточнение, является ли поток, который я описал, правильным?
5. Хммм, я понимаю. Ну, вероятно, это происходит не так, как вы описали, хотя я не уверен, где в коде это обрабатывается. Дело в том, что пакет не будет покидать и повторно входить в ваш узел, поскольку адрес назначения является обратной связью, он будет доставлен напрямую (опять же, есть что-то на
output
стороне, чтобы решить эту проблему, ноinput
здесь это не играет роли). На самом деле,input
никогда не вступает в игру, когда речь идет о пакетах, отправленных с вашего узла. Самое близкое к вашим рассуждениям, о чем я мог подумать, это то, что пакет будет повторно введен в сетевой стек, а затемinput
будет установлен.