1 #include <linux/config.h>
2 #include <linux/types.h>
3 #include <linux/kernel.h>
4 #include <linux/sched.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>
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
;
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
);
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
) {
57 net_profile_add(leaved
, &s
->irq
);
63 static int profile_read_proc(char *buffer
, char **start
, off_t offset
,
64 int length
, int *eof
, void *data
)
69 struct net_profile_slot
*s
;
71 len
+= sprintf(buffer
, "Slot Hits Hi Lo OnIrqHi OnIrqLo Ufl\n");
75 net_prof_total
.active
= 1;
76 atomic_inc(&net_profile_active
);
77 NET_PROFILE_LEAVE(total
);
80 for (s
= net_profile_chain
; s
; s
= s
->next
) {
81 struct net_profile_slot tmp
;
86 /* Wrong, but pretty close to truth */
88 s
->accumulator
.tv_sec
= 0;
89 s
->accumulator
.tv_usec
= 0;
94 /* Repair active count, it is possible, only if code has a bug */
97 atomic_dec(&net_profile_active
);
101 net_profile_sub(&tmp
.irq
, &tmp
.accumulator
);
103 len
+= sprintf(buffer
+len
,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d",
106 tmp
.accumulator
.tv_sec
,
107 tmp
.accumulator
.tv_usec
,
110 tmp
.underflow
, tmp
.active
);
119 if(pos
>offset
+length
)
125 *start
=buffer
+(offset
-begin
);
133 net_prof_total
.active
= 0;
134 net_prof_total
.hits
= 0;
135 net_profile_stamp(&net_prof_total
.entered
);
142 struct iphdr whitehole_iph
;
145 static int whitehole_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
147 struct net_device_stats
*stats
;
149 stats
= (struct net_device_stats
*)dev
->priv
;
151 stats
->tx_bytes
+=skb
->len
;
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
);
173 static int whitehole_close(struct net_device
*dev
)
175 del_timer(&whitehole_timer
);
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
;
186 struct sk_buff
*skb
= alloc_skb(128, GFP_ATOMIC
);
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
;
197 stats
->rx_bytes
+= skb
->len
;
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
;
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
)
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
;
224 dev
->tx_queue_len
= 0;
225 dev
->flags
|= IFF_NOARP
;
226 dev
->flags
&= ~(IFF_BROADCAST
|IFF_MULTICAST
);
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);
238 int net_profile_register(struct net_profile_slot
*slot
)
241 slot
->next
= net_profile_chain
;
242 net_profile_chain
= slot
;
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
) {
263 int __init
net_profile_init(void)
267 #ifdef CONFIG_PROC_FS
268 create_proc_read_entry("net/profile", 0, 0, profile_read_proc
, NULL
);
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");
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");
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
);