vlanproc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:12k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  * vlanproc.c VLAN Module. /proc filesystem interface.
  3.  *
  4.  * This module is completely hardware-independent and provides
  5.  * access to the router using Linux /proc filesystem.
  6.  *
  7.  * Author: Ben Greear, <greearb@candelatech.com> coppied from wanproc.c
  8.  *               by: Gene Kozin <genek@compuserve.com>
  9.  *
  10.  * Copyright: (c) 1998 Ben Greear
  11.  *
  12.  * This program is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU General Public License
  14.  * as published by the Free Software Foundation; either version
  15.  * 2 of the License, or (at your option) any later version.
  16.  * ============================================================================
  17.  * Jan 20, 1998        Ben Greear     Initial Version
  18.  *****************************************************************************/
  19. #include <linux/config.h>
  20. #include <linux/stddef.h> /* offsetof(), etc. */
  21. #include <linux/errno.h> /* return codes */
  22. #include <linux/kernel.h>
  23. #include <linux/slab.h> /* kmalloc(), kfree() */
  24. #include <linux/mm.h> /* verify_area(), etc. */
  25. #include <linux/string.h> /* inline mem*, str* functions */
  26. #include <linux/init.h> /* __initfunc et al. */
  27. #include <asm/segment.h> /* kernel <-> user copy */
  28. #include <asm/byteorder.h> /* htons(), etc. */
  29. #include <asm/uaccess.h> /* copy_to_user */
  30. #include <asm/io.h>
  31. #include <linux/proc_fs.h>
  32. #include <linux/fs.h>
  33. #include <linux/netdevice.h>
  34. #include <linux/if_vlan.h>
  35. #include "vlanproc.h"
  36. #include "vlan.h"
  37. /****** Function Prototypes *************************************************/
  38. #ifdef CONFIG_PROC_FS
  39. /* Proc filesystem interface */
  40. static ssize_t vlan_proc_read(struct file *file, char *buf, size_t count,
  41.                               loff_t *ppos);
  42. /* Methods for preparing data for reading proc entries */
  43. static int vlan_config_get_info(char *buf, char **start, off_t offs, int len);
  44. static int vlandev_get_info(char *buf, char **start, off_t offs, int len);
  45. /* Miscellaneous */
  46. /*
  47.  * Global Data
  48.  */
  49. /*
  50.  * Names of the proc directory entries 
  51.  */
  52. static char name_root[]  = "vlan";
  53. static char name_conf[]  = "config";
  54. static char term_msg[]   = "***KERNEL:  Out of buffer space!***n";
  55. /*
  56.  * Structures for interfacing with the /proc filesystem.
  57.  * VLAN creates its own directory /proc/net/vlan with the folowing
  58.  * entries:
  59.  * config device status/configuration
  60.  * <device> entry for each  device
  61.  */
  62. /*
  63.  * Generic /proc/net/vlan/<file> file and inode operations 
  64.  */
  65. static struct file_operations vlan_fops = {
  66. read: vlan_proc_read,
  67. ioctl: NULL, /* vlan_proc_ioctl */
  68. };
  69. /*
  70.  * /proc/net/vlan/<device> file and inode operations
  71.  */
  72. static struct file_operations vlandev_fops = {
  73. read: vlan_proc_read,
  74. ioctl: NULL, /* vlan_proc_ioctl */
  75. };
  76. /*
  77.  * Proc filesystem derectory entries.
  78.  */
  79. /*
  80.  * /proc/net/vlan 
  81.  */
  82. static struct proc_dir_entry *proc_vlan_dir;
  83. /*
  84.  * /proc/net/vlan/config 
  85.  */
  86. static struct proc_dir_entry *proc_vlan_conf;
  87. /* Strings */
  88. static char conf_hdr[] = "VLAN Dev name  | VLAN IDn";
  89. /*
  90.  * Interface functions
  91.  */
  92. /*
  93.  * Clean up /proc/net/vlan entries
  94.  */
  95. void vlan_proc_cleanup(void)
  96. {
  97. if (proc_vlan_conf)
  98. remove_proc_entry(name_conf, proc_vlan_dir);
  99. if (proc_vlan_dir)
  100. proc_net_remove(name_root);
  101. /* Dynamically added entries should be cleaned up as their vlan_device
  102.  * is removed, so we should not have to take care of it here...
  103.  */
  104. }
  105. /*
  106.  * Create /proc/net/vlan entries
  107.  */
  108. int __init vlan_proc_init(void)
  109. {
  110. proc_vlan_dir = proc_mkdir(name_root, proc_net);
  111. if (proc_vlan_dir) {
  112. proc_vlan_conf = create_proc_entry(name_conf,
  113.    S_IFREG|S_IRUSR|S_IWUSR,
  114.    proc_vlan_dir);
  115. if (proc_vlan_conf) {
  116. proc_vlan_conf->proc_fops = &vlan_fops;
  117. proc_vlan_conf->get_info = vlan_config_get_info;
  118. return 0;
  119. }
  120. }
  121. vlan_proc_cleanup();
  122. return -ENOBUFS;
  123. }
  124. /*
  125.  * Add directory entry for VLAN device.
  126.  */
  127. int vlan_proc_add_dev (struct net_device *vlandev)
  128. {
  129. struct vlan_dev_info *dev_info = VLAN_DEV_INFO(vlandev);
  130. if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) {
  131. printk(KERN_ERR
  132.        "ERROR: vlan_proc_add, device -:%s:- is NOT a VLANn",
  133.        vlandev->name);
  134. return -EINVAL;
  135. }
  136. dev_info->dent = create_proc_entry(vlandev->name,
  137.    S_IFREG|S_IRUSR|S_IWUSR,
  138.    proc_vlan_dir);
  139. if (!dev_info->dent)
  140. return -ENOBUFS;
  141. dev_info->dent->proc_fops = &vlandev_fops;
  142. dev_info->dent->get_info = &vlandev_get_info;
  143. dev_info->dent->data = vlandev;
  144. #ifdef VLAN_DEBUG
  145. printk(KERN_ERR "vlan_proc_add, device -:%s:- being added.n",
  146.        vlandev->name);
  147. #endif
  148. return 0;
  149. }
  150. /*
  151.  * Delete directory entry for VLAN device.
  152.  */
  153. int vlan_proc_rem_dev(struct net_device *vlandev)
  154. {
  155. if (!vlandev) {
  156. printk(VLAN_ERR __FUNCTION__ ": invalid argument: %pn",
  157.        vlandev);
  158. return -EINVAL;
  159. }
  160. if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) {
  161. printk(VLAN_DBG __FUNCTION__ ": invalid argument, device: %s is not a VLAN device, priv_flags: 0x%4hX.n",
  162.        vlandev->name, vlandev->priv_flags);
  163. return -EINVAL;
  164. }
  165. #ifdef VLAN_DEBUG
  166. printk(VLAN_DBG __FUNCTION__ ": dev: %pn", vlandev);
  167. #endif
  168. /** NOTE:  This will consume the memory pointed to by dent, it seems. */
  169. remove_proc_entry(VLAN_DEV_INFO(vlandev)->dent->name, proc_vlan_dir);
  170. VLAN_DEV_INFO(vlandev)->dent = NULL;
  171. return 0;
  172. }
  173. /****** Proc filesystem entry points ****************************************/
  174. /*
  175.  * Read VLAN proc directory entry.
  176.  * This is universal routine for reading all entries in /proc/net/vlan
  177.  * directory.  Each directory entry contains a pointer to the 'method' for
  178.  * preparing data for that entry.
  179.  * o verify arguments
  180.  * o allocate kernel buffer
  181.  * o call get_info() to prepare data
  182.  * o copy data to user space
  183.  * o release kernel buffer
  184.  *
  185.  * Return: number of bytes copied to user space (0, if no data)
  186.  * <0 error
  187.  */
  188. static ssize_t vlan_proc_read(struct file *file, char *buf,
  189.       size_t count, loff_t *ppos)
  190. {
  191. struct inode *inode = file->f_dentry->d_inode;
  192. struct proc_dir_entry *dent;
  193. char *page;
  194. int pos, offs, len;
  195. if (count <= 0)
  196. return 0;
  197. dent = inode->u.generic_ip;
  198. if ((dent == NULL) || (dent->get_info == NULL))
  199. return 0;
  200. page = kmalloc(VLAN_PROC_BUFSZ, GFP_KERNEL);
  201. VLAN_MEM_DBG("page malloc, addr: %p  size: %in",
  202.      page, VLAN_PROC_BUFSZ);
  203. if (page == NULL)
  204. return -ENOBUFS;
  205. pos = dent->get_info(page, dent->data, 0, 0);
  206. offs = file->f_pos;
  207. if (offs < pos) {
  208. len = min_t(int, pos - offs, count);
  209. if (copy_to_user(buf, (page + offs), len))
  210. return -EFAULT;
  211. file->f_pos += len;
  212. } else {
  213. len = 0;
  214. }
  215. kfree(page);
  216. VLAN_FMEM_DBG("page free, addr: %pn", page);
  217. return len;
  218. }
  219. /*
  220.  * The following few functions build the content of /proc/net/vlan/config
  221.  */
  222. static int vlan_proc_get_vlan_info(char* buf, unsigned int cnt)
  223. {
  224. struct net_device *vlandev = NULL;
  225. struct vlan_group *grp = NULL;
  226. int i = 0;
  227. char *nm_type = NULL;
  228. struct vlan_dev_info *dev_info = NULL;
  229. #ifdef VLAN_DEBUG
  230. printk(VLAN_DBG __FUNCTION__ ": cnt == %in", cnt);
  231. #endif
  232. if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) {
  233. nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID";
  234. } else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) {
  235. nm_type = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD";
  236. } else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) {
  237. nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD";
  238. } else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) {
  239. nm_type = "VLAN_NAME_TYPE_PLUS_VID";
  240. } else {
  241. nm_type = "UNKNOWN";
  242. }
  243. cnt += sprintf(buf + cnt, "Name-Type: %s  bad_proto_recvd: %lun",
  244.        nm_type, vlan_bad_proto_recvd);
  245. for (grp = p802_1Q_vlan_list; grp != NULL; grp = grp->next) {
  246. /* loop through all devices for this device */
  247. #ifdef VLAN_DEBUG
  248. printk(VLAN_DBG __FUNCTION__ ": found a group, addr: %pn",grp);
  249. #endif
  250. for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
  251. vlandev = grp->vlan_devices[i];
  252. if (!vlandev)
  253. continue;
  254. #ifdef VLAN_DEBUG
  255. printk(VLAN_DBG __FUNCTION__
  256.        ": found a vlan_dev, addr: %pn", vlandev);
  257. #endif
  258. if ((cnt + 100) > VLAN_PROC_BUFSZ) {
  259. if ((cnt+strlen(term_msg)) < VLAN_PROC_BUFSZ)
  260. cnt += sprintf(buf+cnt, "%s", term_msg);
  261. return cnt;
  262. }
  263. if (!vlandev->priv) {
  264. printk(KERN_ERR __FUNCTION__
  265.        ": ERROR: vlandev->priv is NULLn");
  266. continue;
  267. }
  268. dev_info = VLAN_DEV_INFO(vlandev);
  269. #ifdef VLAN_DEBUG
  270. printk(VLAN_DBG __FUNCTION__
  271.        ": got a good vlandev, addr: %pn",
  272.        VLAN_DEV_INFO(vlandev));
  273. #endif
  274. cnt += sprintf(buf + cnt, "%-15s| %d  | %sn",
  275.        vlandev->name, dev_info->vlan_id,
  276.        dev_info->real_dev->name);
  277. }
  278. }
  279. return cnt;
  280. }
  281. /*
  282.  * Prepare data for reading 'Config' entry.
  283.  * Return length of data.
  284.  */
  285. static int vlan_config_get_info(char *buf, char **start,
  286. off_t offs, int len)
  287. {
  288. strcpy(buf, conf_hdr);
  289. return vlan_proc_get_vlan_info(buf, (unsigned int)(strlen(conf_hdr)));
  290. }
  291. /*
  292.  * Prepare data for reading <device> entry.
  293.  * Return length of data.
  294.  *
  295.  * On entry, the 'start' argument will contain a pointer to VLAN device
  296.  * data space.
  297.  */
  298. static int vlandev_get_info(char *buf, char **start,
  299.     off_t offs, int len)
  300. {
  301. struct net_device *vlandev = (void *) start;
  302. struct net_device_stats *stats = NULL;
  303. struct vlan_dev_info *dev_info = NULL;
  304. struct vlan_priority_tci_mapping *mp;
  305. int cnt = 0;
  306. int i;
  307. #ifdef VLAN_DEBUG
  308. printk(VLAN_DBG __FUNCTION__ ": vlandev: %pn", vlandev);
  309. #endif
  310. if ((vlandev == NULL) || (!vlandev->priv_flags & IFF_802_1Q_VLAN))
  311. return 0;
  312. dev_info = VLAN_DEV_INFO(vlandev);
  313. cnt += sprintf(buf + cnt, "%s  VID: %d  REORDER_HDR: %i  dev->priv_flags: %hxn",
  314.        vlandev->name, dev_info->vlan_id,
  315.        (int)(dev_info->flags & 1), vlandev->priv_flags);
  316. stats = vlan_dev_get_stats(vlandev);
  317. cnt += sprintf(buf + cnt, "%30s: %12lun",
  318.        "total frames received", stats->rx_packets);
  319. cnt += sprintf(buf + cnt, "%30s: %12lun",
  320.        "total bytes received", stats->rx_bytes);
  321. cnt += sprintf(buf + cnt, "%30s: %12lun",
  322.        "Broadcast/Multicast Rcvd", stats->multicast);
  323. cnt += sprintf(buf + cnt, "n%30s: %12lun",
  324.        "total frames transmitted", stats->tx_packets);
  325. cnt += sprintf(buf + cnt, "%30s: %12lun",
  326.        "total bytes transmitted", stats->tx_bytes);
  327. cnt += sprintf(buf + cnt, "%30s: %12lun",
  328.        "total headroom inc", dev_info->cnt_inc_headroom_on_tx);
  329. cnt += sprintf(buf + cnt, "%30s: %12lun",
  330.        "total encap on xmit", dev_info->cnt_encap_on_xmit);
  331. cnt += sprintf(buf + cnt, "Device: %s", dev_info->real_dev->name);
  332. /* now show all PRIORITY mappings relating to this VLAN */
  333. cnt += sprintf(buf + cnt, "nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lun",
  334.        dev_info->ingress_priority_map[0],
  335.        dev_info->ingress_priority_map[1],
  336.        dev_info->ingress_priority_map[2],
  337.        dev_info->ingress_priority_map[3],
  338.        dev_info->ingress_priority_map[4],
  339.        dev_info->ingress_priority_map[5],
  340.        dev_info->ingress_priority_map[6],
  341.        dev_info->ingress_priority_map[7]);
  342. if ((cnt + 100) > VLAN_PROC_BUFSZ) {
  343. if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
  344. /* should never get here */
  345. return cnt;
  346. } else {
  347. cnt += sprintf(buf + cnt, "%s", term_msg);
  348. return cnt;
  349. }
  350. }
  351. cnt += sprintf(buf + cnt, "EGRESSS priority Mappings: ");
  352. for (i = 0; i<16; i++) {
  353. mp = dev_info->egress_priority_map[i];
  354. while (mp) {
  355. cnt += sprintf(buf + cnt, "%lu:%hu ",
  356.        mp->priority, ((mp->vlan_qos >> 13) & 0x7));
  357. if ((cnt + 100) > VLAN_PROC_BUFSZ) {
  358. if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
  359. /* should never get here */
  360. return cnt;
  361. } else {
  362. cnt += sprintf(buf + cnt, "%s", term_msg);
  363. return cnt;
  364. }
  365. }
  366. mp = mp->next;
  367. }
  368. }
  369. cnt += sprintf(buf + cnt, "n");
  370. return cnt;
  371. }
  372. #else /* No CONFIG_PROC_FS */
  373. /*
  374.  * No /proc - output stubs
  375.  */
  376.  
  377. int __init vlan_proc_init (void)
  378. {
  379. return 0;
  380. }
  381. void vlan_proc_cleanup(void)
  382. {
  383. return;
  384. }
  385. int vlan_proc_add_dev(struct net_device *vlandev)
  386. {
  387. return 0;
  388. }
  389. int vlan_proc_rem_dev(struct net_device *vlandev)
  390. {
  391. return 0;
  392. }
  393. #endif /* No CONFIG_PROC_FS */