2013-01-06 66 views
2

我想从协议栈的IP层传递一个sk_buff数据包到我创建和注册的设备驱动程序。的设备驱动程序的代码如下:从IP层传递数据包到设备驱动程序

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

但该数据包是没有得到通过,当我试图加载这个测试模块系统显示致命的错误,并终止进程。你能建议我解决这个问题的好方法吗?

+0

你可以添加代码来检查''dev_queue_xmit''的返回值?它会在错误时返回一个负面的代码。也许你可以检查它是否实际排队传输缓冲区或抛出错误。 – Fred

+0

我已经更改了数据包传输的代码,dev_get_by_name(&init_net,“my_dev”);所以现在恐慌错误被删除,但是dev_queue_xmit()返回2是网络拥塞的消息。现在如何摆脱这一点,并从驱动程序捕获数据包? – user1707718

+0

我不确定。 ''dev_queue_xmit''被允许丢弃数据包,正是出于这个原因和更多。对此我没有足够的经验。 – Fred

回答

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()成功与否分配存储。你只是设置这个(skb)结构的dev和data参数。但是,如果您在文件/net/core/dev.c中看到函数dev_queue_xmit()的源代码,您将得到结果为什么您将返回值设置为正值,但这并不意味着数据包具有被传送。

所以首先尝试创建整个数据包作为它的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); 

变化所需的字段...

+1

这突出了在操纵它们时使用Linux的skbuff例程的重要性。如果你不这样做,那么内部管理变量就不会保持健全,你会*得到奇怪的错误。 – stsquad

相关问题