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
;
157 static void whitehole_inject(unsigned long);
158 int whitehole_init(struct net_device
*dev
);
160 static struct timer_list whitehole_timer
=
161 { NULL
, NULL
, 0, 0L, whitehole_inject
};
163 static struct net_device whitehole_dev
= {
164 "whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL
, whitehole_init
, };
166 static int whitehole_open(struct net_device
*dev
)
168 whitehole_count
= 100000;
169 whitehole_timer
.expires
= jiffies
+ 5*HZ
;
170 add_timer(&whitehole_timer
);
174 static int whitehole_close(struct net_device
*dev
)
176 del_timer(&whitehole_timer
);
180 static void whitehole_inject(unsigned long dummy
)
182 struct net_device_stats
*stats
= (struct net_device_stats
*)whitehole_dev
.priv
;
183 extern int netdev_dropping
;
187 struct sk_buff
*skb
= alloc_skb(128, GFP_ATOMIC
);
190 skb_reserve(skb
, 32);
191 iph
= (struct iphdr
*)skb_put(skb
, sizeof(*iph
));
192 skb
->mac
.raw
= ((u8
*)iph
) - 14;
193 memcpy(iph
, &whitehole_iph
, sizeof(*iph
));
194 skb
->protocol
= __constant_htons(ETH_P_IP
);
195 skb
->dev
= &whitehole_dev
;
196 skb
->pkt_type
= PACKET_HOST
;
198 stats
->rx_bytes
+= skb
->len
;
201 } while (netdev_dropping
== 0 && whitehole_count
>0);
202 if (whitehole_count
> 0) {
203 whitehole_timer
.expires
= jiffies
+ 1;
204 add_timer(&whitehole_timer
);
208 static struct net_device_stats
*whitehole_get_stats(struct net_device
*dev
)
210 struct net_device_stats
*stats
= (struct net_device_stats
*) dev
->priv
;
214 int __init
whitehole_init(struct net_device
*dev
)
216 dev
->priv
= kmalloc(sizeof(struct net_device_stats
), GFP_KERNEL
);
217 if (dev
->priv
== NULL
)
219 memset(dev
->priv
, 0, sizeof(struct net_device_stats
));
220 dev
->get_stats
= whitehole_get_stats
;
221 dev
->hard_start_xmit
= whitehole_xmit
;
222 dev
->open
= whitehole_open
;
223 dev
->stop
= whitehole_close
;
225 dev
->tx_queue_len
= 0;
226 dev
->flags
|= IFF_NOARP
;
227 dev
->flags
&= ~(IFF_BROADCAST
|IFF_MULTICAST
);
229 whitehole_iph
.ihl
= 5;
230 whitehole_iph
.version
= 4;
231 whitehole_iph
.ttl
= 2;
232 whitehole_iph
.saddr
= in_aton("193.233.7.21");
233 whitehole_iph
.daddr
= in_aton("193.233.7.10");
234 whitehole_iph
.tot_len
= htons(20);
235 whitehole_iph
.check
= ip_compute_csum((void *)&whitehole_iph
, 20);
239 int net_profile_register(struct net_profile_slot
*slot
)
242 slot
->next
= net_profile_chain
;
243 net_profile_chain
= slot
;
248 int net_profile_unregister(struct net_profile_slot
*slot
)
250 struct net_profile_slot
**sp
, *s
;
252 for (sp
= &net_profile_chain
; (s
= *sp
) != NULL
; sp
= &s
->next
) {
264 int __init
net_profile_init(void)
268 #ifdef CONFIG_PROC_FS
269 create_proc_read_entry("net/profile", 0, 0, profile_read_proc
, NULL
);
272 register_netdevice(&whitehole_dev
);
274 printk("Evaluating net profiler cost ...");
278 for (i
=0; i
<1024; i
++) {
279 NET_PROFILE_ENTER(total
);
280 NET_PROFILE_LEAVE(total
);
282 if (net_prof_total
.accumulator
.tv_sec
) {
283 printk(" too high!\n");
285 net_profile_adjust
.tv_usec
= net_prof_total
.accumulator
.tv_usec
>>10;
286 printk("%ld units\n", net_profile_adjust
.tv_usec
);
288 net_prof_total
.hits
= 0;
289 net_profile_stamp(&net_prof_total
.entered
);