procfs: Add support for routing tables.
This commit is contained in:
parent
fdca465da6
commit
65698da12d
5
TODO
5
TODO
@ -2097,6 +2097,11 @@ o Build system
|
|||||||
|
|
||||||
$ make apps_distclean
|
$ make apps_distclean
|
||||||
|
|
||||||
|
One solution to this might be to making the special target
|
||||||
|
.PRECIOUS depend on apps/libapps.a. Then if make receives a
|
||||||
|
signal, it will not delete apps/libapps.a. This would have to
|
||||||
|
be done in all Makefiles.
|
||||||
|
|
||||||
Status Open
|
Status Open
|
||||||
Priority: Medium-High. It is a rare event that control-C happens at just the
|
Priority: Medium-High. It is a rare event that control-C happens at just the
|
||||||
point in time. However, when it does occur the resulting code may
|
point in time. However, when it does occur the resulting code may
|
||||||
|
@ -63,6 +63,11 @@ config FS_PROCFS_EXCLUDE_NET
|
|||||||
depends on NET
|
depends on NET
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config FS_PROC_EXCLUDE_ROUTE
|
||||||
|
bool "Exclude routing table"
|
||||||
|
depends on !FS_PROCFS_EXCLUDE_NET && NET_ROUTE
|
||||||
|
default n
|
||||||
|
|
||||||
config FS_PROCFS_EXCLUDE_MTD
|
config FS_PROCFS_EXCLUDE_MTD
|
||||||
bool "Exclude mtd"
|
bool "Exclude mtd"
|
||||||
depends on MTD
|
depends on MTD
|
||||||
|
@ -87,6 +87,7 @@ extern const struct procfs_operations uptime_operations;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern const struct procfs_operations net_procfsoperations;
|
extern const struct procfs_operations net_procfsoperations;
|
||||||
|
extern const struct procfs_operations net_procfs_routeoperations;
|
||||||
extern const struct procfs_operations mtd_procfsoperations;
|
extern const struct procfs_operations mtd_procfsoperations;
|
||||||
extern const struct procfs_operations part_procfsoperations;
|
extern const struct procfs_operations part_procfsoperations;
|
||||||
extern const struct procfs_operations smartfs_procfsoperations;
|
extern const struct procfs_operations smartfs_procfsoperations;
|
||||||
@ -112,42 +113,46 @@ static const struct procfs_entry_s g_procfs_entries[] =
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
|
#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
|
||||||
{ "[0-9]*/**", &proc_operations },
|
{ "[0-9]*/**", &proc_operations, PROCFS_UNKOWN_TYPE },
|
||||||
{ "[0-9]*", &proc_operations },
|
{ "[0-9]*", &proc_operations, PROCFS_DIR_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_SCHED_CPULOAD) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CPULOAD)
|
#if defined(CONFIG_SCHED_CPULOAD) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CPULOAD)
|
||||||
{ "cpuload", &cpuload_operations },
|
{ "cpuload", &cpuload_operations, PROCFS_FILE_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MM_KERNEL_HEAP) && !defined(CONFIG_FS_PROCFS_EXCLUDE_KMM)
|
#if defined(CONFIG_MM_KERNEL_HEAP) && !defined(CONFIG_FS_PROCFS_EXCLUDE_KMM)
|
||||||
{ "kmm", &kmm_operations },
|
{ "kmm", &kmm_operations, PROCFS_FILE_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MODULE) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
#if defined(CONFIG_MODULE) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||||
{ "modules", &module_operations },
|
{ "modules", &module_operations, PROCFS_DIR_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_FS_SMARTFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
|
#if defined(CONFIG_FS_SMARTFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
|
||||||
//{ "fs/smartfs", &smartfs_procfsoperations },
|
//{ "fs/smartfs", &smartfs_procfsoperations, PROCFS_DIR_TYPE },
|
||||||
{ "fs/smartfs**", &smartfs_procfsoperations },
|
{ "fs/smartfs**", &smartfs_procfsoperations, PROCFS_UNKOWN_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_NET) && !defined(CONFIG_FS_PROCFS_EXCLUDE_NET)
|
#if defined(CONFIG_NET) && !defined(CONFIG_FS_PROCFS_EXCLUDE_NET)
|
||||||
{ "net", &net_procfsoperations },
|
{ "net", &net_procfsoperations, PROCFS_DIR_TYPE },
|
||||||
{ "net/**", &net_procfsoperations },
|
#if defined(CONFIG_NET_ROUTE) && !defined(CONFIG_FS_PROCFS_EXCLUDE_ROUTE)
|
||||||
|
{ "net/route", &net_procfs_routeoperations, PROCFS_DIR_TYPE },
|
||||||
|
{ "net/route/**", &net_procfs_routeoperations, PROCFS_UNKOWN_TYPE },
|
||||||
|
#endif
|
||||||
|
{ "net/**", &net_procfsoperations, PROCFS_UNKOWN_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MTD) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MTD)
|
#if defined(CONFIG_MTD) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MTD)
|
||||||
{ "mtd", &mtd_procfsoperations },
|
{ "mtd", &mtd_procfsoperations, PROCFS_FILE_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MTD_PARTITION) && !defined(CONFIG_FS_PROCFS_EXCLUDE_PARTITIONS)
|
#if defined(CONFIG_MTD_PARTITION) && !defined(CONFIG_FS_PROCFS_EXCLUDE_PARTITIONS)
|
||||||
{ "partitions", &part_procfsoperations },
|
{ "partitions", &part_procfsoperations, PROCFS_DIR_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME)
|
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME)
|
||||||
{ "uptime", &uptime_operations },
|
{ "uptime", &uptime_operations, PROCFS_FILE_TYPE },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -348,6 +353,7 @@ static int procfs_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
|
|
||||||
((struct procfs_file_s *) filep->f_priv)->procfsentry =
|
((struct procfs_file_s *) filep->f_priv)->procfsentry =
|
||||||
&g_procfs_entries[x];
|
&g_procfs_entries[x];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -673,6 +679,7 @@ static int procfs_closedir(FAR struct inode *mountpt,
|
|||||||
|
|
||||||
static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||||
{
|
{
|
||||||
|
FAR const struct procfs_entry_s *entry = NULL;
|
||||||
FAR struct procfs_dir_priv_s *priv;
|
FAR struct procfs_dir_priv_s *priv;
|
||||||
FAR struct procfs_level0_s *level0;
|
FAR struct procfs_level0_s *level0;
|
||||||
FAR struct tcb_s *tcb;
|
FAR struct tcb_s *tcb;
|
||||||
@ -705,7 +712,9 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
|||||||
|
|
||||||
while (index < priv->nentries + g_procfs_entrycount)
|
while (index < priv->nentries + g_procfs_entrycount)
|
||||||
{
|
{
|
||||||
name = g_procfs_entries[index - priv->nentries].pathpattern;
|
entry = &g_procfs_entries[index - priv->nentries];
|
||||||
|
name = entry->pathpattern;
|
||||||
|
|
||||||
while (*name != '/' && *name != '\0')
|
while (*name != '/' && *name != '\0')
|
||||||
{
|
{
|
||||||
if (*name == '*' || *name == '[' || *name == '?')
|
if (*name == '*' || *name == '[' || *name == '?')
|
||||||
@ -772,7 +781,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
|||||||
strncpy(dir->fd_dir.d_name, name, level0->lastlen);
|
strncpy(dir->fd_dir.d_name, name, level0->lastlen);
|
||||||
dir->fd_dir.d_name[level0->lastlen] = '\0';
|
dir->fd_dir.d_name[level0->lastlen] = '\0';
|
||||||
|
|
||||||
if (name[level0->lastlen] == '/')
|
if (entry->type == PROCFS_DIR_TYPE)
|
||||||
{
|
{
|
||||||
dir->fd_dir.d_type = DTYPE_DIRECTORY;
|
dir->fd_dir.d_type = DTYPE_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,15 @@ struct procfs_operations
|
|||||||
|
|
||||||
/* Procfs handler prototypes ************************************************/
|
/* Procfs handler prototypes ************************************************/
|
||||||
|
|
||||||
|
/* These are the types of entries that may appear in the procfs: */
|
||||||
|
|
||||||
|
enum procfs_entry_e
|
||||||
|
{
|
||||||
|
PROCFS_UNKOWN_TYPE = 0, /* Unknown type */
|
||||||
|
PROCFS_FILE_TYPE, /* File type */
|
||||||
|
PROCFS_DIR_TYPE, /* Directory type */
|
||||||
|
};
|
||||||
|
|
||||||
/* This is a procfs entry that each handler should provide to supply
|
/* This is a procfs entry that each handler should provide to supply
|
||||||
* specific operations for file and directory handling.
|
* specific operations for file and directory handling.
|
||||||
*/
|
*/
|
||||||
@ -101,6 +110,7 @@ struct procfs_entry_s
|
|||||||
{
|
{
|
||||||
FAR const char *pathpattern;
|
FAR const char *pathpattern;
|
||||||
FAR const struct procfs_operations *ops;
|
FAR const struct procfs_operations *ops;
|
||||||
|
uint8_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Specifies the common elements for an open file in the procfs
|
/* Specifies the common elements for an open file in the procfs
|
||||||
|
@ -47,6 +47,12 @@ ifeq ($(CONFIG_NET_STATISTICS),y)
|
|||||||
NET_CSRCS += net_statistics.c
|
NET_CSRCS += net_statistics.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Routing table
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NET_ROUTE),y)
|
||||||
|
NET_CSRCS += net_procfs_route.c
|
||||||
|
endif
|
||||||
|
|
||||||
# Include packet socket build support
|
# Include packet socket build support
|
||||||
|
|
||||||
DEPPATH += --dep-path procfs
|
DEPPATH += --dep-path procfs
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
#include <nuttx/fs/procfs.h>
|
#include <nuttx/fs/procfs.h>
|
||||||
#include <nuttx/fs/dirent.h>
|
#include <nuttx/fs/dirent.h>
|
||||||
|
#include <nuttx/lib/regex.h>
|
||||||
#include <nuttx/net/netdev.h>
|
#include <nuttx/net/netdev.h>
|
||||||
|
|
||||||
#include "netdev/netdev.h"
|
#include "netdev/netdev.h"
|
||||||
@ -64,6 +65,26 @@
|
|||||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \
|
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \
|
||||||
!defined(CONFIG_FS_PROCFS_EXCLUDE_NET)
|
!defined(CONFIG_FS_PROCFS_EXCLUDE_NET)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Directory entry indices */
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_ROUTE)
|
||||||
|
# define STAT_INDEX 0
|
||||||
|
# define ROUTE_INDEX 1
|
||||||
|
# define DEV_INDEX 2
|
||||||
|
#elif defined(CONFIG_NET_STATISTICS)
|
||||||
|
# define STAT_INDEX 0
|
||||||
|
# define DEV_INDEX 1
|
||||||
|
#elif defined(CONFIG_NET_ROUTE)
|
||||||
|
# define ROUTE_INDEX 0
|
||||||
|
# define DEV_INDEX 1
|
||||||
|
#else
|
||||||
|
# define DEV_INDEX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -112,6 +133,8 @@ const struct procfs_operations net_procfsoperations =
|
|||||||
netprocfs_stat /* stat */
|
netprocfs_stat /* stat */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const struct procfs_operations net_procfs_routeoperations;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -125,6 +148,7 @@ static int netprocfs_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
{
|
{
|
||||||
FAR struct netprocfs_file_s *priv;
|
FAR struct netprocfs_file_s *priv;
|
||||||
FAR struct net_driver_s *dev;
|
FAR struct net_driver_s *dev;
|
||||||
|
enum netprocfs_entry_e entry;
|
||||||
|
|
||||||
finfo("Open '%s'\n", relpath);
|
finfo("Open '%s'\n", relpath);
|
||||||
|
|
||||||
@ -141,18 +165,29 @@ static int netprocfs_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
/* "net/stat" is an acceptable value for the relpath only if network layer
|
/* "net/stat" is an acceptable value for the relpath only if network layer
|
||||||
* statistics are enabled.
|
* statistics are enabled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
|
||||||
if (strcmp(relpath, "net/stat") == 0)
|
if (strcmp(relpath, "net/stat") == 0)
|
||||||
{
|
{
|
||||||
/* A NULL network device reference is a clue that we are processing
|
entry = NETPROCFS_SUBDIR_STAT;
|
||||||
* the network statistics file.
|
dev = NULL;
|
||||||
*/
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
dev = NULL;
|
#ifdef CONFIG_NET_ROUTE
|
||||||
|
/* "net/route" is an acceptable value for the relpath only if routing
|
||||||
|
* table support is initialized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (match("net/route/**", relpath))
|
||||||
|
{
|
||||||
|
/* Use the /net/route directory */
|
||||||
|
|
||||||
|
return net_procfs_routeoperations.open(filep, relpath, oflags, mode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -180,11 +215,14 @@ 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 */
|
||||||
|
|
||||||
priv = (FAR struct netprocfs_file_s *)kmm_zalloc(sizeof(struct netprocfs_file_s));
|
priv = (FAR struct netprocfs_file_s *)
|
||||||
|
kmm_zalloc(sizeof(struct netprocfs_file_s));
|
||||||
if (!priv)
|
if (!priv)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Failed to allocate file attributes\n");
|
ferr("ERROR: Failed to allocate file attributes\n");
|
||||||
@ -193,7 +231,8 @@ 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;
|
||||||
|
|
||||||
/* 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.
|
||||||
@ -240,24 +279,33 @@ static ssize_t netprocfs_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
priv = (FAR struct netprocfs_file_s *)filep->f_priv;
|
priv = (FAR struct netprocfs_file_s *)filep->f_priv;
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
/* Read according to the sub-directory */
|
||||||
/* A NULL device structure reference is the key that we are showing the
|
|
||||||
* network statistics.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (priv->dev == NULL)
|
switch (priv->entry)
|
||||||
{
|
{
|
||||||
/* Show the network layer statistics */
|
case NETPROCFS_SUBDIR_DEV:
|
||||||
|
/* Show device-specific statistics */
|
||||||
|
|
||||||
nreturned = netprocfs_read_netstats(priv, buffer, buflen);
|
nreturned = netprocfs_read_devstats(priv, buffer, buflen);
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
|
case NETPROCFS_SUBDIR_STAT:
|
||||||
|
/* Show the network layer statistics */
|
||||||
|
|
||||||
|
nreturned = netprocfs_read_netstats(priv, buffer, buflen);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
/* Otherwise, we are showing device-specific statistics */
|
|
||||||
|
|
||||||
nreturned = netprocfs_read_devstats(priv, buffer, buflen);
|
#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 */
|
||||||
|
|
||||||
@ -321,13 +369,56 @@ 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;
|
||||||
|
|
||||||
finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
|
finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
|
||||||
DEBUGASSERT(relpath && dir && !dir->u.procfs);
|
DEBUGASSERT(relpath && dir && !dir->u.procfs);
|
||||||
|
|
||||||
/* "net" is the only value of relpath that is a directory */
|
/* "net" and "net/route" are the only values of relpath that are
|
||||||
|
* directories.
|
||||||
|
*/
|
||||||
|
|
||||||
if (strcmp(relpath, "net") != 0)
|
#ifdef CONFIG_NET_ROUTE
|
||||||
|
if (match("net/route", relpath) || match("net/route/**", relpath))
|
||||||
|
{
|
||||||
|
/* Use the /net/route directory */
|
||||||
|
|
||||||
|
return net_procfs_routeoperations.opendir(relpath, dir);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Assume that path refers to the 1st level subdirectory. Allocate the
|
||||||
|
* level1 the dirent structure before checking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
level1 = (FAR struct netprocfs_level1_s *)
|
||||||
|
kmm_zalloc(sizeof(struct netprocfs_level1_s));
|
||||||
|
|
||||||
|
if (level1 == NULL)
|
||||||
|
{
|
||||||
|
ferr("ERROR: Failed to allocate the level1 directory structure\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
level1->base.level = 1;
|
||||||
|
|
||||||
|
if (strcmp(relpath, "net") == 0)
|
||||||
|
{
|
||||||
|
/* Count the number of network devices */
|
||||||
|
|
||||||
|
ndevs = netdev_count();
|
||||||
|
|
||||||
|
/* Initialze base structure components */
|
||||||
|
|
||||||
|
level1->base.nentries = ndevs;
|
||||||
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
|
level1->base.nentries++;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NET_ROUTE
|
||||||
|
level1->base.nentries++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* REVISIT: We really need to check if the relpath refers to a network
|
/* REVISIT: We really need to check if the relpath refers to a network
|
||||||
* device. In that case, we need to return -ENOTDIR. Otherwise, we
|
* device. In that case, we need to return -ENOTDIR. Otherwise, we
|
||||||
@ -335,38 +426,16 @@ static int netprocfs_opendir(FAR const char *relpath,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ferr("ERROR: Bad relpath: %s\n", relpath);
|
ferr("ERROR: Bad relpath: %s\n", relpath);
|
||||||
return -ENOTDIR;
|
ret = -ENOTDIR;
|
||||||
|
goto errout_with_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The path refers to the 1st level sbdirectory. Allocate the level1
|
dir->u.procfs = (FAR void *)level1;
|
||||||
* dirent structure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
level1 = (FAR struct netprocfs_level1_s *)
|
|
||||||
kmm_zalloc(sizeof(struct netprocfs_level1_s));
|
|
||||||
|
|
||||||
if (!level1)
|
|
||||||
{
|
|
||||||
ferr("ERROR: Failed to allocate the level1 directory structure\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count the number of network devices */
|
|
||||||
|
|
||||||
ndevs = netdev_count();
|
|
||||||
|
|
||||||
/* Initialze base structure components */
|
|
||||||
|
|
||||||
level1->base.level = 1;
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
|
||||||
level1->base.nentries = ndevs + 1;
|
|
||||||
#else
|
|
||||||
level1->base.nentries = ndevs;
|
|
||||||
#endif
|
|
||||||
level1->base.index = 0;
|
|
||||||
|
|
||||||
dir->u.procfs = (FAR void *) level1;
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
|
errout_with_alloc:
|
||||||
|
kmm_free(level1);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -404,63 +473,86 @@ static int netprocfs_readdir(FAR struct fs_dirent_s *dir)
|
|||||||
FAR struct netprocfs_level1_s *level1;
|
FAR struct netprocfs_level1_s *level1;
|
||||||
FAR struct net_driver_s *dev;
|
FAR struct net_driver_s *dev;
|
||||||
int index;
|
int index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(dir && dir->u.procfs);
|
DEBUGASSERT(dir && dir->u.procfs);
|
||||||
level1 = dir->u.procfs;
|
level1 = dir->u.procfs;
|
||||||
DEBUGASSERT(level1->base.level == 1);
|
DEBUGASSERT(level1->base.level > 0);
|
||||||
|
|
||||||
/* Have we reached the end of the directory */
|
/* Are we searching this directory? Or is it just an intermediate on the
|
||||||
|
* way to a sub-directory?
|
||||||
index = level1->base.index;
|
|
||||||
DEBUGASSERT(index <= level1->base.nentries);
|
|
||||||
|
|
||||||
if (index >= level1->base.nentries)
|
|
||||||
{
|
|
||||||
/* We signal the end of the directory by returning the special
|
|
||||||
* error -ENOENT.
|
|
||||||
*/
|
|
||||||
|
|
||||||
finfo("Entry %d: End of directory\n", index);
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
|
||||||
else if (index == 0)
|
|
||||||
{
|
|
||||||
/* Copy the network statistics directory entry */
|
|
||||||
|
|
||||||
dir->fd_dir.d_type = DTYPE_FILE;
|
|
||||||
strncpy(dir->fd_dir.d_name, "stat", NAME_MAX + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
int devndx = index;
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
|
||||||
/* Subtract one to account for index == 0 which is used for network
|
|
||||||
* status.
|
|
||||||
*/
|
|
||||||
|
|
||||||
devndx--;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Find the device corresponding to this device index */
|
|
||||||
|
|
||||||
dev = netdev_findbyindex(devndx);
|
|
||||||
|
|
||||||
/* Copy the device statistics file entry */
|
|
||||||
|
|
||||||
dir->fd_dir.d_type = DTYPE_FILE;
|
|
||||||
strncpy(dir->fd_dir.d_name, dev->d_ifname, NAME_MAX + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up the next directory entry offset. NOTE that we could use the
|
|
||||||
* standard f_pos instead of our own private index.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
level1->base.index = index + 1;
|
if (level1->base.level == 1)
|
||||||
return OK;
|
{
|
||||||
|
/* This directory.. Have we reached the end of the directory? */
|
||||||
|
|
||||||
|
index = level1->base.index;
|
||||||
|
DEBUGASSERT(index <= level1->base.nentries);
|
||||||
|
|
||||||
|
if (index >= level1->base.nentries)
|
||||||
|
{
|
||||||
|
/* We signal the end of the directory by returning the special
|
||||||
|
* error -ENOENT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
finfo("Entry %d: End of directory\n", index);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
|
else if (index == STAT_INDEX)
|
||||||
|
{
|
||||||
|
/* Copy the network statistics directory entry */
|
||||||
|
|
||||||
|
dir->fd_dir.d_type = DTYPE_FILE;
|
||||||
|
strncpy(dir->fd_dir.d_name, "stat", NAME_MAX + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NET_ROUTE
|
||||||
|
if (index == ROUTE_INDEX)
|
||||||
|
{
|
||||||
|
/* Copy the network statistics directory entry */
|
||||||
|
|
||||||
|
dir->fd_dir.d_type = DTYPE_DIRECTORY;
|
||||||
|
strncpy(dir->fd_dir.d_name, "route", NAME_MAX + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int devndx = index - DEV_INDEX;
|
||||||
|
|
||||||
|
/* Find the device corresponding to this device index */
|
||||||
|
|
||||||
|
dev = netdev_findbyindex(devndx);
|
||||||
|
|
||||||
|
/* Copy the device statistics file entry */
|
||||||
|
|
||||||
|
dir->fd_dir.d_type = DTYPE_FILE;
|
||||||
|
strncpy(dir->fd_dir.d_name, dev->d_ifname, NAME_MAX + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the next directory entry offset. NOTE that we could use the
|
||||||
|
* standard f_pos instead of our own private index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
level1->base.index = index + 1;
|
||||||
|
ret = OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We are performing a directory search of one of the subdirectories
|
||||||
|
* and we must let the handler perform the read.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DEBUGASSERT(level1->base.procfsentry != NULL &&
|
||||||
|
level1->base.procfsentry->ops->readdir != NULL);
|
||||||
|
|
||||||
|
ret = level1->base.procfsentry->ops->readdir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -505,6 +597,15 @@ static int netprocfs_stat(FAR const char *relpath, FAR struct stat *buf)
|
|||||||
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
|
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
FAR struct net_driver_s *dev;
|
FAR struct net_driver_s *dev;
|
||||||
|
@ -82,7 +82,7 @@ static int netprocfs_retransmissions(FAR struct netprocfs_file_s *netfile);
|
|||||||
|
|
||||||
/* Line generating functions */
|
/* Line generating functions */
|
||||||
|
|
||||||
static const linegen_t g_linegen[] =
|
static const linegen_t g_stat_linegen[] =
|
||||||
{
|
{
|
||||||
netprocfs_header,
|
netprocfs_header,
|
||||||
netprocfs_received,
|
netprocfs_received,
|
||||||
@ -111,7 +111,7 @@ static const linegen_t g_linegen[] =
|
|||||||
#endif /* CONFIG_NET_TCP */
|
#endif /* CONFIG_NET_TCP */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NSTAT_LINES (sizeof(g_linegen) / sizeof(linegen_t))
|
#define NSTAT_LINES (sizeof(g_stat_linegen) / sizeof(linegen_t))
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -456,7 +456,7 @@ static int netprocfs_retransmissions(FAR struct netprocfs_file_s *netfile)
|
|||||||
ssize_t netprocfs_read_netstats(FAR struct netprocfs_file_s *priv,
|
ssize_t netprocfs_read_netstats(FAR struct netprocfs_file_s *priv,
|
||||||
FAR char *buffer, size_t buflen)
|
FAR char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
return netprocfs_read_linegen(priv, buffer, buflen, g_linegen, NSTAT_LINES);
|
return netprocfs_read_linegen(priv, buffer, buflen, g_stat_linegen, NSTAT_LINES);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS &&
|
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS &&
|
||||||
|
@ -84,7 +84,7 @@ static int netprocfs_errors(FAR struct netprocfs_file_s *netfile);
|
|||||||
|
|
||||||
/* Line generating functions */
|
/* Line generating functions */
|
||||||
|
|
||||||
static const linegen_t g_linegen[] =
|
static const linegen_t g_netstat_linegen[] =
|
||||||
{
|
{
|
||||||
netprocfs_linklayer
|
netprocfs_linklayer
|
||||||
#ifdef CONFIG_NET_IPv4
|
#ifdef CONFIG_NET_IPv4
|
||||||
@ -105,7 +105,7 @@ static const linegen_t g_linegen[] =
|
|||||||
#endif /* CONFIG_NETDEV_STATISTICS */
|
#endif /* CONFIG_NETDEV_STATISTICS */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NSTAT_LINES (sizeof(g_linegen) / sizeof(linegen_t))
|
#define NSTAT_LINES (sizeof(g_netstat_linegen) / sizeof(linegen_t))
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -554,7 +554,8 @@ static int netprocfs_errors(FAR struct netprocfs_file_s *netfile)
|
|||||||
ssize_t netprocfs_read_devstats(FAR struct netprocfs_file_s *priv,
|
ssize_t netprocfs_read_devstats(FAR struct netprocfs_file_s *priv,
|
||||||
FAR char *buffer, size_t buflen)
|
FAR char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
return netprocfs_read_linegen(priv, buffer, buflen, g_linegen, NSTAT_LINES);
|
return netprocfs_read_linegen(priv, buffer, buflen, g_netstat_linegen,
|
||||||
|
NSTAT_LINES);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS &&
|
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS &&
|
||||||
|
@ -50,6 +50,10 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_FS_PROCFS_EXCLUDE_ROUTE
|
||||||
|
# undef CONFIG_NET_ROUTE
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Determines the size of an intermediate buffer that must be large enough
|
/* Determines the size of an intermediate buffer that must be large enough
|
||||||
* to handle the longest line generated by this logic.
|
* to handle the longest line generated by this logic.
|
||||||
*/
|
*/
|
||||||
@ -60,6 +64,19 @@
|
|||||||
* 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 */
|
||||||
|
#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 */
|
||||||
@ -70,6 +87,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 */
|
||||||
char line[NET_LINELEN]; /* Pre-allocated buffer for formatted lines */
|
char line[NET_LINELEN]; /* Pre-allocated buffer for formatted lines */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -148,6 +166,29 @@ ssize_t netprocfs_read_netstats(FAR struct netprocfs_file_s *priv,
|
|||||||
FAR char *buffer, size_t buflen);
|
FAR char *buffer, size_t buflen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netprocfs_read_routes
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Read and format routing table entries.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* priv - A reference to the network procfs file structure
|
||||||
|
* buffer - The user-provided buffer into which network status will be
|
||||||
|
* returned.
|
||||||
|
* bulen - The size in bytes of the user provided buffer.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) is returned on success; a negated errno value is returned
|
||||||
|
* on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_ROUTE
|
||||||
|
ssize_t netprocfs_read_routes(FAR struct netprocfs_file_s *priv,
|
||||||
|
FAR char *buffer, size_t buflen);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: netprocfs_read_devstats
|
* Name: netprocfs_read_devstats
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user