cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vlanproc.c (7687B)


      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 */
     36static int vlan_seq_show(struct seq_file *seq, void *v);
     37static void *vlan_seq_start(struct seq_file *seq, loff_t *pos);
     38static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos);
     39static void vlan_seq_stop(struct seq_file *seq, void *);
     40static 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
     51static const char name_root[]	 = "vlan";
     52static 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
     66static 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 */
     78static 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
     92void 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
    111int __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
    126err:
    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
    136int 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 */
    153void 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 */
    167static 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
    189static 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
    210static void vlan_seq_stop(struct seq_file *seq, void *v)
    211	__releases(rcu)
    212{
    213	rcu_read_unlock();
    214}
    215
    216static 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
    241static 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: %llx\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:%d ",
    284				   mp->priority, ((mp->vlan_qos >> 13) & 0x7));
    285			mp = mp->next;
    286		}
    287	}
    288	seq_puts(seq, "\n");
    289
    290	return 0;
    291}