ns: Handle procedure changes for UDP in TS 48.016 (TODO)

Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2015-05-29 19:45:22 +02:00
parent 91ff17c9ef
commit ecb5e8ed25
3 changed files with 93 additions and 8 deletions

View File

@ -61,6 +61,11 @@ enum gprs_ns_cs {
GPRS_NS_CS_ERROR, /*!< Failed to process message */
};
enum gprs_ns_spec {
GPRS_NS_TS_08_16 = 0,
GPRS_NS_TS_48_016,
};
struct gprs_nsvc;
/*! \brief Osmocom GPRS callback function type */
typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
@ -119,10 +124,13 @@ struct gprs_nsvc {
struct osmo_timer_list timer;
enum nsvc_timer_mode timer_mode;
int alive_retries;
enum gprs_ns_spec compliance;
unsigned int remote_end_is_sgsn:1;
unsigned int persistent:1;
unsigned int nsvci_is_valid:1;
unsigned int static_config:1;
unsigned int config_completed:1;
struct rate_ctr_group *ctrg;

View File

@ -126,11 +126,28 @@ static const struct rate_ctr_group_desc nsvc_ctrg_desc = {
.ctr_desc = nsvc_ctr_description,
};
static void nsvc_start_timer(struct gprs_nsvc *nsvc, enum nsvc_timer_mode mode);
#define CHECK_TX_RC(rc, nsvc) \
if (rc < 0) \
LOGP(DNS, LOGL_ERROR, "TX failed (%d) to peer %s\n", \
rc, gprs_ns_ll_str(nsvc));
static int enable_reset_block_proc(const struct gprs_nsvc *nsvc)
{
return nsvc->compliance != GPRS_NS_TS_48_016 ||
!nsvc->static_config ||
nsvc->ll != GPRS_NS_LL_UDP;
}
static int continue_test_proc(const struct gprs_nsvc *nsvc)
{
return nsvc->compliance == GPRS_NS_TS_48_016 &&
nsvc->static_config &&
nsvc->ll == GPRS_NS_LL_UDP &&
nsvc->remote_end_is_sgsn;
}
struct msgb *gprs_ns_msgb_alloc(void)
{
struct msgb *msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM,
@ -552,16 +569,24 @@ static void gprs_ns_timer_cb(void *data)
nsvc->alive_retries++;
if (nsvc->alive_retries >
nsvc->nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES]) {
/* mark as dead and blocked */
nsvc->state = NSE_S_BLOCKED;
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]);
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_DEAD]);
LOGP(DNS, LOGL_NOTICE,
"NSEI=%u Tns-alive expired more then "
"%u times, blocking NS-VC\n", nsvc->nsei,
nsvc->nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES]);
/* mark as dead */
nsvc->state = nsvc->state & ~NSE_S_ALIVE;
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_DEAD]);
ns_osmo_signal_dispatch(nsvc, S_NS_ALIVE_EXP, 0);
ns_osmo_signal_dispatch(nsvc, S_NS_BLOCK, NS_CAUSE_NSVC_BLOCKED);
if (continue_test_proc(nsvc)) {
nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST);
} else if (enable_reset_block_proc(nsvc)) {
/* mark as blocked */
nsvc->state = NSE_S_BLOCKED;
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]);
ns_osmo_signal_dispatch(nsvc, S_NS_BLOCK,
NS_CAUSE_NSVC_BLOCKED);
}
return;
}
/* Tns-test case: send NS-ALIVE PDU */
@ -1064,6 +1089,14 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
return rc;
rc = 0;
} else if (nsvc->static_config && !nsvc->config_completed) {
if (!enable_reset_block_proc(nsvc)) {
nsvc->state = NSE_S_ALIVE;
nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST);
}
nsvc->config_completed = 1;
}
if (nsvc)
@ -1266,10 +1299,18 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg,
* NS-ALIVE out of the blue, we might have been re-started
* and should send a NS-RESET to make sure everything recovers
* fine. */
if ((*nsvc)->state == NSE_S_BLOCKED)
if ((*nsvc)->state == NSE_S_BLOCKED) {
rc = gprs_nsvc_reset((*nsvc), NS_CAUSE_PDU_INCOMP_PSTATE);
else if (!((*nsvc)->state & NSE_S_RESET))
} else if (!((*nsvc)->state & NSE_S_RESET)) {
rc = gprs_ns_tx_alive_ack(*nsvc);
if (!enable_reset_block_proc(*nsvc) &&
!((*nsvc)->state & NSE_S_ALIVE))
{
/* start the test procedure */
gprs_ns_tx_simple((*nsvc), NS_PDUT_ALIVE);
nsvc_start_timer((*nsvc), NSVC_TIMER_TNS_TEST);
}
}
break;
case NS_PDUT_ALIVE_ACK:
/* stop Tns-alive and start Tns-test */
@ -1557,7 +1598,12 @@ struct gprs_nsvc *gprs_ns_nsip_connect(struct gprs_ns_inst *nsi,
nsvc->nsei = nsei;
nsvc->remote_end_is_sgsn = 1;
gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
if (enable_reset_block_proc(nsvc)) {
gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
} else if (continue_test_proc(nsvc)) {
nsvc->state = NSE_S_ALIVE;
nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST);
}
return nsvc;
}

View File

@ -91,6 +91,11 @@ static int config_write_ns(struct vty *vty)
vty_out(vty, " nse %u remote-role %s%s",
nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss",
VTY_NEWLINE);
vty_out(vty, " nse %u compliance %s%s",
nsvc->nsei,
nsvc->compliance == GPRS_NS_TS_08_16 ?
"ts08.16" : "ts48.016",
VTY_NEWLINE);
switch (nsvc->ll) {
case GPRS_NS_LL_UDP:
vty_out(vty, " nse %u encapsulation udp%s", nsvc->nsei,
@ -255,6 +260,7 @@ DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
if (!nsvc) {
nsvc = gprs_nsvc_create(vty_nsi, nsvci);
nsvc->nsei = nsei;
nsvc->static_config = 1;
}
nsvc->nsvci = nsvci;
/* All NSVCs that are explicitly configured by VTY are
@ -387,6 +393,30 @@ DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_nse_compliance, cfg_nse_compliance_cmd,
"nse <0-65535> compliance (ts08.16|ts48.016)",
NSE_CMD_STR
"Set protocol compliance\n"
"Use 3GPP TS 08.16\n"
"Use 3GPP TS 48.016\n")
{
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(argv[1], "ts08.16"))
nsvc->compliance = GPRS_NS_TS_08_16;
else
nsvc->compliance = GPRS_NS_TS_48_016;
return CMD_SUCCESS;
}
DEFUN(cfg_no_nse, cfg_no_nse_cmd,
"no nse <0-65535>",
"Delete Persistent NS Entity\n"
@ -591,6 +621,7 @@ int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
install_element(L_NS_NODE, &cfg_nse_fr_dlci_cmd);
install_element(L_NS_NODE, &cfg_nse_encaps_cmd);
install_element(L_NS_NODE, &cfg_nse_remoterole_cmd);
install_element(L_NS_NODE, &cfg_nse_compliance_cmd);
install_element(L_NS_NODE, &cfg_no_nse_cmd);
install_element(L_NS_NODE, &cfg_ns_timer_cmd);
install_element(L_NS_NODE, &cfg_nsip_local_ip_cmd);