re-structure the LOG dispatcher

we now have a nice structure for dispatching log messages to various
handlers, each self-contained.  As an added benefit, we remove the need
to manually enable all the various log codes, as we simply auto-generate
the default config from all the message types we support.

Furthermore, we reduce computational complexity by avoiding linear
iteration over the array of registered log handlers.
This commit is contained in:
Harald Welte 2016-12-24 01:21:03 +01:00
parent 2c36375f5b
commit faea754d39
13 changed files with 498 additions and 377 deletions

View File

@ -2,7 +2,9 @@ CPPFLAGS ?= -g -O0 -Wall `pkg-config --cflags qmi-glib`
LIBS ?= -losmocore `pkg-config --libs qmi-glib`
all: qxdm-log
qxdm-log: diagchar_hdlc.o diag_io.o qxdm-log.o config.o gprs_rlc.o gprs_mac.o diag_gsm.o protocol.o qmi_decode.o
MODS_LOG = gprs_rlc.o gprs_mac.o diag_gsm.o diag_log.o diag_log_gsm.o diag_log_gprs.o diag_log_umts.o diag_log_qmi.o
qxdm-log: diagchar_hdlc.o diag_io.o qxdm-log.o protocol.o $(MODS_LOG)
$(CC) $(CPPFLAGS) -o $@ $^ $(LIBS)
clean:

View File

@ -1,58 +0,0 @@
#include <stdint.h>
#include <osmocom/core/msgb.h>
#include "diagcmd.h"
#include "protocol.h"
enum log_config_op {
LOG_CONFIG_DISABLE_OP = 0,
LOG_CONFIG_RETRIEVE_ID_RANGES_OP = 1,
LOG_CONFIG_RETRIEVE_VALID_MASK_OP = 2,
LOG_CONFIG_SET_MASK_OP = 3,
LOG_CONFIG_GET_LOGMASK_OP = 4,
};
struct diag_log_config_req_hdr {
uint8_t msg_type;
uint8_t pad[3];
uint32_t operation;
} __attribute((packed));
struct diag_log_config_set_mask {
struct diag_log_config_req_hdr hdr;
uint32_t equip_id;
uint32_t last_item;
uint8_t data[0];
} __attribute((packed));
struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item)
{
struct msgb *msg = msgb_alloc(DIAG_MAX_REQ_SIZE, "Diag Tx");
struct diag_log_config_set_mask *dlcsm;
msg->l2h = msgb_put(msg, sizeof(*dlcsm));
dlcsm = (struct diag_log_config_set_mask *) msg->l2h;
dlcsm->hdr.msg_type = DIAG_LOG_CONFIG_F;
dlcsm->hdr.operation = LOG_CONFIG_SET_MASK_OP;
dlcsm->equip_id = equip_id;
dlcsm->last_item = last_item;
msg->l3h = msgb_put(msg, dlcsm->last_item/8);
return msg;
}
int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in)
{
struct diag_log_config_set_mask *dlcsm;
dlcsm = (struct diag_log_config_set_mask *) msg->l2h;
uint8_t *mask = msg->l3h;
unsigned int byte = bit_in / 8;
unsigned int bit = bit_in % 8;
if (byte > dlcsm->last_item/8)
return -1;
mask[byte] |= (1 << bit);
return 0;
}

View File

@ -1,8 +0,0 @@
#pragma once
#include <stdint.h>
struct msgb;
struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item);
int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in);

143
src/diag_log.c Normal file
View File

