OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [atm/] [proc.c] - Diff between revs 1275 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1275 Rev 1765
/* net/atm/proc.c - ATM /proc interface */
/* net/atm/proc.c - ATM /proc interface */
 
 
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
/*
/*
 * The mechanism used here isn't designed for speed but rather for convenience
 * The mechanism used here isn't designed for speed but rather for convenience
 * of implementation. We only return one entry per read system call, so we can
 * of implementation. We only return one entry per read system call, so we can
 * be reasonably sure not to overrun the page and race conditions may lead to
 * be reasonably sure not to overrun the page and race conditions may lead to
 * the addition or omission of some lines but never to any corruption of a
 * the addition or omission of some lines but never to any corruption of a
 * line's internal structure.
 * line's internal structure.
 *
 *
 * Making the whole thing slightly more efficient is left as an exercise to the
 * Making the whole thing slightly more efficient is left as an exercise to the
 * reader. (Suggestions: wrapper which loops to get several entries per system
 * reader. (Suggestions: wrapper which loops to get several entries per system
 * call; or make --left slightly more clever to avoid O(n^2) characteristics.)
 * call; or make --left slightly more clever to avoid O(n^2) characteristics.)
 * I find it fast enough on my unloaded 266 MHz Pentium 2 :-)
 * I find it fast enough on my unloaded 266 MHz Pentium 2 :-)
 */
 */
 
 
 
 
#include <linux/config.h>
#include <linux/config.h>
#include <linux/module.h> /* for EXPORT_SYMBOL */
#include <linux/module.h> /* for EXPORT_SYMBOL */
#include <linux/string.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/atm.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmdev.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/atmclip.h>
#include <linux/atmclip.h>
#include <linux/atmarp.h>
#include <linux/atmarp.h>
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <linux/init.h> /* for __init */
#include <linux/init.h> /* for __init */
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/atomic.h>
#include <asm/param.h> /* for HZ */
#include <asm/param.h> /* for HZ */
#include "resources.h"
#include "resources.h"
#include "common.h" /* atm_proc_init prototype */
#include "common.h" /* atm_proc_init prototype */
#include "signaling.h" /* to get sigd - ugly too */
#include "signaling.h" /* to get sigd - ugly too */
 
 
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#include <net/atmclip.h>
#include <net/atmclip.h>
#include "ipcommon.h"
#include "ipcommon.h"
#endif
#endif
 
 
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#include "lec.h"
#include "lec.h"
#include "lec_arpc.h"
#include "lec_arpc.h"
#endif
#endif
 
 
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
    loff_t *pos);
    loff_t *pos);
static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
    loff_t *pos);
    loff_t *pos);
 
 
