Compare commits

..

24 Commits

Author SHA1 Message Date
Sukchan Lee
bb2e976958 nextepc release v0.3.11 2019-04-28 05:17:14 +00:00
Sukchan Lee
4165ec1264 Release v0.3.11 2019-04-27 14:00:29 +00:00
Sukchan Lee
540a3956bb Merge pull request #171 from toldjuuso/patch-1
typo: trace log message on s11
2019-04-19 06:15:52 +09:00
Juuso Haavisto
9919e7dc86 typo: trace log message on s11 2019-04-18 20:10:18 +03:00
Sukchan Lee
6bd8411fc1 Add log message if EIA0 is used (#167) 2019-04-02 11:11:24 +09:00
Sukchan Lee
8fea12643a nas_plmn_id_t structure for NAS message. (#166)
/**********************************
 * NAS PLMN_ID Structure             */
typedef struct _nas_plmn_id_t {
ED2(uint8_t mcc2:4;,
    uint8_t mcc1:4;)
ED2(uint8_t mnc3:4;,
    uint8_t mcc3:4;)
ED2(uint8_t mnc2:4;,
    uint8_t mnc1:4;)
} __attribute__ ((packed)) nas_plmn_id_t;

/**********************************
 * PLMN_ID Structure             */
typedef struct _plmn_id_t {
ED2(c_uint8_t mcc2:4;,
    c_uint8_t mcc1:4;)
ED2(c_uint8_t mnc1:4;,
    c_uint8_t mcc3:4;)
ED2(c_uint8_t mnc3:4;,
    c_uint8_t mnc2:4;)
} __attribute__ ((packed)) plmn_id_t;
2019-03-31 14:26:18 +09:00
Sukchan Lee
c964d1df3c Increase packet memory buffer (#161) 2019-03-22 16:59:37 +09:00
Sukchan Lee
ddaea685b3 Notify mailing list 2019-03-17 21:37:48 +09:00
Sukchan Lee
e1ad9c43d7 Fix the source code (#159) 2019-03-17 01:58:14 +00:00
Sukchan Lee
0b91d42cb1 Merge pull request #159 from laf0rge/laforge/typo
nas_message.py: Fix copy+paste error
2019-03-17 10:57:37 +09:00
Harald Welte
653701abdb nas_message.py: Fix copy+paste error
Files are not generated by gtpv2c_tlv.py but by nas_message.py
2019-03-16 20:55:54 +01:00
Sukchan Lee
58bcda332b Set ENB-ID to zero in S1AP message. (#156) 2019-03-10 10:32:26 +09:00
Sukchan Lee
8cb620e477 refine exit routine for nextepc-epcd 2019-03-03 21:11:50 +09:00
Sukchan Lee
5cac796e46 Support 4-byte RES in auth (#147) 2019-02-07 20:53:01 +09:00
Sukchan Lee
8c68560ccd fix the timezone in EMM & GTP encoding 2019-01-20 15:36:11 +09:00
Sukchan Lee
b2c6c8f856 Merge pull request #129 from EugeneBogush/patch-1
maybe this more logically?
2018-12-05 06:46:03 +09:00
EugeneBogush
f753d38338 maybe this more logically? 2018-12-04 18:00:46 +02:00
Sukchan Lee
c711e788d2 Add TimeZone in the docker environment 2018-11-13 10:03:24 +09:00
Sukchan Lee
26f4081979 Merge pull request #109 from brchiu/add_missing_c_namespace 2018-10-12 20:49:48 +09:00
Bi-Ruei, Chiu
3427835ecc Add missing C namespace 2018-10-12 14:59:30 +08:00
Sukchan Lee
7312dd1974 Change configuration description (#100) 2018-09-23 14:41:55 +09:00
Sukchan Lee
f5599896ff SGW selection mode is added (#100) 2018-09-23 14:29:19 +09:00
Sukchan Lee
aea1d83026 Create mme_sgw_t and mme_pgw_t for configuration (#100) 2018-09-23 13:16:40 +09:00
Jihoon Brandon Lee
3dc2d396db S1AP PWS(public warning system) support
S1AP Write Replace Warning Request/Response
S1AP Kill Request/Response
CBC integration (SBc-AP) is required to initiate a PWS procedure.
2018-09-13 20:38:33 -06:00
46 changed files with 1016 additions and 145 deletions

View File

@@ -86,6 +86,11 @@ If you don't understand something about NextEPC, the [http://nextepc.org](http:/
Problem with NextEPC can be filed as [issues](https://github.com/acetcom/nextepc/issues) in this repository. And also, we've created *Discord* workspace for _nextepc_. Use [this link](https://discord.gg/GreNkuc) to get started.
## Mailing List
Discussions related to this project are happening on the nextepc@lists.osmocom.org mailing list, please see <https://lists.osmocom.org/mailman/listinfo/nextepc> for subscription options and the list archive.
## License
NextEPC source files are made available under the terms of the GNU Affero General Public License (GNU AGPLv3). See [this link](http://nextepc.org/docs/nextepc/4-license/) for details.

View File

@@ -8,7 +8,7 @@ dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
AC_INIT([NextEPC], [0.3.10], [acetcom@gmail.com])
AC_INIT([NextEPC], [0.3.11], [acetcom@gmail.com])
AC_SUBST(LIBVERSION)
LIBVERSION=1:0:0

12
debian/changelog vendored
View File

@@ -1,3 +1,15 @@
nextepc (0.3.11~bionic) bionic; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Sat, 27 Apr 2019 13:59:08 +0000
nextepc (0.3.11~xenial) xenial; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Sat, 27 Apr 2019 13:57:42 +0000
nextepc (0.3.10~xenial) xenial; urgency=medium
* Bug Fixed

View File

@@ -14,6 +14,9 @@ extern "C" {
#define SCTP_S1AP_PPID 18
#define SCTP_X2AP_PPID 27
#define MAX_NUM_OF_SGW 32
#define MAX_NUM_OF_PGW 32
#define MAX_NUM_OF_ENB 128
#define MAX_NUM_OF_UE 128
#define MAX_NUM_OF_SESS 4
@@ -87,13 +90,6 @@ typedef struct _e_cgi_t {
c_uint32_t cell_id; /* 28 bit */
} __attribute__ ((packed)) e_cgi_t;
typedef struct _guti_t {
plmn_id_t plmn_id;
c_uint16_t mme_gid;
c_uint8_t mme_code;
c_uint32_t m_tmsi;
} __attribute__ ((packed)) guti_t;
/**************************************************
* Common Structure
* S1AP : 9.2.2.1 Transport Layer Address, See 36.414

View File

@@ -7,8 +7,8 @@
#include "core_debug.h"
#include "core_pool.h"
#define MAX_NUM_OF_CLBUF 256
#define MAX_NUM_OF_PKBUF 256
#define MAX_NUM_OF_CLBUF (8192 + 4096 + 2048 + 1024 + 512 + 128)
#define MAX_NUM_OF_PKBUF (8192 + 4096 + 2048 + 1024 + 512 + 128)
pool_declare(clbuf_pool, clbuf_t, MAX_NUM_OF_CLBUF);
pool_declare(pkbuf_pool, pkbuf_t, MAX_NUM_OF_PKBUF);
@@ -23,12 +23,12 @@ pool_declare(pkbuf_pool, pkbuf_t, MAX_NUM_OF_PKBUF);
#define SIZEOF_CLUSTER_2048 CORE_ALIGN(2048+MAX_SIZEOF_HEADROOM, BOUNDARY)
#define SIZEOF_CLUSTER_8192 CORE_ALIGN(8192+MAX_SIZEOF_HEADROOM, BOUNDARY)
#define MAX_NUM_OF_CLUSTER_128 256
#define MAX_NUM_OF_CLUSTER_256 256
#define MAX_NUM_OF_CLUSTER_512 256
#define MAX_NUM_OF_CLUSTER_1024 256
#define MAX_NUM_OF_CLUSTER_2048 256
#define MAX_NUM_OF_CLUSTER_8192 256
#define MAX_NUM_OF_CLUSTER_128 8192
#define MAX_NUM_OF_CLUSTER_256 4096
#define MAX_NUM_OF_CLUSTER_512 2048
#define MAX_NUM_OF_CLUSTER_1024 1024
#define MAX_NUM_OF_CLUSTER_2048 512
#define MAX_NUM_OF_CLUSTER_8192 128
typedef c_uint8_t cluster_128_t[SIZEOF_CLUSTER_128];
typedef c_uint8_t cluster_256_t[SIZEOF_CLUSTER_256];

View File

@@ -28,14 +28,13 @@ status_t gtp_node_final(void)
return CORE_OK;
}
status_t gtp_add_node(list_t *list, gtp_node_t **node,
status_t gtp_create_node(gtp_node_t **node,
c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4)
{
status_t rv;
gtp_node_t *new_node = NULL;
c_sockaddr_t *preferred_list = NULL;
d_assert(list, return CORE_ERROR,);
d_assert(all_list, return CORE_ERROR,);
rv = core_copyaddrinfo(&preferred_list, all_list);
@@ -71,8 +70,6 @@ status_t gtp_add_node(list_t *list, gtp_node_t **node,
list_init(&new_node->local_list);
list_init(&new_node->remote_list);
list_append(list, new_node);
}
*node = new_node;
@@ -80,7 +77,22 @@ status_t gtp_add_node(list_t *list, gtp_node_t **node,
return CORE_OK;
}
gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid,
status_t gtp_delete_node(gtp_node_t *node)
{
d_assert(node, return CORE_ERROR,);
if (node->sock)
sock_delete(node->sock);
gtp_xact_delete_all(node);
core_freeaddrinfo(node->sa_list);
pool_free_node(&gtp_node_pool, node);
return CORE_OK;
}
gtp_node_t *gtp_add_node(list_t *list, gtp_f_teid_t *f_teid,
c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4)
{
status_t rv;
@@ -94,9 +106,16 @@ gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid,
rv = gtp_f_teid_to_sockaddr(f_teid, port, &sa_list);
d_assert(rv == CORE_OK, return NULL,);
rv = gtp_add_node(list, &node, sa_list, no_ipv4, no_ipv6, prefer_ipv4);
rv = gtp_create_node(&node, sa_list, no_ipv4, no_ipv6, prefer_ipv4);
d_assert(rv == CORE_OK, return NULL,);
d_assert(node, return NULL,);
if (node == NULL)
{
d_error("Invalid Parameter : "
"port[%d], no_ipv4[%d], no_ipv6[%d], prefer_ipv4[%d]",
port, no_ipv4, no_ipv6, prefer_ipv4);
return NULL;
}
list_append(list, node);
rv = gtp_f_teid_to_ip(f_teid, &node->ip);
d_assert(rv == CORE_OK, return NULL,);
@@ -111,19 +130,15 @@ gtp_node_t *gtp_add_node_with_teid(list_t *list, gtp_f_teid_t *f_teid,
status_t gtp_remove_node(list_t *list, gtp_node_t *node)
{
status_t rv;
d_assert(node, return CORE_ERROR,);
list_remove(list, node);
if (node->sock)
sock_delete(node->sock);
rv = gtp_delete_node(node);
d_assert(rv == CORE_OK, return CORE_ERROR,);
gtp_xact_delete_all(node);
core_freeaddrinfo(node->sa_list);
pool_free_node(&gtp_node_pool, node);
return CORE_OK;
return rv;
}
status_t gtp_remove_all_nodes(list_t *list)

View File

@@ -35,9 +35,11 @@ typedef struct _gtp_node_t {
CORE_DECLARE(status_t) gtp_node_init(void);
CORE_DECLARE(status_t) gtp_node_final(void);
CORE_DECLARE(status_t) gtp_add_node(list_t *list, gtp_node_t **node,
c_sockaddr_t *sa_list, int no_ipv4, int no_ipv6, int prefer_ipv4);
CORE_DECLARE(gtp_node_t *) gtp_add_node_with_teid(
CORE_DECLARE(status_t) gtp_create_node(gtp_node_t **node,
c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4);
CORE_DECLARE(status_t) gtp_delete_node(gtp_node_t *node);
CORE_DECLARE(gtp_node_t *) gtp_add_node(
list_t *list, gtp_f_teid_t *f_teid,
c_uint16_t port, int no_ipv4, int no_ipv6, int prefer_ipv4);
CORE_DECLARE(status_t) gtp_remove_node(list_t *list, gtp_node_t *node);

View File

@@ -379,14 +379,18 @@ ED3(c_uint8_t ipv4:1;,
#define GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 0
#define GTP_UE_TIME_ZONE_1_HOUR_FOR_DAYLIGHT_SAVING_TIME 1
#define GTP_UE_TIME_ZONE_2_HOUR_FOR_DAYLIGHT_SAVING_TIME 2
/* Time Zone" IE in 3GPP TS 24.008 [5].
* This field uses the same format as the Timezone field used in the
* TP-Service-Centre-Time-Stamp, which is defined in 3GPP TS 23.040 [90],
* and its value shall be set as defined in 3GPP TS 22.042 */
typedef struct _gtp_ue_timezone_t {
/* Time Zone" IE in 3GPP TS 24.008 [5].
* This field uses the same format as the Timezone field used in the
* TP-Service-Centre-Time-Stamp, which is defined in 3GPP TS 23.040 [90],
* and its value shall be set as defined in 3GPP TS 22.042 */
#define GTP_TIME_TO_BCD(x) TIME_TO_BCD(x)
ED2(c_uint8_t sign:1;,
c_uint8_t gmtoff:7;) /* quarters of an hour */
/* The Time Zone indicates the difference, expressed in quarters of an hour,
* between the local time and GMT. In the first of the two semi-octets,
* the first bit (bit 3 of the seventh octet of
* the TP-Service-Centre-Time-Stamp field) represents
* the algebraic sign of this difference (0: positive, 1: negative). */
c_uint8_t timezone;
ED2(c_uint8_t spare:6;,
c_uint8_t daylight_saving_time:2;)
} __attribute__ ((packed)) gtp_ue_timezone_t;

View File

@@ -24,9 +24,9 @@
*/
/*******************************************************************************
* This file had been created by gtpv2c_tlv.py script v0.1.0
* This file had been created by nas_message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2018-01-23 15:58:42.874567 by acetcom
* Created on: 2019-03-17 01:58:02.778431 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@@ -24,9 +24,9 @@
*/
/*******************************************************************************
* This file had been created by gtpv2c_tlv.py script v0.1.0
* This file had been created by nas_message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2018-01-23 15:58:42.903985 by acetcom
* Created on: 2019-03-17 01:58:02.809354 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@@ -24,9 +24,9 @@
*/
/*******************************************************************************
* This file had been created by gtpv2c_tlv.py script v0.1.0
* This file had been created by nas_message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2018-01-23 15:58:42.829935 by acetcom
* Created on: 2019-03-17 01:58:02.731397 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@@ -24,9 +24,9 @@
*/
/*******************************************************************************
* This file had been created by gtpv2c_tlv.py script v0.1.0
* This file had been created by nas_message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2018-01-23 15:58:42.823738 by acetcom
* Created on: 2019-03-17 01:58:02.723555 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@@ -24,9 +24,9 @@
*/
/*******************************************************************************
* This file had been created by gtpv2c_tlv.py script v0.1.0
* This file had been created by nas_message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2018-01-23 15:58:42.847411 by acetcom
* Created on: 2019-03-17 01:58:02.754073 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@@ -5,6 +5,29 @@
#include "nas_types.h"
void *nas_from_plmn_id(nas_plmn_id_t *nas_plmn_id, plmn_id_t *plmn_id)
{
memcpy(nas_plmn_id, plmn_id, PLMN_ID_LEN);
if (plmn_id->mnc1 != 0xf)
{
nas_plmn_id->mnc1 = plmn_id->mnc1;
nas_plmn_id->mnc2 = plmn_id->mnc2;
nas_plmn_id->mnc3 = plmn_id->mnc3;
}
return nas_plmn_id;
}
void *nas_to_plmn_id(plmn_id_t *plmn_id, nas_plmn_id_t *nas_plmn_id)
{
memcpy(plmn_id, nas_plmn_id, PLMN_ID_LEN);
if (plmn_id->mnc1 != 0xf)
{
plmn_id->mnc1 = nas_plmn_id->mnc1;
plmn_id->mnc2 = nas_plmn_id->mnc2;
plmn_id->mnc3 = nas_plmn_id->mnc3;
}
return plmn_id;
}
static c_uint8_t br_calculate(
c_uint8_t *br, c_uint8_t *extended, c_uint8_t *extended2,
c_uint64_t input)
@@ -229,6 +252,7 @@ void nas_tai_list_build(
tai0_list_t target0;
tai2_list_t target2;
nas_plmn_id_t nas_plmn_id;
d_assert(target, return,);
d_assert(source0, return,);
@@ -249,7 +273,8 @@ void nas_tai_list_build(
return, "num = %d", source0->tai[i].num);
target0.tai[i].num = source0->tai[i].num - 1;
memcpy(&target0.tai[i].plmn_id,
&source0->tai[i].plmn_id, PLMN_ID_LEN);
nas_from_plmn_id(&nas_plmn_id, &source0->tai[i].plmn_id),
PLMN_ID_LEN);
for (j = 0; j < source0->tai[i].num; j++)
{
@@ -290,7 +315,8 @@ void nas_tai_list_build(
for (i = 0; i < source2->num; i++)
{
memcpy(&target2.tai[i].plmn_id,
&source2->tai[i].plmn_id, PLMN_ID_LEN);
nas_from_plmn_id(&nas_plmn_id, &source2->tai[i].plmn_id),
PLMN_ID_LEN);
target2.tai[i].tac = htons(source2->tai[i].tac);
}
memcpy(target->buffer + target->length, &target2, size);

View File

@@ -30,6 +30,27 @@ extern "C" {
#define NAS_KSI_NO_KEY_IS_AVAILABLE 0x7
/**********************************
* NAS PLMN_ID Structure */
typedef struct _nas_plmn_id_t {
ED2(uint8_t mcc2:4;,
uint8_t mcc1:4;)
ED2(uint8_t mnc3:4;,
uint8_t mcc3:4;)
ED2(uint8_t mnc2:4;,
uint8_t mnc1:4;)
} __attribute__ ((packed)) nas_plmn_id_t;
void *nas_from_plmn_id(nas_plmn_id_t *nas_plmn_id, plmn_id_t *plmn_id);
void *nas_to_plmn_id(plmn_id_t *plmn_id, nas_plmn_id_t *nas_plmn_id);
typedef struct _guti_t {
nas_plmn_id_t plmn_id;
uint16_t mme_gid;
uint8_t mme_code;
uint32_t m_tmsi;
} __attribute__ ((packed)) guti_t;
/* 9.9.2.0 Additional information
* O TLV 3-n */
#define NAX_MAX_ADDITIONAL_INFORMATION_LEN 255
@@ -73,7 +94,7 @@ ED8(c_uint8_t ebi15:1;,
* See subclause 10.5.1.3 in 3GPP TS 24.008 [13]
* O TV 6 */
typedef struct _nas_location_area_identification_t {
plmn_id_t plmn_id;
nas_plmn_id_t plmn_id;
c_uint16_t lac;
} __attribute__ ((packed)) nas_location_area_identification_t;
@@ -121,7 +142,7 @@ ED5(c_uint8_t spare:2;,
c_uint8_t odd_even:1;,
c_uint8_t type:3;)
c_uint8_t mbms_servicec_id[3];
plmn_id_t plmn_id;
nas_plmn_id_t plmn_id;
c_uint8_t mbms_session_identity;
} __attribute__ ((packed)) nas_mobile_identity_tmgi_t;
@@ -187,7 +208,7 @@ typedef struct _nas_mobile_station_classmark_3_t {
#define NAS_MAX_PLMN 15
typedef struct _nas_plmn_list_t {
c_uint8_t length;
plmn_id_t plmn_id[NAS_MAX_PLMN];
nas_plmn_id_t plmn_id[NAS_MAX_PLMN];
} __attribute__ ((packed)) nas_plmn_list_t;
/* 9.9.2.10 Supported codec list
@@ -415,7 +436,7 @@ typedef struct _nas_eps_mobile_identity_guti_t {
ED3(c_uint8_t spare:4;,
c_uint8_t odd_even:1;,
c_uint8_t type:3;)
plmn_id_t plmn_id;
nas_plmn_id_t plmn_id;
c_uint16_t mme_gid;
c_uint8_t mme_code;
c_uint32_t m_tmsi;
@@ -715,8 +736,12 @@ typedef struct _nas_time_zone_and_time_t {
c_uint8_t hour;
c_uint8_t min;
c_uint8_t sec;
ED2(c_uint8_t sign:1;,
c_uint8_t gmtoff:7;) /* quarters of an hour */
/* The Time Zone indicates the difference, expressed in quarters of an hour,
* between the local time and GMT. In the first of the two semi-octets,
* the first bit (bit 3 of the seventh octet of
* the TP-Service-Centre-Time-Stamp field) represents
* the algebraic sign of this difference (0: positive, 1: negative). */
c_uint8_t timezone;
} nas_time_zone_and_time_t;
/* 9.9.3.31 TMSI status
@@ -730,7 +755,10 @@ ED3(c_uint8_t type:4;,
/* 9.9.3.32 Tracking area identity
* O TV 6 */
typedef tai_t nas_tracking_area_identity_t;
typedef struct _nas_tracking_area_identity_t {
nas_plmn_id_t plmn_id;
uint16_t tac;
} __attribute__ ((packed)) nas_tracking_area_identity_t;
/* 9.9.3.33 Tracking area identity list
* M LV 7-97 */
@@ -743,6 +771,12 @@ typedef struct _tai0_list_t {
ED3(c_uint8_t spare:1;,
c_uint8_t type:2;,
c_uint8_t num:5;)
/*
* Do not change 'plmn_id_t' to 'nas_plmn_id_t'.
* Use 'plmn_id_t' for easy implementation.
* nas_tai_list_build() changes to NAS format(nas_plmn_id_t)
* and is sent to the UE.
*/
plmn_id_t plmn_id;
c_uint16_t tac[MAX_NUM_OF_TAI];
} __attribute__ ((packed)) tai[MAX_NUM_OF_TAI];
@@ -752,6 +786,12 @@ typedef struct _tai2_list_t {
ED3(c_uint8_t spare:1;,
c_uint8_t type:2;,
c_uint8_t num:5;)
/*
* Do not change 'tai_t' to 'nas_tracking_area_identity_t'.
* Use 'tai_t' for easy implementation.
* nas_tai_list_build() changes to NAS format(nas_tracking_area_identity_t)
* and is sent to the UE.
*/
tai_t tai[MAX_NUM_OF_TAI];
} __attribute__ ((packed)) tai2_list_t;

View File

@@ -87,7 +87,7 @@ def output_header_to_file(f):
""")
f.write("/*******************************************************************************\n")
f.write(" * This file had been created by gtpv2c_tlv.py script v%s\n" % (version))
f.write(" * This file had been created by nas_message.py script v%s\n" % (version))
f.write(" * Please do not modify this file but regenerate it via script.\n")
f.write(" * Created on: %s by %s\n * from %s\n" % (str(now), getpass.getuser(), filename))
f.write(" ******************************************************************************/\n\n")

View File

@@ -72,17 +72,17 @@ status_t app_did_initialize(void)
void app_will_terminate(void)
{
app_logger_stop();
}
void app_did_terminate(void)
{
if (context_self()->db_uri)
{
d_trace(1, "DB-Client try to terminate\n");
context_db_final();
d_trace(1, "DB-Client terminate...done\n");
}
}
void app_did_terminate(void)
{
app_logger_final();
context_final();

View File

@@ -5,6 +5,10 @@
#include <yaml.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
yaml_document_t *document;
yaml_node_t *node;

View File

@@ -21,6 +21,7 @@ libmme_la_SOURCES = \
esm_sm.c esm_handler.c esm_build.c \
mme_gtp_path.c mme_s11_build.c mme_s11_handler.c \
mme_sm.c mme_path.c \
sbc_message.h sbc_handler.h sbc_handler.c \
$(NULL)
if USRSCTP

View File

@@ -278,13 +278,22 @@ status_t emm_build_security_mode_command(
sizeof(replayed_ue_security_capabilities->uea) +
sizeof(replayed_ue_security_capabilities->uia) +
sizeof(replayed_ue_security_capabilities->gea);
d_trace(5, " SEC[LEN:%d EEA:0x%x EIA:0x%x UEA:0x%x UIA:0x%x GEA:0x%x]\n",
d_trace(5, " UE[LEN:%d EEA:0x%x EIA:0x%x UEA:0x%x UIA:0x%x GEA:0x%x]\n",
replayed_ue_security_capabilities->length,
replayed_ue_security_capabilities->eea,
replayed_ue_security_capabilities->eia,
replayed_ue_security_capabilities->uea,
replayed_ue_security_capabilities->uia,
replayed_ue_security_capabilities->gea);
d_trace(5, " Selected[Integrity:0x%x Encrypt:0x%x]\n",
mme_ue->selected_int_algorithm, mme_ue->selected_enc_algorithm);
if (mme_ue->selected_int_algorithm == NAS_SECURITY_ALGORITHMS_EIA0)
{
d_fatal("Encrypt[0x%x] CAN BE skipped, "
"but Integrity[0x%x] CANNOT BE skipped",
mme_ue->selected_enc_algorithm, mme_ue->selected_int_algorithm);
return CORE_ERROR;
}
mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_ue->selected_int_algorithm,
mme_ue->kasme, mme_ue->knas_int);

View File

@@ -100,9 +100,8 @@ status_t emm_handle_attach_request(
{
nas_tracking_area_identity_t *last_visited_registered_tai =
&attach_request->last_visited_registered_tai;
memcpy(&mme_ue->visited_plmn_id,
&last_visited_registered_tai->plmn_id, PLMN_ID_LEN);
nas_to_plmn_id(
&mme_ue->visited_plmn_id, &last_visited_registered_tai->plmn_id);
}
else
{
@@ -222,12 +221,16 @@ status_t emm_handle_attach_complete(
universal_time_and_local_time_zone->min = NAS_TIME_TO_BCD(xt_gmt.tm_min);
universal_time_and_local_time_zone->sec = NAS_TIME_TO_BCD(xt_gmt.tm_sec);
if (xt_local.tm_gmtoff >= 0)
universal_time_and_local_time_zone->sign = 0;
{
universal_time_and_local_time_zone->timezone =
NAS_TIME_TO_BCD(xt_local.tm_gmtoff / 900);
}
else
universal_time_and_local_time_zone->sign = 1;
/* quarters of an hour */
universal_time_and_local_time_zone->gmtoff =
NAS_TIME_TO_BCD(xt_local.tm_gmtoff / 900);
{
universal_time_and_local_time_zone->timezone =
NAS_TIME_TO_BCD((-xt_local.tm_gmtoff) / 900);
universal_time_and_local_time_zone->timezone |= 0x08;
}
emm_information->presencemask |=
NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT;
@@ -460,9 +463,8 @@ status_t emm_handle_tau_request(
{
nas_tracking_area_identity_t *last_visited_registered_tai =
&tau_request->last_visited_registered_tai;
memcpy(&mme_ue->visited_plmn_id,
&last_visited_registered_tai->plmn_id, PLMN_ID_LEN);
nas_to_plmn_id(
&mme_ue->visited_plmn_id, &last_visited_registered_tai->plmn_id);
}
else
{

View File

@@ -403,10 +403,9 @@ void emm_state_authentication(fsm_t *s, event_t *e)
d_trace(3, "[EMM] Authentication response\n");
d_trace(5, " IMSI[%s]\n", mme_ue->imsi_bcd);
if (authentication_response_parameter->length !=
mme_ue->xres_len ||
memcmp(authentication_response_parameter->res,
mme_ue->xres, mme_ue->xres_len) != 0)
if (memcmp(authentication_response_parameter->res,
mme_ue->xres,
authentication_response_parameter->length) != 0)
{
rv = nas_send_authentication_reject(mme_ue);
d_assert(rv == CORE_OK,, "nas send error");

View File

@@ -29,6 +29,9 @@
static mme_context_t self;
static fd_config_t g_fd_conf;
pool_declare(mme_sgw_pool, mme_sgw_t, MAX_NUM_OF_SGW);
pool_declare(mme_pgw_pool, mme_pgw_t, MAX_NUM_OF_PGW);
index_declare(mme_enb_pool, mme_enb_t, MAX_NUM_OF_ENB);
index_declare(mme_ue_pool, mme_ue_t, MAX_POOL_OF_UE);
index_declare(enb_ue_pool, enb_ue_t, MAX_POOL_OF_UE);
@@ -59,6 +62,9 @@ status_t mme_context_init()
list_init(&self.sgw_list);
list_init(&self.pgw_list);
pool_init(&mme_sgw_pool, MAX_NUM_OF_SGW);
pool_init(&mme_pgw_pool, MAX_NUM_OF_PGW);
index_init(&mme_enb_pool, MAX_NUM_OF_ENB);
index_init(&mme_ue_pool, MAX_POOL_OF_UE);
@@ -121,8 +127,12 @@ status_t mme_context_final()
index_final(&mme_enb_pool);
gtp_remove_all_nodes(&self.sgw_list);
gtp_remove_all_nodes(&self.pgw_list);
mme_sgw_remove_all();
mme_pgw_remove_all();
pool_final(&mme_sgw_pool);
pool_final(&mme_pgw_pool);
gtp_node_final();
sock_remove_all_nodes(&self.s1ap_list);
@@ -1280,12 +1290,14 @@ status_t mme_context_parse_config()
yaml_iter_recurse(&mme_iter, &gtpc_array);
do
{
gtp_node_t *sgw = NULL;
mme_sgw_t *sgw = NULL;
c_sockaddr_t *list = NULL;
int family = AF_UNSPEC;
int i, num = 0;
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpc_port;
c_uint16_t tac[MAX_NUM_OF_TAI] = {0,};
c_uint8_t num_of_tac = 0;
if (yaml_iter_type(&gtpc_array) == YAML_MAPPING_NODE)
{
@@ -1356,6 +1368,36 @@ status_t mme_context_parse_config()
const char *v = yaml_iter_value(&gtpc_iter);
if (v) port = atoi(v);
}
else if (!strcmp(gtpc_key, "tac"))
{
yaml_iter_t tac_iter;
yaml_iter_recurse(&gtpc_iter, &tac_iter);
d_assert(yaml_iter_type(&tac_iter) !=
YAML_MAPPING_NODE, return CORE_ERROR,);
do
{
const char *v = NULL;
d_assert(num_of_tac <=
MAX_NUM_OF_TAI, return CORE_ERROR,);
if (yaml_iter_type(&tac_iter) ==
YAML_SEQUENCE_NODE)
{
if (!yaml_iter_next(&tac_iter))
break;
}
v = yaml_iter_value(&tac_iter);
if (v)
{
tac[num_of_tac] = atoi(v);
num_of_tac++;
}
} while(
yaml_iter_type(&tac_iter) ==
YAML_SEQUENCE_NODE);
}
else
d_warn("unknown key `%s`", gtpc_key);
}
@@ -1368,16 +1410,33 @@ status_t mme_context_parse_config()
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
rv = gtp_add_node(&self.sgw_list, &sgw, list,
sgw = mme_sgw_add(list,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
context_self()->parameter.prefer_ipv4);
d_assert(rv == CORE_OK, return CORE_ERROR,);
d_assert(sgw, return CORE_ERROR,);
sgw->num_of_tac = num_of_tac;
if (num_of_tac != 0)
memcpy(sgw->tac, tac, sizeof(sgw->tac));
core_freeaddrinfo(list);
} while(yaml_iter_type(&gtpc_array) == YAML_SEQUENCE_NODE);
}
else if(!strcmp(mme_key, "selection_mode"))
{
const char *selection_mode =
yaml_iter_value(&mme_iter);
if (!strcmp(selection_mode, "rr"))
self.sgw_selection = SGW_SELECT_RR;
else if (!strcmp(selection_mode, "tac"))
self.sgw_selection = SGW_SELECT_TAC;
else
d_warn("unknown sgw_selection mode `%s`",
selection_mode);
}
}
}
else if (!strcmp(root_key, "pgw"))
@@ -1394,7 +1453,7 @@ status_t mme_context_parse_config()
yaml_iter_recurse(&mme_iter, &gtpc_array);
do
{
gtp_node_t *pgw = NULL;
mme_pgw_t *pgw = NULL;
c_sockaddr_t *list = NULL;
int family = AF_UNSPEC;
int i, num = 0;
@@ -1482,11 +1541,11 @@ status_t mme_context_parse_config()
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
rv = gtp_add_node(&self.pgw_list, &pgw, list,
pgw = mme_pgw_add(list,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
context_self()->parameter.prefer_ipv4);
d_assert(rv == CORE_OK, return CORE_ERROR,);
d_assert(pgw, return CORE_ERROR,);
core_freeaddrinfo(list);
@@ -1595,6 +1654,123 @@ status_t mme_context_setup_trace_module()
return CORE_OK;
}
mme_sgw_t *mme_sgw_add(
c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4)
{
status_t rv;
mme_sgw_t *sgw = NULL;
d_assert(all_list, return NULL, "Null param");
pool_alloc_node(&mme_sgw_pool, &sgw);
d_assert(sgw, return NULL, "Null param");
memset(sgw, 0, sizeof *sgw);
rv = gtp_create_node(&sgw->gnode, all_list, no_ipv4, no_ipv6, prefer_ipv4);
d_assert(rv == CORE_OK, return NULL,);
if (sgw->gnode == NULL)
{
d_error("Invalid Parameter : "
"no_ipv4[%d], no_ipv6[%d], prefer_ipv4[%d]",
no_ipv4, no_ipv6, prefer_ipv4);
return NULL;
}
list_append(&self.sgw_list, sgw);
return sgw;
}
status_t mme_sgw_remove(mme_sgw_t *sgw)
{
status_t rv;
d_assert(sgw, return CORE_ERROR, "Null param");
list_remove(&self.sgw_list, sgw);
rv = gtp_delete_node(sgw->gnode);
d_assert(rv == CORE_OK, return CORE_ERROR,);
pool_free_node(&mme_sgw_pool, sgw);
return CORE_OK;
}
status_t mme_sgw_remove_all()
{
mme_sgw_t *sgw = NULL, *next_sgw = NULL;
sgw = list_first(&self.sgw_list);
while (sgw)
{
next_sgw = list_next(sgw);
mme_sgw_remove(sgw);
sgw = next_sgw;
}
return CORE_OK;
}
mme_pgw_t *mme_pgw_add(
c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4)
{
status_t rv;
mme_pgw_t *pgw = NULL;
d_assert(all_list, return NULL, "Null param");
pool_alloc_node(&mme_pgw_pool, &pgw);
d_assert(pgw, return NULL, "Null param");
rv = gtp_create_node(&pgw->gnode, all_list, no_ipv4, no_ipv6, prefer_ipv4);
d_assert(rv == CORE_OK, return NULL,);
if (pgw->gnode == NULL)
{
d_error("Invalid Parameter : "
"no_ipv4[%d], no_ipv6[%d], prefer_ipv4[%d]",
no_ipv4, no_ipv6, prefer_ipv4);
return NULL;
}
list_append(&self.pgw_list, pgw);
return pgw;
}
status_t mme_pgw_remove(mme_pgw_t *pgw)
{
status_t rv;
d_assert(pgw, return CORE_ERROR, "Null param");
list_remove(&self.pgw_list, pgw);
rv = gtp_delete_node(pgw->gnode);
d_assert(rv == CORE_OK, return CORE_ERROR,);
pool_free_node(&mme_pgw_pool, pgw);
return CORE_OK;
}
status_t mme_pgw_remove_all()
{
mme_pgw_t *pgw = NULL, *next_pgw = NULL;
pgw = list_first(&self.pgw_list);
while (pgw)
{
next_pgw = list_next(pgw);
mme_pgw_remove(pgw);
pgw = next_pgw;
}
return CORE_OK;
}
mme_enb_t* mme_enb_add(sock_id sock, c_sockaddr_t *addr)
{
mme_enb_t *enb = NULL;
@@ -1637,8 +1813,7 @@ status_t mme_enb_remove(mme_enb_t *enb)
hash_set(self.enb_sock_hash, &enb->sock, sizeof(enb->sock), NULL);
hash_set(self.enb_addr_hash, enb->addr, sizeof(c_sockaddr_t), NULL);
if (enb->enb_id)
hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL);
hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL);
enb_ue_remove_in_enb(enb);
@@ -1692,14 +1867,12 @@ mme_enb_t* mme_enb_find_by_addr(c_sockaddr_t *addr)
mme_enb_t* mme_enb_find_by_enb_id(c_uint32_t enb_id)
{
d_assert(enb_id, return NULL,"Invalid param");
return (mme_enb_t *)hash_get(self.enb_id_hash, &enb_id, sizeof(enb_id));
}
status_t mme_enb_set_enb_id(mme_enb_t *enb, c_uint32_t enb_id)
{
d_assert(enb, return CORE_ERROR, "Invalid param");
d_assert(enb_id, return CORE_ERROR, "Invalid param");
enb->enb_id = enb_id;
hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), enb);
@@ -1946,13 +2119,39 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
/* Create New GUTI */
mme_ue_new_guti(mme_ue);
/* Setup SGW with round-robin manner */
if (mme_self()->sgw == NULL)
if (mme_self()->sgw_selection == SGW_SELECT_RR)
{
/* Setup SGW with round-robin manner */
if (mme_self()->sgw == NULL)
mme_self()->sgw = list_first(&mme_self()->sgw_list);
d_assert(mme_self()->sgw, return NULL,);
SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode);
mme_self()->sgw = list_next(mme_self()->sgw);
}
else if (mme_self()->sgw_selection == SGW_SELECT_TAC)
{
/* Select SGW by eNB TAC */
int i, found = 0;
mme_self()->sgw = list_first(&mme_self()->sgw_list);
while(mme_self()->sgw && !found)
{
for (i = 0; i < mme_self()->sgw->num_of_tac && !found; i++)
found = mme_self()->sgw->tac[i] == enb_ue->nas.tai.tac ? 1: 0;
SETUP_GTP_NODE(mme_ue, mme_self()->sgw);
if (!found)
mme_self()->sgw = list_next(mme_self()->sgw);
}
mme_self()->sgw = list_next(mme_self()->sgw);
d_assert(mme_self()->sgw, return NULL,);
SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode);
}
else
d_assert(0, return NULL, "Invalid Selection Mode: %d",
mme_self()->sgw_selection);
/* Create paging retry timer */
mme_ue->t3413 = timer_create(&self.tm_service, MME_EVT_EMM_T3413,

View File

@@ -34,6 +34,9 @@ extern "C" {
#define MAX_NUM_OF_BPLMN 6
typedef struct _mme_sgw_t mme_sgw_t;
typedef struct _mme_pgw_t mme_pgw_t;
typedef struct _enb_ue_t enb_ue_t;
typedef struct _mme_ue_t mme_ue_t;
@@ -44,6 +47,11 @@ typedef struct _fd_config_t fd_config_t;
typedef c_uint32_t mme_m_tmsi_t;
typedef enum {
SGW_SELECT_RR = 0, /* Default SGW Selection Method */
SGW_SELECT_TAC,
} sgw_select_e;
typedef struct _served_gummei {
c_uint32_t num_of_plmn_id;
plmn_id_t plmn_id[MAX_PLMN_ID];
@@ -72,7 +80,7 @@ typedef struct _mme_context_t {
c_sockaddr_t *gtpc_addr6; /* MME GTPC IPv6 Address */
list_t sgw_list; /* SGW GTPC Client List */
gtp_node_t *sgw; /* Iterator for SGW round-robin */
mme_sgw_t *sgw; /* Iterator for SGW round-robin */
list_t pgw_list; /* PGW GTPC Client List */
c_sockaddr_t *pgw_addr; /* First IPv4 Address Selected */
@@ -137,9 +145,27 @@ typedef struct _mme_context_t {
/* Network Name */
nas_network_name_t short_name; /* Network short name */
nas_network_name_t full_name; /* Network Full Name */
/* SGW Selection */
sgw_select_e sgw_selection;
} mme_context_t;
typedef struct _mme_sgw_t {
lnode_t node;
c_uint16_t tac[MAX_NUM_OF_TAI];
c_uint8_t num_of_tac;
gtp_node_t *gnode;
} mme_sgw_t;
typedef struct _mme_pgw_t {
lnode_t node;
gtp_node_t *gnode;
} mme_pgw_t;
typedef struct _mme_enb_t {
index_t index; /* An index of this node */
fsm_t sm; /* A state machine */
@@ -509,6 +535,16 @@ CORE_DECLARE(mme_context_t*) mme_self(void);
CORE_DECLARE(status_t) mme_context_parse_config(void);
CORE_DECLARE(status_t) mme_context_setup_trace_module(void);
CORE_DECLARE(mme_sgw_t*) mme_sgw_add(
c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4);
CORE_DECLARE(status_t ) mme_sgw_remove(mme_sgw_t *sgw);
CORE_DECLARE(status_t ) mme_sgw_remove_all();
CORE_DECLARE(mme_pgw_t*) mme_pgw_add(
c_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4);
CORE_DECLARE(status_t ) mme_pgw_remove(mme_pgw_t *pgw);
CORE_DECLARE(status_t ) mme_pgw_remove_all();
CORE_DECLARE(mme_enb_t*) mme_enb_add(sock_id sock, c_sockaddr_t *addr);
CORE_DECLARE(status_t) mme_enb_remove(mme_enb_t *enb);
CORE_DECLARE(status_t) mme_enb_remove_all(void);

View File

@@ -43,14 +43,15 @@ static int _gtpv2_c_recv_cb(sock_id sock, void *data)
return 0;
}
static c_sockaddr_t *gtp_addr_find_by_family(list_t *list, int family)
static c_sockaddr_t *pgw_addr_find_by_family(list_t *list, int family)
{
gtp_node_t *gnode = NULL;
mme_pgw_t *pgw = NULL;
d_assert(list, return NULL,);
for (gnode = list_first(list); gnode; gnode = list_next(gnode))
for (pgw = list_first(list); pgw; pgw = list_next(pgw))
{
c_sockaddr_t *addr = gnode->sa_list;
d_assert(pgw->gnode, return NULL,);
c_sockaddr_t *addr = pgw->gnode->sa_list;
while(addr)
{
if (addr->c_sa_family == family)
@@ -67,7 +68,7 @@ static c_sockaddr_t *gtp_addr_find_by_family(list_t *list, int family)
status_t mme_gtp_open()
{
status_t rv;
gtp_node_t *gnode = NULL;
mme_sgw_t *sgw = NULL;
rv = gtp_server_list(&mme_self()->gtpc_list, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
@@ -82,17 +83,16 @@ status_t mme_gtp_open()
d_assert(mme_self()->gtpc_addr || mme_self()->gtpc_addr6,
return CORE_ERROR, "No GTP Server");
mme_self()->pgw_addr = gtp_addr_find_by_family(
mme_self()->pgw_addr = pgw_addr_find_by_family(
&mme_self()->pgw_list, AF_INET);
mme_self()->pgw_addr6 = gtp_addr_find_by_family(
mme_self()->pgw_addr6 = pgw_addr_find_by_family(
&mme_self()->pgw_list, AF_INET6);
d_assert(mme_self()->pgw_addr || mme_self()->pgw_addr6,
return CORE_ERROR,);
for (gnode = list_first(&mme_self()->sgw_list);
gnode; gnode = list_next(gnode))
for (sgw = list_first(&mme_self()->sgw_list); sgw; sgw = list_next(sgw))
{
rv = gtp_client(gnode);
rv = gtp_client(sgw->gnode);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}

View File

@@ -206,11 +206,15 @@ status_t mme_s11_build_create_session_request(
memset(&ue_timezone, 0, sizeof(ue_timezone));
time_exp_lt(&time_exp, time_now());
if (time_exp.tm_gmtoff >= 0)
ue_timezone.sign = 0;
{
ue_timezone.timezone = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
}
else
ue_timezone.sign = 1;
{
ue_timezone.timezone = GTP_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900);
ue_timezone.timezone |= 0x08;
}
/* quarters of an hour */
ue_timezone.gmtoff = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
ue_timezone.daylight_saving_time =
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
req->ue_time_zone.presence = 1;
@@ -427,11 +431,14 @@ status_t mme_s11_build_create_bearer_response(
memset(&ue_timezone, 0, sizeof(ue_timezone));
time_exp_lt(&time_exp, time_now());
if (time_exp.tm_gmtoff >= 0)
ue_timezone.sign = 0;
{
ue_timezone.timezone = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
}
else
ue_timezone.sign = 1;
/* quarters of an hour */
ue_timezone.gmtoff = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
{
ue_timezone.timezone = GTP_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900);
ue_timezone.timezone |= 0x08;
}
ue_timezone.daylight_saving_time =
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
rsp->ue_time_zone.presence = 1;
@@ -504,11 +511,14 @@ status_t mme_s11_build_update_bearer_response(
memset(&ue_timezone, 0, sizeof(ue_timezone));
time_exp_lt(&time_exp, time_now());
if (time_exp.tm_gmtoff >= 0)
ue_timezone.sign = 0;
{
ue_timezone.timezone = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
}
else
ue_timezone.sign = 1;
/* quarters of an hour */
ue_timezone.gmtoff = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
{
ue_timezone.timezone = GTP_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900);
ue_timezone.timezone |= 0x08;
}
ue_timezone.daylight_saving_time =
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
rsp->ue_time_zone.presence = 1;
@@ -581,11 +591,14 @@ status_t mme_s11_build_delete_bearer_response(
memset(&ue_timezone, 0, sizeof(ue_timezone));
time_exp_lt(&time_exp, time_now());
if (time_exp.tm_gmtoff >= 0)
ue_timezone.sign = 0;
{
ue_timezone.timezone = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
}
else
ue_timezone.sign = 1;
/* quarters of an hour */
ue_timezone.gmtoff = GTP_TIME_TO_BCD(time_exp.tm_gmtoff / 900);
{
ue_timezone.timezone = GTP_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900);
ue_timezone.timezone |= 0x08;
}
ue_timezone.daylight_saving_time =
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
rsp->ue_time_zone.presence = 1;

View File

@@ -1709,6 +1709,8 @@ status_t s1ap_build_handover_request(
subscription_data = &mme_ue->subscription_data;
d_assert(subscription_data, return CORE_ERROR, "Null param");
d_trace(3, "[MME] Handover request\n");
memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t));
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage =
@@ -2287,7 +2289,7 @@ status_t s1ap_build_s1_reset_ack(
S1AP_ResetAcknowledgeIEs_t *ie = NULL;
d_trace(3, "[MME] ResetAcknowledge\n");
d_trace(3, "[MME] Reset acknowledge\n");
memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t));
pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome;
@@ -2384,3 +2386,226 @@ status_t s1ap_build_s1_reset_ack(
return CORE_OK;
}
status_t s1ap_build_write_replace_warning_request(
pkbuf_t **s1apbuf, sbc_pws_data_t *sbc_pws)
{
status_t rv;
S1AP_S1AP_PDU_t pdu;
S1AP_InitiatingMessage_t *initiatingMessage = NULL;
S1AP_WriteReplaceWarningRequest_t *WriteReplaceWarningRequest = NULL;
S1AP_WriteReplaceWarningRequestIEs_t *ie = NULL;
S1AP_MessageIdentifier_t *MessageIdentifier = NULL;
S1AP_SerialNumber_t *SerialNumber = NULL;
S1AP_RepetitionPeriod_t *RepetitionPeriod = NULL;
S1AP_NumberofBroadcastRequest_t *NumberofBroadcastRequest = NULL;
S1AP_DataCodingScheme_t *DataCodingScheme = NULL;
S1AP_WarningMessageContents_t *WarningMessageContents = NULL;
d_trace(3, "[MME] Write-replace warning request\n");
d_assert(sbc_pws, return CORE_ERROR,);
memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t));
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage =
core_calloc(1, sizeof(S1AP_InitiatingMessage_t));
initiatingMessage = pdu.choice.initiatingMessage;
initiatingMessage->procedureCode = S1AP_ProcedureCode_id_WriteReplaceWarning;
initiatingMessage->criticality = S1AP_Criticality_reject;
initiatingMessage->value.present =
S1AP_InitiatingMessage__value_PR_WriteReplaceWarningRequest;
WriteReplaceWarningRequest = &initiatingMessage->value.choice.WriteReplaceWarningRequest;
ie = core_calloc(1, sizeof(S1AP_WriteReplaceWarningRequestIEs_t));
ASN_SEQUENCE_ADD(&WriteReplaceWarningRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_MessageIdentifier;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_WriteReplaceWarningRequestIEs__value_PR_MessageIdentifier;
MessageIdentifier = &ie->value.choice.MessageIdentifier;
MessageIdentifier->size = (16 / 8);
MessageIdentifier->buf =
core_calloc(MessageIdentifier->size, sizeof(c_uint8_t));
MessageIdentifier->bits_unused = 0;
MessageIdentifier->buf[0] = (sbc_pws->message_id >> 8) & 0xFF;
MessageIdentifier->buf[1] = sbc_pws->message_id & 0xFF;
ie = core_calloc(1, sizeof(S1AP_WriteReplaceWarningRequestIEs_t));
ASN_SEQUENCE_ADD(&WriteReplaceWarningRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_SerialNumber;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_WriteReplaceWarningRequestIEs__value_PR_SerialNumber;
SerialNumber = &ie->value.choice.SerialNumber;
SerialNumber->size = (16 / 8);
SerialNumber->buf =
core_calloc(SerialNumber->size, sizeof(c_uint8_t));
SerialNumber->bits_unused = 0;
SerialNumber->buf[0] = (sbc_pws->serial_number >> 8) & 0xFF;
SerialNumber->buf[1] = sbc_pws->serial_number & 0xFF;
/* TODO: optional Warning Area List */
ie = core_calloc(1, sizeof(S1AP_WriteReplaceWarningRequestIEs_t));
ASN_SEQUENCE_ADD(&WriteReplaceWarningRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_RepetitionPeriod;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_WriteReplaceWarningRequestIEs__value_PR_RepetitionPeriod;
RepetitionPeriod = &ie->value.choice.RepetitionPeriod;
*RepetitionPeriod = sbc_pws->repetition_period;
/* TODO: optional Extended Repetition Period */
ie = core_calloc(1, sizeof(S1AP_WriteReplaceWarningRequestIEs_t));
ASN_SEQUENCE_ADD(&WriteReplaceWarningRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_NumberofBroadcastRequest;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_WriteReplaceWarningRequestIEs__value_PR_NumberofBroadcastRequest;
NumberofBroadcastRequest = &ie->value.choice.NumberofBroadcastRequest;
*NumberofBroadcastRequest = sbc_pws->number_of_broadcast;
/* TODO: optional Warnging Type */
/* TODO: optional Warning Security Information */
ie = core_calloc(1, sizeof(S1AP_WriteReplaceWarningRequestIEs_t));
ASN_SEQUENCE_ADD(&WriteReplaceWarningRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_DataCodingScheme;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_WriteReplaceWarningRequestIEs__value_PR_DataCodingScheme;
DataCodingScheme = &ie->value.choice.DataCodingScheme;
DataCodingScheme->size = (8 / 8);
DataCodingScheme->buf =
core_calloc(DataCodingScheme->size, sizeof(c_uint8_t));
DataCodingScheme->bits_unused = 0;
DataCodingScheme->buf[0] = sbc_pws->data_coding_scheme & 0xFF;
ie = core_calloc(1, sizeof(S1AP_WriteReplaceWarningRequestIEs_t));
ASN_SEQUENCE_ADD(&WriteReplaceWarningRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_WarningMessageContents;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_WriteReplaceWarningRequestIEs__value_PR_WarningMessageContents;
WarningMessageContents = &ie->value.choice.WarningMessageContents;
WarningMessageContents->size = sbc_pws->message_length;;
WarningMessageContents->buf =
core_calloc(WarningMessageContents->size, sizeof(c_uint8_t));
memcpy(WarningMessageContents->buf, sbc_pws->message_contents, WarningMessageContents->size);
/* TODO: optional Concurrent Warning Message Indicator */
d_trace(5, " Message[%02x,%02x] Serial[%02x,%02x] Repetition[%d] NumBroadcast[%d]\n",
MessageIdentifier->buf[0], MessageIdentifier->buf[1], SerialNumber->buf[0],
SerialNumber->buf[1], *RepetitionPeriod, *NumberofBroadcastRequest);
rv = s1ap_encode_pdu(s1apbuf, &pdu);
s1ap_free_pdu(&pdu);
if (rv != CORE_OK)
{
d_error("s1ap_encode_pdu() failed");
return CORE_ERROR;
}
return CORE_OK;
}
status_t s1ap_build_kill_request(
pkbuf_t **s1apbuf, sbc_pws_data_t *sbc_pws)
{
status_t rv;
S1AP_S1AP_PDU_t pdu;
S1AP_InitiatingMessage_t *initiatingMessage = NULL;
S1AP_KillRequest_t *KillRequest = NULL;
S1AP_KillRequestIEs_t *ie = NULL;
S1AP_MessageIdentifier_t *MessageIdentifier = NULL;
S1AP_SerialNumber_t *SerialNumber = NULL;
d_trace(3, "[MME] Kill request\n");
d_assert(sbc_pws, return CORE_ERROR,);
memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t));
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage =
core_calloc(1, sizeof(S1AP_InitiatingMessage_t));
initiatingMessage = pdu.choice.initiatingMessage;
initiatingMessage->procedureCode = S1AP_ProcedureCode_id_Kill;
initiatingMessage->criticality = S1AP_Criticality_reject;
initiatingMessage->value.present =
S1AP_InitiatingMessage__value_PR_KillRequest;
KillRequest = &initiatingMessage->value.choice.KillRequest;
ie = core_calloc(1, sizeof(S1AP_KillRequestIEs_t));
ASN_SEQUENCE_ADD(&KillRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_MessageIdentifier;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_KillRequestIEs__value_PR_MessageIdentifier;
MessageIdentifier = &ie->value.choice.MessageIdentifier;
MessageIdentifier->size = (16 / 8);
MessageIdentifier->buf =
core_calloc(MessageIdentifier->size, sizeof(c_uint8_t));
MessageIdentifier->bits_unused = 0;
MessageIdentifier->buf[0] = (sbc_pws->message_id >> 8) & 0xFF;
MessageIdentifier->buf[1] = sbc_pws->message_id & 0xFF;
ie = core_calloc(1, sizeof(S1AP_KillRequestIEs_t));
ASN_SEQUENCE_ADD(&KillRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_SerialNumber;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_KillRequestIEs__value_PR_SerialNumber;
SerialNumber = &ie->value.choice.SerialNumber;
SerialNumber->size = (16 / 8);
SerialNumber->buf =
core_calloc(SerialNumber->size, sizeof(c_uint8_t));
SerialNumber->bits_unused = 0;
SerialNumber->buf[0] = (sbc_pws->serial_number >> 8) & 0xFF;
SerialNumber->buf[1] = sbc_pws->serial_number & 0xFF;
/* TODO: optional Warning Area List */
d_trace(5, " Message[%02x,%02x] Serial[%02x,%02x]\n",
MessageIdentifier->buf[0], MessageIdentifier->buf[1],
SerialNumber->buf[0], SerialNumber->buf[1]);
rv = s1ap_encode_pdu(s1apbuf, &pdu);
s1ap_free_pdu(&pdu);
if (rv != CORE_OK)
{
d_error("s1ap_encode_pdu() failed");
return CORE_ERROR;
}
return CORE_OK;
}

View File

@@ -4,6 +4,8 @@
#include "s1ap/s1ap_message.h"
#include "mme_context.h"
#include "sbc_message.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -78,6 +80,12 @@ CORE_DECLARE(status_t) s1ap_build_s1_reset_ack(
pkbuf_t **s1apbuf,
S1AP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface);
CORE_DECLARE(status_t) s1ap_build_write_replace_warning_request(
pkbuf_t **s1apbuf, sbc_pws_data_t *sbc_pws);
CORE_DECLARE(status_t) s1ap_build_kill_request(
pkbuf_t **s1apbuf, sbc_pws_data_t *sbc_pws);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -833,6 +833,7 @@ void s1ap_handle_ue_context_release_request(
break;
case S1AP_Cause_PR_nas:
d_warn("NAS-Cause[%d]", Cause->choice.nas);
break;
default:
d_warn("Invalid cause group[%d]", Cause->present);
break;
@@ -2106,3 +2107,52 @@ void s1ap_handle_s1_reset(
d_assert(rv == CORE_OK,,);
}
void s1ap_handle_write_replace_warning_response(
mme_enb_t *enb, s1ap_message_t *message)
{
char buf[CORE_ADDRSTRLEN];
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
S1AP_WriteReplaceWarningResponse_t *WriteReplaceWarningResponse = NULL;
d_assert(enb, return,);
d_assert(enb->sock, return,);
d_assert(message, return,);
successfulOutcome = message->choice.successfulOutcome;
d_assert(successfulOutcome, return,);
WriteReplaceWarningResponse =
&successfulOutcome->value.choice.WriteReplaceWarningResponse;
d_assert(WriteReplaceWarningResponse, return,);
d_trace(3, "[MME] Write replace warning response\n");
d_trace(5, " IP[%s] ENB_ID[%d]\n",
CORE_ADDR(enb->addr, buf), enb->enb_id);
}
void s1ap_handle_kill_response(
mme_enb_t *enb, s1ap_message_t *message)
{
char buf[CORE_ADDRSTRLEN];
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
S1AP_KillResponse_t *KillResponse = NULL;
d_assert(enb, return,);
d_assert(enb->sock, return,);
d_assert(message, return,);
successfulOutcome = message->choice.successfulOutcome;
d_assert(successfulOutcome, return,);
KillResponse =
&successfulOutcome->value.choice.KillResponse;
d_assert(KillResponse, return,);
d_trace(3, "[MME] Kill response\n");
d_trace(5, " IP[%s] ENB_ID[%d]\n",
CORE_ADDR(enb->addr, buf), enb->enb_id);
}

View File

@@ -52,6 +52,11 @@ CORE_DECLARE(void) s1ap_handle_handover_notification(
CORE_DECLARE(void) s1ap_handle_s1_reset(
mme_enb_t *enb, s1ap_message_t *message);
CORE_DECLARE(void) s1ap_handle_write_replace_warning_response(
mme_enb_t *enb, s1ap_message_t *message);
CORE_DECLARE(void) s1ap_handle_kill_response(
mme_enb_t *enb, s1ap_message_t *message);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -179,6 +179,16 @@ void s1ap_state_operational(fsm_t *s, event_t *e)
s1ap_handle_handover_request_ack(enb, pdu);
break;
}
case S1AP_ProcedureCode_id_WriteReplaceWarning:
{
s1ap_handle_write_replace_warning_response(enb, pdu);
break;
}
case S1AP_ProcedureCode_id_Kill:
{
s1ap_handle_kill_response(enb, pdu);
break;
}
default:
{
d_warn("Not implemented(choice:%d, proc:%d)",

104
src/mme/sbc_handler.c Normal file
View File

@@ -0,0 +1,104 @@
#define TRACE_MODULE _sbc_handler
#include "core_debug.h"
#include "mme_context.h"
#include "s1ap_path.h"
#include "s1ap_build.h"
#include "sbc_handler.h"
void sbc_handle_write_replace_warning_request(sbc_pws_data_t *sbc_pws)
{
pkbuf_t *s1apbuf = NULL;
hash_index_t *hi = NULL;
mme_enb_t *enb = NULL;
int i, j, flag;
status_t rv;
/* Find enB with matched TAI */
for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi))
{
flag = 0;
enb = mme_enb_this(hi);
if (sbc_pws->no_of_tai > 0)
{
for (i = 0, flag = 0; i < enb->num_of_supported_ta_list; i++)
{
for (j = 0; j < sbc_pws->no_of_tai; j++)
{
if (!memcmp(&enb->supported_ta_list[i],
&sbc_pws->tai[j], sizeof(tai_t)))
flag = 1;
if (flag) break;
}
if (flag) break;
}
}
else
flag = 1;
if (flag)
{
s1apbuf = NULL;
/* Buidl S1AP Write Replace Warning Request message */
rv = s1ap_build_write_replace_warning_request(&s1apbuf, sbc_pws);
d_assert(rv == CORE_OK && s1apbuf, return,
"s1ap build error");
/* Send to enb */
d_assert(s1ap_send_to_enb(
enb, s1apbuf, S1AP_NON_UE_SIGNALLING) == CORE_OK,
return, "s1ap send error");
}
}
}
void sbc_handle_stop_warning_request(sbc_pws_data_t *sbc_pws)
{
pkbuf_t *s1apbuf = NULL;
hash_index_t *hi = NULL;
mme_enb_t *enb = NULL;
int i, j, flag;
status_t rv;
/* Find enB with matched TAI */
for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi))
{
flag = 0;
enb = mme_enb_this(hi);
if (sbc_pws->no_of_tai > 0)
{
for (i = 0, flag = 0; i < enb->num_of_supported_ta_list; i++)
{
for (j = 0; j < sbc_pws->no_of_tai; j++)
{
if (!memcmp(&enb->supported_ta_list[i],
&sbc_pws->tai[j], sizeof(tai_t)))
flag = 1;
if (flag) break;
}
if (flag) break;
}
}
else
flag = 1;
if (flag)
{
s1apbuf = NULL;
/* Buidl S1AP Kill request message */
rv = s1ap_build_kill_request(&s1apbuf, sbc_pws);
d_assert(rv == CORE_OK && s1apbuf, return,
"s1ap build error");
/* Send to enb */
d_assert(s1ap_send_to_enb(
enb, s1apbuf, S1AP_NON_UE_SIGNALLING) == CORE_OK,
return, "s1ap send error");
}
}
}

19
src/mme/sbc_handler.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef __SBC_HANDLER_H__
#define __SBC_HANDLER_H__
#include "sbc_message.h"
/* SBc-AP handles */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
CORE_DECLARE(void) sbc_handle_write_replace_warning_request(sbc_pws_data_t *sbc_pws);
CORE_DECLARE(void) sbc_handle_stop_warning_request(sbc_pws_data_t *sbc_pws);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __SBC_HANDLER_H__ */

34
src/mme/sbc_message.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef __SBC_MESSAGE_H__
#define __SBC_MESSAGE_H__
#include "3gpp_types.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* SBc-AP messages:
* After the CBC integration, the encoding/decoding of
* SBc-AP messages will be fully supported.
*/
/* SBc-AP interface data definitions */
/* SBc-AP WriteReplaceWarning data */
typedef struct _sbc_pws_data_t {
c_uint16_t message_id;
c_uint16_t serial_number;
c_uint32_t no_of_tai;
tai_t tai[16]; /* TODO: max 65535 */
c_uint32_t repetition_period;
c_uint32_t number_of_broadcast;
c_uint8_t data_coding_scheme;
c_uint32_t message_length;
c_uint8_t message_contents[1024]; /* TODO: max 9600 */
} sbc_pws_data_t;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __SBC_MESSAGE_H__ */

View File

@@ -1082,7 +1082,7 @@ gtp_node_t *pgw_sgw_add_by_message(gtp_message_t *message)
sgw = gtp_find_node(&pgw_self()->sgw_s5c_list, sgw_s5c_teid);
if (!sgw)
{
sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5c_list, sgw_s5c_teid,
sgw = gtp_add_node(&pgw_self()->sgw_s5c_list, sgw_s5c_teid,
pgw_self()->gtpc_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,

View File

@@ -86,7 +86,7 @@ void pgw_s5c_handle_create_session_request(
sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid);
if (!sgw)
{
sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5u_list, sgw_s5u_teid,
sgw = gtp_add_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid,
pgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
@@ -190,7 +190,7 @@ void pgw_s5c_handle_create_bearer_response(
sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid);
if (!sgw)
{
sgw = gtp_add_node_with_teid(&pgw_self()->sgw_s5u_list, sgw_s5u_teid,
sgw = gtp_add_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid,
pgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,

View File

@@ -514,7 +514,7 @@ gtp_node_t *sgw_mme_add_by_message(gtp_message_t *message)
mme = gtp_find_node(&sgw_self()->mme_s11_list, mme_s11_teid);
if (!mme)
{
mme = gtp_add_node_with_teid(&sgw_self()->mme_s11_list, mme_s11_teid,
mme = gtp_add_node(&sgw_self()->mme_s11_list, mme_s11_teid,
sgw_self()->gtpc_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,

View File

@@ -38,7 +38,7 @@ void sgw_s11_handle_create_session_request(
req = &gtp_message->create_session_request;
d_trace(3, "[SGW] Create Session Reqeust\n");
d_trace(3, "[SGW] Create Session Request\n");
if (req->bearer_contexts_to_be_created.presence == 0)
{
d_error("No Bearer");
@@ -120,7 +120,7 @@ void sgw_s11_handle_create_session_request(
pgw = gtp_find_node(&sgw_self()->pgw_s5c_list, pgw_s5c_teid);
if (!pgw)
{
pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5c_list, pgw_s5c_teid,
pgw = gtp_add_node(&sgw_self()->pgw_s5c_list, pgw_s5c_teid,
sgw_self()->gtpc_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
@@ -227,7 +227,7 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact,
enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid);
if (!enb)
{
enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, enb_s1u_teid,
enb = gtp_add_node(&sgw_self()->enb_s1u_list, enb_s1u_teid,
sgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
@@ -460,7 +460,7 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid);
if (!enb)
{
enb = gtp_add_node_with_teid(&sgw_self()->enb_s1u_list, enb_s1u_teid,
enb = gtp_add_node(&sgw_self()->enb_s1u_list, enb_s1u_teid,
sgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
@@ -830,8 +830,7 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid);
if (!enb)
{
enb = gtp_add_node_with_teid(
&sgw_self()->enb_s1u_list, req_teid,
enb = gtp_add_node(&sgw_self()->enb_s1u_list, req_teid,
sgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
@@ -871,8 +870,7 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid);
if (!enb)
{
enb = gtp_add_node_with_teid(
&sgw_self()->enb_s1u_list, req_teid,
enb = gtp_add_node(&sgw_self()->enb_s1u_list, req_teid,
sgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,

View File

@@ -98,7 +98,7 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid);
if (!pgw)
{
pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5u_list, pgw_s5u_teid,
pgw = gtp_add_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid,
sgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,
@@ -286,7 +286,7 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid);
if (!pgw)
{
pgw = gtp_add_node_with_teid(&sgw_self()->pgw_s5u_list, pgw_s5u_teid,
pgw = gtp_add_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid,
sgw_self()->gtpu_port,
context_self()->parameter.no_ipv4,
context_self()->parameter.no_ipv6,

View File

@@ -203,7 +203,29 @@ sgw:
addr: 127.0.0.2
#
# <GTP-U Server>>
# <SGW Selection Mode>
#
# o Round-Robin
# (If `selection_mode` is omitted, the default mode is Round-Robin)
#
# selection_mode: rr
# gtpc:
# addr: 127.0.0.2
# addr: 127.0.2.2
# addr: 127.0.4.2
#
# o SGW selection by eNodeB TAC
#
# selection_mode: tac
# gtpc:
# - addr: 127.0.0.2
# tac: 26000
# - addr: 127.0.2.2
# tac: [25000, 27000, 28000]
#
#
# <GTP-U Server>
#
# o GTP-U Server(all address avaiable)
# gtpu:

View File

@@ -56,7 +56,8 @@ services:
- base
environment:
- DB_URI=mongodb://mongodb/nextepc
- DISPLAY=docker.for.mac.localhost:0
- DISPLAY=$DISPLAY
# - DISPLAY=docker.for.mac.localhost:0
cap_add:
- NET_ADMIN
devices:
@@ -67,6 +68,8 @@ services:
- home:/home/${USER}
- ${HOME}:/mnt
- /tmp/.X11-unix:/tmp/.X11-unix
# - /etc/localtime:/etc/localtime:ro
# - /usr/share/zoneinfo/Europe/Helsinki:/etc/localtime:ro
hostname: nextepc-dev
user: ${USER}
entrypoint: /bin/bash -c "/bin/bash -c \"$${@}\""

View File

@@ -155,7 +155,7 @@ static void gtp_message_test1(abts_case *tc, void *data)
&bearer_qos, bearer_qos_buf, GTP_BEARER_QOS_LEN);
memset(&ue_timezone, 0, sizeof(ue_timezone));
ue_timezone.gmtoff = 0x40;
ue_timezone.timezone = 0x40;
ue_timezone.daylight_saving_time =
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
req.ue_time_zone.presence = 1;

View File

@@ -57,6 +57,7 @@ static void nas_message_test2(abts_case *tc, void *data)
nas_attach_accept_t *attach_accept = &message.emm.attach_accept;
tai0_list_t tai0_list;
tai2_list_t tai2_list;
plmn_id_t plmn_id;
pkbuf_t *pkbuf = NULL;
status_t rv;
@@ -85,15 +86,16 @@ static void nas_message_test2(abts_case *tc, void *data)
attach_accept->presencemask |= NAS_ATTACH_ACCEPT_GUTI_PRESENT;
attach_accept->guti.length = 11;
attach_accept->guti.guti.type = NAS_EPS_MOBILE_IDENTITY_GUTI;
plmn_id_build(&attach_accept->guti.guti.plmn_id, 417, 99, 2);
nas_from_plmn_id(&attach_accept->guti.guti.plmn_id,
plmn_id_build(&plmn_id, 417, 99, 2));
attach_accept->guti.guti.mme_gid = 9029;
attach_accept->guti.guti.mme_code = 225;
attach_accept->guti.guti.m_tmsi = 0x00000456;
attach_accept->presencemask |=
NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT;
plmn_id_build(
&attach_accept->location_area_identification.plmn_id, 1, 2, 2);
nas_from_plmn_id(&attach_accept->location_area_identification.plmn_id,
plmn_id_build(&plmn_id, 1, 2, 2));
attach_accept->location_area_identification.lac = 0xfffd;
attach_accept->presencemask |= NAS_ATTACH_ACCEPT_MS_IDENTITY_PRESENT;

View File

@@ -165,6 +165,33 @@ static void s1ap_message_test6(abts_case *tc, void *data)
pkbuf_free(s1apbuf);
}
static void s1ap_message_test7(abts_case *tc, void *data)
{
/* InitialUE(Service Request) */
char *payload =
"000c402d000005000800020071001a00 0504c706b410004300060013f1890001"
"006440080013f189400bb75000864001 40006440080013f189400bb750004340"
"060013f18900014300060013f1890001 006440080013f189400db09000864001"
"30000000000000000000000000000000 00000000000000000000000000000000";
s1ap_message_t message;
pkbuf_t *pkbuf;
int result;
char hexbuf[MAX_SDU_LEN];
pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
ABTS_PTR_NOTNULL(tc, pkbuf);
pkbuf->len = 8192;
memcpy(pkbuf->payload,
CORE_HEX(payload, strlen(payload), hexbuf), 128);
result = s1ap_decode_pdu(&message, pkbuf);
ABTS_INT_EQUAL(tc, 0, result);
s1ap_free_pdu(&message);
pkbuf_free(pkbuf);
}
abts_suite *test_s1ap_message(abts_suite *suite)
{
suite = ADD_SUITE(suite)
@@ -175,6 +202,7 @@ abts_suite *test_s1ap_message(abts_suite *suite)
abts_run_test(suite, s1ap_message_test4, NULL);
abts_run_test(suite, s1ap_message_test5, NULL);
abts_run_test(suite, s1ap_message_test6, NULL);
abts_run_test(suite, s1ap_message_test7, NULL);
return suite;
}

View File

@@ -29,7 +29,7 @@ static void s1setup_test1(abts_case *tc, void *data)
for (i = 0; i < NUM_OF_TEST_DUPLICATED_ENB; i++)
{
rv = tests1ap_build_setup_req(
&sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x54f64);
&sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = tests1ap_enb_send(sock[i], sendbuf);
@@ -75,7 +75,7 @@ static void s1setup_test2(abts_case *tc, void *data)
for (i = 0; i < NUM_OF_TEST_ENB; i++)
{
rv = tests1ap_build_setup_req(
&sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x54f64+i);
&sendbuf, S1AP_ENB_ID_PR_macroENB_ID, i);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = tests1ap_enb_send(sock[i], sendbuf);

View File

@@ -1,6 +1,6 @@
{
"name": "nextepc",
"version": "0.3.10",
"version": "0.3.11",
"description": "NextEPC",
"main": "index.js",
"repository": "https://github.com/acetcom/nextepc",