- 论坛徽章:
- 0
|
我用dummy做模板,实现两个网卡驱动,分别为dummy_bs,dummy_ss。其中,dummy_bs接收到上层数据后直接转发给dummy_ss,dummy_ss收到dummy_bs数据后,将数据包中的skb->dev改为自己的dev,然后调用netif_rx()提交给上层。这样让上层认为该数据是由dummy_ss接收到的。同理,dummy_ss收到上层数据也是直接转发给dummy_bs。
实验环境:VMware+Ubuntu10.04
内核版本:2.6.32.59+drm33.24- static struct task_struct *task_bs_recv;//创建一个接收线程
- static struct net_device *dev_dummy_bs;
- #define WIMAX_BS 0
- #define WIMAX_SS 1
- extern int put_buff(struct sk_buff *skb, int identity);//接收函数
- extern struct sk_buff *get_buff(int identity);//发送函数
- static int numdummies = 1;
- static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- int ret;
- //收到上层数据后,做如下处理
- skb_orphan(skb);
- skb->protocol = eth_type_trans(skb, dev);
- //处理完毕后,发送给dummy_ss
- ret = put_buff(skb, WIMAX_BS);
- if(0 == ret){
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
- }else{
- dev->stats.tx_dropped++;
- }
- return NETDEV_TX_OK;
- }
- //接收函数,实现为线程,负责接收dummy_ss发送给dummy_bs的数据包
- int bs_recv(void *data){
- int pkt_len;
- struct sk_buff *skb, *new;
- while(1){
- set_current_state(TASK_UNINTERRUPTIBLE);
- if(kthread_should_stop()) break;
- //取出dummy_ss发过来的数据
- skb = get_buff(WIMAX_BS);
- if(NULL != skb){
- //因为是dummy_ss发送过来的数据包,所以skb->dev原先指的是dev_dummy_ss,在这里将其改为
- //dev_dummy_bs,让上层认为该数据由dummy_bs接收并转发给上层
- skb->dev = dev_dummy_bs;
- if(likely(netif_rx(new) == NET_RX_SUCCESS)){
- dev_dummy_bs->stats.rx_packets++;
- dev_dummy_bs->stats.rx_bytes += skb->len;
- }else{
- dev_dummy_bs->stats.rx_dropped++;
- }
- }
- // printk("bs_recv running!\n");
- schedule_timeout(1000);
- }
- return 0;
- }
- static const struct net_device_ops dummy_netdev_ops = {
- .ndo_start_xmit = dummy_xmit,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = set_multicast_list,
- .ndo_set_mac_address = dummy_set_address,
- };
- static u32 always_on(struct net_device *dev)
- {
- return 1;
- }
- static const struct ethtool_ops dummy_ethtool_ops = {
- .get_link = always_on,
- .set_tso = ethtool_op_set_tso,
- .get_tx_csum = always_on,
- .get_sg = always_on,
- .get_rx_csum = always_on,
- };
- static void dummy_setup(struct net_device *dev)
- {
- ether_setup(dev);
- /* Initialize the device structure. */
- dev->netdev_ops = &dummy_netdev_ops;
- dev->ethtool_ops = &dummy_ethtool_ops;
- //dev->header_ops = ð_header_ops;
- dev->destructor = free_netdev;
- /* Fill in device structure with ethernet-generic values. */
- dev->tx_queue_len = 100;
- dev->flags |= IFF_NOARP;
- dev->flags |=IFF_PROMISC;
- dev->flags &= ~IFF_MULTICAST;
- random_ether_addr(dev->dev_addr);
- }
- static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
- {
- if (tb[IFLA_ADDRESS]) {
- if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
- return -EINVAL;
- if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
- return -EADDRNOTAVAIL;
- }
- return 0;
- }
- static struct rtnl_link_ops dummy_link_ops __read_mostly = {
- .kind = "dummy_bs",
- .setup = dummy_setup,
- .validate = dummy_validate,
- };
- /* Number of dummy devices to be set up by this module. */
- module_param(numdummies, int, 0);
- MODULE_PARM_DESC(numdummies, "Number of dummy_bs pseudo devices");
- //设备初始化
- static int __init dummy_init_one(void)
- {
- struct net_device *dev_dummy;
- int err;
- dev_dummy = alloc_netdev(0, "dummy_bs%d", dummy_setup);
- if (!dev_dummy)
- return -ENOMEM;
- dev_dummy_bs = dev_dummy;
- err = dev_alloc_name(dev_dummy, dev_dummy->name);
- if (err < 0)
- goto err;
- //netif_start_queue(dev_dummy);
- dev_dummy->rtnl_link_ops = &dummy_link_ops;
- err = register_netdevice(dev_dummy);
- if (err < 0)
- goto err;
- return 0;
- err:
- free_netdev(dev_dummy);
- return err;
- }
- static int __init dummy_init_module(void)
- {
- int i, err = 0;
- //线程初始化
- task_bs_recv = kthread_create(bs_recv, NULL, "bs_recv_task");
- if(IS_ERR(task_bs_recv)){
- printk("Unable to start kernel thread.\n");
- err = PTR_ERR(task_bs_recv);
- task_bs_recv = NULL;
- return err;
- }
- wake_up_process(task_bs_recv);
- rtnl_lock();
- err = __rtnl_link_register(&dummy_link_ops);
- for (i = 0; i < numdummies && !err; i++)
- err = dummy_init_one();
- if (err < 0)
- __rtnl_link_unregister(&dummy_link_ops);
- rtnl_unlock();
- return err;
- }
- static void __exit dummy_cleanup_module(void)
- {
- rtnl_link_unregister(&dummy_link_ops);
- if(task_bs_recv){
- kthread_stop(task_bs_recv);
- task_bs_recv = NULL;
- }
- }
- module_init(dummy_init_module);
- module_exit(dummy_cleanup_module);
- MODULE_LICENSE("GPL");
- MODULE_ALIAS_RTNL_LINK("dummy_bs");
复制代码 下图是静态路由设置:
下图是加载了dummy_bs和dummy_ss后的网络设备情况:
我用ping -c 5 192.168.4.155来做测试,下图是用tcpdump对dummy_bs0和dummy_ss0抓包的结果:
目前是tcpdump能抓到包,但是ping不通,不知道问题出在哪里。我自己觉得可能是在调用netif_rx()这里出错了,请问在调用netif_rx()之前还需要做些什么呢??
请各位高手帮帮忙,看看到底哪里做错了,谢谢! |
|