static struct file_operations proc_dev_atm_operations = {
static struct file_operations proc_dev_atm_operations = {
        read:           proc_dev_atm_read,
        read:           proc_dev_atm_read,
};
};
 
 
static struct file_operations proc_spec_atm_operations = {
static struct file_operations proc_spec_atm_operations = {
        read:           proc_spec_atm_read,
        read:           proc_spec_atm_read,
};
};
 
 
static void add_stats(char *buf,const char *aal,
static void add_stats(char *buf,const char *aal,
  const struct k_atm_aal_stats *stats)
  const struct k_atm_aal_stats *stats)
{
{
        sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal,
        sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal,
            atomic_read(&stats->tx),atomic_read(&stats->tx_err),
            atomic_read(&stats->tx),atomic_read(&stats->tx_err),
            atomic_read(&stats->rx),atomic_read(&stats->rx_err),
            atomic_read(&stats->rx),atomic_read(&stats->rx_err),
            atomic_read(&stats->rx_drop));
            atomic_read(&stats->rx_drop));
}
}
 
 
 
 
static void dev_info(const struct atm_dev *dev,char *buf)
static void dev_info(const struct atm_dev *dev,char *buf)
{
{
        int off,i;
        int off,i;
 
 
        off = sprintf(buf,"%3d %-8s",dev->number,dev->type);
        off = sprintf(buf,"%3d %-8s",dev->number,dev->type);
        for (i = 0; i < ESI_LEN; i++)
        for (i = 0; i < ESI_LEN; i++)
                off += sprintf(buf+off,"%02x",dev->esi[i]);
                off += sprintf(buf+off,"%02x",dev->esi[i]);
        strcat(buf,"  ");
        strcat(buf,"  ");
        add_stats(buf,"0",&dev->stats.aal0);
        add_stats(buf,"0",&dev->stats.aal0);
        strcat(buf,"  ");
        strcat(buf,"  ");
        add_stats(buf,"5",&dev->stats.aal5);
        add_stats(buf,"5",&dev->stats.aal5);
        sprintf(strchr(buf,0), "\t[%d]", atomic_read(&dev->refcnt));
        sprintf(strchr(buf,0), "\t[%d]", atomic_read(&dev->refcnt));
        strcat(buf,"\n");
        strcat(buf,"\n");
}
}
 
 
 
 
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
 
 
 
 
static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
static int svc_addr(char *buf,struct sockaddr_atmsvc *addr)
{
{
        static int code[] = { 1,2,10,6,1,0 };
        static int code[] = { 1,2,10,6,1,0 };
        static int e164[] = { 1,8,4,6,1,0 };
        static int e164[] = { 1,8,4,6,1,0 };
        int *fields;
        int *fields;
        int len,i,j,pos;
        int len,i,j,pos;
 
 
        len = 0;
        len = 0;
        if (*addr->sas_addr.pub) {
        if (*addr->sas_addr.pub) {
                strcpy(buf,addr->sas_addr.pub);
                strcpy(buf,addr->sas_addr.pub);
                len = strlen(addr->sas_addr.pub);
                len = strlen(addr->sas_addr.pub);
                buf += len;
                buf += len;
                if (*addr->sas_addr.prv) {
                if (*addr->sas_addr.prv) {
                        *buf++ = '+';
                        *buf++ = '+';
                        len++;
                        len++;
                }
                }
        }
        }
        else if (!*addr->sas_addr.prv) {
        else if (!*addr->sas_addr.prv) {
                        strcpy(buf,"(none)");
                        strcpy(buf,"(none)");
                        return strlen(buf);
                        return strlen(buf);
                }
                }
        if (*addr->sas_addr.prv) {
        if (*addr->sas_addr.prv) {
                len += 44;
                len += 44;
                pos = 0;
                pos = 0;
                fields = *addr->sas_addr.prv == ATM_AFI_E164 ? e164 : code;
                fields = *addr->sas_addr.prv == ATM_AFI_E164 ? e164 : code;
                for (i = 0; fields[i]; i++) {
                for (i = 0; fields[i]; i++) {
                        for (j = fields[i]; j; j--) {
                        for (j = fields[i]; j; j--) {
                                sprintf(buf,"%02X",addr->sas_addr.prv[pos++]);
                                sprintf(buf,"%02X",addr->sas_addr.prv[pos++]);
                                buf += 2;
                                buf += 2;
                        }
                        }
                        if (fields[i+1]) *buf++ = '.';
                        if (fields[i+1]) *buf++ = '.';
                }
                }
        }
        }
        return len;
        return len;
}
}
 
 
 
 
static void atmarp_info(struct net_device *dev,struct atmarp_entry *entry,
static void atmarp_info(struct net_device *dev,struct atmarp_entry *entry,
    struct clip_vcc *clip_vcc,char *buf)
    struct clip_vcc *clip_vcc,char *buf)
{
{
        unsigned char *ip;
        unsigned char *ip;
        int svc,off,ip_len;
        int svc,off,ip_len;
 
 
        svc = !clip_vcc || clip_vcc->vcc->sk->family == AF_ATMSVC;
        svc = !clip_vcc || clip_vcc->vcc->sk->family == AF_ATMSVC;
        off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC",
        off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC",
            !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
            !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
            (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/
            (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/
            HZ);
            HZ);
        ip = (unsigned char *) &entry->ip;
        ip = (unsigned char *) &entry->ip;
        ip_len = sprintf(buf+off,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
        ip_len = sprintf(buf+off,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
        off += ip_len;
        off += ip_len;
        while (ip_len++ < 16) buf[off++] = ' ';
        while (ip_len++ < 16) buf[off++] = ' ';
        if (!clip_vcc)
        if (!clip_vcc)
                if (time_before(jiffies, entry->expires))
                if (time_before(jiffies, entry->expires))
                        strcpy(buf+off,"(resolving)\n");
                        strcpy(buf+off,"(resolving)\n");
                else sprintf(buf+off,"(expired, ref %d)\n",
                else sprintf(buf+off,"(expired, ref %d)\n",
                            atomic_read(&entry->neigh->refcnt));
                            atomic_read(&entry->neigh->refcnt));
        else if (!svc)
        else if (!svc)
                        sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number,
                        sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number,
                            clip_vcc->vcc->vpi,clip_vcc->vcc->vci);
                            clip_vcc->vcc->vpi,clip_vcc->vcc->vci);
                else {
                else {
                        off += svc_addr(buf+off,&clip_vcc->vcc->remote);
                        off += svc_addr(buf+off,&clip_vcc->vcc->remote);
                        strcpy(buf+off,"\n");
                        strcpy(buf+off,"\n");
                }
                }
}
}
 
 
 
 
#endif
#endif
 
 
 
 
static void pvc_info(struct atm_vcc *vcc, char *buf, int clip_info)
static void pvc_info(struct atm_vcc *vcc, char *buf, int clip_info)
{
{
        static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
        static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
        static const char *aal_name[] = {
        static const char *aal_name[] = {
                "---",  "1",    "2",    "3/4",  /*  0- 3 */
                "---",  "1",    "2",    "3/4",  /*  0- 3 */
                "???",  "5",    "???",  "???",  /*  4- 7 */
                "???",  "5",    "???",  "???",  /*  4- 7 */
                "???",  "???",  "???",  "???",  /*  8-11 */
                "???",  "???",  "???",  "???",  /*  8-11 */
                "???",  "0",     "???",  "???"}; /* 12-15 */
                "???",  "0",     "???",  "???"}; /* 12-15 */
        int off;
        int off;
 
 
        off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s",
        off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s",
            vcc->dev->number,vcc->vpi,vcc->vci,
            vcc->dev->number,vcc->vpi,vcc->vci,
            vcc->qos.aal >= sizeof(aal_name)/sizeof(aal_name[0]) ? "err" :
            vcc->qos.aal >= sizeof(aal_name)/sizeof(aal_name[0]) ? "err" :
            aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr,
            aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr,
            class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
            class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr,
            class_name[vcc->qos.txtp.traffic_class]);
            class_name[vcc->qos.txtp.traffic_class]);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
        if (clip_info && (vcc->push == atm_clip_ops->clip_push)) {
        if (clip_info && (vcc->push == atm_clip_ops->clip_push)) {
                struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
                struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
                struct net_device *dev;
                struct net_device *dev;
 
 
                dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
                dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL;
                off += sprintf(buf+off,"CLIP, Itf:%s, Encap:",
                off += sprintf(buf+off,"CLIP, Itf:%s, Encap:",
                    dev ? dev->name : "none?");
                    dev ? dev->name : "none?");
                if (clip_vcc->encap)
                if (clip_vcc->encap)
                        off += sprintf(buf+off,"LLC/SNAP");
                        off += sprintf(buf+off,"LLC/SNAP");
                else
                else
                        off += sprintf(buf+off,"None");
                        off += sprintf(buf+off,"None");
        }
        }
