aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-01-17 22:04:36 +0100
committerHarald Welte <laforge@osmocom.org>2021-01-18 18:55:53 +0100
commite393c1f7c660aac76ee2f33f86a452edcbc57441 (patch)
tree0fcb07aad96d2c06f2f26325c6f221e4ec603caa
parente5e470b588657b93bd24655d21412102be9500d8 (diff)
NS_Emulation: Respect data_weight==0 or signalling_weight==0
* allow configuration of signalling + data weight for each NS-VC * advertise per-NSVC signalling/data weight in SNS-CONFIG * keep track of unblocked NS-VCS separately for data / signalling * transmit BVCI=0 traffic only over signalling NS-VC * transmit BVCI>0 traffic only over data NS-VC * accept incoming BVCI=0 traffic only if signalling_weight > 0 * accept incoming BVCI>0 traffic only if data_weight > 0 Related: OS#4953 Change-Id: I9798e639b4bc8658482945970775b012b5840779
-rw-r--r--gbproxy/GBProxy_Tests.ttcn21
-rw-r--r--library/NS_Emulation.ttcnpp113
-rw-r--r--library/Osmocom_Gb_Types.ttcn10
-rw-r--r--pcu/PCU_Tests.cfg14
-rw-r--r--pcu/PCU_Tests_SNS.cfg12
-rw-r--r--pcu/PCU_Tests_SNSv6.cfg2
-rw-r--r--sgsn/SGSN_Tests.ttcn12
7 files changed, 152 insertions, 32 deletions
diff --git a/gbproxy/GBProxy_Tests.ttcn b/gbproxy/GBProxy_Tests.ttcn
index 013dc93c..39d7432f 100644
--- a/gbproxy/GBProxy_Tests.ttcn
+++ b/gbproxy/GBProxy_Tests.ttcn
@@ -67,11 +67,14 @@ modulepar {
local_udp_port := 7777,
local_ip := "127.0.0.10",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 0,
+ signalling_weight := 1
}
},
nsvci := 101
}
+
}
}, {
nsei := 102,
@@ -85,7 +88,9 @@ modulepar {
local_udp_port := 8888,
local_ip := "127.0.0.11",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 0,
+ signalling_weight := 1
}
},
nsvci := 102
@@ -109,7 +114,9 @@ modulepar {
local_udp_port := 21010,
local_ip := "127.0.1.1",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 2101
@@ -128,7 +135,9 @@ modulepar {
local_udp_port := 21020,
local_ip := "127.0.2.1",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 2102
@@ -147,7 +156,9 @@ modulepar {
local_udp_port := 21030,
local_ip := "127.0.3.1",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 2103
diff --git a/library/NS_Emulation.ttcnpp b/library/NS_Emulation.ttcnpp
index 03aeb6aa..61ebe95b 100644
--- a/library/NS_Emulation.ttcnpp
+++ b/library/NS_Emulation.ttcnpp
@@ -1,5 +1,5 @@
/* GPRS-NS Emulation in TTCN-3
- * (C) 2018-2020 Harald Welte <laforge@gnumonks.org>
+ * (C) 2018-2021 Harald Welte <laforge@gnumonks.org>
* contributions by sysmocom - s.f.m.c. GmbH
* All rights reserved.
*
@@ -152,7 +152,9 @@ module NS_Emulation {
PortNumber local_udp_port,
charstring local_ip,
PortNumber remote_udp_port,
- charstring remote_ip
+ charstring remote_ip,
+ uint8_t data_weight,
+ uint8_t signalling_weight
};
type record NSVCConfigurationFR {
charstring netdev, /* HDLC net-device for AF_PACKET socket */
@@ -192,10 +194,11 @@ module NS_Emulation {
/* references to the per-NSVC components */
var NsvcTable g_nsvcs := {};
/* list of indexes to g_nsvcs[] of currently unblocked NSVCs */
- var ro_integer g_unblocked_nsvcs := {};
+ var ro_integer g_unblocked_nsvcs_sig := {};
+ var ro_integer g_unblocked_nsvcs_data := {};
};
type record NsvcTableEntry {
- Nsvci nsvci,
+ NSVCConfiguration cfg,
NSVC_CT vc_conn,
NsvcState state
};
@@ -244,7 +247,7 @@ module NS_Emulation {
var charstring nsvc_id := g_id & "-NSVCI" & int2str(nsvc_cfg.nsvci);
var NsvcTableEntry te;
- te.nsvci := nsvc_cfg.nsvci;
+ te.cfg := nsvc_cfg;
te.vc_conn := NSVC_CT.create(nsvc_id);
te.state := NSVC_S_DEAD_BLOCKED;
@@ -258,7 +261,7 @@ module NS_Emulation {
function f_nsvc_find_idx(Nsvci nsvci) runs on NS_CT return integer {
var integer i;
for (i := 0; i < lengthof(g_nsvcs); i := i+1) {
- if (g_nsvcs[i].nsvci == nsvci) {
+ if (g_nsvcs[i].cfg.nsvci == nsvci) {
return i;
}
}
@@ -281,16 +284,32 @@ module NS_Emulation {
}
if (g_nsvcs[i].state != NSVC_S_ALIVE_UNBLOCKED and state == NSVC_S_ALIVE_UNBLOCKED) {
/* add index to list of unblocked NSVCs */
- g_unblocked_nsvcs := g_unblocked_nsvcs & {i};
+ if (not ischosen(g_nsvcs[i].cfg.provider.ip) or
+ g_nsvcs[i].cfg.provider.ip.signalling_weight > 0) {
+ g_unblocked_nsvcs_sig := g_unblocked_nsvcs_sig & {i};
+ }
+ if (not ischosen(g_nsvcs[i].cfg.provider.ip) or
+ g_nsvcs[i].cfg.provider.ip.data_weight > 0) {
+ g_unblocked_nsvcs_data := g_unblocked_nsvcs_data & {i};
+ }
} else if (g_nsvcs[i].state == NSVC_S_ALIVE_UNBLOCKED and state != NSVC_S_ALIVE_UNBLOCKED) {
/* remove index to list of unblocked NSVCs */
- var ro_integer new_unblocked_nsvcs := {};
- for (var integer j := 0; j < lengthof(g_unblocked_nsvcs); j := j+1) {
- if (g_unblocked_nsvcs[j] != i) {
- new_unblocked_nsvcs := new_unblocked_nsvcs & {j};
+ var ro_integer new_unblocked_nsvcs_sig := {};
+ for (var integer j := 0; j < lengthof(g_unblocked_nsvcs_sig); j := j+1) {
+ if (g_unblocked_nsvcs_sig[j] != i) {
+ new_unblocked_nsvcs_sig := new_unblocked_nsvcs_sig & {j};
+ }
+ }
+ g_unblocked_nsvcs_sig := new_unblocked_nsvcs_sig;
+
+ var ro_integer new_unblocked_nsvcs_data := {};
+ for (var integer j := 0; j < lengthof(g_unblocked_nsvcs_data); j := j+1) {
+ if (g_unblocked_nsvcs_data[j] != i) {
+ new_unblocked_nsvcs_data := new_unblocked_nsvcs_data & {j};
}
}
- g_unblocked_nsvcs := new_unblocked_nsvcs;
+ g_unblocked_nsvcs_data := new_unblocked_nsvcs_data;
+
}
g_nsvcs[i].state := state;
}
@@ -365,11 +384,17 @@ module NS_Emulation {
log2str("Received UnitDataInd for invalid NSEI: ", rx_nsudi));
}
/* from user down to NS-VC */
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, *)) -> value rx_nsudr {
+ /* load distribution function */
+ var integer nsvc_idx := g_unblocked_nsvcs_sig[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs_sig)];
+ NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
+ }
[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, ?, *)) -> value rx_nsudr {
/* load distribution function */
- var integer nsvc_idx := g_unblocked_nsvcs[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs)];
+ var integer nsvc_idx := g_unblocked_nsvcs_data[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs_data)];
NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
}
+
[] NS_SP.receive(tr_NsUdReq(?, ?, ?, ?, *)) -> value rx_nsudr {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
log2str("Received NsUnitdataReq for invalid NSEI: ", rx_nsudr));
@@ -392,10 +417,14 @@ module NS_Emulation {
}
if (nsvc_cfg.provider.ip.address_family == AF_INET) {
v4 := v4 & { valueof(ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
- nsvc_cfg.provider.ip.local_udp_port)) };
+ nsvc_cfg.provider.ip.local_udp_port,
+ nsvc_cfg.provider.ip.signalling_weight,
+ nsvc_cfg.provider.ip.data_weight)) };
} else if (nsvc_cfg.provider.ip.address_family == AF_INET6) {
v6 := v6 & { valueof(ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
- nsvc_cfg.provider.ip.local_udp_port)) };
+ nsvc_cfg.provider.ip.local_udp_port,
+ nsvc_cfg.provider.ip.signalling_weight,
+ nsvc_cfg.provider.ip.data_weight)) };
}
}
@@ -690,18 +719,66 @@ module NS_Emulation {
/* tolerate a late NS-UNBLOCK-ACK from peer */
[] NSCP.receive(t_NS_UNBLOCK_ACK) -> value rf {
}
+
+ [not ischosen(g_nsvc_config.provider.ip) or
+ g_nsvc_config.provider.ip.data_weight > 0] as_alive_unblocked_data();
+
+ [not ischosen(g_nsvc_config.provider.ip) or
+ g_nsvc_config.provider.ip.signalling_weight > 0] as_alive_unblocked_sig();
+
+ /* catch any violations of above rule */
+ [ischosen(g_nsvc_config.provider.ip)] NSCP.receive(tr_NS_UNITDATA(?, ?, ?)) -> value rf {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected Rx NS-UNITDATA on NSVC with data_weight=",
+ g_nsvc_config.provider.ip.data_weight, ", sig_weight=",
+ g_nsvc_config.provider.ip.signalling_weight, ": ", rf));
+ }
+ [ischosen(g_nsvc_config.provider.ip)] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, *, *)) -> value ud_req {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected Rx TX-UNITDATA on NSVC with data_weight=",
+ g_nsvc_config.provider.ip.data_weight, ", sig_weight=",
+ g_nsvc_config.provider.ip.signalling_weight, ": ", ud_req));
+ }
+ }
+
+ /* user data transfer; only permitted for some NS-VC */
+ private altstep as_alive_unblocked_data() runs on NSVC_CT {
+ var NsUnitdataRequest ud_req;
+ var PDU_NS rf;
+ /* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
+ [] NSCP.receive(tr_NS_UNITDATA_User(?, ?)) -> value rf {
+ NS_SP.send(ts_NsUdInd(g_config.nsei, g_nsvc_config.nsvci,
+ oct2int(rf.pDU_NS_Unitdata.bVCI),
+ rf.pDU_NS_Unitdata.nS_SDU));
+ }
+ /* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, t_BssgpBvciUser, ?, ?, omit)) -> value ud_req {
+ /* using raw octetstring PDU */
+ NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
+ }
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, t_BssgpBvciUser, ?, omit, ?)) -> value ud_req {
+ /* using decoded BSSGP PDU that we need to encode first */
+ var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
+ NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));
+ }
+ }
+
+ /* signalling (BVCI=0) transfer; only permitted for some NS-VC */
+ private altstep as_alive_unblocked_sig() runs on NSVC_CT {
+ var NsUnitdataRequest ud_req;
+ var PDU_NS rf;
/* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
- [] NSCP.receive(tr_NS_UNITDATA(?, ?, ?)) -> value rf {
+ [] NSCP.receive(tr_NS_UNITDATA(?, 0, ?)) -> value rf {
NS_SP.send(ts_NsUdInd(g_config.nsei, g_nsvc_config.nsvci,
oct2int(rf.pDU_NS_Unitdata.bVCI),
rf.pDU_NS_Unitdata.nS_SDU));
}
/* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
- [] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, ?, omit)) -> value ud_req {
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, omit)) -> value ud_req {
/* using raw octetstring PDU */
NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
}
- [] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, omit, ?)) -> value ud_req {
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, omit, ?)) -> value ud_req {
/* using decoded BSSGP PDU that we need to encode first */
var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));
diff --git a/library/Osmocom_Gb_Types.ttcn b/library/Osmocom_Gb_Types.ttcn
index 90650978..9e4d7029 100644
--- a/library/Osmocom_Gb_Types.ttcn
+++ b/library/Osmocom_Gb_Types.ttcn
@@ -14,6 +14,8 @@ module Osmocom_Gb_Types {
type uint16_t Nsei;
type uint16_t BssgpBvci;
+ template (present) BssgpBvci t_BssgpBvciUser := complement (0);
+
/* TS 48.016 10.3.7 */
type enumerated NsPduType {
NS_PDUT_NS_UNITDATA ('00000000'B),
@@ -407,6 +409,14 @@ octetstring sdu) := {
nS_SDU := sdu
}
}
+ template PDU_NS tr_NS_UNITDATA_User(template NS_SDU_ControlBits bits, template octetstring sdu) := {
+ pDU_NS_Unitdata := {
+ nsPduType := '00'O,
+ nS_SDU_ControlBits := bits,
+ bVCI := complement ('0000'O),
+ nS_SDU := sdu
+ }
+ }
diff --git a/pcu/PCU_Tests.cfg b/pcu/PCU_Tests.cfg
index 13bedec9..dfebb40f 100644
--- a/pcu/PCU_Tests.cfg
+++ b/pcu/PCU_Tests.cfg
@@ -18,7 +18,9 @@ SGSN_Components.mp_nsconfig := {
local_ip := "127.0.0.1",
local_udp_port := 23000,
remote_ip := "127.0.0.1",
- remote_udp_port := 22000
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 1234
@@ -30,7 +32,10 @@ SGSN_Components.mp_nsconfig := {
local_ip := "127.0.0.1",
local_udp_port := 23001,
remote_ip := "127.0.0.1",
- remote_udp_port := 22000
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
}
},
nsvci := 1234
@@ -42,7 +47,10 @@ SGSN_Components.mp_nsconfig := {
local_ip := "127.0.0.1",
local_udp_port := 23002,
remote_ip := "127.0.0.1",
- remote_udp_port := 22000
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
}
},
nsvci := 1234
diff --git a/pcu/PCU_Tests_SNS.cfg b/pcu/PCU_Tests_SNS.cfg
index ab589c53..c36edac7 100644
--- a/pcu/PCU_Tests_SNS.cfg
+++ b/pcu/PCU_Tests_SNS.cfg
@@ -17,7 +17,9 @@ SGSN_Components.mp_nsconfig := {
local_ip := "127.0.0.1",
local_udp_port := 23000,
remote_ip := "127.0.0.1",
- remote_udp_port := 22000
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 1234
@@ -29,7 +31,9 @@ SGSN_Components.mp_nsconfig := {
local_ip := "127.0.0.1",
local_udp_port := 23001,
remote_ip := "127.0.0.1",
- remote_udp_port := 22000
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 1234
@@ -41,7 +45,9 @@ SGSN_Components.mp_nsconfig := {
local_ip := "127.0.0.1",
local_udp_port := 23002,
remote_ip := "127.0.0.1",
- remote_udp_port := 22000
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 1234
diff --git a/pcu/PCU_Tests_SNSv6.cfg b/pcu/PCU_Tests_SNSv6.cfg
index cae9a75f..3747f0a4 100644
--- a/pcu/PCU_Tests_SNSv6.cfg
+++ b/pcu/PCU_Tests_SNSv6.cfg
@@ -18,6 +18,8 @@ SGSN_Components.mp_nsconfig := {
local_udp_port := 23000,
remote_ip := "::1",
remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 1234
diff --git a/sgsn/SGSN_Tests.ttcn b/sgsn/SGSN_Tests.ttcn
index fe31ffcb..7d47a1ff 100644
--- a/sgsn/SGSN_Tests.ttcn
+++ b/sgsn/SGSN_Tests.ttcn
@@ -80,7 +80,9 @@ modulepar {
local_udp_port := 21010,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 97
@@ -99,7 +101,9 @@ modulepar {
local_udp_port := 21011,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 98
@@ -118,7 +122,9 @@ modulepar {
local_udp_port := 21012,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
- remote_ip := "127.0.0.1"
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
}
},
nsvci := 99