Источники задержки при отправке-получении пакетов tcp / udp в linux

Каковы источники задержки в процессе отправки / получения пакетов TCP / UDP в Linux 2.6?

Я хочу знать источники задержки в тестах задержки "пинг-понг".

Есть несколько довольно хороших документов о задержке Ethernet, но они охватывают только источники задержки в проводе и коммутаторе (и довольно поверхностно, только для конкретного коммутатора).

Какие шаги обработки следует за пакетом?

Также будут полезны статьи с глубоким анализом латентности обычного пинга (icmp).

Полагаюсь на сообщество :)


person osgx    schedule 21.04.2010    source источник


Ответы (2)


Несмотря на то, что оно довольно старое, в этом руководстве подробно описывается сетевой стек Linux.

http://www.cs.unh.edu/cnrg/people/gherrin/linux-net.html

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

например если кадр временно буферизуется в ядре

person David Mokon Bond    schedule 15.11.2010

Краткий ответ: для точной задержки в ядре следует использовать perf probe и perf script.

Подробнее. Давайте посмотрим на следующий пример. Сначала мы хотим посмотреть, какие функции используются для теста TCP ping-pong (я использую netperf).

В потоке приема:  введите описание изображения здесь

В потоке передачи:  введите описание изображения здесь

Итак, давайте проследим некоторые функции потока передачи (он длинный, поэтому я покажу основные функции в потоке TCP). Мы можем использовать зонд perf для выборки точки входа и выхода для каждой функции:

perf probe --add sock_sendmsg='sock_sendmsg'
perf probe --add sock_sendmsg_exit='sock_sendmsg%return'
perf probe --add inet_sendmsg='inet_sendmsg'
perf probe --add inet_sendmsg_exit='inet_sendmsg%return'
perf probe --add tcp_sendmsg_exit='tcp_sendmsg%return'
perf probe --add tcp_sendmsg='tcp_sendmsg'
perf probe --add tcp_sendmsg_locked='tcp_sendmsg_locked'
perf probe --add tcp_sendmsg_locked_exit='tcp_sendmsg_locked%return'
perf probe --add sk_stream_alloc_skb='sk_stream_alloc_skb'
perf probe --add sk_stream_alloc_skb_exit='sk_stream_alloc_skb%return'
perf probe --add tcp_push_exit='tcp_push%return'
perf probe --add tcp_push='tcp_push'
perf probe --add tcp_send_mss='tcp_send_mss'
perf probe --add tcp_send_mss_exit='tcp_send_mss%return'
perf probe --add __tcp_push_pending_frames='__tcp_push_pending_frames'
perf probe --add __tcp_push_pending_frames_exit='__tcp_push_pending_frames%return'
perf probe --add tcp_write_xmit_exit='tcp_write_xmit%return'
perf probe --add tcp_transmit_skb_exit='tcp_transmit_skb%return'
perf probe --add tcp_transmit_skb='tcp_transmit_skb'

Нет, мы можем записать это:

perf record -e probe:* -aR taskset -c 7 netperf -t TCP_RR -l 5 -T 7,7

И запустите сценарий perf для отчета о задержке:

perf script -F time,event --ns

Выход (1 итерация):

525987.403094082:                   probe:sock_sendmsg:
525987.403095586:                   probe:inet_sendmsg:
525987.403096192:                    probe:tcp_sendmsg:
525987.403098203:             probe:tcp_sendmsg_locked:
525987.403099296:                   probe:tcp_send_mss:
525987.403100002:              probe:tcp_send_mss_exit:
525987.403100740:            probe:sk_stream_alloc_skb:
525987.403101697:       probe:sk_stream_alloc_skb_exit:
525987.403103079:                       probe:tcp_push:
525987.403104284:      probe:__tcp_push_pending_frames:
525987.403105575:               probe:tcp_transmit_skb:
525987.403110178:               probe:tcp_transmit_skb:
525987.403111640:          probe:tcp_transmit_skb_exit:
525987.403112876:          probe:tcp_transmit_skb_exit:
525987.403114351:            probe:tcp_write_xmit_exit:
525987.403114768: probe:__tcp_push_pending_frames_exit:
525987.403115191:                  probe:tcp_push_exit:
525987.403115718:        probe:tcp_sendmsg_locked_exit:
525987.403117576:               probe:tcp_sendmsg_exit:
525987.403118082:              probe:inet_sendmsg_exit:
525987.403118568:              probe:sock_sendmsg_exit:

Теперь довольно легко увидеть, на что тратится задержка. Например, мы можем заметить, что между вызовами sock_sendmsg () и inet_sendmsg () существует задержка в 1504 наносекунды (нс) или 1,504 микросекунды (нас). Также мы видим, что sk_stream_alloc_skb занимает 957 нс. В целом весь процесс (от входа sock_sendmsg до выхода) занимает ~ 24,5 мкс. Имейте в виду, что это не то, что вы увидите в netperf, поскольку пакет физически передается где-то в середине потока.

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

Надеюсь это поможет.

P.S. Это было сделано на ядре 4.14, а не 2.6. Не знаю, насколько тогда была развита производительность, так что это могло не сработать.

person Tgilgul    schedule 25.11.2017
comment
Спасибо! Теперь можно использовать современные ядра. Как вы получили флеймографы? Классический флеймеграф, как я знаю, использует сумму, это не отрисовка функций по абсолютной шкале времени, а отрисовка процентов времени за несколько выполнений и используется с perf в режиме профилирования. Итак, вы нарисовали perf script вывод, похожий на флеймограф, с абсолютной временной шкалой? Как я увижу задержку доступа к оборудованию на графиках (драйвер должен создать дескриптор в очереди hw / dma и сигнализировать о новом дескрипторе сетевому контроллеру через ports / pio / mmio)? - person osgx; 25.11.2017