profile.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
- #include <linux/config.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/mm.h>
- #include <linux/interrupt.h>
- #include <linux/netdevice.h>
- #include <linux/string.h>
- #include <linux/skbuff.h>
- #include <linux/proc_fs.h>
- #include <linux/init.h>
- #include <linux/ip.h>
- #include <linux/inet.h>
- #include <net/checksum.h>
- #include <asm/processor.h>
- #include <asm/uaccess.h>
- #include <asm/system.h>
- #include <net/profile.h>
- #ifdef CONFIG_NET_PROFILE
- atomic_t net_profile_active;
- struct timeval net_profile_adjust;
- NET_PROFILE_DEFINE(total);
- struct net_profile_slot *net_profile_chain = &net_prof_total;
- #ifdef __alpha__
- __u32 alpha_lo;
- long alpha_hi;
- static void alpha_tick(unsigned long);
- static struct timer_list alpha_timer =
- { NULL, NULL, 0, 0L, alpha_tick };
- void alpha_tick(unsigned long dummy)
- {
- struct timeval dummy_stamp;
- net_profile_stamp(&dummy_stamp);
- alpha_timer.expires = jiffies + 4*HZ;
- add_timer(&alpha_timer);
- }
- #endif
- void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved)
- {
- struct net_profile_slot *s;
- net_profile_sub(entered, leaved);
- for (s = net_profile_chain; s; s = s->next) {
- if (s->active)
- net_profile_add(leaved, &s->irq);
- }
- }
- #ifdef CONFIG_PROC_FS
- static int profile_read_proc(char *buffer, char **start, off_t offset,
- int length, int *eof, void *data)
- {
- off_t pos=0;
- off_t begin=0;
- int len=0;
- struct net_profile_slot *s;
- len+= sprintf(buffer, "Slot Hits Hi Lo OnIrqHi OnIrqLo Ufln");
- if (offset == 0) {
- cli();
- net_prof_total.active = 1;
- atomic_inc(&net_profile_active);
- NET_PROFILE_LEAVE(total);
- sti();
- }
- for (s = net_profile_chain; s; s = s->next) {
- struct net_profile_slot tmp;
- cli();
- tmp = *s;
- /* Wrong, but pretty close to truth */
- s->accumulator.tv_sec = 0;
- s->accumulator.tv_usec = 0;
- s->irq.tv_sec = 0;
- s->irq.tv_usec = 0;
- s->hits = 0;
- s->underflow = 0;
- /* Repair active count, it is possible, only if code has a bug */
- if (s->active) {
- s->active = 0;
- atomic_dec(&net_profile_active);
- }
- sti();
- net_profile_sub(&tmp.irq, &tmp.accumulator);
- len += sprintf(buffer+len,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d",
- tmp.id,
- tmp.hits,
- tmp.accumulator.tv_sec,
- tmp.accumulator.tv_usec,
- tmp.irq.tv_sec,
- tmp.irq.tv_usec,
- tmp.underflow, tmp.active);
- buffer[len++]='n';
-
- pos=begin+len;
- if(pos<offset) {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- goto done;
- }
- *eof = 1;
- done:
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- if (len < 0)
- len = 0;
- if (offset == 0) {
- cli();
- net_prof_total.active = 0;
- net_prof_total.hits = 0;
- net_profile_stamp(&net_prof_total.entered);
- sti();
- }
- return len;
- }
- #endif
- struct iphdr whitehole_iph;
- int whitehole_count;
- static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- struct net_device_stats *stats;
- stats = (struct net_device_stats *)dev->priv;
- stats->tx_packets++;
- stats->tx_bytes+=skb->len;
- dev_kfree_skb(skb);
- return 0;
- }
- static void whitehole_inject(unsigned long);
- int whitehole_init(struct net_device *dev);
- static struct timer_list whitehole_timer =
- { NULL, NULL, 0, 0L, whitehole_inject };
- static struct net_device whitehole_dev = {
- "whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, whitehole_init, };
- static int whitehole_open(struct net_device *dev)
- {
- whitehole_count = 100000;
- whitehole_timer.expires = jiffies + 5*HZ;
- add_timer(&whitehole_timer);
- return 0;
- }
- static int whitehole_close(struct net_device *dev)
- {
- del_timer(&whitehole_timer);
- return 0;
- }
- static void whitehole_inject(unsigned long dummy)
- {
- struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv;
- extern int netdev_dropping;
- do {
- struct iphdr *iph;
- struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
- if (!skb)
- break;
- skb_reserve(skb, 32);
- iph = (struct iphdr*)skb_put(skb, sizeof(*iph));
- skb->mac.raw = ((u8*)iph) - 14;
- memcpy(iph, &whitehole_iph, sizeof(*iph));
- skb->protocol = __constant_htons(ETH_P_IP);
- skb->dev = &whitehole_dev;
- skb->pkt_type = PACKET_HOST;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- netif_rx(skb);
- whitehole_count--;
- } while (netdev_dropping == 0 && whitehole_count>0);
- if (whitehole_count > 0) {
- whitehole_timer.expires = jiffies + 1;
- add_timer(&whitehole_timer);
- }
- }
- static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
- {
- struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
- return stats;
- }
- int __init whitehole_init(struct net_device *dev)
- {
- dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOBUFS;
- memset(dev->priv, 0, sizeof(struct net_device_stats));
- dev->get_stats = whitehole_get_stats;
- dev->hard_start_xmit = whitehole_xmit;
- dev->open = whitehole_open;
- dev->stop = whitehole_close;
- ether_setup(dev);
- dev->tx_queue_len = 0;
- dev->flags |= IFF_NOARP;
- dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
- dev->iflink = 0;
- whitehole_iph.ihl = 5;
- whitehole_iph.version = 4;
- whitehole_iph.ttl = 2;
- whitehole_iph.saddr = in_aton("193.233.7.21");
- whitehole_iph.daddr = in_aton("193.233.7.10");
- whitehole_iph.tot_len = htons(20);
- whitehole_iph.check = ip_compute_csum((void *)&whitehole_iph, 20);
- return 0;
- }
- int net_profile_register(struct net_profile_slot *slot)
- {
- cli();
- slot->next = net_profile_chain;
- net_profile_chain = slot;
- sti();
- return 0;
- }
- int net_profile_unregister(struct net_profile_slot *slot)
- {
- struct net_profile_slot **sp, *s;
- for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) {
- if (s == slot) {
- cli();
- *sp = s->next;
- sti();
- return 0;
- }
- }
- return -ESRCH;
- }
- int __init net_profile_init(void)
- {
- int i;
- #ifdef CONFIG_PROC_FS
- create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
- #endif
- register_netdevice(&whitehole_dev);
- printk("Evaluating net profiler cost ...");
- #ifdef __alpha__
- alpha_tick(0);
- #endif
- for (i=0; i<1024; i++) {
- NET_PROFILE_ENTER(total);
- NET_PROFILE_LEAVE(total);
- }
- if (net_prof_total.accumulator.tv_sec) {
- printk(" too high!n");
- } else {
- net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10;
- printk("%ld unitsn", net_profile_adjust.tv_usec);
- }
- net_prof_total.hits = 0;
- net_profile_stamp(&net_prof_total.entered);
- return 0;
- }
- #endif