- pre2
[davej-history.git] / net / atm / mpoa_proc.c
blobbc04ecc67be0524619f6afd9d336a0562ccc10c8
1 #include <linux/config.h>
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"
18 * mpoa_proc.c: Implementation MPOA client's proc
19 * file system statistics
22 #if 1
23 #define dprintk printk /* debug */
24 #else
25 #define dprintk(format,args...)
26 #endif
28 #define STAT_FILE_NAME "mpc" /* Our statistic file's name */
30 extern struct mpoa_client *mpcs;
31 extern struct proc_dir_entry *atm_proc_root; /* from proc.c. */
33 static ssize_t proc_mpc_read(struct file *file, char *buff,
34 size_t count, loff_t *pos);
36 static ssize_t proc_mpc_write(struct file *file, const char *buff,
37 size_t nbytes, loff_t *ppos);
39 static int parse_qos(const char *buff, int len);
42 * Define allowed FILE OPERATIONS
44 static struct file_operations mpc_file_operations = {
45 read: proc_mpc_read,
46 write: proc_mpc_write,
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);
54 return 0;
58 * Returns the state of an ingress cache entry as a string
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 "";
80 * Returns the state of an egress cache entry as a string
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 "";
99 * READING function - called when the /proc/atm/mpoa file is read from.
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 -EINVAL;
114 if(count == 0)
115 return 0;
116 page = get_free_page(GFP_KERNEL);
117 if(!page)
118 return -ENOMEM;
119 atm_mpoa_disp_qos((char *)page, &length);
120 while(mpc != NULL){
121 length += print_header((char *)page + length, mpc);
122 length += sprintf((char *)page + length,"Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n");
123 in_entry = mpc->in_cache;
124 do_gettimeofday(&now);
125 while(in_entry != NULL){
126 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]);
127 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);
128 if(in_entry->shortcut)
129 length += sprintf((char *)page + length," %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci);
130 length += sprintf((char *)page + length,"\n");
131 in_entry = in_entry->next;
133 length += sprintf((char *)page + length,"\n");
134 eg_entry = mpc->eg_cache;
135 length += sprintf((char *)page + length,"Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n");
136 while(eg_entry != NULL){
137 for(i=0;i<ATM_ESA_LEN;i++){
138 length += sprintf((char *)page + length,"%02x",eg_entry->ctrl_info.in_MPC_data_ATM_addr[i]);}
139 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);
141 /* latest IP address */
142 temp = (unsigned char *)&eg_entry->latest_ip_addr;
143 sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
144 length += sprintf((char *)page + length, "%-16s", ip_string);
146 if(eg_entry->shortcut)
147 length += sprintf((char *)page + length," %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci);
148 length += sprintf((char *)page + length,"\n");
149 eg_entry = eg_entry->next;
151 length += sprintf((char *)page + length,"\n");
152 mpc = mpc->next;
155 if (*pos >= length) length = 0;
156 else {
157 if ((count + *pos) > length) count = length - *pos;
158 if (copy_to_user(buff, (char *)page , count)) {
159 free_page(page);
160 return -EFAULT;
162 *pos += count;
165 free_page(page);
166 return length;
169 static ssize_t proc_mpc_write(struct file *file, const char *buff,
170 size_t nbytes, loff_t *ppos)
172 int incoming, error, retval;
173 char *page, c;
174 const char *tmp;
176 if (nbytes < 0) return -EINVAL;
177 if (nbytes == 0) return 0;
178 if (nbytes > PAGE_SIZE) nbytes = PAGE_SIZE-1;
180 error = verify_area(VERIFY_READ, buff, nbytes);
181 if (error) return error;
183 page = (char *)__get_free_page(GFP_KERNEL);
184 if (page == NULL) return -ENOMEM;
186 incoming = 0;
187 tmp = buff;
188 while(incoming < nbytes){
189 if (get_user(c, tmp++)) return -EFAULT;
190 incoming++;
191 if (c == '\0' || c == '\n')
192 break;
195 retval = copy_from_user(page, buff, incoming);
196 if (retval != 0) {
197 printk("mpoa: proc_mpc_write: copy_from_user() failed\n");
198 return -EFAULT;
201 *ppos += incoming;
203 page[incoming] = '\0';
204 retval = parse_qos(page, incoming);
205 if (retval == 0)
206 printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
208 free_page((unsigned long)page);
210 return nbytes;
213 static int parse_qos(const char *buff, int len)
215 /* possible lines look like this
216 * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
219 int pos, i;
220 uint32_t ipaddr;
221 unsigned char ip[4];
222 char cmd[4], temp[256];
223 const char *tmp, *prev;
224 struct atm_qos qos;
225 int value[5];
227 memset(&qos, 0, sizeof(struct atm_qos));
228 strncpy(cmd, buff, 3);
229 if( strncmp(cmd,"add", 3) && strncmp(cmd,"del", 3))
230 return 0; /* not add or del */
232 pos = 4;
233 /* next parse ip */
234 prev = buff + pos;
235 for (i = 0; i < 3; i++) {
236 tmp = strchr(prev, '.');
237 if (tmp == NULL) return 0;
238 memset(temp, '\0', 256);
239 memcpy(temp, prev, tmp-prev);
240 ip[i] = (char)simple_strtoul(temp, NULL, 0);
241 tmp ++;
242 prev = tmp;
244 tmp = strchr(prev, ' ');
245 if (tmp == NULL) return 0;
246 memset(temp, '\0', 256);
247 memcpy(temp, prev, tmp-prev);
248 ip[i] = (char)simple_strtoul(temp, NULL, 0);
249 ipaddr = *(uint32_t *)ip;
251 if(!strncmp(cmd, "del", 3))
252 return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr));
254 /* next transmit values */
255 tmp = strstr(buff, "tx=");
256 if(tmp == NULL) return 0;
257 tmp += 3;
258 prev = tmp;
259 for( i = 0; i < 1; i++){
260 tmp = strchr(prev, ',');
261 if (tmp == NULL) return 0;
262 memset(temp, '\0', 256);
263 memcpy(temp, prev, tmp-prev);
264 value[i] = (int)simple_strtoul(temp, NULL, 0);
265 tmp ++;
266 prev = tmp;
268 tmp = strchr(prev, ' ');
269 if (tmp == NULL) return 0;
270 memset(temp, '\0', 256);
271 memcpy(temp, prev, tmp-prev);
272 value[i] = (int)simple_strtoul(temp, NULL, 0);
273 qos.txtp.traffic_class = ATM_CBR;
274 qos.txtp.max_pcr = value[0];
275 qos.txtp.max_sdu = value[1];
277 /* next receive values */
278 tmp = strstr(buff, "rx=");
279 if(tmp == NULL) return 0;
280 if (strstr(buff, "rx=tx")) { /* rx == tx */
281 qos.rxtp.traffic_class = qos.txtp.traffic_class;
282 qos.rxtp.max_pcr = qos.txtp.max_pcr;
283 qos.rxtp.max_cdv = qos.txtp.max_cdv;
284 qos.rxtp.max_sdu = qos.txtp.max_sdu;
285 } else {
286 tmp += 3;
287 prev = tmp;
288 for( i = 0; i < 1; i++){
289 tmp = strchr(prev, ',');
290 if (tmp == NULL) return 0;
291 memset(temp, '\0', 256);
292 memcpy(temp, prev, tmp-prev);
293 value[i] = (int)simple_strtoul(temp, NULL, 0);
294 tmp ++;
295 prev = tmp;
297 tmp = strchr(prev, '\0');
298 if (tmp == NULL) return 0;
299 memset(temp, '\0', 256);
300 memcpy(temp, prev, tmp-prev);
301 value[i] = (int)simple_strtoul(temp, NULL, 0);
302 qos.rxtp.traffic_class = ATM_CBR;
303 qos.rxtp.max_pcr = value[0];
304 qos.rxtp.max_sdu = value[1];
306 qos.aal = ATM_AAL5;
307 dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n",
308 qos.txtp.max_pcr,
309 qos.txtp.max_sdu,
310 qos.rxtp.max_pcr,
311 qos.rxtp.max_sdu
314 atm_mpoa_add_qos(ipaddr, &qos);
315 return 1;
319 * INITIALIZATION function - called when module is initialized/loaded.
321 int mpc_proc_init(void)
323 struct proc_dir_entry *p;
325 p = create_proc_entry(STAT_FILE_NAME, 0, atm_proc_root);
326 if (!p) {
327 printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
328 return -ENOMEM;
330 p->proc_fops = &mpc_file_operations;
331 p->owner = THIS_MODULE;
332 return 0;
336 * DELETING function - called when module is removed.
338 void mpc_proc_clean(void)
340 remove_proc_entry(STAT_FILE_NAME,atm_proc_root);
344 #endif /* CONFIG_PROC_FS */