#endif
#endif
        strcpy(buf+off,"\n");
        strcpy(buf+off,"\n");
}
}
 
 
 
 
static const char *vcc_state(struct atm_vcc *vcc)
static const char *vcc_state(struct atm_vcc *vcc)
{
{
        static const char *map[] = { ATM_VS2TXT_MAP };
        static const char *map[] = { ATM_VS2TXT_MAP };
 
 
        return map[ATM_VF2VS(vcc->flags)];
        return map[ATM_VF2VS(vcc->flags)];
}
}
 
 
 
 
static void vc_info(struct atm_vcc *vcc,char *buf)
static void vc_info(struct atm_vcc *vcc,char *buf)
{
{
        char *here;
        char *here;
 
 
        here = buf+sprintf(buf,"%p ",vcc);
        here = buf+sprintf(buf,"%p ",vcc);
        if (!vcc->dev) here += sprintf(here,"Unassigned    ");
        if (!vcc->dev) here += sprintf(here,"Unassigned    ");
        else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
        else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
                    vcc->vci);
                    vcc->vci);
        switch (vcc->sk->family) {
        switch (vcc->sk->family) {
                case AF_ATMPVC:
                case AF_ATMPVC:
                        here += sprintf(here,"PVC");
                        here += sprintf(here,"PVC");
                        break;
                        break;
                case AF_ATMSVC:
                case AF_ATMSVC:
                        here += sprintf(here,"SVC");
                        here += sprintf(here,"SVC");
                        break;
                        break;
                default:
                default:
                        here += sprintf(here,"%3d",vcc->sk->family);
                        here += sprintf(here,"%3d",vcc->sk->family);
        }
        }
        here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
        here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
            vcc->reply,
            vcc->reply,
            atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
            atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
            atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
            atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
}
}
 
 
 
 
static void svc_info(struct atm_vcc *vcc,char *buf)
static void svc_info(struct atm_vcc *vcc,char *buf)
{
{
        char *here;
        char *here;
        int i;
        int i;
 
 
        if (!vcc->dev)
        if (!vcc->dev)
                sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%10s" : "N/A@%p%2s",
                sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%10s" : "N/A@%p%2s",
                    vcc,"");
                    vcc,"");
        else sprintf(buf,"%3d %3d %5d         ",vcc->dev->number,vcc->vpi,
        else sprintf(buf,"%3d %3d %5d         ",vcc->dev->number,vcc->vpi,
                    vcc->vci);
                    vcc->vci);
        here = strchr(buf,0);
        here = strchr(buf,0);
        here += sprintf(here,"%-10s ",vcc_state(vcc));
        here += sprintf(here,"%-10s ",vcc_state(vcc));
        here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub,
        here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub,
            *vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : "");
            *vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : "");
        if (*vcc->remote.sas_addr.prv)
        if (*vcc->remote.sas_addr.prv)
                for (i = 0; i < ATM_ESA_LEN; i++)
                for (i = 0; i < ATM_ESA_LEN; i++)
                        here += sprintf(here,"%02x",
                        here += sprintf(here,"%02x",
                            vcc->remote.sas_addr.prv[i]);
                            vcc->remote.sas_addr.prv[i]);
        strcat(here,"\n");
        strcat(here,"\n");
}
}
 
 
 
 
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 
 
