2015-10-01 2 views
1

J'ai plusieurs modules de noyau qui doivent interagir avec l'espace utilisateur. Par conséquent, chaque module a une socket Netlink.Puis-je avoir plus de 32 sockets netlink dans l'espace noyau?

Mon problème est que ces douilles interfèrent les unes avec les autres. En effet, ils s'inscrivent tous à la même famille d'adresses Netlink (car il n'y en a pas beaucoup pour commencer - les max is 32 et more than half are already reserved) et aussi parce qu'ils se lient tous au même pid (le noyau pid - zéro).

Je souhaite qu'il y avait plus de place pour les familles d'adresses. Ou, mieux encore, je voudrais pouvoir lier mes orbites à d'autres pids. Comment se fait-il que Netlink soit le canal utilisateur-noyau préféré si seulement 32 sockets peuvent être ouvertes en même temps?

libnl-3's documentation dit

L'adresse netlink (port) est constitué d'un nombre entier de 32 bits. Le port 0 (zéro) est réservé au noyau et fait référence au socket côté noyau de chaque famille de protocoles netlink. Les autres numéros de port font généralement référence à des sockets appartenant à l'espace utilisateur, bien que cela ne soit pas appliqué.

Cette dernière affirmation semble être un mensonge en ce moment. Le noyau utilise un constant as pid et ne pas exporter des fonctions plus versatiles:

if (netlink_insert(sk, 0)) 
    goto out_sock_release; 

Je suppose que je peux recompiler le noyau et augmenter la limite de famille d'adresses. Mais ce sont des modules noyau; Je ne devrais pas avoir à faire ça.

Ai-je raté quelque chose?

+1

Selon les sources du noyau, toutes les sockets Netlink côté noyau sont stockées dans le seul tableau pré-alloué ('nl_table') et indexées par numéro de protocole. Donc, vous ne pouvez pas avoir plus de 32 sockets netlink (taille de tableau). Mais rien ne vous empêche d'utiliser un socket unique et de lui envoyer des messages en fonction d'un champ prédéfini dans ces messages. De cette façon, vous aurez plusieurs prises "virtuelles". – Tsyvarev

+0

@Tsyvarev en d'autres termes ... Je devrais coder un nouveau module spécial qui créerait une socket ... et ensuite multiplexer les messages de cette socket à travers les autres modules. Tu as raison; C'est une façon de le résoudre, même si c'est beaucoup plus difficile que cela devrait probablement l'être. Peut-être que cela finira par être la réponse acceptée, bien que je préfère attendre pour voir plus d'opinions pendant un moment. –

Répondre

1

No.

limite du nombre de prise de Netlink est pourquoi Generic Netlink existe.

Netlink générique est une couche sur le dessus de Netlink. Au lieu d'ouvrir une socket, vous enregistrez un rappel sur une socket déjà établie et écoutez les messages dirigés vers une famille "sub". Étant donné qu'il y a plus de créneaux familiaux disponibles (1023) et pas de ports, je suppose qu'ils pensaient qu'une séparation entre les familles et les ports était inutile à cette couche.

Pour enregistrer un écouteur dans l'espace noyau, utilisez genl_register_family() ou siblings. Dans l'espace utilisateur, Generic Netlink peut être utilisé via libnl-3's API (bien que ce soit plutôt limité, mais le code parle beaucoup et est ouvert).

0

Vous êtes perturbé par le nom de la variable MAX_LINKS. Ce n'est pas un "nombre maximal de liens", c'est un "nombre maximal de familles". Les choses que vous avez énumérées sont familles netlink ou IOW groupes netlink. Il y a en effet 32 ​​familles. Chaque famille dédiée à servir un but particulier. Par exemple NETLINK_SELINUX est pour la notification SELinux et NETLINK_KOBJECT_UEVENT est pour les notifications de kobject (ce sont udev poignées).

Mais il n'y a aucune restriction sur le nombre de sockets pour chaque famille.

Lorsque vous appelez netlink_create, il vérifie votre numéro de protocole qui, dans le cas de socket netlink est la famille netlink comme NETLINK_SELINUX. Regardez the code

static int netlink_create(struct net *net, struct socket *sock, int protocol, 
          int kern) 
{ 
... 
     if (protocol < 0 || protocol >= MAX_LINKS) 
       return -EPROTONOSUPPORT; 
... 

Voici comment votre MAX_LINKS utilise. Plus tard, quand créer un socket, il appelle __netlink_create, qui à son tour appelle sk_alloc, ce qui appelle sk_prot_alloc. Maintenant, en sk_prot_alloc elle alloue prise par kmalloc ING (NetLink ne possède pas son propre cache de la dalle):

slab = prot->slab; 
if (slab != NULL) { 
    sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO); 
    if (!sk) 
     return sk; 
    if (priority & __GFP_ZERO) { 
     if (prot->clear_sk) 
      prot->clear_sk(sk, prot->obj_size); 
     else 
      sk_prot_clear_nulls(sk, prot->obj_size); 
    } 
} else 
    sk = kmalloc(prot->obj_size, priority); 
+0

Hmm ... désolé; Je ne pense pas que tu vois mon problème. Oui, je sais que le 32 se réfère aux familles. Idéalement, je voudrais ouvrir plus de sockets par famille. C'est le fait que chaque famille peut avoir ** un pid (port) ** représentant ** dans l'espace noyau ** qui m'empêche de le faire. Je pensais utiliser les familles comme un hack pour ouvrir plus de sockets, mais ensuite je m'attache au max 32. _Mais c'est juste un hack_. –

+0

Ce qui est important est que si j'exécute 'netlink_kernel_create (net, NETLINK_USERSOCK, & cfg)' une fois qu'il se lie au zéro pid de la famille usersock. Si je le fais une seconde fois, il échoue, vraisemblablement [parce que le pid zéro de la famille usersock est déjà pris] (http://lxr.free-electrons.com/source/net/netlink/af_netlink.c#L1086). Il ne semble y avoir aucun moyen de dire à la fonction quel pid je veux utiliser. –