HSS: Add support for Operator-Determined-Barring field

* Add "subscriber_status" cmd to open5gs-dbctl to set values for
  "subscriber_status" and "operator_determined_barring" DB fields.
* Add webui View+Edit for those same fields.
* open5gs-hssd now takes those values into account and submits
  Operator-Determined-Barring AVP with DB-retrieved value if
subscriber_status is set to OPERATOR_DETERMINED_BARRING.

For more information, see TS 29.272 section 5.2.2.1.3  and 7.3.30.
This commit is contained in:
Pau Espin 2023-10-09 16:19:21 +02:00 committed by Sukchan Lee
parent 963df4beeb
commit e108d6297c
13 changed files with 127 additions and 3 deletions

View File

@ -393,6 +393,10 @@ int ogs_dbi_subscription_data(char *supi,
BSON_ITER_HOLDS_INT32(&iter)) {
subscription_data->subscriber_status =
bson_iter_int32(&iter);
} else if (!strcmp(key, "operator_determined_barring") &&
BSON_ITER_HOLDS_INT32(&iter)) {
subscription_data->operator_determined_barring =
bson_iter_int32(&iter);
} else if (!strcmp(key, "network_access_mode") &&
BSON_ITER_HOLDS_INT32(&iter)) {
subscription_data->network_access_mode =

View File

@ -54,6 +54,7 @@ struct dict_object *ogs_diam_s6a_xres = NULL;
struct dict_object *ogs_diam_s6a_autn = NULL;
struct dict_object *ogs_diam_s6a_kasme = NULL;
struct dict_object *ogs_diam_s6a_subscriber_status = NULL;
struct dict_object *ogs_diam_s6a_operator_determined_barring = NULL;
struct dict_object *ogs_diam_s6a_ambr = NULL;
struct dict_object *ogs_diam_s6a_network_access_mode = NULL;
struct dict_object *ogs_diam_s6a_access_restriction_data = NULL;
@ -151,6 +152,7 @@ int ogs_diam_s6a_init(void)
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Served-Party-IP-Address", &ogs_diam_s6a_served_party_ip_address);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Data", &ogs_diam_s6a_subscription_data);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscriber-Status", &ogs_diam_s6a_subscriber_status);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Operator-Determined-Barring", &ogs_diam_s6a_operator_determined_barring);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Network-Access-Mode", &ogs_diam_s6a_network_access_mode);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Access-Restriction-Data", &ogs_diam_s6a_access_restriction_data);
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscribed-Periodic-RAU-TAU-Timer", &ogs_diam_s6a_subscribed_rau_tau_timer);

View File

@ -119,6 +119,7 @@ extern struct dict_object *ogs_diam_s6a_xres;
extern struct dict_object *ogs_diam_s6a_autn;
extern struct dict_object *ogs_diam_s6a_kasme;
extern struct dict_object *ogs_diam_s6a_subscriber_status;
extern struct dict_object *ogs_diam_s6a_operator_determined_barring;
extern struct dict_object *ogs_diam_s6a_ambr;
extern struct dict_object *ogs_diam_s6a_network_access_mode;
extern struct dict_object *ogs_diam_s6a_access_restriction_data;

View File

