aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-07-05 03:11:17 +0200
committerHarald Welte <laforge@gnumonks.org>2019-02-26 13:23:24 +0100
commit57d3515abd319e0f8cd2dde0b82e9833a2cf6acc (patch)
tree6a94a0df04ddcc582bd41dc64a68c3b53aa1eaed
parent2a47c732175b8f15d31155e9b44a0878f16c18c6 (diff)
Optionally Use the NS Sub-Network-Service (SNS) on Gb
This change add support for the recently-introduced GPRS Gb interface auto-configuration using the NS IP Sub-Network Service (SNS) procedures. It requires a Change-Id I84786c3b43a8ae34ef3b3ba84b33c90042d234ea of libosmocore. Related: OS#3372 Depends: I84786c3b43a8ae34ef3b3ba84b33c90042d234ea (libosmcore) Change-Id: I256b40ac592d3b6e75dd581bf7b9512f69b11e83
-rw-r--r--src/bts.h3
-rw-r--r--src/gprs_bssgp_pcu.cpp31
-rw-r--r--src/pcu_vty.c23
3 files changed, 50 insertions, 7 deletions
diff --git a/src/bts.h b/src/bts.h
index 51760e24..578ceceb 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -159,6 +159,9 @@ struct gprs_rlcmac_bts {
/* Path to be used for the pcu-bts socket */
char *pcu_sock_path;
+
+ /* Are we talking Gb with IP-SNS (true) or classic Gb? */
+ bool gb_dialect_sns;
};
#ifdef __cplusplus
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 8bf6b7fe..f63fac30 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -541,12 +541,20 @@ static int nsvc_signal_cb(unsigned int subsys, unsigned int signal,
return -EINVAL;
nssd = (struct ns_signal_data *)signal_data;
- if (nssd->nsvc != the_pcu.nsvc) {
+ if (signal != S_SNS_CONFIGURED && nssd->nsvc != the_pcu.nsvc) {
LOGP(DPCU, LOGL_ERROR, "Signal received of unknown NSVC\n");
return -EINVAL;
}
switch (signal) {
+ case S_SNS_CONFIGURED:
+ the_pcu.bvc_sig_reset = 0;
+ the_pcu.bvc_reset = 0;
+ /* There's no NS-RESET / NS-UNBLOCK procedure on IP SNS based NS-VCs */
+ the_pcu.nsvc_unblocked = 1;
+ LOGP(DPCU, LOGL_NOTICE, "NS-VC %d is unblocked.\n", the_pcu.nsvc->nsvci);
+ bvc_timeout(NULL);
+ break;
case S_NS_UNBLOCK:
if (!the_pcu.nsvc_unblocked) {
the_pcu.nsvc_unblocked = 1;
@@ -872,9 +880,10 @@ static int gprs_ns_reconnect(struct gprs_nsvc *nsvc)
return -EBADF;
}
- nsvc2 = gprs_ns_nsip_connect(bssgp_nsi, &nsvc->ip.bts_addr,
- nsvc->nsei, nsvc->nsvci);
-
+ if (the_pcu.bts->gb_dialect_sns)
+ nsvc2 = gprs_ns_nsip_connect_sns(bssgp_nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci);
+ else
+ nsvc2 = gprs_ns_nsip_connect(bssgp_nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci);
if (!nsvc2) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to reconnect NSVC\n");
return -EIO;
@@ -905,8 +914,13 @@ struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts
return NULL;
}
gprs_ns_vty_init(bssgp_nsi);
- bssgp_nsi->nsip.remote_port = sgsn_port;
- bssgp_nsi->nsip.remote_ip = sgsn_ip;
+ /* don't specify remote IP/port if SNS dialect is in use; Doing so would
+ * issue a connect() on the socket, which prevents us to dynamically communicate
+ * with any number of IP-SNS endpoints on the SGSN side */
+ if (!bts->gb_dialect_sns) {
+ bssgp_nsi->nsip.remote_port = sgsn_port;
+ bssgp_nsi->nsip.remote_ip = sgsn_ip;
+ }
bssgp_nsi->nsip.local_port = local_port;
rc = gprs_ns_nsip_listen(bssgp_nsi);
if (rc < 0) {
@@ -920,7 +934,10 @@ struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts
dest.sin_port = htons(sgsn_port);
dest.sin_addr.s_addr = htonl(sgsn_ip);
- the_pcu.nsvc = gprs_ns_nsip_connect(bssgp_nsi, &dest, nsei, nsvci);
+ if (bts->gb_dialect_sns)
+ the_pcu.nsvc = gprs_ns_nsip_connect_sns(bssgp_nsi, &dest, nsei, nsvci);
+ else
+ the_pcu.nsvc = gprs_ns_nsip_connect(bssgp_nsi, &dest, nsei, nsvci);
if (!the_pcu.nsvc) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSVCt\n");
gprs_ns_destroy(bssgp_nsi);
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 6f50bf10..960c90d9 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -265,6 +265,11 @@ static int config_write_pcu(struct vty *vty)
}
}
+ if (bts->gb_dialect_sns)
+ vty_out(vty, " gb-dialect ip-sns%s", VTY_NEWLINE);
+ else
+ vty_out(vty, " gb-dialect classic%s", VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -1059,6 +1064,23 @@ DEFUN(cfg_pcu_sock,
return CMD_SUCCESS;
}
+DEFUN(cfg_pcu_gb_dialect,
+ cfg_pcu_gb_dialect_cmd,
+ "gb-dialect (classic|ip-sns)",
+ "Select which Gb interface dialect to use\n"
+ "Classic Gb interface with NS-{RESET,BLOCK,UNBLOCK} and static configuration\n"
+ "Modern Gb interface with IP-SNS (Sub Network Service) and dynamic configuration\n")
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ if (!strcmp(argv[0], "ip-sns"))
+ bts->gb_dialect_sns = true;
+ else
+ bts->gb_dialect_sns = false;
+
+ return CMD_SUCCESS;
+}
+
DEFUN(show_tbf,
show_tbf_cmd,
"show tbf all",
@@ -1189,6 +1211,7 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_gsmtap_categ_cmd);
install_element(PCU_NODE, &cfg_pcu_no_gsmtap_categ_cmd);
install_element(PCU_NODE, &cfg_pcu_sock_cmd);
+ install_element(PCU_NODE, &cfg_pcu_gb_dialect_cmd);
install_element_ve(&show_bts_stats_cmd);
install_element_ve(&show_tbf_cmd);