| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Программирование под Unix/Linux > [kernel] передача сетевому от канального уровня |
| Автор: null56 28.1.2011, 17:15 | ||||||||
| Всем привет, не ясен процесс подготовки сокетного буфера (sk_buff), при передаче вышележащим протоколам Собсвенно шаги: - регистрирую обработчик кадров канального уровня со своей сигнатурой
- получив кадр в колбаке, удаляю из заголовка кадра, все что мне нужно, оставляя лишь стандартные данные структуры
- отправляю вышележащим протоколам
Вопрос: я нахожусь на канальном уровне, должен ли я отделять данные канального уровня? или же я должен передавать вышележащему уровню полный кадр, а он сам отделит сетевой уровенЬ?
заранее благодарен за помощь |
| Автор: null56 28.1.2011, 17:56 | ||||||
другими словами, что нужно сделать перед отправкой
удалить полностью заголовок кадра ethernet
и выставить смещение протокола ip
или же достаточно только выставить смещение, в этом случае смещения протоколов канального и сетевого у нас будут совпадать |
| Автор: MAKCim 29.1.2011, 16:13 |
| есть NAPI и legacy драйвера сетевых устройств legacy в контексте _аппаратного_ прерывания вызывают netif_rx затем backlog-устройство для данного cpu добаляется в poll-список, пакет - в входную очередь и генерируется NET_RX_SOFTIRQ затем в контексте NET_RX_SOFTIRQ обработчик process_backlog берет пакеты и дергает netif_receive_skb там, ВНИМАНИЕ, вызывается skb_reset_network_header и далее уже вызываются обработчики packet-сокетов т. е. в netif_rx _уже_ передается пакет с увеличенным data (на 14+ для ethernet или в зависимости от канального уровня) в NAPI аналогично за исключением того, что netif_receive_skb дергается драйвером в process_xxxx обрати внимание на http://lxr.free-electrons.com/source/net/core/dev.c#L2890 packet-сокеты обрабатываются _в контексте_ netif_rx (явном или неявном) поэтому нельзя из них вызывать netif_rx |
| Автор: null56 29.1.2011, 23:46 |
| хотя не, ты наверное имел в виду deliver_skb, оттуда вызываются колбаки http://lxr.free-electrons.com/source/net/core/dev.c#L2715 но вопрос все равно остается, как же передать вышележащим уровням? |
| Автор: null56 30.1.2011, 01:07 | ||||||||||
| MAKCim, я запутался.... да, netif_rx дергается из хардваре, да он добавляет в очередь poll и перепланирует NET_RX_SOFT. далее в netif_receive_skb рано или поздно дергается __netif_receive_skb, из него вызываются зарегистрированные колбаки и все? мне более не надо ничего делать, кроме как поправить протокол?
вышележащим уровням все будет передаваться в теле __netif_receive_skb? так как у вышележащих протоколов есть свои системные колбаки http://lxr.free-electrons.com/source/net/core/dev.c#L3001 поправлю вышесказанное мной...
так ли это? ведь в __netif_receive_skb происходит
получается, что data не изменяется, она как указывала, так и указывает на начало моего канального кадра? то есть после этих манипуляций я не могу использовать функцию
так как
мы получим смещение на мак, а там совсем другие данные? другими словами, я не вижу, где data смещается на заголовок сетевого уровня спасибо |
| Автор: MAKCim 30.1.2011, 11:34 | ||
угу твой зарегистрированный packet-обработчик вызывается тут http://lxr.free-electrons.com/source/net/core/dev.c#L2953 а дальше в этой же функции тут http://lxr.free-electrons.com/source/net/core/dev.c#L3002 обработчики для протокола в частности для ipv4 тут http://lxr.free-electrons.com/ident?i=dev_add_pack идет регистрация обработчика для ipv4 так тут http://lxr.free-electrons.com/source/include/linux/skbuff.h#L1271 network header вычисляется как data - head head указывает на начало линейного буфера (=заголовок канального уровня) значит data при reset'е указывает на network header, смещение которого мы и устанавливаем (т. к. dev-уровень не знает и не должен ничего знать о том, через что пакет физически попал в ядро)
вот ip_rcv http://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L375 обработчик packet-сокета для ipv4 там ip_hdr юзается вполне нормально |
| Автор: MAKCim 30.1.2011, 11:50 | ||
вот драйвер реалтековский r8169.c функция rtl8169_rx_interrupt (обработчик прерывания сетевой карты) http://lxr.free-electrons.com/source/drivers/net/r8169.c?v=2.6.25#L2831 skb_put(skb, pkt_size) формирует линейный буфер сокета eth_type_trans тут http://lxr.free-electrons.com/source/net/ethernet/eth.c#L158 в skb_reset_mac_header мы вычисляем mac header как data - head (data и head тут одинаковы) дальше skb_pull_inline на ETH_HLEN т. е. это и есть увеличение data иными словами, задача _каждого_ драйвера - увеличение data на нужный ему известный размер |
| Автор: null56 30.1.2011, 15:35 | ||||
| получается, что после обработчика прерывания сетевой мы уже имеем в обработчике packet_type: data == network mac = data - (my_mac_size + ETH_SIZE) смещаюсь на мой мак, правлю, убирая мой апендикс и изменяю protocol, далее уже будет вызов в обработчике ip уровня
не факт, я про заголовок канального уровня... head указывает на начало зарезервированного headroom участка, который может быть куда больше заголовка канального уровня, на картинке это хорошо заметно, посмотри функцию push http://www.skbuff.net/skbbasic.html именно поэтому http://lxr.free-electrons.com/source/net/core/dev.c#L2936
в общем спасибо, что помог разобраться с последовательностью вызовов и изменением полей sk_buff, остальное увижу в отладчике или отладочной печати |
| Автор: ROKR 31.1.2011, 14:40 | ||
| Если я правильно понимаю, о чем речь, то: When setting up receive packets that an ethernet device will DMA into, we typically call skb_reserve(skb, NET_IP_ALIGN). By default NET_IP_ALIGN is defined to '2'. This makes it so that, after the ethernet header, the protocol header will be aligned on at least a 4-byte boundary. Nearly all of the IPV4 and IPV6 protocol processing assumes that the headers are properly aligned. Взято http://vger.kernel.org/~davem/skb_data.html Вот пример того, что я делал:
В data уже лежал целиковый ethernet-пакет. Ну и указывать протокол: new_skb->protocol = eth_type_trans( new_skb, btmbnep_netdev ); тоже обязательно. |
| Автор: null56 11.2.2011, 20:27 | ||||||
| Продолжу тему, ибо столкнулся с проблемой.... 1) при отправке пакета, изменяю идентификатор протокола на свой
2) на другой машине ставлю фильтр для этого типа пакетов
3) пакеты как и полагается попадают в колбак, где я пытаюсь изменить протокол и отправить вышележащим
и пакет уходит в неизвестном направлении для примера я использую устройства броадкасты. если посылать пакеты не изменяя h_proto в кадре ethernet и ставя фильтр соответственно на ETH_P_IP, то пакеты также попадают в мой колбак и достигают цели что не так? почему не достаточно просто поправить протокол? что еще нужно сделать? буду благодарен за помощь |
| Автор: null56 11.2.2011, 21:50 |
| смотрю примеры и замечаю, что после определения протокола вызывают netif_rx http://www.google.com/codesearch/p?hl=ru#MBz9zgJ22pw/tools/usbtest/usbnet.c&q=eth_type_trans&sa=N&cd=16&ct=rc поэтому вопрос пока не решен |
| Автор: null56 13.2.2011, 04:57 | ||
пока не ясно, что еще нужно сделать с skb, чтобы сетевая подсистема отправила сама этот буфер вверх по протоколам... но можно попробовать это
но по идее не нужны такие костыли, ведь абсолютно идентичные пакеты, но с обычной ip сигнатурой отправляются, а мои нет... буду мучить, результаты экспериментов не ранее понедельника |
| Автор: null56 17.2.2011, 00:20 | ||||||||
это правильный ответ... а теперь подробнее начать наверное лучше всего с регистрации своего обработчика, фукнция dev_add_pack, посмотрим ее исходный код
ключевой является функция ptype_head в строчке номер 400, вот она ниже
и так мы видим, что если мы регистрируем обработчик для любых езернет кадров (например мы делаем снифер) ETH_P_ALL, то получаем список ptype_all, иначе, как в моем случае, мы получаем список ptype_base. это ключевой момент, теперь можно вернуться к функции __netif_receive_skb первый раз идет вызов обработчиков для ETH_P_ALL http://lxr.free-electrons.com/source/net/core/dev.c#L2949
обращаем внимание, что используется список ptype_all, а второй раз мы как раз идем по списку с нашим обработчиком ptype_base http://lxr.free-electrons.com/source/net/core/dev.c#L3001
тут как раз идем по ptype_base И БОЛЬШЕ НИКТО НИЧЕГО В ЭТОЙ ФУНКЦИИ ВЫЗЫВАТЬ НЕ БУДЕТ. В итоге, как я понял, в нашем обработчике мы должны изменить протокол и вызвать netif_receive_skb, чтобы у меня вызвался обработчик ip кадров и пакет передался выше по стеку протоколов.... так что так |