X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fatm%2Fmpoa_proc.c;h=714fe71aeda912b27703aa8a081e9eb9b65b67d6;hb=40b5a8819a087d0a4ad418754432e71c49f98ae2;hp=4f1849f9ab29a9f2cee57af10b484edf577ea588;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 4f1849f9a..714fe71ae 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -31,24 +30,31 @@ extern struct mpoa_client *mpcs; extern struct proc_dir_entry *atm_proc_root; /* from proc.c. */ -static int proc_mpc_open(struct inode *inode, struct file *file); +static ssize_t proc_mpc_read(struct file *file, char __user *buff, + size_t count, loff_t *pos); + static ssize_t proc_mpc_write(struct file *file, const char __user *buff, size_t nbytes, loff_t *ppos); -static int parse_qos(const char *buff); +static int parse_qos(const char *buff, int len); /* * Define allowed FILE OPERATIONS */ static struct file_operations mpc_file_operations = { .owner = THIS_MODULE, - .open = proc_mpc_open, - .read = seq_read, - .llseek = seq_lseek, + .read = proc_mpc_read, .write = proc_mpc_write, - .release = seq_release, }; +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 */ @@ -90,174 +96,211 @@ static const char *egress_state_string(int state){ } } -/* - * FIXME: mpcs (and per-mpc lists) have no locking whatsoever. - */ - -static void *mpc_start(struct seq_file *m, loff_t *pos) -{ - loff_t l = *pos; - struct mpoa_client *mpc; - - if (!l--) - return SEQ_START_TOKEN; - for (mpc = mpcs; mpc; mpc = mpc->next) - if (!l--) - return mpc; - return NULL; -} - -static void *mpc_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct mpoa_client *p = v; - (*pos)++; - return v == SEQ_START_TOKEN ? mpcs : p->next; -} - -static void mpc_stop(struct seq_file *m, void *v) -{ -} - /* * READING function - called when the /proc/atm/mpoa file is read from. */ -static ssize_t mpc_show(struct seq_file *m, void *v) -{ - struct mpoa_client *mpc = v; +static ssize_t proc_mpc_read(struct file *file, char __user *buff, + size_t count, loff_t *pos){ + unsigned long page = 0; unsigned char *temp; - int i; + 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 (v == SEQ_START_TOKEN) { - atm_mpoa_disp_qos(m); - return 0; - } - - seq_printf(m, "\nInterface %d:\n\n", mpc->dev_num); - seq_printf(m, "Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n"); - do_gettimeofday(&now); - - for (in_entry = mpc->in_cache; in_entry; in_entry = in_entry->next) { - 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]); - seq_printf(m, "%-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) - seq_printf(m, " %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci); - seq_printf(m, "\n"); + if(count == 0) + return 0; + page = get_zeroed_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;ictrl_info.in_MPC_data_ATM_addr[i]);} + 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); + + /* 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; } - seq_printf(m, "\n"); - seq_printf(m, "Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n"); - for (eg_entry = mpc->eg_cache; eg_entry; eg_entry = eg_entry->next) { - unsigned char *p = eg_entry->ctrl_info.in_MPC_data_ATM_addr; - for(i = 0; i < ATM_ESA_LEN; i++) - seq_printf(m, "%02x", p[i]); - seq_printf(m, "\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); - - /* 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]); - seq_printf(m, "%-16s", ip_string); - - if (eg_entry->shortcut) - seq_printf(m, " %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci); - seq_printf(m, "\n"); + if (*pos >= length) length = 0; + else { + if ((count + *pos) > length) count = length - *pos; + if (copy_to_user(buff, (char *)page , count)) { + free_page(page); + return -EFAULT; + } + *pos += count; } - seq_printf(m, "\n"); - return 0; -} - -static struct seq_operations mpc_op = { - .start = mpc_start, - .next = mpc_next, - .stop = mpc_stop, - .show = mpc_show -}; -static int proc_mpc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &mpc_op); + free_page(page); + return length; } static ssize_t proc_mpc_write(struct file *file, const char __user *buff, size_t nbytes, loff_t *ppos) { - char *page, *p; - unsigned len; + int incoming, error, retval; + char *page, c; + const char __user *tmp; - if (nbytes == 0) - return 0; + if (nbytes == 0) return 0; + if (nbytes >= PAGE_SIZE) nbytes = PAGE_SIZE-1; - 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) - return -ENOMEM; - - for (p = page, len = 0; len < nbytes; p++, len++) { - if (get_user(*p, buff++)) { - free_page((unsigned long)page); - return -EFAULT; - } - if (*p == '\0' || *p == '\n') + 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; } - *p = '\0'; + retval = copy_from_user(page, buff, incoming); + if (retval != 0) { + printk("mpoa: proc_mpc_write: copy_from_user() failed\n"); + return -EFAULT; + } + + *ppos += incoming; - if (!parse_qos(page)) + page[incoming] = '\0'; + retval = parse_qos(page, incoming); + if (retval == 0) printk("mpoa: proc_mpc_write: could not parse '%s'\n", page); free_page((unsigned long)page); - return len; + return nbytes; } -static int parse_qos(const char *buff) +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 */ - unsigned char ip[4]; - int tx_pcr, tx_sdu, rx_pcr, rx_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)); - - if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu", - ip, ip+1, ip+2, ip+3) == 4) { - ipaddr = *(uint32_t *)ip; - return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); - } - - if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=tx", - ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu) == 6) { - rx_pcr = tx_pcr; - rx_sdu = tx_sdu; - } else if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=%d,%d", - ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8) - return 0; - + strlcpy(cmd, buff, sizeof(cmd)); + 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 = tx_pcr; - qos.txtp.max_sdu = tx_sdu; - qos.rxtp.traffic_class = ATM_CBR; - qos.rxtp.max_pcr = rx_pcr; - qos.rxtp.max_sdu = rx_sdu; + 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,