root/net/8021q/vlanproc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vlan_proc_cleanup
  2. vlan_proc_init
  3. vlan_proc_add_dev
  4. vlan_proc_rem_dev
  5. vlan_seq_start
  6. vlan_seq_next
  7. vlan_seq_stop
  8. vlan_seq_show
  9. vlandev_seq_show

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /******************************************************************************
   3  * vlanproc.c   VLAN Module. /proc filesystem interface.
   4  *
   5  *              This module is completely hardware-independent and provides
   6  *              access to the router using Linux /proc filesystem.
   7  *
   8  * Author:      Ben Greear, <greearb@candelatech.com> coppied from wanproc.c
   9  *               by: Gene Kozin <genek@compuserve.com>
  10  *
  11  * Copyright:   (c) 1998 Ben Greear
  12  *
  13  * ============================================================================
  14  * Jan 20, 1998        Ben Greear     Initial Version
  15  *****************************************************************************/
  16 
  17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  18 
  19 #include <linux/module.h>
  20 #include <linux/errno.h>
  21 #include <linux/kernel.h>
  22 #include <linux/string.h>
  23 #include <linux/proc_fs.h>
  24 #include <linux/seq_file.h>
  25 #include <linux/fs.h>
  26 #include <linux/netdevice.h>
  27 #include <linux/if_vlan.h>
  28 #include <net/net_namespace.h>
  29 #include <net/netns/generic.h>
  30 #include "vlanproc.h"
  31 #include "vlan.h"
  32 
  33 /****** Function Prototypes *************************************************/
  34 
  35 /* Methods for preparing data for reading proc entries */
  36 static int vlan_seq_show(struct seq_file *seq, void *v);
  37 static void *vlan_seq_start(struct seq_file *seq, loff_t *pos);
  38 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos);
  39 static void vlan_seq_stop(struct seq_file *seq, void *);
  40 static int vlandev_seq_show(struct seq_file *seq, void *v);
  41 
  42 /*
  43  *      Global Data
  44  */
  45 
  46 
  47 /*
  48  *      Names of the proc directory entries
  49  */
  50 
  51 static const char name_root[]    = "vlan";
  52 static const char name_conf[]    = "config";
  53 
  54 /*
  55  *      Structures for interfacing with the /proc filesystem.
  56  *      VLAN creates its own directory /proc/net/vlan with the following
  57  *      entries:
  58  *      config          device status/configuration
  59  *      <device>        entry for each  device
  60  */
  61 
  62 /*
  63  *      Generic /proc/net/vlan/<file> file and inode operations
  64  */
  65 
  66 static const struct seq_operations vlan_seq_ops = {
  67         .start = vlan_seq_start,
  68         .next = vlan_seq_next,
  69         .stop = vlan_seq_stop,
  70         .show = vlan_seq_show,
  71 };
  72 
  73 /*
  74  * Proc filesystem directory entries.
  75  */
  76 
  77 /* Strings */
  78 static const char *const vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
  79     [VLAN_NAME_TYPE_RAW_PLUS_VID]        = "VLAN_NAME_TYPE_RAW_PLUS_VID",
  80     [VLAN_NAME_TYPE_PLUS_VID_NO_PAD]     = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD",
  81     [VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD] = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD",
  82     [VLAN_NAME_TYPE_PLUS_VID]            = "VLAN_NAME_TYPE_PLUS_VID",
  83 };
  84 /*
  85  *      Interface functions
  86  */
  87 
  88 /*
  89  *      Clean up /proc/net/vlan entries
  90  */
  91 
  92 void vlan_proc_cleanup(struct net *net)
  93 {
  94         struct vlan_net *vn = net_generic(net, vlan_net_id);
  95 
  96         if (vn->proc_vlan_conf)
  97                 remove_proc_entry(name_conf, vn->proc_vlan_dir);
  98 
  99         if (vn->proc_vlan_dir)
 100                 remove_proc_entry(name_root, net->proc_net);
 101 
 102         /* Dynamically added entries should be cleaned up as their vlan_device
 103          * is removed, so we should not have to take care of it here...
 104          */
 105 }
 106 
 107 /*
 108  *      Create /proc/net/vlan entries
 109  */
 110 
 111 int __net_init vlan_proc_init(struct net *net)
 112 {
 113         struct vlan_net *vn = net_generic(net, vlan_net_id);
 114 
 115         vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
 116         if (!vn->proc_vlan_dir)
 117                 goto err;
 118 
 119         vn->proc_vlan_conf = proc_create_net(name_conf, S_IFREG | 0600,
 120                         vn->proc_vlan_dir, &vlan_seq_ops,
 121                         sizeof(struct seq_net_private));
 122         if (!vn->proc_vlan_conf)
 123                 goto err;
 124         return 0;
 125 
 126 err:
 127         pr_err("can't create entry in proc filesystem!\n");
 128         vlan_proc_cleanup(net);
 129         return -ENOBUFS;
 130 }
 131 
 132 /*
 133  *      Add directory entry for VLAN device.
 134  */
 135 
 136 int vlan_proc_add_dev(struct net_device *vlandev)
 137 {
 138         struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
 139         struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
 140 
 141         if (!strcmp(vlandev->name, name_conf))
 142                 return -EINVAL;
 143         vlan->dent = proc_create_single_data(vlandev->name, S_IFREG | 0600,
 144                         vn->proc_vlan_dir, vlandev_seq_show, vlandev);
 145         if (!vlan->dent)
 146                 return -ENOBUFS;
 147         return 0;
 148 }
 149 
 150 /*
 151  *      Delete directory entry for VLAN device.
 152  */
 153 void vlan_proc_rem_dev(struct net_device *vlandev)
 154 {
 155         /** NOTE:  This will consume the memory pointed to by dent, it seems. */
 156         proc_remove(vlan_dev_priv(vlandev)->dent);
 157         vlan_dev_priv(vlandev)->dent = NULL;
 158 }
 159 
 160 /****** Proc filesystem entry points ****************************************/
 161 
 162 /*
 163  * The following few functions build the content of /proc/net/vlan/config
 164  */
 165 
 166 /* start read of /proc/net/vlan/config */
 167 static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 168         __acquires(rcu)
 169 {
 170         struct net_device *dev;
 171         struct net *net = seq_file_net(seq);
 172         loff_t i = 1;
 173 
 174         rcu_read_lock();
 175         if (*pos == 0)
 176                 return SEQ_START_TOKEN;
 177 
 178         for_each_netdev_rcu(net, dev) {
 179                 if (!is_vlan_dev(dev))
 180                         continue;
 181 
 182                 if (i++ == *pos)
 183                         return dev;
 184         }
 185 
 186         return  NULL;
 187 }
 188 
 189 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 190 {
 191         struct net_device *dev;
 192         struct net *net = seq_file_net(seq);
 193 
 194         ++*pos;
 195 
 196         dev = v;
 197         if (v == SEQ_START_TOKEN)
 198                 dev = net_device_entry(&net->dev_base_head);
 199 
 200         for_each_netdev_continue_rcu(net, dev) {
 201                 if (!is_vlan_dev(dev))
 202                         continue;
 203 
 204                 return dev;
 205         }
 206 
 207         return NULL;
 208 }
 209 
 210 static void vlan_seq_stop(struct seq_file *seq, void *v)
 211         __releases(rcu)
 212 {
 213         rcu_read_unlock();
 214 }
 215 
 216 static int vlan_seq_show(struct seq_file *seq, void *v)
 217 {
 218         struct net *net = seq_file_net(seq);
 219         struct vlan_net *vn = net_generic(net, vlan_net_id);
 220 
 221         if (v == SEQ_START_TOKEN) {
 222                 const char *nmtype = NULL;
 223 
 224                 seq_puts(seq, "VLAN Dev name     | VLAN ID\n");
 225 
 226                 if (vn->name_type < ARRAY_SIZE(vlan_name_type_str))
 227                     nmtype =  vlan_name_type_str[vn->name_type];
 228 
 229                 seq_printf(seq, "Name-Type: %s\n",
 230                            nmtype ? nmtype :  "UNKNOWN");
 231         } else {
 232                 const struct net_device *vlandev = v;
 233                 const struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
 234 
 235                 seq_printf(seq, "%-15s| %d  | %s\n",  vlandev->name,
 236                            vlan->vlan_id,    vlan->real_dev->name);
 237         }
 238         return 0;
 239 }
 240 
 241 static int vlandev_seq_show(struct seq_file *seq, void *offset)
 242 {
 243         struct net_device *vlandev = (struct net_device *) seq->private;
 244         const struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
 245         struct rtnl_link_stats64 temp;
 246         const struct rtnl_link_stats64 *stats;
 247         static const char fmt64[] = "%30s %12llu\n";
 248         int i;
 249 
 250         if (!is_vlan_dev(vlandev))
 251                 return 0;
 252 
 253         stats = dev_get_stats(vlandev, &temp);
 254         seq_printf(seq,
 255                    "%s  VID: %d  REORDER_HDR: %i  dev->priv_flags: %hx\n",
 256                    vlandev->name, vlan->vlan_id,
 257                    (int)(vlan->flags & 1), vlandev->priv_flags);
 258 
 259         seq_printf(seq, fmt64, "total frames received", stats->rx_packets);
 260         seq_printf(seq, fmt64, "total bytes received", stats->rx_bytes);
 261         seq_printf(seq, fmt64, "Broadcast/Multicast Rcvd", stats->multicast);
 262         seq_puts(seq, "\n");
 263         seq_printf(seq, fmt64, "total frames transmitted", stats->tx_packets);
 264         seq_printf(seq, fmt64, "total bytes transmitted", stats->tx_bytes);
 265         seq_printf(seq, "Device: %s", vlan->real_dev->name);
 266         /* now show all PRIORITY mappings relating to this VLAN */
 267         seq_printf(seq, "\nINGRESS priority mappings: "
 268                         "0:%u  1:%u  2:%u  3:%u  4:%u  5:%u  6:%u 7:%u\n",
 269                    vlan->ingress_priority_map[0],
 270                    vlan->ingress_priority_map[1],
 271                    vlan->ingress_priority_map[2],
 272                    vlan->ingress_priority_map[3],
 273                    vlan->ingress_priority_map[4],
 274                    vlan->ingress_priority_map[5],
 275                    vlan->ingress_priority_map[6],
 276                    vlan->ingress_priority_map[7]);
 277 
 278         seq_printf(seq, " EGRESS priority mappings: ");
 279         for (i = 0; i < 16; i++) {
 280                 const struct vlan_priority_tci_mapping *mp
 281                         = vlan->egress_priority_map[i];
 282                 while (mp) {
 283                         seq_printf(seq, "%u:%hu ",
 284                                    mp->priority, ((mp->vlan_qos >> 13) & 0x7));
 285                         mp = mp->next;
 286                 }
 287         }
 288         seq_puts(seq, "\n");
 289 
 290         return 0;
 291 }

/* [<][>][^][v][top][bottom][index][help] */