@ -0,0 +1,143 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <osmocom/core/msgb.h>
#include "diag_log.h"
#include "protocol.h"
#include "diagcmd.h"
/***********************************************************************
* LOG Configuration / Protocol
***********************************************************************/
enum log_config_op {
LOG_CONFIG_DISABLE_OP = 0,
LOG_CONFIG_RETRIEVE_ID_RANGES_OP = 1,
LOG_CONFIG_RETRIEVE_VALID_MASK_OP = 2,
LOG_CONFIG_SET_MASK_OP = 3,
LOG_CONFIG_GET_LOGMASK_OP = 4,
};
struct diag_log_config_req_hdr {
uint8_t msg_type;
uint8_t pad[3];
uint32_t operation;
} __attribute((packed));
struct diag_log_config_set_mask {
struct diag_log_config_req_hdr hdr;
uint32_t equip_id;
uint32_t last_item;
uint8_t data[0];
} __attribute((packed));
struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item)
{
struct msgb *msg = msgb_alloc(DIAG_MAX_REQ_SIZE, "Diag Tx");
struct diag_log_config_set_mask *dlcsm;
msg->l2h = msgb_put(msg, sizeof(*dlcsm));
dlcsm = (struct diag_log_config_set_mask *) msg->l2h;
dlcsm->hdr.msg_type = DIAG_LOG_CONFIG_F;
dlcsm->hdr.operation = LOG_CONFIG_SET_MASK_OP;
dlcsm->equip_id = equip_id;
dlcsm->last_item = last_item;
msg->l3h = msgb_put(msg, dlcsm->last_item/8);
return msg;
}
int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in)
{
struct diag_log_config_set_mask *dlcsm;
dlcsm = (struct diag_log_config_set_mask *) msg->l2h;
uint8_t *mask = msg->l3h;
unsigned int byte = bit_in / 8;
unsigned int bit = bit_in % 8;
if (byte > dlcsm->last_item/8)
return -1;
mask[byte] |= (1 << bit);
return 0;
}
/***********************************************************************
* LOG Dispatch
***********************************************************************/
/* not particularly memory efficient, but welll, only 500kB on 64bit */
static diag_log_handler *log_handlers[0xffff];
/* called by individual modules to register their own decoders */
void diag_log_reg_dispatch(const struct diag_log_dispatch_tbl *tbl, unsigned int size)
{
unsigned int i;
for (i = 0; i < size; i++) {
printf("Registering dispatch for 0x%04x\n", tbl[i].code);
log_handlers[tbl[i].code] = tbl[i].handler;
}
}
void diag_log_enable_all_supported_family(struct diag_instance *di, uint8_t family)
{
struct msgb *msg;
unsigned int i, size;
unsigned int family_base = (family & 0xf) << 12;
unsigned int max = 0;
for (i = family_base; i < family_base + 0x1000; i++) {
if (log_handlers[i]) {
if (max < i)
max = i;
}
}
if (!max)
return;
size = max - family_base;
printf("family %u: allocating log mask of size %u\n", family, size);
msg = gen_log_config_set_mask(family, size);
for (i = family_base; i < family_base + 0x1000; i++) {
if (log_handlers[i])
log_config_set_mask_bit(msg, i-family_base);
}
diag_transmit_msgb(di, msg);
diag_read(di);
}
void diag_log_enable_all_supported(struct diag_instance *di)
{
unsigned int i;
for (i = 0; i < 0xF; i++) {
diag_log_enable_all_supported_family(di, i);
}
}
void diag_log_handle(struct diag_instance *di, struct msgb *msg)
{
struct diag_log_hdr *dlh;
struct log_hdr *lh;
dlh = (struct diag_log_hdr *) msg->data;
/* FIXME: verify length */
msg->l3h = msgb_pull(msg, sizeof(*dlh));
lh = (struct log_hdr *) msg->l3h;
/* FIXME: verify length */
msgb_pull(msg, sizeof(*lh));
printf("LOG(0x%04x|%u|%u): ", lh->code,
diag_ts_to_epoch(lh->ts), diag_ts_to_fn(lh->ts));
if (log_handlers[lh->code])
log_handlers[lh->code](lh, msg);
else
printf("%s\n", osmo_hexdump(lh->data, lh->len));
}

24
src/diag_log.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "diag_io.h"
#include "protocol.h"
typedef void diag_log_handler(struct log_hdr *lh, struct msgb *msg);
struct diag_log_dispatch_tbl {
uint16_t code;
diag_log_handler *handler;
};
/* called by input whenever a LOG message is registered */
void diag_log_handle(struct diag_instance *di, struct msgb *msg);
/* called by individual modules to register their own decoders */
void diag_log_reg_dispatch(const struct diag_log_dispatch_tbl *tbl, unsigned int size);
void diag_log_enable_all_supported_family(struct diag_instance *di, uint8_t family);
void diag_log_enable_all_supported(struct diag_instance *di);
/* functions for log configuration */
struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item);
int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in);

177
src/diag_log_gprs.c Normal file
View File