static char*
static char*
lec_arp_get_status_string(unsigned char status)
lec_arp_get_status_string(unsigned char status)
{
{
  switch(status) {
  switch(status) {
  case ESI_UNKNOWN:
  case ESI_UNKNOWN:
    return "ESI_UNKNOWN       ";
    return "ESI_UNKNOWN       ";
  case ESI_ARP_PENDING:
  case ESI_ARP_PENDING:
    return "ESI_ARP_PENDING   ";
    return "ESI_ARP_PENDING   ";
  case ESI_VC_PENDING:
  case ESI_VC_PENDING:
    return "ESI_VC_PENDING    ";
    return "ESI_VC_PENDING    ";
  case ESI_FLUSH_PENDING:
  case ESI_FLUSH_PENDING:
    return "ESI_FLUSH_PENDING ";
    return "ESI_FLUSH_PENDING ";
  case ESI_FORWARD_DIRECT:
  case ESI_FORWARD_DIRECT:
    return "ESI_FORWARD_DIRECT";
    return "ESI_FORWARD_DIRECT";
  default:
  default:
    return "<Unknown>         ";
    return "<Unknown>         ";
  }
  }
}
}
 
 
static void
static void
lec_info(struct lec_arp_table *entry, char *buf)
lec_info(struct lec_arp_table *entry, char *buf)
{
{
        int j, offset=0;
        int j, offset=0;
 
 
        for(j=0;j<ETH_ALEN;j++) {
        for(j=0;j<ETH_ALEN;j++) {
                offset+=sprintf(buf+offset,"%2.2x",0xff&entry->mac_addr[j]);
                offset+=sprintf(buf+offset,"%2.2x",0xff&entry->mac_addr[j]);
        }
        }
        offset+=sprintf(buf+offset, " ");
        offset+=sprintf(buf+offset, " ");
        for(j=0;j<ATM_ESA_LEN;j++) {
        for(j=0;j<ATM_ESA_LEN;j++) {
                offset+=sprintf(buf+offset,"%2.2x",0xff&entry->atm_addr[j]);
                offset+=sprintf(buf+offset,"%2.2x",0xff&entry->atm_addr[j]);
        }
        }
        offset+=sprintf(buf+offset, " %s %4.4x",
        offset+=sprintf(buf+offset, " %s %4.4x",
                        lec_arp_get_status_string(entry->status),
                        lec_arp_get_status_string(entry->status),
                        entry->flags&0xffff);
                        entry->flags&0xffff);
        if (entry->vcc) {
        if (entry->vcc) {
                offset+=sprintf(buf+offset, "%3d %3d ", entry->vcc->vpi,
                offset+=sprintf(buf+offset, "%3d %3d ", entry->vcc->vpi,
                                entry->vcc->vci);
                                entry->vcc->vci);
        } else
        } else
                offset+=sprintf(buf+offset, "        ");
                offset+=sprintf(buf+offset, "        ");
        if (entry->recv_vcc) {
        if (entry->recv_vcc) {
                offset+=sprintf(buf+offset, "     %3d %3d",
                offset+=sprintf(buf+offset, "     %3d %3d",
                                entry->recv_vcc->vpi, entry->recv_vcc->vci);
                                entry->recv_vcc->vpi, entry->recv_vcc->vci);
        }
        }
 
 
        sprintf(buf+offset,"\n");
        sprintf(buf+offset,"\n");
}
}
 
 
#endif
#endif
 
 
static int atm_devices_info(loff_t pos,char *buf)
static int atm_devices_info(loff_t pos,char *buf)
{
{
        struct atm_dev *dev;
        struct atm_dev *dev;
        struct list_head *p;
        struct list_head *p;
        int left;
        int left;
 
 
        if (!pos) {
        if (!pos) {
                return sprintf(buf,"Itf Type    ESI/\"MAC\"addr "
                return sprintf(buf,"Itf Type    ESI/\"MAC\"addr "
                    "AAL(TX,err,RX,err,drop) ...               [refcnt]\n");
                    "AAL(TX,err,RX,err,drop) ...               [refcnt]\n");
        }
        }
        left = pos-1;
        left = pos-1;
        spin_lock(&atm_dev_lock);
        spin_lock(&atm_dev_lock);
        list_for_each(p, &atm_devs) {
        list_for_each(p, &atm_devs) {
                dev = list_entry(p, struct atm_dev, dev_list);
                dev = list_entry(p, struct atm_dev, dev_list);
                if (left-- == 0) {
                if (left-- == 0) {
                        dev_info(dev,buf);
                        dev_info(dev,buf);
                        spin_unlock(&atm_dev_lock);
                        spin_unlock(&atm_dev_lock);
                        return strlen(buf);
                        return strlen(buf);
                }
                }
        }
        }
        spin_unlock(&atm_dev_lock);
        spin_unlock(&atm_dev_lock);
        return 0;
        return 0;
}
}
 
 
/*
/*
 * FIXME: it isn't safe to walk the VCC list without turning off interrupts.
 * FIXME: it isn't safe to walk the VCC list without turning off interrupts.
 * What is really needed is some lock on the devices. Ditto for ATMARP.
 * What is really needed is some lock on the devices. Ditto for ATMARP.
 */
 */
 
 
