простой виртуальный сетевой интерфейс

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 03 апр 2012, 10:58

kit_D писал(а):
Хотелось бы этому же интерфейсу присвоить ещё один алиасный IP из другой подсетки: 192.168.50.1
Как?
Для этого надо использовать утилиту ip. ifconfig является устаревшим инструментом (не поддерживает netlink), в то время как утилита ip (пакета iproute2) является новым и гораздо более обширным средством настройки сетевой подсистемы.
Это я знаю (правда, я не помню кто такой netlink ;-) ).

Но я не называл бы ifconfig "устаревшим инструментом"(с) ... хотя бы потому, что эта утилита используется во всех UNIX, а ip - это новый мощный, но сторонний пакет, который я видел только в Linux (ну, и, наверняка, портированный в какие-то ближайшие ОС).

Так что на пока они, скорее, сосуществуют.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 03 апр 2012, 11:04

Olej писал(а): 1. как повторно загрузить модуль под другим именем?
(для сетевых интерфейсов, как устройств фиктивных ;-) - это может иметь смысл)...
Поясняю подробнее:
- как? загрузить файл модуля xxx.ko так...
- что, если модуль xxx уже загружен,
- так он бы загрузился как xxx0 (но, скажем, с какими-то другими параметрами загрузки в командной строке).
Существуют же алиасы для модулей в файле modules.alias ?:

Код: Выделить всё

[olej@notebook 2.6.42.12-1.fc15.i686.PAE]$ cat modules.alias | head -n5
# Aliases extracted from modules themselves.
alias devname:cpu/microcode microcode
alias char-major-10-184 microcode
alias twofish-asm twofish_i586
alias twofish twofish_i586
[olej@notebook 2.6.42.12-1.fc15.i686.PAE]$ lsmod | grep microcode
microcode              18550  0 
[olej@notebook 2.6.42.12-1.fc15.i686.PAE]$ lsmod | grep char-major
Причём, некоторые из них записаны в странной форме:

Код: Выделить всё

[olej@notebook 2.6.42.12-1.fc15.i686.PAE]$ cat modules.alias | grep devnam
alias devname:cpu/microcode microcode
alias devname:fuse fuse
alias devname:btrfs-control btrfs
alias devname:net/tun tun
alias devname:ppp ppp_generic
alias devname:uinput uinput
alias devname:snd/timer snd_timer
alias devname:snd/seq snd_seq
- что означает вот то двоеточие?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 03 апр 2012, 14:45

Ну, вот первый работающий вариант ("уже намазывается, но запах ещё сохраняется"(с) ;-) ), за основу взяты выдержки из разных вариантов примеров kit_D (спасибо ему), но уже сильно покроено, а дальше будет ещё более ;-) .
P.S. да, поменялись: имя модуля, имя интерфейса и т.д. - так мне удобнее.

Для тестирования достаточно на хосте запуска:

Код: Выделить всё

[olej@fedora16vm virt]$ sudo insmod virt.ko link=p7p1
[olej@fedora16vm virt]$ sudo ifconfig virt0 192.168.50.2
- и всё! link (имя физ. интерфейса) - подставьте свой, при запуске без параметра это будет eth0.

На тестирующей стороне (в LAN, VirtualBox), делается что-то типа:

Код: Выделить всё

[olej@nvidia ~]$ sudo ifconfig vboxnet0:1 192.168.50.1

- IP алиас на требуемую подсетку, роутинг должен при этом встать сам (в VirtualBox, по крайней мере).

И всё, можно наслаждаться новой подсеткой:

Код: Выделить всё

[olej@nvidia ~]$ ssh 192.168.50.2
Nasty PTR record "192.168.50.2" is set up for 192.168.50.2, ignoring
olej@192.168.50.2's password: 
Last login: Tue Apr  3 14:04:26 2012 from 192.168.50.1
[olej@fedora16vm ~]$ exit
logout
Connection to 192.168.50.2 closed.
Вложения
virt.tgz
(3.25 КБ) 417 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 03 апр 2012, 14:51

Olej писал(а): Существуют же алиасы для модулей в файле modules.alias ?:
Как? ;-)
... загрузить модуль из файла YYY.ko так, чтобы он встал как модуль (lsmod) как XXX?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 09 апр 2012, 11:16

Olej писал(а): При инициализации перехвата интерфейса меняем то, что было:

Код: Выделить всё

   memcpy( dev->dev_addr, slave->dev_addr, sizeof( slave->dev_addr ) );
   memcpy(dev->broadcast, slave->broadcast, sizeof( slave->broadcast ) );
- это вообще непонятно что записано, учитывая, что slave->dev_addr - это указатель... меняем на то, что стало:

Код: Выделить всё

   memcpy( dev->dev_addr, slave->dev_addr, ETH_ALEN );
   memcpy( dev->broadcast, slave->broadcast, ETH_ALEN );
(ETH_ALEN - это как-раз 6 байт - длина MAC-адреса).
Вот тот неправильный фрагмент, в котором длиной MAC-адреса записан размер указателя на MAC-адрес - он кочует из примера в пример, ещё с тех времён когда его авторы написали это ещё для ядра 2.4 (сначала Alessandro Rubini <rubini@linux.it>, а затем Filippo Bistaffa <liquidator87@gmail.com> - проект insane).

Меня всё удивлял вопрос: как же это у них всё работало, если его годами хоть как, но тестировали?
Думаю, что сейчас мне это понятно:
- практически все разработчики сейчас ведут разработку на 64-бит платформе...
- на 64-бит, при 8 байт размере указателя, в качестве MAC-адреса копировались не 6 положенные (Ethernet), а 8 байт ... с точки зрения значений этого более чем достаточно, а вылезть за предел выделенной области памяти на 2 байта - маловероятно...
- но на 32-бит эта ошибка вылазит явно: первые 4 байт MAC-адреса - идентичные, а последние 2-байта - различные, естественно, что при этом ARP не отрабатывает нормально и приём не происходит.