@ -0,0 +1,177 @@
#include <stdio.h>
#include "diag_log.h"
#include "diag_gsm.h"
#include "gprs_rlc.h"
#include "gprs_mac.h"
#include "log_codes_gsm.h"
static void handle_grr_state_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gprs_grr_state *rrs = (struct diag_gprs_grr_state *) msgb_data(msg);
printf("GRR-STATE { active=%u, state=%s }\n", rrs->active_state,
get_value_string(diag_gprs_grr_st_vals, rrs->grr_state));
}
static void handle_rlc_ul_abnrml_rls(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_ul_abnrml_rls_counts *arc;
arc = (struct gprs_rlc_ul_abnrml_rls_counts *) msgb_data(msg);
printf("RLC-UL-ABNRML-RLS-COUNTS { access_reject_cnt=%u, arc_retry_cnt=%u, arc_wo_retry_cnt=%u, arc_sys_info_cnt=%u }",
arc->access_reject_cnt, arc->arc_retry_cnt, arc->arc_wo_retry_cnt, arc->arc_sys_info_cnt);
}
static void handle_mac_sign_msg(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_signalling_msg *msm;
msm = (struct gprs_mac_signalling_msg *) msgb_data(msg);
printf("MAC-SIGN-MSG { chan_type=%s, msg_type=%s, msg=%s }\n",
get_value_string(gprs_mac_chan_type_vals, msm->chan_type),
get_value_string(gprs_mac_msg_type_vals, msm->msg_type),
osmo_hexdump(msm->msg, msm->msg_len));
}
static void handle_llc_me_info(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gprs_llme_info *gli;
gli = (struct diag_gprs_llme_info *) msgb_data(msg);
printf("LLC-ME-INFO { state=%s, xid_version=%u, tlli_new=0x%08x, tlli_old=0x%08x, gea=%u, key=%s }\n",
get_value_string(diag_gprs_llme_st_vals, gli->state), gli->xid_version,
gli->tlli_new, gli->tlli_old, gli->enc_alg,
osmo_hexdump_nospc(gli->enc_key, sizeof(gli->enc_key)));
}
static void handle_llc_pdu_stats(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gprs_llc_stats *gls;
gls = (struct diag_gprs_llc_stats *) msgb_data(msg);
printf("LLC-PDU-STATS-ACK { sap=%u, l3pdu_tx=%u, octet_tx=%u, octet_retrans=%u, l3pdu_rx=%u, octet_rx=%u }\n",
gls->sapi, gls->ack_l3pdu_tx, gls->ack_octet_tx, gls->ack_l3pdu_retrans, gls->ack_l3pdu_rx, gls->ack_octet_rx);
printf("LLC-PDU-STATS-UNACK { sapi=%u, l3pdu_tx=%u, octet_tx=%u, l3pdu_rx=%u, octet_rx=%u }\n",
gls->sapi, gls->unack_l3pdu_tx, gls->unack_octet_tx, gls->unack_l3pdu_rx, gls->unack_octet_rx);
printf("LLC-PDU-STATS-LLPDU { tx=%u, rx=%u, fcs_err=%u, frm_rej=%u, tlli_err=%u, addr_err=%u, short_err=%u }\n",
gls->llpdu_tx, gls->llpdu_rx, gls->llpdu_fcs_err, gls->llpdu_frm_rej, gls->llpdu_tlli_err, gls->llpdu_addr_err, gls->llpdu_short_err);
}
static void handle_mac_state(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_state_change *msc;
msc = (struct gprs_mac_state_change *) msgb_data(msg);
const char *name = "";
switch (msc->mac_mode) {
case NULL_MODE:
name = get_value_string(gprs_mac_null_substate_vals, msc->mac_null_fsm_state);
break;
case IDLE_MODE:
name = get_value_string(gprs_mac_idle_substate_vals, msc->mac_idle_fsm_state);
break;
case TRANSFER_MODE:
name = get_value_string(gprs_mac_transfer_substate_vals, msc->mac_transfer_fsm_state);
break;
}
printf("MAC-STATE { mode=%s, state=%s }\n",
get_value_string(gprs_mac_mode_vals, msc->mac_mode), name);
}
static void handle_mac_dl_tbf_est(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_dl_tbf_est *dte;
dte = (struct gprs_mac_dl_tbf_est *) msgb_data(msg);
printf("MAC-DL-TBF-EST { tfi=%u, rlc_mode=%u, dl_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, egprs_link_qual_mode=%u, bep_period2=%u }\n",
dte->dl_tfi, dte->rlc_mode, dte->dl_ts_bmap, dte->is_egprs_tbf, dte->egprs_win_size, dte->egprs_link_qual_mode, dte->bep_period2);
}
static void handle_mac_ul_tbf_est(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_ul_tbf_est *ute;
ute = (struct gprs_mac_ul_tbf_est *) msgb_data(msg);
printf("MAC-UL-TBF-EST { tbf_req_cause=%u, acc_granted=%u, radio_prio=%u, peak_tput=%u, ul_tfi=%u, rlc_mode=%u, ul_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, resegment=%u, bep_period2=%u }\n",
ute->tbf_req_cause, ute->acc_granted, ute->radio_prio, ute->peak_tput, ute->ul_tfi, ute->rlc_mode, ute->ul_ts_bmap, ute->is_egprs_tbf, ute->egprs_win_size, ute->resegment, ute->bep_period2);
}
static void handle_mac_dl_tbf_rel(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_tbf_release *tr;
tr = (struct gprs_mac_tbf_release *) msgb_data(msg);
printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause);
}
static void handle_mac_ul_tbf_rel(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_tbf_release *tr;
tr = (struct gprs_mac_tbf_release *) msgb_data(msg);
printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause);
}
static void handle_rlc_ul_evt_cnt(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_ul_event_counts *uec;
uec = (struct gprs_rlc_ul_event_counts *) msgb_data(msg);
printf("RLC-UL-EVT-CNT { llc_event_cnt=%u, mac_event_cnt=%u, pl1_event_cnt=%u, tmr_event_cnt=%u }\n",
uec->llc_event_cnt, uec->mac_event_cnt, uec->pl1_event_cnt, uec->tmr_event_cnt);
}
static void handle_rlc_ul_stats(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_ul_stats *uls;
uls = (struct gprs_rlc_ul_stats *) msgb_data(msg);
printf("RLC-UL-STATS { state=%s(%s), FIXME... }\n",
get_value_string(gprs_rlc_ul_state_vals, uls->rlc_ul_state),
get_value_string(gprs_rlc_ul_substate_vals, uls->rlc_ul_substate));
}
static void handle_rlc_dl_stats(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_dl_stats *dls;
dls = (struct gprs_rlc_dl_stats *) msgb_data(msg);
printf("RLC-DL-STATS { state=%s, FIXME... }\n",
get_value_string(gprs_rlc_dl_state_vals, dls->rlc_dl_state));
}
static void handle_rlc_rel(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_release_ind *rli;
rli = (struct gprs_rlc_release_ind *) msgb_data(msg);
char ud = 'D';
if (lh->code == LOG_GPRS_RLC_UL_RELEASE_IND_C)
ud ='U';
printf("RLC-%cL-RELEASE { tfi=%u, cause=%u }\n", ud, rli->tfi, rli->cause);
}
static const struct diag_log_dispatch_tbl log_tbl[] = {
{ GSM(LOG_GPRS_LLC_ME_INFO_C), handle_llc_me_info },
{ GSM(LOG_GPRS_LLC_PDU_STATS_C), handle_llc_pdu_stats },
{ GSM(LOG_GPRS_GRR_STATE_C), handle_grr_state_msg },
{ GSM(LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C), handle_rlc_ul_abnrml_rls },
{ GSM(LOG_GPRS_RLC_UL_EVENT_COUNTS_C), handle_rlc_ul_evt_cnt },
{ GSM(LOG_GPRS_RLC_UL_RELEASE_IND_C), handle_rlc_rel },
{ GSM(LOG_GPRS_RLC_DL_RELEASE_IND_C), handle_rlc_rel },
{ GSM(LOG_GPRS_MAC_SIGNALLING_MESSAGE_C), handle_mac_sign_msg },
{ GSM(LOG_GPRS_MAC_STATE_C), handle_mac_state },
{ GSM(LOG_GPRS_MAC_DL_TBF_ESTABLISH_C), handle_mac_dl_tbf_est },
{ GSM(LOG_GPRS_MAC_UL_TBF_ESTABLISH_C), handle_mac_ul_tbf_est },
{ GSM(LOG_GPRS_MAC_DL_TBF_RELEASE_C), handle_mac_dl_tbf_rel },
{ GSM(LOG_GPRS_MAC_UL_TBF_RELEASE_C), handle_mac_ul_tbf_rel },
{ GSM(LOG_GPRS_RLC_UL_STATS_C), handle_rlc_ul_stats },
{ GSM(LOG_GPRS_RLC_DL_STATS_C), handle_rlc_dl_stats },
};
static __attribute__((constructor)) void on_dso_load_gprs(void)
{
diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl));
}

33
src/diag_log_gsm.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdio.h>
#include "diag_log.h"
#include "diag_gsm.h"
#include "log_codes_gsm.h"
static void handle_rr_sig_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gsm_rr_msg *rm = (struct diag_gsm_rr_msg *) msgb_data(msg);
printf("RR: %02x %02x %u: %s\n", rm->chan_type, rm->msg_type,
rm->length, osmo_hexdump(msgb_data(msg), rm->length));
}
static void handle_rr_state_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gsm_rr_state *rrs = (struct diag_gsm_rr_state *) msgb_data(msg);
printf("RR-STATE { state=%s, substate=%u, status=%u, mode=%u }\n",
get_value_string(diag_gsm_rr_st_vals, rrs->state)
, rrs->substate, rrs->status, rrs->mode);
}
static const struct diag_log_dispatch_tbl log_tbl[] = {
{ GSM(LOG_GSM_RR_SIGNALING_MESSAGE_C), handle_rr_sig_msg },
{ GSM(LOG_GSM_RR_STATE_C), handle_rr_state_msg },
};
static __attribute__((constructor)) void on_dso_load_gsm(void)
{
diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl));
}

85
src/diag_log_qmi.c Normal file
View File

@ -0,0 +1,85 @@
#include <stdint.h>
#include <stdio.h>
#include <libqmi-glib.h>
#include "diag_log.h"
#include "log_codes_qmi.h"
/* A small wrapper around libqmi-glib to give us a human-readable string
* representation of QMI messages that we receive from DIAG */
static int dump_qmi_msg(const uint8_t *data, unsigned int len)
{
GByteArray *buffer;
GError *error = NULL;
QmiMessage *message;
gchar *printable;
buffer = g_byte_array_sized_new(len);
g_byte_array_append(buffer, data, len);
message = qmi_message_new_from_raw(buffer, &error);
if (!message) {
fprintf(stderr, "qmi_message_new_from_raw() returned NULL\n");
return -1;
}
printable = qmi_message_get_printable(message, "QMI ");
fputs(printable, stdout);
g_free(printable);
return 0;
}
static void handle_qmi_msg(struct log_hdr *lh, struct msgb *msg)
{
dump_qmi_msg(lh->data, lh->len);
}
#define CORE(x) (0x1000 + x)
/* Tx and Rx might be switched */
#define LOG_QMI_PORT_RX(i) CORE(LOG_QMI_RESERVED_CODES_BASE_C+(i*2))
#define LOG_QMI_PORT_TX(i) CORE(LOG_QMI_RESERVED_CODES_BASE_C+(i*2)+1)
static const struct diag_log_dispatch_tbl log_tbl[] = {
{ CORE(LOG_QMI_CALL_FLOW_C), handle_qmi_msg },
{ CORE(LOG_QMI_SUPPORTED_INTERFACES_C), handle_qmi_msg },
{ LOG_QMI_PORT_RX(0), handle_qmi_msg },
{ LOG_QMI_PORT_RX(1), handle_qmi_msg },
{ LOG_QMI_PORT_RX(2), handle_qmi_msg },
{ LOG_QMI_PORT_RX(3), handle_qmi_msg },
{ LOG_QMI_PORT_RX(4), handle_qmi_msg },
{ LOG_QMI_PORT_RX(5), handle_qmi_msg },
{ LOG_QMI_PORT_RX(6), handle_qmi_msg },
{ LOG_QMI_PORT_RX(7), handle_qmi_msg },
{ LOG_QMI_PORT_RX(8), handle_qmi_msg },
{ LOG_QMI_PORT_RX(9), handle_qmi_msg },
{ LOG_QMI_PORT_RX(10), handle_qmi_msg },
{ LOG_QMI_PORT_RX(11), handle_qmi_msg },
{ LOG_QMI_PORT_RX(12), handle_qmi_msg },
{ LOG_QMI_PORT_RX(13), handle_qmi_msg },
{ LOG_QMI_PORT_RX(14), handle_qmi_msg },
{ LOG_QMI_PORT_RX(15), handle_qmi_msg },
{ LOG_QMI_PORT_TX(0), handle_qmi_msg },
{ LOG_QMI_PORT_TX(1), handle_qmi_msg },
{ LOG_QMI_PORT_TX(2), handle_qmi_msg },
{ LOG_QMI_PORT_TX(3), handle_qmi_msg },
{ LOG_QMI_PORT_TX(4), handle_qmi_msg },
{ LOG_QMI_PORT_TX(5), handle_qmi_msg },
{ LOG_QMI_PORT_TX(6), handle_qmi_msg },
{ LOG_QMI_PORT_TX(7), handle_qmi_msg },
{ LOG_QMI_PORT_TX(8), handle_qmi_msg },
{ LOG_QMI_PORT_TX(9), handle_qmi_msg },
{ LOG_QMI_PORT_TX(10), handle_qmi_msg },
{ LOG_QMI_PORT_TX(11), handle_qmi_msg },
{ LOG_QMI_PORT_TX(12), handle_qmi_msg },
{ LOG_QMI_PORT_TX(13), handle_qmi_msg },
{ LOG_QMI_PORT_TX(14), handle_qmi_msg },
{ LOG_QMI_PORT_TX(15), handle_qmi_msg },
};
static __attribute__((constructor)) void on_dso_load_qmi(void)
{
diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl));
}

