IPv6 Control Plane done

This commit is contained in:
Sukchan Lee 2017-12-14 21:42:19 +09:00
parent a74c9be2e6
commit 46c699143a
11 changed files with 163 additions and 36 deletions

View File

@ -121,7 +121,7 @@ typedef struct _paa_t {
/* 8.34 PDN Type */
#define GTP_PDN_TYPE_IPV4 1
#define GTP_PDN_TYPE_IPV6 2
#define GTP_PDN_TYPE_BOTH 3
#define GTP_PDN_TYPE_IPV4V6 3
#define GTP_PDN_TYPE_NON_IP 4
ED2(c_uint8_t spare:5;,
c_uint8_t pdn_type:3;)
@ -138,7 +138,6 @@ ED2(c_uint8_t spare:5;,
/* GTP_PDN_TYPE_BOTH */
struct {
c_uint32_t addr;
struct {
c_uint8_t len;
c_uint8_t addr6[IPV6_LEN];
@ -217,10 +216,10 @@ typedef struct _pcc_rule_t {
typedef struct _pdn_t {
c_uint32_t context_identifier;
c_int8_t apn[MAX_APN_LEN+1];
#define S6A_PDN_TYPE_IPV4 0
#define S6A_PDN_TYPE_IPV6 1
#define S6A_PDN_TYPE_IPV4_AND_IPV6 2
#define S6A_PDN_TYPE_IPV4_OR_IPV6 3
#define HSS_PDN_TYPE_IPV4 0
#define HSS_PDN_TYPE_IPV6 1
#define HSS_PDN_TYPE_IPV4V6 2
#define HSS_PDN_TYPE_IPV4_OR_IPV6 3
c_int8_t pdn_type;
qos_t qos;

View File

@ -1152,10 +1152,24 @@ ED3(c_uint8_t type:4;,
/* 9.9.4.9 PDN address
* M LV 6-14 */
#define NAS_PDN_ADDRESS_IPV4_LEN 5
#define NAS_PDN_ADDRESS_IPV6_LEN 9
#define NAS_PDN_ADDRESS_IPV4V6_LEN 13
typedef struct _nas_pdn_address_t {
c_uint8_t length;
paa_t paa;
} nas_pdn_address_t;
ED2(c_uint8_t reserved:5;,
c_uint8_t pdn_type:3;)
union {
c_uint32_t addr;
struct {
c_uint8_t addr6[IPV6_LEN/2]; /* Interface Identifer Only */
};
struct {
c_uint8_t addr6[IPV6_LEN/2]; /* Interface Identifer Only */
c_uint32_t addr;
} both;
};
} __attribute__ ((packed)) nas_pdn_address_t;
/* 9.9.4.11 Protocol configuration options
* See subclause 10.5.6.3 in 3GPP TS 24.008 [13].
@ -1197,9 +1211,9 @@ ED3(c_uint8_t spare:3;, /* allowed in A/Gb mode or Iu mode */
#define NAS_PDN_CONNECTIVITY_PDN_TYPE_NON_IP 5
typedef struct _nas_request_type_t {
ED4(c_uint8_t spare1:1;,
c_uint8_t request_type:3;,
c_uint8_t pdn_type:3;,
c_uint8_t spare2:1;,
c_uint8_t pdn_type:3;)
c_uint8_t request_type:3;)
} __attribute__ ((packed)) nas_request_type_t;
/* 9.9.4.15 Traffic flow aggregate description

View File

@ -132,8 +132,27 @@ status_t esm_build_activate_default_bearer_context_request(
core_cpystrn(access_point_name->apn, pdn->apn,
c_min(access_point_name->length, MAX_APN_LEN) + 1);
pdn_address->length = PAA_IPV4_LEN;
memcpy(&pdn_address->paa, &pdn->paa, pdn_address->length);
pdn_address->pdn_type = pdn->paa.pdn_type;
if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV4)
{
pdn_address->addr = pdn->paa.addr;
pdn_address->length = NAS_PDN_ADDRESS_IPV4_LEN;
}
else if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV6)
{
memcpy(pdn_address->addr6, pdn->paa.addr6+IPV6_LEN/2, IPV6_LEN/2);
pdn_address->length = NAS_PDN_ADDRESS_IPV6_LEN;
}
else if (pdn_address->pdn_type == GTP_PDN_TYPE_IPV4V6)
{
pdn_address->both.addr = pdn->paa.both.addr;
memcpy(pdn_address->both.addr6,
pdn->paa.both.addr6+IPV6_LEN/2, IPV6_LEN/2);
pdn_address->length = NAS_PDN_ADDRESS_IPV4V6_LEN;
}
else
d_assert(0, return CORE_ERROR,
"Invalid PDN_TYPE(%d)", pdn->paa.pdn_type);
if (pdn->ambr.downlink || pdn->ambr.uplink)
{

View File

@ -18,17 +18,22 @@ status_t esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
mme_sess_t *sess = NULL;
c_uint8_t security_protected_required = 0;
d_assert(bearer, return CORE_ERROR, "Null param");
d_assert(bearer, return CORE_ERROR,);
sess = bearer->sess;
d_assert(sess, return CORE_ERROR, "Null param");
d_assert(sess, return CORE_ERROR,);
mme_ue = sess->mme_ue;
d_assert(mme_ue, return CORE_ERROR, "Null param");
d_assert(mme_ue, return CORE_ERROR,);
d_assert(pdn_connectivity_request, return CORE_ERROR,);
d_assert(MME_UE_HAVE_IMSI(mme_ue), return CORE_ERROR,
"No IMSI in PDN_CPNNECTIVITY_REQUEST");
d_assert(SECURITY_CONTEXT_IS_VALID(mme_ue), return CORE_ERROR,
"No Security Context in PDN_CPNNECTIVITY_REQUEST");
memcpy(&sess->request_type, &pdn_connectivity_request->request_type,
sizeof(sess->request_type));
security_protected_required = 0;
if (pdn_connectivity_request->presencemask &
NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT)

View File

@ -345,6 +345,9 @@ typedef struct _mme_sess_t {
c_uint8_t pti; /* Procedure Trasaction Identity */
/* PDN Connectivity Request */
nas_request_type_t request_type;
/* mme_bearer_first(sess) : Default Bearer Context */
list_t bearer_list;

View File

@ -107,13 +107,42 @@ status_t mme_s11_build_create_session_request(
req->selection_mode.u8 =
GTP_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN | 0xfc;
d_assert(sess->request_type.pdn_type ==
NAS_PDN_CONNECTIVITY_PDN_TYPE_IPV4 ||
sess->request_type.pdn_type ==
NAS_PDN_CONNECTIVITY_PDN_TYPE_IPV6 ||
sess->request_type.pdn_type ==
NAS_PDN_CONNECTIVITY_PDN_TYPE_IPV4V6, return CORE_ERROR,
"UE PDN Configuration Error(%d)", sess->request_type.pdn_type);
if (pdn->pdn_type == HSS_PDN_TYPE_IPV4 ||
pdn->pdn_type == HSS_PDN_TYPE_IPV6 ||
pdn->pdn_type == HSS_PDN_TYPE_IPV4V6)
{
req->pdn_type.u8 = ((pdn->pdn_type + 1) & sess->request_type.pdn_type);
d_assert(req->pdn_type.u8 != 0, return CORE_ERROR,
"PDN Configuration Error:(%d, %d)",
pdn->pdn_type, sess->request_type.pdn_type);
}
else if (pdn->pdn_type == HSS_PDN_TYPE_IPV4_OR_IPV6)
{
req->pdn_type.u8 = sess->request_type.pdn_type;
}
else
d_assert(0, return CORE_ERROR,
"HSS PDN Confiugration Error(%d)", pdn->pdn_type);
req->pdn_type.presence = 1;
req->pdn_type.u8 = GTP_PDN_TYPE_IPV4;
pdn->paa.pdn_type = GTP_PDN_TYPE_IPV4;
req->pdn_address_allocation.presence = 1;
pdn->paa.pdn_type = req->pdn_type.u8;
req->pdn_address_allocation.data = &pdn->paa;
req->pdn_address_allocation.len = PAA_IPV4_LEN;
if (req->pdn_type.u8 == GTP_PDN_TYPE_IPV4)
req->pdn_address_allocation.len = PAA_IPV4_LEN;
else if (req->pdn_type.u8 == GTP_PDN_TYPE_IPV6)
req->pdn_address_allocation.len = PAA_IPV6_LEN;
else if (req->pdn_type.u8 == GTP_PDN_TYPE_IPV4V6)
req->pdn_address_allocation.len = PAA_IPV4V6_LEN;
else
d_assert(0, return CORE_ERROR, "Not supported(%d)", req->pdn_type.u8);
req->pdn_address_allocation.presence = 1;
req->maximum_apn_restriction.presence = 1;
req->maximum_apn_restriction.u8 = GTP_APN_NO_RESTRICTION;

View File

@ -727,7 +727,8 @@ static void *sess_hash_keygen(c_uint8_t *out, int *out_len,
}
pgw_sess_t *pgw_sess_add(
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi)
c_uint8_t *imsi, int imsi_len, c_int8_t *apn,
c_uint8_t pdn_type, c_uint8_t ebi)
{
pgw_sess_t *sess = NULL;
pgw_bearer_t *bearer = NULL;
@ -754,9 +755,29 @@ pgw_sess_t *pgw_sess_add(
"Can't add default bearer context");
bearer->ebi = ebi;
sess->ue_ip = pgw_ue_ip_alloc(AF_INET, apn);
d_assert(sess->ue_ip, pgw_sess_remove(sess); return NULL,
"Can't add default bearer context");
if (pdn_type == GTP_PDN_TYPE_IPV4)
{
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn);
d_assert(sess->ipv4, pgw_sess_remove(sess); return NULL,
"Can't allocate IPv4 Pool");
}
else if (pdn_type == GTP_PDN_TYPE_IPV6)
{
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn);
d_assert(sess->ipv6, pgw_sess_remove(sess); return NULL,
"Can't allocate IPv6 Pool");
}
else if (pdn_type == GTP_PDN_TYPE_IPV4V6)
{
sess->ipv4 = pgw_ue_ip_alloc(AF_INET, apn);
d_assert(sess->ipv4, pgw_sess_remove(sess); return NULL,
"Can't allocate IPv4 Pool");
sess->ipv6 = pgw_ue_ip_alloc(AF_INET6, apn);
d_assert(sess->ipv6, pgw_sess_remove(sess); return NULL,
"Can't allocate IPv6 Pool");
}
else
d_assert(0, return NULL, "Unsupported PDN Type(%d)", pdn_type);
/* Generate Hash Key : IMSI + APN */
sess_hash_keygen(sess->hash_keybuf, &sess->hash_keylen,
@ -773,7 +794,10 @@ status_t pgw_sess_remove(pgw_sess_t *sess)
hash_set(self.sess_hash, sess->hash_keybuf, sess->hash_keylen, NULL);
pgw_ue_ip_free(sess->ue_ip);
if (sess->ipv4)
pgw_ue_ip_free(sess->ipv4);
if (sess->ipv6)
pgw_ue_ip_free(sess->ipv6);
pgw_bearer_remove_all(sess);
@ -874,12 +898,18 @@ pgw_sess_t *pgw_sess_add_by_message(gtp_message_t *message)
d_error("No EPS Bearer ID");
return NULL;
}
if (req->pdn_type.presence == 0)
{
d_error("No PDN Type");
return NULL;
}
apn_parse(apn, req->access_point_name.data, req->access_point_name.len);
sess = pgw_sess_find_by_imsi_apn(req->imsi.data, req->imsi.len, apn);
if (!sess)
{
sess = pgw_sess_add(req->imsi.data, req->imsi.len, apn,
req->pdn_type.u8,
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
d_assert(sess, return NULL, "No Session Context");
}

View File

@ -86,7 +86,8 @@ typedef struct _pgw_sess_t {
/* APN Configuration */
pdn_t pdn;
pgw_ue_ip_t* ue_ip;
pgw_ue_ip_t* ipv4;
pgw_ue_ip_t* ipv6;
/* User-Lication-Info */
tai_t tai;
@ -169,7 +170,8 @@ CORE_DECLARE(gtp_node_t *) pgw_sgw_add_by_message(gtp_message_t *message);
CORE_DECLARE(pgw_sess_t *) pgw_sess_add_by_message(gtp_message_t *message);
CORE_DECLARE(pgw_sess_t*) pgw_sess_add(
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi);
c_uint8_t *imsi, int imsi_len, c_int8_t *apn,
c_uint8_t pdn_type, c_uint8_t ebi);
CORE_DECLARE(status_t ) pgw_sess_remove(pgw_sess_t *sess);
CORE_DECLARE(status_t ) pgw_sess_remove_all();
CORE_DECLARE(pgw_sess_t*) pgw_sess_find(index_t index);

View File

@ -39,7 +39,7 @@ void pgw_gx_send_ccr(gtp_xact_t *xact, pgw_sess_t *sess,
struct session *session = NULL;
d_assert(sess, return, "Null param");
d_assert(sess->ue_ip, return, "Null param");
d_assert(sess->ipv4 || sess->ipv6, return, "Null param");
/* Create the random value to store with the session */
pool_alloc_node(&pgw_gx_sess_pool, &mi);
@ -138,8 +138,16 @@ void pgw_gx_send_ccr(gtp_xact_t *xact, pgw_sess_t *sess,
/* Set Framed-IP-Address */
CHECK_FCT_DO( fd_msg_avp_new(gx_framed_ip_address, 0, &avp),
goto out );
val.os.data = (c_uint8_t*)&sess->ue_ip->addr[0];
val.os.len = sizeof(sess->ue_ip->addr[0]);
if (sess->ipv6)
{
val.os.data = (c_uint8_t*)&sess->ipv6->addr;
val.os.len = 16;
}
else
{
val.os.data = (c_uint8_t*)&sess->ipv4->addr;
val.os.len = 4;
}
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );

View File

@ -59,13 +59,31 @@ status_t pgw_s5c_build_create_session_response(
len = len;
/* PDN Address Allocation */
d_assert(sess->ue_ip, return CORE_ERROR, "No IP Pool");
sess->pdn.paa.pdn_type = GTP_PDN_TYPE_IPV4;
sess->pdn.paa.addr = sess->ue_ip->addr[0];
rsp->pdn_address_allocation.presence = 1;
rsp->pdn_address_allocation.data = &sess->pdn.paa;
rsp->pdn_address_allocation.len = PAA_IPV4_LEN;
if (sess->ipv4 && sess->ipv6)
{
sess->pdn.paa.pdn_type = GTP_PDN_TYPE_IPV4V6;
sess->pdn.paa.both.addr = sess->ipv4->addr[0];
sess->pdn.paa.both.len = IPV6_LEN;
memcpy(sess->pdn.paa.both.addr6, sess->ipv6->addr, IPV6_LEN);
rsp->pdn_address_allocation.len = PAA_IPV4V6_LEN;
}
else if (sess->ipv4)
{
sess->pdn.paa.pdn_type = GTP_PDN_TYPE_IPV4;
sess->pdn.paa.addr = sess->ipv4->addr[0];
rsp->pdn_address_allocation.len = PAA_IPV4_LEN;
}
else if (sess->ipv6)
{
sess->pdn.paa.pdn_type = GTP_PDN_TYPE_IPV6;
sess->pdn.paa.len = IPV6_LEN;
memcpy(sess->pdn.paa.addr6, sess->ipv6->addr, IPV6_LEN);
rsp->pdn_address_allocation.len = PAA_IPV6_LEN;
}
else
d_assert(0, return CORE_ERROR, "No IP Pool");
rsp->pdn_address_allocation.presence = 1;
/* APN Restriction */
rsp->apn_restriction.presence = 1;

View File

@ -450,7 +450,7 @@ status_t tests1ap_build_initial_ue_msg(pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
"000c405800000500 0800020001001a00 302f177ca0b38802 0741020809101010"
"3254869104e060c0 4000050221d011d1 5c0a003103e5e034 9011035758a65d01"
"3254869104e060c0 4000050221d031d1 5c0a003103e5e034 9011035758a65d01"
"00004300060000f1 1030390064400800 00f1101079baf000 86400130",
"000c40809c00"