Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > сетевой драйвер


Автор: dima3351 10.11.2006, 17:32
Я учусь писать сетевые драйверы. Реализовал функцию hard_start_xmit, которая, как я понимаю, вызывается, если модуль передает пакет. Также реализовали и прием пакета через обработчик прерываний.

это все замечательно.

теперь мы пытаемся написать прогу, работающую с этим драйвером.

делаю в ней форк.

в ветке N1

socket(AF_UNIX, SOCK_STREAM, 0)

my_addr.sin_family = AF_UNIX;
my_addr.sin_port = htons(50);
my_addr.sin_addr.s_addr = "100.100.100.100";
memset( &(my_addr.sin_zero), '\0', 8);

bind(sfd, (struct sockaddr*) &my_addr, sizeof(struct sockaddr); listen(sfd, 10);

в ветке N2

socket(AF_UNIX, SOCK_STREAM, 0);

dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(50);
dest_addr.sin_addr.s_addr = "100.100.100.100";
memset( &(dest_addr.sin_zero), '\0', 8);

connect(sfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr))

connect не срабатывает, пишет Invalid parametr в чем дело? параметры у bind в ветке 1 и connect в ветке 2 одинаковы...

Автор: MAKCim 10.11.2006, 18:23
dima3351, 
в ветке 2
что-то непонятно
т. е создается локальный сокет
Цитата

socket(AF_UNIX, SOCK_STREAM, 0);

но в sin_family указывается почему то AF_INET
что за тип у dest_addr? (должен быть struct sockaddr_un из <sys/un.h>)

Автор: dima3351 10.11.2006, 19:43
Цитата

но в sin_family указывается почему то AF_INET

да, глюк, пробовал и так и так - не помогает.

Цитата

что за тип у dest_addr? 


читал http://www.beej.us/guide/bgnet/output/htmlsingle/bgnet.html#connect, тип соответственно struct sockaddr_in.

А реально, что именно это приводит к ошибке? Опробую.

Автор: MAKCim 10.11.2006, 20:23
dima3351
для локальных сокетов порт и адрес указывать не надо
надо:
 - семейство протоколов (в данном случае AF_UNIX)
 - path
т. е
Код

struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, <path>);

Автор: bsa 11.11.2006, 01:00
dima3351, прежде чем грешить на свой драйвер, попробуй ту же программу запустить на одном из стандартных. Если заработает, то виноват драйвер, если нет - прога.

Автор: dima3351 13.11.2006, 12:28
спасибо за ответы)

Цитата

для локальных сокетов порт и адрес указывать не надо

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

ifconfig mcb address 100.100.100.100 up
(при этом драйвер реагирует нормально, запускается функция open)

а потом пытаюсь работать в программе так
Код

struct sockaddr_in my_addr;
sfd = socket(AF_INET, SOCK_STREAM, 0);

my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(50);
my_addr.sin_addr.s_addr = "100.100.100.100";
memset( &(my_addr.sin_zero), '\0', 8);

bind(sfd, (struct sockaddr*) &my_addr, sizeof(struct sockaddr));


но уже эти строчки не работают: 
bind(): -1 Cannot assign requested address

Цитата

dima3351, прежде чем грешить на свой драйвер, попробуй ту же программу запустить на одном из стандартных. 

хм, а не подскажите какой-нибудь несложный ethernet драйвер? Мне в нем покопаться оччень полезно будет.

Автор: MAKCim 13.11.2006, 15:46
Цитата

хм, а не подскажите какой-нибудь несложный ethernet драйвер? Мне в нем покопаться оччень полезно будет. 

за несложность ручаться не могу  smile 
drivers/net/8139cp.c

Автор: GrayCardinal 17.11.2006, 12:27
MAKCim, 
Это сложный ;p

drivers/net/8139too.c - наш выбор  smile 

dima3351, 
Извиняюсь что припозднился...
Кода, так понимаю - не будет ?
Значит так, на пальцах :
Упс, сорри, прозевал две строчки ифконфа... 
Но вообще, там AF_INET должно быть везде, это точно 
 smile