25
src/diag_log_umts.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdio.h>
#include "diag_log.h"
#include "diag_wcdma.h"
#include "log_codes_wcdma.h"
static void handle_rrc_sig_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_umts_rrc_msg *rrm = (struct diag_umts_rrc_msg *) msgb_data(msg);
printf("RRC: %u %u %u: %s\n", rrm->chan_type, rrm->rb_id, rrm->length,
osmo_hexdump(msgb_data(msg), rrm->length));
}
#define UMTS(x) (0x4000 + x)
static const struct diag_log_dispatch_tbl log_tbl[] = {
{ UMTS(LOG_WCDMA_SIGNALING_MSG_C), handle_rrc_sig_msg },
};
static __attribute__((constructor)) void on_dso_load_umts(void)
{
diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl));
}

View File

@ -1,5 +1,7 @@
#pragma once
#define GSM(x) (0x5000 + x)
enum diag_log_code_gsm {
LOG_GSM_POWER_SCAN_C = 0x64,
LOG_GSM_FCCH_DECODE_C = 0x65,

View File

@ -1,29 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <libqmi-glib.h>
/* A small wrapper around libqmi-glib to give us a human-readable string
* representation of QMI messages that we receive from DIAG */
int dump_qmi_msg(const uint8_t *data, unsigned int len)
{
GByteArray *buffer;
GError *error = NULL;
QmiMessage *message;
gchar *printable;
buffer = g_byte_array_sized_new(len);
g_byte_array_append(buffer, data, len);
message = qmi_message_new_from_raw(buffer, &error);
if (!message) {
fprintf(stderr, "qmi_message_new_from_raw() returned NULL\n");
return -1;
}
printable = qmi_message_get_printable(message, "QMI ");
fputs(printable, stdout);
g_free(printable);
return 0;
}

View File

@ -1,4 +0,0 @@
#pragma once
#include <stdint.h>
int dump_qmi_msg(const uint8_t *data, unsigned int len);

View File

@ -16,16 +16,8 @@
#include "diag_io.h"
#include "protocol.h"
#include "config.h"
#include "diag_log.h"
#include "diagcmd.h"
#include "diag_gsm.h"
#include "log_codes_gsm.h"
#include "log_codes_wcdma.h"
#include "log_codes_qmi.h"
#include "diag_wcdma.h"
#include "gprs_rlc.h"
#include "gprs_mac.h"
#include "qmi_decode.h"
/* handler for EXT MSG */
static int diag_rx_ext_msg_f(const uint8_t *data, const size_t len)
@ -66,248 +58,13 @@ static int diag_rx_ext_msg_f(const uint8_t *data, const size_t len)
return 0;
}
static void handle_rr_sig_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gsm_rr_msg *rm = (struct diag_gsm_rr_msg *) msgb_data(msg);
printf("RR: %02x %02x %u: %s\n", rm->chan_type, rm->msg_type,
rm->length, osmo_hexdump(msgb_data(msg), rm->length));
}
static void handle_rr_state_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gsm_rr_state *rrs = (struct diag_gsm_rr_state *) msgb_data(msg);
printf("RR-STATE { state=%s, substate=%u, status=%u, mode=%u }\n",
get_value_string(diag_gsm_rr_st_vals, rrs->state)
, rrs->substate, rrs->status, rrs->mode);
}
static void handle_grr_state_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gprs_grr_state *rrs = (struct diag_gprs_grr_state *) msgb_data(msg);
printf("GRR-STATE { active=%u, state=%s }\n", rrs->active_state,
get_value_string(diag_gprs_grr_st_vals, rrs->grr_state));
}
static void handle_rrc_sig_msg(struct log_hdr *lh, struct msgb *msg)
{
struct diag_umts_rrc_msg *rrm = (struct diag_umts_rrc_msg *) msgb_data(msg);
printf("RRC: %u %u %u: %s\n", rrm->chan_type, rrm->rb_id, rrm->length,
osmo_hexdump(msgb_data(msg), rrm->length));
}
static void handle_rlc_ul_abnrml_rls(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_ul_abnrml_rls_counts *arc;
arc = (struct gprs_rlc_ul_abnrml_rls_counts *) msgb_data(msg);
printf("RLC-UL-ABNRML-RLS-COUNTS { access_reject_cnt=%u, arc_retry_cnt=%u, arc_wo_retry_cnt=%u, arc_sys_info_cnt=%u }",
arc->access_reject_cnt, arc->arc_retry_cnt, arc->arc_wo_retry_cnt, arc->arc_sys_info_cnt);
}
static void handle_mac_sign_msg(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_signalling_msg *msm;
msm = (struct gprs_mac_signalling_msg *) msgb_data(msg);
printf("MAC-SIGN-MSG { chan_type=%s, msg_type=%s, msg=%s }\n",
get_value_string(gprs_mac_chan_type_vals, msm->chan_type),
get_value_string(gprs_mac_msg_type_vals, msm->msg_type),
osmo_hexdump(msm->msg, msm->msg_len));
}
static void handle_llc_me_info(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gprs_llme_info *gli;
gli = (struct diag_gprs_llme_info *) msgb_data(msg);
printf("LLC-ME-INFO { state=%s, xid_version=%u, tlli_new=0x%08x, tlli_old=0x%08x, gea=%u, key=%s }\n",
get_value_string(diag_gprs_llme_st_vals, gli->state), gli->xid_version,
gli->tlli_new, gli->tlli_old, gli->enc_alg,
osmo_hexdump_nospc(gli->enc_key, sizeof(gli->enc_key)));
}
static void handle_llc_pdu_stats(struct log_hdr *lh, struct msgb *msg)
{
struct diag_gprs_llc_stats *gls;
gls = (struct diag_gprs_llc_stats *) msgb_data(msg);
printf("LLC-PDU-STATS-ACK { sap=%u, l3pdu_tx=%u, octet_tx=%u, octet_retrans=%u, l3pdu_rx=%u, octet_rx=%u }\n",
gls->sapi, gls->ack_l3pdu_tx, gls->ack_octet_tx, gls->ack_l3pdu_retrans, gls->ack_l3pdu_rx, gls->ack_octet_rx);
printf("LLC-PDU-STATS-UNACK { sapi=%u, l3pdu_tx=%u, octet_tx=%u, l3pdu_rx=%u, octet_rx=%u }\n",
gls->sapi, gls->unack_l3pdu_tx, gls->unack_octet_tx, gls->unack_l3pdu_rx, gls->unack_octet_rx);
printf("LLC-PDU-STATS-LLPDU { tx=%u, rx=%u, fcs_err=%u, frm_rej=%u, tlli_err=%u, addr_err=%u, short_err=%u }\n",
gls->llpdu_tx, gls->llpdu_rx, gls->llpdu_fcs_err, gls->llpdu_frm_rej, gls->llpdu_tlli_err, gls->llpdu_addr_err, gls->llpdu_short_err);
}
static void handle_mac_state(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_state_change *msc;
msc = (struct gprs_mac_state_change *) msgb_data(msg);
const char *name = "";
switch (msc->mac_mode) {
case NULL_MODE:
name = get_value_string(gprs_mac_null_substate_vals, msc->mac_null_fsm_state);
break;
case IDLE_MODE:
name = get_value_string(gprs_mac_idle_substate_vals, msc->mac_idle_fsm_state);
break;
case TRANSFER_MODE:
name = get_value_string(gprs_mac_transfer_substate_vals, msc->mac_transfer_fsm_state);
break;
}
printf("MAC-STATE { mode=%s, state=%s }\n",
get_value_string(gprs_mac_mode_vals, msc->mac_mode), name);
}
static void handle_mac_dl_tbf_est(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_dl_tbf_est *dte;
dte = (struct gprs_mac_dl_tbf_est *) msgb_data(msg);
printf("MAC-DL-TBF-EST { tfi=%u, rlc_mode=%u, dl_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, egprs_link_qual_mode=%u, bep_period2=%u }\n",
dte->dl_tfi, dte->rlc_mode, dte->dl_ts_bmap, dte->is_egprs_tbf, dte->egprs_win_size, dte->egprs_link_qual_mode, dte->bep_period2);
}
static void handle_mac_ul_tbf_est(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_ul_tbf_est *ute;
ute = (struct gprs_mac_ul_tbf_est *) msgb_data(msg);
printf("MAC-UL-TBF-EST { tbf_req_cause=%u, acc_granted=%u, radio_prio=%u, peak_tput=%u, ul_tfi=%u, rlc_mode=%u, ul_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, resegment=%u, bep_period2=%u }\n",
ute->tbf_req_cause, ute->acc_granted, ute->radio_prio, ute->peak_tput, ute->ul_tfi, ute->rlc_mode, ute->ul_ts_bmap, ute->is_egprs_tbf, ute->egprs_win_size, ute->resegment, ute->bep_period2);
}
static void handle_mac_dl_tbf_rel(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_tbf_release *tr;
tr = (struct gprs_mac_tbf_release *) msgb_data(msg);
printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause);
}
static void handle_mac_ul_tbf_rel(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_mac_tbf_release *tr;
tr = (struct gprs_mac_tbf_release *) msgb_data(msg);
printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause);
}
static void handle_rlc_ul_evt_cnt(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_ul_event_counts *uec;
uec = (struct gprs_rlc_ul_event_counts *) msgb_data(msg);
printf("RLC-UL-EVT-CNT { llc_event_cnt=%u, mac_event_cnt=%u, pl1_event_cnt=%u, tmr_event_cnt=%u }\n",
uec->llc_event_cnt, uec->mac_event_cnt, uec->pl1_event_cnt, uec->tmr_event_cnt);
}
static void handle_rlc_ul_stats(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_ul_stats *uls;
uls = (struct gprs_rlc_ul_stats *) msgb_data(msg);
printf("RLC-UL-STATS { state=%s(%s), FIXME... }\n",
get_value_string(gprs_rlc_ul_state_vals, uls->rlc_ul_state),
get_value_string(gprs_rlc_ul_substate_vals, uls->rlc_ul_substate));
}
static void handle_rlc_dl_stats(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_dl_stats *dls;
dls = (struct gprs_rlc_dl_stats *) msgb_data(msg);
printf("RLC-DL-STATS { state=%s, FIXME... }\n",
get_value_string(gprs_rlc_dl_state_vals, dls->rlc_dl_state));
}
static void handle_rlc_rel(struct log_hdr *lh, struct msgb *msg)
{
struct gprs_rlc_release_ind *rli;
rli = (struct gprs_rlc_release_ind *) msgb_data(msg);
char ud = 'D';
if (lh->code == LOG_GPRS_RLC_UL_RELEASE_IND_C)
ud ='U';
printf("RLC-%cL-RELEASE { tfi=%u, cause=%u }\n", ud, rli->tfi, rli->cause);
}
struct log_dispatch_tbl {
uint16_t code;
void (*handler)(struct log_hdr *lh, struct msgb *msg);
};
#define GSM(x) (0x5000 + x)
#define UMTS(x) (0x4000 + x)
static const struct log_dispatch_tbl log_tbl[] = {
{ GSM(LOG_GSM_RR_SIGNALING_MESSAGE_C), handle_rr_sig_msg },
{ GSM(LOG_GSM_RR_STATE_C), handle_rr_state_msg },
{ GSM(LOG_GPRS_LLC_ME_INFO_C), handle_llc_me_info },
{ GSM(LOG_GPRS_LLC_PDU_STATS_C), handle_llc_pdu_stats },
{ GSM(LOG_GPRS_GRR_STATE_C), handle_grr_state_msg },
{ GSM(LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C), handle_rlc_ul_abnrml_rls },
{ GSM(LOG_GPRS_RLC_UL_EVENT_COUNTS_C), handle_rlc_ul_evt_cnt },
{ GSM(LOG_GPRS_RLC_UL_RELEASE_IND_C), handle_rlc_rel },
{ GSM(LOG_GPRS_RLC_DL_RELEASE_IND_C), handle_rlc_rel },
{ GSM(LOG_GPRS_MAC_SIGNALLING_MESSAGE_C), handle_mac_sign_msg },
{ GSM(LOG_GPRS_MAC_STATE_C), handle_mac_state },
{ GSM(LOG_GPRS_MAC_DL_TBF_ESTABLISH_C), handle_mac_dl_tbf_est },
{ GSM(LOG_GPRS_MAC_UL_TBF_ESTABLISH_C), handle_mac_ul_tbf_est },
{ GSM(LOG_GPRS_MAC_DL_TBF_RELEASE_C), handle_mac_dl_tbf_rel },
{ GSM(LOG_GPRS_MAC_UL_TBF_RELEASE_C), handle_mac_ul_tbf_rel },
{ GSM(LOG_GPRS_RLC_UL_STATS_C), handle_rlc_ul_stats },
{ GSM(LOG_GPRS_RLC_DL_STATS_C), handle_rlc_dl_stats },
{ UMTS(LOG_WCDMA_SIGNALING_MSG_C), handle_rrc_sig_msg },
};
static void diag_log_handle(struct msgb *msg)
{
struct diag_log_hdr *dlh;
struct log_hdr *lh;
int i;
dlh = (struct diag_log_hdr *) msg->data;
/* FIXME: verify length */
msg->l3h = msgb_pull(msg, sizeof(*dlh));
lh = (struct log_hdr *) msg->l3h;
/* FIXME: verify length */
msgb_pull(msg, sizeof(*lh));
printf("LOG(0x%04x|%u|%u): ", lh->code,
diag_ts_to_epoch(lh->ts), diag_ts_to_fn(lh->ts));
for (i = 0; i < ARRAY_SIZE(log_tbl); i++) {
if (log_tbl[i].code == lh->code) {
log_tbl[i].handler(lh, msg);
return;
}
}
printf("%s\n", osmo_hexdump(lh->data, lh->len));
uint8_t subsys = lh->code >> 12;
if (subsys == 0x01 &&
((lh->code & 0xfff) >= LOG_QMI_RESERVED_CODES_BASE_C) &&
((lh->code & 0xfff) <= LOG_QMI_LAST_C))
dump_qmi_msg(lh->data, lh->len);
}
/*********/
static void diag_process_msg(struct diag_instance *di, struct msgb *msg)
{
switch (msg->l2h[0]) {
case DIAG_LOG_F:
diag_log_handle(msg);
diag_log_handle(di, msg);
break;
case DIAG_EXT_MSG_F:
diag_rx_ext_msg_f(msgb_data(msg), msgb_length(msg));
@ -361,6 +118,7 @@ static void do_configure(struct diag_instance *di)
diag_transmit_buf(di, extended_report_cfg, sizeof(extended_report_cfg));
diag_read(di);
#if 0
printf("GSM\n");
struct msgb *msg = gen_log_config_set_mask(5, 1064);
#if 0
@ -369,38 +127,20 @@ static void do_configure(struct diag_instance *di)
#endif
log_config_set_mask_bit(msg, LOG_GSM_RR_CONTROL_CHANNEL_PARAMS_C);
log_config_set_mask_bit(msg, LOG_GSM_RR_SIGNALING_MESSAGE_C);
log_config_set_mask_bit(msg, LOG_GSM_RR_STATE_C);
log_config_set_mask_bit(msg, LOG_GPRS_GRR_STATE_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_EVENT_COUNTS_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_STATS_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_STATS_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_ACKNACK_PARAMS_VER2_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_ACKNACK_PARAMS_VER2_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_RELEASE_IND_C);
log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_RELEASE_IND_C);
log_config_set_mask_bit(msg, LOG_EGPRS_RLC_DL_HEADER_C);
log_config_set_mask_bit(msg, LOG_EGPRS_RLC_UL_HEADER_C);
log_config_set_mask_bit(msg, LOG_GPRS_LLC_ME_INFO_C);
log_config_set_mask_bit(msg, LOG_GPRS_LLC_PDU_STATS_C);
log_config_set_mask_bit(msg, LOG_GPRS_LLC_PERIODIC_STATS_C);
log_config_set_mask_bit(msg, LOG_GPRS_SNDCP_UL_TCP_HDR_C);
log_config_set_mask_bit(msg, LOG_GPRS_SNDCP_DL_TCP_HDR_C);
log_config_set_mask_bit(msg, 546);
log_config_set_mask_bit(msg, 547);
log_config_set_mask_bit(msg, LOG_GPRS_MAC_STATE_C);
log_config_set_mask_bit(msg, LOG_GPRS_MAC_SIGNALLING_MESSAGE_C);
log_config_set_mask_bit(msg, LOG_GPRS_MAC_UL_TBF_ESTABLISH_C);
log_config_set_mask_bit(msg, LOG_GPRS_MAC_DL_TBF_ESTABLISH_C);
log_config_set_mask_bit(msg, LOG_EGPRS_MAC_UL_ACKNACK_C);
log_config_set_mask_bit(msg, LOG_EGPRS_MAC_DL_ACKNACK_C);
log_config_set_mask_bit(msg, LOG_GPRS_MAC_UL_TBF_RELEASE_C);
log_config_set_mask_bit(msg, LOG_GPRS_MAC_DL_TBF_RELEASE_C);
diag_transmit_msgb(di, msg);
diag_read(di);
@ -416,23 +156,12 @@ static void do_configure(struct diag_instance *di)
log_config_set_mask_bit(msg, 0x127);
log_config_set_mask_bit(msg, 0x128);
log_config_set_mask_bit(msg, 0x129);
log_config_set_mask_bit(msg, LOG_WCDMA_SIGNALING_MSG_C);
diag_transmit_msgb(di, msg);
diag_read(di);
printf("Core\n");
msg = gen_log_config_set_mask(1, 1064);
log_config_set_mask_bit(msg, LOG_QMI_CALL_FLOW_C);
log_config_set_mask_bit(msg, LOG_QMI_SUPPORTED_INTERFACES_C);
for (int i = 0; i < 16*2; i++)
log_config_set_mask_bit(msg, LOG_QMI_RESERVED_CODES_BASE_C+i);
for (int i = LOG_QMI_RESERVED_CODES_BASE_C; i < LOG_QMI_LAST_C; i++)
log_config_set_mask_bit(msg, i);
diag_transmit_msgb(di, msg);
diag_read(di);
#else
diag_log_enable_all_supported(di);
#endif
}
int main(int argc, char **argv)