From ecb5e8ed258a471f5647c7d97a999aced951f53a Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Fri, 29 May 2015 19:45:22 +0200 Subject: ns: Handle procedure changes for UDP in TS 48.016 (TODO) Sponsored-by: On-Waves ehf --- include/osmocom/gprs/gprs_ns.h | 8 ++++++ src/gb/gprs_ns.c | 62 ++++++++++++++++++++++++++++++++++++------ src/gb/gprs_ns_vty.c | 31 +++++++++++++++++++++ 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index d5a605df..820700f4 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -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; diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 827d09d7..eca4dc35 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -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; } diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c index 155e1e97..29aeb137 100644 --- a/src/gb/gprs_ns_vty.c +++ b/src/gb/gprs_ns_vty.c @@ -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); -- cgit v1.2.3