open5gs/lib/nas/common/types.c

507 lines
17 KiB
C
Raw Normal View History

2019-04-27 14:54:30 +00:00
/*
2020-06-04 18:12:05 +00:00
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
2019-04-27 14:54:30 +00:00
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2017-08-20 10:04:23 +00:00
2020-05-22 01:24:21 +00:00
#include "ogs-nas-common.h"
2017-08-20 10:04:23 +00:00
2019-09-13 12:07:47 +00:00
int __ogs_nas_domain;
2019-04-27 14:54:30 +00:00
static uint8_t nas_ambr_from_kbps(
2019-04-27 14:54:30 +00:00
uint8_t *br, uint8_t *extended, uint8_t *extended2,
uint64_t input)
2017-08-20 10:04:23 +00:00
{
2019-04-27 14:54:30 +00:00
uint8_t length = 0;
2017-08-20 10:04:23 +00:00
/*
* Octet 3
* 11111111 0kbps
*/
if (input < 1) {
2017-08-20 10:04:23 +00:00
*br = 0xff;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 1);
2017-08-20 10:04:23 +00:00
return length;
}
/*
* Octet 3
2017-08-20 10:04:23 +00:00
*
* In network to UE direction:
* 00000000 Reserved
*
* Octet 3 : 00000001 - 00111111
* The APN-AMBR is binary coded in 8 bits, using a granularity of 1 kbps
* giving a range of values from 1 kbps to 63 kbps in 1 kbps increments.
*
* Octet 3 : 01000000 - 01111111
2017-08-20 10:04:23 +00:00
* The APN-AMBR is
* 64 kbps + ((the binary coded value in 8 bits 01000000) * 8 kbps)
* giving a range of values from 64 kbps to 568 kbps in 8 kbps increments.
*
* Octet 3 : 10000000 - 11111110
* The APN-AMBR is
* 576 kbps + ((the binary coded value in 8 bits 10000000) * 64 kbps)
* giving a range of values from 576 kbps to 8640 kbps in 64 kbps increments
*/
2017-08-20 10:04:23 +00:00
/* giving a range of 1 kbps to 63 kbps in 1 kbps increments. */
if (input >= 1 && input <= 63) {
2017-08-20 10:04:23 +00:00
*br = input;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 1);
2017-08-20 10:04:23 +00:00
}
/* giving a range of 64 kbps to 568 kbps in 8 kbps increments. */
else if (input >= 64 && input <= 568) {
2017-08-20 10:04:23 +00:00
*br = ((input - 64) / 8) + 0b01000000;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 1);
2017-08-20 10:04:23 +00:00
}
/* Set to 568 Kbps */
else if (input > 568 && input < 576) {
2017-08-20 10:04:23 +00:00
*br = 0b01111111;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 1);
2017-08-20 10:04:23 +00:00
}
/* giving a range of 576 kbps to 8640 kbps in 64 kbps increments. */
else if (input >= 576 && input <= 8640) {
2017-08-20 10:04:23 +00:00
*br = ((input - 576) / 64) + 0b10000000;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 1);
2017-08-20 10:04:23 +00:00
}
/* Set to 8640 Kbps */
else if (input > 8640 && input < 8700) {
2017-08-20 10:04:23 +00:00
*br = 0b11111110;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 1);
2017-08-20 10:04:23 +00:00
}
/*
* Octet 5 : 00000000
2017-08-20 10:04:23 +00:00
* Use the value indicated by the APN-AMBR for downlink in octet 3.
*
* Octet 5 : 00000001 - 01001010
2017-08-20 10:04:23 +00:00
* The APN-AMBR is
* 8600 kbps + ((the binary coded value in 8 bits) * 100 kbps),
* giving a range of values from 8700 kbps to 16000 kbps
* in 100 kbps increments.
*
* Octet 5 : 01001011 - 10111010
* The APN-AMBR is
* 16 Mbps + ((the binary coded value in 8 bits - 01001010) * 1 Mbps),
* giving a range of values from 17 Mbps to 128 Mbps in 1 Mbps increments.
*
* Octet 5 : 10111011 - 11111010
* 128 Mbps + (the binary coded value in 8 bits - 10111010) * 2 Mbps
* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments.
*
* All other values shall be interpreted as '11111010'.
2017-08-20 10:04:23 +00:00
*/
/* giving a range of 8700 kbps to 16000 kbps in 100 kbps increments. */
else if (input >= 8700 && input <= 16000) {
2017-08-20 10:04:23 +00:00
*br = 0b11111110;
*extended = ((input - 8600) / 100);
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 2);
2017-08-20 10:04:23 +00:00
}
/* Set to 16000 Kbps */
else if (input > 16000 && input < (17*1024)) {
2017-08-20 10:04:23 +00:00
*br = 0b11111110;
*extended = 0b01001010;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 2);
2017-08-20 10:04:23 +00:00
}
/* giving a range of 17 Mbps to 128 Mbps in 1 Mbps increments. */
else if (input >= (17*1024) && input <= (128*1024)) {
2017-08-20 10:04:23 +00:00
*br = 0b11111110;
*extended = ((input - (16*1024)) / (1*1024)) + 0b01001010;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 2);
2017-08-20 10:04:23 +00:00
}
/* Set to 128 Mbps */
else if (input > (128*1024) && input < (130*1024)) {
2017-08-20 10:04:23 +00:00
*br = 0b11111110;
*extended = 0b10111010;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 2);
2017-08-20 10:04:23 +00:00
}
/* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments. */
else if (input >= (130*1024) && input <= (256*1024)) {
2017-08-20 10:04:23 +00:00
*br = 0b11111110;
*extended = ((input - (128*1024)) / (2*1024)) + 0b10111010;
2019-04-27 14:54:30 +00:00
length = ogs_max(length, 2);
2017-08-20 10:04:23 +00:00
}
/* Set to 256 Mbps */
else if (input > (1*256*1024) && input < (2*256*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
length = ogs_max(length, 2);
}
/*
* Octet 7 : 00000000
* Use the value indicated by the APN-AMBR for downlink and
* APN-AMBR for downlink (extended) in octets 3 and 5.
*
* Octet 7 : 00000001 - 11111110
* The APN-AMBR is
* (the binary coded value in 8 bits) * 256 Mbps +
* "the value indicated by the APN-AMBR for downlink
* and APN-AMBR for downlink (extended) in octets 3 and 5",
*/
/* giving a range of values from 260M to 500M in 4M increments */
else if (input >= (2*256*1024) && input <= (255*256*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (1*256*1024)) / (256*1024);
length = ogs_max(length, 3);
}
/* if the sending entity want to indicate BR higher than 65280M */
else if (input > (255*256*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b11111110;
length = ogs_max(length, 3);
}
2017-08-20 10:04:23 +00:00
return length;
}
static uint8_t nas_qos_from_kbps(
uint8_t *br, uint8_t *extended, uint8_t *extended2,
uint64_t input)
{
uint8_t length = 0;
/*
* Octet 4
* 11111111 0kbps
*/
if (input < 1) {
*br = 0xff;
length = ogs_max(length, 1);
return length;
}
/*
* Octet 4
*
* In UE to network direction:
* 00000000 Subscribed maximum bit rate
*
* In network to UE direction:
* 00000000 Reserved
*
* Octet 4 : 00000001 - 00111111
* giving a range of 1 kbps to 63 kbps in 1 kbps increments.
*
* Octet 4 : 01000000 - 01111111
* 64 kbps + (the binary coded value in 8 bits - 01000000) * 8 kbps
* giving a range of 64 kbps to 568 kbps in 8 kbps increments.
*
* Octet 4 : 10000000 - 11111110
* 576 kbps + (the binary coded value in 8 bits 10000000) * 64 kbps
* giving a range of 576 kbps to 8640 kbps in 64 kbps increments.
*/
/* giving a range of 1 kbps to 63 kbps in 1 kbps increments. */
if (input >= 1 && input <= 63) {
*br = input;
length = ogs_max(length, 1);
}
/* giving a range of 64 kbps to 568 kbps in 8 kbps increments. */
else if (input >= 64 && input <= 568) {
*br = ((input - 64) / 8) + 0b01000000;
length = ogs_max(length, 1);
}
/* Set to 568 Kbps */
else if (input > 568 && input < 576) {
*br = 0b01111111;
length = ogs_max(length, 1);
}
/* giving a range of 576 kbps to 8640 kbps in 64 kbps increments. */
else if (input >= 576 && input <= 8640) {
*br = ((input - 576) / 64) + 0b10000000;
length = ogs_max(length, 1);
}
/* Set to 8640 Kbps */
else if (input > 8640 && input < 8700) {
*br = 0b11111110;
length = ogs_max(length, 1);
}
/*
* Octet 8
* 00000000 Use the value indicated by the bit rate in octet 4
*
* Octet 8 : 00000001 - 01001010
* 8600 kbps + (the binary coded value in 8 bits) * 100 kbps
* giving a range of 8700 kbps to 16000 kbps in 100 kbps increments.
*
* Octet 8 : 01001011 - 10111010
* 16 Mbps + (the binary coded value in 8 bits - 01001010) * 1 Mbps
* giving a range of 17 Mbps to 128 Mbps in 1 Mbps increments.
*
* Octet 8 : 10111011 - 11111010
* 128 Mbps + (the binary coded value in 8 bits - 10111010) * 2 Mbps
* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments.
*/
/* giving a range of 8700 kbps to 16000 kbps in 100 kbps increments. */
else if (input >= 8700 && input <= 16000) {
*br = 0b11111110;
*extended = ((input - 8600) / 100);
length = ogs_max(length, 2);
}
/* Set to 16000 Kbps */
else if (input > 16000 && input < (17*1024)) {
*br = 0b11111110;
*extended = 0b01001010;
length = ogs_max(length, 2);
}
/* giving a range of 17 Mbps to 128 Mbps in 1 Mbps increments. */
else if (input >= (17*1024) && input <= (128*1024)) {
*br = 0b11111110;
*extended = ((input - (16*1024)) / (1*1024)) + 0b01001010;
length = ogs_max(length, 2);
}
/* Set to 128 Mbps */
else if (input > (128*1024) && input < (130*1024)) {
*br = 0b11111110;
*extended = 0b10111010;
length = ogs_max(length, 2);
}
/* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments. */
else if (input >= (130*1024) && input <= (256*1024)) {
*br = 0b11111110;
*extended = ((input - (128*1024)) / (2*1024)) + 0b10111010;
length = ogs_max(length, 2);
}
/* Set to 256 Mbps */
else if (input > (256*1024) && input < (260*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
length = ogs_max(length, 2);
}
/*
* Octet 12 : 00000000
* 00000000 Use the value indicated by the bit rate in octet 4 and 8
*
* Octet 12 : 00000001 - 00111101
* 256Mbps + the binary coded value in 8 bits * 4Mbps
* giving a range of 260 Mbps to 500 Mbps in 4 Mbps increments.
*
* Octet 12 : 00111110 - 10100001
* 500Mbps + (the binary coded value in 8 bits - 00111101) * 10Mbps
* giving a range of 510 Mbps to 1500 Mbps in 10 Mbps increments.
*
* Octet 12 : 10100010 - 11110110
* 1500Mbps + (the binary coded value in 8 bits - 10100001) * 100Mbps
* giving a range of 1600 Mbps to 10 Gbps Mbps in 100 Mbps increaments.
*/
/* giving a range of values from 260M to 500M in 4M increments */
else if (input >= (260*1024) && input <= (500*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (256*1024)) / (4*1024);
length = ogs_max(length, 3);
}
/* if a range of values from 500M to 510M */
else if (input > (500*1024) && input < (510*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b00111101;
length = ogs_max(length, 3);
}
/* giving a range of values from 510M to 1500M in 10M increments */
else if (input >= (510*1024) && input <= (1500*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (500*1024)) / (10*1024) + 0b00111101;
length = ogs_max(length, 3);
}
/* if a range of values from 1500M to 1600M */
else if (input > (1500*1024) && input < (1600*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b10100001;
length = ogs_max(length, 3);
}
/* giving a range of values from 1600M to 10000M in 100M increments */
else if (input >= (1600*1024) && input <= (10*1000*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (1500*1024)) / (100*1024) + 0b10100001;
length = ogs_max(length, 3);
}
/* if the sending entity want to indicate BR higher than 10000Mbps */
else if (input > (10*1000*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b11110110;
length = ogs_max(length, 3);
}
return length;
}
2017-08-20 10:04:23 +00:00
void apn_ambr_build(
2019-09-13 12:07:47 +00:00
ogs_nas_apn_aggregate_maximum_bit_rate_t *apn_aggregate_maximum_bit_rate,
2019-04-27 14:54:30 +00:00
uint32_t dl_apn_ambr, uint32_t ul_apn_ambr)
2017-08-20 10:04:23 +00:00
{
2019-04-27 14:54:30 +00:00
uint8_t length = 0;
2017-08-20 10:04:23 +00:00
dl_apn_ambr = dl_apn_ambr / 1024; /* Kbps */
ul_apn_ambr = ul_apn_ambr / 1024; /* Kbps */
memset(apn_aggregate_maximum_bit_rate, 0,
2019-09-13 12:07:47 +00:00
sizeof(ogs_nas_apn_aggregate_maximum_bit_rate_t));
2017-08-20 10:04:23 +00:00
length = ogs_max(length, nas_ambr_from_kbps(
2017-08-20 10:04:23 +00:00
&apn_aggregate_maximum_bit_rate->dl_apn_ambr,
&apn_aggregate_maximum_bit_rate->dl_apn_ambr_extended,
&apn_aggregate_maximum_bit_rate->dl_apn_ambr_extended2,
dl_apn_ambr));
length = ogs_max(length, nas_ambr_from_kbps(
2017-08-20 10:04:23 +00:00
&apn_aggregate_maximum_bit_rate->ul_apn_ambr,
&apn_aggregate_maximum_bit_rate->ul_apn_ambr_extended,
&apn_aggregate_maximum_bit_rate->ul_apn_ambr_extended2,
ul_apn_ambr));
apn_aggregate_maximum_bit_rate->length = length*2;
}
2019-09-13 12:07:47 +00:00
void eps_qos_build(ogs_nas_eps_quality_of_service_t *eps_qos, uint8_t qci,
2019-04-27 14:54:30 +00:00
uint64_t dl_mbr, uint64_t ul_mbr, uint64_t dl_gbr, uint64_t ul_gbr)
2017-09-04 15:04:05 +00:00
{
2019-04-27 14:54:30 +00:00
uint8_t length = 0;
2017-09-04 15:04:05 +00:00
dl_mbr = dl_mbr / 1024; /* Kbps */
ul_mbr = ul_mbr / 1024; /* Kbps */
dl_gbr = dl_gbr / 1024; /* Kbps */
ul_gbr = ul_gbr / 1024; /* Kbps */
2019-09-13 12:07:47 +00:00
memset(eps_qos, 0, sizeof(ogs_nas_eps_quality_of_service_t));
2017-09-04 15:04:05 +00:00
eps_qos->qci = qci;
if (dl_mbr)
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->dl_mbr,
&eps_qos->dl_mbr_extended,
&eps_qos->dl_mbr_extended2,
dl_mbr));
if (ul_mbr)
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->ul_mbr,
&eps_qos->ul_mbr_extended,
&eps_qos->ul_mbr_extended2,
ul_mbr));
if (dl_gbr)
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->dl_gbr,
&eps_qos->dl_gbr_extended,
&eps_qos->dl_gbr_extended2,
dl_gbr));
if (ul_gbr)
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->ul_gbr,
&eps_qos->ul_gbr_extended,
&eps_qos->ul_gbr_extended2,
ul_gbr));
2017-09-04 15:04:05 +00:00
eps_qos->length = length*4+1;
}
void ogs_nas_bitrate_from_uint64(ogs_nas_bitrate_t *nas, uint64_t bitrate)
{
ogs_assert(nas);
ogs_assert(bitrate);
bitrate >>= 10; /* bps to Kbps */
for (nas->unit = OGS_NAS_BR_UNIT_1K;
nas->unit < OGS_NAS_BR_UNIT_256P; nas->unit++) {
if ((bitrate >> 2) == 0) {
break;
}
bitrate >>= 2;
}
nas->value = bitrate;
}
2021-11-14 12:07:56 +00:00
uint64_t ogs_nas_bitrate_to_uint64(ogs_nas_bitrate_t *nas_bitrate)
{
ogs_assert(nas_bitrate);
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1K)
return nas_bitrate->value * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4K)
return nas_bitrate->value * 4 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16K)
return nas_bitrate->value * 16 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64K)
return nas_bitrate->value * 64 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256K)
return nas_bitrate->value * 256 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1M)
return nas_bitrate->value * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4M)
return nas_bitrate->value * 4 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16M)
return nas_bitrate->value * 16 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64M)
return nas_bitrate->value * 64 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256M)
return nas_bitrate->value * 256 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1G)
return nas_bitrate->value * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4G)
return nas_bitrate->value * 4 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16G)
return nas_bitrate->value * 16 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64G)
return nas_bitrate->value * 64 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256G)
return nas_bitrate->value * 256 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1T)
return nas_bitrate->value * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4T)
return nas_bitrate->value * 4 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16T)
return nas_bitrate->value * 16 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64T)
return nas_bitrate->value * 64 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256T)
return nas_bitrate->value * 256 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1P)
return nas_bitrate->value * 1024 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4P)
return nas_bitrate->value * 4 * 1024 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16P)
return nas_bitrate->value * 16 * 1024 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64P)
return nas_bitrate->value * 64 * 1024 * 1024 * 1024 * 1024 * 1024;
if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256P)
return nas_bitrate->value * 256 * 1024 * 1024 * 1024 * 1024 * 1024;
ogs_fatal("Unknown unit [%d]", nas_bitrate->unit);
ogs_assert_if_reached();
return 0;
}