Forum: PC-Programmierung Linux - NetzwerkTreiberModule Frage


von Markus R. (mark989)


Angehängte Dateien:

Lesenswert?

Hi,
hat jemand eine Ahnung warum beim laden dieses Moduls(mit insmod) sofort 
nach der probe-Funktion die open-Funktion aufgerufen wird? Es ist ja 
sonst eig. üblich dass die open-Funktion per Konsole mit "ifconfig eth1 
up" aufgerufen wird!
Danke für jeden Hinweis!

Gruß Markus

von Thomas M. (thomil)


Lesenswert?

Läuft irgendein network manager, der automatisch alle verfügbaren 
Netzwerk interfaces konfigurieren will?

von Thomas M. (thomil)


Lesenswert?

Außerdem hast du noch ein memory leak wenn register_netdev() 
fehlschlägt.

Dein
1
#define DRV_NAME my
sollte vermutlich ein
1
#define DRV_NAME "my"
sein. Allerdings wird das ganze define nirgends verwendet.

Ein pointer wie dein 'static struct my_net *my' ist unüblich, da du dir 
den Pointer jederzeit mit netdev_priv() holen kannst. Dann kannst du 
später u.U. auch mehrere NICs gleichzeitig betreiben.

Und anstatt den ganzen 'my' wäre vielleicht ein anderes Prefix 
treffender.

von Markus R. (mark989)


Lesenswert?

>Läuft irgendein network manager, der automatisch alle verfügbaren
>Netzwerk interfaces konfigurieren will?
Nein. Denn bei einem Treiber ohne SPI Anbindung wie in(Seite 272):
ftp://ftp.tm.informatik.uni-frankfurt.de/pub/papers/ir/kernelbook.pdf
..kann ich das Interfaces bequem per Konsole (de)aktivieren, dort ist es 
aber kein Ethernettreiber, und die netdev_ops werden anders gehandhabt, 
nicht mit einem struct sondern mit einer setup-Methode, die dann 
alloc_netdev übergeben wird.
Wo liegen hier die Unterschiede/Vorteile? Was ist zu bevorzugen? Ich 
habe mich bis jetzt an dem enc28j60 Treiber orientiert.

thomil danke für die Hinweise!

Bin für Literaturvorschlage speziell für Netzwerktreiber sehr dankbar, 
ich hab bisher leider nur allgemeine Treiberbücher gefunden.

von Hans Ulli K. (Gast)


Lesenswert?

Suche mal nach LDD3e.pdf
Das ist "Linux Device Drivers" von einigen Kernelentwicklern.

Einige Anregungen :
Zeile 19
1
static struct my_net *my;
das ist falsch. Was machst du wenn noch ein Device dazu kommt
auch ist das verwirrend mit der Funktion

static int __devinit my_probe(struct spi_device *spi)

