将数据包从IP层传递到设备驱动程序 [英] passing packets from IP layer to device driver

查看:65
本文介绍了将数据包从IP层传递到设备驱动程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将sk_buff数据包从协议栈的IP层传递到我创建并注册的设备驱动程序中.设备驱动程序的代码如下:

I am trying to pass a sk_buff packet from IP layer of the protocol stack to a device driver which I have created and registered. The code for the device driver is as follows :

    #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()函数传递数据包.代码如下:

then after loading this module and using "ifconfig " to assign IP address to it, I have tried to pass a packet using dev_queue_xmit() function. the code is as fllows:

   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);

但是数据包没有通过,当我尝试加载此测试模块时,系统显示致命错误并终止进程.您能建议我一个解决此问题的好方法吗?

but the packet is not getting passed and when I am trying to load this testing module the system shows fatal error and terminate the process. Can you suggest me a good approach to solve this?

推荐答案

如代码所示,您只是将skb分配为

As your code is showing that you are just allocating the skb as

   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()的源代码,您将得到为什么您要获得返回值的结果是肯定的,但这并不意味着数据包已被传输.

so there is no checking that alloc_skb() allocate the storage successfully or not. And you are just setting the dev and data parameter of this(skb) structure. But if you see the source code of the function dev_queue_xmit() in the file /net/core/dev.c you will get the result why u are getting return value as positive but it doesn't mean the packet has been transmitted.

因此,首先尝试创建整个数据包作为其UDP/TCP报头,IP报头,数据作为协议建议.然后将skb的字段设置为这个全新创建的数据包. 现在尝试发送它,您将获得结果.

so first of all try to create the whole packet as its UDP/TCP header, IP Header,data as protocol suggest. and then set the fields of the skb to this whole new created packet. Now try to send it you will get result.

供参考try->

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);

根据需要更改字段...

change the fields as required...

这篇关于将数据包从IP层传递到设备驱动程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