Netdev List
 help / color / mirror / Atom feed
* Re: [PATCHES] TX batching
From: Jeff Garzik @ 2007-09-23 18:19 UTC (permalink / raw)
  To: hadi
  Cc: David Miller, krkumar2, johnpol, herbert, kaber, shemminger,
	jagana, Robert.Olsson, rick.jones2, xma, gaagaan, netdev, rdreier,
	peter.p.waskiewicz.jr, mcarlson, mchan, general, kumarkr, tgraf,
	randy.dunlap, sri
In-Reply-To: <1190569987.4256.52.camel@localhost>

jamal wrote:
> More patches to follow  - i didnt want to overload people by dumping 
> too many patches. Most of these patches below are ready to go; some are
> need some testing and others need a little porting from an earlier
> kernel: 
> - tg3 driver (tested and works well, but dont want to send 
> - tun driver
> - pktgen
> - netiron driver
> - e1000 driver


You should post at least a couple driver patches to see how its used on 
Real Hardware(tm)...   :)

The batching idea has always seemed like a no-brainer to me, so I'm very 
interested to see how this turns out.

	Jeff



^ permalink raw reply

* Re: pktgen question
From: jamal @ 2007-09-23 18:18 UTC (permalink / raw)
  To: Steve Wise; +Cc: Evgeniy Polyakov, netdev, Robert Olsson
In-Reply-To: <46F6A887.1030301@opengridcomputing.com>

On Sun, 2007-23-09 at 12:55 -0500, Steve Wise wrote:

> Its a hack that breaks cxgb3 because cxgb3 uses the skb->cb area for 
> each skb passed down.  So cxgb3 is at fault then?  IE a driver cannot 
> use the skb->cb field if the users count is > 1?  Or maybe a driver can 
> _never_ use the cb field?

any layer can use the cb structure whichever way they wish. There are
violations, e.g:
the vlan code also uses the cb field to pass vlan details for hardware
acceleration. How does pktgen affect it though, clone() will just copy
the cb field and pktgen doesnt touch it.
In retrospect, pktgen may have to use clone - ccing Robert Olsson.

cheers,
jamal


^ permalink raw reply

* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently runsoftirqnetwork code on SMP
From: jamal @ 2007-09-23 18:07 UTC (permalink / raw)
  To: john ye; +Cc: David Miller, netdev, kuznet, pekkas, jmorris, kaber, iceburgue
In-Reply-To: <000501c7fdf8$c7f7c8d0$d6ddfea9@JOHNYE1>

[-- Attachment #1: Type: text/plain, Size: 258 bytes --]

John,
It will NEVER be an acceptable solution as long as you have re-ordering.
I will look at it - but i have to run out for now. In the meantime,
I have indented it for you to be in proper kernel format so others can
also look it. Attached.

cheers,
jamal


[-- Attachment #2: bs.c --]
[-- Type: text/x-csrc, Size: 20712 bytes --]

/*
* BOTTOM_SOFTIRQ_NET
* An implementation of bottom softirq concurrent execution on SMP
* This is implemented by splitting current net softirq into top half
* and bottom half, dispatch the bottom half to each cpu's workqueue.
* Hopefully, it can raise the throughput of NIC when running iptalbes
* with heavy softirq load on SMP machine.
*               
*  Version:    $Id: bs_smp.c, v 2.6.13-15 for kernel 2.6.13-15-smp
*   
*  Authors:    John Ye & QianYu Ye, 2007.08.27
*/

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/backing-dev.h>

#include <asm/uaccess.h>

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/romfs_fs.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include <linux/vfs.h>
#include <linux/delay.h>
#include <linux/bio.h>
#include <linux/aio.h>
#include <asm/uaccess.h>

//for debug_syscalls
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/list.h>

#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/debugreg.h>
#include <asm/ldt.h>
#include <asm/desc.h>

#include <linux/swap.h>
//#include <linux/interrupt.h>
#include <asm/i387.h>
#include <asm/debugreg.h>
#include <asm/ldt.h>
#include <asm/desc.h>

#include <linux/swap.h>

#include <linux/init.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/major.h>
#include <linux/pm.h>
#include <linux/proc_fs.h>
#include <linux/kmod.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>

#include <linux/config.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <net/tcp.h>
#include <net/inet_common.h>
#include <linux/ipsec.h>
#include <asm/unaligned.h>

#include <asm/system.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/config.h>

#include <linux/net.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>

#include <net/snmp.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/arp.h>
#include <net/icmp.h>
#include <net/raw.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>
#include <net/xfrm.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
#include <net/route.h>"
#include <linux/inetdevice.h>

static spinlock_t *p_ptype_lock;
static struct list_head *p_ptype_base;	/* 16 way hashed list */

int (*Pip_options_rcv_srr) (struct sk_buff * skb);
int (*Pnf_rcv_postxfrm_nonlocal) (struct sk_buff * skb);
struct ip_rt_acct *ip_rt_acct;
struct ipv4_devconf *Pipv4_devconf;

#define ipv4_devconf (*Pipv4_devconf)
//#define ip_rt_acct Pip_rt_acct
#define ip_options_rcv_srr Pip_options_rcv_srr
#define nf_rcv_postxfrm_nonlocal Pnf_rcv_postxfrm_nonlocal
//extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
//extern int ip_options_rcv_srr(struct sk_buff *skb);
static struct workqueue_struct **Pkeventd_wq;
#define keventd_wq (*Pkeventd_wq)

#define INSERT_CODE_HERE

static inline int ip_rcv_finish(struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	struct iphdr *iph = skb->nh.iph;
	int err;

/*
* Initialise the virtual path cache for the packet. It describes
* how the packet travels inside Linux networking.
*/
	if (skb->dst == NULL) {
		if ((err =
		     ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
				    dev))) {
			if (err == -EHOSTUNREACH)
				IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
			goto drop;
		}
	}

	if (nf_xfrm_nonlocal_done(skb))
		return nf_rcv_postxfrm_nonlocal(skb);

#ifdef CONFIG_NET_CLS_ROUTE
	if (skb->dst->tclassid) {
		struct ip_rt_acct *st = ip_rt_acct + 256 * smp_processor_id();
		u32 idx = skb->dst->tclassid;
		st[idx & 0xFF].o_packets++;
		st[idx & 0xFF].o_bytes += skb->len;
		st[(idx >> 16) & 0xFF].i_packets++;
		st[(idx >> 16) & 0xFF].i_bytes += skb->len;
	}
#endif

	if (iph->ihl > 5) {
		struct ip_options *opt;

/* It looks as overkill, because not all
   IP options require packet mangling.
   But it is the easiest for now, especially taking
   into account that combination of IP options
   and running sniffer is extremely rare condition.
                                      --ANK (980813)
*/

		if (skb_cow(skb, skb_headroom(skb))) {
			IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
			goto drop;
		}
		iph = skb->nh.iph;

		if (ip_options_compile(NULL, skb))
			goto inhdr_error;

		opt = &(IPCB(skb)->opt);
		if (opt->srr) {
			struct in_device *in_dev = in_dev_get(dev);
			if (in_dev) {
				if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
					if (IN_DEV_LOG_MARTIANS(in_dev)
					    && net_ratelimit())
						printk(KERN_INFO
						       "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
						       NIPQUAD(iph->saddr),
						       NIPQUAD(iph->daddr));
					in_dev_put(in_dev);
					goto drop;
				}
				in_dev_put(in_dev);
			}
			if (ip_options_rcv_srr(skb))
				goto drop;
		}
	}

	return dst_input(skb);

      inhdr_error:
	IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
      drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}

#define CONFIG_BOTTOM_SOFTIRQ_SMP
#define CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL

#ifdef CONFIG_BOTTOM_SOFTIRQ_SMP

#ifdef COMMENT____________
/*
[PATCH: 2.6.13-15-SMP 1/2] network: concurrently run softirq network 
code on SMP Bottom Softirq Implementation. John Ye, 2007.08.27

Why this patch:
Make kernel be able to concurrently execute softirq's net code on SMP system.
Take full advantages of SMP to handle more packets and greatly raises 
NIC throughput.
The current kernel's net packet processing logic is:
1) The CPU which handles a hardirq must be executing its related softirq.
2) One softirq instance(irqs handled by 1 CPU) can't be executed on more 
than 2 CPUs at the same time.
The limitation make kernel network be hard to take the advantages of SMP.

How this patch:
It splits the current softirq code into 2 parts: the cpu-sensitive top half,
and the cpu-insensitive bottom half, then make bottom half(calld BS) be
executed on SMP concurrently.
The two parts are not equal in terms of size and load. Top part has 
constant code size(mainly, in net/core/dev.c and NIC drivers), while 
bottom part involves netfilter(iptables) whose load varies very much. 
An iptalbes with 1000 rules to match will make the bottom part's load 
be very high. So, if the bottom part softirq can be randomly distributed 
to processors and run concurrently on them, the network will gain much 
more packet handling capacity, network throughput will be be increased
remarkably.

Where useful:
It's useful on SMP machines that meet the following 2 conditions:
1) have high kernel network load, for example, running iptables with 
thousands of rules, etc).
2) have more CPUs than active NICs, e.g. a 4 CPUs machine with 2 NICs).
On these system, with the increase of softirq load, some CPUs will be idle
while others(number is equal to # of NIC) keeps busy.
IRQBALANCE will help, but it only shifts IRQ among CPUS, makes no 
softirq concurrency.
Balancing the load of each cpus will not remarkably increase network 
speed.

Where NOT useful:
If the bottom half of softirq is too small(without running iptables), or 
the network is too idle, BS patch will not be seen to have visible effect. 
But It has no negative affect either.
User can turn on/off BS functionality by /proc/sys/net/bs_enable switch.

How to test:
On a linux box, run iptables, add 2000 rules to table filter & table nat to 
simulate huge softirq load. Then, open 20 ftp sessions to download big file. 
On another machine(who use this test machine as gateway), open 20 more ftp 
download sessions. Compare the speed, without BS enabled, and with BS 
enabled.
cat /proc/sys/net/bs_enable. this is a switch to turn on/off BS
cat /proc/sys/net/bs_status. this shows the usage of each CPUs
Test shown that when bottom softirq load is high, the network throughput 
can be nearly doubled on 2 CPUs machine. hopefully it may be quadrupled on 
a 4 cpus linux box.

Bugs:
It will NOT allow hotplug CPU.
It only allows incremental CPUs ids, starting from 0 to num_online_cpus().
for example, 0,1,2,3 is OK. 0,1,8,9 is KO.

Some considerations in the future:
1) With BS patch, the irq balance code on arch/i386/kernel/io_apic.c 
seems no need any more, at least not for network irq.
2) Softirq load will become very small. It only run the top half of 
old softirq, which is much less expensive than bottom half
---the netfilter program.
To let top softirq process more packets, can these 3 network parameters 
be given a larger value?
   extern int netdev_max_backlog = 1000;
   extern int netdev_budget = 300;
   extern int weight_p = 64;
3) Now, BS are running on built-in keventd thread, we can create new 
workqueues to let it run on?

Signed-off-by: John Ye (Seeker) <[email]johny@webizmail.com[/email]>
*/
#endif

#define BS_USE_PERCPU_DATA
struct cpu_stat {
	unsigned long irqs;	//total irqs
	unsigned long dids;	//I did,
	unsigned long others;
	unsigned long works;
};
#define BS_CPU_STAT_DEFINED

static int nr_cpus = 0;

#ifdef BS_USE_PERCPU_DATA
static DEFINE_PER_CPU(struct sk_buff_head, bs_cpu_queues);	// cacheline_aligned_in_smp;
static DEFINE_PER_CPU(struct work_struct, bs_works);
//static DEFINE_PER_CPU(struct cpu_stat, bs_cpu_status);
struct cpu_stat bs_cpu_status[NR_CPUS] = { {0,}, {0,}, };
#else
#define NR_CPUS  8
static struct sk_buff_head bs_cpu_queues[NR_CPUS];
static struct work_struct bs_works[NR_CPUS];
static struct cpu_stat bs_cpu_status[NR_CPUS];
#endif

int bs_enable = 1;
static int ip_rcv1(struct sk_buff *skb, struct net_device *dev)
{
	return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
			    ip_rcv_finish, nf_hook_input_cond(skb));
}

static void bs_func(void *data)
{
	int flags, num, cpu;
	struct sk_buff *skb;
	struct work_struct *bs_works;
	struct sk_buff_head *q;
	cpu = smp_processor_id();

#ifdef BS_USE_PERCPU_DATA
	bs_works = &per_cpu(bs_works, cpu);
	q = &per_cpu(bs_cpu_queues, cpu);
#else
	bs_works = &bs_works[cpu];
	q = &bs_cpu_queues[cpu];
#endif

	local_bh_disable();
      restart:
	num = 0;
	while (1) {
		spin_lock_irqsave(&q->lock, flags);
		skb = __skb_dequeue(q);
		spin_unlock_irqrestore(&q->lock, flags);
		if (!skb)
			break;
		num++;
//local_bh_disable();
		ip_rcv1(skb, skb->dev);
//__local_bh_enable(); //sub_preempt_count(SOFTIRQ_OFFSET - 1);
	}

	bs_cpu_status[cpu].others += num;
//if(num > 2) printk("%d %d\n", num, cpu);
	if (num > 0) {
		goto restart;
	}

	__local_bh_enable();	//sub_preempt_count(SOFTIRQ_OFFSET - 1);
	bs_works->func = 0;

	return;
}

/* COPY_IN_START_FROM kernel/workqueue.c */
struct cpu_workqueue_struct {

	spinlock_t lock;

	long remove_sequence;	/* Least-recently added (next to run) */
	long insert_sequence;	/* Next to add */

	struct list_head worklist;
	wait_queue_head_t more_work;
	wait_queue_head_t work_done;

	struct workqueue_struct *wq;
	task_t *thread;

	int run_depth;		/* Detect run_workqueue() recursion depth */
} ____cacheline_aligned;

struct workqueue_struct {
	struct cpu_workqueue_struct cpu_wq[NR_CPUS];
	const char *name;
	struct list_head list;	/* Empty if single thread */
};
/* COPY_IN_END_FROM kernel/worqueue.c */

extern struct workqueue_struct *keventd_wq;

/* Preempt must be disabled. */
static void __queue_work(struct cpu_workqueue_struct *cwq,
			 struct work_struct *work)
{
	unsigned long flags;

	spin_lock_irqsave(&cwq->lock, flags);
	work->wq_data = cwq;
	list_add_tail(&work->entry, &cwq->worklist);
	cwq->insert_sequence++;
	wake_up(&cwq->more_work);
	spin_unlock_irqrestore(&cwq->lock, flags);
}

#endif //CONFIG_BOTTOM_SOFTIRQ_SMP

/*
* Main IP Receive routine.
*/
/* hard irq are in CPU1, why this get called from CPU0?, __do_IRQ() did so?
*
*/
int REP_ip_rcv(struct sk_buff *skb, struct net_device *dev,
	       struct packet_type *pt)
{
	struct iphdr *iph;

/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
	if (skb->pkt_type == PACKET_OTHERHOST)
		goto drop;

	IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES);

	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
		IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
		goto out;
	}

	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
		goto inhdr_error;

	iph = skb->nh.iph;

/*
* RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
*
* Is the datagram acceptable?
*
* 1. Length at least the size of an ip header
* 2. Version of 4
* 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]
* 4. Doesn't have a bogus length
*/

	if (iph->ihl < 5 || iph->version != 4)
		goto inhdr_error;

	if (!pskb_may_pull(skb, iph->ihl * 4))
		goto inhdr_error;

	iph = skb->nh.iph;

	if (ip_fast_csum((u8 *) iph, iph->ihl) != 0)
		goto inhdr_error;

	{
		__u32 len = ntohs(iph->tot_len);
		if (skb->len < len || len < (iph->ihl << 2))
			goto inhdr_error;

/* Our transport medium may have padded the buffer out. Now we know it
* is IP we can trim to the true length of the frame.
* Note this now means skb->len holds ntohs(iph->tot_len).
*/
		if (pskb_trim_rcsum(skb, len)) {
			IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
			goto drop;
		}
	}

#ifdef CONFIG_BOTTOM_SOFTIRQ_SMP

	if (!nr_cpus)
		nr_cpus = num_online_cpus();

	if (bs_enable && nr_cpus > 1 && iph->protocol != IPPROTO_ICMP) {
		//if(bs_enable && iph->protocol == IPPROTO_ICMP) { //test on icmp first
		unsigned int flags, cur, cpu;
		struct work_struct *bs_works;
		struct sk_buff_head *q;

		cur = smp_processor_id();

		bs_cpu_status[cur].irqs++;

		if (!nr_cpus) {
			nr_cpus = num_online_cpus();
		}
//random distribute
		cpu = (bs_cpu_status[cur].irqs % nr_cpus);
		if (cpu == cur) {
			bs_cpu_status[cpu].dids++;
			return ip_rcv1(skb, dev);
		}
#ifdef BS_USE_PERCPU_DATA
		q = &per_cpu(bs_cpu_queues, cpu);
#else
		q = &bs_cpu_queues[cpu];
#endif

		if (!q->next) {	// || skb_queue_len(q) == 0 ) {
			skb_queue_head_init(q);
		}

#ifdef BS_USE_PERCPU_DATA
		bs_works = &per_cpu(bs_works, cpu);
#else
		bs_works = &bs_works[cpu];
#endif
		spin_lock_irqsave(&q->lock, flags);
		__skb_queue_tail(q, skb);
		spin_unlock_irqrestore(&q->lock, flags);

		if (!bs_works->func) {
			INIT_WORK(bs_works, bs_func, q);
			bs_cpu_status[cpu].works++;
			preempt_disable();
			__queue_work(keventd_wq->cpu_wq + cpu, bs_works);
			preempt_enable();
		}
	} else {
		int cpu = smp_processor_id();
		bs_cpu_status[cpu].irqs++;
		bs_cpu_status[cpu].dids++;
		return ip_rcv1(skb, dev);
	}
	return 0;
#else
	return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
			    ip_rcv_finish, nf_hook_input_cond(skb));
#endif //CONFIG_BOTTOM_SOFTIRQ_SMP

      inhdr_error:
	IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
      drop:
	kfree_skb(skb);
      out:
	return NET_RX_DROP;
}

//for standard patch, those lines should be moved into ../../net/sysctl_net.c

/* COPY_OUT_START_TO net/sysctl_net.c */
#ifdef CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL
#if !defined(BS_CPU_STAT_DEFINED)
struct cpu_stat {
	unsigned long irqs;	//total irqs
	unsigned long dids;	//I did,
	unsigned long others;
	unsigned long works;
};
#endif
extern struct cpu_stat bs_cpu_status[NR_CPUS];

extern int bs_enable;
/* COPY_OUT_END_TO net/sysctl_net.c */

static ctl_table bs_ctl_table[] = {

/* COPY_OUT_START_TO net/sysctl_net.c */
	{
	 .ctl_name = 99,
	 .procname = "bs_status",
	 .data = &bs_cpu_status,
	 .maxlen = sizeof(bs_cpu_status),
	 .mode = 0644,
	 .proc_handler = &proc_dointvec,
	 }
	,

	{
	 .ctl_name = 99,
	 .procname = "bs_enable",
	 .data = &bs_enable,
	 .maxlen = sizeof(int),
	 .mode = 0644,
	 .proc_handler = &proc_dointvec,
	 },
/* COPY_OUT_END_TO net/net_sysctl.c */

	{0,},
};

static ctl_table bs_sysctl_root[] = {
	{
	 .ctl_name = CTL_NET,
	 .procname = "net",
	 .mode = 0555,
	 .child = bs_ctl_table,
	 },
	{0,},
};

struct ctl_table_header *bs_sysctl_hdr;
register_bs_sysctl(void)
{
	bs_sysctl_hdr = register_sysctl_table(bs_sysctl_root, 0);
	return 0;
}

unregister_bs_sysctl(void)
{
	unregister_sysctl_table(bs_sysctl_hdr);
}

#endif //CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL

#if 1
seeker_init()
{
	int i;
	if (nr_cpus == 0)
		nr_cpus = num_online_cpus();
	register_bs_sysctl();
}

seeker_exit()
{
	unregister_bs_sysctl();
	bs_enable = 0;
	msleep(1000);
	flush_scheduled_work();
	msleep(1000);
	printk("......exit...........\n");
}
#endif

/*--------------------------------------------------------------------------
*/
struct packet_type *dev_find_pack(int type)
{
	struct list_head *head;
	struct packet_type *pt1;

	spin_lock_bh(p_ptype_lock);

	head = &p_ptype_base[type & 15];

	list_for_each_entry(pt1, head, list) {
		printk("pt1: %x\n", pt1->type);
		if (pt1->type == htons(type)) {
			printk("FOUND\n");
			goto out;
		}
	}

	pt1 = 0;
	printk("dev_remove_pack: %p not found. type %x %x %x\n", pt1, type,
	       ETH_P_IP, htons(ETH_P_IP));
      out:
	spin_unlock_bh(p_ptype_lock);
	return pt1;
}

static char system_map[128] = "/boot/System.map-";
static unsigned long sysmap_size;
static char *sysmap_buf;

unsigned long sysmap_name2addr(char *name)
{
	char *cp, *dp;
	unsigned long addr;
	int len, n;

	if (!sysmap_buf)
		return 0;
	if (!name || !name[0])
		return 0;
	n = strlen(name);
	for (cp = sysmap_buf;;) {
		cp = strstr(cp, name);
		if (!cp)
			return 0;

		for (dp = cp; *dp && *dp != '\n' && *dp != ' ' && *dp != '\t';
		     dp++) ;

		len = dp - cp;
		if (len < n)
			goto cont;
		if (cp > sysmap_buf && cp[-1] != ' ' && cp[-1] != '\t') {
			goto cont;
		}
		if (len > n) {
			goto cont;
		}
		break;
	      cont:
		if (*dp == 0)
			break;
		cp += (len + 1);
	}

	cp -= 11;
	if (cp > sysmap_buf && cp[-1] != '\n') {
		printk("_ERROR_ in name2addr cp = %p base %p\n", cp,
		       sysmap_buf);
		return 0;
	}
	sscanf(cp, "%x", &addr);
	printk("%s -> %p\n", name, addr);

	return addr;
}

char *kas_init()
{
	struct file *fp;
	int i;
	long addr;
	struct kstat st;
	mm_segment_t old_fs;

	//printk("system #%s#%s#%s#%s\n", system_utsname.sysname, system_utsname.nodename, system_utsname.release, system_utsname.version);
	strcat(system_map, system_utsname.release);
	printk("System.map is %s\n", system_map);

	old_fs = get_fs();
	set_fs(get_ds());	//systemp_map is __user variable
	i = vfs_stat(system_map, &st);
	set_fs(old_fs);

	//sysmap_size = 1024*1024; //error
	sysmap_size = st.size + 32;
	fp = filp_open(system_map, O_RDONLY, FMODE_READ);

	if (!fp)
		return 1;
	sysmap_buf = vmalloc(sysmap_size);
	if (!sysmap_buf)
		return 2;
	i = kernel_read(fp, 0, sysmap_buf, sysmap_size);
	if (i <= 0) {
		filp_close(fp, 0);
		vfree(sysmap_buf);
		sysmap_buf = 0;
		return 3;
	}
	sysmap_size = i;
	*(int *)&sysmap_buf[i] = 0;
	filp_close(fp, 0);
	//sysmap_symbol2addr = sysmap_name2addr;

	p_ptype_lock = sysmap_name2addr("ptype_lock");
	p_ptype_base = sysmap_name2addr("ptype_base");
	/*
	   int (*Pip_options_rcv_srr)(struct sk_buff *skb);
	   int (*Pnf_rcv_postxfrm_nonlocal)(struct sk_buff *skb);
	   struct ip_rt_acct *ip_rt_acct;
	   struct ipv4_devconf *Pipv4_devconf;
	 */
	Pkeventd_wq = sysmap_name2addr("keventd_wq");
	//keventd_wq = *(long *)&keventd_wq;

	Pip_options_rcv_srr = sysmap_name2addr("ip_options_rcv_srr");
	Pnf_rcv_postxfrm_nonlocal =
	    sysmap_name2addr("nf_rcv_postxfrm_nonlocal");
	ip_rt_acct = sysmap_name2addr("ip_rt_acct");
	Pipv4_devconf = sysmap_name2addr("ipv4_devconf");
	printk("lock = %p base = %p\n", p_ptype_lock, p_ptype_base);
	vfree(sysmap_buf);

}

struct packet_type *ip_handler;
static int __init init()
{
	struct packet_type *pt;
	kas_init();
	pt = dev_find_pack(ETH_P_IP);
	if (!pt)
		return -1;
//printk("pt %p func ip_rcv %p should be %p\n", pt, pt->func, ip_rcv);

	lock_kernel();
	if (pt->func == ip_rcv) {
		pt->func = REP_ip_rcv;
	} else
		printk("no...\n");

	ip_handler = pt;
	unlock_kernel();
	seeker_init();
	return 0;
}

static void __exit exit(void)
{
	seeker_exit();
	lock_kernel();
	if (ip_handler->func == REP_ip_rcv)
		ip_handler->func = ip_rcv;
	else
		printk("error...\n");
	unlock_kernel();
}

module_init(init)
    module_exit(exit)
    MODULE_LICENSE("GPL");

^ permalink raw reply

* Re: pktgen question
From: Evgeniy Polyakov @ 2007-09-23 17:28 UTC (permalink / raw)
  To: Steve Wise; +Cc: netdev
In-Reply-To: <46F6905C.6030309@opengridcomputing.com>

Hi Steve.

On Sun, Sep 23, 2007 at 11:12:12AM -0500, Steve Wise (swise@opengridcomputing.com) wrote:
> The pktgen module provides a way to "clone" the skb its using for 
> transmission, and allows passing N clones of the originally created skb 
> to the driver under test.    However, it doesn't really use skb_clone(), 
> but rather it just bumps the skb->users count for each "clone" and 
> passes the same skb ptr to the driver.
> 
> Q: Is that a valid use of skb->users or should pktgen really be cloning 
> the skbuff?

It's a hack, but since skb is owned by pktgen only (no copies in some
outside queues or some other access) it is allowed just to bump reference
counter (i.e. 'share' skb in usual notation).

-- 
	Evgeniy Polyakov

^ permalink raw reply

* [ofa-general] [PATCH 4/4][NET_SCHED] kill dev->gso_skb
From: jamal @ 2007-09-23 18:02 UTC (permalink / raw)
  To: David Miller
  Cc: johnpol, peter.p.waskiewicz.jr, kumarkr, herbert, gaagaan,
	Robert.Olsson, netdev, rdreier, mcarlson, randy.dunlap, jagana,
	general, mchan, tgraf, jeff, sri, shemminger, kaber
In-Reply-To: <1190570409.4256.62.camel@localhost>

[-- Attachment #1: Type: text/plain, Size: 98 bytes --]


This patch removes dev->gso_skb as it is no longer necessary with
batching code.

cheers,
jamal


[-- Attachment #2: patch40f4 --]
[-- Type: text/plain, Size: 2277 bytes --]

[NET_SCHED] kill dev->gso_skb
The batching code does what gso used to batch at the drivers.
There is no more need for gso_skb. If for whatever reason the
requeueing is a bad idea we are going to leave packets in dev->blist
(and still not need dev->gso_skb)

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>

---
commit c6d2d61a73e1df5daaa294876f62454413fcb0af
tree 1d7bf650096a922a6b6a4e7d6810f83320eb94dd
parent e26705f6ef7db034df7af3f4fccd7cd40b8e46e0
author Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 12:25:10 -0400
committer Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 12:25:10 -0400

 include/linux/netdevice.h |    3 ---
 net/sched/sch_generic.c   |   12 ------------
 2 files changed, 0 insertions(+), 15 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 443cded..7811729 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -560,9 +560,6 @@ struct net_device
 	struct list_head	qdisc_list;
 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
 
-	/* Partially transmitted GSO packet. */
-	struct sk_buff		*gso_skb;
-
 	/* ingress path synchronizer */
 	spinlock_t		ingress_lock;
 	struct Qdisc		*qdisc_ingress;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 86a3f9d..b4e1607 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -172,13 +172,6 @@ static int xmit_get_pkts(struct net_device *dev,
 	struct sk_buff *skb;
 	int count = dev->xmit_win;
 
-	if (count  && dev->gso_skb) {
-		skb = dev->gso_skb;
-		dev->gso_skb = NULL;
-		count -= xmit_count_skbs(skb);
-		__skb_queue_tail(pktlist, skb);
-	}
-
 	while (count > 0) {
 		skb = q->dequeue(q);
 		if (!skb)
@@ -654,7 +647,6 @@ void dev_activate(struct net_device *dev)
 void dev_deactivate(struct net_device *dev)
 {
 	struct Qdisc *qdisc;
-	struct sk_buff *skb;
 
 	spin_lock_bh(&dev->queue_lock);
 	qdisc = dev->qdisc;
@@ -662,15 +654,11 @@ void dev_deactivate(struct net_device *dev)
 
 	qdisc_reset(qdisc);
 
-	skb = dev->gso_skb;
-	dev->gso_skb = NULL;
 	if (!skb_queue_empty(&dev->blist))
 		skb_queue_purge(&dev->blist);
 	dev->xmit_win = 1;
 	spin_unlock_bh(&dev->queue_lock);
 
-	kfree_skb(skb);
-
 	dev_watchdog_down(dev);
 
 	/* Wait for outstanding dev_queue_xmit calls. */

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related

* [PATCH 3/4][NET_BATCH] net core use batching
From: jamal @ 2007-09-23 18:00 UTC (permalink / raw)
  To: David Miller
  Cc: krkumar2, johnpol, herbert, kaber, shemminger, jagana,
	Robert.Olsson, rick.jones2, xma, gaagaan, netdev, rdreier,
	peter.p.waskiewicz.jr, mcarlson, jeff, mchan, general, kumarkr,
	tgraf, randy.dunlap, sri
In-Reply-To: <1190570317.4256.59.camel@localhost>

[-- Attachment #1: Type: text/plain, Size: 71 bytes --]

This patch adds the usage of batching within the core.

cheers,
jamal


[-- Attachment #2: patch30f4 --]
[-- Type: text/plain, Size: 6919 bytes --]

[NET_BATCH] net core use batching

This patch adds the usage of batching within the core.
The same test methodology used in introducing txlock is used, with
the following results on different kernels:

        +------------+--------------+-------------+------------+--------+
        |       64B  |  128B        | 256B        | 512B       |1024B   |
        +------------+--------------+-------------+------------+--------+
Original| 467482     | 463061       | 388267      | 216308     | 114704 |
        |            |              |             |            |        |
txlock  | 468922     | 464060       | 388298      | 216316     | 114709 |
        |            |              |             |            |        |
tg3nobtx| 468012     | 464079       | 388293      | 216314     | 114704 |
        |            |              |             |            |        |
tg3btxdr| 480794     | 475102       | 388298      | 216316     | 114705 |
        |            |              |             |            |        |
tg3btxco| 481059     | 475423       | 388285      | 216308     | 114706 |
        +------------+--------------+-------------+------------+--------+

The first two colums "Original" and "txlock" were introduced in an earlier
patch and demonstrate a slight increase in performance with txlock.
"tg3nobtx" shows the tg3 driver with no changes to support batching.
The purpose of this test is to demonstrate the effect of introducing
the core changes to a driver that doesnt support them.
Although this patch brings down perfomance slightly compared to txlock
for such netdevices, it is still better compared to just the original kernel.
"tg3btxdr" demonstrates the effect of using ->hard_batch_xmit() with tg3
driver. "tg3btxco" demonstrates the effect of letting the core do all the
work. As can be seen the last two are not very different in performance.
The difference is ->hard_batch_xmit() introduces a new method which
is intrusive.

I have #if-0ed some of the old functions so the patch is more readable.

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>

---
commit e26705f6ef7db034df7af3f4fccd7cd40b8e46e0
tree b99c469497a0145ca5c0651dc4229ce17da5b31c
parent 6b8e2f76f86c35a6b2cee3698c633d20495ae0c0
author Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 11:35:25 -0400
committer Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 11:35:25 -0400

 net/sched/sch_generic.c |  127 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 115 insertions(+), 12 deletions(-)

diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 95ae119..86a3f9d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -56,6 +56,7 @@ static inline int qdisc_qlen(struct Qdisc *q)
 	return q->q.qlen;
 }
 
+#if 0
 static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
 				  struct Qdisc *q)
 {
@@ -110,6 +111,97 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
 
 	return ret;
 }
+#endif
+
+static inline int handle_dev_cpu_collision(struct net_device *dev)
+{
+	if (unlikely(dev->xmit_lock_owner == smp_processor_id())) {
+		if (net_ratelimit())
+			printk(KERN_WARNING
+				"Dead loop on netdevice %s, fix it urgently!\n",
+				dev->name);
+		return 1;
+	}
+	__get_cpu_var(netdev_rx_stat).cpu_collision++;
+	return 0;
+}
+
+static inline int
+dev_requeue_skbs(struct sk_buff_head *skbs, struct net_device *dev,
+	       struct Qdisc *q)
+{
+
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(skbs)) != NULL)
+		q->ops->requeue(skb, q);
+
+	netif_schedule(dev);
+	return 0;
+}
+
+static inline int
+xmit_islocked(struct sk_buff_head *skbs, struct net_device *dev,
+	    struct Qdisc *q)
+{
+	int ret = handle_dev_cpu_collision(dev);
+
+	if (ret) {
+		if (!skb_queue_empty(skbs))
+			skb_queue_purge(skbs);
+		return qdisc_qlen(q);
+	}
+
+	return dev_requeue_skbs(skbs, dev, q);
+}
+
+static int xmit_count_skbs(struct sk_buff *skb)
+{
+	int count = 0;
+	for (; skb; skb = skb->next) {
+		count += skb_shinfo(skb)->nr_frags;
+		count += 1;
+	}
+	return count;
+}
+
+static int xmit_get_pkts(struct net_device *dev,
+			   struct Qdisc *q,
+			   struct sk_buff_head *pktlist)
+{
+	struct sk_buff *skb;
+	int count = dev->xmit_win;
+
+	if (count  && dev->gso_skb) {
+		skb = dev->gso_skb;
+		dev->gso_skb = NULL;
+		count -= xmit_count_skbs(skb);
+		__skb_queue_tail(pktlist, skb);
+	}
+
+	while (count > 0) {
+		skb = q->dequeue(q);
+		if (!skb)
+			break;
+
+		count -= xmit_count_skbs(skb);
+		__skb_queue_tail(pktlist, skb);
+	}
+
+	return skb_queue_len(pktlist);
+}
+
+static int xmit_prepare_pkts(struct net_device *dev,
+			     struct sk_buff_head *tlist)
+{
+	struct sk_buff *skb;
+	struct sk_buff_head *flist = &dev->blist;
+
+	while ((skb = __skb_dequeue(tlist)) != NULL)
+		xmit_prepare_skb(skb, dev);
+
+	return skb_queue_len(flist);
+}
 
 /*
  * NOTE: Called under dev->queue_lock with locally disabled BH.
@@ -130,22 +222,27 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
  *				>0 - queue is not empty.
  *
  */
-static inline int qdisc_restart(struct net_device *dev)
+
+static inline int qdisc_restart(struct net_device *dev,
+				struct sk_buff_head *tpktlist)
 {
 	struct Qdisc *q = dev->qdisc;
-	struct sk_buff *skb;
-	int ret;
+	int ret = 0;
 
-	/* Dequeue packet */
-	if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
-		return 0;
+	ret = xmit_get_pkts(dev, q, tpktlist);
 
+	if (!ret)
+		return 0;
 
-	/* And release queue */
+	/* We got em packets */
 	spin_unlock(&dev->queue_lock);
 
+	/* prepare to embark */
+	xmit_prepare_pkts(dev, tpktlist);
+
+	/* bye packets ....*/
 	HARD_TX_LOCK(dev, smp_processor_id());
-	ret = dev_hard_start_xmit(skb, dev);
+	ret = dev_batch_xmit(dev);
 	HARD_TX_UNLOCK(dev);
 
 	spin_lock(&dev->queue_lock);
@@ -158,8 +255,8 @@ static inline int qdisc_restart(struct net_device *dev)
 		break;
 
 	case NETDEV_TX_LOCKED:
-		/* Driver try lock failed */
-		ret = handle_dev_cpu_collision(skb, dev, q);
+		/* Driver lock failed */
+		ret = xmit_islocked(&dev->blist, dev, q);
 		break;
 
 	default:
@@ -168,7 +265,7 @@ static inline int qdisc_restart(struct net_device *dev)
 			printk(KERN_WARNING "BUG %s code %d qlen %d\n",
 			       dev->name, ret, q->q.qlen);
 
-		ret = dev_requeue_skb(skb, dev, q);
+		ret = dev_requeue_skbs(&dev->blist, dev, q);
 		break;
 	}
 
@@ -177,8 +274,11 @@ static inline int qdisc_restart(struct net_device *dev)
 
 void __qdisc_run(struct net_device *dev)
 {
+	struct sk_buff_head tpktlist;
+	skb_queue_head_init(&tpktlist);
+
 	do {
-		if (!qdisc_restart(dev))
+		if (!qdisc_restart(dev, &tpktlist))
 			break;
 	} while (!netif_queue_stopped(dev));
 
@@ -564,6 +664,9 @@ void dev_deactivate(struct net_device *dev)
 
 	skb = dev->gso_skb;
 	dev->gso_skb = NULL;
+	if (!skb_queue_empty(&dev->blist))
+		skb_queue_purge(&dev->blist);
+	dev->xmit_win = 1;
 	spin_unlock_bh(&dev->queue_lock);
 
 	kfree_skb(skb);

^ permalink raw reply related

* [ofa-general] [PATCH 2/4] [NET_BATCH] Introduce batching interface
From: jamal @ 2007-09-23 17:58 UTC (permalink / raw)
  To: David Miller
  Cc: johnpol, peter.p.waskiewicz.jr, kumarkr, herbert, gaagaan,
	Robert.Olsson, netdev, rdreier, mcarlson, randy.dunlap, jagana,
	general, mchan, tgraf, jeff, sri, shemminger, kaber
In-Reply-To: <1190570205.4256.56.camel@localhost>

[-- Attachment #1: Type: text/plain, Size: 77 bytes --]


This patch introduces the netdevice interface for batching.

cheers,
jamal


[-- Attachment #2: patch20f4 --]
[-- Type: text/plain, Size: 8823 bytes --]

[NET_BATCH] Introduce batching interface

This patch introduces the netdevice interface for batching.

A typical driver dev->hard_start_xmit() has 4 parts:
a) packet formating (example vlan, mss, descriptor counting etc)
b) chip specific formatting
c) enqueueing the packet on a DMA ring
d) IO operations to complete packet transmit, tell DMA engine to chew on,
tx completion interupts etc

[For code cleanliness/readability sake, regardless of this work,
one should break the dev->hard_start_xmit() into those 4 functions
anyways].

With the api introduced in this patch, a driver which has all
4 parts and needing to support batching is advised to split its
dev->hard_start_xmit() in the following manner:
1)use its dev->hard_prep_xmit() method to achieve #a
2)use its dev->hard_end_xmit() method to achieve #d
3)#b and #c can stay in ->hard_start_xmit() (or whichever way you want
to do this)
Note: There are drivers which may need not support any of the two
methods (example the tun driver i patched) so the two methods are
optional.

The core will first do the packet formatting by invoking your supplied
dev->hard_prep_xmit() method. It will then pass you the packet via
your dev->hard_start_xmit() method and lastly will invoke your
dev->hard_end_xmit() when it completes passing you all the packets
queued for you. dev->hard_prep_xmit() is invoked without holding any
tx lock but the rest are under TX_LOCK().

LLTX present a challenge in that we have to introduce a deviation
from the norm and introduce the ->hard_batch_xmit() method. An LLTX
driver presents us with ->hard_batch_xmit() to which we pass it a list
of packets in a dev->blist skb queue. It is then the responsibility
of the ->hard_batch_xmit() to exercise steps #b and #c for all packets
and #d when the batching is complete. Step #a is already done for you
by the time you get the packets in dev->blist.
And last xmit_win variable is introduced to ensure that when we pass
the driver a list of packets it will swallow all of them - which is
useful because we dont requeue to the qdisc (and avoids burning
unnecessary cpu cycles or introducing any strange re-ordering). The driver
tells us when it invokes netif_wake_queue how much space it has for
descriptors by setting this variable.

Some decisions i had to make:
- every driver will have a xmit_win variable and the core will set it
to 1 which means the behavior of non-batching drivers stays the same.
- the batch list, blist, is no longer a pointer; wastes a little extra
memmory i plan to recoup by killing gso_skb in later patches.

Theres a lot of history and reasoning of why batching in a document
i am writting which i may submit as a patch.
Thomas Graf (who doesnt know this probably) gave me the impetus to
start looking at this back in 2004 when he invited me to the linux
conference he was organizing. Parts of what i presented in SUCON in
2004 talk about batching. Herbert Xu forced me to take a second look around
2.6.18 - refer to my netconf 2006 presentation. Krishna Kumar provided
me with more motivation in May 2007 when he posted on netdev and engaged me.
Sridhar Samudrala, Krishna Kumar, Matt Carlson, Michael Chan,
Jeremy Ethridge, Evgeniy Polyakov, Sivakumar Subramani, and
David Miller, have contributed in one or more of {bug fixes, enhancements,
testing, lively discussion}. The Broadcom and netiron folks have been
outstanding in their help.

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>

---
commit ab4b07ef2e4069c115c9c1707d86ae2344a5ded5
tree 994b42b03bbfcc09ac8b7670c53c12e0b2a71dc7
parent b0e36991c5850dfe930f80ee508b08fdcabc18d1
author Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 10:30:32 -0400
committer Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 10:30:32 -0400

 include/linux/netdevice.h |   17 +++++++
 net/core/dev.c            |  106 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index cf89ce6..443cded 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -453,6 +453,7 @@ struct net_device
 #define NETIF_F_NETNS_LOCAL	8192	/* Does not change network namespaces */
 #define NETIF_F_MULTI_QUEUE	16384	/* Has multiple TX/RX queues */
 #define NETIF_F_LRO		32768	/* large receive offload */
+#define NETIF_F_BTX		65536	/* Capable of batch tx */
 
 	/* Segmentation offload features */
 #define NETIF_F_GSO_SHIFT	16
@@ -578,6 +579,15 @@ struct net_device
 	void			*priv;	/* pointer to private data	*/
 	int			(*hard_start_xmit) (struct sk_buff *skb,
 						    struct net_device *dev);
+	/* hard_batch_xmit is needed for LLTX, kill it when those
+	 * disappear or better kill it now and dont support LLTX
+	*/
+	int			(*hard_batch_xmit) (struct net_device *dev);
+	int			(*hard_prep_xmit) (struct sk_buff *skb,
+						   struct net_device *dev);
+	void			(*hard_end_xmit) (struct net_device *dev);
+	int			xmit_win;
+
 	/* These may be needed for future network-power-down code. */
 	unsigned long		trans_start;	/* Time (in jiffies) of last Tx	*/
 
@@ -592,6 +602,7 @@ struct net_device
 
 	/* delayed register/unregister */
 	struct list_head	todo_list;
+	struct sk_buff_head     blist;
 	/* device index hash chain */
 	struct hlist_node	index_hlist;
 
@@ -1022,6 +1033,12 @@ extern int		dev_set_mac_address(struct net_device *,
 					    struct sockaddr *);
 extern int		dev_hard_start_xmit(struct sk_buff *skb,
 					    struct net_device *dev);
+extern int		dev_batch_xmit(struct net_device *dev);
+extern int		prepare_gso_skb(struct sk_buff *skb,
+					struct net_device *dev,
+					struct sk_buff_head *skbs);
+extern int		xmit_prepare_skb(struct sk_buff *skb,
+					 struct net_device *dev);
 
 extern int		netdev_budget;
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 91c31e6..25d01fd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1531,6 +1531,110 @@ static int dev_gso_segment(struct sk_buff *skb)
 	return 0;
 }
 
+int prepare_gso_skb(struct sk_buff *skb, struct net_device *dev,
+		    struct sk_buff_head *skbs)
+{
+	int tdq = 0;
+	do {
+		struct sk_buff *nskb = skb->next;
+
+		skb->next = nskb->next;
+		nskb->next = NULL;
+
+		if (dev->hard_prep_xmit) {
+			/* note: skb->cb is set in hard_prep_xmit(),
+			 * it should not be trampled somewhere
+			 * between here and the driver picking it
+			 * The VLAN code wrongly assumes it owns it
+			 * so the driver needs to be careful; for
+			 * good handling look at tg3 driver ..
+			*/
+			int ret = dev->hard_prep_xmit(nskb, dev);
+			if (ret != NETDEV_TX_OK)
+				continue;
+		}
+		/* Driver likes this packet .. */
+		tdq++;
+		__skb_queue_tail(skbs, nskb);
+	} while (skb->next);
+	skb->destructor = DEV_GSO_CB(skb)->destructor;
+	kfree_skb(skb);
+
+	return tdq;
+}
+
+int xmit_prepare_skb(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sk_buff_head *skbs = &dev->blist;
+
+	if (netif_needs_gso(dev, skb)) {
+		if (unlikely(dev_gso_segment(skb))) {
+			kfree_skb(skb);
+			return 0;
+		}
+		if (skb->next)
+			return prepare_gso_skb(skb, dev, skbs);
+	}
+
+	if (dev->hard_prep_xmit) {
+		int ret = dev->hard_prep_xmit(skb, dev);
+		if (ret != NETDEV_TX_OK)
+			return 0;
+	}
+	__skb_queue_tail(skbs, skb);
+	return 1;
+}
+
+int dev_batch_xmit(struct net_device *dev)
+{
+	struct sk_buff_head *skbs = &dev->blist;
+	int rc = NETDEV_TX_OK;
+	struct sk_buff *skb;
+	int orig_w = dev->xmit_win;
+	int orig_pkts = skb_queue_len(skbs);
+
+	if (dev->hard_batch_xmit) { /* only for LLTX devices */
+		rc = dev->hard_batch_xmit(dev);
+	} else {
+		while ((skb = __skb_dequeue(skbs)) != NULL) {
+			if (!list_empty(&ptype_all))
+				dev_queue_xmit_nit(skb, dev);
+			rc = dev->hard_start_xmit(skb, dev);
+			if (unlikely(rc))
+				break;
+			/*
+			 * XXX: multiqueue may need closer srutiny..
+			*/
+			if (unlikely(netif_queue_stopped(dev) ||
+			     netif_subqueue_stopped(dev, skb->queue_mapping))) {
+				rc = NETDEV_TX_BUSY;
+				break;
+			}
+		}
+	}
+
+	/* driver is likely buggy and lied to us on how much
+	 * space it had. Damn you driver ..
+	*/
+	if (unlikely(skb_queue_len(skbs))) {
+		printk(KERN_WARNING "Likely bug %s %s (%d) "
+				"left %d/%d window now %d, orig %d\n",
+			dev->name, rc?"busy":"locked",
+			netif_queue_stopped(dev),
+			skb_queue_len(skbs),
+			orig_pkts,
+			dev->xmit_win,
+			orig_w);
+			rc = NETDEV_TX_BUSY;
+	}
+
+	if (orig_pkts > skb_queue_len(skbs))
+		if (dev->hard_end_xmit)
+			dev->hard_end_xmit(dev);
+
+	return rc;
+}
+
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	if (likely(!skb->next)) {
@@ -3565,6 +3669,8 @@ int register_netdevice(struct net_device *dev)
 		}
 	}
 
+	dev->xmit_win = 1;
+	skb_queue_head_init(&dev->blist);
 	/*
 	 *	nil rebuild_header routine,
 	 *	that should be never called and used as just bug trap.

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related

* [ofa-general] [PATCH 1/4] [NET_SCHED] explict hold dev tx lock
From: jamal @ 2007-09-23 17:56 UTC (permalink / raw)
  To: David Miller
  Cc: johnpol, peter.p.waskiewicz.jr, kumarkr, herbert, gaagaan,
	Robert.Olsson, netdev, rdreier, mcarlson, randy.dunlap, jagana,
	general, mchan, tgraf, jeff, sri, shemminger, kaber
In-Reply-To: <1190569987.4256.52.camel@localhost>

[-- Attachment #1: Type: text/plain, Size: 141 bytes --]


I have submitted this before; but here it is again.
Against net-2.6.24 from yesterday for this and all following patches. 


cheers,
jamal


[-- Attachment #2: patch10f4 --]
[-- Type: text/plain, Size: 3260 bytes --]

[NET_SCHED] explict hold dev tx lock

For N cpus, with full throttle traffic on all N CPUs, funneling traffic
to the same ethernet device, the devices queue lock is contended by all
N CPUs constantly. The TX lock is only contended by a max of 2 CPUS.
In the current mode of qdisc operation, when all N CPUs contend for
the dequeue region and one of them (after all the work) entering
dequeue region, we may endup aborting the path if we are unable to get
the tx lock and go back to contend for the queue lock. As N goes up,
this gets worse.

The changes in this patch result in a small increase in performance
with a 4CPU (2xdual-core) with no irq binding. My tests are UDP
based and keep all 4CPUs busy all the time for the period of the test.
Both e1000 and tg3 showed similar behavior.
I expect higher gains with more CPUs. Summary below with different
UDP packets and the resulting pps seen. Note at around 200Bytes,
the two dont seem that much different and we are approaching wire
speed (with plenty of CPU available; eg at 512B, the app is sitting
at 80% idle on both cases).

        +------------+--------------+-------------+------------+--------+
pktsize |       64B  |  128B        | 256B        | 512B       |1024B   |
        +------------+--------------+-------------+------------+--------+
Original| 467482     | 463061       | 388267      | 216308     | 114704 |
        |            |              |             |            |        |
txlock  | 468922     | 464060       | 388298      | 216316     | 114709 |
        -----------------------------------------------------------------

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>

---
commit b0e36991c5850dfe930f80ee508b08fdcabc18d1
tree b1787bba26f80a325298f89d1ec882cc5ab524ae
parent 42765047105fdd496976bc1784d22eec1cd9b9aa
author Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 09:09:17 -0400
committer Jamal Hadi Salim <hadi@cyberus.ca> Sun, 23 Sep 2007 09:09:17 -0400

 net/sched/sch_generic.c |   19 ++-----------------
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index e970e8e..95ae119 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -134,34 +134,19 @@ static inline int qdisc_restart(struct net_device *dev)
 {
 	struct Qdisc *q = dev->qdisc;
 	struct sk_buff *skb;
-	unsigned lockless;
 	int ret;
 
 	/* Dequeue packet */
 	if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
 		return 0;
 
-	/*
-	 * When the driver has LLTX set, it does its own locking in
-	 * start_xmit. These checks are worth it because even uncongested
-	 * locks can be quite expensive. The driver can do a trylock, as
-	 * is being done here; in case of lock contention it should return
-	 * NETDEV_TX_LOCKED and the packet will be requeued.
-	 */
-	lockless = (dev->features & NETIF_F_LLTX);
-
-	if (!lockless && !netif_tx_trylock(dev)) {
-		/* Another CPU grabbed the driver tx lock */
-		return handle_dev_cpu_collision(skb, dev, q);
-	}
 
 	/* And release queue */
 	spin_unlock(&dev->queue_lock);
 
+	HARD_TX_LOCK(dev, smp_processor_id());
 	ret = dev_hard_start_xmit(skb, dev);
-
-	if (!lockless)
-		netif_tx_unlock(dev);
+	HARD_TX_UNLOCK(dev);
 
 	spin_lock(&dev->queue_lock);
 	q = dev->qdisc;

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related

* Re: pktgen question
From: Steve Wise @ 2007-09-23 17:55 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: netdev
In-Reply-To: <20070923172803.GA11997@2ka.mipt.ru>



Evgeniy Polyakov wrote:
> Hi Steve.
> 
> On Sun, Sep 23, 2007 at 11:12:12AM -0500, Steve Wise (swise@opengridcomputing.com) wrote:
>> The pktgen module provides a way to "clone" the skb its using for 
>> transmission, and allows passing N clones of the originally created skb 
>> to the driver under test.    However, it doesn't really use skb_clone(), 
>> but rather it just bumps the skb->users count for each "clone" and 
>> passes the same skb ptr to the driver.
>>
>> Q: Is that a valid use of skb->users or should pktgen really be cloning 
>> the skbuff?
> 
> It's a hack, but since skb is owned by pktgen only (no copies in some
> outside queues or some other access) it is allowed just to bump reference
> counter (i.e. 'share' skb in usual notation).
>

Its a hack that breaks cxgb3 because cxgb3 uses the skb->cb area for 
each skb passed down.  So cxgb3 is at fault then?  IE a driver cannot 
use the skb->cb field if the users count is > 1?  Or maybe a driver can 
_never_ use the cb field?

Steve.





^ permalink raw reply

* [PATCHES] TX batching
From: jamal @ 2007-09-23 17:53 UTC (permalink / raw)
  To: David Miller
  Cc: krkumar2, johnpol, herbert, kaber, shemminger, jagana,
	Robert.Olsson, rick.jones2, xma, gaagaan, netdev, rdreier,
	peter.p.waskiewicz.jr, mcarlson, jeff, mchan, general, kumarkr,
	tgraf, randy.dunlap, sri
In-Reply-To: <1189988958.4230.55.camel@localhost>


I had plenty of time this weekend so i have been doing a _lot_ of
testing.  My next emails will send a set of patches:
 
Patch 1: Introduces explicit tx locking
Patch 2: Introduces batching interface
Patch 3: Core uses batching interface
Patch 4: get rid of dev->gso_skb

Testing
-------
Each of these patches has been performance tested and the results
are in the logs on a per-patch basis. 
My system under test hardware is a 2xdual core opteron with a couple of 
tg3s. 
My test tool generates udp traffic of different sizes for upto 60 
seconds per run or a total of 30M packets. I have 4 threads each 
running on a specific CPU which keep all the CPUs as busy as they can 
sending packets targetted at a directly connected box's udp discard
port.

All 4 CPUs target a single tg3 to send. The receiving box has a tc rule 
which counts and drops all incoming udp packets to discard port - this
allows me to make sure that the receiver is not the bottleneck in the
testing. Packet sizes sent are {64B, 128B, 256B, 512B, 1024B}. Each
packet size run is repeated 10 times to ensure that there are no
transients. The average of all 10 runs is then computed and collected.

I have not run testing on patch #4 because i had to let the machine
go, but will have some access to it tommorow early morning where i can
run some tests.

Comments
--------
Iam trying to kill ->hard_batch_xmit() but it would be tricky to do
without it for LLTX drivers. Anything i try will require a few extra
checks. OTOH, I could kill LLTX for the drivers i am using that
are LLTX and then drop that interface or I could say "no support
for LLTX". I am in a dilema.

Dave please let me know if this meets your desires to allow devices
which are SG and able to compute CSUM benefit just in case i
misunderstood. 
Herbert, if you can look at at least patch 4 i will appreaciate it.

More patches to follow  - i didnt want to overload people by dumping 
too many patches. Most of these patches below are ready to go; some are
need some testing and others need a little porting from an earlier
kernel: 
- tg3 driver (tested and works well, but dont want to send 
- tun driver
- pktgen
- netiron driver
- e1000 driver
- ethtool interface
- There is at least one other driver promised to me

I am also going to update the two documents i posted earlier.
Hopefully i can do that today.

cheers,
jamal


^ permalink raw reply

* Re: [ofa-general] Re: [PATCH V5 2/11] IB/ipoib: Notify the world before doing unregister
From: Roland Dreier @ 2007-09-23 16:34 UTC (permalink / raw)
  To: Moni Shoua; +Cc: netdev, Jay Vosburgh, OpenFabrics General
In-Reply-To: <46F61BF6.3000203@gmail.com>

 > The action in bonding to a detach of slave is to unregister the master (see patch 10).
 > This can't be done from the context of unregister_netdevice itself (it is protected by rtnl_lock).

I'm confused.  Your patch has:

 > +		ipoib_slave_detach(cpriv->dev);
 >  		unregister_netdev(cpriv->dev);

And ipoib_slave_detach() is:

 > +static inline void ipoib_slave_detach(struct net_device *dev)
 > +{
 > +	rtnl_lock();
 > +	netdev_slave_detach(dev);
 > +	rtnl_unlock();
 > +}

so you are calling netdev_slave_detach() with the rtnl lock held.
Why can't you make the same call from the start of unregister_netdevice()?

Anyway, if the rtnl lock is a problem, can you just add the call to
netdev_slave_detach() to unregister_netdev() before it takes the rtnl lock?

 - R.

^ permalink raw reply

* pktgen question
From: Steve Wise @ 2007-09-23 16:12 UTC (permalink / raw)
  To: netdev

The pktgen module provides a way to "clone" the skb its using for 
transmission, and allows passing N clones of the originally created skb 
to the driver under test.    However, it doesn't really use skb_clone(), 
but rather it just bumps the skb->users count for each "clone" and 
passes the same skb ptr to the driver.

Q: Is that a valid use of skb->users or should pktgen really be cloning 
the skbuff?

Thanks,

Steve.

^ permalink raw reply

* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently runsoftirqnetwork code on SMP
From: john ye @ 2007-09-23 15:45 UTC (permalink / raw)
  To: hadi; +Cc: David Miller, netdev, kuznet, pekkas, jmorris, kaber, iceburgue
In-Reply-To: <1190551422.4256.36.camel@localhost>

Dear Jamal,

Yes. you are right. I do "need some real fast traffic generator; possibly 
one that can do
thousands of tcp sessions." to get some kind of convincing result.

Also, the packet reordering is also my big concern. round-robin doesn't have 
much help.

"The INPUT speed is doubled by using 2 CPUs" is shown by these steps:
1) without intables, ftp get a 50M file from another machine, ftp can show 
speed 10M/s.
2) run iptables and add many intpalbes rules, ftp get the same file, the 
speed is down to 3M/s, top shows CPU0 busy in softirq. CPU1 idle.
3) insmod my module BS, then ftp get the same file, the speed can reach 
6M/s, top shows both CPU0 and CPU1 are busy in keventd/0/1

I will try my best to do further test. the best test should be done on a 4 
CPU GATEWAY machine. In China, there are many companies who use linux box 
running iptables as a gateway to serve 1000 around clients, for example. On 
those machines, a lot conntracking, and they have the "idle CPUs while net 
is too busy" problem.

In my BS module (If you got it), only 2 functions are needed to see: 
REP_ip_rcv(), and bs_func(). Others have nothing to do with the BS patch ---  
they are there only for accessing non-EXPORT_SYMBOLed kernel variables.

Thanks a lot for your thought.

John Ye


----- Original Message ----- 
From: "jamal" <hadi@cyberus.ca>
To: "john ye" <johny@asimco.com.cn>
Cc: "David Miller" <davem@davemloft.net>; <netdev@vger.kernel.org>; 
<kuznet@ms2.inr.ac.ru>; <pekkas@netcore.fi>; <jmorris@namei.org>; 
<kaber@coreworks.de>
Sent: Sunday, September 23, 2007 8:43 PM
Subject: Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently 
runsoftirqnetwork code on SMP


> On Sun, 2007-23-09 at 12:45 +0800, john ye wrote:
>
>>  I do randomly select a CPU to dispatch the skb to. Previously, I
>> dispatch
>>  skb evenly to all CPUs( round robin, one by one). but I didn't find a
>> quick
>>  coding. for_each_online_cpu is not quick enough.
>
> for_each_online_cpu doenst look that expensive - but even round robin
> wont fix the reordering problem. What you need to do is make sure that a
> flow always goes to the same cpu over some period of time.
>
>>  According to my test result, it did make packet INPUT speed doubled
>> because
>>  another CPU is used concurrently.
>
> How did you measure "speed" - was it throughput? Did you measure how
> much cpu was being utilized?
>
>>  It seems the packets still keep "roughly ordering" after turning on
>> BS patch.
>
> Linux TCP is very resilient to reordering compared to other OSes, but
> even then if you hit it with enough packets it is going to start
> sweating it.
>
>>  The test is simple: use an 2400 lines of iptables -t filter -A INPUT
>> -p
>>  tcp -s x.x.x.x --dport yy -j XXXX.
>>  these rules make the current softirq be very busy on one CPU and make
>> the
>>  incoming net very slow. after turning on BS, the speed doubled.
>>
> Ok, but how do you observe "doubled"?
> Do you have conntrack on? It maybe that what you have just found is
> netfilter needs to have its work defered from packet rcv.
> You need some real fast traffic generator; possibly one that can do
> thousands of tcp sessions.
>
>>  For NAT test, I didn't get a good result like INPUT because real
>> environment limitation.
>>  The test is very basic and is far from "full".
>
> What happens when you totally compile out netfilter and you just use
> this machine as a server?
>
>>  It seems to me that the cross-cpu spinlock_xxxx for the queue doesn't
>> have
>>  big cost and is allowable in terms of CPU time consumption, compared
>> with
>>  the gains by making other CPUs joint in the work.
>>
>>  I have made BS patch into a loadable module.
>>  http://linux.chinaunix.net/bbs/thread-909725-2-1.html and let others
>> help with testing.
>
> It is still very hard to read; and i am not sure how you are going to
> get the performance you claim eventually - you are registering as a tap
> for ip packets, which means you will process two of each incoming
> packets.
>
> cheers,
> jamal
>
> 



^ permalink raw reply

* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run softirqnetwork code on SMP
From: jamal @ 2007-09-23 12:43 UTC (permalink / raw)
  To: john ye; +Cc: David Miller, netdev, kuznet, pekkas, jmorris, kaber
In-Reply-To: <004901c7fd9c$94370df0$d6ddfea9@JOHNYE1>

On Sun, 2007-23-09 at 12:45 +0800, john ye wrote:

>  I do randomly select a CPU to dispatch the skb to. Previously, I
> dispatch
>  skb evenly to all CPUs( round robin, one by one). but I didn't find a
> quick
>  coding. for_each_online_cpu is not quick enough.

for_each_online_cpu doenst look that expensive - but even round robin
wont fix the reordering problem. What you need to do is make sure that a
flow always goes to the same cpu over some period of time.

>  According to my test result, it did make packet INPUT speed doubled
> because
>  another CPU is used concurrently.

How did you measure "speed" - was it throughput? Did you measure how
much cpu was being utilized?

>  It seems the packets still keep "roughly ordering" after turning on
> BS patch.

Linux TCP is very resilient to reordering compared to other OSes, but
even then if you hit it with enough packets it is going to start
sweating it.

>  The test is simple: use an 2400 lines of iptables -t filter -A INPUT
> -p
>  tcp -s x.x.x.x --dport yy -j XXXX.
>  these rules make the current softirq be very busy on one CPU and make
> the
>  incoming net very slow. after turning on BS, the speed doubled.
> 
Ok, but how do you observe "doubled"?
Do you have conntrack on? It maybe that what you have just found is
netfilter needs to have its work defered from packet rcv.
You need some real fast traffic generator; possibly one that can do
thousands of tcp sessions.

>  For NAT test, I didn't get a good result like INPUT because real 
> environment limitation.
>  The test is very basic and is far from "full".

What happens when you totally compile out netfilter and you just use
this machine as a server?

>  It seems to me that the cross-cpu spinlock_xxxx for the queue doesn't
> have
>  big cost and is allowable in terms of CPU time consumption, compared
> with
>  the gains by making other CPUs joint in the work.
> 
>  I have made BS patch into a loadable module.
>  http://linux.chinaunix.net/bbs/thread-909725-2-1.html and let others
> help with testing.

It is still very hard to read; and i am not sure how you are going to
get the performance you claim eventually - you are registering as a tap
for ip packets, which means you will process two of each incoming
packets.

cheers,
jamal


^ permalink raw reply

* Re: [ofa-general] Re: [PATCH V5 2/11] IB/ipoib: Notify the world before doing unregister
From: Moni Shoua @ 2007-09-23  7:55 UTC (permalink / raw)
  To: Roland Dreier; +Cc: Moni Shoua, netdev, Jay Vosburgh, OpenFabrics General
In-Reply-To: <adaabrhgvfa.fsf@cisco.com>

Roland Dreier wrote:
>  > +		ipoib_slave_detach(cpriv->dev);
>  >  		unregister_netdev(cpriv->dev);
> 
> Maybe you already answered this before, but I'm still not clear why
> this notifier call can't just be added to the start of
> unregister_netdevice(), so we can avoid having driver needing to know
> anything about bonding internals?
> 
>  - R.

The action in bonding to a detach of slave is to unregister the master (see patch 10).
This can't be done from the context of unregister_netdevice itself (it is protected by rtnl_lock).

That's why I had to notify the detach before unregister begins.



^ permalink raw reply

* Re: Please pull 'upstream-davem' branch of wireless-2.6 (for 2.6.24)
From: David Miller @ 2007-09-23  6:04 UTC (permalink / raw)
  To: linville; +Cc: jeff, netdev, linux-wireless
In-Reply-To: <20070922195457.GA22629@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Sat, 22 Sep 2007 15:54:57 -0400

> Another round of miscellaneous driver and stack fixes intended for
> 2.6.24...
> 
> The tree is based on the latest net-2.6.24 as of this morning.
> I've included a 'master-davem' branch in my tree as a reference in
> case net-2.6.24 gets rebased again in the meantime.

Hey John.

I'm busy away from home this weekend since last Thursday, and I should
be back late Monday night so you can probably expect your pending bits
to be pulled in some time on Tuesday.

Thanks!

^ permalink raw reply

* Re: bind and O_NONBLOCK
From: David Miller @ 2007-09-23  5:58 UTC (permalink / raw)
  To: drepper; +Cc: johnpol, netdev, alan
In-Reply-To: <46F54CA5.8020200@redhat.com>

From: Ulrich Drepper <drepper@redhat.com>
Date: Sat, 22 Sep 2007 10:11:01 -0700

> There was no public mail.  I asked RH engineering for proposals for
> changes to the POSIX spec and Alan replied.

Please do not discuss such proposals only privately, especially when
the ramifications affect the entire community.

It is important the things get hashed out on a public forum where
all networking developers can add their insight into the problem.

^ permalink raw reply

* Re: incorrect cksum with tcp/udp on lo with 2.6.20/2.6.21/2.6.22
From: Herbert Xu @ 2007-09-23  4:39 UTC (permalink / raw)
  To: Krzysztof Oledzki; +Cc: netdev
In-Reply-To: <Pine.LNX.4.64.0709131942370.27961@bizon.gios.gov.pl>

Krzysztof Oledzki <olel@ans.pl> wrote:
> 
> It seems that after some not very recent changes udp and tcp packes 
> carring data send by a loopback have incorrect cksum:

This correct.  The loopback interfaces has the no checksum flag
set so we only provide a partial checksum on output (i.e., the
pseudoheader without the payload).

We even export this to user-space via a flag.  So you should fix
tcpdump to read this flag and ignore the checksum.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run softirqnetwork code on SMP
From: john ye @ 2007-09-23  3:45 UTC (permalink / raw)
  To: hadi; +Cc: David Miller, netdev, kuznet, pekkas, jmorris, kaber, John Ye
In-Reply-To: <1190375023.4261.34.camel@localhost>

Dear Jamal,

Sorry, I sent to you all a not-good-formatted mail.
Thanks for instructions and corrections from you all.

I have thought that packet re-ordering for upper TCP protocol will become 
more intensive and this will make the network even slower.

I do randomly select a CPU to dispatch the skb to. Previously, I dispatch 
skb evenly to all CPUs( round robin, one by one). but I didn't find a quick 
coding. for_each_online_cpu is not quick enough.

According to my test result, it did make packet INPUT speed doubled because 
another CPU is used concurrently.
It seems the packets still keep "roughly ordering" after turning on BS 
patch.

The test is simple: use an 2400 lines of iptables -t filter -A INPUT -p 
tcp -s x.x.x.x --dport yy -j XXXX.
these rules make the current softirq be very busy on one CPU and make the 
incoming net very slow. after turning on BS, the speed doubled.

For NAT test, I didn't get a good result like INPUT because real environment 
limitation.
The test is very basic and is far from "full".

It seems to me that the cross-cpu spinlock_xxxx for the queue doesn't have 
big cost and is allowable in terms of CPU time consumption, compared with 
the gains by making other CPUs joint in the work.

I have made BS patch into a loadable module. 
http://linux.chinaunix.net/bbs/thread-909725-2-1.html and let others help 
with testing.

John Ye


----- Original Message ----- 
From: "jamal" <hadi@cyberus.ca>
To: "John Ye" <johny@asimco.com.cn>
Cc: "David Miller" <davem@davemloft.net>; <netdev@vger.kernel.org>; 
<kuznet@ms2.inr.ac.ru>; <pekkas@netcore.fi>; <jmorris@namei.org>; 
<kaber@coreworks.de>
Sent: Friday, September 21, 2007 7:43 PM
Subject: Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrently run 
softirqnetwork code on SMP


> On Fri, 2007-21-09 at 17:25 +0800, John Ye wrote:
>> David,
>>
>> Thanks for your reply. I understand it's not worth to do.
>>
>> I have made it a loadable module to fulfill the function. it mainly for 
>> busy
>> NAT gateway server with SMP to speed up.
>>
>
> John,
>
> It was a little hard to read your code; however, it does seems to me
> like will cause a massive amount of packet reordering to the end hosts
> using you as the gateway especially when it is receiving a lot of
> packets/second.
> You have a queue per CPU that connects your bottom and top half and
> several CPUs that may service a single NIC in your bottom half.
> one cpu in either bottom/top half has to be slightly loaded and you
> loose the ordering where incoming doesnt match outgoing packet order.
>
> cheers,
> jamal
>
> 



^ permalink raw reply

* Please pull 'upstream-davem' branch of wireless-2.6 (for 2.6.24)
From: John W. Linville @ 2007-09-22 19:54 UTC (permalink / raw)
  To: davem; +Cc: jeff, netdev, linux-wireless

Jeff & Dave,

Another round of miscellaneous driver and stack fixes intended for
2.6.24...

The tree is based on the latest net-2.6.24 as of this morning.
I've included a 'master-davem' branch in my tree as a reference in
case net-2.6.24 gets rebased again in the meantime.

Thanks!

John

---

The individual patches are available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/upstream-davem/

---

The following changes since commit 42765047105fdd496976bc1784d22eec1cd9b9aa:
  David S. Miller (1):
        [MAC80211]: Fix mixed declarations and code in ap_sta_ps_start().

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream-davem

Andrew Morton (1):
      p54pci: terminate pci table

Jesper Juhl (1):
      zd1211rw: Don't needlessly initialize variable to NULL in zd_chip

Johannes Berg (11):
      fix softmac lockdep reports
      mac80211: allow drivers to indicate failed FCS/PLCP checksum
      mac80211: remove key threshold stuff
      mac80211: remove IEEE80211_CONF_SSID_HIDDEN
      mac80211: yet more documentation
      mac80211: fix warnings introduced by the doc patches
      mac80211: remove tx info sw_retry_attempt member
      mac80211: print out wiphy name instead of master device
      mac80211: rename ieee80211_cfg.c to cfg.c
      mac80211: kill IE parse typedef
      mac80211: kill vlan_id

Larry Finger (3):
      bcm43xx: Change radio hardware switch status printk from debug to regular
      b43legacy: Support for turning the radio off from software.
      b43legacy: Change the hardware radio enable logic and cleanup code

Michael Buesch (7):
      b43: Don't lock irq_lock in debugfs txpower adjust
      ssb: Use ioreadX() and iowriteX() for PCI.
      ssb: Sparse fixes.
      b43: Change loglevel of radio-enable message.
      mac80211: Add support for setting TX power and radio status
      b43: Remove the "radio hw enabled" message on startup.
      b43: Support for turning the radio off from software.

Michael Wu (1):
      mac80211: rename ieee80211_cfg.h to cfg.h

Ryan Mallon (2):
      libertas: set dnld_sent correctly for CF parts
      libertas: fix interrupts in CF driver

Ulrich Kunitz (1):
      zd1211rw: add USB id for Telegent TG54USB WLAN adapter

Vladimir Davydov (2):
      libertas: fix oops on the blackfin architecture
      libertas: fix oops on the blackfin architecture

Zhu Yi (2):
      iwlwifi: remove per-file CFLAGS for IWL define
      iwlwifi: create own directory for iwlwifi driver

 drivers/net/wireless/Kconfig                      |  130 +-------------
 drivers/net/wireless/Makefile                     |   12 +-
 drivers/net/wireless/b43/b43.h                    |   11 +-
 drivers/net/wireless/b43/debugfs.c                |   19 +--
 drivers/net/wireless/b43/leds.c                   |   15 +-
 drivers/net/wireless/b43/main.c                   |   44 ++++-
 drivers/net/wireless/b43/main.h                   |   17 --
 drivers/net/wireless/b43/phy.c                    |   48 ++++--
 drivers/net/wireless/b43legacy/b43legacy.h        |   11 +-
 drivers/net/wireless/b43legacy/leds.c             |   12 +-
 drivers/net/wireless/b43legacy/main.c             |   41 ++++-
 drivers/net/wireless/b43legacy/main.h             |   20 --
 drivers/net/wireless/b43legacy/phy.c              |   14 +--
 drivers/net/wireless/b43legacy/radio.c            |   41 ++++-
 drivers/net/wireless/bcm43xx/bcm43xx_main.c       |    4 +-
 drivers/net/wireless/bcm43xx/bcm43xx_radio.c      |    2 +-
 drivers/net/wireless/iwlwifi/Kconfig              |  128 +++++++++++++
 drivers/net/wireless/iwlwifi/Makefile             |    5 +
 drivers/net/wireless/{ => iwlwifi}/iwl-3945-hw.h  |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-3945-rs.c  |    2 +
 drivers/net/wireless/{ => iwlwifi}/iwl-3945-rs.h  |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-3945.c     |    2 +
 drivers/net/wireless/{ => iwlwifi}/iwl-3945.h     |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-4965-hw.h  |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-4965-rs.c  |    2 +
 drivers/net/wireless/{ => iwlwifi}/iwl-4965-rs.h  |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-4965.c     |    2 +
 drivers/net/wireless/{ => iwlwifi}/iwl-4965.h     |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-channel.h  |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-commands.h |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-debug.h    |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-eeprom.h   |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-helpers.h  |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-hw.h       |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-io.h       |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-priv.h     |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-prph.h     |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl-spectrum.h |    0 
 drivers/net/wireless/{ => iwlwifi}/iwl3945-base.c |    2 +
 drivers/net/wireless/{ => iwlwifi}/iwl4965-base.c |    2 +
 drivers/net/wireless/{ => iwlwifi}/iwlwifi.h      |    0 
 drivers/net/wireless/libertas/if_cs.c             |   42 +++--
 drivers/net/wireless/libertas/scan.c              |    8 +-
 drivers/net/wireless/p54pci.c                     |    1 +
 drivers/net/wireless/zd1211rw/zd_chip.c           |    2 +-
 drivers/net/wireless/zd1211rw/zd_usb.c            |    1 +
 drivers/ssb/b43_pci_bridge.c                      |    2 +
 drivers/ssb/driver_chipcommon.c                   |    7 +-
 drivers/ssb/pci.c                                 |   18 +-
 include/net/ieee80211softmac.h                    |    2 +
 include/net/mac80211.h                            |  208 +++++++++++++++------
 net/ieee80211/softmac/ieee80211softmac_assoc.c    |    8 +-
 net/ieee80211/softmac/ieee80211softmac_auth.c     |    8 +-
 net/ieee80211/softmac/ieee80211softmac_event.c    |    2 +-
 net/ieee80211/softmac/ieee80211softmac_module.c   |   10 +-
 net/ieee80211/softmac/ieee80211softmac_scan.c     |    4 +-
 net/ieee80211/softmac/ieee80211softmac_wx.c       |    8 +-
 net/mac80211/Makefile                             |    2 +-
 net/mac80211/{ieee80211_cfg.c => cfg.c}           |    2 +-
 net/mac80211/{ieee80211_cfg.h => cfg.h}           |    6 +-
 net/mac80211/debugfs.c                            |    4 -
 net/mac80211/debugfs_sta.c                        |    1 -
 net/mac80211/hostapd_ioctl.h                      |    1 -
 net/mac80211/ieee80211.c                          |   58 ++-----
 net/mac80211/ieee80211_common.h                   |    2 +-
 net/mac80211/ieee80211_i.h                        |    7 -
 net/mac80211/ieee80211_ioctl.c                    |   42 ++++-
 net/mac80211/ieee80211_rate.c                     |    4 +-
 net/mac80211/ieee80211_sta.c                      |    9 +-
 net/mac80211/rx.c                                 |   42 +++-
 net/mac80211/sta_info.c                           |    4 +-
 net/mac80211/sta_info.h                           |    2 -
 net/mac80211/tx.c                                 |   16 +-
 net/mac80211/util.c                               |    6 +
 74 files changed, 664 insertions(+), 461 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/Kconfig
 create mode 100644 drivers/net/wireless/iwlwifi/Makefile
 rename drivers/net/wireless/{ => iwlwifi}/iwl-3945-hw.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-3945-rs.c (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-3945-rs.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-3945.c (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-3945.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-4965-hw.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-4965-rs.c (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-4965-rs.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-4965.c (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-4965.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-channel.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-commands.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-debug.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-eeprom.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-helpers.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-hw.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-io.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-priv.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-prph.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl-spectrum.h (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl3945-base.c (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwl4965-base.c (100%)
 rename drivers/net/wireless/{ => iwlwifi}/iwlwifi.h (100%)
 rename net/mac80211/{ieee80211_cfg.c => cfg.c} (98%)
 rename net/mac80211/{ieee80211_cfg.h => cfg.h} (55%)
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply

* Re: bind and O_NONBLOCK
From: Evgeniy Polyakov @ 2007-09-22 17:40 UTC (permalink / raw)
  To: Alan Cox; +Cc: Ulrich Drepper, netdev
In-Reply-To: <20070922173556.GA26346@devserv.devel.redhat.com>

On Sat, Sep 22, 2007 at 01:35:56PM -0400, Alan Cox (alan@redhat.com) wrote:
> On Sat, Sep 22, 2007 at 08:14:15PM +0400, Evgeniy Polyakov wrote:
> > of operations. There are four ways where bind can fail:
> > 
> > 1. unsufficient rights - nothing can help here
> > 2. there is no memory - async binding can not help here too, since it
> > 	some memory just has to be allocated to save async request
> > 	somewhere.
> > 3. socket is locked.
> > 4. addres is being bound is in use.
> 
> For most protocols yes - but not all. For things like IP specifying O_NDELAY
> is meaningless on a bind it will always complete on the spot as you say

Yes, of course, bind conflict can be handled in different way as Ulrich noted - 
from checking bind bucket, to request remote node if address is in use or not.

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: bind and O_NONBLOCK
From: Alan Cox @ 2007-09-22 17:35 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: Ulrich Drepper, netdev, Alan Cox
In-Reply-To: <20070922161414.GA29637@2ka.mipt.ru>

On Sat, Sep 22, 2007 at 08:14:15PM +0400, Evgeniy Polyakov wrote:
> of operations. There are four ways where bind can fail:
> 
> 1. unsufficient rights - nothing can help here
> 2. there is no memory - async binding can not help here too, since it
> 	some memory just has to be allocated to save async request
> 	somewhere.
> 3. socket is locked.
> 4. addres is being bound is in use.

For most protocols yes - but not all. For things like IP specifying O_NDELAY
is meaningless on a bind it will always complete on the spot as you say


^ permalink raw reply

* Re: bind and O_NONBLOCK
From: Evgeniy Polyakov @ 2007-09-22 17:19 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: netdev, Alan Cox
In-Reply-To: <46F54CA5.8020200@redhat.com>

On Sat, Sep 22, 2007 at 10:11:01AM -0700, Ulrich Drepper (drepper@redhat.com) wrote:
> Evgeniy Polyakov wrote:
> > Could you point to the original Alan's proposal, I only found short note
> > (as in you original mail) at opengroup.org and failed to correctly
> > googlify it in the web.
> 
> There was no public mail.  I asked RH engineering for proposals for
> changes to the POSIX spec and Alan replied.

Then I belive RH engineers will implement this issue and you should
not send this to netdev@ (maybe only as a warning for all others :)

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: bind and O_NONBLOCK
From: Ulrich Drepper @ 2007-09-22 17:11 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: netdev, Alan Cox
In-Reply-To: <20070922165938.GA11234@2ka.mipt.ru>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Evgeniy Polyakov wrote:
> Could you point to the original Alan's proposal, I only found short note
> (as in you original mail) at opengroup.org and failed to correctly
> googlify it in the web.

There was no public mail.  I asked RH engineering for proposals for
changes to the POSIX spec and Alan replied.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFG9Uyl2ijCOnn/RHQRAtyNAJ0TLrZ8P3VcoFDWT1g+Qft1eTU+1QCffus6
Tljy9S9Sxb7z09l/GBkLSvY=
=golD
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: bind and O_NONBLOCK
From: Evgeniy Polyakov @ 2007-09-22 16:59 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: netdev, Alan Cox
In-Reply-To: <46F540F2.1090109@redhat.com>

On Sat, Sep 22, 2007 at 09:21:06AM -0700, Ulrich Drepper (drepper@redhat.com) wrote:
> Evgeniy Polyakov wrote:
> > So, did I understand you correctly, that you want to introduce network
> > AIO here? (for example on behalf of work queue or something else?)
> 
> See Alan's mail.  All this was his proposal, I just got it accepted
> upstream.
> 
> The problem to solve is if you have a distributed network port set.
> Apparently NetBIOS has it but I could also imagine this to be useful in
> cluster implementations which have to appear as one machine.  In this
> case, before binding to a given port, you have to make sure no other
> machine already handles this port.

Yes, to handle bind conflict in some or another way.
Could you point to the original Alan's proposal, I only found short note
(as in you original mail) at opengroup.org and failed to correctly
googlify it in the web.

-- 
	Evgeniy Polyakov

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox