Модуль ядра для эха пакетов Ethernet

Я разрабатываю модуль ядра Linux для повторной передачи некоторого пакета Ethernet (сделайте эхо). Приходит пакет, я проверяю адрес назначения Ethernet, и если он для меня, я повторяю передачу. Если нет, я ничего не делаю.

Я использовал dev_pack_eth, чтобы определить обработчик протокола для получения всех пакетов Ethernet (EHT_P_ALL) и dev_queue_xmit для передачи полученного баффа skb.

Он работает, эхо работает, но...

Иногда, очень часто. ядро падает, и я не знаю, почему.

Когда я повторно передаю пакет, я возвращаю NET_RX_Sucess.

Когда я не передаю повторно, я использую kfree_skb, чтобы освободить полученный бафф skb и вернуть NET_RX_DROP.

Я думаю проблема моя быть на этом вопросы. Вы можете помочь мне?

При необходимости я мог бы опубликовать код модуля ядра.

С уважением!

------------ Редактировать: добавлен код --------

#include <linux/module.h>   /* Needed by all modules */
#include <linux/kernel.h>   /* Needed for KERN_INFO */
#include <linux/init.h>     /* Needed for the macros */
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_bridge.h>
#include <asm-generic/types.h>


/*Buscar as interfaces de rede*/
struct net_device *dev_eth0;
struct net_device *dev_eth1;
int contador;

static struct packet_type hook; /* Initialisation routine */

void handler_add_config (void);
void handler_remove(void);
void print_mac_hdr(struct ethhdr *eth);

static int hook_func( struct sk_buff *skb)
{

        struct ethhdr *eth;    
        struct ethhdr aux;

        eth= eth_hdr(skb)
        print_mac_hdr(eth);


       /*If destination isn't the same that dev_addr, the packet is not for me: do nothing*/
        if(memcmp(eth->h_dest,skb->dev->dev_addr,ETH_ALEN)!=0)
            {
            printk("Não são iguais!!!\n");
            }
        else
            {
        /*Swap addr*/
            memcpy(&(aux.h_dest),eth->h_dest,ETH_ALEN);
            memcpy(eth->h_dest,eth->h_source,ETH_ALEN);
            memcpy(eth->h_source,&(aux.h_dest),ETH_ALEN);
     /*Re build ther hearders*/
            skb->data = (unsigned char *)skb->mac_header;
            skb->len += ETH_HLEN;

            skb->pkt_type = PACKET_OUTGOING;

                  /*Send*/
                if(dev_queue_xmit(skb)!= NET_XMIT_SUCCESS)
                 {
                      printk("Erro na transmissão\n");
                 }
                else
                 {
                      printk("Trama retransmitida com sucesso\n");
                      return NET_RX_SUCCESS;
                 }

            }



    kfree_skb(skb);
    return NET_RX_DROP;
}

/*Print eth  headers*/
void print_mac_hdr(struct ethhdr *eth)
{
    printk("Destino: %02x:%02x:%02x:%02x:%02x:%02x \n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
    printk("Origem: %02x:%02x:%02x:%02x:%02x:%02x\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
    printk("Proto: 0x%04x\n",ntohs(eth->h_proto));

}

/*Configure Protocol Handler*/

void handler_add_config (void)
{
        hook.type = htons(ETH_P_ALL);
        hook.func = (void *)hook_func;
        hook.dev = NULL;
        dev_add_pack(&hook);
        printk("Handler Protocol adicionado!!!!\n");

}
/*Unregist protocol handler*/
void handler_remove(void)
{
    dev_remove_pack(&hook);
    printk("Handler Protocol removido!!!!\n");
    synchronize_net();/*Sincronizar a rede!*/
}

/*Init module and protocol handler*/
static int __init hook_init(void)
{

    printk("Hello:I'm the hook module!!!!\n");
    contador =0;
    dev_eth0=dev_get_by_name(&init_net,"eth0");
    dev_eth1=dev_get_by_name(&init_net,"eth1");
    handler_add_config();
    return 0;
}


/*Remove module and protocol handler*/
static void __exit hook_exit(void)
{

    printk("Hook module says Goodbye!!!!!\n");
    handler_remove();

}

module_init(hook_init);
module_exit(hook_exit);
MODULE_LICENSE("GPL");

person Ricardo    schedule 11.04.2012    source источник
comment
Пожалуйста, опубликуйте код. Отладка кода сложна, отладка без кода невозможна.   -  person Kristof Provost    schedule 11.04.2012
comment
Можете ли вы также добавить вывод ошибок ядра?   -  person Kristof Provost    schedule 11.04.2012
comment
Я пытаюсь проверить последнее сообщение ядра в /var/log, но ничего не говорю (по крайней мере, я его не нашел). Завтра я постараюсь выглядеть лучше, потому что компьютера, на котором я программировал, сейчас нет со мной. Если можно постараюсь добавить. Спасибо.   -  person Ricardo    schedule 11.04.2012
comment
Я не нахожу сообщение об ошибке.   -  person Ricardo    schedule 12.04.2012
comment
Попробуйте запустить без графического интерфейса (т.е. без X). Вы должны увидеть сообщение об ошибке на консоли, когда это произойдет. В качестве альтернативы изучите настройку последовательной консоли.   -  person Kristof Provost    schedule 12.04.2012
comment
Возможно ли, что если интерфейс выйдет из строя... ядро ​​рухнет? Поскольку модуль продолжает перенаправлять пакет на отключенный интерфейс.   -  person Ricardo    schedule 13.04.2012
comment
Если интерфейс не работает, я бы не ожидал, что пакеты будут продолжать поступать. Возможно, там есть состояние гонки, но это будет означать, что сбой очень редкий, а вы сказали, что это происходит очень часто.   -  person Kristof Provost    schedule 13.04.2012
comment
Я не знаю, что делать. Ядро не отправило сообщение об ошибке.   -  person Ricardo    schedule 16.04.2012


Ответы (3)


я думаю, что когда вы возвращаете return NET_RX_DROP;, это вызывает проблемы, потому что в хуках есть в основном возвращаемые типы...

Return Code          Meaning
  NF_DROP        Discard the packet.
  NF_ACCEPT      Keep the packet.
  NF_STOLEN      Forget about the packet.
  NF_QUEUE       Queue packet for userspace.
  NF_REPEAT      Call this hook function again.

& u возвращает NET_RX_DROP, поэтому попробуйте использовать NF_DROP.

person akp    schedule 23.11.2012

Посмотрите на af_x25.c в net/x25 для примера реализации того же самого, где они возвращают 0 даже при удалении. Кстати, не понял, почему вы увеличиваете skb-> len, когда все, что вы делаете, это меняете местами mac-адреса? То есть зачем в этом смысле пересобирать hdrs? Я что-то упустил здесь?

person smam    schedule 18.06.2014
comment
Хорошо, чтобы ответить на мой собственный вопрос, это необходимо, поскольку ETH HDR удаляется в eth_type_trans(), который будет вызываться драйвером устройства NIC в его процедуре Rx. - person smam; 18.06.2014

Вероятно, у вас происходит сбой, потому что вы освобождаете slngle-копию sk_buff, вызывая kfree_skb(skb);

person Biswajit Sadhu    schedule 01.09.2017