Add vty cmd 'cdr trap' to send CDR through CTRL iface

Default behavior is to have them disabled, and can be explicitly
disabled too by using 'no cdr trap' cmd.

Tested with osmo_ctrl.py that messages are send successfully:
TRAP 0 cdr-v1 20171129125950222,901700000015254,357737055592090,555,0,5,,pdp-periodic,2731,127.0.0.2,127.0.0.1,internet,176.16.222.3,20793,10045,1

Related: OS#2360

Change-Id: I1d144d87effd934d991257a65e19cf046a938907
This commit is contained in:
Pau Espin 2017-11-29 14:01:35 +01:00
parent 291efcb590
commit 2e9ea50f78
4 changed files with 70 additions and 27 deletions

View File

@ -52,6 +52,7 @@ enum sgsn_rate_ctr_keys {
struct sgsn_cdr { struct sgsn_cdr {
char *filename; char *filename;
bool trap;
int interval; int interval;
}; };

View File

@ -18,6 +18,8 @@
* *
*/ */
#include <osmocom/ctrl/control_if.h>
#include <osmocom/sgsn/sgsn.h> #include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/signal.h> #include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/gprs_utils.h> #include <osmocom/sgsn/gprs_utils.h>
@ -38,6 +40,7 @@
/* TODO...avoid going through a global */ /* TODO...avoid going through a global */
extern struct sgsn_instance *sgsn; extern struct sgsn_instance *sgsn;
extern struct ctrl_handle *g_ctrlh;
/** /**
* The CDR module will generate an entry like: * The CDR module will generate an entry like:
@ -59,6 +62,11 @@ extern struct sgsn_instance *sgsn;
* CAUSE_FOR_TERM, # CAUSE_FOR_TERM * CAUSE_FOR_TERM, # CAUSE_FOR_TERM
*/ */
static void send_cdr_trap(char *value)
{
if (ctrl_cmd_send_trap(g_ctrlh, "cdr-v1", value) < 0)
LOGP(DGPRS, LOGL_ERROR, "Failed to create and send TRAP cdr-v1\n");
}
static void maybe_print_header(FILE *cdr_file) static void maybe_print_header(FILE *cdr_file)
{ {
@ -97,21 +105,27 @@ static void cdr_log_mm(struct sgsn_instance *inst, const char *ev,
FILE *cdr_file; FILE *cdr_file;
char buf[1024]; char buf[1024];
if (!inst->cfg.cdr.filename) if (!inst->cfg.cdr.filename && !inst->cfg.cdr.trap)
return; return;
cdr_file = fopen(inst->cfg.cdr.filename, "a");
if (!cdr_file) {
LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n",
inst->cfg.cdr.filename);
return;
}
maybe_print_header(cdr_file);
cdr_snprintf_mm(buf, sizeof(buf), ev, mmctx); cdr_snprintf_mm(buf, sizeof(buf), ev, mmctx);
fprintf(cdr_file, "%s\n", buf);
fclose(cdr_file); if (inst->cfg.cdr.trap)
send_cdr_trap(buf);
if (inst->cfg.cdr.filename) {
cdr_file = fopen(inst->cfg.cdr.filename, "a");
if (!cdr_file) {
LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n",
inst->cfg.cdr.filename);
return;
}
maybe_print_header(cdr_file);
fprintf(cdr_file, "%s\n", buf);
fclose(cdr_file);
}
} }
static void extract_eua(struct ul66_t *eua, char *eua_addr) static void extract_eua(struct ul66_t *eua, char *eua_addr)
@ -200,20 +214,26 @@ static void cdr_log_pdp(struct sgsn_instance *inst, const char *ev,
FILE *cdr_file; FILE *cdr_file;
char buf[1024]; char buf[1024];
if (!inst->cfg.cdr.filename) if (!inst->cfg.cdr.filename && !inst->cfg.cdr.trap)
return; return;
cdr_file = fopen(inst->cfg.cdr.filename, "a");
if (!cdr_file) {
LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n",
inst->cfg.cdr.filename);
return;
}
maybe_print_header(cdr_file);
cdr_snprintf_pdp(buf, sizeof(buf), ev, pdp); cdr_snprintf_pdp(buf, sizeof(buf), ev, pdp);
fprintf(cdr_file, "%s\n", buf);
fclose(cdr_file); if (inst->cfg.cdr.trap)
send_cdr_trap(buf);
if (inst->cfg.cdr.filename) {
cdr_file = fopen(inst->cfg.cdr.filename, "a");
if (!cdr_file) {
LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n",
inst->cfg.cdr.filename);
return;
}
maybe_print_header(cdr_file);
fprintf(cdr_file, "%s\n", buf);
fclose(cdr_file);
}
} }
static void cdr_pdp_timeout(void *_data) static void cdr_pdp_timeout(void *_data)

View File

@ -76,6 +76,7 @@
#include <getopt.h> #include <getopt.h>
void *tall_bsc_ctx; void *tall_bsc_ctx;
struct ctrl_handle *g_ctrlh;
struct gprs_ns_inst *sgsn_nsi; struct gprs_ns_inst *sgsn_nsi;
static int daemonize = 0; static int daemonize = 0;
@ -367,7 +368,6 @@ static bool file_exists(const char *path)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct ctrl_handle *ctrl;
int rc; int rc;
#if BUILD_IU #if BUILD_IU
struct osmo_sccp_instance *sccp; struct osmo_sccp_instance *sccp;
@ -454,9 +454,9 @@ int main(int argc, char **argv)
/* start control interface after reading config for /* start control interface after reading config for
* ctrl_vty_get_bind_addr() */ * ctrl_vty_get_bind_addr() */
ctrl = sgsn_controlif_setup(NULL, ctrl_vty_get_bind_addr(), g_ctrlh = sgsn_controlif_setup(NULL, ctrl_vty_get_bind_addr(),
OSMO_CTRL_PORT_SGSN); OSMO_CTRL_PORT_SGSN);
if (!ctrl) { if (!g_ctrlh) {
LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n"); LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n");
exit(1); exit(1);
} }

View File

@ -233,6 +233,10 @@ static int config_write_sgsn(struct vty *vty)
vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE); vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
else else
vty_out(vty, " no cdr filename%s", VTY_NEWLINE); vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
if (g_cfg->cdr.trap)
vty_out(vty, " cdr trap%s", VTY_NEWLINE);
else
vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE); vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE); vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
@ -1100,7 +1104,7 @@ DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd, DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
"cdr filename NAME", "cdr filename NAME",
"CDR\nSet filename\nname\n") "CDR\nEnable saving CDR to filename\nname\n")
{ {
talloc_free(g_cfg->cdr.filename); talloc_free(g_cfg->cdr.filename);
g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]); g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
@ -1109,13 +1113,29 @@ DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd, DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
"no cdr filename", "no cdr filename",
NO_STR "CDR\nDisable CDR generation\n") NO_STR "CDR\nDisable saving CDR to file\n")
{ {
talloc_free(g_cfg->cdr.filename); talloc_free(g_cfg->cdr.filename);
g_cfg->cdr.filename = NULL; g_cfg->cdr.filename = NULL;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_cdr_trap, cfg_cdr_trap_cmd,
"cdr trap",
"CDR\nEnable sending CDR via TRAP CTRL messages\n")
{
g_cfg->cdr.trap = true;
return CMD_SUCCESS;
}
DEFUN(cfg_no_cdr_trap, cfg_no_cdr_trap_cmd,
"no cdr trap",
NO_STR "CDR\nDisable sending CDR via TRAP CTRL messages\n")
{
g_cfg->cdr.trap = false;
return CMD_SUCCESS;
}
DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd, DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
"cdr interval <1-2147483647>", "cdr interval <1-2147483647>",
"CDR\nPDP periodic log interval\nSeconds\n") "CDR\nPDP periodic log interval\nSeconds\n")
@ -1250,6 +1270,8 @@ int sgsn_vty_init(struct sgsn_config *cfg)
install_element(SGSN_NODE, &cfg_no_apn_name_cmd); install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
install_element(SGSN_NODE, &cfg_cdr_filename_cmd); install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd); install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
install_element(SGSN_NODE, &cfg_cdr_trap_cmd);
install_element(SGSN_NODE, &cfg_no_cdr_trap_cmd);
install_element(SGSN_NODE, &cfg_cdr_interval_cmd); install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd); install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
install_element(SGSN_NODE, &cfg_grx_ggsn_cmd); install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);