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
This commit is contained in:
parent
37474b2b38
commit
2f9df96eba
|
@ -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 @@ struct gsm_bts_gprs_nsvc {
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 @@ static void config_write_bts_gprs(struct vty *vty, struct gsm_bts *bts)
|
|||
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 @@ DEFUN(cfg_bts_gprs_nsvc_rport, cfg_bts_gprs_nsvc_rport_cmd,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -227,6 +227,12 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
|
|||
/* 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);
|
||||
|
|
|
@ -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 @@ struct msgb *nanobts_attr_nscv_get(struct gsm_bts *bts)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -61,5 +61,7 @@ int bts_model_sysmobts_init(void)
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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 @@ static int pcu_tx_info_ind(struct gsm_bts *bts)
|
|||
/* 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++) {
|
||||
|
|
|
@ -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 @@ int main(int argc, char **argv)
|
|||
};
|
||||
|
||||
/* 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 @@ int main(int argc, char **argv)
|
|||
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);
|
||||
|
|
|
@ -23,4 +23,9 @@ result= 2d0b0500020362
|
|||
expected=2d0b0500020362
|
||||
ok.
|
||||
|
||||
Testing nanobts_attr_nscv_get()...
|
||||
result= 9f00020065fd001629005a3c59e2fd005678901234567890123456789012
|
||||
expected=9f00020065fd001629005a3c59e2fd005678901234567890123456789012
|
||||
ok.
|
||||
|
||||
Done
|
||||
|
|
Loading…
Reference in New Issue