diff options
-rw-r--r-- | include/osmocom/gprs/gprs_ns.h | 2 | ||||
-rw-r--r-- | src/gb/gprs_ns.c | 17 | ||||
-rw-r--r-- | src/gb/gprs_ns_vty.c | 62 |
3 files changed, 57 insertions, 24 deletions
diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index 02faa506..94d30368 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -97,6 +97,8 @@ struct gprs_ns_inst { uint32_t remote_ip; uint16_t remote_port; int dscp; + /*! IPA compatibility: NS-RESET/BLOCK/UNBLOCK even on IP-SNS */ + bool use_reset_block_unblock; } nsip; /*! NS-over-FR-over-GRE-over-IP specific bits */ struct { diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 4e584adc..f1b36f44 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -327,7 +327,7 @@ struct gprs_nsvc *gprs_nsvc_create2(struct gprs_ns_inst *nsi, uint16_t nsvci, nsvc->nsvci = nsvci; nsvc->nsvci_is_valid = 1; /* before RESET procedure: BLOCKED and DEAD */ - if (nsi->bss_sns_fi) + if (nsi->bss_sns_fi || !nsi->nsip.use_reset_block_unblock) ns_set_state(nsvc, 0); else ns_set_state(nsvc, NSE_S_BLOCKED); @@ -793,7 +793,7 @@ static void gprs_ns_timer_cb(void *data) nsvc->nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES]) { /* mark as dead (and blocked unless IP-SNS) */ rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_DEAD]); - if (!nsvc->nsi->bss_sns_fi) { + if (!nsvc->nsi->bss_sns_fi && nsvc->nsi->nsip.use_reset_block_unblock) { ns_set_state(nsvc, NSE_S_BLOCKED); rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]); } else @@ -804,7 +804,7 @@ static void gprs_ns_timer_cb(void *data) nsvc->nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES]); ns_osmo_signal_dispatch(nsvc, S_NS_ALIVE_EXP, 0); /* FIXME: should we send this signal in case of SNS? */ - if (!nsvc->nsi->bss_sns_fi) + if (!nsvc->nsi->bss_sns_fi && nsvc->nsi->nsip.use_reset_block_unblock) ns_osmo_signal_dispatch(nsvc, S_NS_BLOCK, NS_CAUSE_NSVC_BLOCKED); return; } @@ -1758,8 +1758,12 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, * fine. */ 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)) { + /* if we're not alive, we cannot transmit the ACK; set ALIVE */ + if (!((*nsvc)->state & NSE_S_ALIVE)) + ns_mark_alive(*nsvc); rc = gprs_ns_tx_alive_ack(*nsvc); + } break; case NS_PDUT_ALIVE_ACK: ns_mark_alive(*nsvc); @@ -1915,6 +1919,11 @@ struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb, void *ctx) llist_del(&nsi->unknown_nsvc->list); INIT_LLIST_HEAD(&nsi->unknown_nsvc->list); + /* By default we are in IPA compatible mode, that is we use NS-RESET, NS-BLOCK + * and NS-UNBLOCK procedures even for an IP/UDP based Gb interface, in violation + * of 3GPP TS 48.016. */ + nsi->nsip.use_reset_block_unblock = true; + return nsi; } diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c index 9cffb71d..bd53f2f1 100644 --- a/src/gb/gprs_ns_vty.c +++ b/src/gb/gprs_ns_vty.c @@ -90,6 +90,32 @@ static int config_write_ns(struct vty *vty) vty_out(vty, "ns%s", VTY_NEWLINE); + /* global configuration must be written first, as some of it may be + * relevant when creating the NSE/NSVC later below */ + + if (vty_nsi->nsip.local_ip) { + ia.s_addr = osmo_htonl(vty_nsi->nsip.local_ip); + vty_out(vty, " encapsulation udp local-ip %s%s", + inet_ntoa(ia), VTY_NEWLINE); + } + if (vty_nsi->nsip.local_port) + vty_out(vty, " encapsulation udp local-port %u%s", + vty_nsi->nsip.local_port, VTY_NEWLINE); + if (vty_nsi->nsip.dscp) + vty_out(vty, " encapsulation udp dscp %d%s", + vty_nsi->nsip.dscp, VTY_NEWLINE); + + vty_out(vty, " encapsulation udp use-reset-block-unblock %s%s", + vty_nsi->nsip.use_reset_block_unblock ? "enabled" : "disabled", VTY_NEWLINE); + + vty_out(vty, " encapsulation framerelay-gre enabled %u%s", + vty_nsi->frgre.enabled ? 1 : 0, VTY_NEWLINE); + if (vty_nsi->frgre.local_ip) { + ia.s_addr = osmo_htonl(vty_nsi->frgre.local_ip); + vty_out(vty, " encapsulation framerelay-gre local-ip %s%s", + inet_ntoa(ia), VTY_NEWLINE); + } + llist_for_each_entry(nsvc, &vty_nsi->gprs_nsvcs, list) { if (!nsvc->persistent) continue; @@ -130,26 +156,6 @@ static int config_write_ns(struct vty *vty) get_value_string(gprs_ns_timer_strs, i), vty_nsi->timeout[i], VTY_NEWLINE); - if (vty_nsi->nsip.local_ip) { - ia.s_addr = osmo_htonl(vty_nsi->nsip.local_ip); - vty_out(vty, " encapsulation udp local-ip %s%s", - inet_ntoa(ia), VTY_NEWLINE); - } - if (vty_nsi->nsip.local_port) - vty_out(vty, " encapsulation udp local-port %u%s", - vty_nsi->nsip.local_port, VTY_NEWLINE); - if (vty_nsi->nsip.dscp) - vty_out(vty, " encapsulation udp dscp %d%s", - vty_nsi->nsip.dscp, VTY_NEWLINE); - - vty_out(vty, " encapsulation framerelay-gre enabled %u%s", - vty_nsi->frgre.enabled ? 1 : 0, VTY_NEWLINE); - if (vty_nsi->frgre.local_ip) { - ia.s_addr = osmo_htonl(vty_nsi->frgre.local_ip); - vty_out(vty, " encapsulation framerelay-gre local-ip %s%s", - inet_ntoa(ia), VTY_NEWLINE); - } - return CMD_SUCCESS; } @@ -500,6 +506,21 @@ DEFUN(cfg_nsip_dscp, cfg_nsip_dscp_cmd, return CMD_SUCCESS; } +DEFUN(cfg_nsip_res_block_unblock, cfg_nsip_res_block_unblock_cmd, + "encapsulation udp use-reset-block-unblock (enabled|disabled)", + ENCAPS_STR "NS over UDP Encapsulation\n" + "Use NS-{RESET,BLOCK,UNBLOCK} procedures in violation of 3GPP TS 48.016\n" + "Enable NS-{RESET,BLOCK,UNBLOCK}\n" + "Disable NS-{RESET,BLOCK,UNBLOCK}\n") +{ + if (!strcmp(argv[0], "enabled")) + vty_nsi->nsip.use_reset_block_unblock = true; + else + vty_nsi->nsip.use_reset_block_unblock = false; + + return CMD_SUCCESS; +} + DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd, "encapsulation framerelay-gre local-ip A.B.C.D", ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n" @@ -643,6 +664,7 @@ int gprs_ns_vty_init(struct gprs_ns_inst *nsi) install_element(L_NS_NODE, &cfg_nsip_local_ip_cmd); install_element(L_NS_NODE, &cfg_nsip_local_port_cmd); install_element(L_NS_NODE, &cfg_nsip_dscp_cmd); + install_element(L_NS_NODE, &cfg_nsip_res_block_unblock_cmd); install_element(L_NS_NODE, &cfg_frgre_enable_cmd); install_element(L_NS_NODE, &cfg_frgre_local_ip_cmd); |