2

プロトコルスタックのIP層から作成して登録したデバイスドライバーにsk_buffパケットを渡そうとしています。デバイスドライバのコードは次のとおりです。

    #include<linux/module.h>
    #include<linux/netdevice.h>
    #include<linux/kernel.h>
    #include<linux/skbuff.h>
    #include<linux/pci.h>
    #include<linux/interrupt.h>
    struct net_device *my_dev;
    static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
    {
           printk(KERN_INFO "I got a packet");    
           return NETDEV_TX_OK;
    }
    static int veth_open(struct net_device *dev)
    {

                  memcpy(dev->dev_addr, "\0ABCD0", ETH_ALEN);
                  netif_start_queue(dev);

                  return 0;
    }


    int veth_close(struct net_device *dev)
    {
           printk("releasing mydev\n");
           netif_stop_queue(dev);
           return 0;
    }

    int veth_dev_init(struct net_device *dev)
    {
           printk("initialising\n");
           return 0;
    }

    static struct net_device_ops veth_ops = {

     .ndo_init         = veth_dev_init,
     .ndo_open         = veth_open,
     .ndo_stop         = veth_close,
     .ndo_start_xmit   = veth_xmit,

       };
   int veth_init()
   {
   int ret,i;
   my_dev = alloc_netdev(sizeof(struct net_device), "my_dev", ether_setup);
   if (my_dev == NULL)
    return -ENOMEM; 
   my_dev->netdev_ops = &veth_ops;
       register_netdev(my_dev);
       return 0;
   }
   void veth_exit()
   {
    unregister_netdev(my_dev);
    free_netdev(my_dev);
   }

   module_init(veth_init);
   module_exit(veth_exit);

次に、このモジュールをロードし、「ifconfig」を使用してIPアドレスを割り当てた後、dev_queue_xmit()関数を使用してパケットを渡そうとしました。コードは次のとおりです。

   struct sk_buff *skb;
   void generate_send()
   {
   skb=alloc_skb(skb,2);
   skb->data[0]='m';//just to check
       skb->dev="my_dev";
       dev_queue_xmit(skb);
   }
   static int testing_init(void)
   {
   //time=4;    
   generate_send();

   return 0;    
   }
   static void testing_exit(void)
   {
printk(KERN_INFO "Goodbye, world 2\n");
   }
   module_init(testing_init);
   module_exit(testing_exit);

しかし、パケットが渡されておらず、このテストモジュールをロードしようとすると、システムに致命的なエラーが表示され、プロセスが終了します。これを解決するための良いアプローチを教えていただけますか?

4

1 に答える 1

1

あなたのコードはあなたがちょうどskbを次のように割り当てていることを示しているので

   struct sk_buff *skb;
   void generate_send()
   {
   skb=alloc_skb(skb,2);
   skb->data[0]='m';//just to check
       skb->dev="my_dev";
       dev_queue_xmit(skb);
   }

したがって、alloc_skb()がストレージを正常に割り当てるかどうかのチェックはありません。そして、this(skb)構造のdevおよびdataパラメーターを設定しているだけです。ただし、ファイル/net/core/dev.cに関数dev_queue_xmit()のソースコードが表示されている場合は、uが正の値を返している理由がわかりますが、パケットが送信されたことを意味するわけではありません。

したがって、まず最初に、プロトコルが示唆するように、UDP / TCPヘッダー、IPヘッダー、データとしてパケット全体を作成してみてください。次に、skbのフィールドをこの新しく作成されたパケットに設定します。今それを送ってみてくださいあなたは結果を得るでしょう。

参考のために試してみてください->

skb = alloc_skb(len, GFP_ATOMIC);
if (!skb)
        return;

skb_put(skb, len);

skb_push(skb, sizeof(*udph));
skb_reset_transport_header(skb);
udph = udp_hdr(skb);
udph->source = htons(....);
udph->dest = htons(...);
udph->len = htons(udp_len);
udph->check = 0;
udph->check = csum_tcpudp_magic(local_ip,
                                remote_ip,
                                udp_len, IPPROTO_UDP,
                                csum_partial(udph, udp_len, 0));

if (udph->check == 0)
        udph->check = CSUM_MANGLED_0;

skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb);
iph = ip_hdr(skb);

/* iph->version = 4; iph->ihl = 5; */
put_unaligned(0x45, (unsigned char *)iph);
iph->tos      = 0;
put_unaligned(htons(ip_len), &(iph->tot_len));
iph->id       = htons(atomic_inc_return(&ip_ident));
iph->frag_off = 0;
iph->ttl      = 64;
iph->protocol = IPPROTO_UDP;
iph->check    = 0;
put_unaligned(local_ip, &(iph->saddr));
put_unaligned(remote_ip, &(iph->daddr));
iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);

eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
skb->protocol = eth->h_proto = htons(ETH_P_IP);
memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
memcpy(eth->h_dest, remote_mac, ETH_ALEN);

skb->dev = dev;


dev_queue_xmit(skb);

必要に応じてフィールドを変更します。

于 2013-01-08T10:53:47.597 に答える