From d3d5aec5551d7d451fa4dae3df118a6ebd4cc2b7 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Wed, 29 Apr 2026 14:08:37 +0300 Subject: pptp: encapsulate statistics counters Group the PPTP starting and active statistics in struct pptp_stat_t and keep the storage under the PPTP server object instead of exposing writable stat_* globals. This keeps ownership inside the PPTP control code while preserving the existing CLI and ACCEL-PPP-MIB counter semantics. Route counter updates through pptp_stat_*() helpers. Connection setup, transition to PPP, and teardown paths no longer open-code individual counter increments/decrements; the update policy now lives beside the PPTP-owned storage and uses relaxed atomic operations for the simple state counters. Make the CLI show-stat path render from a local snapshot and convert the PPTP SNMP starting/active scalars from watched raw pointers to scalar handlers. SNMP now reads through pptp_stat_starting() and pptp_stat_active(), removing the old pptp_get_stat() pointer escape hatch. Signed-off-by: Denys Fedoryshchenko --- accel-pppd/ctrl/pptp/pptp.c | 101 ++++++++++++++++++++++++++++++-------------- accel-pppd/ctrl/pptp/pptp.h | 7 +++ 2 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 accel-pppd/ctrl/pptp/pptp.h (limited to 'accel-pppd/ctrl/pptp') diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index 24984db8..efd2e592 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -25,6 +25,7 @@ #include "cli.h" #include "connlimit.h" +#include "pptp.h" #include "memdebug.h" @@ -55,6 +56,19 @@ struct pptp_conn_t struct ppp_t ppp; }; +struct pptp_stat_t +{ + unsigned int starting; + unsigned int active; +}; + +struct pptp_serv_t +{ + struct triton_context_t ctx; + struct triton_md_handler_t hnd; + struct pptp_stat_t stat; +}; + static int conf_ppp_max_mtu = PPTP_MAX_MTU; static int conf_timeout = 5; static int conf_echo_interval = 0; @@ -69,14 +83,53 @@ static const char *conf_ifname; static mempool_t conn_pool; -static unsigned int stat_starting; -static unsigned int stat_active; - static int pptp_read(struct triton_md_handler_t *h); static int pptp_write(struct triton_md_handler_t *h); static void pptp_timeout(struct triton_timer_t *); static void ppp_started(struct ap_session *); static void ppp_finished(struct ap_session *); +static void pptp_ctx_switch(struct triton_context_t *ctx, void *arg); +static int pptp_connect(struct triton_md_handler_t *h); +static void pptp_serv_close(struct triton_context_t *ctx); + +static struct pptp_serv_t serv = +{ + .hnd.read = pptp_connect, + .ctx.close = pptp_serv_close, + .ctx.before_switch = pptp_ctx_switch, +}; + +static void pptp_stat_inc(unsigned int *stat) +{ + __atomic_add_fetch(stat, 1, __ATOMIC_RELAXED); +} + +static void pptp_stat_dec(unsigned int *stat) +{ + __atomic_sub_fetch(stat, 1, __ATOMIC_RELAXED); +} + +static void pptp_stat_move(unsigned int *from, unsigned int *to) +{ + pptp_stat_dec(from); + pptp_stat_inc(to); +} + +static void pptp_stat_get(struct pptp_stat_t *stat) +{ + stat->starting = __atomic_load_n(&serv.stat.starting, __ATOMIC_RELAXED); + stat->active = __atomic_load_n(&serv.stat.active, __ATOMIC_RELAXED); +} + +unsigned int __export pptp_stat_starting(void) +{ + return __atomic_load_n(&serv.stat.starting, __ATOMIC_RELAXED); +} + +unsigned int __export pptp_stat_active(void) +{ + return __atomic_load_n(&serv.stat.active, __ATOMIC_RELAXED); +} static void pptp_ctx_switch(struct triton_context_t *ctx, void *arg) { @@ -101,11 +154,11 @@ static void disconnect(struct pptp_conn_t *conn) triton_timer_del(&conn->echo_timer); if (conn->state == STATE_PPP) { - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); conn->state = STATE_CLOSE; ap_session_terminate(&conn->ppp.ses, TERM_LOST_CARRIER, 1); } else if (conn->state != STATE_CLOSE) - __sync_sub_and_fetch(&stat_starting, 1); + pptp_stat_dec(&serv.stat.starting); triton_event_fire(EV_CTRL_FINISHED, &conn->ppp.ses); @@ -356,8 +409,7 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn) return -1; } conn->state = STATE_PPP; - __sync_sub_and_fetch(&stat_starting, 1); - __sync_add_and_fetch(&stat_active, 1); + pptp_stat_move(&serv.stat.starting, &serv.stat.active); if (conn->timeout_timer.tpd) triton_timer_del(&conn->timeout_timer); @@ -397,7 +449,7 @@ static int pptp_call_clear_rqst(struct pptp_conn_t *conn) triton_timer_del(&conn->echo_timer); if (conn->state == STATE_PPP) { - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); conn->state = STATE_CLOSE; ap_session_terminate(&conn->ppp.ses, TERM_USER_REQUEST, 1); } @@ -578,7 +630,7 @@ static void pptp_close(struct triton_context_t *ctx) { struct pptp_conn_t *conn = container_of(ctx, typeof(*conn), ctx); if (conn->state == STATE_PPP) { - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); conn->state = STATE_CLOSE; ap_session_terminate(&conn->ppp.ses, TERM_ADMIN_RESET, 1); if (send_pptp_call_disconnect_notify(conn, 3)) { @@ -609,7 +661,7 @@ static void ppp_finished(struct ap_session *ses) if (conn->state != STATE_CLOSE) { log_ppp_debug("pptp: ppp finished\n"); conn->state = STATE_CLOSE; - __sync_sub_and_fetch(&stat_active, 1); + pptp_stat_dec(&serv.stat.active); if (send_pptp_call_disconnect_notify(conn, 3)) triton_context_call(&conn->ctx, (void (*)(void*))disconnect, conn); @@ -626,12 +678,6 @@ static void ppp_finished(struct ap_session *ses) //================================== -struct pptp_serv_t -{ - struct triton_context_t ctx; - struct triton_md_handler_t hnd; -}; - static int pptp_connect(struct triton_md_handler_t *h) { struct sockaddr_in addr; @@ -733,7 +779,7 @@ static int pptp_connect(struct triton_md_handler_t *h) triton_event_fire(EV_CTRL_STARTING, &conn->ppp.ses); - __sync_add_and_fetch(&stat_starting, 1); + pptp_stat_inc(&serv.stat.starting); } return 0; } @@ -744,28 +790,19 @@ static void pptp_serv_close(struct triton_context_t *ctx) triton_context_unregister(ctx); } -static struct pptp_serv_t serv= -{ - .hnd.read = pptp_connect, - .ctx.close = pptp_serv_close, - .ctx.before_switch = pptp_ctx_switch, -}; - static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) { + struct pptp_stat_t stat; + + pptp_stat_get(&stat); + cli_send(client, "pptp:\r\n"); - cli_sendv(client," starting: %u\r\n", stat_starting); - cli_sendv(client," active: %u\r\n", stat_active); + cli_sendv(client," starting: %u\r\n", stat.starting); + cli_sendv(client," active: %u\r\n", stat.active); return CLI_CMD_OK; } -void __export pptp_get_stat(unsigned int **starting, unsigned int **active) -{ - *starting = &stat_starting; - *active = &stat_active; -} - static void load_config(void) { char *opt; diff --git a/accel-pppd/ctrl/pptp/pptp.h b/accel-pppd/ctrl/pptp/pptp.h new file mode 100644 index 00000000..29f24ca2 --- /dev/null +++ b/accel-pppd/ctrl/pptp/pptp.h @@ -0,0 +1,7 @@ +#ifndef __PPTP_H +#define __PPTP_H + +unsigned int pptp_stat_starting(void); +unsigned int pptp_stat_active(void); + +#endif -- cgit v1.2.3 From d6383d69813cf2244f31d8116176733ffbbeaceb Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Wed, 29 Apr 2026 15:21:02 +0300 Subject: session: encapsulate statistics counters Group the core session starting, active, and finishing statistics behind the private ap_session_stat storage in session.c instead of exposing writable counters through ap_session.h. This keeps ownership inside the session core while preserving the existing CLI and ACCEL-PPP-MIB counter semantics. Route session counter updates through ap_session_stat_*() helpers. Session start, activation, termination, finish, and shutdown-idle paths no longer open-code individual counter increments/decrements; the update policy now lives beside the session-owned storage and uses relaxed atomic operations for the simple state counters. Make the CLI show-stat path render from a local snapshot and convert the PPP SNMP starting/active/finishing scalars from watched raw pointers to scalar handlers. PPP controllers now read max-session limits through ap_session_stat_starting() and ap_session_stat_active(), removing external direct access to ap_session_stat. Signed-off-by: Denys Fedoryshchenko --- accel-pppd/cli/std_cmd.c | 14 +++- accel-pppd/ctrl/ipoe/ipoe.c | 8 +- accel-pppd/ctrl/l2tp/l2tp.c | 12 +-- accel-pppd/ctrl/pppoe/pppoe.c | 8 +- accel-pppd/ctrl/pptp/pptp.c | 4 +- accel-pppd/ctrl/sstp/sstp.c | 4 +- accel-pppd/extra/net-snmp/statPPP.c | 145 ++++++++++++++++++++++++------------ accel-pppd/include/ap_session.h | 6 +- accel-pppd/session.c | 67 ++++++++++++++--- 9 files changed, 186 insertions(+), 82 deletions(-) (limited to 'accel-pppd/ctrl/pptp') diff --git a/accel-pppd/cli/std_cmd.c b/accel-pppd/cli/std_cmd.c index c37777b1..9e7bf557 100644 --- a/accel-pppd/cli/std_cmd.c +++ b/accel-pppd/cli/std_cmd.c @@ -71,10 +71,16 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, cli_sendv(client, " timer_pending: %u\r\n", triton_stat.timer_pending); //=========== - cli_send(client, "sessions:\r\n"); - cli_sendv(client, " starting: %u\r\n", ap_session_stat.starting); - cli_sendv(client, " active: %u\r\n", ap_session_stat.active); - cli_sendv(client, " finishing: %u\r\n", ap_session_stat.finishing); + { + struct ap_session_stat ses_stat; + + ap_session_stat_get(&ses_stat); + + cli_send(client, "sessions:\r\n"); + cli_sendv(client, " starting: %u\r\n", ses_stat.starting); + cli_sendv(client, " active: %u\r\n", ses_stat.active); + cli_sendv(client, " finishing: %u\r\n", ses_stat.finishing); + } return CLI_CMD_OK; } diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 42d142fe..5592845f 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -1392,10 +1392,10 @@ static struct ipoe_session *ipoe_session_create_dhcpv4(struct ipoe_serv *serv, s if (ap_shutdown) return NULL; - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return NULL; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return NULL; ses = ipoe_session_alloc(serv->ifname); @@ -2137,10 +2137,10 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc if (ap_shutdown) return NULL; - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return NULL; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return NULL; if (connlimit_loaded && connlimit_check(serv->opt_shared ? cl_key_from_ipv4(saddr) : serv->ifindex)) diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index 91b49d79..cf0c502c 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -2836,10 +2836,10 @@ static int l2tp_recv_SCCRQ(const struct l2tp_serv_t *serv, return 0; } - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return 0; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return 0; if (triton_module_loaded("connlimit") @@ -3382,10 +3382,10 @@ static int l2tp_recv_ICRQ(struct l2tp_conn_t *conn, return 0; } - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return 0; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return 0; if (triton_module_loaded("connlimit") @@ -3722,10 +3722,10 @@ static int l2tp_recv_OCRQ(struct l2tp_conn_t *conn, return 0; } - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return 0; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return 0; if (triton_module_loaded("connlimit") diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 475ee530..93824af5 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -1013,10 +1013,10 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size) if (ap_shutdown || pado_delay == -1) return; - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return; if (check_padi_limit(serv, ethhdr->h_source)) { @@ -1148,10 +1148,10 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) if (ap_shutdown) return; - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) return; - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) return; if (!memcmp(ethhdr->h_dest, bc_addr, ETH_ALEN)) { diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index efd2e592..f8e498d6 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -699,12 +699,12 @@ static int pptp_connect(struct triton_md_handler_t *h) continue; } - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) { + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) { close(sock); continue; } - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) { + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) { close(sock); continue; } diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 71fb17e7..21c519fa 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -2330,12 +2330,12 @@ static int sstp_connect(struct triton_md_handler_t *h) continue; } - if (conf_max_starting && ap_session_stat.starting >= conf_max_starting) { + if (conf_max_starting && ap_session_stat_starting() >= conf_max_starting) { close(sock); continue; } - if (conf_max_sessions && ap_session_stat.active + ap_session_stat.starting >= conf_max_sessions) { + if (conf_max_sessions && ap_session_stat_active() + ap_session_stat_starting() >= conf_max_sessions) { close(sock); continue; } diff --git a/accel-pppd/extra/net-snmp/statPPP.c b/accel-pppd/extra/net-snmp/statPPP.c index 37e4630c..7dc1f659 100644 --- a/accel-pppd/extra/net-snmp/statPPP.c +++ b/accel-pppd/extra/net-snmp/statPPP.c @@ -6,9 +6,22 @@ #include #include #include + +#include "ap_session.h" #include "statPPP.h" -#include "ppp.h" +static int handle_statPPPStarting(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests); +static int handle_statPPPActive(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests); +static int handle_statPPPFinishing(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests); /* * Our initialization routine, called automatically by the agent @@ -17,77 +30,115 @@ void init_statPPP(void) { - netsnmp_handler_registration *reg; - netsnmp_watcher_info *winfo; - static oid statPPPStarting_oid[] = { 1,3,6,1,4,1,8072,100,1,2,1 }; static oid statPPPActive_oid[] = { 1,3,6,1,4,1,8072,100,1,2,2 }; static oid statPPPFinishing_oid[] = { 1,3,6,1,4,1,8072,100,1,2,3 }; - /* - * a debugging statement. Run the agent with -DstatPPP to see - * the output of this debugging statement. - */ DEBUGMSGTL(("statPPP", "Initializing the statPPP module\n")); - - /* - * Register scalar watchers for each of the MIB objects. - * The ASN type and RO/RW status are taken from the MIB definition, - * but can be adjusted if needed. - * - * In most circumstances, the scalar watcher will handle all - * of the necessary processing. But the NULL parameter in the - * netsnmp_create_handler_registration() call can be used to - * supply a user-provided handler if necessary. - * - * This approach can also be used to handle Counter64, string- - * and OID-based watched scalars (although variable-sized writeable - * objects will need some more specialised initialisation). - */ DEBUGMSGTL(("statPPP", "Initializing statPPPStarting scalar integer. Default value = %d\n", 0)); - reg = netsnmp_create_handler_registration( - "statPPPStarting", NULL, + if (netsnmp_register_scalar(netsnmp_create_handler_registration( + "statPPPStarting", handle_statPPPStarting, statPPPStarting_oid, OID_LENGTH(statPPPStarting_oid), - HANDLER_CAN_RONLY); - winfo = netsnmp_create_watcher_info( - &ap_session_stat.starting, sizeof(ap_session_stat.starting), - ASN_INTEGER, WATCHER_FIXED_SIZE); - if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { - snmp_log( LOG_ERR, "Failed to register watched statPPPStarting" ); + HANDLER_CAN_RONLY)) < 0 ) { + snmp_log( LOG_ERR, "Failed to register statPPPStarting" ); } DEBUGMSGTL(("statPPP", "Initializing statPPPActive scalar integer. Default value = %d\n", 0)); - reg = netsnmp_create_handler_registration( - "statPPPActive", NULL, + if (netsnmp_register_scalar(netsnmp_create_handler_registration( + "statPPPActive", handle_statPPPActive, statPPPActive_oid, OID_LENGTH(statPPPActive_oid), - HANDLER_CAN_RONLY); - winfo = netsnmp_create_watcher_info( - &ap_session_stat.active, sizeof(ap_session_stat.active), - ASN_INTEGER, WATCHER_FIXED_SIZE); - if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { - snmp_log( LOG_ERR, "Failed to register watched statPPPActive" ); + HANDLER_CAN_RONLY)) < 0 ) { + snmp_log( LOG_ERR, "Failed to register statPPPActive" ); } DEBUGMSGTL(("statPPP", "Initializing statPPPFinishing scalar integer. Default value = %d\n", 0)); - reg = netsnmp_create_handler_registration( - "statPPPFinishing", NULL, + if (netsnmp_register_scalar(netsnmp_create_handler_registration( + "statPPPFinishing", handle_statPPPFinishing, statPPPFinishing_oid, OID_LENGTH(statPPPFinishing_oid), - HANDLER_CAN_RONLY); - winfo = netsnmp_create_watcher_info( - &ap_session_stat.finishing, sizeof(ap_session_stat.finishing), - ASN_INTEGER, WATCHER_FIXED_SIZE); - if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { - snmp_log( LOG_ERR, "Failed to register watched statPPPFinishing" ); + HANDLER_CAN_RONLY)) < 0 ) { + snmp_log( LOG_ERR, "Failed to register statPPPFinishing" ); } DEBUGMSGTL(("statPPP", "Done initalizing statPPP module\n")); } + +static int handle_statPPPStarting(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + long stat; + + (void)handler; + (void)reginfo; + + switch (reqinfo->mode) { + case MODE_GET: + stat = ap_session_stat_starting(); + snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, + (u_char *)&stat, sizeof(stat)); + break; + default: + snmp_log(LOG_ERR, "unknown mode (%d) in handle_statPPPStarting\n", reqinfo->mode); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int handle_statPPPActive(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + long stat; + + (void)handler; + (void)reginfo; + + switch (reqinfo->mode) { + case MODE_GET: + stat = ap_session_stat_active(); + snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, + (u_char *)&stat, sizeof(stat)); + break; + default: + snmp_log(LOG_ERR, "unknown mode (%d) in handle_statPPPActive\n", reqinfo->mode); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int handle_statPPPFinishing(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + long stat; + + (void)handler; + (void)reginfo; + + switch (reqinfo->mode) { + case MODE_GET: + stat = ap_session_stat_finishing(); + snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, + (u_char *)&stat, sizeof(stat)); + break; + default: + snmp_log(LOG_ERR, "unknown mode (%d) in handle_statPPPFinishing\n", reqinfo->mode); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h index 27471859..a4d3b867 100644 --- a/accel-pppd/include/ap_session.h +++ b/accel-pppd/include/ap_session.h @@ -136,10 +136,14 @@ extern int ap_shutdown; extern int sock_fd; extern int sock6_fd; extern int urandom_fd; -extern struct ap_session_stat ap_session_stat; extern int conf_max_sessions; extern int conf_max_starting; +void ap_session_stat_get(struct ap_session_stat *stat); +unsigned int ap_session_stat_starting(void); +unsigned int ap_session_stat_active(void); +unsigned int ap_session_stat_finishing(void); + void ap_session_init(struct ap_session *ses); void ap_session_set_ifindex(struct ap_session *ses); int ap_session_starting(struct ap_session *ses); diff --git a/accel-pppd/session.c b/accel-pppd/session.c index a1b194a3..c16f68ae 100644 --- a/accel-pppd/session.c +++ b/accel-pppd/session.c @@ -62,13 +62,58 @@ static spinlock_t seq_lock; static long long unsigned seq; static struct timespec seq_ts; -struct ap_session_stat __export ap_session_stat; +static struct ap_session_stat ap_session_stat; static void (*shutdown_cb)(void); static void generate_sessionid(struct ap_session *ses); static void save_seq(void); +void __export ap_session_stat_get(struct ap_session_stat *stat) +{ + stat->starting = __atomic_load_n(&ap_session_stat.starting, __ATOMIC_RELAXED); + stat->active = __atomic_load_n(&ap_session_stat.active, __ATOMIC_RELAXED); + stat->finishing = __atomic_load_n(&ap_session_stat.finishing, __ATOMIC_RELAXED); +} + +unsigned int __export ap_session_stat_starting(void) +{ + return __atomic_load_n(&ap_session_stat.starting, __ATOMIC_RELAXED); +} + +unsigned int __export ap_session_stat_active(void) +{ + return __atomic_load_n(&ap_session_stat.active, __ATOMIC_RELAXED); +} + +unsigned int __export ap_session_stat_finishing(void) +{ + return __atomic_load_n(&ap_session_stat.finishing, __ATOMIC_RELAXED); +} + +static void ap_session_stat_inc(unsigned int *stat) +{ + __atomic_add_fetch(stat, 1, __ATOMIC_RELAXED); +} + +static void ap_session_stat_dec(unsigned int *stat) +{ + __atomic_sub_fetch(stat, 1, __ATOMIC_RELAXED); +} + +static void ap_session_stat_move(unsigned int *from, unsigned int *to) +{ + ap_session_stat_dec(from); + ap_session_stat_inc(to); +} + +static int ap_session_stat_idle(void) +{ + return !ap_session_stat_starting() + && !ap_session_stat_active() + && !ap_session_stat_finishing(); +} + void __export ap_session_init(struct ap_session *ses) { memset(ses, 0, sizeof(*ses)); @@ -113,7 +158,7 @@ int __export ap_session_starting(struct ap_session *ses) ses->state = AP_STATE_STARTING; } - __sync_add_and_fetch(&ap_session_stat.starting, 1); + ap_session_stat_inc(&ap_session_stat.starting); pthread_rwlock_wrlock(&ses_lock); list_add_tail(&ses->entry, &ses_list); @@ -156,8 +201,7 @@ void __export ap_session_activate(struct ap_session *ses) return; ses->state = AP_STATE_ACTIVE; - __sync_sub_and_fetch(&ap_session_stat.starting, 1); - __sync_add_and_fetch(&ap_session_stat.active, 1); + ap_session_stat_move(&ap_session_stat.starting, &ap_session_stat.active); if (!ses->session_timeout && conf_session_timeout) ses->session_timeout = conf_session_timeout; @@ -198,14 +242,14 @@ void __export ap_session_finished(struct ap_session *ses) switch (ses->state) { case AP_STATE_ACTIVE: - __sync_sub_and_fetch(&ap_session_stat.active, 1); + ap_session_stat_dec(&ap_session_stat.active); break; case AP_STATE_RESTORE: case AP_STATE_STARTING: - __sync_sub_and_fetch(&ap_session_stat.starting, 1); + ap_session_stat_dec(&ap_session_stat.starting); break; case AP_STATE_FINISHING: - __sync_sub_and_fetch(&ap_session_stat.finishing, 1); + ap_session_stat_dec(&ap_session_stat.finishing); break; } @@ -266,7 +310,7 @@ void __export ap_session_finished(struct ap_session *ses) ses->backup->storage->free(ses->backup); #endif - if (ap_shutdown && !ap_session_stat.starting && !ap_session_stat.active && !ap_session_stat.finishing) { + if (ap_shutdown && ap_session_stat_idle()) { if (shutdown_cb) shutdown_cb(); else @@ -299,11 +343,10 @@ void __export ap_session_terminate(struct ap_session *ses, int cause, int hard) } if (ses->state == AP_STATE_ACTIVE) - __sync_sub_and_fetch(&ap_session_stat.active, 1); + ap_session_stat_move(&ap_session_stat.active, &ap_session_stat.finishing); else - __sync_sub_and_fetch(&ap_session_stat.starting, 1); + ap_session_stat_move(&ap_session_stat.starting, &ap_session_stat.finishing); - __sync_add_and_fetch(&ap_session_stat.finishing, 1); ses->terminating = 1; ses->state = AP_STATE_FINISHING; @@ -333,7 +376,7 @@ int ap_shutdown_soft(void (*cb)(void), int term) pthread_rwlock_rdlock(&ses_lock); - if (!ap_session_stat.starting && !ap_session_stat.active && !ap_session_stat.finishing) { + if (ap_session_stat_idle()) { pthread_rwlock_unlock(&ses_lock); if (shutdown_cb) shutdown_cb(); -- cgit v1.2.3