kit_D
Писатель
Сообщения: 52
Зарегистрирован: 13 мар 2012, 13:14
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение kit_D » 09 апр 2012, 11:22

Ну подождите. Я всегда считал и до сих пор считаю, что
если char array[100], то sizeof(array) вернет не размер указателя, а размер массива байтах, в данном случае - 100.
Аналогично sizeof(array)/sizeof(array[0]) вернет количество элементов в массиве.
Вы же об этом говорите?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 09 апр 2012, 12:09

kit_D писал(а):Ну подождите. Я всегда считал и до сих пор считаю, что
если char array[100], то sizeof(array) вернет не размер указателя, а размер массива байтах, в данном случае - 100.
Аналогично sizeof(array)/sizeof(array[0]) вернет количество элементов в массиве.

Код: Выделить всё

#include <stdio.h>

#define SIZE 6
typedef int elem_t;

void func( elem_t* MAC ) {
   printf( "in func: длина массива = %d, размерность массива = %d\n",
           sizeof( MAC ), sizeof( MAC ) / sizeof( MAC[ 0 ] ) );
}

int main( void ) {
   elem_t MAC[ SIZE ];
   printf( "in main: длина массива = %d, размерность массива = %d\n",
           sizeof( MAC ), sizeof( MAC ) / sizeof( MAC[ 0 ] ) );
   func( MAC );
   return 0;
}
- чтоб смешнее (нагляднее) я в качестве типа элемента взял не char, а int...

Код: Выделить всё

[olej@notebook size]$ make
cc     size.c   -o size
[olej@notebook size]$ ./size
in main: длина массива = 24, размерность массива = 6
in func: длина массива = 4, размерность массива = 1
P.S. А для char ещё смешнее :-o :

Код: Выделить всё

[olej@notebook size]$ ./size
in main: длина массива = 6, размерность массива = 6
in func: длина массива = 4, размерность массива = 4

kit_D
Писатель
Сообщения: 52
Зарегистрирован: 13 мар 2012, 13:14
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение kit_D » 09 апр 2012, 12:51

Не, ну это понятно. Когда вы в функцию передаете указатель, то sizeof вернет размер указателя. Но в примере с МАК адресами такого же не происходит, мы берем sizeof от массива и вероятно компилятор понимает что именно мы имеем ввиду.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 09 апр 2012, 12:54

Olej писал(а):
kit_D писал(а):Ну подождите. Я всегда считал и до сих пор считаю, что
если char array[100], то sizeof(array) вернет не размер указателя, а размер массива байтах, в данном случае - 100.
Аналогично sizeof(array)/sizeof(array[0]) вернет количество элементов в массиве.
- чтоб смешнее (нагляднее) я в качестве типа элемента взял не char, а int...
Не совсем в тему, но к тому же вопросу ... чтоб смешнее было ;-) :

Код: Выделить всё

#include <stdio.h>
#include <string.h>

#define SIZE 6
//typedef int elem_t;
typedef char elem_t;
struct arr { elem_t MAC[ SIZE ]; };

void str_func( struct arr data ) {
   printf( "in struct: длина массива = %d, размерность массива = %d\n",
           sizeof( data.MAC ), sizeof( data.MAC ) / sizeof( data.MAC[ 0 ] ) );
}

void func( elem_t* MAC ) {
   printf( "in func: длина массива = %d, размерность массива = %d\n",
           sizeof( MAC ), sizeof( MAC ) / sizeof( MAC[ 0 ] ) );
}

int main( void ) {
   elem_t MAC[ SIZE ];
   printf( "in main: длина массива = %d, размерность массива = %d\n",
           sizeof( MAC ), sizeof( MAC ) / sizeof( MAC[ 0 ] ) );
   func( MAC );
   struct arr data;
   memcpy( (void*)&data, MAC, sizeof( MAC ) );
   str_func( data );
   return 0;
}
Результат:

Код: Выделить всё

[olej@notebook size]$ ./size
in main: длина массива = 6, размерность массива = 6
in func: длина массива = 4, размерность массива = 4
in struct: длина массива = 6, размерность массива = 6
P.S. кому интересно убедиться будет (или развить пример) так я пример прикреплю, чтоб не бить с экрана...
size.tgz
(581 байт) 428 скачиваний
P.P.S. а ещё веселее, что на это (на тот же пример) скажет компилятор Microsoft Visual C, ... а он скажет по-другому :lol: (ещё загадочнее) ... но, может, это от версии зависит, а я смотрел последний раз году в 2007-м.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: простой виртуальный сетевой интерфейс

Непрочитанное сообщение Olej » 09 апр 2012, 13:04

kit_D писал(а):Не, ну это понятно. Когда вы в функцию передаете указатель, то sizeof вернет размер указателя. Но в примере с МАК адресами такого же не происходит, мы берем sizeof от массива и вероятно компилятор понимает что именно мы имеем ввиду.
Но там (<linux/netdevice.h>) в struct net_device описан dev_addr как указатель (это ядро 2.6.42):

Код: Выделить всё

        /* Interface address info used in eth_type_trans() */
        unsigned char           *dev_addr;      /* hw address, (before bcast
                                                   because most packets are
                                                   unicast) */
...
        unsigned char           broadcast[MAX_ADDR_LEN];        /* hw bcast add */
Возможно раньше там было описание массивом, так же как broadcast, который имеет ... а-а-афиговенную длину ;-) в 32 байта.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей