LCOV - code coverage report
Current view: top level - net/8021q - vlanproc.c (source / functions) Hit Total Coverage
Test: Real Lines: 13 77 16.9 %
Date: 2020-10-17 15:46:16 Functions: 0 9 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       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                 :          1 : void vlan_proc_cleanup(struct net *net)
      93                 :            : {
      94                 :          1 :         struct vlan_net *vn = net_generic(net, vlan_net_id);
      95                 :            : 
      96                 :          1 :         if (vn->proc_vlan_conf)
      97                 :          1 :                 remove_proc_entry(name_conf, vn->proc_vlan_dir);
      98                 :            : 
      99                 :          1 :         if (vn->proc_vlan_dir)
     100                 :          1 :                 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                 :          1 : }
     106                 :            : 
     107                 :            : /*
     108                 :            :  *      Create /proc/net/vlan entries
     109                 :            :  */
     110                 :            : 
     111                 :          3 : int __net_init vlan_proc_init(struct net *net)
     112                 :            : {
     113                 :          3 :         struct vlan_net *vn = net_generic(net, vlan_net_id);
     114                 :            : 
     115                 :          3 :         vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
     116                 :          3 :         if (!vn->proc_vlan_dir)
     117                 :            :                 goto err;
     118                 :            : 
     119                 :          3 :         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                 :          3 :         if (!vn->proc_vlan_conf)
     123                 :            :                 goto err;
     124                 :            :         return 0;
     125                 :            : 
     126                 :            : err:
     127                 :          0 :         pr_err("can't create entry in proc filesystem!\n");
     128                 :          0 :         vlan_proc_cleanup(net);
     129                 :          0 :         return -ENOBUFS;
     130                 :            : }
     131                 :            : 
     132                 :            : /*
     133                 :            :  *      Add directory entry for VLAN device.
     134                 :            :  */
     135                 :            : 
     136                 :          0 : int vlan_proc_add_dev(struct net_device *vlandev)
     137                 :            : {
     138                 :            :         struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
     139                 :          0 :         struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
     140                 :            : 
     141                 :          0 :         if (!strcmp(vlandev->name, name_conf))
     142                 :            :                 return -EINVAL;
     143                 :          0 :         vlan->dent = proc_create_single_data(vlandev->name, S_IFREG | 0600,
     144                 :            :                         vn->proc_vlan_dir, vlandev_seq_show, vlandev);
     145                 :          0 :         if (!vlan->dent)
     146                 :            :                 return -ENOBUFS;
     147                 :          0 :         return 0;
     148                 :            : }
     149                 :            : 
     150                 :            : /*
     151                 :            :  *      Delete directory entry for VLAN device.
     152                 :            :  */
     153                 :          0 : void vlan_proc_rem_dev(struct net_device *vlandev)
     154                 :            : {
     155                 :            :         /** NOTE:  This will consume the memory pointed to by dent, it seems. */
     156                 :          0 :         proc_remove(vlan_dev_priv(vlandev)->dent);
     157                 :          0 :         vlan_dev_priv(vlandev)->dent = NULL;
     158                 :          0 : }
     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                 :          0 : 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                 :          0 :         if (*pos == 0)
     176                 :            :                 return SEQ_START_TOKEN;
     177                 :            : 
     178                 :          0 :         for_each_netdev_rcu(net, dev) {
     179                 :          0 :                 if (!is_vlan_dev(dev))
     180                 :          0 :                         continue;
     181                 :            : 
     182                 :          0 :                 if (i++ == *pos)
     183                 :          0 :                         return dev;
     184                 :            :         }
     185                 :            : 
     186                 :            :         return  NULL;
     187                 :            : }
     188                 :            : 
     189                 :          0 : 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                 :          0 :         ++*pos;
     195                 :            : 
     196                 :            :         dev = v;
     197                 :          0 :         if (v == SEQ_START_TOKEN)
     198                 :          0 :                 dev = net_device_entry(&net->dev_base_head);
     199                 :            : 
     200                 :          0 :         for_each_netdev_continue_rcu(net, dev) {
     201                 :          0 :                 if (!is_vlan_dev(dev))
     202                 :          0 :                         continue;
     203                 :            : 
     204                 :          0 :                 return dev;
     205                 :            :         }
     206                 :            : 
     207                 :            :         return NULL;
     208                 :            : }
     209                 :            : 
     210                 :          0 : static void vlan_seq_stop(struct seq_file *seq, void *v)
     211                 :            :         __releases(rcu)
     212                 :            : {
     213                 :            :         rcu_read_unlock();
     214                 :          0 : }
     215                 :            : 
     216                 :          0 : static int vlan_seq_show(struct seq_file *seq, void *v)
     217                 :            : {
     218                 :            :         struct net *net = seq_file_net(seq);
     219                 :          0 :         struct vlan_net *vn = net_generic(net, vlan_net_id);
     220                 :            : 
     221                 :          0 :         if (v == SEQ_START_TOKEN) {
     222                 :            :                 const char *nmtype = NULL;
     223                 :            : 
     224                 :          0 :                 seq_puts(seq, "VLAN Dev name        | VLAN ID\n");
     225                 :            : 
     226                 :          0 :                 if (vn->name_type < ARRAY_SIZE(vlan_name_type_str))
     227                 :          0 :                     nmtype =  vlan_name_type_str[vn->name_type];
     228                 :            : 
     229                 :          0 :                 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                 :          0 :                 seq_printf(seq, "%-15s| %d  | %s\n",  vlandev->name,
     236                 :          0 :                            vlan->vlan_id,    vlan->real_dev->name);
     237                 :            :         }
     238                 :          0 :         return 0;
     239                 :            : }
     240                 :            : 
     241                 :          0 : static int vlandev_seq_show(struct seq_file *seq, void *offset)
     242                 :            : {
     243                 :          0 :         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                 :          0 :         if (!is_vlan_dev(vlandev))
     251                 :            :                 return 0;
     252                 :            : 
     253                 :          0 :         stats = dev_get_stats(vlandev, &temp);
     254                 :          0 :         seq_printf(seq,
     255                 :            :                    "%s  VID: %d     REORDER_HDR: %i  dev->priv_flags: %hx\n",
     256                 :          0 :                    vlandev->name, vlan->vlan_id,
     257                 :          0 :                    (int)(vlan->flags & 1), vlandev->priv_flags);
     258                 :            : 
     259                 :          0 :         seq_printf(seq, fmt64, "total frames received", stats->rx_packets);
     260                 :          0 :         seq_printf(seq, fmt64, "total bytes received", stats->rx_bytes);
     261                 :          0 :         seq_printf(seq, fmt64, "Broadcast/Multicast Rcvd", stats->multicast);
     262                 :          0 :         seq_puts(seq, "\n");
     263                 :          0 :         seq_printf(seq, fmt64, "total frames transmitted", stats->tx_packets);
     264                 :          0 :         seq_printf(seq, fmt64, "total bytes transmitted", stats->tx_bytes);
     265                 :          0 :         seq_printf(seq, "Device: %s", vlan->real_dev->name);
     266                 :            :         /* now show all PRIORITY mappings relating to this VLAN */
     267                 :          0 :         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                 :          0 :         seq_printf(seq, " EGRESS priority mappings: ");
     279                 :          0 :         for (i = 0; i < 16; i++) {
     280                 :          0 :                 const struct vlan_priority_tci_mapping *mp
     281                 :            :                         = vlan->egress_priority_map[i];
     282                 :          0 :                 while (mp) {
     283                 :          0 :                         seq_printf(seq, "%u:%hu ",
     284                 :          0 :                                    mp->priority, ((mp->vlan_qos >> 13) & 0x7));
     285                 :          0 :                         mp = mp->next;
     286                 :            :                 }
     287                 :            :         }
     288                 :          0 :         seq_puts(seq, "\n");
     289                 :            : 
     290                 :          0 :         return 0;
     291                 :            : }
    

Generated by: LCOV version 1.14