@ -685,6 +685,16 @@ typedef struct ogs_subscription_data_s {
#define OGS_SUBSCRIBER_STATUS_SERVICE_GRANTED 0
#define OGS_SUBSCRIBER_STATUS_OPERATOR_DETERMINED_BARRING 1
uint32_t subscriber_status;
#define OGS_OP_DET_BARRING_ALL_PS_BARRED (1<<0)
#define OGS_OP_DET_BARRING_ROAM_ACC_HPLMN_AP_BARRED (1<<1)
#define OGS_OP_DET_BARRING_ROAM_ACC_VPLMN_AP_BARRED (1<<2)
#define OGS_OP_DET_BARRING_ALL_OUT_CALLS (1<<3)
#define OGS_OP_DET_BARRING_ALL_OUT_INT_CALLS (1<<4)
#define OGS_OP_DET_BARRING_ALL_OUT_INT_CALLS_EXCL_HPLMN_COUNTRY (1<<5)
#define OGS_OP_DET_BARRING_ALL_OUT_INTERZONE_CALLS (1<<6)
#define OGS_OP_DET_BARRING_ALL_OUT_INTERZONE_CALLS_EXCL_HPLMN_COUNTRY (1<<7)
#define OGS_OPD_ETEBARRING_OUT_INT_CALLS_EXCL_EXCL_HPLMN_COUNTRY_AND_INTERZONE_CALLS (1<<8)
uint32_t operator_determined_barring; /* 3GPP TS 29.272 7.3.30 */
#define OGS_NETWORK_ACCESS_MODE_PACKET_AND_CIRCUIT 0
#define OGS_NETWORK_ACCESS_MODE_RESERVED 1
#define OGS_NETWORK_ACCESS_MODE_ONLY_PACKET 2

View File

@ -25,7 +25,7 @@ display_help() {
echo " showpretty: shows the list of subscriber in the db in a pretty json tree format"
echo " showfiltered: shows {imsi key opc apn ip} information of subscriber"
echo " ambr_speed {imsi dl_value dl_unit ul_value ul_unit}: Change AMBR speed from a specific user and the unit values are \"[0=bps 1=Kbps 2=Mbps 3=Gbps 4=Tbps ]\""
echo " subscriber_status {imsi subscriber_status_val={0,1} operator_determined_barring={0..8}}: Change TS 29.272 values for Subscriber-Status (7.3.29) and Operator-Determined-Barring (7.3.30)"
}
@ -118,6 +118,8 @@ if [ "$1" = "add" ]; then
},
\"access_restriction_data\": 32,
\"network_access_mode\": 0,
\"subscriber_status\": 0,
\"operator_determined_barring\": 0,
\"subscribed_rau_tau_timer\": 12,
\"__v\": 0
}
@ -194,6 +196,8 @@ if [ "$1" = "add" ]; then
},
\"access_restriction_data\": 32,
\"network_access_mode\": 0,
\"subscriber_status\": 0,
\"operator_determined_barring\": 0,
\"subscribed_rau_tau_timer\": 12,
\"__v\": 0
}
@ -325,6 +329,8 @@ if [ "$1" = "addT1" ]; then
},
\"access_restriction_data\": 32,
\"network_access_mode\": 0,
\"subscriber_status\": 0,
\"operator_determined_barring\": 0,
\"subscribed_rau_tau_timer\": 12,
\"__v\": 0
}
@ -464,6 +470,8 @@ if [ "$1" = "addT1" ]; then
},
\"access_restriction_data\": 32,
\"network_access_mode\": 0,
\"subscriber_status\": 0,
\"operator_determined_barring\": 0,
\"subscribed_rau_tau_timer\": 12,
\"__v\": 0
}
@ -598,6 +606,8 @@ if [ "$1" = "add_ue_with_apn" ]; then
},
\"access_restriction_data\": 32,
\"network_access_mode\": 0,
\"subscriber_status\": 0,
\"operator_determined_barring\": 0,
\"subscribed_rau_tau_timer\": 12,
\"__v\": 0
}
@ -678,6 +688,8 @@ if [ "$1" = "add_ue_with_slice" ]; then
},
\"access_restriction_data\": 32,
\"network_access_mode\": 0,
\"subscriber_status\": 0,
\"operator_determined_barring\": 0,
\"subscribed_rau_tau_timer\": 12,
\"__v\": 0
}
@ -773,6 +785,21 @@ if [ "$1" = "update_slice" ]; then
echo "open5gs-dbctl: incorrect number of args, format is \"open5gs-dbctl update_slice imsi apn sst sd\""
exit 1
fi
if [ "$1" = "subscriber_status" ]; then
if [ "$#" -eq 4 ]; then
IMSI=$2
SUB_STATUS=$3
OP_DET_BARRING=$4
mongosh --eval "db.subscribers.updateOne({ \"imsi\": \"$IMSI\"},
{\$set: { \"subscriber_status\": $SUB_STATUS,
\"operator_determined_barring\": $OP_DET_BARRING
}
});" $DB_URI
exit $?
fi
echo "open5gs-dbctl: incorrect number of args, format is \"open5gs-dbctl subscriber_status imsi subscriber_status_val={0,1} operator_determined_barring={0..8}"
exit 1
fi
if [ "$1" = "showall" ]; then
mongosh --eval "db.subscribers.find()" $DB_URI
exit $?

View File

@ -39,6 +39,7 @@ sub_data = {
"subscribed_rau_tau_timer": 12,
"network_access_mode": 0,
"subscriber_status": 0,
"operator_determined_barring": 0,
"access_restriction_data": 32,
"slice" : slice_data,
"ambr": {"uplink": {"value": 1, "unit": 3}, "downlink": {"value": 1, "unit": 3}},

View File

@ -43,13 +43,15 @@ class TestSchemaUpdater(unittest.TestCase):
'opc': 'iamatransparentsecretopcstring'
},
'subscribed_rau_tau_timer': 12,
'subscriber_status': 0
'subscriber_status': 0,
"operator_determined_barring": 0,
}
def test_top_level_migration(self):
new_sub = SchemaUpdater.create_v1_from_v0(self.legacy_sub)
self.assertEqual(new_sub["imsi"], self.legacy_sub["imsi"])
self.assertEqual(new_sub["subscriber_status"], self.legacy_sub["subscriber_status"])
self.assertEqual(new_sub["operator_determined_barring"], self.legacy_sub["operator_determined_barring"])
self.assertEqual(new_sub["subscribed_rau_tau_timer"], self.legacy_sub["subscribed_rau_tau_timer"])
self.assertEqual(new_sub["network_access_mode"], self.legacy_sub["network_access_mode"])
self.assertEqual(new_sub["access_restriction_data"], self.legacy_sub["access_restriction_data"])

View File

@ -1254,6 +1254,12 @@ int hss_handle_change_event(const bson_t *document)
send_idr_flag = true;
subdatamask = (subdatamask |
OGS_DIAM_S6A_SUBDATA_SUB_STATUS);
} else if (!strncmp(child2_key,
"operator_determined_barring",
strlen("operator_determined_barring"))) {
send_idr_flag = true;
subdatamask = (subdatamask |
OGS_DIAM_S6A_SUBDATA_SUB_STATUS);
} else if (!strncmp(child2_key,
"network_access_mode",
strlen("network_access_mode"))) {

View File

@ -303,7 +303,7 @@ static int hss_s6a_avp_add_subscription_data(
struct avp *avp_msisdn, *avp_a_msisdn;
struct avp *avp_access_restriction_data;
struct avp *avp_subscriber_status, *avp_network_access_mode;
struct avp *avp_subscriber_status, *avp_operator_determined_barring, *avp_network_access_mode;
struct avp *avp_ambr, *avp_max_bandwidth_ul, *avp_max_bandwidth_dl;
struct avp *avp_rau_tau_timer;
@ -373,6 +373,17 @@ static int hss_s6a_avp_add_subscription_data(
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_subscriber_status);
ogs_assert(ret == 0);
if (subscription_data->subscriber_status == OGS_SUBSCRIBER_STATUS_OPERATOR_DETERMINED_BARRING) {
ret = fd_msg_avp_new(
ogs_diam_s6a_operator_determined_barring, 0, &avp_operator_determined_barring);
ogs_assert(ret == 0);
val.i32 = subscription_data->operator_determined_barring;
ret = fd_msg_avp_setvalue(avp_operator_determined_barring, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_operator_determined_barring);
ogs_assert(ret == 0);
}
}
if (subdatamask & OGS_DIAM_S6A_SUBDATA_NAM) {

View File

@ -1511,6 +1511,7 @@ bson_t *test_db_new_simple(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);
@ -1615,6 +1616,7 @@ bson_t *test_db_new_qos_flow(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);
@ -1743,6 +1745,7 @@ bson_t *test_db_new_session(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);
@ -1893,6 +1896,7 @@ bson_t *test_db_new_ims(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);
@ -2270,6 +2274,7 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);
@ -2647,6 +2652,7 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);
@ -2801,6 +2807,7 @@ bson_t *test_db_new_non3gpp(test_ue_t *test_ue)
"subscribed_rau_tau_timer", BCON_INT32(12),
"network_access_mode", BCON_INT32(0),
"subscriber_status", BCON_INT32(0),
"operator_determined_barring", BCON_INT32(0),
"access_restriction_data", BCON_INT32(32)
);
ogs_assert(doc);

View File

@ -91,6 +91,10 @@ const Subscriber = new Schema({
$type: Number,
default: 0 // Service Granted
},
operator_determined_barring: {
$type: Number,
default: 0 // No barring
},
network_access_mode: {
$type: Number,
default: 0 // Packet and Circuit

View File

@ -120,6 +120,30 @@ const schema = {
}
}
},
"subscriber_status": {
"type": "number",
"title": "Subscriber Status (TS 29.272 7.3.29)",
"enum": [ 0, 1 ],
"enumNames": ["SERVICE_GRANTED", "OPERATOR_DETERMINED_BARRING"],
"default": 0,
},
"operator_determined_barring": {
"type": "number",
"title": "Operator Determined Barring (TS 29.272 7.3.30)",
"enum": [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ],
"enumNames": [
"(0) All Packet Oriented Services Barred",
"(1) Roamer Access HPLMN-AP Barred",
"(2) Roamer Access to VPLMN-AP Barred",
"(3) Barring of all outgoing calls",
"(4) Barring of all outgoing international calls",
"(5) Barring of all outgoing international calls except those directed to the home PLMN country",
"(6) Barring of all outgoing inter-zonal calls",
"(7) Barring of all outgoing inter-zonal calls except those directed to the home PLMN country",
"(8) Barring of all outgoing international calls except those directed to the home PLMN country and Barring of all outgoing inter-zonal calls"
],
"default": 0,
},
"slice": {
"type": "array",
"title": "Slice Configurations",
@ -503,6 +527,12 @@ const uiSchema = {
},
}
},
"subscriber_status" : {
classNames: "col-xs-7",
},
"operator_determined_barring" : {
classNames: "col-xs-7",
},
"slice": {
classNames: "col-xs-12",
"items": {

View File

@ -175,6 +175,8 @@ const View = ({ visible, disableOnClickOutside, subscriber, onEdit, onDelete, on
const purge_flag = (subscriber || {}).purge_flag;
const security = ((subscriber || {}).security || {});
const ambr = ((subscriber || {}).ambr || {});
const subscriber_status = (subscriber || {}).subscriber_status;
const operator_determined_barring = (subscriber || {}).operator_determined_barring;
const slice_list = ((subscriber || {}).slice || []);
return (
@ -260,6 +262,23 @@ const View = ({ visible, disableOnClickOutside, subscriber, onEdit, onDelete, on
</div>
</div>
</div>
<div className="sectioncolumn">
<div className="body">
<div className="left">
<SecurityIcon/>
</div>
<div className="right">
<div className="data">
{subscriber_status == 0 ? ( "SERVICE_GRANTED (0)" ) : ( "OPERATOR_DETERMINED_BARRING (1)" )}
<span style={{color:oc.gray[5]}}><KeyboardControlIcon/>Subscriber Status (TS 29.272 7.3.29)</span>
</div>
<div className="data">
{operator_determined_barring}
<span style={{color:oc.gray[5]}}><KeyboardControlIcon/>Operator Determined Barring (TS 29.272 7.3.30)</span>
</div>
</div>
</div>
</div>
<div className="sectioncolumn">
{mme_host && mme_host.length !== 0 &&
<div className="body">