richtig ist es so
1
static int __devinit my_probe(struct spi_device *spi)
2
{
3
  struct net_device *dev;
4
  struct my_net *priv;
5
6
  int ret;
7
  
8
  dev = alloc_etherdev(sizeof(struct my_net));
9
  if(!dev){
10
      printk("Unable to alloc new ethernet\n");
11
  }
12
  else{
13
    printk("Ethernet allocated!\n");
14
  }
15
16
  pric = netdev_priv(dev);
Du willst ja in zu deinem privaten (priv) Treiberbereich referenzieren.

Schau mal den Code in
drivers/net/ethernet/microchip/enc28j60.c
an. Da hast du einen Netzwerktreiber mit SPI

Gefunden mit
git grep -w spi drivers/net
in den Kernel Sourcen

von Markus R. (mark989)


Lesenswert?

>richtig ist es so

Genauso habe ich es implementiert. Es funktioniert ja, nur wird 
open-Funktion direkt beim laden aufgerufen, und die close-Funktion beim 
entladen. Ich will die Funktionen aber manuell mit ifconfig eth1 up 
aufrufen.
Der enc28j60 ist bei mir leiider nicht verfügbar, den habe ich beim 
Kernelkomp. in der config nicht aktiviert. Kann der enc29j60 mit 
ifconfig eth1 up aktiviert werden??

von Martin B. (martin_b35)


Lesenswert?

Hast du NetworkManager am laufen?
Wenn Debian oder ähnliches trag mal in /etc/network/interfaces
eth1 aus der auto Liste aus und sag
iface eth1 inet manual

von Hans Ulli K. (Gast)


Lesenswert?

Markus R. schrieb:
>>richtig ist es so
>
> Genauso habe ich es implementiert. Es funktioniert ja, nur wird
> open-Funktion direkt beim laden aufgerufen, und die close-Funktion beim
> entladen. Ich will die Funktionen aber manuell mit ifconfig eth1 up
> aufrufen.

Seltsam ...

> Der enc28j60 ist bei mir leiider nicht verfügbar, den habe ich beim
> Kernelkomp. in der config nicht aktiviert. Kann der enc29j60 mit
> ifconfig eth1 up aktiviert werden??

Nein.
Du musst den Treiber schon im Kernel haben.
Wenn du einen Kernel mit Modulunterstüzung hast kannst du diesen ja 
laden.

von Markus R. (mark989)


Angehängte Dateien:

Lesenswert?

Wenn nach dem laden ifconfig eth1 down aufrufe sehe folgenden Output auf 
der Konsole:

[  114.163546] tps1_init called!
[  114.167567] Ethernet allocated!
[  114.177484] tps1 driver registered
[  114.271174] open called!
[  149.145411] close called!
[  149.214344] open called!

Es wird direkt nach dem Aufruf von close wieder open aufgerufen! ???
Anbei nochmal den aktuellen C Code.

In /etc/network/interface steht für eth1 folgendes:
iface eth1 inet manual

von Markus R. (mark989)


Lesenswert?

Thomas Miletich schrieb:
>Ein pointer wie dein 'static struct my_net *my' ist unüblich, da du dir
>den Pointer jederzeit mit netdev_priv() holen kannst. Dann kannst du
>später u.U. auch mehrere NICs gleichzeitig betreiben.

Gibt es sonst noch Vorzüge es mit netdev_priv() zu implementieren?

von Thomas M. (thomil)


Lesenswert?

Markus R. schrieb:
> Thomas Miletich schrieb:
>>Ein pointer wie dein 'static struct my_net *my' ist unüblich, da du dir
>>den Pointer jederzeit mit netdev_priv() holen kannst. Dann kannst du
>>später u.U. auch mehrere NICs gleichzeitig betreiben.
>
> Gibt es sonst noch Vorzüge es mit netdev_priv() zu implementieren?

Es hat sonst noch den Vorteil, dass das jeder andere Treiber in Linux, 
*BSD, etc so macht. Wenn jemand Anderes also schon mal so einen Treiber 
gesehen hat, wird er sich fragen "Nanu, wo kommt den eigentlich der 
pointer her, ich habe am Anfang der Funktion gar kein netdev_priv() 
gesehen?".

Wenn du aus irgendwelchen Gründen bei deinem static pointer bleiben 
willst, solltest du sicherheitshalber in probe() sicherstellen, dass 
probe() nur für 1 device aufgerufen werden kann. Um dies zuverlässig 
ausschließen zu können ist u.U. ein Mutex nötig, was für mich schon 
Grund genug wäre, um es mit netdev_priv() zu machen.

von Hans Ulli K. (Gast)


Lesenswert?

Thomas Miletich schrieb:

> Wenn du aus irgendwelchen Gründen bei deinem static pointer bleiben
> willst, solltest du sicherheitshalber in probe() sicherstellen, dass
> probe() nur für 1 device aufgerufen werden kann. Um dies zuverlässig
> ausschließen zu können ist u.U. ein Mutex nötig, was für mich schon
> Grund genug wäre, um es mit netdev_priv() zu machen.

Flascher Ansatz.
Wenn der static pointer benutzt wird, würde ich ihn gegen NULL prüfen 
und dabei ggf. ein Mutex benutzen.

Beides ist aber FALSCH
Wenn irgendwann die probes parallel ablaufen brauchst du einen spinlock.

Also wenn irgendwelche Pointer, Zähler usw. für dein Device verwenden 
willst kommt es in den privaten Teil.

von Thomas M. (thomil)


Lesenswert?

Hans Ulli Kroll schrieb:
> Thomas Miletich schrieb:
>
>> Wenn du aus irgendwelchen Gründen bei deinem static pointer bleiben
>> willst, solltest du sicherheitshalber in probe() sicherstellen, dass
>> probe() nur für 1 device aufgerufen werden kann. Um dies zuverlässig
>> ausschließen zu können ist u.U. ein Mutex nötig, was für mich schon
>> Grund genug wäre, um es mit netdev_priv() zu machen.
>
> Flascher Ansatz.
> Wenn der static pointer benutzt wird, würde ich ihn gegen NULL prüfen
> und dabei ggf. ein Mutex benutzen.

Genau so habe ich das gemeint.

> Beides ist aber *FALSCH*
> Wenn irgendwann die probes parallel ablaufen brauchst du einen spinlock.
>
> Also wenn irgendwelche Pointer, Zähler usw. für dein Device verwenden
> willst kommt es in den privaten Teil.

War von mir ebenfalls so gemeint. Alle Informationen über den Treiber 
state und die hardware kommen in eine Struktur, die im private pointer 
des struct net_device gespeichert ist.

Was mir im Moment nicht ganz klar ist, wo ich nun den spinlock in 
probe() benötige? Es gibt mehrere devices, für jedes ein struct 
net_device, mit eigenem private pointer. Somit ist jeder probe() thread 
unabhängig vom anderen. Vielleicht stehe ich aber gerade nur auf dem 
Schlauch.

von Markus R. (mark989)


Lesenswert?

Erstmal danke für die ganzes Infos, bin noch sehr neu auf dem Gebiet.
Es handelt sich um einen SPI-Treiber, wobei die SPpins des Boards fest 
mit dem Netzwerkchip verdrahtet sind, es wird also immer eine Instanz 
des Treibers erzeugt werden.

von Markus R. (mark989)


Lesenswert?

Hi, noch ne Frage

wieso wird bei dem obigen Netzwerkmodul nicht die send-Methode durch das 
NetzwerkSubsystem aufgerufen??
Muss man über ifconfig irgendetwas aktivieren oder in 
etc/network/interfaces irgendwas einstellen ??
eth1 ist auf jeden Fall aktiv!

von Hans Ulli K. (Gast)


Lesenswert?

Aktiv sagt nur aus das die Schnittstelle genutzt werden kann.

Mit ping kannst du ja ein Paket senden.

von Markus R. (mark989)


Lesenswert?

Auch mit ping wird eth1 nicht angesprochen, standart Schnittstelle ist 
eth0, ich kann sie aber nicht deaktivieren weil über sie (ssh) das 
RaspberryPi steuere..

von Hans Ulli K. (Gast)


Lesenswert?

Hmmm.

Was ich erstnal machen würde ist, deinen Treiber zu erweitern.
Folgende Funktionen fehlen da noch:

.ndo_change_mtu
.ndo_set_mac_address

Was mich aber immer noch stört warum machst du die Arbeit und 
schreibst einen neuen Treiber.
Wie ich mal sagte in
drivers/net/ethernet/microchip/enc28j60.c
ist ein entsprechender Treiber, der muss halt nur auf deine Platform 
angepasst werden.

Und zu dem GPIO Problem was ich in einem anderen Thread von dir gefunden 
habe, schau mal nach pinctrl (Pincontrol).
So wie ich es gelesen habe ist es die "neue" Schnittstelle um GPIOs 
anzubinden.

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Gib dem Interface ein andere IP Subnetz und Pinge eine IP aus diesem 
Subnetz an, dann gehts über dein zweites IF.

von Markus R. (mark989)


Lesenswert?

elektroman schrieb:

>Was ich erstnal machen würde ist, deinen Treiber zu erweitern.
>Folgende Funktionen fehlen da noch:
>.ndo_change_mtu
>.ndo_set_mac_address

Ich habe ihn jetzt mit random_ether_addr(dev->dev_addr); erweitert, 
heißt jetzt hat er eine zuf. macadresse und eine MTU=1500.


>Was mich aber immer noch stört warum machst du die Arbeit und
>schreibst einen neuen Treiber.
>Wie ich mal sagte in
>drivers/net/ethernet/microchip/enc28j60.c
>ist ein entsprechender Treiber, der muss halt nur auf deine Platform
>angepasst werden.

Ich habe vor einen Treiber zu bauen(BA Arbeit) für einen Netzwerkchip 
der schon eine fertige API zu Verfügung stellt. Das heißt die 
SPI-Kommunikation ist schon so gut wie fertig. Jetzt muss ich nur noch 
Ethernetframes vom Kernel entgegennehmen können und mit einer Methode 
der API (Send_EthernetFrame(...)) versenden. Die Eigenschaften der NICs 
wie zB die Mac adresse werden über die API gesetzt, dh. mein Treiber 
unterscheidet bis auf die Anbindung an das Netzwerksubsystem komplett 
von dem enc28j60-Treiber.

>Und zu dem GPIO Problem was ich in einem anderen Thread von dir gefunden
>habe, schau mal nach pinctrl (Pincontrol).
>So wie ich es gelesen habe ist es die "neue" Schnittstelle um GPIOs
>anzubinden.
Da die GPIOs einwandfrei funktionieren denk ich mal das die 
printk-Ausgabe falsch programmiert wurde, und das fälschlicher Weise 
"Invalid GPIO" ausgegeben wird.

>Gib dem Interface ein andere IP Subnetz und Pinge eine IP aus diesem
>Subnetz an, dann gehts über dein zweites IF.
eth1 ist von außen noch nicht erreichbar.


Ich hab es einmal hinbekommen dass die send-Funktion aufgerufen wurde, 
im jetzt funkioniert es iwie nicht nicht(musste Raspbian neu 
installieren weil sich das Linuxdateisystem zerschießt wenn man zu oft 
den Strom wegnimmt, war leider nötig..).

von Markus R. (mark989)


Lesenswert?

kruemeltee schrieb:

>>Gib dem Interface ein andere IP Subnetz und Pinge eine IP aus diesem
>>Subnetz an, dann gehts über dein zweites IF.

Habs erst falsch verstanden, bin jetz aber von selbst drauf gekommen.
So funktionierts!! Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.