forked from acouzens/open5gs
IPv6 Control Plane done
This commit is contained in:
parent
a74c9be2e6
commit
46c699143a
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue