We wrote a KernelModule for fetching internet packets through certain interface, and reforwarding them through another interface of our choice based on IP-address,Port values of packet. This module is working fine for less rate of traffic(< 200 Mbps) , But same module is dropping some of the packets(4 lakhs out of 10 lakhs) for highier speeds(> 200Mbps).Function *dev_queue_xmit()* in the kernel module, is returning NET_XMIT_DROP for dropped packets.This is due to the function call *q->enqueue(skb,q)* in dev_queue_xmit().What might be the reason for that return value. Is it the problem with s/w or h/w ? We are using Linux-2.4 and Gigabyte Eth cards.And we are genrating traffic by resending same packet for many times.How can we figure out the location of problem. We are attaching our module file. I will be very thankful to your help. Thanks in advance, K.AnanthaKiran
#define MODULE #define __KERNEL__ #include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/in.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/icmp.h> #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/if_arp.h> #include <linux/if_ether.h> #include <linux/if_packet.h> #include <asm-i386/types.h> /* This is the structure we shall use to register our function */ static struct nf_hook_ops nfho; /* Initialisation routine */ int hook_func(unsigned int hooknum, struct sk_buff **skbuff, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct sk_buff* skb=*skbuff; struct iphdr *iph; struct tcphdr *th; struct ethhdr *ether; unsigned char ea1[7] = {0x00,0x07,0xe9,0x24,0x71,0x15}; unsigned int devno; static int cnt[3]; struct net_device *dev; u32 saddr,daddr; u16 source,dest; /* * Checking whether skb and IP_Header are not null */ if (!skb ) return NF_ACCEPT; if (!(skb->nh.iph)) return NF_ACCEPT; if(strcmp(in->name,"eth0") != 0) return NF_ACCEPT; /* * Checking whether Packet is from Ethernet device or not * Doubt: What is the better place to put it ! */ if(skb->dev->type!=ARPHRD_ETHER) return NF_ACCEPT; iph = skb->nh.iph; /* * Checking whether packet is TCP or UDP packet * otherwise ignore it */ if ( iph -> protocol != IPPROTO_TCP && iph -> protocol != IPPROTO_UDP ) return NF_ACCEPT; th = (struct tcphdr *) (skb->data + (skb->nh.iph->ihl * 4) ) ; // Getting source and destination ip addresses from ip header saddr = iph->saddr; daddr = iph->daddr; // Getting source and destination ports from TCP header source = th->source; dest = th->dest; // Computing Hash devno = (saddr + daddr + source + dest) % 2; // Starting address of ethernet frame if((ether = (struct ethhdr *)skb->mac.ethernet)== NULL) return NF_ACCEPT; // Selecting device switch(devno) { case 0: if( (dev = dev_get_by_name("eth1")) == NULL) return NF_ACCEPT; memcpy(ether->h_source,dev->dev_addr,ETH_ALEN); break; case 1: if( (dev = dev_get_by_name("eth2")) == NULL) return NF_ACCEPT; memcpy(ether->h_source,dev->dev_addr,ETH_ALEN); break; case 2: if( (dev = dev_get_by_name("eth1")) == NULL) return NF_ACCEPT; memcpy(ether->h_source,dev->dev_addr,ETH_ALEN); break; } //Setting Destination as ea1 memcpy(ether->h_dest,ea1,ETH_ALEN); skb->data = (unsigned char *)skb->mac.ethernet; skb->len += ETH_HLEN; // Setting it as outgoing packet skb->pkt_type=PACKET_OUTGOING; // changing the dev to output device we need skb->dev = dev; // Transmitting the packet if((cnt[2]=dev_queue_xmit(skb))==NET_XMIT_SUCCESS) cnt[0]++; else if(cnt[2] != 1) printk("%d ",cnt[2]); cnt[1]++; if((cnt[1]%100000)==0) printk("%d %d\n",cnt[0],cnt[1]); return NF_STOLEN; } int init_module() { /* Fill in our hook structure */ nfho.hook = (nf_hookfn *)hook_func; /* Handler function */ nfho.hooknum = NF_IP_PRE_ROUTING; /* First hook for IPv4 */ nfho.pf = PF_INET; nfho.priority = NF_IP_PRI_FIRST; /* Make our function first */ nf_register_hook(&nfho); return 0; } /* Cleanup routine */ void cleanup_module() { nf_unregister_hook(&nfho); }