Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 17.11. MAC Address Resolution

Оглавление
Английский оригинал Перевод на русский

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

17.11. Определение MAC адресов

hardorsoft 26.10.10 в 04:23

0

17.11. Разрешение MAC адресов

ximen 26.10.10 в 11:52

0

Возникает вопрос, как ассоциировать MAC-адрес (уникальный
аппаратный идентификатор) и IP-адрес. Многие протоколы сталкиваются
с подобной проблемой, но мы рассмотрим только протокол Ethernet. Мы
попытаемся дать исчерпывающий ответ, и покажем три ситуации: ARP,
Ethernet-заголовки без ARP (как plip), и не Ethernet-заголовки.

hardorsoft 26.10.10 в 04:23

0

17.11.1. Использование ARP с Ethernet

hardorsoft 26.10.10 в 04:23

0

Обычно для определения адресов используется 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

0

Хотя ядро и определяет адрес (и кэширует результат), для
построения пакета требуется помощь драйвера интерфейса. Ведь,
драйверу известен заголовок физического уровня, а авторы сетевого кода
надежно изолировали оставшуюся часть ядра от этой информации. В
конце ядро вызывает метод драйвера hard_header, для посылки пакета с
результатом ARP-запроса. Обычно разработчик Ethernet-драйвера не
интересуется этим процессом, имеющийся код Ethernet решает эту
проблему.

hardorsoft 26.10.10 в 04:24

0

17.11.2. Переопределение ARP

hardorsoft 26.10.10 в 04:24

0

Простой интерфейс точка-точка, такой как plip, может извлечь
выгоду из использования Ethernet-заголовков: избежать накладных
расходов при пересылки ARP пакетов туда-сюда. Простой интерфейс
snull получает еще больший выигрыш для этого класса сетевых
устройств. snull не может использовать ARP, потому как драйвер меняет
IP адреса пакета при передаче, и ARP пакеты заменяют IP адреса. Хотя
мы могли бы реализовать простой генератор ARP ответов, чтобы лучше
показать непосредственную обработку заголовков физического уровня.

hardorsoft 26.10.10 в 04:24

0

Если ваше устройство использует обычные аппаратные заголовки
без использования ARP, вы должны перекрыть метод по-умолчанию
dev->hard_header. В snull-реализации, это короткая функция:

hardorsoft 26.10.10 в 04:24

0

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

0

Функция просто берет информацию предоставляемую ядром, и
преобразует в стандартный заголовок Ethernet. Также переключается
один бит в ethernet-адресе получателя, позже мы скажем, зачем это
делается.

hardorsoft 26.10.10 в 04:25

0

Когда пакет получен интерфейсом, аппаратный заголовок
используется несколькими способами в eth_type_trans. Мы уже видели
этот вызов в snull_rx:

hardorsoft 26.10.10 в 04:25

0

skb->protocol = eth_type_trans(skb, dev);

hardorsoft 26.10.10 в 04:25

0

skb->protocol = eth_type_trans(skb, dev);

hardorsoft 26.10.10 в 04:25

0

Функция извлекает идентификатор протокола (в данном случае
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

0

Функция извлекает идентификатор протокола (в данном случае
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

0

Функция извлекает идентификатор протокола (в данном случае
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

0

Если ваш интерфейс – канал точка-точка, он не принимает
групповые пакеты. Для устранения этой проблемы, вспомните, что если в
адресе назначения младший бит первого октета равен нулю, то пакет
предназначен одному хосту (то есть, является или PACKET_HOST или
PACKET_OTHERHOST). plip драйвер использует значение 0xfc, в первом
октете аппаратного адреса, когда как snull использует 0x00.

hardorsoft 26.10.10 в 04:25

0

Оба адреса работают в Ethernet-ориентированном канале точка-точка.

hardorsoft 26.10.10 в 04:26

0

17.11.3. Не Ethernet заголовки

hardorsoft 26.10.10 в 04:27

0

Мы увидели, что аппаратный заголовок, помимо адреса назначения
пакета, содержит и другую информацию коммуникационного протокола.
Теперь мы расскажем, как получить полезную информацию из
аппаратных заголовков. Для получения более полной информации,
можете ознакомиться с исходным кодом ядра, или технической
документацией средств передачи. Большинство разработчиков могут
игнорировать эту тему и использовать Ethernet-реализацию.

hardorsoft 26.10.10 в 04:27

0

Здесь не приведена вся информация о каждом протоколе.
Соединение точка-точка, такое как plip или snull, не передает
заголовок Ethernet. В метод устройства hard_header, показанный ранее в
реализации snull_header, передается информация (протокольного уровня
и аппаратные адреса) из ядра. Также предается 16-разрядный номер
протокола в аргументе type. На пример, IP идентифицируется значением
ETH_P_IP. Предполагается, что драйвер корректно передаст и пакет
данных, и номер протокола на принимающий хост. Соединение точка-
точка опускает адрес из аппаратного заголовка, предавая только номер
протокола, потому что гарантируется независимость адресов отправителя
и адресата. Только IP-соединения могут не передавать аппаратные
заголовки.

hardorsoft 26.10.10 в 04:27

0

Когда пакет получен, функция приема в драйвере корректно
установит поля skb->protocol, skb->pkt_type и skb->mac.raw.

hardorsoft 26.10.10 в 04:27

0

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

0

skb->mac.raw = skb->data;
skb_pull(skb, dev->hard_header_len);

hardorsoft 26.10.10 в 04:28

0

В простейшем случае (соединение точка-точка без заголовков), skb-
>mac.raw может указывать на статический буфер содержащий
аппаратный адрес интерфейса, протокол может быть установлен в
значение ETH_P_IP, и packet_type может содержать значение по
умолчанию PACKET_HOST.

hardorsoft 26.10.10 в 04:28

0

Т.к. каждый тип аппаратуры – уникален, тяжело добавить к уже
сказанному что-то еще. Много примеров можно увидеть в ядре. На
пример, посмотрите драйвер AppleTalk (drivers/net/appletalk/cops.c),
драйвер инфракрасного порта (drivers/net/irda/smc_ircc.c), или
драйвер PPP (drivers/net/ppp_generic.c).

hardorsoft 26.10.10 в 04:28

0
Минутку...