Estou implementando um módulo / driver de rede no Linux que usa net_devices
structure. E até agora consegui adicionar e remover meu módulo de e para o espaço do kernel usando o comando insmod
. Via ifconfig
eu configurei um ip para minha interface recém-criada e consegui enviar pacotes de ping. O que preciso fazer agora é capturar sk_buff
pacotes dentro da minha função ndo_start_xmit
e enviá-los / recebê-los por meio de conectores físicos UART. ou seja, assim como no caso de aplicativos userspace onde nós abrimos um dispositivo tty através de descritores de arquivos ( /dev/tty*
) e escrevemos para para transmissão (e lidos para receber), agora tenho que de alguma forma detectar ou encontrar meu dispositivo no kernel (dentro do meu módulo de rede) e enviar ou receber dados através das linhas Rx e Tx. Abaixo está o meu driver:
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/kernel.h>
#include <linux/etherdevice.h>
struct net_device *mynet;
int mynet_open(struct net_device *dev) {
printk(KERN_ALERT "open called\n");
return 0;
}
int mynet_release(struct net_device *dev) {
printk(KERN_ALERT "release called\n");
netif_stop_queue(dev);
return 0;
}
int mynet_xmit(struct sk_buff *skb, struct net_device *dev) {
printk(KERN_ALERT "dummy xmit function called...\n");
///////// UART SEND HERE /////////
dev_kfree_skb(skb);
return 0;
}
int mynet_init(struct net_device *dev) {
printk(KERN_ALERT "gohmnet0 device initialized\n");
return 0;
}
const struct net_device_ops my_netdev_ops = {
.ndo_init = mynet_init,
.ndo_open = mynet_open,
.ndo_stop = mynet_release,
.ndo_start_xmit = mynet_xmit,
};
static void virtual_setup(struct net_device *dev){
dev->netdev_ops = &my_netdev_ops;
}
int mynet_init_module(void) {
int result;
mynet = alloc_netdev(0, "mynet",NET_NAME_UNKNOWN, virtual_setup);
if((result = register_netdev(mynet)))
{
printk(KERN_ALERT "mynet: Error %d initalizing card ...", result);
return result;
}
return 0;
}
void mynet_cleanup (void)
{
printk (KERN_ALERT "<0> Cleaning Up the Module\n");
unregister_netdev (mynet);
}
module_init(mynet_init_module);
module_exit(mynet_cleanup);
MODULE_LICENSE("GPL");
P.S. Eu pesquisei o seguinte método e preciso de uma alternativa para ele, por isso está fora de questão:
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open(path, flags, rights);
set_fs(oldfs);
Como nota final, parece-me que preciso usar o driver UART no espaço do kernel em meu próprio módulo / unidade sem ir e voltar para o espaço do usuário.