static int atm_pvc_info(loff_t pos,char *buf)
static int atm_pvc_info(loff_t pos,char *buf)
{
{
        struct sock *s;
        struct sock *s;
        struct atm_vcc *vcc;
        struct atm_vcc *vcc;
        int left, clip_info = 0;
        int left, clip_info = 0;
 
 
        if (!pos) {
        if (!pos) {
                return sprintf(buf,"Itf VPI VCI   AAL RX(PCR,Class) "
                return sprintf(buf,"Itf VPI VCI   AAL RX(PCR,Class) "
                    "TX(PCR,Class)\n");
                    "TX(PCR,Class)\n");
        }
        }
        left = pos-1;
        left = pos-1;
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
        if (try_atm_clip_ops())
        if (try_atm_clip_ops())
                clip_info = 1;
                clip_info = 1;
#endif
#endif
        read_lock(&vcc_sklist_lock);
        read_lock(&vcc_sklist_lock);
        for(s = vcc_sklist; s; s = s->next) {
        for(s = vcc_sklist; s; s = s->next) {
                vcc = s->protinfo.af_atm;
                vcc = s->protinfo.af_atm;
                if (vcc->sk->family == PF_ATMPVC && vcc->dev && !left--) {
                if (vcc->sk->family == PF_ATMPVC && vcc->dev && !left--) {
                        pvc_info(vcc,buf,clip_info);
                        pvc_info(vcc,buf,clip_info);
                        read_unlock(&vcc_sklist_lock);
                        read_unlock(&vcc_sklist_lock);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
                        if (clip_info && atm_clip_ops->owner)
                        if (clip_info && atm_clip_ops->owner)
                                __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                                __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
#endif
#endif
                        return strlen(buf);
                        return strlen(buf);
                }
                }
        }
        }
        read_unlock(&vcc_sklist_lock);
        read_unlock(&vcc_sklist_lock);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
        if (clip_info && atm_clip_ops->owner)
        if (clip_info && atm_clip_ops->owner)
                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
#endif
#endif
        return 0;
        return 0;
}
}
 
 
 
 
static int atm_vc_info(loff_t pos,char *buf)
static int atm_vc_info(loff_t pos,char *buf)
{
{
        struct atm_vcc *vcc;
        struct atm_vcc *vcc;
        struct sock *s;
        struct sock *s;
        int left;
        int left;
 
 
        if (!pos)
        if (!pos)
                return sprintf(buf,sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
                return sprintf(buf,sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
                    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
                    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
                    "     Recv buffer\n");
                    "     Recv buffer\n");
        left = pos-1;
        left = pos-1;
        read_lock(&vcc_sklist_lock);
        read_lock(&vcc_sklist_lock);
        for(s = vcc_sklist; s; s = s->next) {
        for(s = vcc_sklist; s; s = s->next) {
                vcc = s->protinfo.af_atm;
                vcc = s->protinfo.af_atm;
                if (!left--) {
                if (!left--) {
                        vc_info(vcc,buf);
                        vc_info(vcc,buf);
                        read_unlock(&vcc_sklist_lock);
                        read_unlock(&vcc_sklist_lock);
                        return strlen(buf);
                        return strlen(buf);
                }
                }
        }
        }
        read_unlock(&vcc_sklist_lock);
        read_unlock(&vcc_sklist_lock);
 
 
        return 0;
        return 0;
}
}
 
 
 
 
static int atm_svc_info(loff_t pos,char *buf)
static int atm_svc_info(loff_t pos,char *buf)
{
{
        struct sock *s;
        struct sock *s;
        struct atm_vcc *vcc;
        struct atm_vcc *vcc;
        int left;
        int left;
 
 
        if (!pos)
        if (!pos)
                return sprintf(buf,"Itf VPI VCI           State      Remote\n");
                return sprintf(buf,"Itf VPI VCI           State      Remote\n");
        left = pos-1;
        left = pos-1;
        read_lock(&vcc_sklist_lock);
        read_lock(&vcc_sklist_lock);
        for(s = vcc_sklist; s; s = s->next) {
        for(s = vcc_sklist; s; s = s->next) {
                vcc = s->protinfo.af_atm;
                vcc = s->protinfo.af_atm;
                if (vcc->sk->family == PF_ATMSVC && !left--) {
                if (vcc->sk->family == PF_ATMSVC && !left--) {
                        svc_info(vcc,buf);
                        svc_info(vcc,buf);
                        read_unlock(&vcc_sklist_lock);
                        read_unlock(&vcc_sklist_lock);
                        return strlen(buf);
                        return strlen(buf);
                }
                }
        }
        }
        read_unlock(&vcc_sklist_lock);
        read_unlock(&vcc_sklist_lock);
 
 
        return 0;
        return 0;
}
}
 
 
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
static int atm_arp_info(loff_t pos,char *buf)
static int atm_arp_info(loff_t pos,char *buf)
{
{
        struct neighbour *n;
        struct neighbour *n;
        int i,count;
        int i,count;
 
 
        if (!pos) {
        if (!pos) {
                return sprintf(buf,"IPitf TypeEncp Idle IP address      "
                return sprintf(buf,"IPitf TypeEncp Idle IP address      "
                    "ATM address\n");
                    "ATM address\n");
        }
        }
        if (!try_atm_clip_ops())
        if (!try_atm_clip_ops())
                return 0;
                return 0;
        count = pos;
        count = pos;
        read_lock_bh(&clip_tbl_hook->lock);
        read_lock_bh(&clip_tbl_hook->lock);
        for (i = 0; i <= NEIGH_HASHMASK; i++)
        for (i = 0; i <= NEIGH_HASHMASK; i++)
                for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) {
                for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) {
                        struct atmarp_entry *entry = NEIGH2ENTRY(n);
                        struct atmarp_entry *entry = NEIGH2ENTRY(n);
                        struct clip_vcc *vcc;
                        struct clip_vcc *vcc;
 
 
                        if (!entry->vccs) {
                        if (!entry->vccs) {
                                if (--count) continue;
                                if (--count) continue;
                                atmarp_info(n->dev,entry,NULL,buf);
                                atmarp_info(n->dev,entry,NULL,buf);
                                read_unlock_bh(&clip_tbl_hook->lock);
                                read_unlock_bh(&clip_tbl_hook->lock);
                                if (atm_clip_ops->owner)
                                if (atm_clip_ops->owner)
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                                return strlen(buf);
                                return strlen(buf);
                        }
                        }
                        for (vcc = entry->vccs; vcc;
                        for (vcc = entry->vccs; vcc;
                            vcc = vcc->next) {
                            vcc = vcc->next) {
                                if (--count) continue;
                                if (--count) continue;
                                atmarp_info(n->dev,entry,vcc,buf);
                                atmarp_info(n->dev,entry,vcc,buf);
                                read_unlock_bh(&clip_tbl_hook->lock);
                                read_unlock_bh(&clip_tbl_hook->lock);
                                if (atm_clip_ops->owner)
                                if (atm_clip_ops->owner)
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                                return strlen(buf);
                                return strlen(buf);
                        }
                        }
                }
                }
        read_unlock_bh(&clip_tbl_hook->lock);
        read_unlock_bh(&clip_tbl_hook->lock);
        if (atm_clip_ops->owner)
        if (atm_clip_ops->owner)
                __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
                __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
        return 0;
        return 0;
}
}
#endif
#endif
 
 
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
static int atm_lec_info(loff_t pos,char *buf)
static int atm_lec_info(loff_t pos,char *buf)
{
{
        unsigned long flags;
        unsigned long flags;
        struct lec_priv *priv;
        struct lec_priv *priv;
        struct lec_arp_table *entry;
        struct lec_arp_table *entry;
        int i, count, d, e;
        int i, count, d, e;
        struct net_device *dev;
        struct net_device *dev;
 
 
        if (!pos) {
        if (!pos) {
                return sprintf(buf,"Itf  MAC          ATM destination"
                return sprintf(buf,"Itf  MAC          ATM destination"
                    "                          Status            Flags "
                    "                          Status            Flags "
                    "VPI/VCI Recv VPI/VCI\n");
                    "VPI/VCI Recv VPI/VCI\n");
        }
        }
        if (!try_atm_lane_ops())
        if (!try_atm_lane_ops())
                return 0; /* the lane module is not there yet */
                return 0; /* the lane module is not there yet */
 
 
        count = pos;
        count = pos;
        for(d = 0; d < MAX_LEC_ITF; d++) {
        for(d = 0; d < MAX_LEC_ITF; d++) {
                dev = atm_lane_ops->get_lec(d);
                dev = atm_lane_ops->get_lec(d);
                if (!dev || !(priv = (struct lec_priv *) dev->priv))
                if (!dev || !(priv = (struct lec_priv *) dev->priv))
                        continue;
                        continue;
                spin_lock_irqsave(&priv->lec_arp_lock, flags);
                spin_lock_irqsave(&priv->lec_arp_lock, flags);
                for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
                for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
                        for(entry = priv->lec_arp_tables[i]; entry; entry = entry->next) {
                        for(entry = priv->lec_arp_tables[i]; entry; entry = entry->next) {
                                if (--count)
                                if (--count)
                                        continue;
                                        continue;
                                e = sprintf(buf,"%s ", dev->name);
                                e = sprintf(buf,"%s ", dev->name);
                                lec_info(entry, buf+e);
                                lec_info(entry, buf+e);
                                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                                dev_put(dev);
                                dev_put(dev);
                                if (atm_lane_ops->owner)
                                if (atm_lane_ops->owner)
                                        __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                                        __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                                return strlen(buf);
                                return strlen(buf);
                        }
                        }
                }
                }
                for(entry = priv->lec_arp_empty_ones; entry; entry = entry->next) {
                for(entry = priv->lec_arp_empty_ones; entry; entry = entry->next) {
                        if (--count)
                        if (--count)
                                continue;
                                continue;
                        e = sprintf(buf,"%s ", dev->name);
                        e = sprintf(buf,"%s ", dev->name);
                        lec_info(entry, buf+e);
                        lec_info(entry, buf+e);
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                        dev_put(dev);
                        dev_put(dev);
                        if (atm_lane_ops->owner)
                        if (atm_lane_ops->owner)
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                        return strlen(buf);
                        return strlen(buf);
                }
                }
                for(entry = priv->lec_no_forward; entry; entry=entry->next) {
                for(entry = priv->lec_no_forward; entry; entry=entry->next) {
                        if (--count)
                        if (--count)
                                continue;
                                continue;
                        e = sprintf(buf,"%s ", dev->name);
                        e = sprintf(buf,"%s ", dev->name);
                        lec_info(entry, buf+e);
                        lec_info(entry, buf+e);
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                        dev_put(dev);
                        dev_put(dev);
                        if (atm_lane_ops->owner)
                        if (atm_lane_ops->owner)
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                        return strlen(buf);
                        return strlen(buf);
                }
                }
                for(entry = priv->mcast_fwds; entry; entry = entry->next) {
                for(entry = priv->mcast_fwds; entry; entry = entry->next) {
                        if (--count)
                        if (--count)
                                continue;
                                continue;
                        e = sprintf(buf,"%s ", dev->name);
                        e = sprintf(buf,"%s ", dev->name);
                        lec_info(entry, buf+e);
                        lec_info(entry, buf+e);
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                        dev_put(dev);
                        dev_put(dev);
                        if (atm_lane_ops->owner)
                        if (atm_lane_ops->owner)
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                        return strlen(buf);
                        return strlen(buf);
                }
                }
                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                dev_put(dev);
                dev_put(dev);
        }
        }
        if (atm_lane_ops->owner)
        if (atm_lane_ops->owner)
                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
                __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
        return 0;
        return 0;
}
}
#endif
#endif
 
 
 
 
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
    loff_t *pos)
    loff_t *pos)
{
{
        struct atm_dev *dev;
        struct atm_dev *dev;
        unsigned long page;
        unsigned long page;
        int length;
        int length;
 
 
        if (count == 0) return 0;
        if (count == 0) return 0;
        page = get_free_page(GFP_KERNEL);
        page = get_free_page(GFP_KERNEL);
        if (!page) return -ENOMEM;
        if (!page) return -ENOMEM;
        dev = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
        dev = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
            ->data;
            ->data;
        if (!dev->ops->proc_read)
        if (!dev->ops->proc_read)
                length = -EINVAL;
                length = -EINVAL;
        else {
        else {
                length = dev->ops->proc_read(dev,pos,(char *) page);
                length = dev->ops->proc_read(dev,pos,(char *) page);
                if (length > count) length = -EINVAL;
                if (length > count) length = -EINVAL;
        }
        }
        if (length >= 0) {
        if (length >= 0) {
                if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
                if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
                (*pos)++;
                (*pos)++;
        }
        }
        free_page(page);
        free_page(page);
        return length;
        return length;
}
}
 
 
 
 
static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
    loff_t *pos)
    loff_t *pos)
{
{
        unsigned long page;
        unsigned long page;
        int length;
        int length;
        int (*info)(loff_t,char *);
        int (*info)(loff_t,char *);
        info = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
        info = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
            ->data;
            ->data;
 
 
        if (count == 0) return 0;
        if (count == 0) return 0;
        page = get_free_page(GFP_KERNEL);
        page = get_free_page(GFP_KERNEL);
        if (!page) return -ENOMEM;
        if (!page) return -ENOMEM;
        length = (*info)(*pos,(char *) page);
        length = (*info)(*pos,(char *) page);
        if (length > count) length = -EINVAL;
        if (length > count) length = -EINVAL;
        if (length >= 0) {
        if (length >= 0) {
                if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
                if (copy_to_user(buf,(char *) page,length)) length = -EFAULT;
                (*pos)++;
                (*pos)++;
        }
        }
        free_page(page);
        free_page(page);
        return length;
        return length;
}
}
 
 
 
 
struct proc_dir_entry *atm_proc_root;
struct proc_dir_entry *atm_proc_root;
EXPORT_SYMBOL(atm_proc_root);
EXPORT_SYMBOL(atm_proc_root);
 
 
 
 
int atm_proc_dev_register(struct atm_dev *dev)
int atm_proc_dev_register(struct atm_dev *dev)
{
{
        int digits,num;
        int digits,num;
        int error;
        int error;
 
 
        error = -ENOMEM;
        error = -ENOMEM;
        digits = 0;
        digits = 0;
        for (num = dev->number; num; num /= 10) digits++;
        for (num = dev->number; num; num /= 10) digits++;
        if (!digits) digits++;
        if (!digits) digits++;
 
 
        dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_ATOMIC);
        dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_ATOMIC);
        if (!dev->proc_name)
        if (!dev->proc_name)
                goto fail1;
                goto fail1;
        sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
        sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
 
 
        dev->proc_entry = create_proc_entry(dev->proc_name, 0, atm_proc_root);
        dev->proc_entry = create_proc_entry(dev->proc_name, 0, atm_proc_root);
        if (!dev->proc_entry)
        if (!dev->proc_entry)
                goto fail0;
                goto fail0;
        dev->proc_entry->data = dev;
        dev->proc_entry->data = dev;
        dev->proc_entry->proc_fops = &proc_dev_atm_operations;
        dev->proc_entry->proc_fops = &proc_dev_atm_operations;
        dev->proc_entry->owner = THIS_MODULE;
        dev->proc_entry->owner = THIS_MODULE;
        return 0;
        return 0;
