Linux - NetzwerkTreiberModule Frage

OP #3229450
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
Angehängte Dateien:
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.
OP
>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.
Gast
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
OP
>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??
Gast
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.
OP
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
Angehängte Dateien:
OP
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?
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.
Gast
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.
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.
OP
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.
OP
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!
Gast
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.
OP
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..).
OP
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!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.