Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
17.11. Определение MAC адресов
hardorsoft
26.10.10 в 04:23
17.11. Разрешение MAC адресов
ximen
26.10.10 в 11:52
|
|
Возникает вопрос, как ассоциировать MAC-адрес (уникальный аппаратный идентификатор) и IP-адрес. Многие протоколы сталкиваются с подобной проблемой, но мы рассмотрим только протокол Ethernet. Мы попытаемся дать исчерпывающий ответ, и покажем три ситуации: ARP, Ethernet-заголовки без ARP (как plip), и не Ethernet-заголовки.
hardorsoft
26.10.10 в 04:23
|
|
17.11.1. Использование ARP с Ethernet
hardorsoft
26.10.10 в 04:23
|
|
Обычно для определения адресов используется ARP (Address Resolution Protocol – протокол определения адресов). К счастью, ARP управляется ядром, Ethernet-интерфейсу не нужно ничего делать для поддержки ARP. Если dev->addr и dev->addr_len корректно назначены при открытии, драйверу не требуется что-либо делать для преобразования IP в MAC-адрес. ether_setup назначает устройству методы dev->hard_header и dev->rebuild_header.
hardorsoft
26.10.10 в 04:24
|
|
Хотя ядро и определяет адрес (и кэширует результат), для построения пакета требуется помощь драйвера интерфейса. Ведь, драйверу известен заголовок физического уровня, а авторы сетевого кода надежно изолировали оставшуюся часть ядра от этой информации. В конце ядро вызывает метод драйвера hard_header, для посылки пакета с результатом ARP-запроса. Обычно разработчик Ethernet-драйвера не интересуется этим процессом, имеющийся код Ethernet решает эту проблему.
hardorsoft
26.10.10 в 04:24
|
|
17.11.2. Переопределение ARP
hardorsoft
26.10.10 в 04:24
|
|
Простой интерфейс точка-точка, такой как plip, может извлечь выгоду из использования Ethernet-заголовков: избежать накладных расходов при пересылки ARP пакетов туда-сюда. Простой интерфейс snull получает еще больший выигрыш для этого класса сетевых устройств. snull не может использовать ARP, потому как драйвер меняет IP адреса пакета при передаче, и ARP пакеты заменяют IP адреса. Хотя мы могли бы реализовать простой генератор ARP ответов, чтобы лучше показать непосредственную обработку заголовков физического уровня.
hardorsoft
26.10.10 в 04:24
|
|
Если ваше устройство использует обычные аппаратные заголовки без использования ARP, вы должны перекрыть метод по-умолчанию dev->hard_header. В snull-реализации, это короткая функция:
hardorsoft
26.10.10 в 04:24
|
|
int snull_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned int len) { struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); eth->h_proto = htons(type); memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len); memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len); eth->h_dest[ETH_ALEN-1] ^= 0x01; /* dest is us xor 1 */ return (dev->hard_header_len); }
hardorsoft
26.10.10 в 04:25
|
|
Функция просто берет информацию предоставляемую ядром, и преобразует в стандартный заголовок Ethernet. Также переключается один бит в ethernet-адресе получателя, позже мы скажем, зачем это делается.
hardorsoft
26.10.10 в 04:25
|
|
Когда пакет получен интерфейсом, аппаратный заголовок используется несколькими способами в eth_type_trans. Мы уже видели этот вызов в snull_rx:
hardorsoft
26.10.10 в 04:25
|
|
skb->protocol = eth_type_trans(skb, dev);
hardorsoft
26.10.10 в 04:25
skb->protocol = eth_type_trans(skb, dev);
hardorsoft
26.10.10 в 04:25
|
|
Функция извлекает идентификатор протокола (в данном случае ETH_P_IP) из Ethernet-заголовка. Также назначается skb->mac.raw, удаляются аппаратные заголовки из пакета (с помощью skb_pull), и устанавливатся skb->pkt_type. По умолчанию, при выделении skb, skb- >pkt_type устанавливается в значение PACKET_HOST (это показывает, что пакет предназначен локальному хосту). eth_type_trans меняет это значение в зависимости от Ethernet-адреса получателя: если адрес не совпадает с адресом принявшего интерфейса, поле pkt_type устанавливается в PACKET_OTHERHOST. Впоследствии, если интерфейс не находится в неразборчивом (promiscuous) режиме, или отправка пакета разрешена в ядре, netif_rx не принимает любой пакет типа PACKET_OTHERHOST. Поэтому snull_header назначает аппаратный адрес получателя, который принимается интерфейсом.
hardorsoft
26.10.10 в 04:25
Функция извлекает идентификатор протокола (в данном случае ETH_P_IP) из Ethernet-заголовка. Также назначается skb->mac.raw, удаляются аппаратные заголовки из пакета (с помощью skb_pull), и устанавливатся skb->pkt_type. По умолчанию, при выделении skb, skb- >pkt_type устанавливается в значение PACKET_HOST (это показывает, что пакет предназначен локальному хосту). eth_type_trans меняет это значение в зависимости от Ethernet-адреса получателя: если адрес не совпадает с адресом принявшего интерфейса, поле pkt_type устанавливается в PACKET_OTHERHOST. Впоследствии, если интерфейс не находится в неразборчивом (promiscuous) режиме, или отправка пакета разрешена в ядре, netif_rx не принимает любой пакет типа PACKET_OTHERHOST. Поэтому snull_header назначает аппаратный адрес получателя, который принимается интерфейсом.
hardorsoft
26.10.10 в 04:25
Функция извлекает идентификатор протокола (в данном случае ETH_P_IP) из Ethernet-заголовка. Также назначается skb->mac.raw, удаляются аппаратные заголовки из пакета (с помощью skb_pull), и устанавливатся skb->pkt_type. По умолчанию, при выделении skb, skb- >pkt_type устанавливается в значение PACKET_HOST (это показывает, что пакет предназначен локальному хосту). eth_type_trans меняет это значение в зависимости от Ethernet-адреса получателя: если адрес не совпадает с адресом принявшего интерфейса, поле pkt_type устанавливается в PACKET_OTHERHOST. Впоследствии, если интерфейс не находится в неразборчивом (promiscuous) режиме, или отправка пакета разрешена в ядре, netif_rx не принимает любой пакет типа PACKET_OTHERHOST. Поэтому snull_header назначает аппаратный адрес получателя, который принимается интерфейсом.
hardorsoft
26.10.10 в 04:25
|
|
Если ваш интерфейс – канал точка-точка, он не принимает групповые пакеты. Для устранения этой проблемы, вспомните, что если в адресе назначения младший бит первого октета равен нулю, то пакет предназначен одному хосту (то есть, является или PACKET_HOST или PACKET_OTHERHOST). plip драйвер использует значение 0xfc, в первом октете аппаратного адреса, когда как snull использует 0x00.
hardorsoft
26.10.10 в 04:25
|
|
Оба адреса работают в Ethernet-ориентированном канале точка-точка.
hardorsoft
26.10.10 в 04:26
|
|
17.11.3. Не Ethernet заголовки
hardorsoft
26.10.10 в 04:27
|
|
Мы увидели, что аппаратный заголовок, помимо адреса назначения пакета, содержит и другую информацию коммуникационного протокола. Теперь мы расскажем, как получить полезную информацию из аппаратных заголовков. Для получения более полной информации, можете ознакомиться с исходным кодом ядра, или технической документацией средств передачи. Большинство разработчиков могут игнорировать эту тему и использовать Ethernet-реализацию.
hardorsoft
26.10.10 в 04:27
|
|
Здесь не приведена вся информация о каждом протоколе. Соединение точка-точка, такое как plip или snull, не передает заголовок Ethernet. В метод устройства hard_header, показанный ранее в реализации snull_header, передается информация (протокольного уровня и аппаратные адреса) из ядра. Также предается 16-разрядный номер протокола в аргументе type. На пример, IP идентифицируется значением ETH_P_IP. Предполагается, что драйвер корректно передаст и пакет данных, и номер протокола на принимающий хост. Соединение точка- точка опускает адрес из аппаратного заголовка, предавая только номер протокола, потому что гарантируется независимость адресов отправителя и адресата. Только IP-соединения могут не передавать аппаратные заголовки.
hardorsoft
26.10.10 в 04:27
|
|
Когда пакет получен, функция приема в драйвере корректно установит поля skb->protocol, skb->pkt_type и skb->mac.raw.
hardorsoft
26.10.10 в 04:27
|
|
kb->mac.raw – символьный указатель, используемый для механизма определения адреса, реализованного на верхних уровнях сетевого кода (на пример net/ipv4/arp.c). Должен указывать на адрес, соответствующий dev->type. Возможные значения dev->type приведены в <linux></linux>if_arp.h>. Для интерфейсов Ethernet используется ARPHRD_ETHER. В качестве примера посмотрите, как eth_type_trans работает с Ethernet-заголовками для приема пакетов:
hardorsoft
26.10.10 в 04:28
|
|
skb->mac.raw = skb->data; skb_pull(skb, dev->hard_header_len);
hardorsoft
26.10.10 в 04:28
|
|
В простейшем случае (соединение точка-точка без заголовков), skb- >mac.raw может указывать на статический буфер содержащий аппаратный адрес интерфейса, протокол может быть установлен в значение ETH_P_IP, и packet_type может содержать значение по умолчанию PACKET_HOST.
hardorsoft
26.10.10 в 04:28
|
|
Т.к. каждый тип аппаратуры – уникален, тяжело добавить к уже сказанному что-то еще. Много примеров можно увидеть в ядре. На пример, посмотрите драйвер AppleTalk (drivers/net/appletalk/cops.c), драйвер инфракрасного порта (drivers/net/irda/smc_ircc.c), или драйвер PPP (drivers/net/ppp_generic.c).
hardorsoft
26.10.10 в 04:28
|
|