From patchwork Mon Jan 4 18:11:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Erlbeck X-Patchwork-Id: 562613 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.osmocom.org (unknown [IPv6:2a01:4f8:191:444b::2:7]) by ozlabs.org (Postfix) with ESMTP id 5BB90140326 for ; Tue, 5 Jan 2016 05:11:24 +1100 (AEDT) Received: from lists.osmocom.org (lists.osmocom.org [144.76.43.76]) by lists.osmocom.org (Postfix) with ESMTP id 179BAB5FD; Mon, 4 Jan 2016 18:11:22 +0000 (UTC) X-Original-To: openbsc@lists.osmocom.org Delivered-To: openbsc@lists.osmocom.org Received: from mail.sysmocom.de (mail.sysmocom.de [IPv6:2a01:4f8:191:444c::2:4]) by lists.osmocom.org (Postfix) with ESMTP id BE1D4B5F4 for ; Mon, 4 Jan 2016 18:11:20 +0000 (UTC) Received: from sysmocom-tmp.am93.sysmocom.de (ip5b418565.dynamic.kabel-deutschland.de [91.65.133.101]) by mail.sysmocom.de (Postfix) with ESMTPSA id 681A71B2A5; Mon, 4 Jan 2016 18:11:20 +0000 (UTC) From: Jacob Erlbeck To: openbsc@lists.osmocom.org Subject: [PATCH] ns: Handle procedure changes for UDP in TS 48.016 Date: Mon, 4 Jan 2016 19:11:07 +0100 Message-Id: <1451931067-7511-1-git-send-email-jerlbeck@sysmocom.de> X-Mailer: git-send-email 1.9.1 X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Development of the OpenBSC GSM base station controller List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openbsc-bounces@lists.osmocom.org Sender: "OpenBSC" In TS 48.016 the network service procedure change depending on the network link type being used. This mainly affects the reset and test procedures. Not obeying these changes makes it impossible to set up NSVC with equipment relying on them. This commits adds the possibility to be compliant to either specification by adding a configuration option to select the compliance mode explicitly for each NSE. The TS 48.016 mode mainly gains conformance, but hinders dynamic NSCV establishment since there aren't any RESET messages. Therefore that mode is not enabled by default. Note that dynamic NSVC establishment as defined by TS 48.016 is not being implemented, since it does not work with routers using network address translation (NAT). New VTY commands (config-ns node): - nse <0-65535> compliance ts08.16 Just use UDP instead of FR - nse <0-65535> compliance ts48.016 Use the modified procedures 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 7c3b23c..1219307 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, @@ -120,10 +125,13 @@ struct gprs_nsvc { enum nsvc_timer_mode timer_mode; struct timeval timer_started; 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; struct osmo_stat_item_group *statg; diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index a29c946..0e874cf 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -149,11 +149,28 @@ static const struct osmo_stat_item_group_desc nsvc_statg_desc = { .class_id = OSMO_STATS_CLASS_PEER, }; +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, @@ -588,16 +605,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 */ @@ -1109,6 +1134,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) @@ -1311,10 +1344,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: if ((*nsvc)->timer_mode == NSVC_TIMER_TNS_ALIVE) @@ -1605,7 +1646,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 5a951dc..1353bf3 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, @@ -257,6 +262,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 @@ -389,6 +395,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" @@ -593,6 +623,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);