summaryrefslogtreecommitdiffstats
path: root/net/atm/mpoa_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/atm/mpoa_proc.c')
-rw-r--r--net/atm/mpoa_proc.c391
1 files changed, 391 insertions, 0 deletions
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
new file mode 100644
index 000000000..fc51bdd0a
--- /dev/null
+++ b/net/atm/mpoa_proc.c
@@ -0,0 +1,391 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_PROC_FS
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/time.h>
+#include <asm/uaccess.h>
+#include <linux/atmmpc.h>
+#include <linux/atm.h>
+#include "mpc.h"
+#include "mpoa_caches.h"
+
+/*
+ * mpoa_proc.c: Implementation MPOA client's proc
+ * file system statistics
+ */
+
+#if 1
+#define dprintk printk /* debug */
+#else
+#define dprintk(format,args...)
+#endif
+
+#define STAT_FILE_NAME "mpc" /* Our statistic file's name */
+
+extern struct mpoa_client *mpcs;
+extern struct proc_dir_entry atm_proc_root; /* from proc.c. */
+
+static ssize_t proc_mpc_read(struct file *file, char *buff,
+ size_t count, loff_t *pos);
+
+static ssize_t proc_mpc_write(struct file *file, const char *buff,
+ size_t nbytes, loff_t *ppos);
+
+static int parse_qos(const char *buff, int len);
+
+/*
+ * Define allowed FILE OPERATIONS
+ */
+static struct file_operations mpc_file_operations = {
+ NULL, /* lseek */
+ proc_mpc_read, /* read */
+ proc_mpc_write, /* write */
+ NULL, /* readdir */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* no fsync */
+};
+
+/*
+ * Define allowed INODE OPERATIONS
+ */
+static struct inode_operations mpc_inode_operations = {
+ &mpc_file_operations,
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+
+/*
+ * Our statistics file
+ */
+static struct proc_dir_entry mpc_stats = {
+ 0, /* low_ino */
+ sizeof(STAT_FILE_NAME)-1, /* name length */
+ STAT_FILE_NAME, /* name */
+ S_IFREG | S_IRUGO, /* mode */
+ 1, /* 1=file */
+ 0, /* UID */
+ 0, /* GID */
+ 0, /* size */
+ &mpc_inode_operations, /* inode operations */
+ NULL /* get_info func-ptr */
+
+};
+
+static int print_header(char *buff,struct mpoa_client *mpc){
+ if(mpc != NULL){
+ return sprintf(buff,"\nInterface %d:\n\n",mpc->dev_num);
+
+ }
+ return 0;
+}
+
+/*
+ * Returns the state of an ingress cache entry as a string
+ */
+static const char *ingress_state_string(int state){
+ switch(state) {
+ case INGRESS_RESOLVING:
+ return "resolving ";
+ break;
+ case INGRESS_RESOLVED:
+ return "resolved ";
+ break;
+ case INGRESS_INVALID:
+ return "invalid ";
+ break;
+ case INGRESS_REFRESHING:
+ return "refreshing ";
+ break;
+ default:
+ return "";
+ }
+}
+
+/*
+ * Returns the state of an egress cache entry as a string
+ */
+static const char *egress_state_string(int state){
+ switch(state) {
+ case EGRESS_RESOLVED:
+ return "resolved ";
+ break;
+ case EGRESS_PURGE:
+ return "purge ";
+ break;
+ case EGRESS_INVALID:
+ return "invalid ";
+ break;
+ default:
+ return "";
+ }
+}
+
+/*
+ * READING function - called when the /proc/atm/mpoa file is read from.
+ */
+static ssize_t proc_mpc_read(struct file *file, char *buff,
+ size_t count, loff_t *pos){
+ unsigned long page = 0;
+ unsigned char *temp;
+ ssize_t length = 0;
+ int i = 0;
+ struct mpoa_client *mpc = mpcs;
+ in_cache_entry *in_entry;
+ eg_cache_entry *eg_entry;
+ struct timeval now;
+ unsigned char ip_string[16];
+ if(count < 0)
+ return -EINVAL;
+ if(count == 0)
+ return 0;
+ page = get_free_page(GFP_KERNEL);
+ if(!page)
+ return -ENOMEM;
+ atm_mpoa_disp_qos((char *)page, &length);
+ while(mpc != NULL){
+ length += print_header((char *)page + length, mpc);
+ length += sprintf((char *)page + length,"Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n");
+ in_entry = mpc->in_cache;
+ do_gettimeofday(&now);
+ while(in_entry != NULL){
+ 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]);
+ 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);
+ if(in_entry->shortcut)
+ length += sprintf((char *)page + length," %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci);
+ length += sprintf((char *)page + length,"\n");
+ in_entry = in_entry->next;
+ }
+ length += sprintf((char *)page + length,"\n");
+ eg_entry = mpc->eg_cache;
+ length += sprintf((char *)page + length,"Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n");
+ while(eg_entry != NULL){
+ for(i=0;i<ATM_ESA_LEN;i++){
+ length += sprintf((char *)page + length,"%02x",eg_entry->ctrl_info.in_MPC_data_ATM_addr[i]);}
+ length += sprintf((char *)page + length,"\n%-16lu%s%-14lu%-15u",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);
+
+ /* latest IP address */
+ temp = (unsigned char *)&eg_entry->latest_ip_addr;
+ sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
+ length += sprintf((char *)page + length, "%-16s", ip_string);
+
+ if(eg_entry->shortcut)
+ length += sprintf((char *)page + length," %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci);
+ length += sprintf((char *)page + length,"\n");
+ eg_entry = eg_entry->next;
+ }
+ length += sprintf((char *)page + length,"\n");
+ mpc = mpc->next;
+ }
+
+ if (*pos >= length) length = 0;
+ else {
+ if ((count + *pos) > length) count = length - *pos;
+ copy_to_user(buff, (char *)page , count);
+ *pos += count;
+ }
+
+ free_page(page);
+ return length;
+}
+
+static ssize_t proc_mpc_write(struct file *file, const char *buff,
+ size_t nbytes, loff_t *ppos)
+{
+ int incoming, error, retval;
+ char *page, c;
+ const char *tmp;
+
+ if (nbytes < 0) return -EINVAL;
+ if (nbytes == 0) return 0;
+ if (nbytes > PAGE_SIZE) nbytes = PAGE_SIZE-1;
+
+ error = verify_area(VERIFY_READ, buff, nbytes);
+ if (error) return error;
+
+ page = (char *)__get_free_page(GFP_KERNEL);
+ if (page == NULL) return -ENOMEM;
+
+ incoming = 0;
+ tmp = buff;
+ while(incoming < nbytes){
+ if (get_user(c, tmp++)) return -EFAULT;
+ incoming++;
+ if (c == '\0' || c == '\n')
+ break;
+ }
+
+ retval = copy_from_user(page, buff, incoming);
+ if (retval != 0) {
+ printk("mpoa: proc_mpc_write: copy_from_user() failed\n");
+ return -EFAULT;
+ }
+
+ *ppos += incoming;
+
+ page[incoming] = '\0';
+ retval = parse_qos(buff, incoming);
+ if (retval == 0)
+ printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
+
+ free_page((unsigned long)page);
+
+ return nbytes;
+}
+
+static int parse_qos(const char *buff, int len)
+{
+ /* possible lines look like this
+ * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
+ */
+
+ int pos, i;
+ uint32_t ipaddr;
+ unsigned char ip[4];
+ char cmd[4], temp[256];
+ const char *tmp, *prev;
+ struct atm_qos qos;
+ int value[5];
+
+ memset(&qos, 0, sizeof(struct atm_qos));
+ strncpy(cmd, buff, 3);
+ if( strncmp(cmd,"add", 3) && strncmp(cmd,"del", 3))
+ return 0; /* not add or del */
+
+ pos = 4;
+ /* next parse ip */
+ prev = buff + pos;
+ for (i = 0; i < 3; i++) {
+ tmp = strchr(prev, '.');
+ if (tmp == NULL) return 0;
+ memset(temp, '\0', 256);
+ memcpy(temp, prev, tmp-prev);
+ ip[i] = (char)simple_strtoul(temp, NULL, 0);
+ tmp ++;
+ prev = tmp;
+ }
+ tmp = strchr(prev, ' ');
+ if (tmp == NULL) return 0;
+ memset(temp, '\0', 256);
+ memcpy(temp, prev, tmp-prev);
+ ip[i] = (char)simple_strtoul(temp, NULL, 0);
+ ipaddr = *(uint32_t *)ip;
+
+ if(!strncmp(cmd, "del", 3))
+ return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr));
+
+ /* next transmit values */
+ tmp = strstr(buff, "tx=");
+ if(tmp == NULL) return 0;
+ tmp += 3;
+ prev = tmp;
+ for( i = 0; i < 1; i++){
+ tmp = strchr(prev, ',');
+ if (tmp == NULL) return 0;
+ memset(temp, '\0', 256);
+ memcpy(temp, prev, tmp-prev);
+ value[i] = (int)simple_strtoul(temp, NULL, 0);
+ tmp ++;
+ prev = tmp;
+ }
+ tmp = strchr(prev, ' ');
+ if (tmp == NULL) return 0;
+ memset(temp, '\0', 256);
+ memcpy(temp, prev, tmp-prev);
+ value[i] = (int)simple_strtoul(temp, NULL, 0);
+ qos.txtp.traffic_class = ATM_CBR;
+ qos.txtp.max_pcr = value[0];
+ qos.txtp.max_sdu = value[1];
+
+ /* next receive values */
+ tmp = strstr(buff, "rx=");
+ if(tmp == NULL) return 0;
+ if (strstr(buff, "rx=tx")) { /* rx == tx */
+ qos.rxtp.traffic_class = qos.txtp.traffic_class;
+ qos.rxtp.max_pcr = qos.txtp.max_pcr;
+ qos.rxtp.max_cdv = qos.txtp.max_cdv;
+ qos.rxtp.max_sdu = qos.txtp.max_sdu;
+ } else {
+ tmp += 3;
+ prev = tmp;
+ for( i = 0; i < 1; i++){
+ tmp = strchr(prev, ',');
+ if (tmp == NULL) return 0;
+ memset(temp, '\0', 256);
+ memcpy(temp, prev, tmp-prev);
+ value[i] = (int)simple_strtoul(temp, NULL, 0);
+ tmp ++;
+ prev = tmp;
+ }
+ tmp = strchr(prev, '\0');
+ if (tmp == NULL) return 0;
+ memset(temp, '\0', 256);
+ memcpy(temp, prev, tmp-prev);
+ value[i] = (int)simple_strtoul(temp, NULL, 0);
+ qos.rxtp.traffic_class = ATM_CBR;
+ qos.rxtp.max_pcr = value[0];
+ qos.rxtp.max_sdu = value[1];
+ }
+ qos.aal = ATM_AAL5;
+ dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n",
+ qos.txtp.max_pcr,
+ qos.txtp.max_sdu,
+ qos.rxtp.max_pcr,
+ qos.rxtp.max_sdu
+ );
+
+ atm_mpoa_add_qos(ipaddr, &qos);
+ return 1;
+}
+
+/*
+ * INITIALIZATION function - called when module is initialized/loaded.
+ */
+int mpc_proc_init(void)
+{
+ int retval = 0;
+
+ if ( (retval = proc_register(&atm_proc_root,&mpc_stats)) != 0 ) {
+ printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
+ return retval;
+ }
+ return 0;
+}
+
+/*
+ * DELETING function - called when module is removed.
+ */
+void mpc_proc_clean(void)
+{
+ proc_unregister(&atm_proc_root,mpc_stats.low_ino);
+}
+
+
+#endif /* CONFIG_PROC_FS */
+
+
+
+
+
+