Добавлено @ 12:37 
Вот эту шнягу замените :
my_addr.sin_addr.s_addr = "100.100.100.100";
на 
inet_aton ("100.100.100.100", &my_addr.sin_addr).
формат-то сетевой........

Добавлено @ 12:39 
Объясните мне кто-нибудь каким боком тут AF_UNIX ?  smile 

Автор: dima3351 17.11.2006, 13:25
большое спасибо за ответы! потихоньку ситуация проясняется.
AF_UNIX здесь действительно абсолютно левый. на чем остановился сечас:
(весь код не привожу, дабы не загромождать тему. если нужно - могу весть сюда скопипастить)
Код

if (fork())
{
        sfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&my_addr, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(port);
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

        bind(sfd, (struct sockaddr*) &my_addr, sizeof(struct sockaddr));
        listen(sfd, 10), strerror(errno));
        accept(sfd, (struct sockaddr *)&their_addr, &sin_size);
        close(sfd);
}
else 
{
        sleep(3);
        sfd1 = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&dest_addr, sizeof(dest_addr));
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(port);
        inet_pton(AF_INET, "127.0.0.1", &dest_addr, &sin_size);

        connect(sfd1, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
}

Ошибка возникает при connect(): Address family not supported by protocol

При этом netstat -a пишет 

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 *:9000                  *:*                     LISTEN


то есть все вроде нормально. теперь, как я понимаю, надо прикрутить в драйвере поддержку AF_INET?

Автор: GrayCardinal 17.11.2006, 15:02
dima3351, 
Поддержка AF_INET там по дефолту  smile 
Вообще пока пакеты не начнут уходить _через_ девайс, девайс ничего и не делает. Т.е. регистрация, все у тебя на компе локальный девайс с таким-то IP. И все это все равно через loopback 
 smile 
А дальше 
/sbin/route 
GW, как я понимаю.................................

ЗЫ
Цитата

connect(): Address family not supported by protocol

А вот этого быть не должно... Скорее всего просто надо в sizeof давать не sockaddr а sockaddr_in  smile У ядра размер адреса не совпал, оттого и ругается.

Автор: dima3351 18.12.2006, 15:32
привет! Я опять вернулся к своему драйверу. Сеичас точно определил, что ошибка в нем, тестовые программы бегают под loopback, но не бегуют под мои драйвер. 

Первая ошибка, которую я нашел было то, что не были проинициализированы поля структуры struct net_device. Помогите найти глюк... Ошибку прога выдает ту же:  Address family not supported by protocol

Код

#include <linux/kernel.h> 
#include <linux/module.h>
#include <linux/netdevice.h>

struct net_device *mcb2;

struct mcb2_priv { struct net_device_stats stats; };

int mcb2_open(struct net_device *dev) {    return 0; }
int mcb2_stop(struct net_device *dev) { return 0; }
int mcb2_hsx(struct sk_buff *skb, struct net_device *dev) { return 0; }
int mcb2_conf(struct net_device *dev, struct ifmap *map) { return 0; }

struct net_device_stats * mcb2_stats(struct net_device *dev)
{
    struct mcb2_priv *priv = netdev_priv(dev);
    return &priv->stats;
}

int mcb2_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { return 0; }
int mcb2_rebuild_header(struct sk_buff *skb) { return 0; }

void mcb2_tx_timeout(struct net_device *dev){;}

void mcb_init2(struct net_device *dev)
{
   struct mcb2_priv *priv = netdev_priv(dev);
   memset(priv, 0, sizeof(struct mcb2_priv));

   ether_setup(dev);
   dev->open = mcb2_open;
   dev->stop = mcb2_stop;
   dev->hard_start_xmit = mcb2_hsx;
   dev->set_config = mcb2_conf;
   dev->get_stats = mcb2_stats;
   dev->hard_header = mcb2_header;
   dev->rebuild_header = mcb2_rebuild_header;
   dev->tx_timeout = mcb2_tx_timeout;
}

static int m_init(void)
{
   mcb2 = alloc_netdev( sizeof(struct mcb2_priv), "mcb_tmp", mcb_init2);
   register_netdev(mcb2);
   return 0;
}

