oml: encode IPv6 NSVC using the new OML attribute NM_ATT_OSMO_NS_LINK_CFG
The old IE NM_ATT_IPACC_NS_LINK_CFG didn't support IPv6 NSVC.
Depends: Ic261bc43a07fa741b97a9c6ec5a9ed6f5ecae588 (libosmocore)
Depends: I9e279bb20940c66eea5196f281184cb4f8a5cc5f (libosmocore)
Change-Id: I6529876a3c1116a79dd624312243d8ae48a41fe2
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 90ab8ea..8d07fb1 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -8,6 +8,7 @@
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/select.h>
+#include <osmocom/core/socket.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/stat_item.h>
#include <osmocom/gsm/bts_features.h>
@@ -745,9 +746,7 @@
int id;
uint16_t nsvci;
uint16_t local_port; /* on the BTS */
- uint16_t remote_port; /* on the SGSN */
- uint32_t remote_ip; /* on the SGSN */
-
+ struct osmo_sockaddr remote;
struct gsm_abis_mo mo;
};
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 8808c20..f58b272 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -36,9 +36,11 @@
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/gsm/gsm23236.h>
+#include <osmocom/core/sockaddr_str.h>
#include <arpa/inet.h>
+#include <osmocom/core/byteswap.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/socket.h>
#include <osmocom/bsc/gsm_data.h>
@@ -762,17 +764,27 @@
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
struct gsm_bts_gprs_nsvc *nsvc =
&bts->gprs.nsvc[i];
- struct in_addr ia;
+ struct osmo_sockaddr_str remote = {};
+ uint16_t port;
- ia.s_addr = htonl(nsvc->remote_ip);
vty_out(vty, " gprs nsvc %u nsvci %u%s", i,
nsvc->nsvci, VTY_NEWLINE);
+
vty_out(vty, " gprs nsvc %u local udp port %u%s", i,
nsvc->local_port, VTY_NEWLINE);
- vty_out(vty, " gprs nsvc %u remote udp port %u%s", i,
- nsvc->remote_port, VTY_NEWLINE);
- vty_out(vty, " gprs nsvc %u remote ip %s%s", i,
- inet_ntoa(ia), VTY_NEWLINE);
+
+ osmo_sockaddr_str_from_sockaddr(&remote, &nsvc->remote.u.sas);
+ if (remote.af != AF_UNSPEC) {
+ vty_out(vty, " gprs nsvc %u remote ip %s%s", i,
+ remote.ip, VTY_NEWLINE);
+ }
+
+ /* Can't use remote.port because it's only valid when family != AF_UNSPEC, but the
+ * port can be even configured when the IP isn't */
+ port = osmo_htons(nsvc->remote.u.sin.sin_port);
+ if (port)
+ vty_out(vty, " gprs nsvc %u remote udp port %u%s", i,
+ port, VTY_NEWLINE);
}
/* EGPRS specific parameters */
@@ -3010,26 +3022,41 @@
GPRS_CHECK_ENABLED(bts);
- bts->gprs.nsvc[idx].remote_port = atoi(argv[1]);
+ /* sockaddr_in and sockaddr_in6 have the port at the same position */
+ bts->gprs.nsvc[idx].remote.u.sin.sin_port = htons(atoi(argv[1]));
return CMD_SUCCESS;
}
DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
- "gprs nsvc <0-1> remote ip A.B.C.D",
+ "gprs nsvc <0-1> remote ip " VTY_IPV46_CMD,
GPRS_TEXT NSVC_TEXT
"GPRS NS Remote IP Address\n"
"GPRS NS Remote IP Address\n"
- "GPRS NS Remote IP Address\n")
+ "GPRS NS Remote IPv4 Address\n"
+ "GPRS NS Remote IPv6 Address\n")
{
struct gsm_bts *bts = vty->index;
+ struct osmo_sockaddr_str remote;
int idx = atoi(argv[0]);
- struct in_addr ia;
+ int ret;
GPRS_CHECK_ENABLED(bts);
- inet_aton(argv[1], &ia);
- bts->gprs.nsvc[idx].remote_ip = ntohl(ia.s_addr);
+ ret = osmo_sockaddr_str_from_str2(&remote, argv[1]);
+ if (ret) {
+ vty_out(vty, "%% Invalid IP address %s%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* Can't use osmo_sockaddr_str_to_sockaddr() because the port would be overriden */
+ bts->gprs.nsvc[idx].remote.u.sas.ss_family = remote.af;
+ switch (remote.af) {
+ case AF_INET:
+ osmo_sockaddr_str_to_in_addr(&remote, &bts->gprs.nsvc[idx].remote.u.sin.sin_addr);
+ case AF_INET6:
+ osmo_sockaddr_str_to_in6_addr(&remote, &bts->gprs.nsvc[idx].remote.u.sin6.sin6_addr);
+ }
return CMD_SUCCESS;
}
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index e02eabc..4c95196 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts.c
@@ -227,6 +227,12 @@
/* We skip NSVC1 since we only use NSVC0 */
if (nsvc->id == 1)
break;
+ if (!osmo_bts_has_feature(&bts->features, BTS_FEAT_IPV6_NSVC) &&
+ nsvc->remote.u.sa.sa_family == AF_INET6) {
+ LOGP(DLINP, LOGL_ERROR, "BTS %d does not support IPv6 but an IPv6 address was configured!\n", bts->nr);
+ break;
+ }
+
if ((new_state->availability == NM_AVSTATE_OFF_LINE) ||
(new_state->availability == NM_AVSTATE_DEPENDENCY)) {
msgb = nanobts_attr_nscv_get(bts);
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c
index b979cc7..b723932 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c
@@ -24,6 +24,7 @@
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/abis_nm.h>
#include <osmocom/bsc/bts.h>
+#include <osmocom/gsm/bts_features.h>
struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts)
{
@@ -202,13 +203,33 @@
buf[1] = bts->gprs.nsvc[0].nsvci & 0xff;
msgb_tl16v_put(msgb, NM_ATT_IPACC_NSVCI, 2, buf);
- /* remote udp port */
- osmo_store16be(bts->gprs.nsvc[0].remote_port, &buf[0]);
- /* remote ip address */
- osmo_store32be(bts->gprs.nsvc[0].remote_ip, &buf[2]);
- /* local udp port */
- osmo_store16be(bts->gprs.nsvc[0].local_port, &buf[6]);
- msgb_tl16v_put(msgb, NM_ATT_IPACC_NS_LINK_CFG, 8, buf);
+ switch (bts->gprs.nsvc->remote.u.sa.sa_family) {
+ case AF_INET6:
+ /* all fields are encoded in network byte order */
+ /* protocol family */
+ buf[0] = OSMO_NSVC_ADDR_IPV6;
+ /* padding */
+ buf[1] = 0x00;
+ /* local udp port */
+ osmo_store16be(bts->gprs.nsvc[0].local_port, &buf[2]);
+ /* remote udp port */
+ memcpy(&buf[4], &bts->gprs.nsvc[0].remote.u.sin6.sin6_port, sizeof(uint16_t));
+ /* remote ip address */
+ memcpy(&buf[6], &bts->gprs.nsvc[0].remote.u.sin6.sin6_addr, sizeof(struct in6_addr));
+ msgb_tl16v_put(msgb, NM_ATT_OSMO_NS_LINK_CFG, 6 + sizeof(struct in6_addr), buf);
+ break;
+ case AF_INET:
+ /* remote udp port */
+ memcpy(&buf[0], &bts->gprs.nsvc[0].remote.u.sin.sin_port, sizeof(uint16_t));
+ /* remote ip address */
+ memcpy(&buf[2], &bts->gprs.nsvc[0].remote.u.sin.sin_addr, sizeof(struct in_addr));
+ /* local udp port */
+ osmo_store16be(bts->gprs.nsvc[0].local_port, &buf[6]);
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_NS_LINK_CFG, 8, buf);
+ break;
+ default:
+ break;
+ }
return msgb;
}
diff --git a/src/osmo-bsc/bts_sysmobts.c b/src/osmo-bsc/bts_sysmobts.c
index df43d76..d7d15eb 100644
--- a/src/osmo-bsc/bts_sysmobts.c
+++ b/src/osmo-bsc/bts_sysmobts.c
@@ -61,5 +61,7 @@
osmo_bts_set_feature(&model_sysmobts.features, BTS_FEAT_EGPRS);
osmo_bts_set_feature(&model_sysmobts.features, BTS_FEAT_PAGING_COORDINATION);
+ model_sysmobts.nm_att_tlvdef.def[NM_ATT_OSMO_NS_LINK_CFG].type = TLV_TYPE_TL16V;
+
return gsm_bts_model_register(&model_sysmobts);
}
diff --git a/src/osmo-bsc/pcu_sock.c b/src/osmo-bsc/pcu_sock.c
index c2df7c4..4897502 100644
--- a/src/osmo-bsc/pcu_sock.c
+++ b/src/osmo-bsc/pcu_sock.c
@@ -30,6 +30,7 @@
#include <sys/socket.h>
#include <sys/un.h>
+#include <osmocom/core/byteswap.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/socket.h>
@@ -190,10 +191,18 @@
/* NSVC */
for (i = 0; i < ARRAY_SIZE(info_ind->nsvci); i++) {
nsvc = &bts->gprs.nsvc[i];
+
+ if (nsvc->remote.u.sa.sa_family == AF_INET6) {
+ LOGP(DPCU, LOGL_ERROR, "PCU does not support IPv6 NSVC but an IPv6 NSVC was configured!\n");
+ continue;
+ }
+ if (nsvc->remote.u.sa.sa_family != AF_INET)
+ continue;
+
info_ind->nsvci[i] = nsvc->nsvci;
info_ind->local_port[i] = nsvc->local_port;
- info_ind->remote_port[i] = nsvc->remote_port;
- info_ind->remote_ip[i] = nsvc->remote_ip;
+ info_ind->remote_port[i] = osmo_ntohs(nsvc->remote.u.sin.sin_port);
+ info_ind->remote_ip[i] = osmo_ntohl(nsvc->remote.u.sin.sin_addr.s_addr);
}
for (i = 0; i < ARRAY_SIZE(info_ind->trx); i++) {
diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.c b/tests/nanobts_omlattr/nanobts_omlattr_test.c
index ea98409..da220c1 100644
--- a/tests/nanobts_omlattr/nanobts_omlattr_test.c
+++ b/tests/nanobts_omlattr/nanobts_omlattr_test.c
@@ -27,6 +27,7 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/application.h>
+#include <osmocom/core/sockaddr_str.h>
#include <stdio.h>
#include <string.h>
@@ -263,9 +264,10 @@
};
/* Parameters needed to test nanobts_attr_nscv_get() */
+ struct osmo_sockaddr_str addr;
+ osmo_sockaddr_str_from_str(&addr, "10.9.1.101", 23000);
+ osmo_sockaddr_str_to_sockaddr(&addr, &bts->gprs.nsvc[0].remote.u.sas);
bts->gprs.nsvc[0].nsvci = 0x65;
- bts->gprs.nsvc[0].remote_port = 0x59d8;
- bts->gprs.nsvc[0].remote_ip = 0x0a090165;
bts->gprs.nsvc[0].local_port = 0x5a3c;
uint8_t attr_nscv_expected[] =
{ 0x9f, 0x00, 0x02, 0x00, 0x65, 0xa2, 0x00, 0x08, 0x59, 0xd8, 0x0a,
@@ -286,6 +288,24 @@
test_nanobts_attr_nscv_get(bts, attr_nscv_expected);
test_nanobts_attr_radio_get(bts, trx, attr_radio_expected);
+ /* NSVC IPv6 test */
+ struct osmo_sockaddr_str addr6;
+ osmo_sockaddr_str_from_str(&addr6, "fd00:5678:9012:3456:7890:1234:5678:9012", 23010);
+ osmo_sockaddr_str_to_sockaddr(&addr6, &bts->gprs.nsvc[0].remote.u.sas);
+ bts->gprs.nsvc[0].nsvci = 0x65;
+ bts->gprs.nsvc[0].local_port = 0x5a3c;
+ uint8_t attr_nscv6_expected[] =
+ /* |- oml attr |-16bit length */
+ { 0x9f, 0x00, 0x02, 0x00, 0x65, 0xfd, 0x00, 0x16,
+ /* 1b type, 1b padding, 2b local port, 2b remote port */
+ 0x29, 0x00, 0x5a, 0x3c, 0x59, 0xe2,
+ /* 128bit / 16b ipv6 address */
+ 0xfd, 0x00, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56,
+ 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12,
+ };
+ test_nanobts_attr_nscv_get(bts, attr_nscv6_expected);
+
+
printf("Done\n");
talloc_free(bts);
talloc_free(net);
diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.ok b/tests/nanobts_omlattr/nanobts_omlattr_test.ok
index ef46cf9..abdb95e 100644
--- a/tests/nanobts_omlattr/nanobts_omlattr_test.ok
+++ b/tests/nanobts_omlattr/nanobts_omlattr_test.ok
@@ -23,4 +23,9 @@
expected=2d0b0500020362
ok.
+Testing nanobts_attr_nscv_get()...
+result= 9f00020065fd001629005a3c59e2fd005678901234567890123456789012
+expected=9f00020065fd001629005a3c59e2fd005678901234567890123456789012
+ok.
+
Done