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
This commit is contained in:
Harald Welte 2021-01-17 22:04:36 +01:00
parent e5e470b588
commit e393c1f7c6
7 changed files with 153 additions and 33 deletions

View File

@ -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

View File

@ -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 := new_unblocked_nsvcs;
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_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, ?, ?, ?, *)) -> value rx_nsudr {
[] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, *)) -> 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_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_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(?, ?, ?)) -> value rf {
[] 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, ?, ?, ?, omit)) -> value ud_req {
[] 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, ?, ?, omit, ?)) -> value ud_req {
[] 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(?, 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, 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, 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));

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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