Can i use dev_queue_xmit()

From: K.Anantha Kiran
Date: Thu Apr 08 2004 - 14:26:24 EST



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