net/procfs: add entry mapping table

add entry mapping table to simplify new component registration

Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
chao an 2022-09-04 21:39:06 +08:00 committed by Xiang Xiao
parent 3913ef2f2f
commit 4068b2eccc
2 changed files with 130 additions and 181 deletions

View File

@ -52,26 +52,27 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Directory entry indices */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#ifdef CONFIG_NET_STATISTICS /****************************************************************************
# define STAT_INDEX 0 * Private Type Definitions
# ifdef CONFIG_NET_MLD ****************************************************************************/
# define MLD_INDEX 1
# define _ROUTE_INDEX 2
# else
# define _ROUTE_INDEX 1
# endif
#else
# define _ROUTE_INDEX 0
#endif
#ifdef CONFIG_NET_ROUTE /* Read statistics function type */
# define ROUTE_INDEX _ROUTE_INDEX
# define DEV_INDEX (_ROUTE_INDEX + 1) typedef CODE ssize_t (*read_stat_t)(FAR struct netprocfs_file_s *priv,
#else FAR char *buffer, size_t buflen);
# define DEV_INDEX _ROUTE_INDEX
#endif struct netprocfs_entry_s
{
uint8_t type; /* Type of file */
FAR const char *name; /* File name */
union
{
read_stat_t stat; /* Read statistics hook */
FAR const struct procfs_operations *ops;
} u;
};
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
@ -98,6 +99,48 @@ static int netprocfs_rewinddir(FAR struct fs_dirent_s *dir);
static int netprocfs_stat(FAR const char *relpath, FAR struct stat *buf); static int netprocfs_stat(FAR const char *relpath, FAR struct stat *buf);
/****************************************************************************
* Private Data
****************************************************************************/
extern const struct procfs_operations net_procfs_routeoperations;
/* Netprocfs component mappings */
static const struct netprocfs_entry_s g_net_entries[] =
{
#ifdef CONFIG_NET_STATISTICS
{
DTYPE_FILE, "stat",
{
netprocfs_read_netstats
}
},
# ifdef CONFIG_NET_MLD
{
DTYPE_FILE, "mld",
{
netprocfs_read_mldstats
}
},
# endif
#endif
#ifdef CONFIG_NET_ROUTE
{
DTYPE_DIRECTORY, "route",
{
(FAR void *)&net_procfs_routeoperations
}
},
#endif
{
DTYPE_FILE, "",
{
netprocfs_read_devstats
}
}
};
/**************************************************************************** /****************************************************************************
* Public Data * Public Data
****************************************************************************/ ****************************************************************************/
@ -123,8 +166,6 @@ const struct procfs_operations net_procfsoperations =
netprocfs_stat /* stat */ netprocfs_stat /* stat */
}; };
extern const struct procfs_operations net_procfs_routeoperations;
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -136,9 +177,9 @@ extern const struct procfs_operations net_procfs_routeoperations;
static int netprocfs_open(FAR struct file *filep, FAR const char *relpath, static int netprocfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode) int oflags, mode_t mode)
{ {
FAR struct net_driver_s *dev = NULL;
FAR struct netprocfs_file_s *priv; FAR struct netprocfs_file_s *priv;
FAR struct net_driver_s *dev; int i;
enum netprocfs_entry_e entry;
finfo("Open '%s'\n", relpath); finfo("Open '%s'\n", relpath);
@ -155,44 +196,25 @@ static int netprocfs_open(FAR struct file *filep, FAR const char *relpath,
return -EACCES; return -EACCES;
} }
#ifdef CONFIG_NET_STATISTICS /* For each net entries */
/* "net/stat" is an acceptable value for the relpath only if network layer
* statistics are enabled.
*/
if (strcmp(relpath, "net/stat") == 0) for (i = 0; i < ARRAY_SIZE(g_net_entries); i++)
{ {
entry = NETPROCFS_SUBDIR_STAT; if (strncmp(relpath + 4, g_net_entries[i].name,
dev = NULL; strlen(g_net_entries[i].name)))
}
else
#ifdef CONFIG_NET_MLD
/* "net/mld" is an acceptable value for the relpath only if MLD is
* enabled.
*/
if (strcmp(relpath, "net/mld") == 0)
{ {
entry = NETPROCFS_SUBDIR_MLD; continue;
dev = NULL;
} }
else
#endif
#endif
#ifdef CONFIG_NET_ROUTE if (g_net_entries[i].type == DTYPE_DIRECTORY)
/* "net/route" is an acceptable value for the relpath only if routing
* table support is initialized.
*/
if (fnmatch("net/route/**", relpath, 0) == 0)
{ {
/* Use the /net/route directory */ return g_net_entries[i].u.ops->open(filep, relpath, oflags, mode);
return net_procfs_routeoperations.open(filep, relpath, oflags, mode);
} }
else
#endif break;
}
if (i == ARRAY_SIZE(g_net_entries) - 1)
{ {
FAR char *devname; FAR char *devname;
FAR char *copy; FAR char *copy;
@ -217,8 +239,6 @@ static int netprocfs_open(FAR struct file *filep, FAR const char *relpath,
ferr("ERROR: relpath is '%s'\n", relpath); ferr("ERROR: relpath is '%s'\n", relpath);
return -ENOENT; return -ENOENT;
} }
entry = NETPROCFS_SUBDIR_DEV;
} }
/* Allocate the open file structure */ /* Allocate the open file structure */
@ -234,7 +254,7 @@ static int netprocfs_open(FAR struct file *filep, FAR const char *relpath,
/* Initialize the open-file structure */ /* Initialize the open-file structure */
priv->dev = dev; priv->dev = dev;
priv->entry = entry; priv->entry = i;
/* Save the open file structure as the open-specific state in /* Save the open file structure as the open-specific state in
* filep->f_priv. * filep->f_priv.
@ -272,7 +292,7 @@ static ssize_t netprocfs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen) size_t buflen)
{ {
FAR struct netprocfs_file_s *priv; FAR struct netprocfs_file_s *priv;
ssize_t nreturned; ssize_t nreturned = -EINVAL;
finfo("buffer=%p buflen=%lu\n", buffer, (unsigned long)buflen); finfo("buffer=%p buflen=%lu\n", buffer, (unsigned long)buflen);
@ -283,42 +303,8 @@ static ssize_t netprocfs_read(FAR struct file *filep, FAR char *buffer,
/* Read according to the sub-directory */ /* Read according to the sub-directory */
switch (priv->entry) nreturned = g_net_entries[priv->entry].u.stat(priv,
{ buffer, buflen);
case NETPROCFS_SUBDIR_DEV:
/* Show device-specific statistics */
nreturned = netprocfs_read_devstats(priv, buffer, buflen);
break;
#ifdef CONFIG_NET_STATISTICS
case NETPROCFS_SUBDIR_STAT:
/* Show the network layer statistics */
nreturned = netprocfs_read_netstats(priv, buffer, buflen);
break;
#ifdef CONFIG_NET_MLD
case NETPROCFS_SUBDIR_MLD:
/* Show the MLD statistics */
nreturned = netprocfs_read_mldstats(priv, buffer, buflen);
break;
#endif
#endif
#ifdef CONFIG_NET_ROUTE
case NETPROCFS_SUBDIR_ROUTE:
nerr("ERROR: Cannot read from directory net/route\n");
#endif
default:
nerr("ERROR: Invalid entry for reading: %u\n", priv->entry);
nreturned = -EINVAL;
}
/* Update the file offset */ /* Update the file offset */
@ -384,23 +370,28 @@ static int netprocfs_opendir(FAR const char *relpath,
FAR struct netprocfs_level1_s *level1; FAR struct netprocfs_level1_s *level1;
int ndevs; int ndevs;
int ret; int ret;
int i;
finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL"); finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
DEBUGASSERT(relpath && dir); DEBUGASSERT(relpath && dir);
/* "net" and "net/route" are the only values of relpath that are /* Subdirectory ? */
* directories.
*/
#ifdef CONFIG_NET_ROUTE for (i = 0; i < ARRAY_SIZE(g_net_entries); i++)
if (fnmatch("net/route", relpath, 0) == 0 ||
fnmatch("net/route/**", relpath, 0) == 0)
{ {
/* Use the /net/route directory */ if (strncmp(relpath + 4, g_net_entries[i].name,
strlen(g_net_entries[i].name)))
return net_procfs_routeoperations.opendir(relpath, dir); {
continue;
}
if (g_net_entries[i].type == DTYPE_DIRECTORY)
{
return g_net_entries[i].u.ops->opendir(relpath, dir);
}
break;
} }
#endif
/* Assume that path refers to the 1st level subdirectory. Allocate the /* Assume that path refers to the 1st level subdirectory. Allocate the
* level1 the dirent structure before checking. * level1 the dirent structure before checking.
@ -426,15 +417,10 @@ static int netprocfs_opendir(FAR const char *relpath,
/* Initialize base structure components */ /* Initialize base structure components */
level1->base.nentries = ndevs; level1->base.nentries = ndevs;
#ifdef CONFIG_NET_STATISTICS
level1->base.nentries++; /* Add other enabled net components, except netdev */
#ifdef CONFIG_NET_MLD
level1->base.nentries++; level1->base.nentries += ARRAY_SIZE(g_net_entries) - 1;
#endif
#endif
#ifdef CONFIG_NET_ROUTE
level1->base.nentries++;
#endif
} }
else else
{ {
@ -510,36 +496,18 @@ static int netprocfs_readdir(FAR struct fs_dirent_s *dir,
return -ENOENT; return -ENOENT;
} }
#ifdef CONFIG_NET_STATISTICS /* Process other enabled net components, except netdev */
if (index == STAT_INDEX)
{
/* Copy the network statistics directory entry */
entry->d_type = DTYPE_FILE; if (index < ARRAY_SIZE(g_net_entries) - 1)
strlcpy(entry->d_name, "stat", sizeof(entry->d_name));
}
else
#ifdef CONFIG_NET_MLD
if (index == MLD_INDEX)
{ {
/* Copy the MLD directory entry */ entry->d_type = g_net_entries[index].type;
strlcpy(entry->d_name,
entry->d_type = DTYPE_FILE; g_net_entries[index].name, sizeof(entry->d_name));
strlcpy(entry->d_name, "mld", sizeof(entry->d_name));
} }
else
#endif
#endif
#ifdef CONFIG_NET_ROUTE
if (index == ROUTE_INDEX)
{
/* Copy the network statistics directory entry */
entry->d_type = DTYPE_DIRECTORY; /* Net device entry */
strlcpy(entry->d_name, "route", sizeof(entry->d_name));
}
else else
#endif
{ {
int ifindex; int ifindex;
@ -567,9 +535,9 @@ static int netprocfs_readdir(FAR struct fs_dirent_s *dir,
level1->ifindex = ifindex + 1; level1->ifindex = ifindex + 1;
#else #else
/* Get the raw index, accounting for 1 based indexing */ /* Get the raw index */
ifindex = index - DEV_INDEX + 1; ifindex = index - ARRAY_SIZE(g_net_entries) + 1;
#endif #endif
/* Find the device corresponding to this device index */ /* Find the device corresponding to this device index */
@ -636,40 +604,37 @@ static int netprocfs_rewinddir(FAR struct fs_dirent_s *dir)
static int netprocfs_stat(FAR const char *relpath, FAR struct stat *buf) static int netprocfs_stat(FAR const char *relpath, FAR struct stat *buf)
{ {
int i;
/* Check for the directory "net" */ /* Check for the directory "net" */
buf->st_mode = 0;
if (strcmp(relpath, "net") == 0 || strcmp(relpath, "net/") == 0) if (strcmp(relpath, "net") == 0 || strcmp(relpath, "net/") == 0)
{ {
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR; buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
} }
else else
#ifdef CONFIG_NET_STATISTICS {
/* Check for network statistics "net/stat" */ for (i = 0; i < ARRAY_SIZE(g_net_entries); i++)
{
if (strcmp(relpath, "net/stat") == 0) if (strcmp(relpath + 4, g_net_entries[i].name) == 0)
{
if (g_net_entries[i].type == DTYPE_FILE)
{ {
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR; buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
} }
else else if (g_net_entries[i].type == DTYPE_DIRECTORY)
#ifdef CONFIG_NET_MLD
/* Check for MLD statistics "net/mld" */
if (strcmp(relpath, "net/mld") == 0)
{
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
}
else
#endif
#endif
#ifdef CONFIG_NET_ROUTE
/* Check for network statistics "net/stat" */
if (strcmp(relpath, "net/route") == 0)
{ {
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR; buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
} }
else
#endif break;
}
}
}
if (buf->st_mode == 0)
{ {
FAR struct net_driver_s *dev; FAR struct net_driver_s *dev;
FAR char *devname; FAR char *devname;

View File

@ -49,22 +49,6 @@
* Public Type Definitions * Public Type Definitions
****************************************************************************/ ****************************************************************************/
/* Describes the /net directory entries */
enum netprocfs_entry_e
{
NETPROCFS_SUBDIR_DEV = 0 /* Multiple instances, e.g. /proc/net/eth0 */
#ifdef CONFIG_NET_STATISTICS
, NETPROCFS_SUBDIR_STAT /* /proc/net/stat */
#ifdef CONFIG_NET_MLD
, NETPROCFS_SUBDIR_MLD /* /proc/net/mld */
#endif
#endif
#ifdef CONFIG_NET_ROUTE
, NETPROCFS_SUBDIR_ROUTE /* /proc/net/route */
#endif
};
/* This structure describes one open "file" */ /* This structure describes one open "file" */
struct net_driver_s; /* Forward reference */ struct net_driver_s; /* Forward reference */
@ -75,7 +59,7 @@ struct netprocfs_file_s
uint8_t lineno; /* Line number */ uint8_t lineno; /* Line number */
uint8_t linesize; /* Number of valid characters in line[] */ uint8_t linesize; /* Number of valid characters in line[] */
uint8_t offset; /* Offset to first valid character in line[] */ uint8_t offset; /* Offset to first valid character in line[] */
uint8_t entry; /* See enum netprocfs_entry_e */ uint8_t entry; /* Entry index of netprocfs_entry_s */
char line[NET_LINELEN]; /* Pre-allocated buffer for formatted lines */ char line[NET_LINELEN]; /* Pre-allocated buffer for formatted lines */
}; };