profile.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #include <asm/processor.h>
  16. #include <asm/uaccess.h>
  17. #include <asm/system.h>
  18. #include <net/profile.h>
  19. #ifdef CONFIG_NET_PROFILE
  20. atomic_t net_profile_active;
  21. struct timeval net_profile_adjust;
  22. NET_PROFILE_DEFINE(total);
  23. struct net_profile_slot *net_profile_chain = &net_prof_total;
  24. #ifdef __alpha__
  25. __u32 alpha_lo;
  26. long alpha_hi;
  27. static void alpha_tick(unsigned long);
  28. static struct timer_list alpha_timer =
  29. { NULL, NULL, 0, 0L, alpha_tick };
  30. void alpha_tick(unsigned long dummy)
  31. {
  32. struct timeval dummy_stamp;
  33. net_profile_stamp(&dummy_stamp);
  34. alpha_timer.expires = jiffies + 4*HZ;
  35. add_timer(&alpha_timer);
  36. }
  37. #endif
  38. void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved)
  39. {
  40. struct net_profile_slot *s;
  41. net_profile_sub(entered, leaved);
  42. for (s = net_profile_chain; s; s = s->next) {
  43. if (s->active)
  44. net_profile_add(leaved, &s->irq);
  45. }
  46. }
  47. #ifdef CONFIG_PROC_FS
  48. static int profile_read_proc(char *buffer, char **start, off_t offset,
  49.      int length, int *eof, void *data)
  50. {
  51. off_t pos=0;
  52. off_t begin=0;
  53. int len=0;
  54. struct net_profile_slot *s;
  55. len+= sprintf(buffer, "Slot            Hits       Hi         Lo         OnIrqHi    OnIrqLo    Ufln");
  56. if (offset == 0) {
  57. cli();
  58. net_prof_total.active = 1;
  59. atomic_inc(&net_profile_active);
  60. NET_PROFILE_LEAVE(total);
  61. sti();
  62. }
  63. for (s = net_profile_chain; s; s = s->next) {
  64. struct net_profile_slot tmp;
  65. cli();
  66. tmp = *s;
  67. /* Wrong, but pretty close to truth */
  68. s->accumulator.tv_sec = 0;
  69. s->accumulator.tv_usec = 0;
  70. s->irq.tv_sec = 0;
  71. s->irq.tv_usec = 0;
  72. s->hits = 0;
  73. s->underflow = 0;
  74. /* Repair active count, it is possible, only if code has a bug */
  75. if (s->active) {
  76. s->active = 0;
  77. atomic_dec(&net_profile_active);
  78. }
  79. sti();
  80. net_profile_sub(&tmp.irq, &tmp.accumulator);
  81. len += sprintf(buffer+len,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d",
  82.        tmp.id,
  83.        tmp.hits,
  84.        tmp.accumulator.tv_sec,
  85.        tmp.accumulator.tv_usec,
  86.        tmp.irq.tv_sec,
  87.        tmp.irq.tv_usec,
  88.        tmp.underflow, tmp.active);
  89. buffer[len++]='n';
  90. pos=begin+len;
  91. if(pos<offset) {
  92. len=0;
  93. begin=pos;
  94. }
  95. if(pos>offset+length)
  96. goto done;
  97. }
  98. *eof = 1;
  99. done:
  100. *start=buffer+(offset-begin);
  101. len-=(offset-begin);
  102. if(len>length)
  103. len=length;
  104. if (len < 0)
  105. len = 0;
  106. if (offset == 0) {
  107. cli();
  108. net_prof_total.active = 0;
  109. net_prof_total.hits = 0;
  110. net_profile_stamp(&net_prof_total.entered);
  111. sti();
  112. }
  113. return len;
  114. }
  115. #endif
  116. struct iphdr whitehole_iph;
  117. int whitehole_count;
  118. static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev)
  119. {
  120. struct net_device_stats *stats;
  121. stats = (struct net_device_stats *)dev->priv;
  122. stats->tx_packets++;
  123. stats->tx_bytes+=skb->len;
  124. dev_kfree_skb(skb);
  125. return 0;
  126. }
  127. static void whitehole_inject(unsigned long);
  128. int whitehole_init(struct net_device *dev);
  129. static struct timer_list whitehole_timer =
  130. { NULL, NULL, 0, 0L, whitehole_inject };
  131. static struct net_device whitehole_dev = {
  132. "whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, whitehole_init, };
  133. static int whitehole_open(struct net_device *dev)
  134. {
  135. whitehole_count = 100000;
  136. whitehole_timer.expires = jiffies + 5*HZ;
  137. add_timer(&whitehole_timer);
  138. return 0;
  139. }
  140. static int whitehole_close(struct net_device *dev)
  141. {
  142. del_timer(&whitehole_timer);
  143. return 0;
  144. }
  145. static void whitehole_inject(unsigned long dummy)
  146. {
  147. struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv;
  148. extern int netdev_dropping;
  149. do {
  150. struct iphdr *iph;
  151. struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
  152. if (!skb)
  153. break;
  154. skb_reserve(skb, 32);
  155. iph = (struct iphdr*)skb_put(skb, sizeof(*iph));
  156. skb->mac.raw = ((u8*)iph) - 14;
  157. memcpy(iph, &whitehole_iph, sizeof(*iph));
  158. skb->protocol = __constant_htons(ETH_P_IP);
  159. skb->dev = &whitehole_dev;
  160. skb->pkt_type = PACKET_HOST;
  161. stats->rx_packets++;
  162. stats->rx_bytes += skb->len;
  163. netif_rx(skb);
  164. whitehole_count--;
  165. } while (netdev_dropping == 0 && whitehole_count>0);
  166. if (whitehole_count > 0) {
  167. whitehole_timer.expires = jiffies + 1;
  168. add_timer(&whitehole_timer);
  169. }
  170. }
  171. static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
  172. {
  173. struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
  174. return stats;
  175. }
  176. int __init whitehole_init(struct net_device *dev)
  177. {
  178. dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
  179. if (dev->priv == NULL)
  180. return -ENOBUFS;
  181. memset(dev->priv, 0, sizeof(struct net_device_stats));
  182. dev->get_stats = whitehole_get_stats;
  183. dev->hard_start_xmit = whitehole_xmit;
  184. dev->open = whitehole_open;
  185. dev->stop = whitehole_close;
  186. ether_setup(dev);
  187. dev->tx_queue_len = 0;
  188. dev->flags |= IFF_NOARP;
  189. dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
  190. dev->iflink = 0;
  191. whitehole_iph.ihl = 5;
  192. whitehole_iph.version = 4;
  193. whitehole_iph.ttl = 2;
  194. whitehole_iph.saddr = in_aton("193.233.7.21");
  195. whitehole_iph.daddr = in_aton("193.233.7.10");
  196. whitehole_iph.tot_len = htons(20);
  197. whitehole_iph.check = ip_compute_csum((void *)&whitehole_iph, 20);
  198. return 0;
  199. }
  200. int net_profile_register(struct net_profile_slot *slot)
  201. {
  202. cli();
  203. slot->next = net_profile_chain;
  204. net_profile_chain = slot;
  205. sti();
  206. return 0;
  207. }
  208. int net_profile_unregister(struct net_profile_slot *slot)
  209. {
  210. struct net_profile_slot **sp, *s;
  211. for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) {
  212. if (s == slot) {
  213. cli();
  214. *sp = s->next;
  215. sti();
  216. return 0;
  217. }
  218. }
  219. return -ESRCH;
  220. }
  221. int __init net_profile_init(void)
  222. {
  223. int i;
  224. #ifdef CONFIG_PROC_FS
  225. create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
  226. #endif
  227. register_netdevice(&whitehole_dev);
  228. printk("Evaluating net profiler cost ...");
  229. #ifdef __alpha__
  230. alpha_tick(0);
  231. #endif
  232. for (i=0; i<1024; i++) {
  233. NET_PROFILE_ENTER(total);
  234. NET_PROFILE_LEAVE(total);
  235. }
  236. if (net_prof_total.accumulator.tv_sec) {
  237. printk(" too high!n");
  238. } else {
  239. net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10;
  240. printk("%ld unitsn", net_profile_adjust.tv_usec);
  241. }
  242. net_prof_total.hits = 0;
  243. net_profile_stamp(&net_prof_total.entered);
  244. return 0;
  245. }
  246. #endif