mirror of https://github.com/F-Stack/f-stack.git
Add tool: sysctl.
This commit contains an ipc library implemented by dpdk rte_ring and sysctl tool ported from FreeBSD. With this commit we can get and set FreeBSD kernel state in runtime.
This commit is contained in:
parent
7d25ffc210
commit
7abd0fb2a9
|
@ -33,7 +33,7 @@ CORE_LIBS+=" -g -Wl,--no-as-needed -fvisibility=default -pthread -lm -lrt"
|
||||||
CORE_LIBS+=" -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring"
|
CORE_LIBS+=" -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring"
|
||||||
CORE_LIBS+=" -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool"
|
CORE_LIBS+=" -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool"
|
||||||
CORE_LIBS+=" -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio"
|
CORE_LIBS+=" -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio"
|
||||||
CORE_LIBS+=" -Wl,--no-whole-archive -lrt -lm -ldl -lm -lcrypto"
|
CORE_LIBS+=" -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto"
|
||||||
|
|
||||||
cat << END > $NGX_MAKEFILE
|
cat << END > $NGX_MAKEFILE
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
|
TOPDIR=..
|
||||||
|
|
||||||
|
ifeq ($(FF_PATH),)
|
||||||
|
FF_PATH=${TOPDIR}
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(FF_DPDK),)
|
||||||
|
FF_DPDK=${TOPDIR}/dpdk/x86_64-native-linuxapp-gcc
|
||||||
|
endif
|
||||||
|
|
||||||
LIBS+= -L${FF_PATH}/lib -L${FF_DPDK}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive
|
LIBS+= -L${FF_PATH}/lib -L${FF_DPDK}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive
|
||||||
LIBS+= -g -Wl,--no-as-needed -fvisibility=default -pthread -lm -lrt
|
LIBS+= -g -Wl,--no-as-needed -fvisibility=default -pthread -lm -lrt
|
||||||
LIBS+= -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring
|
LIBS+= -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring
|
||||||
LIBS+= -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool
|
LIBS+= -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool
|
||||||
LIBS+= -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio
|
LIBS+= -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio
|
||||||
LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lm -lcrypto
|
LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto
|
||||||
|
|
||||||
TARGET="helloworld"
|
TARGET="helloworld"
|
||||||
all:
|
all:
|
||||||
|
|
163
lib/ff_dpdk_if.c
163
lib/ff_dpdk_if.c
|
@ -55,11 +55,15 @@
|
||||||
#include "ff_config.h"
|
#include "ff_config.h"
|
||||||
#include "ff_veth.h"
|
#include "ff_veth.h"
|
||||||
#include "ff_host_interface.h"
|
#include "ff_host_interface.h"
|
||||||
|
#include "ff_msg.h"
|
||||||
|
#include "ff_api.h"
|
||||||
|
|
||||||
#define MEMPOOL_CACHE_SIZE 256
|
#define MEMPOOL_CACHE_SIZE 256
|
||||||
|
|
||||||
#define ARP_RING_SIZE 2048
|
#define ARP_RING_SIZE 2048
|
||||||
|
|
||||||
|
#define MSG_RING_SIZE 32
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configurable number of RX/TX ring descriptors
|
* Configurable number of RX/TX ring descriptors
|
||||||
*/
|
*/
|
||||||
|
@ -153,6 +157,16 @@ static struct rte_mempool *pktmbuf_pool[NB_SOCKETS];
|
||||||
|
|
||||||
static struct rte_ring **arp_ring[RTE_MAX_LCORE];
|
static struct rte_ring **arp_ring[RTE_MAX_LCORE];
|
||||||
|
|
||||||
|
struct ff_msg_ring {
|
||||||
|
char ring_name[2][RTE_RING_NAMESIZE];
|
||||||
|
/* ring[0] for lcore recv msg, other send */
|
||||||
|
/* ring[1] for lcore send msg, other read */
|
||||||
|
struct rte_ring *ring[2];
|
||||||
|
} __rte_cache_aligned;
|
||||||
|
|
||||||
|
static struct ff_msg_ring msg_ring[RTE_MAX_LCORE];
|
||||||
|
static struct rte_mempool *message_pool;
|
||||||
|
|
||||||
struct ff_dpdk_if_context {
|
struct ff_dpdk_if_context {
|
||||||
void *sc;
|
void *sc;
|
||||||
void *ifp;
|
void *ifp;
|
||||||
|
@ -441,6 +455,25 @@ init_mem_pool(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rte_ring *
|
||||||
|
create_ring(const char *name, unsigned count, int socket_id, unsigned flags)
|
||||||
|
{
|
||||||
|
struct rte_ring *ring;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* If already create, just attached it */
|
||||||
|
if (likely((ring = rte_ring_lookup(name)) != NULL))
|
||||||
|
return ring;
|
||||||
|
|
||||||
|
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
|
||||||
|
return rte_ring_create(name, count, socket_id, flags);
|
||||||
|
} else {
|
||||||
|
return rte_ring_lookup(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_arp_ring(void)
|
init_arp_ring(void)
|
||||||
{
|
{
|
||||||
|
@ -472,21 +505,14 @@ init_arp_ring(void)
|
||||||
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[j].port_id;
|
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[j].port_id;
|
||||||
|
|
||||||
for(i = 0; i < nb_procs; ++i) {
|
for(i = 0; i < nb_procs; ++i) {
|
||||||
snprintf(name_buf, RTE_RING_NAMESIZE, "ring_%d_%d", i, port_id);
|
snprintf(name_buf, RTE_RING_NAMESIZE, "arp_ring_%d_%d", i, port_id);
|
||||||
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
|
arp_ring[i][port_id] = create_ring(name_buf, ARP_RING_SIZE,
|
||||||
arp_ring[i][port_id] = rte_ring_create(name_buf,
|
socketid, RING_F_SC_DEQ);
|
||||||
ARP_RING_SIZE, socketid,
|
|
||||||
RING_F_SC_DEQ);
|
|
||||||
if (rte_ring_lookup(name_buf) != arp_ring[i][port_id])
|
|
||||||
rte_panic("lookup arp ring:%s failed!\n", name_buf);
|
|
||||||
} else {
|
|
||||||
arp_ring[i][port_id] = rte_ring_lookup(name_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arp_ring[i][port_id] == NULL)
|
if (arp_ring[i][port_id] == NULL)
|
||||||
rte_panic("create arp ring::%s failed!\n", name_buf);
|
rte_panic("create ring:%s failed!\n", name_buf);
|
||||||
|
|
||||||
printf("create arp ring:%s success, %u ring entries are now free!\n",
|
printf("create ring:%s success, %u ring entries are now free!\n",
|
||||||
name_buf, rte_ring_free_count(arp_ring[i][port_id]));
|
name_buf, rte_ring_free_count(arp_ring[i][port_id]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,6 +520,58 @@ init_arp_ring(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ff_msg_init(struct rte_mempool *mp,
|
||||||
|
__attribute__((unused)) void *opaque_arg,
|
||||||
|
void *obj, __attribute__((unused)) unsigned i)
|
||||||
|
{
|
||||||
|
struct ff_msg *msg = (struct ff_msg *)obj;
|
||||||
|
msg->buf_addr = (char *)msg + sizeof(struct ff_msg);
|
||||||
|
msg->buf_len = mp->elt_size - sizeof(struct ff_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_msg_ring(void)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint16_t nb_procs = ff_global_cfg.dpdk.nb_procs;
|
||||||
|
unsigned socketid = lcore_conf.socket_id;
|
||||||
|
|
||||||
|
/* Create message buffer pool */
|
||||||
|
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
|
||||||
|
message_pool = rte_mempool_create(FF_MSG_POOL,
|
||||||
|
MSG_RING_SIZE * 2 * nb_procs,
|
||||||
|
MAX_MSG_BUF_SIZE, MSG_RING_SIZE / 2, 0,
|
||||||
|
NULL, NULL, ff_msg_init, NULL,
|
||||||
|
socketid, 0);
|
||||||
|
} else {
|
||||||
|
message_pool = rte_mempool_lookup(FF_MSG_POOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message_pool == NULL) {
|
||||||
|
rte_panic("Create msg mempool failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < nb_procs; ++i) {
|
||||||
|
snprintf(msg_ring[i].ring_name[0], RTE_RING_NAMESIZE,
|
||||||
|
"%s%u", FF_MSG_RING_IN, i);
|
||||||
|
snprintf(msg_ring[i].ring_name[1], RTE_RING_NAMESIZE,
|
||||||
|
"%s%u", FF_MSG_RING_OUT, i);
|
||||||
|
|
||||||
|
msg_ring[i].ring[0] = create_ring(msg_ring[i].ring_name[0],
|
||||||
|
MSG_RING_SIZE, socketid, RING_F_SP_ENQ | RING_F_SC_DEQ);
|
||||||
|
if (msg_ring[i].ring[0] == NULL)
|
||||||
|
rte_panic("create ring::%s failed!\n", msg_ring[i].ring_name[0]);
|
||||||
|
|
||||||
|
msg_ring[i].ring[1] = create_ring(msg_ring[i].ring_name[1],
|
||||||
|
MSG_RING_SIZE, socketid, RING_F_SP_ENQ | RING_F_SC_DEQ);
|
||||||
|
if (msg_ring[i].ring[1] == NULL)
|
||||||
|
rte_panic("create ring::%s failed!\n", msg_ring[i].ring_name[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_kni(void)
|
init_kni(void)
|
||||||
{
|
{
|
||||||
|
@ -730,6 +808,8 @@ ff_dpdk_init(int argc, char **argv)
|
||||||
|
|
||||||
init_arp_ring();
|
init_arp_ring();
|
||||||
|
|
||||||
|
init_msg_ring();
|
||||||
|
|
||||||
enable_kni = ff_global_cfg.kni.enable;
|
enable_kni = ff_global_cfg.kni.enable;
|
||||||
if (enable_kni) {
|
if (enable_kni) {
|
||||||
init_kni();
|
init_kni();
|
||||||
|
@ -872,12 +952,61 @@ process_arp_ring(uint8_t port_id, uint16_t queue_id,
|
||||||
struct rte_mbuf **pkts_burst, const struct ff_dpdk_if_context *ctx)
|
struct rte_mbuf **pkts_burst, const struct ff_dpdk_if_context *ctx)
|
||||||
{
|
{
|
||||||
/* read packet from ring buf and to process */
|
/* read packet from ring buf and to process */
|
||||||
uint16_t nb_tx;
|
uint16_t nb_rb;
|
||||||
nb_tx = rte_ring_dequeue_burst(arp_ring[queue_id][port_id],
|
nb_rb = rte_ring_dequeue_burst(arp_ring[queue_id][port_id],
|
||||||
(void **)pkts_burst, MAX_PKT_BURST);
|
(void **)pkts_burst, MAX_PKT_BURST);
|
||||||
|
|
||||||
if(nb_tx > 0) {
|
if(nb_rb > 0) {
|
||||||
process_packets(port_id, queue_id, pkts_burst, nb_tx, ctx, 1);
|
process_packets(port_id, queue_id, pkts_burst, nb_rb, ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
handle_sysctl_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
int ret = ff_sysctl(msg->sysctl.name, msg->sysctl.namelen,
|
||||||
|
msg->sysctl.old, msg->sysctl.oldlenp, msg->sysctl.new,
|
||||||
|
msg->sysctl.newlen);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
msg->result = errno;
|
||||||
|
} else {
|
||||||
|
msg->result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
handle_default_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
msg->result = EINVAL;
|
||||||
|
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
handle_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
switch (msg->msg_type) {
|
||||||
|
case FF_SYSCTL:
|
||||||
|
handle_sysctl_msg(msg, proc_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handle_default_msg(msg, proc_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
process_msg_ring(uint16_t proc_id)
|
||||||
|
{
|
||||||
|
void *msg;
|
||||||
|
int ret = rte_ring_dequeue(msg_ring[proc_id].ring[0], &msg);
|
||||||
|
|
||||||
|
if (unlikely(ret == 0)) {
|
||||||
|
handle_msg((struct ff_msg *)msg, proc_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1104,6 +1233,8 @@ main_loop(void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process_msg_ring(qconf->proc_id);
|
||||||
|
|
||||||
if (likely(lr->loop != NULL)) {
|
if (likely(lr->loop != NULL)) {
|
||||||
lr->loop(lr->arg);
|
lr->loop(lr->arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,6 +383,9 @@ ff_kni_alloc(uint8_t port_id, unsigned socket_id,
|
||||||
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
|
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
|
||||||
kni_rp[port_id] = rte_ring_create(ring_name, KNI_QUEUE_SIZE,
|
kni_rp[port_id] = rte_ring_create(ring_name, KNI_QUEUE_SIZE,
|
||||||
socket_id, RING_F_SC_DEQ);
|
socket_id, RING_F_SC_DEQ);
|
||||||
|
|
||||||
|
if (rte_ring_lookup(ring_name) != kni_rp[port_id])
|
||||||
|
rte_panic("lookup kni ring failed!\n");
|
||||||
} else {
|
} else {
|
||||||
kni_rp[port_id] = rte_ring_lookup(ring_name);
|
kni_rp[port_id] = rte_ring_lookup(ring_name);
|
||||||
}
|
}
|
||||||
|
@ -390,9 +393,6 @@ ff_kni_alloc(uint8_t port_id, unsigned socket_id,
|
||||||
if (kni_rp[port_id] == NULL)
|
if (kni_rp[port_id] == NULL)
|
||||||
rte_panic("create kni ring failed!\n");
|
rte_panic("create kni ring failed!\n");
|
||||||
|
|
||||||
if (rte_ring_lookup(ring_name) != kni_rp[port_id])
|
|
||||||
rte_panic("lookup kni ring failed!\n");
|
|
||||||
|
|
||||||
printf("create kni ring success, %u ring entries are now free!\n",
|
printf("create kni ring success, %u ring entries are now free!\n",
|
||||||
rte_ring_free_count(kni_rp[port_id]));
|
rte_ring_free_count(kni_rp[port_id]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FF_MSG_H_
|
||||||
|
#define _FF_MSG_H_
|
||||||
|
|
||||||
|
#include <rte_memory.h>
|
||||||
|
|
||||||
|
#define FF_MSG_RING_IN "ff_msg_ring_in_"
|
||||||
|
#define FF_MSG_RING_OUT "ff_msg_ring_out_"
|
||||||
|
#define FF_MSG_POOL "ff_msg_pool"
|
||||||
|
|
||||||
|
/* MSG TYPE: sysctl, sysctlbyname, etc.. */
|
||||||
|
enum FF_MSG_TYPE {
|
||||||
|
FF_UNKNOWN = 0,
|
||||||
|
FF_SYSCTL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ff_sysctl_args {
|
||||||
|
int *name;
|
||||||
|
unsigned namelen;
|
||||||
|
void *old;
|
||||||
|
size_t *oldlenp;
|
||||||
|
void *new;
|
||||||
|
size_t newlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_MSG_BUF_SIZE 10240
|
||||||
|
|
||||||
|
/* structure of ipc msg */
|
||||||
|
struct ff_msg {
|
||||||
|
enum FF_MSG_TYPE msg_type;
|
||||||
|
/* Result of msg processing */
|
||||||
|
int result;
|
||||||
|
/* Length of segment buffer. */
|
||||||
|
uint16_t buf_len;
|
||||||
|
/* Address of segment buffer. */
|
||||||
|
char *buf_addr;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct ff_sysctl_args sysctl;
|
||||||
|
};
|
||||||
|
} __attribute__((packed)) __rte_cache_aligned;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,7 @@
|
||||||
|
SUBDIRS=ipc sysctl
|
||||||
|
|
||||||
|
all:
|
||||||
|
for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done
|
||||||
|
|
||||||
|
clean:
|
||||||
|
for d in $(SUBDIRS); do ( cd $$d; $(MAKE) clean ) ; done
|
|
@ -0,0 +1,120 @@
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
Directory `ipc` implements an ipc library using dpdk `rte_ring`, can be used to communicate with F-Stack processes.
|
||||||
|
|
||||||
|
All other directories are useful tools ported from FreeBSD.
|
||||||
|
|
||||||
|
# ipc
|
||||||
|
|
||||||
|
This is a simple implemention using dpdk `rte_ring`.
|
||||||
|
`ff_ipc_msg_alloc` get msg structure from rte_mempool.
|
||||||
|
`ff_ipc_msg_free` put msg to rte_mempool.
|
||||||
|
`ff_ipc_send` enqueue msg to rte_ring.
|
||||||
|
`ff_ipc_recv` dequeue msg from rte_ring.
|
||||||
|
|
||||||
|
Since F-Stack is multi-process architecture and every process has an independent stack, so we must communicate with every F-Stack process.
|
||||||
|
|
||||||
|
# sysctl
|
||||||
|
Usage:
|
||||||
|
`sysctl -p <f-stack proc_id> [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...`
|
||||||
|
`sysctl -p <f-stack proc_id> [-bdehNnoqTtWx] [ -B <bufsize> ] -a`
|
||||||
|
|
||||||
|
-p Which F-Stack process to communicate with, default 0.
|
||||||
|
|
||||||
|
Except this option, it is same with the original FreeBSD sysctl, see [Manual page](https://www.freebsd.org/cgi/man.cgi?sysctl).
|
||||||
|
|
||||||
|
# how to implement a custom tool for communicating with F-Stack process
|
||||||
|
|
||||||
|
Add a new FF_MSG_TYPE in ff_msg.h:
|
||||||
|
```
|
||||||
|
enum FF_MSG_TYPE {
|
||||||
|
FF_UNKNOWN = 0,
|
||||||
|
FF_SYSCTL,
|
||||||
|
FF_HELLOWORLD,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Define a structure used to communicate:
|
||||||
|
```
|
||||||
|
struct ff_helloworld_args {
|
||||||
|
void *request;
|
||||||
|
size_t req_len;
|
||||||
|
void *reply;
|
||||||
|
size_t rep_len;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
Note that, when using struct ff_helloworld_args, pointers in this structure must point to the addresses range from ff_msg.buf_addr and ff_msg.buf_addr+ff_msg.buf_len, ff_msg.buf_len is (10240 - sizeof(struct ff_msg)).
|
||||||
|
|
||||||
|
And add it to ff_msg:
|
||||||
|
```
|
||||||
|
struct ff_msg {
|
||||||
|
...
|
||||||
|
union {
|
||||||
|
struct ff_sysctl_args sysctl;
|
||||||
|
struct ff_helloworld_args helloworld;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Modify ff_dpdk_if.c, add a handle function:
|
||||||
|
```
|
||||||
|
static inline void
|
||||||
|
handle_helloworld_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
printf("helloworld msg recved.\n");
|
||||||
|
msg->result = 0;
|
||||||
|
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
handle_msg(struct ff_msg *msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
switch (msg->msg_type) {
|
||||||
|
case FF_SYSCTL:
|
||||||
|
handle_sysctl_msg(msg, proc_id);
|
||||||
|
break;
|
||||||
|
case FF_HELLOWORLD:
|
||||||
|
handle_helloworld_msg(msg, proc_id);
|
||||||
|
default:
|
||||||
|
handle_default_msg(msg, proc_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create helloworld.c:
|
||||||
|
|
||||||
|
```
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct ff_msg *msg = ff_ipc_msg_alloc();
|
||||||
|
|
||||||
|
char *buf = msg->buf_addr;
|
||||||
|
|
||||||
|
msg->helloworld.request = buf;
|
||||||
|
memcpy(msg->helloworld.request, "hello", 5);
|
||||||
|
msg->helloworld.req_len = 5;
|
||||||
|
buf += 5;
|
||||||
|
|
||||||
|
msg->helloworld.reply = buf;
|
||||||
|
msg->helloworld.rep_len = 10;
|
||||||
|
|
||||||
|
ff_ipc_send(msg, 0);
|
||||||
|
|
||||||
|
struct ff_msg *retmsg;
|
||||||
|
ff_ipc_recv(retmsg, 0);
|
||||||
|
assert(remsg==msg);
|
||||||
|
|
||||||
|
ff_ipc_msg_free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The Makefile may like this:
|
||||||
|
```
|
||||||
|
TOPDIR?=${CURDIR}/../..
|
||||||
|
|
||||||
|
PROG=helloworld
|
||||||
|
|
||||||
|
include ${TOPDIR}/tools/prog.mk
|
||||||
|
```
|
|
@ -0,0 +1,32 @@
|
||||||
|
TOPDIR?=${CURDIR}/../..
|
||||||
|
|
||||||
|
ifeq ($(FF_DPDK),)
|
||||||
|
FF_DPDK=${TOPDIR}/dpdk/x86_64-native-linuxapp-gcc
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGET=libfstack_ipc.a
|
||||||
|
|
||||||
|
DPDK_CFLAGS= -g -Wall -Werror -include ${FF_DPDK}/include/rte_config.h
|
||||||
|
DPDK_CFLAGS+= -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
|
||||||
|
DPDK_CFLAGS+= -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
|
||||||
|
DPDK_CFLAGS+= -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2
|
||||||
|
DPDK_CFLAGS+= -I${FF_DPDK}/include
|
||||||
|
|
||||||
|
CFLAGS+= ${DPDK_CFLAGS}
|
||||||
|
CFLAGS+= -I${TOPDIR}/lib
|
||||||
|
|
||||||
|
SRCS=ff_ipc.c
|
||||||
|
OBJS=$(patsubst %.c,%.o,${SRCS})
|
||||||
|
|
||||||
|
all: ${TARGET}
|
||||||
|
|
||||||
|
${TARGET}: ${OBJS}
|
||||||
|
ar -cqs $@ ${OBJS}
|
||||||
|
|
||||||
|
${OBJS}: %.o: %.c
|
||||||
|
${CC} -c $< ${CFLAGS} -o $@
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f *.o ${TARGET}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rte_common.h>
|
||||||
|
#include <rte_memory.h>
|
||||||
|
#include <rte_config.h>
|
||||||
|
#include <rte_eal.h>
|
||||||
|
#include <rte_ring.h>
|
||||||
|
#include <rte_mempool.h>
|
||||||
|
#include <rte_malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "ff_ipc.h"
|
||||||
|
|
||||||
|
static int inited;
|
||||||
|
|
||||||
|
static struct rte_mempool *message_pool;
|
||||||
|
|
||||||
|
static int
|
||||||
|
ff_ipc_init(void)
|
||||||
|
{
|
||||||
|
if (inited) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dpdk_argv[] = {
|
||||||
|
"-c1", "-n4",
|
||||||
|
"--proc-type=secondary",
|
||||||
|
"--log-level=0",
|
||||||
|
};
|
||||||
|
|
||||||
|
int ret = rte_eal_init(sizeof(dpdk_argv)/sizeof(dpdk_argv[0]), dpdk_argv);
|
||||||
|
if (ret < 0) {
|
||||||
|
rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
message_pool = rte_mempool_lookup(FF_MSG_POOL);
|
||||||
|
if (message_pool == NULL) {
|
||||||
|
rte_exit(EXIT_FAILURE, "lookup message pool:%s failed!\n", FF_MSG_POOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inited = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ff_msg *
|
||||||
|
ff_ipc_msg_alloc(void)
|
||||||
|
{
|
||||||
|
if (inited == 0) {
|
||||||
|
int ret = ff_ipc_init();
|
||||||
|
if (ret < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *msg;
|
||||||
|
if (rte_mempool_get(message_pool, &msg) < 0) {
|
||||||
|
printf("get buffer from message pool failed.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (struct ff_msg *)msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ff_ipc_msg_free(struct ff_msg *msg)
|
||||||
|
{
|
||||||
|
if (inited == 0) {
|
||||||
|
printf("ff ipc not inited\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_mempool_put(message_pool, msg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ff_ipc_send(const struct ff_msg *msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (inited == 0) {
|
||||||
|
printf("ff ipc not inited\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[RTE_RING_NAMESIZE];
|
||||||
|
snprintf(name, RTE_RING_NAMESIZE, "%s%u",
|
||||||
|
FF_MSG_RING_IN, proc_id);
|
||||||
|
struct rte_ring *ring = rte_ring_lookup(name);
|
||||||
|
if (ring == NULL) {
|
||||||
|
printf("lookup message ring:%s failed!\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rte_ring_enqueue(ring, (void *)msg);
|
||||||
|
if (ret < 0) {
|
||||||
|
printf("ff_ipc_send failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ff_ipc_recv(struct ff_msg **msg, uint16_t proc_id)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
if (inited == 0) {
|
||||||
|
printf("ff ipc not inited\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[RTE_RING_NAMESIZE];
|
||||||
|
snprintf(name, RTE_RING_NAMESIZE, "%s%u",
|
||||||
|
FF_MSG_RING_OUT, proc_id);
|
||||||
|
struct rte_ring *ring = rte_ring_lookup(name);
|
||||||
|
if (ring == NULL) {
|
||||||
|
printf("lookup message ring:%s failed!\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *obj;
|
||||||
|
#define MAX_ATTEMPTS_NUM 1000
|
||||||
|
for (i = 0; i < MAX_ATTEMPTS_NUM; i++) {
|
||||||
|
ret = rte_ring_dequeue(ring, &obj);
|
||||||
|
if (ret == 0) {
|
||||||
|
*msg = (struct ff_msg *)obj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FF_IPC_H_
|
||||||
|
#define _FF_IPC_H_
|
||||||
|
|
||||||
|
#include "ff_msg.h"
|
||||||
|
|
||||||
|
struct ff_msg *ff_ipc_msg_alloc(void);
|
||||||
|
int ff_ipc_msg_free(struct ff_msg *msg);
|
||||||
|
|
||||||
|
int ff_ipc_send(const struct ff_msg *msg, uint16_t proc_id);
|
||||||
|
int ff_ipc_recv(struct ff_msg **msg, uint16_t proc_id);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,71 @@
|
||||||
|
#
|
||||||
|
# Derived from FreeBSD src/share/mk/bsd.prog.mk
|
||||||
|
#
|
||||||
|
|
||||||
|
ifdef DEBUG_FLAGS
|
||||||
|
CFLAGS+=${DEBUG_FLAGS}
|
||||||
|
CXXFLAGS+=${DEBUG_FLAGS}
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef NO_SHARED
|
||||||
|
ifneq (${NO_SHARED},no)
|
||||||
|
ifneq (${NO_SHARED},NO)
|
||||||
|
LDFLAGS+= -static
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef PROG_CXX
|
||||||
|
PROG= ${PROG_CXX}
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef PROG
|
||||||
|
$(error PROG or PROG_CXX must be defined.)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef TOPDIR
|
||||||
|
$(error TOPDIR must be defined.)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef SRCS
|
||||||
|
ifdef PROG_CXX
|
||||||
|
SRCS= ${PROG}.cc
|
||||||
|
else
|
||||||
|
SRCS= ${PROG}.c
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
OBJS+= $(patsubst %.cc,%.o,$(patsubst %.c,%.o,${SRCS}))
|
||||||
|
|
||||||
|
ifeq ($(FF_DPDK),)
|
||||||
|
FF_DPDK=${TOPDIR}/dpdk/x86_64-native-linuxapp-gcc
|
||||||
|
endif
|
||||||
|
|
||||||
|
FF_PROG_CFLAGS:= -g -Wall -Werror -DFSTACK
|
||||||
|
FF_PROG_CFLAGS+= -I${TOPDIR}/lib -I${TOPDIR}/tools/ipc
|
||||||
|
FF_PROG_CFLAGS+= -include ${FF_DPDK}/include/rte_config.h
|
||||||
|
FF_PROG_CFLAGS+= -I${FF_DPDK}/include
|
||||||
|
|
||||||
|
FF_PROG_LIBS:= -L${TOPDIR}/tools/ipc -lfstack_ipc
|
||||||
|
FF_PROG_LIBS+= -L${FF_DPDK}/lib
|
||||||
|
FF_PROG_LIBS+= -g -Wl,--no-as-needed -fvisibility=default -pthread -lm -lrt
|
||||||
|
FF_PROG_LIBS+= -Wl,--whole-archive -lrte_eal -Wl,-lrte_mempool -lrte_ring
|
||||||
|
FF_PROG_LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto
|
||||||
|
|
||||||
|
CFLAGS+= ${FF_PROG_CFLAGS}
|
||||||
|
CXXFLAGS+= ${FF_PROG_CFLAGS}
|
||||||
|
|
||||||
|
LIBS+= ${FF_PROG_LIBS}
|
||||||
|
|
||||||
|
${PROG}: ${OBJS}
|
||||||
|
ifdef PROG_CXX
|
||||||
|
${CXX} ${CXXFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
|
||||||
|
else
|
||||||
|
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f ${PROG} ${OBJS}
|
||||||
|
|
||||||
|
all: ${PROG}
|
|
@ -0,0 +1,5 @@
|
||||||
|
TOPDIR?=${CURDIR}/../..
|
||||||
|
|
||||||
|
PROG=sysctl
|
||||||
|
|
||||||
|
include ${TOPDIR}/tools/prog.mk
|
|
@ -0,0 +1,326 @@
|
||||||
|
.\" Copyright (c) 1993
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 4. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd December 10, 2015
|
||||||
|
.Dt SYSCTL 8
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm sysctl
|
||||||
|
.Nd get or set kernel state
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl bdehiNnoRTtqx
|
||||||
|
.Op Fl B Ar bufsize
|
||||||
|
.Op Fl f Ar filename
|
||||||
|
.Ar name Ns Op = Ns Ar value
|
||||||
|
.Ar ...
|
||||||
|
.Nm
|
||||||
|
.Op Fl bdehNnoRTtqx
|
||||||
|
.Op Fl B Ar bufsize
|
||||||
|
.Fl a
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility retrieves kernel state and allows processes with appropriate
|
||||||
|
privilege to set kernel state.
|
||||||
|
The state to be retrieved or set is described using a
|
||||||
|
.Dq Management Information Base
|
||||||
|
.Pq Dq MIB
|
||||||
|
style name, described as a dotted set of
|
||||||
|
components.
|
||||||
|
.Pp
|
||||||
|
The following options are available:
|
||||||
|
.Bl -tag -width indent
|
||||||
|
.It Fl A
|
||||||
|
Equivalent to
|
||||||
|
.Fl o a
|
||||||
|
(for compatibility).
|
||||||
|
.It Fl a
|
||||||
|
List all the currently available non-opaque values.
|
||||||
|
This option is ignored if one or more variable names are specified on
|
||||||
|
the command line.
|
||||||
|
.It Fl b
|
||||||
|
Force the value of the variable(s) to be output in raw, binary format.
|
||||||
|
No names are printed and no terminating newlines are output.
|
||||||
|
This is mostly useful with a single variable.
|
||||||
|
.It Fl B Ar bufsize
|
||||||
|
Set the buffer size to read from the
|
||||||
|
.Nm
|
||||||
|
to
|
||||||
|
.Ar bufsize .
|
||||||
|
This is necessary for a
|
||||||
|
.Nm
|
||||||
|
that has variable length, and the probe value of 0 is a valid length, such as
|
||||||
|
.Va kern.arandom .
|
||||||
|
.It Fl d
|
||||||
|
Print the description of the variable instead of its value.
|
||||||
|
.It Fl e
|
||||||
|
Separate the name and the value of the variable(s) with
|
||||||
|
.Ql = .
|
||||||
|
This is useful for producing output which can be fed back to the
|
||||||
|
.Nm
|
||||||
|
utility.
|
||||||
|
This option is ignored if either
|
||||||
|
.Fl N
|
||||||
|
or
|
||||||
|
.Fl n
|
||||||
|
is specified, or a variable is being set.
|
||||||
|
.It Fl f Ar filename
|
||||||
|
Specify a file which contains a pair of name and value in each line.
|
||||||
|
.Nm
|
||||||
|
reads and processes the specified file first and then processes the name
|
||||||
|
and value pairs in the command line argument.
|
||||||
|
.It Fl h
|
||||||
|
Format output for human, rather than machine, readability.
|
||||||
|
.It Fl i
|
||||||
|
Ignore unknown OIDs.
|
||||||
|
The purpose is to make use of
|
||||||
|
.Nm
|
||||||
|
for collecting data from a variety of machines (not all of which
|
||||||
|
are necessarily running exactly the same software) easier.
|
||||||
|
.It Fl N
|
||||||
|
Show only variable names, not their values.
|
||||||
|
This is particularly useful with shells that offer programmable
|
||||||
|
completion.
|
||||||
|
To enable completion of variable names in
|
||||||
|
.Xr zsh 1 Pq Pa ports/shells/zsh ,
|
||||||
|
use the following code:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
listsysctls () { set -A reply $(sysctl -AN ${1%.*}) }
|
||||||
|
compctl -K listsysctls sysctl
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
To enable completion of variable names in
|
||||||
|
.Xr tcsh 1 ,
|
||||||
|
use:
|
||||||
|
.Pp
|
||||||
|
.Dl "complete sysctl 'n/*/`sysctl -Na`/'"
|
||||||
|
.It Fl n
|
||||||
|
Show only variable values, not their names.
|
||||||
|
This option is useful for setting shell variables.
|
||||||
|
For instance, to save the pagesize in variable
|
||||||
|
.Va psize ,
|
||||||
|
use:
|
||||||
|
.Pp
|
||||||
|
.Dl "set psize=`sysctl -n hw.pagesize`"
|
||||||
|
.It Fl o
|
||||||
|
Show opaque variables (which are normally suppressed).
|
||||||
|
The format and length are printed, as well as a hex dump of the first
|
||||||
|
sixteen bytes of the value.
|
||||||
|
.It Fl q
|
||||||
|
Suppress some warnings generated by
|
||||||
|
.Nm
|
||||||
|
to standard error.
|
||||||
|
.It Fl T
|
||||||
|
Display only variables that are settable via loader (CTLFLAG_TUN).
|
||||||
|
.It Fl t
|
||||||
|
Print the type of the variable.
|
||||||
|
.It Fl W
|
||||||
|
Display only writable variables that are not statistical.
|
||||||
|
Useful for determining the set of runtime tunable sysctls.
|
||||||
|
.It Fl X
|
||||||
|
Equivalent to
|
||||||
|
.Fl x a
|
||||||
|
(for compatibility).
|
||||||
|
.It Fl x
|
||||||
|
As
|
||||||
|
.Fl o ,
|
||||||
|
but prints a hex dump of the entire value instead of just the first
|
||||||
|
few bytes.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The information available from
|
||||||
|
.Nm
|
||||||
|
consists of integers, strings, and opaque types.
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility
|
||||||
|
only knows about a couple of opaque types, and will resort to hexdumps
|
||||||
|
for the rest.
|
||||||
|
The opaque information is much more useful if retrieved by special
|
||||||
|
purpose programs such as
|
||||||
|
.Xr ps 1 ,
|
||||||
|
.Xr systat 1 ,
|
||||||
|
and
|
||||||
|
.Xr netstat 1 .
|
||||||
|
.Pp
|
||||||
|
Some of the variables which cannot be modified during normal system
|
||||||
|
operation can be initialized via
|
||||||
|
.Xr loader 8
|
||||||
|
tunables.
|
||||||
|
This can for example be done by setting them in
|
||||||
|
.Xr loader.conf 5 .
|
||||||
|
Please refer to
|
||||||
|
.Xr loader.conf 5
|
||||||
|
for more information on which tunables are available and how to set them.
|
||||||
|
.Pp
|
||||||
|
The string and integer information is summarized below.
|
||||||
|
For a detailed description of these variable see
|
||||||
|
.Xr sysctl 3 .
|
||||||
|
.Pp
|
||||||
|
The changeable column indicates whether a process with appropriate
|
||||||
|
privilege can change the value.
|
||||||
|
String and integer values can be set using
|
||||||
|
.Nm .
|
||||||
|
.Bl -column security.bsd.unprivileged_read_msgbuf integerxxx
|
||||||
|
.It Sy "Name Type Changeable"
|
||||||
|
.It "kern.ostype string no"
|
||||||
|
.It "kern.osrelease string no"
|
||||||
|
.It "kern.osrevision integer no"
|
||||||
|
.It "kern.version string no"
|
||||||
|
.It "kern.maxvnodes integer yes"
|
||||||
|
.It "kern.maxproc integer no"
|
||||||
|
.It "kern.maxprocperuid integer yes"
|
||||||
|
.It "kern.maxfiles integer yes"
|
||||||
|
.It "kern.maxfilesperproc integer yes"
|
||||||
|
.It "kern.argmax integer no"
|
||||||
|
.It "kern.securelevel integer raise only"
|
||||||
|
.It "kern.hostname string yes"
|
||||||
|
.It "kern.hostid integer yes"
|
||||||
|
.It "kern.clockrate struct no"
|
||||||
|
.It "kern.posix1version integer no"
|
||||||
|
.It "kern.ngroups integer no"
|
||||||
|
.It "kern.job_control integer no"
|
||||||
|
.It "kern.saved_ids integer no"
|
||||||
|
.It "kern.boottime struct no"
|
||||||
|
.It "kern.domainname string yes"
|
||||||
|
.It "kern.filedelay integer yes"
|
||||||
|
.It "kern.dirdelay integer yes"
|
||||||
|
.It "kern.metadelay integer yes"
|
||||||
|
.It "kern.osreldate string no"
|
||||||
|
.It "kern.bootfile string yes"
|
||||||
|
.It "kern.corefile string yes"
|
||||||
|
.It "kern.logsigexit integer yes"
|
||||||
|
.It "security.bsd.suser_enabled integer yes"
|
||||||
|
.It "security.bsd.see_other_uids integer yes"
|
||||||
|
.It "security.bsd.unprivileged_proc_debug integer yes"
|
||||||
|
.It "security.bsd.unprivileged_read_msgbuf integer yes"
|
||||||
|
.It "vm.loadavg struct no"
|
||||||
|
.It "hw.machine string no"
|
||||||
|
.It "hw.model string no"
|
||||||
|
.It "hw.ncpu integer no"
|
||||||
|
.It "hw.byteorder integer no"
|
||||||
|
.It "hw.physmem integer no"
|
||||||
|
.It "hw.usermem integer no"
|
||||||
|
.It "hw.pagesize integer no"
|
||||||
|
.It "hw.floatingpoint integer no"
|
||||||
|
.It "hw.machine_arch string no"
|
||||||
|
.It "hw.realmem integer no"
|
||||||
|
.It "machdep.adjkerntz integer yes"
|
||||||
|
.It "machdep.disable_rtc_set integer yes"
|
||||||
|
.It "machdep.guessed_bootdev string no"
|
||||||
|
.It "user.cs_path string no"
|
||||||
|
.It "user.bc_base_max integer no"
|
||||||
|
.It "user.bc_dim_max integer no"
|
||||||
|
.It "user.bc_scale_max integer no"
|
||||||
|
.It "user.bc_string_max integer no"
|
||||||
|
.It "user.coll_weights_max integer no"
|
||||||
|
.It "user.expr_nest_max integer no"
|
||||||
|
.It "user.line_max integer no"
|
||||||
|
.It "user.re_dup_max integer no"
|
||||||
|
.It "user.posix2_version integer no"
|
||||||
|
.It "user.posix2_c_bind integer no"
|
||||||
|
.It "user.posix2_c_dev integer no"
|
||||||
|
.It "user.posix2_char_term integer no"
|
||||||
|
.It "user.posix2_fort_dev integer no"
|
||||||
|
.It "user.posix2_fort_run integer no"
|
||||||
|
.It "user.posix2_localedef integer no"
|
||||||
|
.It "user.posix2_sw_dev integer no"
|
||||||
|
.It "user.posix2_upe integer no"
|
||||||
|
.It "user.stream_max integer no"
|
||||||
|
.It "user.tzname_max integer no"
|
||||||
|
.El
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width ".In netinet/icmp_var.h" -compact
|
||||||
|
.It In sys/sysctl.h
|
||||||
|
definitions for top level identifiers, second level kernel and hardware
|
||||||
|
identifiers, and user level identifiers
|
||||||
|
.It In sys/socket.h
|
||||||
|
definitions for second level network identifiers
|
||||||
|
.It In sys/gmon.h
|
||||||
|
definitions for third level profiling identifiers
|
||||||
|
.It In vm/vm_param.h
|
||||||
|
definitions for second level virtual memory identifiers
|
||||||
|
.It In netinet/in.h
|
||||||
|
definitions for third level Internet identifiers and
|
||||||
|
fourth level IP identifiers
|
||||||
|
.It In netinet/icmp_var.h
|
||||||
|
definitions for fourth level ICMP identifiers
|
||||||
|
.It In netinet/udp_var.h
|
||||||
|
definitions for fourth level UDP identifiers
|
||||||
|
.El
|
||||||
|
.Sh EXAMPLES
|
||||||
|
For example, to retrieve the maximum number of processes allowed
|
||||||
|
in the system, one would use the following request:
|
||||||
|
.Pp
|
||||||
|
.Dl "sysctl kern.maxproc"
|
||||||
|
.Pp
|
||||||
|
To set the maximum number of processes allowed
|
||||||
|
per uid to 1000, one would use the following request:
|
||||||
|
.Pp
|
||||||
|
.Dl "sysctl kern.maxprocperuid=1000"
|
||||||
|
.Pp
|
||||||
|
Information about the system clock rate may be obtained with:
|
||||||
|
.Pp
|
||||||
|
.Dl "sysctl kern.clockrate"
|
||||||
|
.Pp
|
||||||
|
Information about the load average history may be obtained with:
|
||||||
|
.Pp
|
||||||
|
.Dl "sysctl vm.loadavg"
|
||||||
|
.Pp
|
||||||
|
More variables than these exist, and the best and likely only place
|
||||||
|
to search for their deeper meaning is undoubtedly the source where
|
||||||
|
they are defined.
|
||||||
|
.Sh COMPATIBILITY
|
||||||
|
The
|
||||||
|
.Fl w
|
||||||
|
option has been deprecated and is silently ignored.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr sysctl 3 ,
|
||||||
|
.Xr loader.conf 5 ,
|
||||||
|
.Xr sysctl.conf 5 ,
|
||||||
|
.Xr loader 8
|
||||||
|
.Sh HISTORY
|
||||||
|
A
|
||||||
|
.Nm
|
||||||
|
utility first appeared in
|
||||||
|
.Bx 4.4 .
|
||||||
|
.Pp
|
||||||
|
In
|
||||||
|
.Fx 2.2 ,
|
||||||
|
.Nm
|
||||||
|
was significantly remodeled.
|
||||||
|
.Sh BUGS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility presently exploits an undocumented interface to the kernel
|
||||||
|
sysctl facility to traverse the sysctl tree and to retrieve format
|
||||||
|
and name information.
|
||||||
|
This correct interface is being thought about for the time being.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue