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