static void m_exit(void)
{
   unregister_netdev(mcb2);
   free_netdev(mcb2);
}

module_init(m_init);
module_exit(m_exit);


Автор: GrayCardinal 19.12.2006, 04:40
dima3351, 
И где в приведенном куске, даже чисто теоретически, может быть ошибка ? В куче операторов "=" ?

Автор: BlackStar 19.12.2006, 13:03
Цитата
Сеичас точно определил, что ошибка в нем, тестовые программы бегают под лоопбацк, но не бегуют под мои драйвер. 

И с чего бы им бегать если mcb2_hsx возращает ноль. Советую посмотреть реализацию сетевых драйверов здесь:

* виртуальные
/usr/src/linux/drivers/net/dummy.c
/usr/src/linux/drivers/net/loopback.c

*аппаратные
/usr/src/linux/drivers/net/pci-skeleton.c
/usr/src/linux/drivers/net/isa-skeleton.c

Автор: dima3351 19.12.2006, 13:49
BlackStar
огромное спасибо, особенно за ссылку на /usr/src/linux/drivers/net/dummy.c! Как раз то, что мне нужно, чтоб разобраться.

GrayCardinal
а вот есть тут ошибки! не хватает тут многого...

Автор: GrayCardinal 19.12.2006, 15:01
dima3351, 
И ? Предлагаете дописать ?

Автор: dima3351 19.12.2006, 19:34
да нет конечно же)
вообще надо было мне еще давно сказать /usr/src/linux/drivers/net/dummy.c и я был бы щастлив)

Автор: BlackStar 19.12.2006, 19:43
Обращайся, рад был помочь.

Автор: GrayCardinal 20.12.2006, 09:59
dima3351, 
Ну я тебя не так понял значит smile
Но вслудующий раз стоит просто спросить "Где копнуть". Пошлют куда надо, гарантия smile
Галку поставьте на тему.

Автор: dima3351 29.1.2007, 12:29
Продолжаю непонимать...

Вот есть у нас 2 сетевых "устройства":
[root@ws11 cs]# ifconfig
dummy0    Link encap:Ethernet  HWaddr 00:00:00:00:00:00
          inet addr:127.0.0.2  Bcast:127.255.255.255  Mask:255.0.0.0
          UP BROADCAST RUNNING NOARP  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:376 errors:0 dropped:0 overruns:0 frame:0
          TX packets:376 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:32168 (31.4 Kb)  TX bytes:32168 (31.4 Kb)

Предположим, я запустил некоторое простейшую серверную программку...
[root@ws11 cs]# ./server 80000 &
...и клиент к нему
[root@ws11 cs]# ./client 127.0.0.2 qwer 80000
Сервер нормально пишет, что к нему кто-то подключился...
Client connected: 127.0.0.2
Received: qwer

Но, посмотрев еще раз вывод ifconfig, видим, что пакеты шли через loopback...

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:831 errors:0 dropped:0 overruns:0 frame:0
          TX packets:831 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:73464 (71.7 Kb)  TX bytes:73464 (71.7 Kb)

Читаем заголовок dummy.c:
The purpose of this driver is to provide a device to point a route through, but not to actually transmit packets.

Ага, значит так и должно быть (?) Получается, что dummy.c не позволяет даже передавать пакеты, только устанавливать соединение (?) Поправьте меня, если не прав.

Тут я подумал - ну тогда надо посмотреть этот самый loopback.c, через который мои пакеты таки доходят. В нем регистрация проходит не через стандартные module_init и module_exit, а через статическую компиляцию с другими сишниками (net_init.o), но это не самое главное. Плохо то, что я не вижу в нем сильных отличий от dummy. Похожее заполнение struct net_device, похожее hard_start_xmit... В чем фишка-то? Объясните плз...

Автор: BlackStar 1.2.2007, 15:09
Честно говоря сам до конца не понимаю как работает dummy, но различие с loopback.c в hard_start_xmit: dummy осбождает пакет (dev_kfree_skb),  loopback отправляет его на верхний уровень (netif_rx).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)