* Re: pktgen
[not found] ` <20041127004325.GA17401@xi.wantstofly.org>
@ 2004-11-27 12:04 ` Robert Olsson
2004-11-27 13:53 ` pktgen Lennert Buytenhek
0 siblings, 1 reply; 23+ messages in thread
From: Robert Olsson @ 2004-11-27 12:04 UTC (permalink / raw)
To: Lennert Buytenhek; +Cc: Robert Olsson, hadi, netdev
Lennert Buytenhek writes:
> Can you do me a favor and run the attached script on your box that can
> do 870kpps and send me the output?
OK! netdev is cc:ed as there are related discussions...
sleep was 1 sec and I run SMP kernel. UP kernel give some extra kpps
acript data is attached as well as some systeminfo.
--ro
> #!/bin/sh
>
> DEVICE=eth1
> MAC=00:0E:0C:64:CC:A1
>
> for size in `seq 60 4 1500`
> do
> echo rem_device_all > /proc/net/pktgen/kpktgend_0
> echo add_device $DEVICE > /proc/net/pktgen/kpktgend_0
>
> echo min_pkt_size $size > /proc/net/pktgen/$DEVICE
> echo max_pkt_size $size > /proc/net/pktgen/$DEVICE
> echo count 1000000 > /proc/net/pktgen/$DEVICE
> echo clone_skb 1000000 > /proc/net/pktgen/$DEVICE
> echo dst_min 10.10.10.1 > /proc/net/pktgen/$DEVICE
> echo dst_max 10.10.10.1 > /proc/net/pktgen/$DEVICE
> echo src_min 10.10.10.2 > /proc/net/pktgen/$DEVICE
> echo src_max 10.10.10.2 > /proc/net/pktgen/$DEVICE
> echo src_mac $MAC > /proc/net/pktgen/$DEVICE
> echo dst_mac $MAC > /proc/net/pktgen/$DEVICE
>
> echo start > /proc/net/pktgen/pgctrl
> sleep 0.1
> echo -ne "$size\t"
> tail -1 /proc/net/pktgen/$DEVICE | awk '{print $1}' | sed s/pps//
> done
>
60 825789
64 748975
68 729149
72 719721
76 720204
80 720127
84 702722
88 702799
92 705107
96 701711
100 703858
104 692120
108 696139
112 708936
116 697780
120 677887
124 678158
128 739290
132 737070
136 736894
140 737645
144 737816
148 682755
152 648547
156 646464
160 679270
164 663134
168 649420
172 637685
176 623475
180 612669
184 599538
188 588232
192 577422
196 566923
200 556811
204 547059
208 537637
212 528532
216 519271
220 511227
224 503027
228 495054
232 487353
236 479877
240 472637
244 465579
248 458754
252 452132
256 445681
260 438682
264 433324
268 427376
272 421577
276 416015
280 409920
284 405213
288 400012
292 394926
296 390010
300 385253
304 380546
308 375449
312 370965
316 366609
320 362369
324 358179
328 354149
332 350213
336 346290
340 342524
344 339244
348 335559
352 332027
356 328502
360 324697
364 321396
368 318073
372 315286
376 312123
380 308651
384 305657
388 302719
392 300121
396 296961
400 294140
404 291707
408 288638
412 286076
416 283756
420 280944
424 278409
428 276012
432 273548
436 271198
440 268858
444 266802
448 264349
452 262355
456 259928
460 257763
464 255713
468 253556
472 251542
476 249541
480 247356
484 245664
488 243680
492 241597
496 239978
500 238109
504 236376
508 234565
512 232851
516 231085
520 229229
524 227734
528 226098
532 224427
536 222851
540 221305
544 219546
548 218018
552 216502
556 215007
560 213722
564 212266
568 210867
572 209392
576 207854
580 206483
584 205175
588 203801
592 202445
596 201178
600 199913
604 198779
608 197514
612 196267
616 194893
620 193672
624 192649
628 191481
632 190136
636 189003
640 187870
644 186890
648 185617
652 184589
656 183608
660 182360
664 181342
668 180423
672 179220
676 178234
680 177220
684 176219
688 175234
692 174294
696 173307
700 172330
704 171407
708 170447
712 169538
716 168598
720 167698
724 166792
728 165934
732 165027
736 164170
740 163358
744 162496
748 161627
752 160808
756 160000
760 159041
764 158382
768 157593
772 156769
776 155901
780 155225
784 154484
788 153702
792 152950
796 152207
800 151460
804 150648
808 149907
812 149251
816 148500
820 147832
824 147132
828 146414
832 145748
836 145127
840 144374
844 143728
848 143176
852 142516
856 141817
860 141167
864 140465
868 139840
872 139221
876 138679
880 138089
884 137420
888 136833
892 136218
896 135668
900 135057
904 134445
908 133962
912 133329
916 132754
920 132196
924 131687
928 131121
932 130524
936 130013
940 129437
944 128925
948 128420
952 127892
956 127319
960 126800
964 126278
968 125854
972 125282
976 124800
980 124296
984 123770
988 123291
992 122888
996 122369
1000 121890
1004 121396
1008 120902
1012 120484
1016 120008
1020 119529
1024 119107
1028 118652
1032 118226
1036 117746
1040 117325
1044 116832
1048 116446
1052 115991
1056 115603
1060 115127
1064 114724
1068 114345
1072 113859
1076 113471
1080 113089
1084 112698
1088 112235
1092 111792
1096 111423
1100 111038
1104 110671
1108 110289
1112 109883
1116 109476
1120 109040
1124 108677
1128 108284
1132 107968
1136 107591
1140 107177
1144 106863
1148 106547
1152 106155
1156 105756
1160 105431
1164 105054
1168 104668
1172 104414
1176 104014
1180 103638
1184 103274
1188 103017
1192 102628
1196 102266
1200 101986
1204 101635
1208 101263
1212 100991
1216 100639
1220 100367
1224 100009
1228 99731
1232 99334
1236 99089
1240 98733
1244 98484
1248 98112
1252 97859
1256 97491
1260 97228
1264 96867
1268 96600
1272 96346
1276 95981
1280 95731
1284 95459
1288 95111
1292 94847
1296 94597
1300 94324
1304 93940
1308 93697
1312 93427
1316 93180
1320 92827
1324 92569
1328 92302
1332 92070
1336 91812
1340 91545
1344 91196
1348 90984
1352 90724
1356 90455
1360 90194
1364 89929
1368 89666
1372 89415
1376 89162
1380 88930
1384 88651
1388 88409
1392 88161
1396 87932
1400 87672
1404 87405
1408 87176
1412 86910
1416 86670
1420 86454
1424 86158
1428 85945
1432 85771
1436 85508
1440 85260
1444 85024
1448 84782
1452 84537
1456 84367
1460 84065
1464 83888
1468 83646
1472 83397
1476 83240
1480 83018
1484 82770
1488 82552
1492 82374
1496 82122
1500 81882
00:00.0 Host bridge: ServerWorks CNB20LE Host Bridge (rev 06)
00:00.1 Host bridge: ServerWorks CNB20LE Host Bridge (rev 06)
00:02.0 VGA compatible controller: S3 Inc. ViRGE/DX or /GX (rev 01)
00:03.0 Ethernet controller: Digital Equipment Corporation DECchip 21140 [FasterNet] (rev 22)
00:06.0 Ethernet controller: Intel Corp. 82557/8/9 [Ethernet Pro 100] (rev 08)
00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 50)
00:0f.1 IDE interface: ServerWorks OSB4 IDE Controller
00:0f.2 USB Controller: ServerWorks OSB4/CSB5 OHCI USB Controller (rev 04)
01:01.0 Ethernet controller: Intel Corp. 82543GC Gigabit Ethernet Controller (Copper) (rev 02)
01:02.0 Ethernet controller: Intel Corp. 82543GC Gigabit Ethernet Controller (Copper) (rev 02)
01:03.0 SCSI storage controller: Adaptec AIC-7892P U160/m (rev 02)
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 8
model name : Pentium III (Coppermine)
stepping : 6
cpu MHz : 866.711
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr sse
bogomips : 1712.12
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 8
model name : Pentium III (Coppermine)
stepping : 6
cpu MHz : 866.711
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr sse
bogomips : 1728.51
Linux version 2.6.9-rc2-bk11 (root@Sourcemage) (gcc version 3.3.2) #232 SMP Wed Oct 20 18:31:15 CEST 2004
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-27 12:04 ` pktgen Robert Olsson
@ 2004-11-27 13:53 ` Lennert Buytenhek
2004-11-27 14:39 ` pktgen Lennert Buytenhek
2004-11-29 15:27 ` pktgen Robert Olsson
0 siblings, 2 replies; 23+ messages in thread
From: Lennert Buytenhek @ 2004-11-27 13:53 UTC (permalink / raw)
To: Robert Olsson; +Cc: hadi, netdev
On Sat, Nov 27, 2004 at 01:04:53PM +0100, Robert Olsson wrote:
> 60 825789
> 64 748975
> 68 729149
> 72 719721
> 76 720204
> 80 720127
> 84 702722
> 88 702799
> 92 705107
> 96 701711
> 100 703858
> 104 692120
> 108 696139
> 112 708936
> 116 697780
> 120 677887
> 124 678158
> 128 739290
> 132 737070
> 136 736894
> 140 737645
> 144 737816
> 148 682755
> 152 648547
> 156 646464
This part is strange. In my case the pps rate for 132-byte packets is
100kpps lower than for 60-byte packets, in your case the curve is rather
flat. Perhaps you're CPU-bound here (or hitting some NIC limit.)
Your data is a bit noisy -- can you rerun the test for the 60-200 byte
packet range but using 10M packets per run instead of 1M?
> 160 679270
>From this point onwards your HW can saturate the pipe, this is the
boring part of the graph.
thanks,
Lennert
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-27 13:53 ` pktgen Lennert Buytenhek
@ 2004-11-27 14:39 ` Lennert Buytenhek
2004-11-27 15:04 ` pktgen jamal
2004-11-29 15:27 ` pktgen Robert Olsson
1 sibling, 1 reply; 23+ messages in thread
From: Lennert Buytenhek @ 2004-11-27 14:39 UTC (permalink / raw)
To: Robert Olsson; +Cc: hadi, netdev
On Sat, Nov 27, 2004 at 02:53:54PM +0100, Lennert Buytenhek wrote:
> > 160 679270
>
> From this point onwards your HW can saturate the pipe, this is the
> boring part of the graph.
Look at it this way. Assume that the cost of transmitting a single
packet consists of a packet-size-dependent part (call it 'bandwidth')
and a packet-size-independent part (call that one 'latency').
The higher the latter part is, the bigger packets you need to saturate
the (GigE) pipe.
Your 64/133 setup saturates GigE with 160B packets, my 32/66 setup needs
350B packets even though there is ample bandwidth in both cases.
Hope I'm making some sense here.
--L
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-27 14:39 ` pktgen Lennert Buytenhek
@ 2004-11-27 15:04 ` jamal
2004-11-28 18:31 ` pktgen Lennert Buytenhek
0 siblings, 1 reply; 23+ messages in thread
From: jamal @ 2004-11-27 15:04 UTC (permalink / raw)
To: Lennert Buytenhek; +Cc: Robert Olsson, netdev
On Sat, 2004-11-27 at 09:39, Lennert Buytenhek wrote:
> Look at it this way. Assume that the cost of transmitting a single
> packet consists of a packet-size-dependent part (call it 'bandwidth')
> and a packet-size-independent part (call that one 'latency').
>
> The higher the latter part is, the bigger packets you need to saturate
> the (GigE) pipe.
>
> Your 64/133 setup saturates GigE with 160B packets, my 32/66 setup needs
> 350B packets even though there is ample bandwidth in both cases.
>
> Hope I'm making some sense here.
Yes, you are.
Note the constant part of the equation though is not exactly "constant"
even if uyou picked constant hardware. It is per machine (chipset,
topology layout of the bus), per machine setup (how much latency does
your RAM have) and worse: load dependent (two IO endpoints contending
for a PCI-X bridge or the CPU being very busy at the moment with a lot
compute vs RAM-bound execution).
It would be interesting to see a study in this area though.
cheers,
jamal
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-27 15:04 ` pktgen jamal
@ 2004-11-28 18:31 ` Lennert Buytenhek
2004-11-29 13:49 ` pktgen jamal
0 siblings, 1 reply; 23+ messages in thread
From: Lennert Buytenhek @ 2004-11-28 18:31 UTC (permalink / raw)
To: jamal; +Cc: Robert Olsson, netdev
On Sat, Nov 27, 2004 at 10:04:22AM -0500, jamal wrote:
> Note the constant part of the equation though is not exactly "constant"
> even if uyou picked constant hardware. It is per machine (chipset,
> topology layout of the bus), per machine setup (how much latency does
> your RAM have) and worse: load dependent (two IO endpoints contending
> for a PCI-X bridge or the CPU being very busy at the moment with a lot
> compute vs RAM-bound execution).
Yup.
> It would be interesting to see a study in this area though.
Indeed. Right now it feels like I'm just poking around in the dark. I'm
really interested by now in finding out exactly what part of packet TX is
taking how long and where all my cycles are going.
I don't have an Itanic but it's still possible to instrument the driver
and do some stuff Grant talks about in his OLS paper, something like the
attached. (Exports # of MMIO reads/writes/flushes in the RX frame/
TX carrier/collision stats field. Beware, flushes are double-counted
as reads. Produces lots of output.)
During a 10Mpkt pktgen session (~16 seconds), I'm seeing:
- 131757 interrupts, ~8k ints/sec, ~76 pkts/int
- 131789 pure MMIO reads (i.e. not counting MMIO reads intended as write
flushes), which is E1000_READ_REG(icr) in the irq handler
- 10263536 MMIO writes (which would be 1 per packet plus 2 per interrupt)
- 131757 MMIO write flushes (readl() of the e1000 status register after
re-enabling IRQs in dev->poll())
Pretty consistent with what Grant was seeing.
MMIO reads from the e1000 are somewhere between 2000 and 3000 cycles a
pop on my hardware. 2400MHz CPU -> ~1us/each. (Reading netdevice stats
does ~50 of those in a row.)
cheers,
Lennert
diff -urN e1000.orig/e1000_hw.h e1000/e1000_hw.h
--- e1000.orig/e1000_hw.h 2004-11-24 15:35:24.000000000 +0100
+++ e1000/e1000_hw.h 2004-11-28 14:27:25.953933398 +0100
@@ -1038,6 +1038,9 @@
boolean_t adaptive_ifs;
boolean_t ifs_params_forced;
boolean_t in_ifs_mode;
+ uint32_t mmio_reads;
+ uint32_t mmio_writes;
+ uint32_t mmio_write_flushes;
};
diff -urN e1000.orig/e1000_main.c e1000/e1000_main.c
--- e1000.orig/e1000_main.c 2004-11-24 15:35:23.000000000 +0100
+++ e1000/e1000_main.c 2004-11-28 15:52:13.127944083 +0100
@@ -491,7 +491,7 @@
}
#ifdef NETIF_F_TSO
- /* Disbaled for now until root-cause is found for
+ /* Disabled for now until root cause is found for
* hangs reported against non-IA archs. TSO can be
* enabled using ethtool -K eth<x> tso on */
if((adapter->hw.mac_type >= e1000_82544) &&
@@ -585,6 +585,21 @@
if(eeprom_data & E1000_EEPROM_APME)
adapter->wol |= E1000_WUFC_MAG;
+ /* print bus type/speed/width info */
+ printk(KERN_INFO "%s: e1000 (PCI%s:%s:%s) ", netdev->name,
+ ((adapter->hw.bus_type == e1000_bus_type_pcix) ? "X" : ""),
+ ((adapter->hw.bus_speed == e1000_bus_speed_133) ? "133MHz" :
+ (adapter->hw.bus_speed == e1000_bus_speed_120) ? "120MHz" :
+ (adapter->hw.bus_speed == e1000_bus_speed_100) ? "100MHz" :
+ (adapter->hw.bus_speed == e1000_bus_speed_66) ? "66MHz" :
+ "33MHz"),
+ ((adapter->hw.bus_width == e1000_bus_width_64) ? "64-bit" :
+ "32-bit"));
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", netdev->dev_addr[i],
+ i == 5 ? '\n' : ':');
+
/* reset the hardware with the new settings */
e1000_reset(adapter);
@@ -1971,6 +1986,7 @@
* be written while holding adapter->stats_lock
*/
+#if 0
adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
@@ -2035,6 +2051,7 @@
adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
}
+#endif
/* Fill out the OS statistics structure */
@@ -2043,7 +2060,7 @@
adapter->net_stats.rx_bytes = adapter->stats.gorcl;
adapter->net_stats.tx_bytes = adapter->stats.gotcl;
adapter->net_stats.multicast = adapter->stats.mprc;
- adapter->net_stats.collisions = adapter->stats.colc;
+ adapter->net_stats.collisions = hw->mmio_write_flushes;
/* Rx Errors */
@@ -2054,7 +2071,7 @@
adapter->net_stats.rx_dropped = adapter->stats.rnbc;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
- adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
+ adapter->net_stats.rx_frame_errors = hw->mmio_reads;
adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
@@ -2064,12 +2081,13 @@
adapter->stats.latecol;
adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
adapter->net_stats.tx_window_errors = adapter->stats.latecol;
- adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
+ adapter->net_stats.tx_carrier_errors = hw->mmio_writes;
/* Tx Dropped needs to be maintained elsewhere */
/* Phy Stats */
+#if 0
if(hw->media_type == e1000_media_type_copper) {
if((adapter->link_speed == SPEED_1000) &&
(!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
@@ -2082,6 +2100,7 @@
!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
adapter->phy_stats.receive_errors += phy_tmp;
}
+#endif
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
diff -urN e1000.orig/e1000_osdep.h e1000/e1000_osdep.h
--- e1000.orig/e1000_osdep.h 2004-11-24 15:35:23.000000000 +0100
+++ e1000/e1000_osdep.h 2004-11-28 16:05:50.063341317 +0100
@@ -78,23 +78,40 @@
#define E1000_WRITE_REG(a, reg, value) ( \
+ printk(KERN_INFO "e1000: MMIO write\n"), \
+ (a)->mmio_writes++, \
writel((value), ((a)->hw_addr + \
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
-#define E1000_READ_REG(a, reg) ( \
- readl((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
+#define E1000_READ_REG(a, reg) ({ \
+ unsigned long s, e, d, v; \
+\
+ (a)->mmio_reads++; \
+ rdtsc(s, d); \
+ v = readl((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)); \
+ rdtsc(e, d); \
+ e -= s; \
+ printk(KERN_INFO "e1000: MMIO read took %ld clocks\n", e); \
+ printk(KERN_INFO "e1000: in process %d(%s)\n", current->pid, current->comm); \
+ dump_stack(); \
+ v; \
+})
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+ (a)->mmio_writes++, \
writel((value), ((a)->hw_addr + \
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
((offset) << 2))))
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
+ (a)->mmio_reads++, \
readl((a)->hw_addr + \
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
((offset) << 2)))
-#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
+#define E1000_WRITE_FLUSH(a) ( \
+ (a)->mmio_write_flushes++, \
+ E1000_READ_REG(a, STATUS))
#endif /* _E1000_OSDEP_H_ */
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-28 18:31 ` pktgen Lennert Buytenhek
@ 2004-11-29 13:49 ` jamal
2004-11-29 16:57 ` pktgen Grant Grundler
0 siblings, 1 reply; 23+ messages in thread
From: jamal @ 2004-11-29 13:49 UTC (permalink / raw)
To: Lennert Buytenhek; +Cc: Robert Olsson, netdev, Grant Grundler
On Sun, 2004-11-28 at 13:31, Lennert Buytenhek wrote:
> On Sat, Nov 27, 2004 at 10:04:22AM -0500, jamal wrote:
>
> > It would be interesting to see a study in this area though.
>
> Indeed. Right now it feels like I'm just poking around in the dark. I'm
> really interested by now in finding out exactly what part of packet TX is
> taking how long and where all my cycles are going.
>
> I don't have an Itanic but it's still possible to instrument the driver
> and do some stuff Grant talks about in his OLS paper, something like the
> attached. (Exports # of MMIO reads/writes/flushes in the RX frame/
> TX carrier/collision stats field. Beware, flushes are double-counted
> as reads. Produces lots of output.)
>
> During a 10Mpkt pktgen session (~16 seconds), I'm seeing:
> - 131757 interrupts, ~8k ints/sec, ~76 pkts/int
> - 131789 pure MMIO reads (i.e. not counting MMIO reads intended as write
> flushes), which is E1000_READ_REG(icr) in the irq handler
> - 10263536 MMIO writes (which would be 1 per packet plus 2 per interrupt)
> - 131757 MMIO write flushes (readl() of the e1000 status register after
> re-enabling IRQs in dev->poll())
>
> Pretty consistent with what Grant was seeing.
>
> MMIO reads from the e1000 are somewhere between 2000 and 3000 cycles a
> pop on my hardware. 2400MHz CPU -> ~1us/each. (Reading netdevice stats
> does ~50 of those in a row.)
>
Reads are known to be expensive. Good to see how much they are reduced.
Not sure if this applies to MMIO reads though. Grant?
cheers,
jamal
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-27 13:53 ` pktgen Lennert Buytenhek
2004-11-27 14:39 ` pktgen Lennert Buytenhek
@ 2004-11-29 15:27 ` Robert Olsson
1 sibling, 0 replies; 23+ messages in thread
From: Robert Olsson @ 2004-11-29 15:27 UTC (permalink / raw)
To: Lennert Buytenhek; +Cc: Robert Olsson, hadi, netdev
Lennert Buytenhek writes:
> Your data is a bit noisy -- can you rerun the test for the 60-200 byte
> packet range but using 10M packets per run instead of 1M?
OK!
60 825976
64 746730
68 730215
72 720942
76 721090
80 721772
84 704472
88 704489
92 705184
96 714750
100 694178
104 700853
108 703332
112 715865
116 692223
120 677893
124 678306
128 736908
132 712328
136 722271
140 706784
144 716770
148 694497
152 647868
156 647693
160 678071
164 663694
168 649894
172 636478
176 623761
180 611580
184 599835
188 588540
192 577549
196 567044
200 556967
--ro
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2004-11-29 13:49 ` pktgen jamal
@ 2004-11-29 16:57 ` Grant Grundler
0 siblings, 0 replies; 23+ messages in thread
From: Grant Grundler @ 2004-11-29 16:57 UTC (permalink / raw)
To: jamal; +Cc: Lennert Buytenhek, Robert Olsson, netdev, Grant Grundler
On Mon, Nov 29, 2004 at 08:49:52AM -0500, jamal wrote:
> On Sun, 2004-11-28 at 13:31, Lennert Buytenhek wrote:
> > Indeed. Right now it feels like I'm just poking around in the dark. I'm
> > really interested by now in finding out exactly what part of packet TX is
> > taking how long and where all my cycles are going.
ia64 PMU can measure exactly where/why the CPU is stalling.
MMIO reads are by far the worst offenders - but not the only ones.
"bubbles" in the pipeline can be caused by lots of other
stalls and will affect CPU utilization as well.
A very nice description of CPU stalls caused by memory subsystem is here:
http://www.gelato.org/pdf/mysql_itanium2_perf.pdf
Gelato.org, sgi.com, intel.com, hp.com have more white papers
on ia64 performance tools and tuning.
> > I don't have an Itanic but it's still possible to instrument the driver
> > and do some stuff Grant talks about in his OLS paper, something like the
> > attached. (Exports # of MMIO reads/writes/flushes in the RX frame/
> > TX carrier/collision stats field. Beware, flushes are double-counted
> > as reads. Produces lots of output.)
I'd be happy to give you access to an IA64 machine to poke at.
If you can send me:
o preferred login
o public ssh key
o work telephone #
BTW, Jamal, I'm expecting we'll be able to get Robur an RX2600
to play with this quarter. I need to ask about that again.
> > During a 10Mpkt pktgen session (~16 seconds), I'm seeing:
> > - 131757 interrupts, ~8k ints/sec, ~76 pkts/int
> > - 131789 pure MMIO reads (i.e. not counting MMIO reads intended as write
> > flushes), which is E1000_READ_REG(icr) in the irq handler
> > - 10263536 MMIO writes (which would be 1 per packet plus 2 per interrupt)
> > - 131757 MMIO write flushes (readl() of the e1000 status register after
> > re-enabling IRQs in dev->poll())
> >
> > Pretty consistent with what Grant was seeing.
yup.
> >
> > MMIO reads from the e1000 are somewhere between 2000 and 3000 cycles a
> > pop on my hardware. 2400MHz CPU -> ~1us/each. (Reading netdevice stats
> > does ~50 of those in a row.)
> >
>
> Reads are known to be expensive. Good to see how much they are reduced.
> Not sure if this applies to MMIO reads though. Grant?
I don't differentiate between "pure" MMIO reads and posted MMIO write
flushes. They cost the same AFAIK. If one can tweak the algorithm so
either is not needed, it's a win.
But I didn't see any opportunity to do that in e1000 driver.
There is such an opportunity in tg3 though. I just won't have
a chance to pursue it. :^(
The absolute cost in CPU cycles of an MMIO read will depend on chipset,
CPU speed, and number of bridges the transaction has to cross.
On an idle 1Ghz system, I've measured ~1000-1200 cycles.
When measured in time (not CPU cycles), the cost hasn't changed that
much in the past 6-8 years (mostly 66Mhz PCI busses).
Adding or removing a PCI-PCI bridge is the biggest variable in
absolute time.
thanks,
grant
^ permalink raw reply [flat|nested] 23+ messages in thread
* pktgen (was Re: tests of kernel modules)
[not found] ` <9fa31860611211236i104cb510mb5100ea056b657db@mail.gmail.com>
@ 2006-11-21 21:22 ` Alexey Dobriyan
2006-11-28 23:33 ` pktgen David Miller
0 siblings, 1 reply; 23+ messages in thread
From: Alexey Dobriyan @ 2006-11-21 21:22 UTC (permalink / raw)
To: Pavol Gono; +Cc: netdev
[CCing netdev, bug in pktgen]
[build modular pktgen]
while true; do modprobe pktgen && rmmod pktgen; done
BUG: warning at fs/proc/generic.c:732/remove_proc_entry()
[<c016a7ad>] remove_proc_entry+0x161/0x1ca
[<e19969ab>] pg_cleanup+0xd5/0xdc [pktgen]
[<c011fa3e>] autoremove_wake_function+0x0/0x35
[<c01280bd>] sys_delete_module+0x162/0x189
[<c0136500>] remove_vma+0x31/0x36
[<c0136df7>] do_munmap+0x193/0x1ac
[<c0102829>] sysenter_past_esp+0x56/0x79
[<c02d007b>] fn_hash_delete+0x4f/0x1c7
On Tue, Nov 21, 2006 at 09:36:46PM +0100, Pavol Gono wrote:
> I am going to add two more:
> for i in 1 2 3 4 5 ; do modprobe pktgen ; rmmod pktgen ; done
Looks like it creates /proc/net/pktgen/kpktgen_%i but forgets to remove
them.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-21 21:22 ` pktgen (was Re: tests of kernel modules) Alexey Dobriyan
@ 2006-11-28 23:33 ` David Miller
2006-11-29 20:04 ` pktgen Alexey Dobriyan
0 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2006-11-28 23:33 UTC (permalink / raw)
To: adobriyan; +Cc: pavol.gono, netdev
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Wed, 22 Nov 2006 00:22:51 +0300
> [CCing netdev, bug in pktgen]
>
> [build modular pktgen]
> while true; do modprobe pktgen && rmmod pktgen; done
>
> BUG: warning at fs/proc/generic.c:732/remove_proc_entry()
> [<c016a7ad>] remove_proc_entry+0x161/0x1ca
> [<e19969ab>] pg_cleanup+0xd5/0xdc [pktgen]
> [<c011fa3e>] autoremove_wake_function+0x0/0x35
> [<c01280bd>] sys_delete_module+0x162/0x189
> [<c0136500>] remove_vma+0x31/0x36
> [<c0136df7>] do_munmap+0x193/0x1ac
> [<c0102829>] sysenter_past_esp+0x56/0x79
> [<c02d007b>] fn_hash_delete+0x4f/0x1c7
>
> On Tue, Nov 21, 2006 at 09:36:46PM +0100, Pavol Gono wrote:
> > I am going to add two more:
> > for i in 1 2 3 4 5 ; do modprobe pktgen ; rmmod pktgen ; done
>
> Looks like it creates /proc/net/pktgen/kpktgen_%i but forgets to remove
> them.
It's pretty careful to delete all of the entries under
/proc/net/pktgen/.
When the module is brought down, it walks the list of threads
and brings them down by setting T_TERMINATE in t->control.
This makes the thread break out of it's loop and run:
pktgen_stop(t);
pktgen_rem_all_ifs(t);
pktgen_rem_thread(t);
pktgen_rem_all_ifs() will delete all device entries in
/proc/net/pktgen/
Next, pktgen_rem_thread() will kill off the entry for
/proc/net/pktgen/kpkgen_%i
Finally, the top-level module remove code will delete the
control file right before it tries to kill off the directory
via:
/* Clean up proc file system */
remove_proc_entry(PGCTRL, pg_proc_dir);
proc_net_remove(PG_PROC_DIR);
So I don't see any bugs that could cause this.
One possibility is that the thread's t->name is being
corrupted somehow, that would make the remove_proc_entry()
fail and cause the behavior you see. But I can't see anything
obvious that might do that either.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-28 23:33 ` pktgen David Miller
@ 2006-11-29 20:04 ` Alexey Dobriyan
2006-11-30 1:49 ` pktgen David Miller
0 siblings, 1 reply; 23+ messages in thread
From: Alexey Dobriyan @ 2006-11-29 20:04 UTC (permalink / raw)
To: David Miller; +Cc: pavol.gono, netdev
On Tue, Nov 28, 2006 at 03:33:25PM -0800, David Miller wrote:
> From: Alexey Dobriyan <adobriyan@gmail.com>
> Date: Wed, 22 Nov 2006 00:22:51 +0300
>
> > [CCing netdev, bug in pktgen]
> >
> > [build modular pktgen]
> > while true; do modprobe pktgen && rmmod pktgen; done
> >
> > BUG: warning at fs/proc/generic.c:732/remove_proc_entry()
> > [<c016a7ad>] remove_proc_entry+0x161/0x1ca
> > [<e19969ab>] pg_cleanup+0xd5/0xdc [pktgen]
> > [<c011fa3e>] autoremove_wake_function+0x0/0x35
> > [<c01280bd>] sys_delete_module+0x162/0x189
> > [<c0136500>] remove_vma+0x31/0x36
> > [<c0136df7>] do_munmap+0x193/0x1ac
> > [<c0102829>] sysenter_past_esp+0x56/0x79
> > [<c02d007b>] fn_hash_delete+0x4f/0x1c7
> >
> > On Tue, Nov 21, 2006 at 09:36:46PM +0100, Pavol Gono wrote:
> > > I am going to add two more:
> > > for i in 1 2 3 4 5 ; do modprobe pktgen ; rmmod pktgen ; done
> >
> > Looks like it creates /proc/net/pktgen/kpktgen_%i but forgets to remove
> > them.
>
> It's pretty careful to delete all of the entries under
> /proc/net/pktgen/.
>
> When the module is brought down, it walks the list of threads
> and brings them down by setting T_TERMINATE in t->control.
Looks like worker thread strategically clears it if scheduled at wrong
moment.
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3292,7 +3292,6 @@ static void pktgen_thread_worker(struct
init_waitqueue_head(&t->queue);
- t->control &= ~(T_TERMINATE);
t->control &= ~(T_RUN);
t->control &= ~(T_STOP);
t->control &= ~(T_REMDEVALL);
> This makes the thread break out of it's loop and run:
>
> pktgen_stop(t);
> pktgen_rem_all_ifs(t);
> pktgen_rem_thread(t);
Kernel seeems to survive, but when I hit Ctrl+C after half
a minute backtrace is back being the very last dmesg lines.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-29 20:04 ` pktgen Alexey Dobriyan
@ 2006-11-30 1:49 ` David Miller
2006-11-30 7:30 ` pktgen Alexey Dobriyan
0 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2006-11-30 1:49 UTC (permalink / raw)
To: adobriyan; +Cc: pavol.gono, netdev
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Wed, 29 Nov 2006 23:04:37 +0300
> Looks like worker thread strategically clears it if scheduled at wrong
> moment.
>
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -3292,7 +3292,6 @@ static void pktgen_thread_worker(struct
>
> init_waitqueue_head(&t->queue);
>
> - t->control &= ~(T_TERMINATE);
> t->control &= ~(T_RUN);
> t->control &= ~(T_STOP);
> t->control &= ~(T_REMDEVALL);
Good catch Alexey. Did you rerun the load/unload test with
this fix applied? If it fixes things, I'll merge it.
Thanks!
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-30 1:49 ` pktgen David Miller
@ 2006-11-30 7:30 ` Alexey Dobriyan
2006-11-30 8:45 ` pktgen Robert Olsson
0 siblings, 1 reply; 23+ messages in thread
From: Alexey Dobriyan @ 2006-11-30 7:30 UTC (permalink / raw)
To: David Miller; +Cc: pavol.gono, netdev
On 11/30/06, David Miller <davem@davemloft.net> wrote:
> From: Alexey Dobriyan <adobriyan@gmail.com>
> Date: Wed, 29 Nov 2006 23:04:37 +0300
>
> > Looks like worker thread strategically clears it if scheduled at wrong
> > moment.
> >
> > --- a/net/core/pktgen.c
> > +++ b/net/core/pktgen.c
> > @@ -3292,7 +3292,6 @@ static void pktgen_thread_worker(struct
> >
> > init_waitqueue_head(&t->queue);
> >
> > - t->control &= ~(T_TERMINATE);
> > t->control &= ~(T_RUN);
> > t->control &= ~(T_STOP);
> > t->control &= ~(T_REMDEVALL);
>
> Good catch Alexey. Did you rerun the load/unload test with
> this fix applied? If it fixes things, I'll merge it.
Well, yes, it fixes things, except Ctrl+C getting you out of
modprobe/rmmod loop will spit
backtrace again. And other flags: T_RUN, T_STOP. Clearance is not
needed due to kZalloc and
create bugs as demostrated.
Give me some time.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-30 7:30 ` pktgen Alexey Dobriyan
@ 2006-11-30 8:45 ` Robert Olsson
2006-11-30 17:33 ` pktgen Ben Greear
0 siblings, 1 reply; 23+ messages in thread
From: Robert Olsson @ 2006-11-30 8:45 UTC (permalink / raw)
To: Alexey Dobriyan; +Cc: David Miller, pavol.gono, netdev
Hello!
Seems you found a race when rmmod is done before it's fully started
Try:
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 733d86d..ac0b4b1 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -160,7 +160,7 @@
#include <asm/div64.h> /* do_div */
#include <asm/timex.h>
-#define VERSION "pktgen v2.68: Packet Generator for packet performance testing.\n"
+#define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n"
/* #define PG_DEBUG(a) a */
#define PG_DEBUG(a)
@@ -3673,6 +3673,8 @@ static void __exit pg_cleanup(void)
struct list_head *q, *n;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
+
+ schedule_timeout_interruptible(msecs_to_jiffies(125));
/* Stop all interfaces & threads */
for i in 1 2 3 4 5 ; do modprobe pktgen ; rmmod pktgen ; done
In dmesg
pktgen v2.69: Packet Generator for packet performance testing.
pktgen v2.69: Packet Generator for packet performance testing.
pktgen v2.69: Packet Generator for packet performance testing.
pktgen v2.69: Packet Generator for packet performance testing.
pktgen v2.69: Packet Generator for packet performance testing.
Cheers.
--ro
Alexey Dobriyan writes:
> On 11/30/06, David Miller <davem@davemloft.net> wrote:
> > From: Alexey Dobriyan <adobriyan@gmail.com>
> > Date: Wed, 29 Nov 2006 23:04:37 +0300
> >
> > > Looks like worker thread strategically clears it if scheduled at wrong
> > > moment.
> > >
> > > --- a/net/core/pktgen.c
> > > +++ b/net/core/pktgen.c
> > > @@ -3292,7 +3292,6 @@ static void pktgen_thread_worker(struct
> > >
> > > init_waitqueue_head(&t->queue);
> > >
> > > - t->control &= ~(T_TERMINATE);
> > > t->control &= ~(T_RUN);
> > > t->control &= ~(T_STOP);
> > > t->control &= ~(T_REMDEVALL);
> >
> > Good catch Alexey. Did you rerun the load/unload test with
> > this fix applied? If it fixes things, I'll merge it.
>
> Well, yes, it fixes things, except Ctrl+C getting you out of
> modprobe/rmmod loop will spit
> backtrace again. And other flags: T_RUN, T_STOP. Clearance is not
> needed due to kZalloc and
> create bugs as demostrated.
>
> Give me some time.
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-30 8:45 ` pktgen Robert Olsson
@ 2006-11-30 17:33 ` Ben Greear
2006-12-01 4:14 ` pktgen David Miller
0 siblings, 1 reply; 23+ messages in thread
From: Ben Greear @ 2006-11-30 17:33 UTC (permalink / raw)
To: Robert Olsson; +Cc: Alexey Dobriyan, David Miller, pavol.gono, netdev
Robert Olsson wrote:
> Hello!
>
> Seems you found a race when rmmod is done before it's fully started
>
> Try:
>
> diff --git a/net/core/pktgen.c b/net/core/pktgen.c
> index 733d86d..ac0b4b1 100644
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -160,7 +160,7 @@
> #include <asm/div64.h> /* do_div */
> #include <asm/timex.h>
>
> -#define VERSION "pktgen v2.68: Packet Generator for packet performance testing.\n"
> +#define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n"
>
> /* #define PG_DEBUG(a) a */
> #define PG_DEBUG(a)
> @@ -3673,6 +3673,8 @@ static void __exit pg_cleanup(void)
> struct list_head *q, *n;
> wait_queue_head_t queue;
> init_waitqueue_head(&queue);
> +
> + schedule_timeout_interruptible(msecs_to_jiffies(125));
>
> /* Stop all interfaces & threads */
>
>
That strikes me as a hack..surely there is a better method than just adding
a sleep??
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-11-30 17:33 ` pktgen Ben Greear
@ 2006-12-01 4:14 ` David Miller
2006-12-01 8:14 ` pktgen Robert Olsson
2006-12-01 8:22 ` pktgen Christoph Hellwig
0 siblings, 2 replies; 23+ messages in thread
From: David Miller @ 2006-12-01 4:14 UTC (permalink / raw)
To: greearb; +Cc: Robert.Olsson, adobriyan, pavol.gono, netdev
From: Ben Greear <greearb@candelatech.com>
Date: Thu, 30 Nov 2006 09:33:43 -0800
> Robert Olsson wrote:
> > @@ -3673,6 +3673,8 @@ static void __exit pg_cleanup(void)
> > struct list_head *q, *n;
> > wait_queue_head_t queue;
> > init_waitqueue_head(&queue);
> > +
> > + schedule_timeout_interruptible(msecs_to_jiffies(125));
> >
> > /* Stop all interfaces & threads */
> >
>
> That strikes me as a hack..surely there is a better method than just adding
> a sleep??
Agreed.
Robert, please fix this by using a completion so that we can
wait for the threads to start up, something like this:
...
#include <linux/completion.h>
...
struct pktgen_thread_info {
struct pktgen_thread *t;
struct completion *c;
};
static void pktgen_thread_worker(struct pktgen_thread_info *info)
{
struct pktgen_thread *t = info->t;
...
__set_current_state(TASK_INTERRUPTIBLE);
mb();
complete(info->c);
...
}
static int __init pktgen_create_thread(const char *name, int cpu)
{
...
struct pktgen_thread_info info;
struct complation started;
...
init_completion(&started);
info.t = t;
info.c = &started;
err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
if (err < 0) {
printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
remove_proc_entry(t->name, pg_proc_dir);
list_del(&t->th_list);
kfree(t);
return err;
}
wait_for_completion(&started);
return 0;
}
We can horse around with fixing the initial t->control bit flipping
in pktgen_thread_worker() in a future changeset if we want.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 4:14 ` pktgen David Miller
@ 2006-12-01 8:14 ` Robert Olsson
2006-12-01 9:51 ` pktgen Alexey Dobriyan
2007-01-02 4:53 ` pktgen David Miller
2006-12-01 8:22 ` pktgen Christoph Hellwig
1 sibling, 2 replies; 23+ messages in thread
From: Robert Olsson @ 2006-12-01 8:14 UTC (permalink / raw)
To: David Miller; +Cc: greearb, Robert.Olsson, adobriyan, pavol.gono, netdev
David Miller writes:
> Agreed.
>
> Robert, please fix this by using a completion so that we can
> wait for the threads to start up, something like this:
Included. It passes my test but Alexey and others test.
Cheers.
--ro
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 733d86d..a630a73 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -147,6 +147,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/wait.h>
+#include <linux/completion.h>
#include <linux/etherdevice.h>
#include <net/checksum.h>
#include <net/ipv6.h>
@@ -160,7 +161,7 @@
#include <asm/div64.h> /* do_div */
#include <asm/timex.h>
-#define VERSION "pktgen v2.68: Packet Generator for packet performance testing.\n"
+#define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n"
/* #define PG_DEBUG(a) a */
#define PG_DEBUG(a)
@@ -206,6 +207,11 @@ static struct proc_dir_entry *pg_proc_di
#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
+struct pktgen_thread_info {
+ struct pktgen_thread *t;
+ struct completion *c;
+};
+
struct flow_state {
__u32 cur_daddr;
int count;
@@ -3264,10 +3270,11 @@ out:;
* Main loop of the thread goes here
*/
-static void pktgen_thread_worker(struct pktgen_thread *t)
+static void pktgen_thread_worker(struct pktgen_thread_info *info)
{
DEFINE_WAIT(wait);
struct pktgen_dev *pkt_dev = NULL;
+ struct pktgen_thread *t = info->t;
int cpu = t->cpu;
sigset_t tmpsig;
u32 max_before_softirq;
@@ -3307,6 +3314,8 @@ static void pktgen_thread_worker(struct
__set_current_state(TASK_INTERRUPTIBLE);
mb();
+ complete(info->c);
+
while (1) {
__set_current_state(TASK_RUNNING);
@@ -3518,6 +3527,8 @@ static struct pktgen_thread *__init pktg
static int __init pktgen_create_thread(const char *name, int cpu)
{
int err;
+ struct pktgen_thread_info info;
+ struct completion started;
struct pktgen_thread *t = NULL;
struct proc_dir_entry *pe;
@@ -3558,7 +3569,11 @@ static int __init pktgen_create_thread(c
t->removed = 0;
- err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
+ init_completion(&started);
+ info.t = t;
+ info.c = &started;
+
+ err = kernel_thread((void *)pktgen_thread_worker, (void *)&info,
CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
if (err < 0) {
printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
@@ -3568,6 +3583,7 @@ static int __init pktgen_create_thread(c
return err;
}
+ wait_for_completion(&started);
return 0;
}
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 4:14 ` pktgen David Miller
2006-12-01 8:14 ` pktgen Robert Olsson
@ 2006-12-01 8:22 ` Christoph Hellwig
2006-12-01 23:17 ` pktgen David Miller
1 sibling, 1 reply; 23+ messages in thread
From: Christoph Hellwig @ 2006-12-01 8:22 UTC (permalink / raw)
To: David Miller; +Cc: greearb, Robert.Olsson, adobriyan, pavol.gono, netdev
On Thu, Nov 30, 2006 at 08:14:23PM -0800, David Miller wrote:
> Agreed.
>
> Robert, please fix this by using a completion so that we can
> wait for the threads to start up, something like this:
No, that's wrong aswell :) Please use the kthread_ API that takes
care of all this. kernel_thread is going away mid-term, so you'd
have to do this work anyway.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 8:14 ` pktgen Robert Olsson
@ 2006-12-01 9:51 ` Alexey Dobriyan
2006-12-01 17:18 ` pktgen Robert Olsson
2006-12-01 23:25 ` pktgen David Miller
2007-01-02 4:53 ` pktgen David Miller
1 sibling, 2 replies; 23+ messages in thread
From: Alexey Dobriyan @ 2006-12-01 9:51 UTC (permalink / raw)
To: Robert Olsson; +Cc: David Miller, greearb, pavol.gono, netdev
On 12/1/06, Robert Olsson <Robert.Olsson@data.slu.se> wrote:
> David Miller writes:
> > Agreed.
> >
> > Robert, please fix this by using a completion so that we can
> > wait for the threads to start up, something like this:
>
> Included. It passes my test but Alexey and others test.
Confused now. Is my "t->control &= ~(T_TERMINATE);" fix deprecated by
completions?
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -147,6 +147,7 @@
> #include <linux/proc_fs.h>
> #include <linux/seq_file.h>
> #include <linux/wait.h>
> +#include <linux/completion.h>
> #include <linux/etherdevice.h>
> #include <net/checksum.h>
> #include <net/ipv6.h>
> @@ -160,7 +161,7 @@
> #include <asm/div64.h> /* do_div */
> #include <asm/timex.h>
>
> -#define VERSION "pktgen v2.68: Packet Generator for packet performance
> testing.\n"
> +#define VERSION "pktgen v2.69: Packet Generator for packet performance
> testing.\n"
>
> /* #define PG_DEBUG(a) a */
> #define PG_DEBUG(a)
> @@ -206,6 +207,11 @@ static struct proc_dir_entry *pg_proc_di
> #define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
> #define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
>
> +struct pktgen_thread_info {
> + struct pktgen_thread *t;
> + struct completion *c;
> +};
> +
> struct flow_state {
> __u32 cur_daddr;
> int count;
> @@ -3264,10 +3270,11 @@ out:;
> * Main loop of the thread goes here
> */
>
> -static void pktgen_thread_worker(struct pktgen_thread *t)
> +static void pktgen_thread_worker(struct pktgen_thread_info *info)
> {
> DEFINE_WAIT(wait);
> struct pktgen_dev *pkt_dev = NULL;
> + struct pktgen_thread *t = info->t;
> int cpu = t->cpu;
> sigset_t tmpsig;
> u32 max_before_softirq;
> @@ -3307,6 +3314,8 @@ static void pktgen_thread_worker(struct
> __set_current_state(TASK_INTERRUPTIBLE);
> mb();
>
> + complete(info->c);
> +
> while (1) {
>
> __set_current_state(TASK_RUNNING);
> @@ -3518,6 +3527,8 @@ static struct pktgen_thread *__init pktg
> static int __init pktgen_create_thread(const char *name, int cpu)
> {
> int err;
> + struct pktgen_thread_info info;
> + struct completion started;
> struct pktgen_thread *t = NULL;
> struct proc_dir_entry *pe;
>
> @@ -3558,7 +3569,11 @@ static int __init pktgen_create_thread(c
>
> t->removed = 0;
>
> - err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
> + init_completion(&started);
> + info.t = t;
> + info.c = &started;
> +
> + err = kernel_thread((void *)pktgen_thread_worker, (void *)&info,
> CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
> if (err < 0) {
> printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
> @@ -3568,6 +3583,7 @@ static int __init pktgen_create_thread(c
> return err;
> }
>
> + wait_for_completion(&started);
> return 0;
> }
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 9:51 ` pktgen Alexey Dobriyan
@ 2006-12-01 17:18 ` Robert Olsson
2006-12-01 23:25 ` pktgen David Miller
1 sibling, 0 replies; 23+ messages in thread
From: Robert Olsson @ 2006-12-01 17:18 UTC (permalink / raw)
To: Alexey Dobriyan; +Cc: Robert Olsson, David Miller, greearb, pavol.gono, netdev
Alexey Dobriyan writes:
>
> Confused now. Is my "t->control &= ~(T_TERMINATE);" fix deprecated by
> completions?
It's not needed with completion patch as this does the job a bit more
mainstream. The T_TERMINATE seems to work well I've tested on machine
with CPU:s. Only once I noticed that only 2 of 4 threads got started
but it could be something else...
And the race is hardly seen with any real use of pktgen.. .Let's hear
what others... and completions was out-of-date.
Cheers.
--ro
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 8:22 ` pktgen Christoph Hellwig
@ 2006-12-01 23:17 ` David Miller
0 siblings, 0 replies; 23+ messages in thread
From: David Miller @ 2006-12-01 23:17 UTC (permalink / raw)
To: hch; +Cc: greearb, Robert.Olsson, adobriyan, pavol.gono, netdev
From: Christoph Hellwig <hch@infradead.org>
Date: Fri, 1 Dec 2006 08:22:25 +0000
> On Thu, Nov 30, 2006 at 08:14:23PM -0800, David Miller wrote:
> > Agreed.
> >
> > Robert, please fix this by using a completion so that we can
> > wait for the threads to start up, something like this:
>
> No, that's wrong aswell :) Please use the kthread_ API that takes
> care of all this. kernel_thread is going away mid-term, so you'd
> have to do this work anyway.
I was going to suggest this Christophe, but I wanted a change small
and easy enough to verify in order to merge the fix into the -stable
branch. Converting the thing over to kthread would make the change
more risky in such a context.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 9:51 ` pktgen Alexey Dobriyan
2006-12-01 17:18 ` pktgen Robert Olsson
@ 2006-12-01 23:25 ` David Miller
1 sibling, 0 replies; 23+ messages in thread
From: David Miller @ 2006-12-01 23:25 UTC (permalink / raw)
To: adobriyan; +Cc: Robert.Olsson, greearb, pavol.gono, netdev
From: "Alexey Dobriyan" <adobriyan@gmail.com>
Date: Fri, 1 Dec 2006 12:51:53 +0300
> On 12/1/06, Robert Olsson <Robert.Olsson@data.slu.se> wrote:
> > David Miller writes:
> > > Agreed.
> > >
> > > Robert, please fix this by using a completion so that we can
> > > wait for the threads to start up, something like this:
> >
> > Included. It passes my test but Alexey and others test.
>
> Confused now. Is my "t->control &= ~(T_TERMINATE);" fix deprecated by
> completions?
The completions solve the bug completely.
But later on we should integate a change that eliminates
these spurious t->control bit clears at the start of the
pktgen thread execution, it just isn't needed to fix the
bug so we can make it later.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: pktgen
2006-12-01 8:14 ` pktgen Robert Olsson
2006-12-01 9:51 ` pktgen Alexey Dobriyan
@ 2007-01-02 4:53 ` David Miller
1 sibling, 0 replies; 23+ messages in thread
From: David Miller @ 2007-01-02 4:53 UTC (permalink / raw)
To: Robert.Olsson; +Cc: greearb, adobriyan, pavol.gono, netdev
From: Robert Olsson <Robert.Olsson@data.slu.se>
Date: Fri, 1 Dec 2006 09:14:01 +0100
>
> David Miller writes:
>
> > Agreed.
> >
> > Robert, please fix this by using a completion so that we can
> > wait for the threads to start up, something like this:
>
> Included. It passes my test but Alexey and others test.
Ok, I'm going to put Robert's version of the fix into 2.6.19
and previous -stable branches.
But for 2.6.20 I'd like to do the following, based upon
Christoph's suggestion to convert to kthread.
Can folks please give this a spin? I've tested that the
module loads and unloads properly, the threads startup
and shutdown, but that's it.
Thanks!
commit b3010a665cc33596fbf4be3fc6c3c5c80aeefb65
Author: David S. Miller <davem@sunset.davemloft.net>
Date: Mon Jan 1 20:51:53 2007 -0800
[PKTGEN]: Convert to kthread API.
Based upon a suggestion from Christoph Hellwig.
This fixes various races in module load/unload handling
too.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 1897a3a..04d4b93 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -148,6 +148,7 @@
#include <linux/seq_file.h>
#include <linux/wait.h>
#include <linux/etherdevice.h>
+#include <linux/kthread.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
@@ -360,8 +361,7 @@ struct pktgen_thread {
spinlock_t if_lock;
struct list_head if_list; /* All device here */
struct list_head th_list;
- int removed;
- char name[32];
+ struct task_struct *tsk;
char result[512];
u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
@@ -1689,7 +1689,7 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
BUG_ON(!t);
seq_printf(seq, "Name: %s max_before_softirq: %d\n",
- t->name, t->max_before_softirq);
+ t->tsk->comm, t->max_before_softirq);
seq_printf(seq, "Running: ");
@@ -3112,7 +3112,7 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
{
/* Remove from the thread list */
- remove_proc_entry(t->name, pg_proc_dir);
+ remove_proc_entry(t->tsk->comm, pg_proc_dir);
mutex_lock(&pktgen_thread_lock);
@@ -3260,58 +3260,40 @@ out:;
* Main loop of the thread goes here
*/
-static void pktgen_thread_worker(struct pktgen_thread *t)
+static int pktgen_thread_worker(void *arg)
{
DEFINE_WAIT(wait);
+ struct pktgen_thread *t = arg;
struct pktgen_dev *pkt_dev = NULL;
int cpu = t->cpu;
- sigset_t tmpsig;
u32 max_before_softirq;
u32 tx_since_softirq = 0;
- daemonize("pktgen/%d", cpu);
-
- /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
-
- spin_lock_irq(¤t->sighand->siglock);
- tmpsig = current->blocked;
- siginitsetinv(¤t->blocked,
- sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGTERM));
-
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
-
- /* Migrate to the right CPU */
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu)
- BUG();
+ BUG_ON(smp_processor_id() != cpu);
init_waitqueue_head(&t->queue);
- t->control &= ~(T_TERMINATE);
- t->control &= ~(T_RUN);
- t->control &= ~(T_STOP);
- t->control &= ~(T_REMDEVALL);
- t->control &= ~(T_REMDEV);
-
t->pid = current->pid;
PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid));
max_before_softirq = t->max_before_softirq;
- __set_current_state(TASK_INTERRUPTIBLE);
- mb();
+ set_current_state(TASK_INTERRUPTIBLE);
- while (1) {
-
- __set_current_state(TASK_RUNNING);
+ while (!kthread_should_stop()) {
+ pkt_dev = next_to_run(t);
- /*
- * Get next dev to xmit -- if any.
- */
+ if (!pkt_dev &&
+ (t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV))
+ == 0) {
+ prepare_to_wait(&(t->queue), &wait,
+ TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ / 10);
+ finish_wait(&(t->queue), &wait);
+ }
- pkt_dev = next_to_run(t);
+ __set_current_state(TASK_RUNNING);
if (pkt_dev) {
@@ -3329,21 +3311,8 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
do_softirq();
tx_since_softirq = 0;
}
- } else {
- prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
- finish_wait(&(t->queue), &wait);
}
- /*
- * Back from sleep, either due to the timeout or signal.
- * We check if we have any "posted" work for us.
- */
-
- if (t->control & T_TERMINATE || signal_pending(current))
- /* we received a request to terminate ourself */
- break;
-
if (t->control & T_STOP) {
pktgen_stop(t);
t->control &= ~(T_STOP);
@@ -3364,20 +3333,19 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
t->control &= ~(T_REMDEV);
}
- if (need_resched())
- schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
}
- PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
+ PG_DEBUG(printk("pktgen: %s stopping all device\n", t->tsk->comm));
pktgen_stop(t);
- PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
+ PG_DEBUG(printk("pktgen: %s removing all device\n", t->tsk->comm));
pktgen_rem_all_ifs(t);
- PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
+ PG_DEBUG(printk("pktgen: %s removing thread.\n", t->tsk->comm));
pktgen_rem_thread(t);
- t->removed = 1;
+ return 0;
}
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
@@ -3495,37 +3463,11 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
return add_dev_to_thread(t, pkt_dev);
}
-static struct pktgen_thread *__init pktgen_find_thread(const char *name)
+static int __init pktgen_create_thread(int cpu)
{
struct pktgen_thread *t;
-
- mutex_lock(&pktgen_thread_lock);
-
- list_for_each_entry(t, &pktgen_threads, th_list)
- if (strcmp(t->name, name) == 0) {
- mutex_unlock(&pktgen_thread_lock);
- return t;
- }
-
- mutex_unlock(&pktgen_thread_lock);
- return NULL;
-}
-
-static int __init pktgen_create_thread(const char *name, int cpu)
-{
- int err;
- struct pktgen_thread *t = NULL;
struct proc_dir_entry *pe;
-
- if (strlen(name) > 31) {
- printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n");
- return -EINVAL;
- }
-
- if (pktgen_find_thread(name)) {
- printk("pktgen: ERROR: thread: %s already exists\n", name);
- return -EINVAL;
- }
+ struct task_struct *p;
t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
if (!t) {
@@ -3533,14 +3475,29 @@ static int __init pktgen_create_thread(const char *name, int cpu)
return -ENOMEM;
}
- strcpy(t->name, name);
spin_lock_init(&t->if_lock);
t->cpu = cpu;
- pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+ INIT_LIST_HEAD(&t->if_list);
+
+ list_add_tail(&t->th_list, &pktgen_threads);
+
+ p = kthread_create(pktgen_thread_worker, t, "kpktgend_%d", cpu);
+ if (IS_ERR(p)) {
+ printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
+ list_del(&t->th_list);
+ kfree(t);
+ return PTR_ERR(p);
+ }
+ kthread_bind(p, cpu);
+ t->tsk = p;
+
+ pe = create_proc_entry(t->tsk->comm, 0600, pg_proc_dir);
if (!pe) {
printk("pktgen: cannot create %s/%s procfs entry.\n",
- PG_PROC_DIR, t->name);
+ PG_PROC_DIR, t->tsk->comm);
+ kthread_stop(p);
+ list_del(&t->th_list);
kfree(t);
return -EINVAL;
}
@@ -3548,21 +3505,7 @@ static int __init pktgen_create_thread(const char *name, int cpu)
pe->proc_fops = &pktgen_thread_fops;
pe->data = t;
- INIT_LIST_HEAD(&t->if_list);
-
- list_add_tail(&t->th_list, &pktgen_threads);
-
- t->removed = 0;
-
- err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (err < 0) {
- printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
- remove_proc_entry(t->name, pg_proc_dir);
- list_del(&t->th_list);
- kfree(t);
- return err;
- }
+ wake_up_process(p);
return 0;
}
@@ -3643,10 +3586,8 @@ static int __init pg_init(void)
for_each_online_cpu(cpu) {
int err;
- char buf[30];
- sprintf(buf, "kpktgend_%i", cpu);
- err = pktgen_create_thread(buf, cpu);
+ err = pktgen_create_thread(cpu);
if (err)
printk("pktgen: WARNING: Cannot create thread for cpu %d (%d)\n",
cpu, err);
@@ -3674,9 +3615,8 @@ static void __exit pg_cleanup(void)
list_for_each_safe(q, n, &pktgen_threads) {
t = list_entry(q, struct pktgen_thread, th_list);
- t->control |= (T_TERMINATE);
-
- wait_event_interruptible_timeout(queue, (t->removed == 1), HZ);
+ kthread_stop(t->tsk);
+ kfree(t);
}
/* Un-register us from receiving netdevice events */
^ permalink raw reply related [flat|nested] 23+ messages in thread
end of thread, other threads:[~2007-01-02 4:53 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20061121174737.GA5220@martell.zuzino.mipt.ru>
[not found] ` <9fa31860611211236i104cb510mb5100ea056b657db@mail.gmail.com>
2006-11-21 21:22 ` pktgen (was Re: tests of kernel modules) Alexey Dobriyan
2006-11-28 23:33 ` pktgen David Miller
2006-11-29 20:04 ` pktgen Alexey Dobriyan
2006-11-30 1:49 ` pktgen David Miller
2006-11-30 7:30 ` pktgen Alexey Dobriyan
2006-11-30 8:45 ` pktgen Robert Olsson
2006-11-30 17:33 ` pktgen Ben Greear
2006-12-01 4:14 ` pktgen David Miller
2006-12-01 8:14 ` pktgen Robert Olsson
2006-12-01 9:51 ` pktgen Alexey Dobriyan
2006-12-01 17:18 ` pktgen Robert Olsson
2006-12-01 23:25 ` pktgen David Miller
2007-01-02 4:53 ` pktgen David Miller
2006-12-01 8:22 ` pktgen Christoph Hellwig
2006-12-01 23:17 ` pktgen David Miller
[not found] <20041110165318.GA19639@xi.wantstofly.org>
[not found] ` <20041111233507.GA3202@xi.wantstofly.org>
[not found] ` <20041124161848.GA18059@xi.wantstofly.org>
[not found] ` <16804.48120.375307.718766@robur.slu.se>
[not found] ` <20041124170948.GC18059@xi.wantstofly.org>
[not found] ` <16804.60621.990421.525393@robur.slu.se>
[not found] ` <20041125030450.GA24417@xi.wantstofly.org>
[not found] ` <16805.40983.937641.670275@robur.slu.se>
[not found] ` <20041127002841.GA17184@xi.wantstofly.org>
[not found] ` <20041127004325.GA17401@xi.wantstofly.org>
2004-11-27 12:04 ` pktgen Robert Olsson
2004-11-27 13:53 ` pktgen Lennert Buytenhek
2004-11-27 14:39 ` pktgen Lennert Buytenhek
2004-11-27 15:04 ` pktgen jamal
2004-11-28 18:31 ` pktgen Lennert Buytenhek
2004-11-29 13:49 ` pktgen jamal
2004-11-29 16:57 ` pktgen Grant Grundler
2004-11-29 15:27 ` pktgen Robert Olsson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).