vlanproc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

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 "%s: invalid argument: %pn",
  157. __FUNCTION__, vlandev);
  158. return -EINVAL;
  159. }
  160. if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) {
  161. printk(VLAN_DBG "%s: invalid argument, device: %s is not a VLAN device, priv_flags: 0x%4hX.n",
  162. __FUNCTION__, 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 h, i;
  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: %sn", nm_type);
  244. spin_lock_bh(&vlan_group_lock);
  245. for (h = 0; h < VLAN_GRP_HASH_SIZE; h++) {
  246. for (grp = vlan_group_hash[h]; grp != NULL; grp = grp->next) {
  247. for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
  248. vlandev = grp->vlan_devices[i];
  249. if (!vlandev)
  250. continue;
  251. if ((cnt + 100) > VLAN_PROC_BUFSZ) {
  252. if ((cnt+strlen(term_msg)) < VLAN_PROC_BUFSZ)
  253. cnt += sprintf(buf+cnt, "%s", term_msg);
  254. goto out;
  255. }
  256. dev_info = VLAN_DEV_INFO(vlandev);
  257. cnt += sprintf(buf + cnt, "%-15s| %d  | %sn",
  258.        vlandev->name,
  259.        dev_info->vlan_id,
  260.        dev_info->real_dev->name);
  261. }
  262. }
  263. }
  264. out:
  265. spin_unlock_bh(&vlan_group_lock);
  266. return cnt;
  267. }
  268. /*
  269.  * Prepare data for reading 'Config' entry.
  270.  * Return length of data.
  271.  */
  272. static int vlan_config_get_info(char *buf, char **start,
  273. off_t offs, int len)
  274. {
  275. strcpy(buf, conf_hdr);
  276. return vlan_proc_get_vlan_info(buf, (unsigned int)(strlen(conf_hdr)));
  277. }
  278. /*
  279.  * Prepare data for reading <device> entry.
  280.  * Return length of data.
  281.  *
  282.  * On entry, the 'start' argument will contain a pointer to VLAN device
  283.  * data space.
  284.  */
  285. static int vlandev_get_info(char *buf, char **start,
  286.     off_t offs, int len)
  287. {
  288. struct net_device *vlandev = (void *) start;
  289. struct net_device_stats *stats = NULL;
  290. struct vlan_dev_info *dev_info = NULL;
  291. struct vlan_priority_tci_mapping *mp;
  292. int cnt = 0;
  293. int i;
  294. if ((vlandev == NULL) || (!(vlandev->priv_flags & IFF_802_1Q_VLAN)))
  295. return 0;
  296. dev_info = VLAN_DEV_INFO(vlandev);
  297. cnt += sprintf(buf + cnt, "%s  VID: %d  REORDER_HDR: %i  dev->priv_flags: %hxn",
  298.        vlandev->name, dev_info->vlan_id,
  299.        (int)(dev_info->flags & 1), vlandev->priv_flags);
  300. stats = vlan_dev_get_stats(vlandev);
  301. cnt += sprintf(buf + cnt, "%30s: %12lun",
  302.        "total frames received", stats->rx_packets);
  303. cnt += sprintf(buf + cnt, "%30s: %12lun",
  304.        "total bytes received", stats->rx_bytes);
  305. cnt += sprintf(buf + cnt, "%30s: %12lun",
  306.        "Broadcast/Multicast Rcvd", stats->multicast);
  307. cnt += sprintf(buf + cnt, "n%30s: %12lun",
  308.        "total frames transmitted", stats->tx_packets);
  309. cnt += sprintf(buf + cnt, "%30s: %12lun",
  310.        "total bytes transmitted", stats->tx_bytes);
  311. cnt += sprintf(buf + cnt, "%30s: %12lun",
  312.        "total headroom inc", dev_info->cnt_inc_headroom_on_tx);
  313. cnt += sprintf(buf + cnt, "%30s: %12lun",
  314.        "total encap on xmit", dev_info->cnt_encap_on_xmit);
  315. cnt += sprintf(buf + cnt, "Device: %s", dev_info->real_dev->name);
  316. /* now show all PRIORITY mappings relating to this VLAN */
  317. cnt += sprintf(buf + cnt, "nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lun",
  318.        dev_info->ingress_priority_map[0],
  319.        dev_info->ingress_priority_map[1],
  320.        dev_info->ingress_priority_map[2],
  321.        dev_info->ingress_priority_map[3],
  322.        dev_info->ingress_priority_map[4],
  323.        dev_info->ingress_priority_map[5],
  324.        dev_info->ingress_priority_map[6],
  325.        dev_info->ingress_priority_map[7]);
  326. if ((cnt + 100) > VLAN_PROC_BUFSZ) {
  327. if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
  328. /* should never get here */
  329. return cnt;
  330. } else {
  331. cnt += sprintf(buf + cnt, "%s", term_msg);
  332. return cnt;
  333. }
  334. }
  335. cnt += sprintf(buf + cnt, "EGRESSS priority Mappings: ");
  336. for (i = 0; i < 16; i++) {
  337. mp = dev_info->egress_priority_map[i];
  338. while (mp) {
  339. cnt += sprintf(buf + cnt, "%lu:%hu ",
  340.        mp->priority, ((mp->vlan_qos >> 13) & 0x7));
  341. if ((cnt + 100) > VLAN_PROC_BUFSZ) {
  342. if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
  343. /* should never get here */
  344. return cnt;
  345. } else {
  346. cnt += sprintf(buf + cnt, "%s", term_msg);
  347. return cnt;
  348. }
  349. }
  350. mp = mp->next;
  351. }
  352. }
  353. cnt += sprintf(buf + cnt, "n");
  354. return cnt;
  355. }
  356. #else /* No CONFIG_PROC_FS */
  357. /*
  358.  * No /proc - output stubs
  359.  */
  360.  
  361. int __init vlan_proc_init (void)
  362. {
  363. return 0;
  364. }
  365. void vlan_proc_cleanup(void)
  366. {
  367. return;
  368. }
  369. int vlan_proc_add_dev(struct net_device *vlandev)
  370. {
  371. return 0;
  372. }
  373. int vlan_proc_rem_dev(struct net_device *vlandev)
  374. {
  375. return 0;
  376. }
  377. #endif /* No CONFIG_PROC_FS */