ggsn: Introduce tdef and make it configurable over VTY

Related: OS#5485
Change-Id: I10bc8e2e197c0e8753b23b684b5ae41025672bf7
This commit is contained in:
Pau Espin 2022-11-02 19:52:19 +01:00
parent b9036af7ca
commit 9f1f747d8e
6 changed files with 53 additions and 13 deletions

View File

@ -6,6 +6,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/tdef.h>
#include <osmocom/ctrl/control_if.h>
#include "../lib/tun.h"
@ -152,6 +153,7 @@ struct apn_ctx *ggsn_find_or_create_apn(struct ggsn_ctx *ggsn, const char *name)
/* ggsn_main.c */
extern struct ctrl_handle *g_ctrlh;
extern void *tall_ggsn_ctx;
extern struct osmo_tdef_group ggsn_tdef_group[];
/* ggsn.c */
extern int ggsn_start(struct ggsn_ctx *ggsn);

View File

@ -34,6 +34,7 @@
#include <osmocom/core/stats.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/tdef.h>
#include <osmocom/core/utils.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/control_cmd.h>
@ -60,6 +61,11 @@ struct ul255_t apn;
static char *config_file = "osmo-ggsn.cfg";
struct osmo_tdef_group ggsn_tdef_group[] = {
{.name = "gtp", .tdefs = gtp_T_defs, .desc = "GTP (libgtp) timers" },
{ }
};
/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
static void signal_handler(int s)
{

View File

@ -33,6 +33,7 @@
#include <osmocom/vty/command.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/misc.h>
#include <osmocom/vty/tdef_vty.h>
#include "../gtp/gtp.h"
#include "../gtp/pdp.h"
@ -795,6 +796,7 @@ static int config_write_ggsn(struct vty *vty)
vty_out(vty, " gtp control-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpc_addr), VTY_NEWLINE);
if (ggsn->cfg.gtpu_addr.v4.s_addr)
vty_out(vty, " gtp user-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpu_addr), VTY_NEWLINE);
osmo_tdef_vty_groups_write(vty, " ");
llist_for_each_entry(apn, &ggsn->apn_list, list)
config_write_apn(vty, apn);
if (ggsn->cfg.default_apn)
@ -1113,6 +1115,8 @@ int ggsn_vty_init(void)
install_element(GGSN_NODE, &cfg_ggsn_echo_interval_cmd);
install_element(GGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
osmo_tdef_vty_groups_init(GGSN_NODE, ggsn_tdef_group);
install_node(&apn_node, NULL);
install_element(APN_NODE, &cfg_description_cmd);
install_element(APN_NODE, &cfg_no_description_cmd);

View File

@ -62,11 +62,6 @@
#include "gtpie.h"
#include "queue.h"
/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
#define N3_REQUESTS 5
#define T3_REQUEST 3
/* Error reporting functions */
#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
@ -104,6 +99,18 @@ static const struct rate_ctr_group_desc gsn_ctrg_desc = {
};
static unsigned int gsn_ctr_next_idx = 0;
/* Global timer definitions for GTP operation, provided for convenience. To make these user configurable, it is convenient to add
* gtp_gsn_tdefs as one of your program's osmo_tdef_group entries and call osmo_tdef_vty_init(). */
struct osmo_tdef gtp_T_defs[] = {
{ .T = GTP_GSN_TIMER_T3_RESPONSE, .default_val = 5, .unit = OSMO_TDEF_S,
.desc = "Timer T3-RESPONSE holds the maximum wait time for a response of a request message"
},
{ .T = GTP_GSN_TIMER_N3_REQUESTS, .default_val = 3, .unit = OSMO_TDEF_CUSTOM,
.desc = "Counter N3-REQUESTS holds the maximum number of attempts made by GTP to send a request message"
},
{}
};
/* API Functions */
@ -241,13 +248,17 @@ static int queue_timer_retrans(struct gsn_t *gsn)
/* Remove from queue if maxretrans exceeded */
time_t now;
struct qmsg_t *qmsg;
unsigned int t3_response, n3_requests;
now = time(NULL);
t3_response = osmo_tdef_get(gsn->tdef, GTP_GSN_TIMER_T3_RESPONSE, OSMO_TDEF_S, -1);
n3_requests = osmo_tdef_get(gsn->tdef, GTP_GSN_TIMER_N3_REQUESTS, OSMO_TDEF_CUSTOM, -1);
/* get first element in queue, as long as the timeout of that
* element has expired */
while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
(qmsg->timeout <= now)) {
if (qmsg->retrans > N3_REQUESTS) { /* Too many retrans */
if (qmsg->retrans > n3_requests) { /* Too many retrans */
LOGP(DLGTP, LOGL_NOTICE, "Retransmit req queue timeout of seq %" PRIu16 "\n",
qmsg->seq);
if (gsn->cb_conf)
@ -266,7 +277,7 @@ static int queue_timer_retrans(struct gsn_t *gsn)
qmsg->l, strerror(errno));
}
queue_back(gsn->queue_req, qmsg);
qmsg->timeout = now + T3_REQUEST;
qmsg->timeout = now + t3_response;
qmsg->retrans++;
}
}
@ -424,6 +435,14 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
/* Initialise sequence number */
(*gsn)->seq_next = (*gsn)->restart_counter * 1024;
/* Initialize timers: */
(*gsn)->tdef = gtp_T_defs;
/* Small hack to properly reset tdef for old clients not using the tdef_group: */
osmo_static_assert(gtp_T_defs[0].default_val != 0, first_default_val_not_zero);
if (gtp_T_defs[0].val == 0)
osmo_tdefs_reset((*gsn)->tdef);
/* Initialise request retransmit queue */
queue_new(&(*gsn)->queue_req);
queue_new(&(*gsn)->queue_resp);

View File

@ -15,6 +15,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/defs.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/tdef.h>
#include <osmocom/core/rate_ctr.h>
#include "pdp.h"
@ -24,6 +25,8 @@
#define RESTART_FILE "gsn_restart"
extern struct osmo_tdef gtp_T_defs[];
/* ***********************************************************
* Information storage for each gsn instance
*
@ -60,6 +63,12 @@ enum gsn_rate_ctr_keys {
GSN_CTR_PKT_INVALID, /* Number of invalid message format messages */
};
/* 3GPP TS 29.006 14.1, 14,2 */
enum gtp_gsn_timers {
GTP_GSN_TIMER_T3_RESPONSE = 3,
GTP_GSN_TIMER_N3_REQUESTS = 1003,
};
struct gsn_t {
/* Parameters related to the network interface */
@ -100,6 +109,9 @@ struct gsn_t {
/* Counters */
struct rate_ctr_group *ctrg;
/* Timers: */
struct osmo_tdef *tdef;
};
/* External API functions */

View File

@ -60,11 +60,6 @@
#include "gtpie.h"
#include "queue.h"
/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
#define N3_REQUESTS 5
#define T3_REQUEST 3
/* Error reporting functions */
#define GTP_LOGPKG(pri, peer, pack, len, fmt, args...) \
@ -400,11 +395,13 @@ static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp,
LOGP(DLGTP, LOGL_ERROR, "Retransmit req queue is full (seq=%" PRIu16 ")\n",
gsn->seq_next);
} else {
unsigned int t3_response;
LOGP(DLGTP, LOGL_DEBUG, "Registering seq=%" PRIu16
" in restransmit req queue\n", gsn->seq_next);
t3_response = osmo_tdef_get(gsn->tdef, GTP_GSN_TIMER_T3_RESPONSE, OSMO_TDEF_S, -1);
memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
qmsg->l = len;
qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
qmsg->timeout = time(NULL) + t3_response; /* When to timeout */
qmsg->retrans = 0; /* No retransmissions so far */
qmsg->cbp = cbp;
qmsg->type = ntoh8(packet->gtp0.h.type);