ethernet device xmit function is not gettting called

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
I wrote a module to create dummy ethernet device, the intention is to add it to a bridge and transmit modified packets. I get ethernet device created but its xmit function is not called when the bridge receives a packet.


I feel I have missed some information to register netdevice.

To add to bridge I did the following:
brctl addbr br0
brctl addif bro eth0
brctl addif br0 firsteth0
ifconfig etho 0.0.0.0
ifconfig bro 172.16.2.100 up

When I try to add IP address to firsteth0, I get a kernel panic!!
Can we give IP to dummy ethernet device?

Please help, I am given little time to complete this :( I am attaching the code for the dummy ethernet device.
-Ravi
#ifndef __KERNEL__
#   define __KERNEL__
#endif

#ifndef MODULE
#  define MODULE
#endif

#define DEVNAME "firsteth"

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>

#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/rtnetlink.h>
#include <linux/if_arp.h>

/* netfilters related */
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

#include <linux/in.h>
#include <linux/udp.h>
#include <net/ip.h>

int test_open(struct inode *,struct file *);
int test_release(struct inode *,struct file*);


struct test_struct{
	struct net_device *dev;
	char name[IFNAMSIZ];
	
};

struct file_operations test_fop={
llseek:  	NULL,
read:   	NULL,
write:  	NULL,
ioctl:  	NULL,
open:   	test_open,
release: 	test_release,
};


struct test_struct pTestStruct;

	
static int testdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct iphdr *oldiph;
	unsigned char tos=0;
	unsigned short df =0;
	unsigned char ttl;
	
	printk(KERN_INFO " In xmit function\n");
	oldiph = (skb->protocol==htons(ETH_P_IP))
	           ? (struct iphdr*)(skb->data+ETH_HLEN)
	           : NULL;
	
        tos = oldiph->tos;
        df = oldiph->frag_off;
        ttl = oldiph->ttl;
	printk(KERN_INFO"src IP: %x dst IP: %x , protocol %d \n",ntohl(oldiph->saddr), ntohl(oldiph->daddr),oldiph->protocol);
      
	return 0;
}

int test_open(struct inode *inode, struct file *filep)
{
	MOD_INC_USE_COUNT;
	return 0;
}

int test_release(struct inode *inode, struct file *filep)
{
	MOD_DEC_USE_COUNT;
	return 0;
}

int testdev_open(struct net_device *dev)
{
	MOD_INC_USE_COUNT;
	return 0;
}

int testdev_close(struct net_device *dev)
{
	unregister_netdev(dev);
	MOD_DEC_USE_COUNT;
	return 0;
}
//t test_ioctl(struct inode *inode, 
static int test_init_dev(struct net_device *dev)
{
	struct test_struct *c;

	printk(KERN_INFO "in test_init_dev\n");
	
	c = (struct test_struct *)dev->priv;
	if(!c)
		return -ENODEV;

	memset(c,0,sizeof(struct test_struct));
        c->dev = dev;			

       // ether_setup(dev);	
	dev->open  = testdev_open;
	dev->stop  = testdev_close;
	dev->hard_start_xmit        = testdev_xmit;
	dev->mtu   = ETH_DATA_LEN - sizeof(struct udphdr) - sizeof(struct iphdr) ;
        dev_init_buffers(dev);

	printk(KERN_INFO "completed test_init_dev\n");
	return 0;
}
			

int init_module(void)
{
	int result,i;
        struct net_device *tempDev;
	struct test_struct *temp_struct;
        char devname[25]; // Remove the hardcode

	
	 for(i=0;i<99;i++)
	 {
           sprintf(devname,"firseth%d",i);
           if(__dev_get_by_name(devname) == NULL)
	     break;
	 }
         if(i==100)
	      return -ENFILE;
         printk(KERN_INFO "********MACOUDP TUNNEL******\n");	 
	
	temp_struct = (struct test_struct *)kmalloc(sizeof(struct test_struct),GFP_KERNEL);
	if(!temp_struct)
	{
		printk(KERN_ERR "error in allocating memory\n");
		return -ENOMEM;
	}
	result = register_chrdev(244,"testdrv",&test_fop);
	if( result !=  0 ){
		printk(KERN_WARNING "test: cant get major\n");
		return result;
	}
	i=0;
        memset(temp_struct,0,sizeof(struct test_struct));
	//sprintf(temp_struct->name, DEVNAME "%d",i);
	tempDev = (struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL);
	if( !tempDev)
	{
		printk(KERN_ERR "kmalloc faied\n");
		return -ENOMEM;
	}
	memset(tempDev,0,sizeof(struct net_device));
	temp_struct->dev = tempDev;
	temp_struct->dev->priv = &pTestStruct;
	temp_struct->dev->next = NULL;
	temp_struct->dev->base_addr=0;
	temp_struct->dev->init = test_init_dev;
   
	temp_struct->dev->dev_addr[0]=0xFC;
	temp_struct->dev->dev_addr[1]=0xFC;
	temp_struct->dev->dev_addr[2]=0xA;
	temp_struct->dev->dev_addr[3]=0xB;
	temp_struct->dev->dev_addr[4]=0xC;
        temp_struct->dev->addr_len = ETH_ALEN;
	i = dev_alloc_name(temp_struct->dev,"firsteth%d");
	if(i < 0 )
	{
		printk(KERN_ERR "cant allocate device\n");
		return -ENODEV;
	}
        ether_setup(temp_struct->dev);	
	rtnl_lock();
	printk(KERN_INFO "Before calling register_netdevice\n");
	i = register_netdevice((temp_struct->dev));
	rtnl_unlock();
	memcpy(&pTestStruct,temp_struct,sizeof(struct test_struct));
	if( i < 0 ){
		printk(KERN_ERR "register netdevice failed\n");
                return -1;
	}
	return 0;
}

void cleanup_module(void)
{
        rtnl_lock();
	unregister_netdevice(pTestStruct.dev);
	rtnl_unlock();
	unregister_chrdev(244,"testdrv");
}







[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux