免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 思一克
打印 上一主题 下一主题

关于LINUX上中断在各个CPU之间的负载平衡问题 [复制链接]

论坛徽章:
0
51 [报告]
发表于 2007-09-22 16:43 |只看该作者
这是模块版本的BS实现, 仅仅适合与2.6.13-15内核版本. 欢迎实验.




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

  13. #include <linux/module.h>
  14. #include <linux/fs.h>
  15. #include <linux/pagemap.h>
  16. #include <linux/highmem.h>
  17. #include <linux/init.h>
  18. #include <linux/string.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/backing-dev.h>

  21. #include <asm/uaccess.h>



  22. #include <linux/module.h>
  23. #include <linux/moduleparam.h>
  24. #include <linux/types.h>
  25. #include <linux/errno.h>
  26. #include <linux/slab.h>
  27. #include <linux/romfs_fs.h>
  28. #include <linux/fs.h>
  29. #include <linux/init.h>
  30. #include <linux/pagemap.h>
  31. #include <linux/smp_lock.h>
  32. #include <linux/buffer_head.h>
  33. #include <linux/vfs.h>
  34. #include <linux/delay.h>
  35. #include <linux/bio.h>
  36. #include <linux/aio.h>
  37. #include <asm/uaccess.h>


  38. //for debug_syscalls
  39. #include <linux/kernel.h>
  40. #include <linux/sched.h>
  41. #include <linux/mm.h>
  42. #include <linux/smp.h>
  43. #include <linux/ptrace.h>
  44. #include <linux/user.h>
  45. #include <linux/security.h>
  46. #include <linux/list.h>

  47. #include <asm/pgtable.h>
  48. #include <asm/system.h>
  49. #include <asm/processor.h>
  50. #include <asm/i387.h>
  51. #include <asm/debugreg.h>
  52. #include <asm/ldt.h>
  53. #include <asm/desc.h>


  54. #include <linux/swap.h>
  55. //#include <linux/interrupt.h>
  56. #include <asm/i387.h>
  57. #include <asm/debugreg.h>
  58. #include <asm/ldt.h>
  59. #include <asm/desc.h>

  60. #include <linux/swap.h>

  61. #include <linux/init.h>
  62. #include <linux/sched.h>
  63. #include <linux/smp_lock.h>
  64. #include <linux/input.h>
  65. #include <linux/module.h>
  66. #include <linux/random.h>
  67. #include <linux/major.h>
  68. #include <linux/pm.h>
  69. #include <linux/proc_fs.h>
  70. #include <linux/kmod.h>
  71. #include <linux/interrupt.h>
  72. #include <linux/poll.h>
  73. #include <linux/device.h>
  74. #include <linux/devfs_fs_kernel.h>
  75. #include <linux/interrupt.h>
  76. #include <linux/workqueue.h>
  77. #include <linux/skbuff.h>

  78. #include <linux/config.h>
  79. #include <linux/mm.h>
  80. #include <linux/module.h>
  81. #include <linux/sysctl.h>
  82. #include <net/tcp.h>
  83. #include <net/inet_common.h>
  84. #include <linux/ipsec.h>
  85. #include <asm/unaligned.h>

  86. #include <asm/system.h>
  87. #include <linux/module.h>
  88. #include <linux/types.h>
  89. #include <linux/kernel.h>
  90. #include <linux/string.h>
  91. #include <linux/errno.h>
  92. #include <linux/config.h>

  93. #include <linux/net.h>
  94. #include <linux/socket.h>
  95. #include <linux/sockios.h>
  96. #include <linux/in.h>
  97. #include <linux/inet.h>
  98. #include <linux/netdevice.h>
  99. #include <linux/etherdevice.h>

  100. #include <net/snmp.h>
  101. #include <net/ip.h>
  102. #include <net/protocol.h>
  103. #include <net/route.h>
  104. #include <linux/skbuff.h>
  105. #include <net/sock.h>
  106. #include <net/arp.h>
  107. #include <net/icmp.h>
  108. #include <net/raw.h>
  109. #include <net/checksum.h>
  110. #include <linux/netfilter_ipv4.h>
  111. #include <net/xfrm.h>
  112. #include <linux/mroute.h>
  113. #include <linux/netlink.h>
  114. #include <net/route.h>"
  115. #include <linux/inetdevice.h>

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

  118. int (*Pip_options_rcv_srr)(struct sk_buff *skb);
  119. int (*Pnf_rcv_postxfrm_nonlocal)(struct sk_buff *skb);
  120. struct ip_rt_acct *ip_rt_acct;
  121. struct ipv4_devconf *Pipv4_devconf;

  122. #define ipv4_devconf (*Pipv4_devconf)
  123. //#define ip_rt_acct Pip_rt_acct
  124. #define ip_options_rcv_srr Pip_options_rcv_srr
  125. #define nf_rcv_postxfrm_nonlocal Pnf_rcv_postxfrm_nonlocal
  126. //extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
  127. //extern int ip_options_rcv_srr(struct sk_buff *skb);
  128. static struct workqueue_struct **Pkeventd_wq;
  129. #define keventd_wq (*Pkeventd_wq)


  130. #define INSERT_CODE_HERE   


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

  136. /*
  137. * Initialise the virtual path cache for the packet. It describes
  138. * how the packet travels inside Linux networking.
  139. */
  140. if (skb->dst == NULL) {
  141. if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
  142. if (err == -EHOSTUNREACH)
  143. IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
  144. goto drop;
  145. }
  146. }

  147. if (nf_xfrm_nonlocal_done(skb))
  148. return nf_rcv_postxfrm_nonlocal(skb);

  149. #ifdef CONFIG_NET_CLS_ROUTE
  150. if (skb->dst->tclassid) {
  151. struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
  152. u32 idx = skb->dst->tclassid;
  153. st[idx&0xFF].o_packets++;
  154. st[idx&0xFF].o_bytes+=skb->len;
  155. st[(idx>>16)&0xFF].i_packets++;
  156. st[(idx>>16)&0xFF].i_bytes+=skb->len;
  157. }
  158. #endif

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

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

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

  173. if (ip_options_compile(NULL, skb))
  174. goto inhdr_error;

  175. opt = &(IPCB(skb)->opt);
  176. if (opt->srr) {
  177. struct in_device *in_dev = in_dev_get(dev);
  178. if (in_dev) {
  179. if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
  180. if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
  181. printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
  182.        NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
  183. in_dev_put(in_dev);
  184. goto drop;
  185. }
  186. in_dev_put(in_dev);
  187. }
  188. if (ip_options_rcv_srr(skb))
  189. goto drop;
  190. }
  191. }

  192. return dst_input(skb);

  193. inhdr_error:
  194. IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
  195. drop:
  196.         kfree_skb(skb);
  197.         return NET_RX_DROP;
  198. }



  199. #define CONFIG_BOTTOM_SOFTIRQ_SMP
  200. #define CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL

  201. #ifdef CONFIG_BOTTOM_SOFTIRQ_SMP

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

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

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

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

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

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

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

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

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

  264. #define BS_USE_PERCPU_DATA
  265. struct cpu_stat {
  266. unsigned long irqs; //total irqs
  267. unsigned long dids; //I did,
  268. unsigned long others;
  269. unsigned long works;
  270. };
  271. #define BS_CPU_STAT_DEFINED

  272. static int nr_cpus = 0;

  273. #ifdef BS_USE_PERCPU_DATA
  274. static DEFINE_PER_CPU(struct sk_buff_head, bs_cpu_queues); // cacheline_aligned_in_smp;
  275. static DEFINE_PER_CPU(struct work_struct, bs_works);
  276. //static DEFINE_PER_CPU(struct cpu_stat, bs_cpu_status);
  277. struct cpu_stat bs_cpu_status[NR_CPUS] = { {0, }, {0, }, };
  278. #else
  279. #define NR_CPUS  8
  280. static struct sk_buff_head bs_cpu_queues[NR_CPUS];
  281. static struct work_struct  bs_works[NR_CPUS];
  282. static struct cpu_stat    bs_cpu_status[NR_CPUS];
  283. #endif

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


  289. static void bs_func(void *data)
  290. {
  291. int flags, num, cpu;
  292. struct sk_buff *skb;
  293. struct work_struct *bs_works;
  294. struct sk_buff_head *q;
  295. cpu = smp_processor_id();


  296. #ifdef BS_USE_PERCPU_DATA
  297. bs_works = &per_cpu(bs_works, cpu);
  298. q = &per_cpu(bs_cpu_queues, cpu);
  299. #else
  300. bs_works = &bs_works[cpu];
  301. q = &bs_cpu_queues[cpu];
  302. #endif

  303. local_bh_disable();
  304. restart:
  305. num = 0;
  306. while(1) {
  307. spin_lock_irqsave(&q->lock, flags);
  308.         skb = __skb_dequeue(q);
  309. spin_unlock_irqrestore(&q->lock, flags);
  310. if(!skb) break;
  311. num++;
  312. //local_bh_disable();
  313.         ip_rcv1(skb, skb->dev);
  314. //__local_bh_enable(); //sub_preempt_count(SOFTIRQ_OFFSET - 1);
  315. }

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

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

  321. return;
  322. }

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

  325. spinlock_t lock;

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

  328. struct list_head worklist;
  329. wait_queue_head_t more_work;
  330. wait_queue_head_t work_done;

  331. struct workqueue_struct *wq;
  332. task_t *thread;

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


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

  341. extern struct workqueue_struct *keventd_wq;

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

  347. spin_lock_irqsave(&cwq->lock, flags);
  348. work->wq_data = cwq;
  349. list_add_tail(&work->entry, &cwq->worklist);
  350. cwq->insert_sequence++;
  351. wake_up(&cwq->more_work);
  352. spin_unlock_irqrestore(&cwq->lock, flags);
  353. }

  354. #endif //CONFIG_BOTTOM_SOFTIRQ_SMP

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

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

  369. IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES);

  370. if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
  371. IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
  372. goto out;
  373. }

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

  376. iph = skb->nh.iph;

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

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

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

  391. iph = skb->nh.iph;

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

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

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

  407. #ifdef CONFIG_BOTTOM_SOFTIRQ_SMP

  408. if(!nr_cpus)
  409. nr_cpus = num_online_cpus();

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

  415. cur = smp_processor_id();

  416. bs_cpu_status[cur].irqs++;

  417. if(!nr_cpus) {
  418. nr_cpus = num_online_cpus();
  419. }

  420. //random distribute
  421. cpu = (bs_cpu_status[cur].irqs % nr_cpus);
  422. if(cpu == cur) {
  423. bs_cpu_status[cpu].dids++;
  424. return ip_rcv1(skb, dev);
  425. }

  426. #ifdef BS_USE_PERCPU_DATA
  427. q = &per_cpu(bs_cpu_queues, cpu);
  428. #else
  429. q = &bs_cpu_queues[cpu];
  430. #endif

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


  434. #ifdef BS_USE_PERCPU_DATA
  435. bs_works = &per_cpu(bs_works, cpu);
  436. #else
  437. bs_works = &bs_works[cpu];
  438. #endif
  439.         spin_lock_irqsave(&q->lock, flags);
  440. __skb_queue_tail(q, skb);
  441.         spin_unlock_irqrestore(&q->lock, flags);
  442.         
  443.            if (!bs_works->func) {
  444.       INIT_WORK(bs_works, bs_func, q);
  445. bs_cpu_status[cpu].works++;
  446. preempt_disable();
  447. __queue_work(keventd_wq->cpu_wq + cpu, bs_works);
  448. preempt_enable();
  449. }
  450. } else {
  451. int cpu = smp_processor_id();
  452. bs_cpu_status[cpu].irqs++;
  453. bs_cpu_status[cpu].dids++;
  454. return ip_rcv1(skb, dev);
  455. }
  456. return 0;
  457. #else
  458. return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish, nf_hook_input_cond(skb));
  459. #endif //CONFIG_BOTTOM_SOFTIRQ_SMP


  460. inhdr_error:
  461. IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
  462. drop:
  463.         kfree_skb(skb);
  464. out:
  465.         return NET_RX_DROP;
  466. }


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

  468. /* COPY_OUT_START_TO net/sysctl_net.c */
  469. #ifdef CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL
  470. #if !defined(BS_CPU_STAT_DEFINED)
  471. struct cpu_stat {
  472. unsigned long irqs; //total irqs
  473. unsigned long dids; //I did,
  474. unsigned long others;
  475. unsigned long works;
  476. };
  477. #endif
  478. extern struct cpu_stat bs_cpu_status[NR_CPUS];

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

  481. static ctl_table bs_ctl_table[]={

  482. /* COPY_OUT_START_TO net/sysctl_net.c */
  483. {
  484. .ctl_name = 99,
  485. .procname = "bs_status",
  486. .data = &bs_cpu_status,
  487. .maxlen = sizeof(bs_cpu_status),
  488. .mode = 0644,
  489. .proc_handler = &proc_dointvec,
  490. },

  491. {
  492. .ctl_name = 99,
  493. .procname = "bs_enable",
  494. .data = &bs_enable,
  495. .maxlen = sizeof(int),
  496. .mode = 0644,
  497. .proc_handler = &proc_dointvec,
  498. },
  499. /* COPY_OUT_END_TO net/net_sysctl.c */

  500. { 0, },
  501. };

  502. static ctl_table bs_sysctl_root[] = {
  503. {
  504. .ctl_name = CTL_NET,
  505. .procname = "net",
  506. .mode = 0555,
  507. .child = bs_ctl_table,
  508. },
  509.   { 0, },
  510. };

  511. struct ctl_table_header *bs_sysctl_hdr;
  512. register_bs_sysctl(void)
  513. {
  514. bs_sysctl_hdr = register_sysctl_table(bs_sysctl_root, 0);
  515. return 0;
  516. }

  517. unregister_bs_sysctl(void)
  518. {
  519. unregister_sysctl_table(bs_sysctl_hdr);
  520. }

  521. #endif //CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL

  522. #if 1
  523. seeker_init()
  524. {
  525. int i;
  526. if(nr_cpus == 0)
  527. nr_cpus = num_online_cpus();
  528. register_bs_sysctl();
  529. }

  530. seeker_exit()
  531. {
  532. unregister_bs_sysctl();
  533. bs_enable = 0;
  534. msleep(1000);
  535. flush_scheduled_work();
  536. msleep(1000);
  537. printk("......exit...........\n");
  538. }
  539. #endif










  540. /*--------------------------------------------------------------------------
  541. */
  542. struct packet_type *dev_find_pack(int type)
  543. {
  544. struct list_head *head;
  545. struct packet_type *pt1;

  546. spin_lock_bh(p_ptype_lock);

  547. head = &p_ptype_base[type & 15];

  548. list_for_each_entry(pt1, head, list) {
  549. printk("pt1: %x\n", pt1->type);
  550. if (pt1->type == htons(type)) {
  551. printk("FOUND\n");
  552. goto out;
  553. }
  554. }

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


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

  564. unsigned long sysmap_name2addr(char *name)
  565. {
  566. char *cp, *dp;
  567. unsigned long addr;
  568. int len, n;

  569.     if(!sysmap_buf) return 0;
  570.     if(!name || !name[0]) return 0;
  571.     n = strlen(name);
  572.     for(cp = sysmap_buf; ;) {
  573.     cp = strstr(cp, name);
  574.     if(!cp) return 0;

  575. for(dp = cp; *dp && *dp != '\n' && *dp != ' ' && *dp != '\t'; dp++);
  576.         
  577. len = dp - cp;
  578. if(len < n) goto cont;
  579.         if(cp > sysmap_buf && cp[-1] != ' ' && cp[-1] != '\t') {
  580. goto cont;
  581. }
  582. if(len > n) {
  583. goto cont;
  584. }
  585. break;
  586. cont:
  587. if(*dp == 0) break;
  588.         cp += (len+1);
  589.     }
  590.    
  591.     cp -= 11;
  592.     if(cp > sysmap_buf && cp[-1] != '\n') {
  593. printk("_ERROR_ in name2addr cp = %p base %p\n", cp, sysmap_buf);
  594. return 0;
  595.     }
  596.     sscanf(cp, "%x", &addr);
  597.     printk("%s -> %p\n", name, addr);

  598.     return addr;   
  599. }

  600. char *kas_init()
  601. {
  602. struct file *fp;
  603. int i;
  604. long addr;
  605. struct kstat st;
  606. mm_segment_t old_fs;

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

  610.     old_fs = get_fs();
  611.     set_fs(get_ds()); //systemp_map is __user variable
  612.     i = vfs_stat(system_map, &st);
  613.     set_fs(old_fs);

  614.     //sysmap_size = 1024*1024; //error
  615.     sysmap_size = st.size + 32;
  616.     fp = filp_open(system_map, O_RDONLY, FMODE_READ);
  617.    
  618.     if(!fp) return 1;
  619.     sysmap_buf = vmalloc(sysmap_size);
  620.     if(!sysmap_buf) return 2;
  621.     i = kernel_read(fp, 0, sysmap_buf, sysmap_size);   
  622.     if(i <= 0) {
  623. filp_close(fp, 0);
  624. vfree(sysmap_buf);
  625. sysmap_buf = 0;
  626. return 3;
  627.     }
  628.     sysmap_size = i;
  629.     *(int*)&sysmap_buf[i] = 0;
  630.     filp_close(fp, 0);
  631.     //sysmap_symbol2addr = sysmap_name2addr;
  632.    
  633.    
  634.     p_ptype_lock = sysmap_name2addr("ptype_lock");
  635.     p_ptype_base = sysmap_name2addr("ptype_base");
  636.     /*
  637.     int (*Pip_options_rcv_srr)(struct sk_buff *skb);
  638.     int (*Pnf_rcv_postxfrm_nonlocal)(struct sk_buff *skb);
  639.     struct ip_rt_acct *ip_rt_acct;
  640.     struct ipv4_devconf *Pipv4_devconf;
  641.     */
  642.     Pkeventd_wq = sysmap_name2addr("keventd_wq");
  643.     //keventd_wq = *(long *)&keventd_wq;
  644.    
  645.     Pip_options_rcv_srr = sysmap_name2addr("ip_options_rcv_srr");
  646.     Pnf_rcv_postxfrm_nonlocal = sysmap_name2addr("nf_rcv_postxfrm_nonlocal");
  647.     ip_rt_acct = sysmap_name2addr("ip_rt_acct");
  648.     Pipv4_devconf = sysmap_name2addr("ipv4_devconf");
  649.     printk("lock = %p base = %p\n", p_ptype_lock, p_ptype_base);
  650.     vfree(sysmap_buf);
  651.    
  652. }


  653. struct packet_type *ip_handler;
  654. static int  __init init()
  655. {
  656. struct packet_type *pt;
  657. kas_init();
  658. pt = dev_find_pack(ETH_P_IP);
  659. if(!pt) return -1;
  660. //printk("pt %p func ip_rcv %p should be %p\n", pt, pt->func, ip_rcv);

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

  666. ip_handler = pt;
  667. unlock_kernel();
  668. seeker_init();
  669. return 0;
  670. }

  671. static void __exit exit(void)
  672. {
  673. seeker_exit();
  674. lock_kernel();
  675. if(ip_handler->func == REP_ip_rcv)
  676. ip_handler->func = ip_rcv;
  677. else
  678. printk("error...\n");
  679. unlock_kernel();
  680. }

  681. module_init(init)
  682. module_exit(exit)
  683. MODULE_LICENSE("GPL");

复制代码

论坛徽章:
0
52 [报告]
发表于 2007-09-22 20:26 |只看该作者
  1. [quote]
  2. local_bh_disable(); //timer lost and local cpu suck
  3. restart:
  4. num = 0;
  5. while(1) {
  6. spin_lock_irqsave(&q->lock, flags);
  7.         skb = __skb_dequeue(q);
  8. spin_unlock_irqrestore(&q->lock, flags);
  9. if(!skb) break;
  10. num++;
  11. //local_bh_disable();
  12.         ip_rcv1(skb, skb->dev);
  13. //__local_bh_enable(); //sub_preempt_count(SOFTIRQ_OFFSET - 1);
  14. }

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

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

  20. return;
  21. [/quote]
复制代码

论坛徽章:
0
53 [报告]
发表于 2007-09-22 23:18 |只看该作者
我在研究你的指正. 没有结论所以没有给你回.

这个目的我是不让在处理其间调度走.
但一轮完了后就调度走了.
num会成为0.

那个if(num > 0) goto restart

其实没有多大用途.

肯定有不周到(BUG)地方.所以让各位TESTING

论坛徽章:
0
54 [报告]
发表于 2007-09-23 13:33 |只看该作者
seeker did really nice job in BH way,
and local_bh_disable is too stronger,
btw, rx_softirq is driven by timer conditionally,
and scheduled by kthread,
so, it sounds nicer to ask linux complete what u dream,
especially when alot work remains in user space.

论坛徽章:
0
55 [报告]
发表于 2007-09-24 09:05 |只看该作者
to 斑竹,sisi8408等各位,

认真的,你们谁有条件帮做做测试。无论是肯定的还是否定的结果都要,真实就可以。
还要有简单的测试方法和结果数据。

测试主要就是在iptables,大流量下的效果。

如果这东西真能有些用处,我会在程序头将做测试工作的人(name, email, date)一一列出在上面。
如果证明无用被抛弃,那么就算大家尽义务了。

THANKS

论坛徽章:
0
56 [报告]
发表于 2007-09-27 09:02 |只看该作者
通过讨论,已经改进了成新的模块代码。

贴在我的BLOG上。

主要改动是避免IP包因为并行处理到达的太快而引起的重组问题。

http://blog.chinaunix.net/u/12848/showart.php?id=389602

论坛徽章:
0
57 [报告]
发表于 2007-09-27 09:24 |只看该作者
原帖由 思一克 于 2007-6-29 11:04 发表
关于LINUX上中断在各个CPU之间的负载平衡问题

看帖子
http://linux.chinaunix.net/bbs/thread-753474-1-1.html

说4个CPU有严重的不平衡问题。因为无条件实验,
LZ也不在回贴。所以请有兴趣的来参加实验 ...

monitor kernel  load  status and user process  number in running ,  if the kernel  load  no heavy  and is so light , this cause is normal , else is a problem .

论坛徽章:
0
58 [报告]
发表于 2007-10-10 01:49 |只看该作者
to 斑竹,sisi8408等各位,

认真的,你们谁有条件帮做做测试。无论是肯定的还是否定的结果都要,真实就可以。
还要有简单的测试方法和结果数据。

测试主要就是在iptables,大流量下的效果。

如果这东西真能有些用处,我会在程序头将做测试工作的人(name, email, date)一一列出在上面。
如果证明无用被抛弃,那么就算大家尽义务了。

THANKS


你大爷的, i cough,
俺敬仰的seeker,说这样不负责任的话,俺就再cough。

不自信?你的那么漂亮的工作,不就没人测么,你着哪门子急?
有一些暇疵就放弃?说不过去呀。

俺回京就去找你。

论坛徽章:
0
59 [报告]
发表于 2007-10-10 09:34 |只看该作者
谢谢你的认可。

我现在已经将bridge, ipv6, 等所有在softirq中的NETFILTER都给并行了。一会将PATCH贴出来。


原帖由 sisi8408 于 2007-10-10 01:49 发表


你大爷的, i cough,
俺敬仰的seeker,说这样不负责任的话,俺就再cough。

不自信?你的那么漂亮的工作,不就没人测么,你着哪门子急?
有一些暇疵就放弃?说不过去呀。

俺回京就去找你。

论坛徽章:
0
60 [报告]
发表于 2007-10-10 09:37 |只看该作者
BOTTOM SOFTIRQ version 2.

将各协议在softirq中的运行都并行了。不仅仅ipv4. 欢迎测试。


  1. --- linux-2.6.23-rc8/net/core/dev.c 2007-09-25 08:33:10.000000000 +0800
  2. +++ linux-2.6.23-rc8/net/core/dev.c 2007-10-10 09:30:30.000000000 +0800
  3. @@ -1919,12 +1919,269 @@
  4. }
  5. #endif

  6. +
  7. +#define CONFIG_BOTTOM_SOFTIRQ_SMP
  8. +#define CONFIG_BOTTOM_SOFTIRQ_SMP_SYSCTL
  9. +
  10. +
  11. +#ifdef CONFIG_BOTTOM_SOFTIRQ_SMP
  12. +
  13. +/*
  14. +[PATCH: 2.6.13-15-SMP 1/2] network: concurrently run softirq network code on SMP
  15. +Bottom Softirq Implementation. John Ye, 2007.08.27
  16. +
  17. +This is the version 2 BS patch. it will make parallelization for all protocol's
  18. +netfilter runing in softirq, IPV4, IPV6, bridge, etc.
  19. +
  20. +Why this patch:
  21. +Make kernel be able to concurrently execute softirq's net code on SMP system.
  22. +Take full advantages of SMP to handle more packets and greatly raises NIC throughput.
  23. +The current kernel's net packet processing logic is:
  24. +1) The CPU which handles a hardirq must be executing its related softirq.
  25. +2) One softirq instance(irqs handled by 1 CPU) can't be executed on more than 2 CPUs
  26. +at the same time.
  27. +The limitation make kernel network be hard to take the advantages of SMP.
  28. +
  29. +How this patch:
  30. +It splits the current softirq code into 2 parts: the cpu-sensitive top half,
  31. +and the cpu-insensitive bottom half, then make bottom half(calld BS) be
  32. +executed on SMP concurrently.
  33. +The two parts are not equal in terms of size and load. Top part has constant code
  34. +size(mainly, in net/core/dev.c and NIC drivers), while bottom part involves
  35. +netfilter(iptables) whose load varies very much. An iptalbes with 1000 rules to match
  36. +will make the bottom part's load be very high. So, if the bottom part softirq
  37. +can be distributed to processors and run concurrently on them, the network will
  38. +gain much more packet handling capacity, network throughput will be be increased
  39. +remarkably.
  40. +
  41. +Where useful:
  42. +It's useful on SMP machines that meet the following 2 conditions:
  43. +1) have high kernel network load, for example, running iptables with thousands of rules, etc).
  44. +2) have more CPUs than active NICs, e.g. a 4 CPUs machine with 2 NICs).
  45. +On these system, with the increase of softirq load, some CPUs will be idle
  46. +while others(number is equal to # of NIC) keeps busy.
  47. +IRQBALANCE will help, but it only shifts IRQ among CPUS, makes no softirq concurrency.
  48. +Balancing the load of each cpus will not remarkably increase network speed.
  49. +
  50. +Where NOT useful:
  51. +If the bottom half of softirq is too small(without running iptables), or the network
  52. +is too idle, BS patch will not be seen to have visible effect. But It has no
  53. +negative affect either.
  54. +User can turn off BS functionality by set /proc/sys/net/bs_policy value to 0.
  55. +
  56. +How to test:
  57. +On a linux box, run iptables, add 2000 rules to table filter & table nat to simulate huge
  58. +softirq load. Then, open 20 ftp sessions to download big file. On another machine(who
  59. +use this test machine as gateway), open 20 more ftp download sessions. Compare the speed,
  60. +without BS enabled, and with BS enabled.
  61. +cat /proc/sys/net/bs_policy. 1 for flow dispatch, 2 random dispatch. 0 no dispatch.
  62. +cat /proc/sys/net/bs_status. this shows the usage of each CPUs
  63. +Test shown that when bottom softirq load is high, the network throughput can be nearly
  64. +doubled on 2 CPUs machine. hopefully it may be quadrupled on a 4 cpus linux box.
  65. +
  66. +Bugs:
  67. +It will NOT allow hotplug CPU.
  68. +It only allows incremental CPUs ids, starting from 0 to num_online_cpus().
  69. +for example, 0,1,2,3 is OK. 0,1,8,9 is KO.
  70. +
  71. +Some considerations in the future:
  72. +1) With BS patch, the irq balance code on arch/i386/kernel/io_apic.c seems no need any more,
  73. +at least not for network irq.
  74. +2) Softirq load will become very small. It only run the top half of old softirq, which
  75. +is much less expensive than bottom half---the netfilter program.
  76. +To let top softirq process more packets, can these 3 network parameters be given a larger value?
  77. +extern int netdev_max_backlog = 1000;
  78. +extern int netdev_budget = 300;
  79. +extern int weight_p = 64;
  80. +3) Now, BS are running on built-in keventd thread, we can create new workqueues to let it run on?
  81. +
  82. +Signed-off-by: John Ye (Seeker) <[email]johny@webizmail.com[/email]>
  83. +*/
  84. +
  85. +
  86. +#define CBPTR( skb ) (*((void **)(skb->cb)))
  87. +#define BS_USE_PERCPU_DATA
  88. +struct cpu_stat
  89. +{
  90. +        unsigned long irqs;                       //total irqs
  91. +        unsigned long dids;                       //I did,
  92. +        unsigned long works;
  93. +};
  94. +#define BS_CPU_STAT_DEFINED
  95. +
  96. +static int nr_cpus = 0;
  97. +
  98. +#define BS_POL_LINK     1
  99. +#define BS_POL_RANDOM   2
  100. +int bs_policy = BS_POL_LINK; //cpu hash. 0 will turn off BS. 1 link based, 2 random
  101. +
  102. +static DEFINE_PER_CPU(struct sk_buff_head, bs_cpu_queues);
  103. +static DEFINE_PER_CPU(struct work_struct, bs_works);
  104. +//static DEFINE_PER_CPU(struct cpu_stat, bs_cpu_status);
  105. +struct cpu_stat bs_cpu_status[NR_CPUS];
  106. +
  107. +//static int __netif_recv_skb(struct sk_buff *skb, struct net_device *odev);
  108. +static int __netif_recv_skb(struct sk_buff *skb);
  109. +
  110. +static void bs_func(struct work_struct *data)
  111. +{
  112. +        int flags, num, cpu;
  113. +        struct sk_buff *skb;
  114. +        struct work_struct *bs_works;
  115. +        struct sk_buff_head *q;
  116. +        cpu = smp_processor_id();
  117. +
  118. +        bs_works = &per_cpu(bs_works, cpu);
  119. +        q = &per_cpu(bs_cpu_queues, cpu);
  120. +
  121. +        //local_bh_disable();
  122. +        restart:
  123. +
  124. +        num = 0;
  125. +        while(1)
  126. +        {
  127. +                spin_lock_irqsave(&q->lock, flags);
  128. +                if(!(skb = __skb_dequeue(q))) {
  129. +                spin_unlock_irqrestore(&q->lock, flags);
  130. + break;
  131. + }
  132. +                spin_unlock_irqrestore(&q->lock, flags);
  133. +                num++;
  134. +
  135. +                local_bh_disable();
  136. +                __netif_recv_skb(skb);
  137. +                local_bh_enable();      // sub_preempt_count(SOFTIRQ_OFFSET - 1);
  138. +        }
  139. +
  140. +        bs_cpu_status[cpu].dids += num;
  141. +        //if(num > 2) printk("%d %d\n", num, cpu);
  142. +        if(num > 0)
  143. +                goto restart;
  144. +
  145. +        //__local_bh_enable();
  146. +        bs_works->func = 0;
  147. +
  148. +        return;
  149. +}
  150. +
  151. +struct cpu_workqueue_struct {
  152. +
  153. + spinlock_t lock;
  154. +
  155. + struct list_head worklist;
  156. + wait_queue_head_t more_work;
  157. + struct work_struct *current_work;
  158. +
  159. + struct workqueue_struct *wq;
  160. + struct task_struct *thread;
  161. +
  162. + int run_depth; /* Detect run_workqueue() recursion depth */
  163. +} ____cacheline_aligned;
  164. +
  165. +struct workqueue_struct {
  166. + struct cpu_workqueue_struct *cpu_wq;
  167. + struct list_head list;
  168. + const char *name;
  169. + int singlethread;
  170. + int freezeable; /* Freeze threads during suspend */
  171. +};
  172. +
  173. +#ifndef CONFIG_BOTTOM_SOFTIRQ_MODULE
  174. +extern void __queue_work(struct cpu_workqueue_struct *cwq, struct work_struct *work);
  175. +extern struct workqueue_struct *keventd_wq;
  176. +#endif
  177. +#include <linux/in.h>
  178. +#include <linux/ip.h>
  179. +#include <linux/tcp.h>
  180. +
  181. +static inline int bs_dispatch(struct sk_buff *skb)
  182. +{
  183. + struct iphdr *iph = ip_hdr(skb);
  184. +
  185. + if(!nr_cpus)
  186. + nr_cpus = num_online_cpus();
  187. +
  188. + if(bs_policy && nr_cpus > 1) { // && iph->protocol != IPPROTO_ICMP) {
  189. + //if(bs_policy && nr_cpus > 1 && iph->protocol == IPPROTO_ICMP) { //test on icmp first
  190. + unsigned int flags, cur, cpu;
  191. + struct work_struct *bs_works;
  192. + struct sk_buff_head *q;
  193. +
  194. + cpu = cur = smp_processor_id();
  195. +
  196. + bs_cpu_status[cur].irqs++;
  197. +
  198. + //good point for Jamal. thanks no reordering
  199. + if(bs_policy == BS_POL_LINK) {
  200. + int seed = 0;
  201. + if(iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
  202. + struct tcphdr *th = (struct tcphdr*)(iph + 1);  //udp is same as tcp
  203. + seed = ntohs(th->source) + ntohs(th->dest);
  204. + }
  205. + cpu = (iph->saddr + iph->daddr + seed) % nr_cpus;
  206. +
  207. + /*
  208. + if(net_ratelimit() && iph->protocol == IPPROTO_TCP) {
  209. + struct tcphdr *th = iph + 1;
  210. +
  211. + printk("seed %u (%u %u) cpu %d. source %d dest %d\n",
  212. +                                seed, iph->saddr + iph->daddr, iph->saddr + iph->daddr + seed, cpu,
  213. + ntohs(th->source), ntohs(th->dest));
  214. + }
  215. + */
  216. + } else
  217. + //random distribute
  218. + if(bs_policy == BS_POL_RANDOM)
  219. + cpu = (bs_cpu_status[cur].irqs % nr_cpus);
  220. +
  221. + //cpu = cur;
  222. + //cpu = (cur? 0: 1);
  223. +
  224. + if(cpu == cur) {
  225. + bs_cpu_status[cpu].dids++;
  226. + return __netif_recv_skb(skb);
  227. + }
  228. +
  229. + q = &per_cpu(bs_cpu_queues, cpu);
  230. +
  231. + if(!q->next) { // || skb_queue_len(q) == 0 ) {
  232. + skb_queue_head_init(q);
  233. + }
  234. +
  235. +
  236. + bs_works = &per_cpu(bs_works, cpu);
  237. + spin_lock_irqsave(&q->lock, flags);
  238. + __skb_queue_tail(q, skb);
  239. + spin_unlock_irqrestore(&q->lock, flags);
  240. +
  241. +    if (!bs_works->func) {
  242. +                        INIT_WORK(bs_works, bs_func);
  243. +                        bs_cpu_status[cpu].works++;
  244. +                        preempt_disable();
  245. + set_bit(WORK_STRUCT_PENDING, work_data_bits(bs_works));
  246. + __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), bs_works);
  247. +                        preempt_enable();
  248. + }
  249. +
  250. + } else {
  251. +
  252. + bs_cpu_status[smp_processor_id()].dids++;
  253. + return __netif_recv_skb(skb);
  254. + }
  255. + return 0;
  256. +}
  257. +
  258. +
  259. +
  260. +#endif
  261. +
  262. +
  263. int netif_receive_skb(struct sk_buff *skb)
  264. {
  265. - struct packet_type *ptype, *pt_prev;
  266. + //struct packet_type *ptype, *pt_prev;
  267.   struct net_device *orig_dev;
  268. - int ret = NET_RX_DROP;
  269. - __be16 type;
  270. + //int ret = NET_RX_DROP;
  271. + //__be16 type;

  272.   /* if we've gotten here through NAPI, check netpoll */
  273.   if (skb->dev->poll && netpoll_rx(skb))
  274. @@ -1947,6 +2204,19 @@
  275.   skb_reset_transport_header(skb);
  276.   skb->mac_len = skb->network_header - skb->mac_header;

  277. + CBPTR(skb) = orig_dev;
  278. + return bs_dispatch(skb);
  279. +}
  280. +
  281. +int __netif_recv_skb(struct sk_buff *skb)
  282. +{
  283. + struct packet_type *ptype, *pt_prev;
  284. + struct net_device *orig_dev;
  285. + int ret = NET_RX_DROP;
  286. + __be16 type;
  287. +
  288. + orig_dev = CBPTR(skb);
  289. + CBPTR(skb) = 0;
  290.   pt_prev = NULL;

  291.   rcu_read_lock();
  292. --- linux-2.6.23-rc8/kernel/workqueue.c 2007-09-25 08:33:10.000000000 +0800
  293. +++ linux-2.6.23-rc8/kernel/workqueue.c 2007-10-10 08:52:05.000000000 +0800
  294. @@ -138,7 +138,9 @@
  295. }

  296. /* Preempt must be disabled. */
  297. -static void __queue_work(struct cpu_workqueue_struct *cwq,
  298. +//static void __queue_work(struct cpu_workqueue_struct *cwq,
  299. +// struct work_struct *work)
  300. +void __queue_work(struct cpu_workqueue_struct *cwq,
  301.   struct work_struct *work)
  302. {
  303.   unsigned long flags;
  304. @@ -515,7 +517,12 @@
  305. }
  306. EXPORT_SYMBOL(cancel_delayed_work_sync);

  307. +
  308. +/*
  309. static struct workqueue_struct *keventd_wq __read_mostly;
  310. +*/
  311. +struct workqueue_struct *keventd_wq __read_mostly;
  312. +

  313. /**
  314.   * schedule_work - put work task in global workqueue
  315. @@ -848,5 +855,6 @@
  316.   cpu_singlethread_map = cpumask_of_cpu(singlethread_cpu);
  317.   hotcpu_notifier(workqueue_cpu_callback, 0);
  318.   keventd_wq = create_workqueue("events");
  319. + printk("keventd_wq %p %p OK.\n", keventd_wq, keventd_wq->cpu_wq);
  320.   BUG_ON(!keventd_wq);
  321. }
  322. --- linux-2.6.23-rc8/net/sysctl_net.c 2007-09-25 08:33:10.000000000 +0800
  323. +++ linux-2.6.23-rc8/net/sysctl_net.c 2007-10-09 21:10:41.000000000 +0800
  324. @@ -29,6 +29,15 @@
  325. #include <linux/if_tr.h>
  326. #endif

  327. +struct cpu_stat
  328. +{
  329. +        unsigned long irqs;                       /* total irqs on me */
  330. +        unsigned long dids;                       /* I did, */
  331. +        unsigned long works;                      /* q works */
  332. +};
  333. +extern int bs_policy;
  334. +extern struct cpu_stat bs_cpu_status[NR_CPUS];
  335. +
  336. struct ctl_table net_table[] = {
  337.   {
  338.   .ctl_name = NET_CORE,
  339. @@ -36,6 +45,24 @@
  340.   .mode = 0555,
  341.   .child = core_table,
  342.   },
  343. +
  344. +        {
  345. +                .ctl_name       = 99,
  346. +                .procname       = "bs_status",
  347. +                .data           = &bs_cpu_status,
  348. +                .maxlen         = sizeof(bs_cpu_status),
  349. +                .mode           = 0644,
  350. +                .proc_handler   = &proc_dointvec,
  351. +        },
  352. +        {
  353. +                .ctl_name       = 99,
  354. +                .procname       = "bs_policy",
  355. +                .data           = &bs_policy,
  356. +                .maxlen         = sizeof(int),
  357. +                .mode           = 0644,
  358. +                .proc_handler   = &proc_dointvec,
  359. +        },
  360. +
  361. #ifdef CONFIG_INET
  362.   {
  363.   .ctl_name = NET_IPV4,


复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP