mpoa_proc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <linux/config.h>
  2. #ifdef CONFIG_PROC_FS
  3. #include <linux/errno.h>
  4. #include <linux/kernel.h>
  5. #include <linux/string.h> 
  6. #include <linux/mm.h>
  7. #include <linux/module.h>
  8. #include <linux/proc_fs.h>
  9. #include <linux/time.h>
  10. #include <asm/uaccess.h>
  11. #include <linux/atmmpc.h>
  12. #include <linux/atm.h>
  13. #include "mpc.h"
  14. #include "mpoa_caches.h"
  15. /*
  16.  * mpoa_proc.c: Implementation MPOA client's proc
  17.  * file system statistics 
  18.  */
  19. #if 1
  20. #define dprintk printk   /* debug */
  21. #else
  22. #define dprintk(format,args...)
  23. #endif
  24. #define STAT_FILE_NAME "mpc"     /* Our statistic file's name */
  25. extern struct mpoa_client *mpcs;
  26. extern struct proc_dir_entry *atm_proc_root;  /* from proc.c. */
  27. static ssize_t proc_mpc_read(struct file *file, char *buff,
  28.      size_t count, loff_t *pos);
  29. static ssize_t proc_mpc_write(struct file *file, const char *buff,
  30.                               size_t nbytes, loff_t *ppos);
  31. static int parse_qos(const char *buff, int len);
  32. /*
  33.  *   Define allowed FILE OPERATIONS
  34.  */
  35. static struct file_operations mpc_file_operations = {
  36. read: proc_mpc_read,
  37. write: proc_mpc_write,
  38. };
  39. static int print_header(char *buff,struct mpoa_client *mpc){
  40.         if(mpc != NULL){
  41.         return sprintf(buff,"nInterface %d:nn",mpc->dev_num);  
  42.   
  43. }
  44. return 0;
  45. }
  46. /*
  47.  * Returns the state of an ingress cache entry as a string
  48.  */
  49. static const char *ingress_state_string(int state){
  50.         switch(state) {
  51. case INGRESS_RESOLVING:
  52.         return "resolving  ";
  53. break;
  54. case INGRESS_RESOLVED:
  55.                 return "resolved   ";
  56. break;
  57. case INGRESS_INVALID:
  58.         return "invalid    ";
  59. break;
  60. case INGRESS_REFRESHING:
  61.         return "refreshing ";
  62. break;
  63. default:
  64.        return "";
  65. }
  66. }
  67. /*
  68.  * Returns the state of an egress cache entry as a string
  69.  */
  70. static const char *egress_state_string(int state){
  71.         switch(state) {
  72. case EGRESS_RESOLVED:
  73.         return "resolved   ";
  74. break;
  75. case EGRESS_PURGE:
  76.                 return "purge      ";
  77. break;
  78. case EGRESS_INVALID:
  79.         return "invalid    ";
  80. break;
  81. default:
  82.        return "";
  83. }
  84. }
  85. /*
  86.  * READING function - called when the /proc/atm/mpoa file is read from.
  87.  */
  88. static ssize_t proc_mpc_read(struct file *file, char *buff,
  89.      size_t count, loff_t *pos){
  90.         unsigned long page = 0;
  91. unsigned char *temp;
  92.         ssize_t length  = 0;
  93. int i = 0;
  94. struct mpoa_client *mpc = mpcs;
  95. in_cache_entry *in_entry;
  96. eg_cache_entry *eg_entry;
  97. struct timeval now;
  98. unsigned char ip_string[16];
  99. if(count == 0)
  100.         return 0;
  101. page = get_free_page(GFP_KERNEL);
  102. if(!page)
  103.         return -ENOMEM;
  104. atm_mpoa_disp_qos((char *)page, &length);
  105. while(mpc != NULL){
  106.         length += print_header((char *)page + length, mpc);
  107. length += sprintf((char *)page + length,"Ingress Entries:nIP address      State      Holding time  Packets fwded  VPI  VCIn");
  108. in_entry = mpc->in_cache;
  109. do_gettimeofday(&now);
  110. while(in_entry != NULL){
  111.         temp = (unsigned char *)&in_entry->ctrl_info.in_dst_ip;                        sprintf(ip_string,"%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
  112.         length += sprintf((char *)page + length,"%-16s%s%-14lu%-12u", ip_string, ingress_state_string(in_entry->entry_state), (in_entry->ctrl_info.holding_time-(now.tv_sec-in_entry->tv.tv_sec)), in_entry->packets_fwded);
  113. if(in_entry->shortcut)
  114.         length += sprintf((char *)page + length,"   %-3d  %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci);
  115. length += sprintf((char *)page + length,"n");
  116. in_entry = in_entry->next;
  117. }
  118. length += sprintf((char *)page + length,"n");
  119. eg_entry = mpc->eg_cache;
  120. length += sprintf((char *)page + length,"Egress Entries:nIngress MPC ATM addrnCache-id        State      Holding time  Packets recvd  Latest IP addr   VPI VCIn");
  121. while(eg_entry != NULL){
  122.   for(i=0;i<ATM_ESA_LEN;i++){
  123.           length += sprintf((char *)page + length,"%02x",eg_entry->ctrl_info.in_MPC_data_ATM_addr[i]);}  
  124.         length += sprintf((char *)page + length,"n%-16lu%s%-14lu%-15u",(unsigned long) ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd);
  125. /* latest IP address */
  126. temp = (unsigned char *)&eg_entry->latest_ip_addr;
  127. sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
  128. length += sprintf((char *)page + length, "%-16s", ip_string);
  129. if(eg_entry->shortcut)
  130.         length += sprintf((char *)page + length," %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci);
  131. length += sprintf((char *)page + length,"n");
  132. eg_entry = eg_entry->next;
  133. }
  134. length += sprintf((char *)page + length,"n");
  135. mpc = mpc->next;
  136. }
  137. if (*pos >= length) length = 0;
  138. else {
  139.   if ((count + *pos) > length) count = length - *pos;
  140.   if (copy_to_user(buff, (char *)page , count)) {
  141.     free_page(page);
  142.   return -EFAULT;
  143.           }
  144.   *pos += count;
  145. }
  146.   free_page(page);
  147.         return length;
  148. }
  149. static ssize_t proc_mpc_write(struct file *file, const char *buff,
  150.                               size_t nbytes, loff_t *ppos)
  151. {
  152.         int incoming, error, retval;
  153.         char *page, c;
  154.         const char *tmp;
  155.         if (nbytes == 0) return 0;
  156.         if (nbytes >= PAGE_SIZE) nbytes = PAGE_SIZE-1;
  157.         error = verify_area(VERIFY_READ, buff, nbytes);
  158.         if (error) return error;
  159.         page = (char *)__get_free_page(GFP_KERNEL);
  160.         if (page == NULL) return -ENOMEM;
  161.         incoming = 0;
  162.         tmp = buff;
  163.         while(incoming < nbytes){
  164.                 if (get_user(c, tmp++)) return -EFAULT;
  165.                 incoming++;
  166.                 if (c == '' || c == 'n')
  167.                         break;
  168.         }
  169.         retval = copy_from_user(page, buff, incoming);
  170.         if (retval != 0) {
  171.                 printk("mpoa: proc_mpc_write: copy_from_user() failedn");
  172.                 return -EFAULT;
  173.         }
  174.         *ppos += incoming;
  175.         page[incoming] = '';
  176. retval = parse_qos(page, incoming);
  177.         if (retval == 0)
  178.                 printk("mpoa: proc_mpc_write: could not parse '%s'n", page);
  179.         free_page((unsigned long)page);
  180.         
  181.         return nbytes;
  182. }
  183. static int parse_qos(const char *buff, int len)
  184. {
  185.         /* possible lines look like this
  186.          * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
  187.          */
  188.         
  189.         int pos, i;
  190.         uint32_t ipaddr;
  191.         unsigned char ip[4]; 
  192.         char cmd[4], temp[256];
  193.         const char *tmp, *prev;
  194. struct atm_qos qos; 
  195. int value[5];
  196.         
  197.         memset(&qos, 0, sizeof(struct atm_qos));
  198.         strncpy(cmd, buff, 3);
  199.         if( strncmp(cmd,"add", 3) &&  strncmp(cmd,"del", 3))
  200.         return 0;  /* not add or del */
  201. pos = 4;
  202.         /* next parse ip */
  203.         prev = buff + pos;
  204.         for (i = 0; i < 3; i++) {
  205.                 tmp = strchr(prev, '.');
  206.                 if (tmp == NULL) return 0;
  207.                 memset(temp, '', 256);
  208.                 memcpy(temp, prev, tmp-prev);
  209.                 ip[i] = (char)simple_strtoul(temp, NULL, 0);
  210. tmp ++; 
  211. prev = tmp;
  212.         }
  213. tmp = strchr(prev, ' ');
  214.         if (tmp == NULL) return 0;
  215.         memset(temp, '', 256);
  216.         memcpy(temp, prev, tmp-prev);
  217.         ip[i] = (char)simple_strtoul(temp, NULL, 0);
  218.         ipaddr = *(uint32_t *)ip;
  219.                 
  220. if(!strncmp(cmd, "del", 3))
  221.          return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr));
  222.         /* next transmit values */
  223. tmp = strstr(buff, "tx=");
  224. if(tmp == NULL) return 0;
  225. tmp += 3;
  226. prev = tmp;
  227. for( i = 0; i < 1; i++){
  228.          tmp = strchr(prev, ',');
  229.  if (tmp == NULL) return 0;
  230.  memset(temp, '', 256);
  231.  memcpy(temp, prev, tmp-prev);
  232.  value[i] = (int)simple_strtoul(temp, NULL, 0);
  233.  tmp ++; 
  234.  prev = tmp;
  235. }
  236. tmp = strchr(prev, ' ');
  237.         if (tmp == NULL) return 0;
  238. memset(temp, '', 256);
  239.         memcpy(temp, prev, tmp-prev);
  240.         value[i] = (int)simple_strtoul(temp, NULL, 0);
  241. qos.txtp.traffic_class = ATM_CBR;
  242. qos.txtp.max_pcr = value[0];
  243. qos.txtp.max_sdu = value[1];
  244.         /* next receive values */
  245. tmp = strstr(buff, "rx=");
  246. if(tmp == NULL) return 0;
  247.         if (strstr(buff, "rx=tx")) { /* rx == tx */
  248.                 qos.rxtp.traffic_class = qos.txtp.traffic_class;
  249.                 qos.rxtp.max_pcr = qos.txtp.max_pcr;
  250.                 qos.rxtp.max_cdv = qos.txtp.max_cdv;
  251.                 qos.rxtp.max_sdu = qos.txtp.max_sdu;
  252.         } else {
  253.                 tmp += 3;
  254.                 prev = tmp;
  255.                 for( i = 0; i < 1; i++){
  256.                         tmp = strchr(prev, ',');
  257.                         if (tmp == NULL) return 0;
  258.                         memset(temp, '', 256);
  259.                         memcpy(temp, prev, tmp-prev);
  260.                         value[i] = (int)simple_strtoul(temp, NULL, 0);
  261.                         tmp ++; 
  262.                         prev = tmp;
  263.                 }
  264.                 tmp = strchr(prev, '');
  265.                 if (tmp == NULL) return 0;
  266.                 memset(temp, '', 256);
  267.                 memcpy(temp, prev, tmp-prev);
  268.                 value[i] = (int)simple_strtoul(temp, NULL, 0);
  269.                 qos.rxtp.traffic_class = ATM_CBR;
  270.                 qos.rxtp.max_pcr = value[0];
  271.                 qos.rxtp.max_sdu = value[1];
  272.         }
  273.         qos.aal = ATM_AAL5;
  274. dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%dn",
  275. qos.txtp.max_pcr,
  276. qos.txtp.max_sdu,
  277. qos.rxtp.max_pcr,
  278. qos.rxtp.max_sdu
  279. );
  280. atm_mpoa_add_qos(ipaddr, &qos);
  281. return 1;
  282. }
  283. /*
  284.  * INITIALIZATION function - called when module is initialized/loaded.
  285.  */
  286. int mpc_proc_init(void)
  287. {
  288. struct proc_dir_entry *p;
  289.         p = create_proc_entry(STAT_FILE_NAME, 0, atm_proc_root);
  290. if (!p) {
  291.                 printk(KERN_ERR "Unable to initialize /proc/atm/%sn", STAT_FILE_NAME);
  292.                 return -ENOMEM;
  293.         }
  294. p->proc_fops = &mpc_file_operations;
  295. p->owner = THIS_MODULE;
  296. return 0;
  297. }
  298. /*
  299.  * DELETING function - called when module is removed.
  300.  */
  301. void mpc_proc_clean(void)
  302. {
  303. remove_proc_entry(STAT_FILE_NAME,atm_proc_root);
  304. }
  305. #endif /* CONFIG_PROC_FS */