fail0:
fail0:
        kfree(dev->proc_name);
        kfree(dev->proc_name);
fail1:
fail1:
        return error;
        return error;
}
}
 
 
 
 
void atm_proc_dev_deregister(struct atm_dev *dev)
void atm_proc_dev_deregister(struct atm_dev *dev)
{
{
        remove_proc_entry(dev->proc_name, atm_proc_root);
        remove_proc_entry(dev->proc_name, atm_proc_root);
        kfree(dev->proc_name);
        kfree(dev->proc_name);
}
}
 
 
 
 
#define CREATE_ENTRY(name) \
#define CREATE_ENTRY(name) \
    name = create_proc_entry(#name,0,atm_proc_root); \
    name = create_proc_entry(#name,0,atm_proc_root); \
    if (!name) goto cleanup; \
    if (!name) goto cleanup; \
    name->data = atm_##name##_info; \
    name->data = atm_##name##_info; \
    name->proc_fops = &proc_spec_atm_operations; \
    name->proc_fops = &proc_spec_atm_operations; \
    name->owner = THIS_MODULE
    name->owner = THIS_MODULE
 
 
static struct proc_dir_entry *devices = NULL, *pvc = NULL,
static struct proc_dir_entry *devices = NULL, *pvc = NULL,
                *svc = NULL, *arp = NULL, *lec = NULL, *vc = NULL;
                *svc = NULL, *arp = NULL, *lec = NULL, *vc = NULL;
 
 
static void atm_proc_cleanup(void)
static void atm_proc_cleanup(void)
{
{
        if (devices)
        if (devices)
                remove_proc_entry("devices",atm_proc_root);
                remove_proc_entry("devices",atm_proc_root);
        if (pvc)
        if (pvc)
                remove_proc_entry("pvc",atm_proc_root);
                remove_proc_entry("pvc",atm_proc_root);
        if (svc)
        if (svc)
                remove_proc_entry("svc",atm_proc_root);
                remove_proc_entry("svc",atm_proc_root);
        if (arp)
        if (arp)
                remove_proc_entry("arp",atm_proc_root);
                remove_proc_entry("arp",atm_proc_root);
        if (lec)
        if (lec)
                remove_proc_entry("lec",atm_proc_root);
                remove_proc_entry("lec",atm_proc_root);
        if (vc)
        if (vc)
                remove_proc_entry("vc",atm_proc_root);
                remove_proc_entry("vc",atm_proc_root);
        remove_proc_entry("net/atm",NULL);
        remove_proc_entry("net/atm",NULL);
}
}
 
 
int atm_proc_init(void)
int atm_proc_init(void)
{
{
        atm_proc_root = proc_mkdir("net/atm",NULL);
        atm_proc_root = proc_mkdir("net/atm",NULL);
        if (!atm_proc_root)
        if (!atm_proc_root)
                return -ENOMEM;
                return -ENOMEM;
        CREATE_ENTRY(devices);
        CREATE_ENTRY(devices);
        CREATE_ENTRY(pvc);
        CREATE_ENTRY(pvc);
        CREATE_ENTRY(svc);
        CREATE_ENTRY(svc);
        CREATE_ENTRY(vc);
        CREATE_ENTRY(vc);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
        CREATE_ENTRY(arp);
        CREATE_ENTRY(arp);
#endif
#endif
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
        CREATE_ENTRY(lec);
        CREATE_ENTRY(lec);
#endif
#endif
        return 0;
        return 0;
 
 
cleanup:
cleanup:
        atm_proc_cleanup();
        atm_proc_cleanup();
        return -ENOMEM;
        return -ENOMEM;
}
}
 
 
void atm_proc_exit(void)
void atm_proc_exit(void)
{
{
        atm_proc_cleanup();
        atm_proc_cleanup();
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.