Import 2.3.25pre1
[davej-history.git] / net / core / profile.c
blob8b2616c5022c7b12a4d1dd61df5e68b0699f8113
1 #include <linux/config.h>
2 #include <linux/types.h>
3 #include <linux/kernel.h>
4 #include <linux/sched.h>
5 #include <linux/mm.h>
6 #include <linux/interrupt.h>
7 #include <linux/netdevice.h>
8 #include <linux/string.h>
9 #include <linux/skbuff.h>
10 #include <linux/proc_fs.h>
11 #include <linux/init.h>
12 #include <linux/ip.h>
13 #include <linux/inet.h>
14 #include <net/checksum.h>
16 #include <asm/processor.h>
17 #include <asm/uaccess.h>
18 #include <asm/system.h>
20 #include <net/profile.h>
22 #ifdef CONFIG_NET_PROFILE
24 atomic_t net_profile_active;
25 struct timeval net_profile_adjust;
27 NET_PROFILE_DEFINE(total);
29 struct net_profile_slot *net_profile_chain = &net_prof_total;
31 #ifdef __alpha__
32 __u32 alpha_lo;
33 long alpha_hi;
35 static void alpha_tick(unsigned long);
37 static struct timer_list alpha_timer =
38 { NULL, NULL, 0, 0L, alpha_tick };
40 void alpha_tick(unsigned long dummy)
42 struct timeval dummy_stamp;
43 net_profile_stamp(&dummy_stamp);
44 alpha_timer.expires = jiffies + 4*HZ;
45 add_timer(&alpha_timer);
48 #endif
50 void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved)
52 struct net_profile_slot *s;
54 net_profile_sub(entered, leaved);
55 for (s = net_profile_chain; s; s = s->next) {
56 if (s->active)
57 net_profile_add(leaved, &s->irq);
62 #ifdef CONFIG_PROC_FS
63 static int profile_read_proc(char *buffer, char **start, off_t offset,
64 int length, int *eof, void *data)
66 off_t pos=0;
67 off_t begin=0;
68 int len=0;
69 struct net_profile_slot *s;
71 len+= sprintf(buffer, "Slot Hits Hi Lo OnIrqHi OnIrqLo Ufl\n");
73 if (offset == 0) {
74 cli();
75 net_prof_total.active = 1;
76 atomic_inc(&net_profile_active);
77 NET_PROFILE_LEAVE(total);
78 sti();
80 for (s = net_profile_chain; s; s = s->next) {
81 struct net_profile_slot tmp;
83 cli();
84 tmp = *s;
86 /* Wrong, but pretty close to truth */
88 s->accumulator.tv_sec = 0;
89 s->accumulator.tv_usec = 0;
90 s->irq.tv_sec = 0;
91 s->irq.tv_usec = 0;
92 s->hits = 0;
93 s->underflow = 0;
94 /* Repair active count, it is possible, only if code has a bug */
95 if (s->active) {
96 s->active = 0;
97 atomic_dec(&net_profile_active);
99 sti();
101 net_profile_sub(&tmp.irq, &tmp.accumulator);
103 len += sprintf(buffer+len,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d",
104 tmp.id,
105 tmp.hits,
106 tmp.accumulator.tv_sec,
107 tmp.accumulator.tv_usec,
108 tmp.irq.tv_sec,
109 tmp.irq.tv_usec,
110 tmp.underflow, tmp.active);
112 buffer[len++]='\n';
114 pos=begin+len;
115 if(pos<offset) {
116 len=0;
117 begin=pos;
119 if(pos>offset+length)
120 goto done;
122 *eof = 1;
124 done:
125 *start=buffer+(offset-begin);
126 len-=(offset-begin);
127 if(len>length)
128 len=length;
129 if (len < 0)
130 len = 0;
131 if (offset == 0) {
132 cli();
133 net_prof_total.active = 0;
134 net_prof_total.hits = 0;
135 net_profile_stamp(&net_prof_total.entered);
136 sti();
138 return len;
140 #endif
142 struct iphdr whitehole_iph;
143 int whitehole_count;
145 static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev)
147 struct net_device_stats *stats;
148 dev_kfree_skb(skb);
149 stats = (struct net_device_stats *)dev->priv;
150 stats->tx_packets++;
151 stats->tx_bytes+=skb->len;
153 return 0;
156 static void whitehole_inject(unsigned long);
157 int whitehole_init(struct net_device *dev);
159 static struct timer_list whitehole_timer =
160 { NULL, NULL, 0, 0L, whitehole_inject };
162 static struct net_device whitehole_dev = {
163 "whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, whitehole_init, };
165 static int whitehole_open(struct net_device *dev)
167 whitehole_count = 100000;
168 whitehole_timer.expires = jiffies + 5*HZ;
169 add_timer(&whitehole_timer);
170 return 0;
173 static int whitehole_close(struct net_device *dev)
175 del_timer(&whitehole_timer);
176 return 0;
179 static void whitehole_inject(unsigned long dummy)
181 struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv;
182 extern int netdev_dropping;
184 do {
185 struct iphdr *iph;
186 struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
187 if (!skb)
188 break;
189 skb_reserve(skb, 32);
190 iph = (struct iphdr*)skb_put(skb, sizeof(*iph));
191 skb->mac.raw = ((u8*)iph) - 14;
192 memcpy(iph, &whitehole_iph, sizeof(*iph));
193 skb->protocol = __constant_htons(ETH_P_IP);
194 skb->dev = &whitehole_dev;
195 skb->pkt_type = PACKET_HOST;
196 stats->rx_packets++;
197 stats->rx_bytes += skb->len;
198 netif_rx(skb);
199 whitehole_count--;
200 } while (netdev_dropping == 0 && whitehole_count>0);
201 if (whitehole_count > 0) {
202 whitehole_timer.expires = jiffies + 1;
203 add_timer(&whitehole_timer);
207 static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
209 struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
210 return stats;
213 int __init whitehole_init(struct net_device *dev)
215 dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
216 if (dev->priv == NULL)
217 return -ENOBUFS;
218 memset(dev->priv, 0, sizeof(struct net_device_stats));
219 dev->get_stats = whitehole_get_stats;
220 dev->hard_start_xmit = whitehole_xmit;
221 dev->open = whitehole_open;
222 dev->stop = whitehole_close;
223 ether_setup(dev);
224 dev->tx_queue_len = 0;
225 dev->flags |= IFF_NOARP;
226 dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
227 dev->iflink = 0;
228 whitehole_iph.ihl = 5;
229 whitehole_iph.version = 4;
230 whitehole_iph.ttl = 2;
231 whitehole_iph.saddr = in_aton("193.233.7.21");
232 whitehole_iph.daddr = in_aton("193.233.7.10");
233 whitehole_iph.tot_len = htons(20);
234 whitehole_iph.check = ip_compute_csum((void *)&whitehole_iph, 20);
235 return 0;
238 int net_profile_register(struct net_profile_slot *slot)
240 cli();
241 slot->next = net_profile_chain;
242 net_profile_chain = slot;
243 sti();
244 return 0;
247 int net_profile_unregister(struct net_profile_slot *slot)
249 struct net_profile_slot **sp, *s;
251 for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) {
252 if (s == slot) {
253 cli();
254 *sp = s->next;
255 sti();
256 return 0;
259 return -ESRCH;
263 int __init net_profile_init(void)
265 int i;
267 #ifdef CONFIG_PROC_FS
268 create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
269 #endif
271 register_netdevice(&whitehole_dev);
273 printk("Evaluating net profiler cost ...");
274 #if CPU == 586 || CPU == 686
275 if (!(boot_cpu_data.x86_capability & X86_FEATURE_TSC)) {
276 printk(KERN_ERR "Sorry, your CPU does not support TSC. Net profiler disabled.\n");
277 return -1;
279 #endif
280 #ifdef __alpha__
281 alpha_tick(0);
282 #endif
283 for (i=0; i<1024; i++) {
284 NET_PROFILE_ENTER(total);
285 NET_PROFILE_LEAVE(total);
287 if (net_prof_total.accumulator.tv_sec) {
288 printk(" too high!\n");
289 } else {
290 net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10;
291 printk("%ld units\n", net_profile_adjust.tv_usec);
293 net_prof_total.hits = 0;
294 net_profile_stamp(&net_prof_total.entered);
295 return 0;
298 #endif