~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/core/profile.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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>
 15 
 16 #include <asm/processor.h>
 17 #include <asm/uaccess.h>
 18 #include <asm/system.h>
 19 
 20 #include <net/profile.h>
 21 
 22 #ifdef CONFIG_NET_PROFILE
 23 
 24 atomic_t net_profile_active;
 25 struct timeval net_profile_adjust;
 26 
 27 NET_PROFILE_DEFINE(total);
 28 
 29 struct net_profile_slot *net_profile_chain = &net_prof_total;
 30 
 31 #ifdef __alpha__
 32 __u32 alpha_lo;
 33 long alpha_hi;
 34 
 35 static void alpha_tick(unsigned long);
 36 
 37 static struct timer_list alpha_timer =
 38         { NULL, NULL, 0, 0L, alpha_tick };
 39 
 40 void alpha_tick(unsigned long dummy)
 41 {
 42         struct timeval dummy_stamp;
 43         net_profile_stamp(&dummy_stamp);
 44         alpha_timer.expires = jiffies + 4*HZ;
 45         add_timer(&alpha_timer);
 46 }
 47 
 48 #endif
 49 
 50 void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved)
 51 {
 52         struct net_profile_slot *s;
 53 
 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);
 58         }
 59 }
 60 
 61 
 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)
 65 {
 66         off_t pos=0;
 67         off_t begin=0;
 68         int len=0;
 69         struct net_profile_slot *s;
 70 
 71         len+= sprintf(buffer, "Slot            Hits       Hi         Lo         OnIrqHi    OnIrqLo    Ufl\n");
 72 
 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();
 79         }
 80         for (s = net_profile_chain; s; s = s->next) {
 81                 struct net_profile_slot tmp;
 82 
 83                 cli();
 84                 tmp = *s;
 85 
 86                 /* Wrong, but pretty close to truth */
 87 
 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);
 98                 }
 99                 sti();
100 
101                 net_profile_sub(&tmp.irq, &tmp.accumulator);
102 
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);
111 
112                         buffer[len++]='\n';
113                 
114                         pos=begin+len;
115                         if(pos<offset) {
116                                 len=0;
117                                 begin=pos;
118                         }
119                         if(pos>offset+length)
120                                 goto done;
121         }
122         *eof = 1;
123 
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();
137         }
138         return len;
139 }
140 #endif
141 
142 struct iphdr whitehole_iph;
143 int whitehole_count;
144 
145 static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev)
146 {
147         struct net_device_stats *stats;
148 
149         stats = (struct net_device_stats *)dev->priv;
150         stats->tx_packets++;
151         stats->tx_bytes+=skb->len;
152 
153         dev_kfree_skb(skb);
154         return 0;
155 }
156 
157 static void whitehole_inject(unsigned long);
158 int whitehole_init(struct net_device *dev);
159 
160 static struct timer_list whitehole_timer =
161         { NULL, NULL, 0, 0L, whitehole_inject };
162 
163 static struct net_device whitehole_dev = {
164         "whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, whitehole_init, };
165 
166 static int whitehole_open(struct net_device *dev)
167 {
168         whitehole_count = 100000;
169         whitehole_timer.expires = jiffies + 5*HZ;
170         add_timer(&whitehole_timer);
171         return 0;
172 }
173 
174 static int whitehole_close(struct net_device *dev)
175 {
176         del_timer(&whitehole_timer);
177         return 0;
178 }
179 
180 static void whitehole_inject(unsigned long dummy)
181 {
182         struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv;
183         extern int netdev_dropping;
184 
185         do {
186                 struct iphdr *iph;
187                 struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
188                 if (!skb)
189                         break;
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;
197                 stats->rx_packets++;
198                 stats->rx_bytes += skb->len;
199                 netif_rx(skb);
200                 whitehole_count--;
201         } while (netdev_dropping == 0 && whitehole_count>0);
202         if (whitehole_count > 0) {
203                 whitehole_timer.expires = jiffies + 1;
204                 add_timer(&whitehole_timer);
205         }
206 }
207 
208 static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
209 {
210         struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
211         return stats;
212 }
213 
214 int __init whitehole_init(struct net_device *dev)
215 {
216         dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
217         if (dev->priv == NULL)
218                 return -ENOBUFS;
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;
224         ether_setup(dev);
225         dev->tx_queue_len = 0;
226         dev->flags |= IFF_NOARP;
227         dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
228         dev->iflink = 0;
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);
236         return 0;
237 }
238 
239 int net_profile_register(struct net_profile_slot *slot)
240 {
241         cli();
242         slot->next = net_profile_chain;
243         net_profile_chain = slot;
244         sti();
245         return 0;
246 }
247 
248 int net_profile_unregister(struct net_profile_slot *slot)
249 {
250         struct net_profile_slot **sp, *s;
251 
252         for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) {
253                 if (s == slot) {
254                         cli();
255                         *sp = s->next;
256                         sti();
257                         return 0;
258                 }
259         }
260         return -ESRCH;
261 }
262 
263 
264 int __init net_profile_init(void)
265 {
266         int i;
267 
268 #ifdef CONFIG_PROC_FS
269         create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
270 #endif
271 
272         register_netdevice(&whitehole_dev);
273 
274         printk("Evaluating net profiler cost ...");
275 #ifdef __alpha__
276         alpha_tick(0);
277 #endif
278         for (i=0; i<1024; i++) {
279                 NET_PROFILE_ENTER(total);
280                 NET_PROFILE_LEAVE(total);
281         }
282         if (net_prof_total.accumulator.tv_sec) {
283                 printk(" too high!\n");
284         } else {
285                 net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10;
286                 printk("%ld units\n", net_profile_adjust.tv_usec);
287         }
288         net_prof_total.hits = 0;
289         net_profile_stamp(&net_prof_total.entered);
290         return 0;
291 }
292 
293 #endif
294 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.