Introduce Gn interface (GTPv1C) Support to PGW (#1351)

* [CORE] tlv: Store mode in ogs_tlv_t

This allows specifying the format of the IE for each individual IE,
hence allowing messages containing IEs formatted in different ways.

This is needed in order to support parsing GTPv1-C, since messages
contain IEs with different structure (TLV vs TV). Hence, this is a
preparation patch to add support for parsing TVs in ogs-tlv.c/.h.

* [CORE] tlv: Support parsing msg with both TLV and TV in it

IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder
doesn't provide with ways to parse messages which contain TV formatted
IEs. This patch adds the relevant types and ways to encode/decode them.

Furthermore, the current parser/builder allows parsing/building messages
containing the exact same format in all its IEs. A new parser function
is added which allows parsing messages of different types (TV, TLV)
mixed in the same message. In order to be able to do so, it uses the
general msg_mode passed to it in order to know the general TLV format
(in essence, the length of the Tag field, and also the length of the
Length field if applicable each IE).

Looking up the instance in the TLV description is left undone and
hadcoded to 0, since the only user so far requiring this API is GTPv1-C,
which has no instances.

* [CORE] tlv: Support repeated tag+instance parsing TLV message

In GTPv2C, repeated IEs (same tag) are easily differentiated by the
Instance byte, which provides info to match different decoded
structures. In GTPv1C though, there's no Instance byte, and we still
encounter repeated IEs (like GSN Address in Create PDP Context Request).
Hence, the TLV decoder needs to be updated to track count of IEs found
(identified by tag+instance, where instance is always 0 in GTPv1C) and
get the proper description index + offset into the decoded structure.

* [GTP]: Move GTPv2-C specifics to its own libgtp subdir

This will allow adding GTPv1-C code by the side. Most GTPv2 code is left
in this patch as "gtp" instead of renaming it to "gtp2" in order to
avoid massive changes. It can be done at a later stage if wanted.

* [GTP] Support generating GTPv1-C messages

* [SMF] Add Gn interface support

This patch introduces GTPv1C support to open5gs-smfd. With it,
open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting
GERAN and UTRAN networks.
This commit is contained in:
Pau Espin 2022-02-18 14:23:45 +01:00 committed by GitHub
parent 3eab4be135
commit 8cc70694db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
146 changed files with 9199 additions and 538 deletions

View File

@ -250,7 +250,34 @@ int ogs_ipv6prefix_from_string(
uint8_t *addr6, uint8_t *prefixlen, char *string);
/**************************************************
* 8.14 PDN Address Allocation (PAA) */
* GTPv1-C: TS 29.060 7.7.27 End User Address (EUA) */
#define OGS_PDP_EUA_ORG_ETSI 0
#define OGS_PDP_EUA_ORG_IETF 1
#define OGS_PDP_EUA_ETSI_PPP 1
#define OGS_PDP_EUA_IETF_IPV4 0x21
#define OGS_PDP_EUA_IETF_IPV6 0x57
#define OGS_PDP_EUA_IETF_IPV4V6 0x8D
typedef struct ogs_eua_s {
ED2(uint8_t spare:4;,
uint8_t organization:4;)
uint8_t type;
union {
/* PDU_SESSION_TYPE_IPV4 */
uint32_t addr;
/* PDU_SESSION_TYPE_IPV6 */
uint8_t addr6[OGS_IPV6_LEN];
/* PDU_SESSION_TYPE_IPV4V6 */
struct {
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
} __attribute__ ((packed)) both;
};
} __attribute__ ((packed)) ogs_eua_t;
/**************************************************
* GTPv2-C: TS 29.274 8.14 PDN Address Allocation (PAA) */
#define OGS_PAA_IPV4_LEN 5
#define OGS_PAA_IPV6_LEN 18
#define OGS_PAA_IPV4V6_LEN 22

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* This file is part of Open5GS.
*
@ -36,38 +37,89 @@ ogs_tlv_desc_t ogs_tlv_desc_more7 = {
ogs_tlv_desc_t ogs_tlv_desc_more8 = {
OGS_TLV_MORE, "More", 0, 8, 0, 0, { NULL } };
static ogs_tlv_t *tlv_add_leaf(
ogs_tlv_t *parent_tlv, ogs_tlv_t *tlv, ogs_tlv_desc_t *desc, void *msg)
/* Return specific TLV mode based on its TLV description type and the msg
* provided mode (used to know the type length) */
static uint8_t tlv_ctype2mode(ogs_tlv_type_e ctype, uint8_t msg_mode)
{
switch(ctype) {
case OGS_TLV_UINT8:
case OGS_TLV_UINT16:
case OGS_TLV_UINT24:
case OGS_TLV_UINT32:
case OGS_TLV_INT8:
case OGS_TLV_INT16:
case OGS_TLV_INT24:
case OGS_TLV_INT32:
case OGS_TLV_FIXED_STR:
case OGS_TLV_VAR_STR:
case OGS_TLV_NULL:
case OGS_TLV_MORE:
case OGS_TLV_COMPOUND:
case OGS_TLV_MESSAGE:
return msg_mode;
case OGS_TV_UINT8:
case OGS_TV_UINT16:
case OGS_TV_UINT24:
case OGS_TV_UINT32:
case OGS_TV_INT8:
case OGS_TV_INT16:
case OGS_TV_INT24:
case OGS_TV_INT32:
case OGS_TV_FIXED_STR:
case OGS_TV_VAR_STR:
case OGS_TV_NULL:
case OGS_TV_MORE:
if (msg_mode == OGS_TLV_MODE_T2_L2)
return OGS_TLV_MODE_T1; /* Here return OGS_TLV_MODE_T2 if ever existing */
else
return OGS_TLV_MODE_T1;
default:
ogs_assert_if_reached();
break;
}
}
static ogs_tlv_t *tlv_add_leaf(
ogs_tlv_t *parent_tlv, ogs_tlv_t *tlv, ogs_tlv_desc_t *desc, void *msg, uint8_t msg_mode)
{
uint8_t tlv_mode = tlv_ctype2mode(desc->ctype, msg_mode);
switch (desc->ctype) {
case OGS_TLV_UINT8:
case OGS_TLV_INT8:
case OGS_TV_UINT8:
case OGS_TV_INT8:
{
ogs_tlv_uint8_t *v = (ogs_tlv_uint8_t *)msg;
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, 1, desc->instance, &v->u8);
else
tlv = ogs_tlv_add(tlv, desc->type, 1, desc->instance, &v->u8);
tlv = ogs_tlv_add(tlv, tlv_mode, desc->type, 1, desc->instance, &v->u8);
ogs_expect_or_return_val(tlv, NULL);
break;
}
case OGS_TLV_UINT16:
case OGS_TLV_INT16:
case OGS_TV_UINT16:
case OGS_TV_INT16:
{
ogs_tlv_uint16_t *v = (ogs_tlv_uint16_t *)msg;
v->u16 = htobe16(v->u16);
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, 2, desc->instance, &v->u16);
else
tlv = ogs_tlv_add(tlv, desc->type, 2, desc->instance, &v->u16);
tlv = ogs_tlv_add(tlv, tlv_mode, desc->type, 2, desc->instance, &v->u16);
ogs_expect_or_return_val(tlv, NULL);
break;
}
case OGS_TLV_UINT24:
case OGS_TLV_INT24:
case OGS_TV_UINT24:
case OGS_TV_INT24:
{
ogs_tlv_uint24_t *v = (ogs_tlv_uint24_t *)msg;
@ -75,38 +127,41 @@ static ogs_tlv_t *tlv_add_leaf(
v->u24 = htobe32(v->u24);
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, 3, desc->instance, &v->u24);
else
tlv = ogs_tlv_add(tlv, desc->type, 3, desc->instance, &v->u24);
tlv = ogs_tlv_add(tlv, tlv_mode, desc->type, 3, desc->instance, &v->u24);
ogs_expect_or_return_val(tlv, NULL);
break;
}
case OGS_TLV_UINT32:
case OGS_TLV_INT32:
case OGS_TV_UINT32:
case OGS_TV_INT32:
{
ogs_tlv_uint32_t *v = (ogs_tlv_uint32_t *)msg;
v->u32 = htobe32(v->u32);
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, 4, desc->instance, &v->u32);
else
tlv = ogs_tlv_add(tlv,
tlv = ogs_tlv_add(tlv, tlv_mode,
desc->type, 4, desc->instance, &v->u32);
ogs_expect_or_return_val(tlv, NULL);
break;
}
case OGS_TLV_FIXED_STR:
case OGS_TV_FIXED_STR:
{
ogs_tlv_octet_t *v = (ogs_tlv_octet_t *)msg;
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, desc->length, desc->instance, v->data);
else
tlv = ogs_tlv_add(tlv,
tlv = ogs_tlv_add(tlv, tlv_mode,
desc->type, desc->length, desc->instance, v->data);
ogs_expect_or_return_val(tlv, NULL);
break;
@ -122,21 +177,22 @@ static ogs_tlv_t *tlv_add_leaf(
}
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, v->len, desc->instance, v->data);
else
tlv = ogs_tlv_add(tlv,
tlv = ogs_tlv_add(tlv, tlv_mode,
desc->type, v->len, desc->instance, v->data);
ogs_expect_or_return_val(tlv, NULL);
break;
}
case OGS_TLV_NULL:
case OGS_TV_NULL:
{
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_mode,
desc->type, 0, desc->instance, NULL);
else
tlv = ogs_tlv_add(tlv,
tlv = ogs_tlv_add(tlv, tlv_mode,
desc->type, 0, desc->instance, NULL);
ogs_expect_or_return_val(tlv, NULL);
break;
@ -150,7 +206,7 @@ static ogs_tlv_t *tlv_add_leaf(
}
static uint32_t tlv_add_compound(ogs_tlv_t **root, ogs_tlv_t *parent_tlv,
ogs_tlv_desc_t *parent_desc, void *msg, int depth)
ogs_tlv_desc_t *parent_desc, void *msg, int depth, uint8_t mode)
{
ogs_tlv_presence_t *presence_p;
ogs_tlv_desc_t *desc = NULL, *next_desc = NULL;
@ -186,15 +242,15 @@ static uint32_t tlv_add_compound(ogs_tlv_t **root, ogs_tlv_t *parent_tlv,
desc->vsize, p + offset2);
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_ctype2mode(desc->ctype, mode),
desc->type, 0, desc->instance, NULL);
else
tlv = ogs_tlv_add(tlv,
tlv = ogs_tlv_add(tlv, tlv_ctype2mode(desc->ctype, mode),
desc->type, 0, desc->instance, NULL);
r = tlv_add_compound(&emb_tlv, tlv, desc,
p + offset2 + sizeof(ogs_tlv_presence_t),
depth + 1);
depth + 1, mode);
ogs_expect_or_return_val(r > 0 && emb_tlv, 0);
count += 1 + r;
} else {
@ -204,7 +260,7 @@ static uint32_t tlv_add_compound(ogs_tlv_t **root, ogs_tlv_t *parent_tlv,
desc->instance, desc->ctype, desc->vsize,
p + offset2);
tlv = tlv_add_leaf(parent_tlv, tlv, desc, p + offset2);
tlv = tlv_add_leaf(parent_tlv, tlv, desc, p + offset2, mode);
ogs_expect_or_return_val(tlv, 0);
count++;
}
@ -226,15 +282,15 @@ static uint32_t tlv_add_compound(ogs_tlv_t **root, ogs_tlv_t *parent_tlv,
desc->vsize, p + offset);
if (parent_tlv)
tlv = ogs_tlv_embed(parent_tlv,
tlv = ogs_tlv_embed(parent_tlv, tlv_ctype2mode(desc->ctype, mode),
desc->type, 0, desc->instance, NULL);
else
tlv = ogs_tlv_add(tlv,
tlv = ogs_tlv_add(tlv, tlv_ctype2mode(desc->ctype, mode),
desc->type, 0, desc->instance, NULL);
r = tlv_add_compound(&emb_tlv, tlv, desc,
p + offset + sizeof(ogs_tlv_presence_t),
depth + 1);
depth + 1, mode);
ogs_expect_or_return_val(r > 0 && emb_tlv, 0);
count += 1 + r;
} else {
@ -244,7 +300,7 @@ static uint32_t tlv_add_compound(ogs_tlv_t **root, ogs_tlv_t *parent_tlv,
desc->instance, desc->ctype, desc->vsize,
p + offset);
tlv = tlv_add_leaf(parent_tlv, tlv, desc, p + offset);
tlv = tlv_add_leaf(parent_tlv, tlv, desc, p + offset, mode);
ogs_expect_or_return_val(tlv, 0);
count++;
}
@ -271,10 +327,10 @@ ogs_pkbuf_t *ogs_tlv_build_msg(ogs_tlv_desc_t *desc, void *msg, int mode)
ogs_assert(desc->ctype == OGS_TLV_MESSAGE);
if (desc->child_descs[0]) {
r = tlv_add_compound(&root, NULL, desc, msg, 0);
r = tlv_add_compound(&root, NULL, desc, msg, 0, mode);
ogs_expect_or_return_val(r > 0 && root, NULL);
length = ogs_tlv_calc_length(root, mode);
length = ogs_tlv_calc_length(root);
} else {
length = 0;
}
@ -284,7 +340,7 @@ ogs_pkbuf_t *ogs_tlv_build_msg(ogs_tlv_desc_t *desc, void *msg, int mode)
ogs_pkbuf_put(pkbuf, length);
if (desc->child_descs[0]) {
rendlen = ogs_tlv_render(root, pkbuf->data, length, mode);
rendlen = ogs_tlv_render(root, pkbuf->data, length);
ogs_expect_or_return_val(rendlen == length, NULL);
ogs_tlv_free_all(root);
@ -293,21 +349,24 @@ ogs_pkbuf_t *ogs_tlv_build_msg(ogs_tlv_desc_t *desc, void *msg, int mode)
return pkbuf;
}
static ogs_tlv_desc_t* tlv_find_desc(uint8_t *desc_index,
uint32_t *tlv_offset, ogs_tlv_desc_t *parent_desc, ogs_tlv_t *tlv)
static ogs_tlv_desc_t* tlv_find_desc_by_type_inst(uint8_t *desc_index,
uint32_t *tlv_offset, ogs_tlv_desc_t *parent_desc, uint16_t match_type, uint8_t match_instance, uint8_t match_type_pos)
{
ogs_tlv_desc_t *prev_desc = NULL, *desc = NULL;
int i, offset = 0;
unsigned match_i = 0;
ogs_assert(parent_desc);
ogs_assert(tlv);
for (i = 0, desc = parent_desc->child_descs[i]; desc != NULL;
i++, desc = parent_desc->child_descs[i]) {
if (desc->type == tlv->type && desc->instance == tlv->instance) {
*desc_index = i;
*tlv_offset = offset;
break;
if (desc->type == match_type && desc->instance == match_instance) {
if (match_i == match_type_pos) {
*desc_index = i;
*tlv_offset = offset;
break;
}
match_i++;
}
if (desc->ctype == OGS_TLV_MORE) {
@ -330,6 +389,8 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
ogs_assert(tlv);
switch (desc->ctype) {
case OGS_TV_UINT8:
case OGS_TV_INT8:
case OGS_TLV_UINT8:
case OGS_TLV_INT8:
{
@ -343,6 +404,8 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
v->u8 = *(uint8_t*)(tlv->value);
break;
}
case OGS_TV_UINT16:
case OGS_TV_INT16:
case OGS_TLV_UINT16:
case OGS_TLV_INT16:
{
@ -357,6 +420,8 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
((((uint8_t*)tlv->value)[1] )&0x00ff);
break;
}
case OGS_TV_UINT24:
case OGS_TV_INT24:
case OGS_TLV_UINT24:
case OGS_TLV_INT24:
{
@ -372,6 +437,8 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
((((uint8_t*)tlv->value)[2] )&0x000000ff);
break;
}
case OGS_TV_UINT32:
case OGS_TV_INT32:
case OGS_TLV_UINT32:
case OGS_TLV_INT32:
{
@ -388,6 +455,7 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
((((uint8_t*)tlv->value)[3] )&0x000000ff);
break;
}
case OGS_TV_FIXED_STR:
case OGS_TLV_FIXED_STR:
{
ogs_tlv_octet_t *v = (ogs_tlv_octet_t *)msg;
@ -411,6 +479,7 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
v->len = tlv->length;
break;
}
case OGS_TV_NULL:
case OGS_TLV_NULL:
{
if (tlv->length != 0) {
@ -427,6 +496,50 @@ static int tlv_parse_leaf(void *msg, ogs_tlv_desc_t *desc, ogs_tlv_t *tlv)
return OGS_OK;
}
/* rbtree structure used to keep track count of TLVs with given <type,instance>
* while parsing. This is used to link it to the matching nth field in a
* ogs_tlv_desc_t struct */
typedef struct tlv_count_node_s {
ogs_rbnode_t node;
uint32_t key; /* type<<8 + instance */
unsigned count;
} tlv_count_node_t;
static tlv_count_node_t *tlv_count_node_find(ogs_rbtree_t *tree, tlv_count_node_t *count_node_arr, unsigned count_node_arr_len,
unsigned *count_alloc_next, uint16_t type, uint8_t instance)
{
ogs_rbnode_t **new = NULL;
ogs_rbnode_t *parent = NULL;
tlv_count_node_t *this;
uint64_t key = (((uint32_t)type)<<8) | instance;
new = &tree->root;
while (*new) {
this = ogs_rb_entry(*new, tlv_count_node_t, node);
parent = *new;
if (key < this->key) {
new = &(*new)->left;
} else if (key > this->key) {
new = &(*new)->right;
} else { /* found entry: */
return this;
}
}
/* No entry, need to add one: */
if (*count_alloc_next == count_node_arr_len) {
ogs_error("This TLV has to many entries, can't parse");
return NULL;
}
this = &count_node_arr[(*count_alloc_next)++];
this->key = key;
this->count = 0;
ogs_rbtree_link_node(&this->node, parent, new);
ogs_rbtree_insert_color(tree, &this->node);
return this;
}
static int tlv_parse_compound(void *msg, ogs_tlv_desc_t *parent_desc,
ogs_tlv_t *parent_tlv, int depth, int mode)
{
@ -438,6 +551,9 @@ static int tlv_parse_compound(void *msg, ogs_tlv_desc_t *parent_desc,
uint32_t offset = 0;
uint8_t index = 0;
int i = 0, j;
OGS_RBTREE(tree);
tlv_count_node_t count_node[OGS_TLV_MAX_CHILD_DESC];
unsigned count_node_alloc_next = 0;
char indent[17] = " "; /* 16 spaces */
ogs_assert(msg);
@ -449,7 +565,11 @@ static int tlv_parse_compound(void *msg, ogs_tlv_desc_t *parent_desc,
tlv = parent_tlv;
while (tlv) {
desc = tlv_find_desc(&index, &offset, parent_desc, tlv);
tlv_count_node_t *curr_count = tlv_count_node_find(&tree, &count_node[0],
OGS_ARRAY_SIZE(count_node), &count_node_alloc_next, tlv->type, tlv->instance);
if (!curr_count)
return OGS_ERROR;
desc = tlv_find_desc_by_type_inst(&index, &offset, parent_desc, tlv->type, tlv->instance, curr_count->count);
if (desc == NULL) {
ogs_warn("Unknown TLV type [%d]", tlv->type);
tlv = tlv->next;
@ -475,6 +595,8 @@ static int tlv_parse_compound(void *msg, ogs_tlv_desc_t *parent_desc,
tlv = tlv->next;
continue;
}
} else {
curr_count->count++;
}
if (desc->ctype == OGS_TLV_COMPOUND) {
@ -544,3 +666,117 @@ int ogs_tlv_parse_msg(void *msg, ogs_tlv_desc_t *desc, ogs_pkbuf_t *pkbuf,
return rv;
}
static uint16_t parse_get_element_type(uint8_t *pos, uint8_t mode)
{
uint16_t type;
switch(mode) {
case OGS_TLV_MODE_T1_L1:
case OGS_TLV_MODE_T1_L2:
case OGS_TLV_MODE_T1_L2_I1:
case OGS_TLV_MODE_T1:
type = *pos;
break;
case OGS_TLV_MODE_T2_L2:
type = *(pos++) << 8;
type += *(pos++);
break;
default:
ogs_assert_if_reached();
break;
}
return type;
}
/* Get TLV element taking into account msg_mode (to know TLV tag length) +
* specific TLV information from "desc" (to know whether the specific IE is TLV
* or TV, and its expected length in the later case). */
static uint8_t *tlv_get_element_desc(ogs_tlv_t *tlv, uint8_t *blk, uint8_t msg_mode, ogs_tlv_desc_t *desc)
{
uint8_t instance;
unsigned tlv_tag_pos;
uint8_t desc_index = 0;
uint32_t tlv_offset = 0;
uint16_t tlv_tag;
uint8_t tlv_mode;
static ogs_tlv_desc_t* tlv_desc;
tlv_tag = parse_get_element_type(blk, msg_mode);
instance = 0; /* TODO: support instance != 0 if ever really needed by looking it up in pos */
tlv_tag_pos = 0; /* All tags with same instance should use the same tlv_desc, so take the first one */
tlv_desc = tlv_find_desc_by_type_inst(&desc_index, &tlv_offset, desc, tlv_tag, instance, tlv_tag_pos);
if (!tlv_desc) {
ogs_error("Can't parse find TLV description for type %u", tlv_tag);
return NULL;
}
tlv_mode = tlv_ctype2mode(tlv_desc->ctype, msg_mode);
if (tlv_mode == OGS_TLV_MODE_T1)
return tlv_get_element_fixed(tlv, blk, tlv_mode, tlv_desc->length);
return tlv_get_element(tlv, blk, tlv_mode);
}
/* Similar to ogs_tlv_parse_block(), but taking into account each TLV format from "desc". */
static ogs_tlv_t *ogs_tlv_parse_block_desc(uint32_t length, void *data, uint8_t msg_mode, ogs_tlv_desc_t *desc)
{
uint8_t *pos = data;
uint8_t *blk = data;
ogs_tlv_t *root = NULL;
ogs_tlv_t *prev = NULL;
ogs_tlv_t *curr = NULL;
root = curr = ogs_tlv_get();
ogs_assert(curr);
pos = tlv_get_element_desc(curr, pos, msg_mode, desc);
ogs_assert(pos);
while(pos - blk < length) {
prev = curr;
curr = ogs_tlv_get();
ogs_assert(curr);
prev->next = curr;
pos = tlv_get_element_desc(curr, pos, msg_mode, desc);
ogs_assert(pos);
}
ogs_assert(length == (pos - blk));
return root;
}
/* Similar to ogs_tlv_parse_msg(), but takes each TLV type from the desc
* defintion. This allows parsing messages which have different types of TLVs in
* it (for instance GTPv1-C). */
int ogs_tlv_parse_msg_desc(
void *msg, ogs_tlv_desc_t *desc, ogs_pkbuf_t *pkbuf, int msg_mode)
{
int rv;
ogs_tlv_t *root;
ogs_assert(msg);
ogs_assert(desc);
ogs_assert(pkbuf);
ogs_assert(desc->ctype == OGS_TLV_MESSAGE);
ogs_assert(desc->child_descs[0]);
root = ogs_tlv_parse_block_desc(pkbuf->len, pkbuf->data, msg_mode, desc);
if (root == NULL) {
ogs_error("Can't parse TLV message");
return OGS_ERROR;
}
rv = tlv_parse_compound(msg, desc, root, 0, msg_mode);
ogs_tlv_free_all(root);
return rv;
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* This file is part of Open5GS.
*
@ -50,6 +51,18 @@ typedef enum {
OGS_TLV_MORE,
OGS_TLV_COMPOUND,
OGS_TLV_MESSAGE,
OGS_TV_UINT8,
OGS_TV_UINT16,
OGS_TV_UINT24,
OGS_TV_UINT32,
OGS_TV_INT8,
OGS_TV_INT16,
OGS_TV_INT24,
OGS_TV_INT32,
OGS_TV_FIXED_STR,
OGS_TV_VAR_STR,
OGS_TV_NULL,
OGS_TV_MORE,
} ogs_tlv_type_e;
typedef struct ogs_tlv_desc_s {
@ -158,6 +171,8 @@ typedef struct ogs_tlv_null_s {
ogs_pkbuf_t *ogs_tlv_build_msg(ogs_tlv_desc_t *desc, void *msg, int mode);
int ogs_tlv_parse_msg(
void *msg, ogs_tlv_desc_t *desc, ogs_pkbuf_t *pkbuf, int mode);
int ogs_tlv_parse_msg_desc(
void *msg, ogs_tlv_desc_t *desc, ogs_pkbuf_t *pkbuf, int msg_mode);
#ifdef __cplusplus
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* This file is part of Open5GS.
*
@ -105,14 +106,14 @@ uint32_t ogs_tlv_value_32(ogs_tlv_t *tlv)
return u_32;
}
uint32_t ogs_tlv_calc_length(ogs_tlv_t *tlv, uint8_t mode)
uint32_t ogs_tlv_calc_length(ogs_tlv_t *tlv)
{
ogs_tlv_t *iter = tlv;
uint32_t length = 0;
while(iter) {
/* this is length for type field */
switch(mode) {
switch(iter->mode) {
case OGS_TLV_MODE_T1_L1:
length += 2;
break;
@ -123,6 +124,9 @@ uint32_t ogs_tlv_calc_length(ogs_tlv_t *tlv, uint8_t mode)
case OGS_TLV_MODE_T2_L2:
length += 4;
break;
case OGS_TLV_MODE_T1:
length += 1;
break;
default:
ogs_assert_if_reached();
break;
@ -130,7 +134,7 @@ uint32_t ogs_tlv_calc_length(ogs_tlv_t *tlv, uint8_t mode)
/* this is length for type field */
if(iter->embedded != NULL) {
iter->length = ogs_tlv_calc_length(iter->embedded, mode);
iter->length = ogs_tlv_calc_length(iter->embedded);
}
/* this is length for value field */
@ -163,6 +167,7 @@ static uint8_t *tlv_put_type(uint32_t type, uint8_t *pos, uint8_t mode)
case OGS_TLV_MODE_T1_L1:
case OGS_TLV_MODE_T1_L2:
case OGS_TLV_MODE_T1_L2_I1:
case OGS_TLV_MODE_T1:
*(pos++) = type & 0xFF;
break;
case OGS_TLV_MODE_T2_L2:
@ -188,6 +193,8 @@ static uint8_t *tlv_put_length(uint32_t length, uint8_t *pos, uint8_t mode)
*(pos++) = (length >> 8) & 0xFF;
*(pos++) = length & 0xFF;
break;
case OGS_TLV_MODE_T1:
break;
default:
ogs_assert_if_reached();
break;
@ -209,10 +216,12 @@ static uint8_t *tlv_put_instance(uint8_t instance, uint8_t *pos, uint8_t mode)
return pos;
}
static uint8_t *tlv_get_element(ogs_tlv_t *tlv, uint8_t *blk, uint8_t mode)
uint8_t *tlv_get_element(ogs_tlv_t *tlv, uint8_t *blk, uint8_t mode)
{
uint8_t *pos = blk;
tlv->mode = mode;
switch(mode) {
case OGS_TLV_MODE_T1_L1:
tlv->type = *(pos++);
@ -235,6 +244,29 @@ static uint8_t *tlv_get_element(ogs_tlv_t *tlv, uint8_t *blk, uint8_t mode)
tlv->length = *(pos++) << 8;
tlv->length += *(pos++);
break;
case OGS_TLV_MODE_T1:
tlv->type = *(pos++);
tlv->length = 0;
break;
default:
ogs_assert_if_reached();
break;
}
tlv->value = pos;
return (pos + ogs_tlv_length(tlv));
}
uint8_t *tlv_get_element_fixed(ogs_tlv_t *tlv, uint8_t *blk, uint8_t mode, uint32_t fixed_length)
{
uint8_t *pos = blk;
switch(mode) {
case OGS_TLV_MODE_T1:
tlv->type = *(pos++);
tlv->length = fixed_length;
break;
default:
ogs_assert_if_reached();
break;
@ -268,7 +300,7 @@ ogs_tlv_t *ogs_tlv_find_root(ogs_tlv_t *tlv)
return head;
}
ogs_tlv_t *ogs_tlv_add(ogs_tlv_t *head,
ogs_tlv_t *ogs_tlv_add(ogs_tlv_t *head, uint8_t mode,
uint32_t type, uint32_t length, uint8_t instance, void *value)
{
ogs_tlv_t *curr = head;
@ -279,6 +311,7 @@ ogs_tlv_t *ogs_tlv_add(ogs_tlv_t *head,
if(length != 0)
ogs_assert(value);
new->mode = mode;
new->type = type;
new->length = length;
new->instance = instance;
@ -304,7 +337,7 @@ ogs_tlv_t *ogs_tlv_add(ogs_tlv_t *head,
return new;
}
ogs_tlv_t *ogs_tlv_copy(void *buff, uint32_t buff_len,
ogs_tlv_t *ogs_tlv_copy(void *buff, uint32_t buff_len, uint8_t mode,
uint32_t type, uint32_t length, uint8_t instance, void *value)
{
ogs_tlv_t *new = NULL;
@ -312,6 +345,7 @@ ogs_tlv_t *ogs_tlv_copy(void *buff, uint32_t buff_len,
new = ogs_tlv_get();
ogs_assert(new);
new->mode = mode;
new->type = type;
new->length = length;
new->instance = instance;
@ -327,7 +361,7 @@ ogs_tlv_t *ogs_tlv_copy(void *buff, uint32_t buff_len,
return new;
}
ogs_tlv_t *ogs_tlv_embed(ogs_tlv_t *parent,
ogs_tlv_t *ogs_tlv_embed(ogs_tlv_t *parent, uint8_t mode,
uint32_t type, uint32_t length, uint8_t instance, void *value)
{
ogs_tlv_t *new = NULL, *root = NULL;
@ -337,6 +371,7 @@ ogs_tlv_t *ogs_tlv_embed(ogs_tlv_t *parent,
new = ogs_tlv_get();
ogs_assert(new);
new->mode = mode;
new->type = type;
new->length = length;
new->instance = instance;
@ -364,8 +399,7 @@ ogs_tlv_t *ogs_tlv_embed(ogs_tlv_t *parent,
return new;
}
uint32_t ogs_tlv_render(ogs_tlv_t *root,
void *data, uint32_t length, uint8_t mode)
uint32_t ogs_tlv_render(ogs_tlv_t *root, void *data, uint32_t length)
{
ogs_tlv_t *curr = root;
uint8_t *pos = data;
@ -373,11 +407,11 @@ uint32_t ogs_tlv_render(ogs_tlv_t *root,
uint32_t embedded_len = 0;
while(curr) {
pos = tlv_put_type(curr->type, pos, mode);
pos = tlv_put_type(curr->type, pos, curr->mode);
if(curr->embedded == NULL) {
pos = tlv_put_length(curr->length, pos, mode);
pos = tlv_put_instance(curr->instance, pos, mode);
pos = tlv_put_length(curr->length, pos, curr->mode);
pos = tlv_put_instance(curr->instance, pos, curr->mode);
if ((pos - blk) + ogs_tlv_length(curr) > length)
ogs_assert_if_reached();
@ -385,11 +419,11 @@ uint32_t ogs_tlv_render(ogs_tlv_t *root,
memcpy((char*)pos, (char*)curr->value, curr->length);
pos += curr->length;
} else {
embedded_len = ogs_tlv_calc_length(curr->embedded, mode);
pos = tlv_put_length(embedded_len, pos, mode);
pos = tlv_put_instance(curr->instance, pos, mode);
embedded_len = ogs_tlv_calc_length(curr->embedded);
pos = tlv_put_length(embedded_len, pos, curr->mode);
pos = tlv_put_instance(curr->instance, pos, curr->mode);
ogs_tlv_render(curr->embedded,
pos, length - (uint32_t)(pos-blk), mode);
pos, length - (uint32_t)(pos-blk));
pos += embedded_len;
}
curr = curr->next;

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* This file is part of Open5GS.
*
@ -32,6 +33,7 @@ extern "C" {
#define OGS_TLV_MODE_T1_L2 2
#define OGS_TLV_MODE_T1_L2_I1 3
#define OGS_TLV_MODE_T2_L2 4
#define OGS_TLV_MODE_T1 5
/* ogs_tlv_t struncture */
@ -45,6 +47,9 @@ typedef struct ogs_tlv_s
struct ogs_tlv_s *parent;
struct ogs_tlv_s *embedded;
/* tlv mode: defines exact meaning and (conditional) use of fields in next section */
uint8_t mode;
/* tlv basic element */
uint32_t type;
uint32_t length;
@ -74,24 +79,25 @@ void ogs_tlv_final(void);
uint32_t ogs_tlv_pool_avail(void);
/* ogs_tlv_t encoding functions */
ogs_tlv_t *ogs_tlv_add(ogs_tlv_t *head,
ogs_tlv_t *ogs_tlv_add(ogs_tlv_t *head, uint8_t mode,
uint32_t type, uint32_t length, uint8_t instance, void *value);
ogs_tlv_t *ogs_tlv_copy(void *buff, uint32_t buff_len,
ogs_tlv_t *ogs_tlv_copy(void *buff, uint32_t buff_len, uint8_t mode,
uint32_t type, uint32_t length, uint8_t instance, void *value);
ogs_tlv_t *ogs_tlv_embed(ogs_tlv_t *parent,
ogs_tlv_t *ogs_tlv_embed(ogs_tlv_t *parent, uint8_t mode,
uint32_t type, uint32_t length, uint8_t instance, void *value);
uint32_t ogs_tlv_render(
ogs_tlv_t *root, void *data, uint32_t length, uint8_t mode);
uint32_t ogs_tlv_render(ogs_tlv_t *root, void *data, uint32_t length);
/* ogs_tlv_t parsing functions */
uint8_t *tlv_get_element(ogs_tlv_t *tlv, uint8_t *blk, uint8_t mode);
uint8_t *tlv_get_element_fixed(ogs_tlv_t *tlv, uint8_t *blk, uint8_t mode, uint32_t fixed_length);
ogs_tlv_t *ogs_tlv_parse_block(uint32_t length, void *data, uint8_t mode);
ogs_tlv_t *ogs_tlv_parse_embedded_block(ogs_tlv_t *tlv, uint8_t mode);
/* tlv operation-related function */
ogs_tlv_t *ogs_tlv_find(ogs_tlv_t *root, uint32_t type);
ogs_tlv_t *ogs_tlv_find_root(ogs_tlv_t *tlv);
uint32_t ogs_tlv_calc_length(ogs_tlv_t *tlv, uint8_t mode);
uint32_t ogs_tlv_calc_length(ogs_tlv_t *tlv);
uint32_t ogs_tlv_calc_count(ogs_tlv_t *tlv);
uint8_t ogs_tlv_value_8(ogs_tlv_t *tlv);
uint16_t ogs_tlv_value_16(ogs_tlv_t *tlv);

View File

@ -18,23 +18,35 @@
libgtp_sources = files('''
ogs-gtp.h
message.h
types.h
conv.h
context.h
build.h
path.h
xact.h
util.h
xact.h
v1/build.h
v1/conv.h
v1/message.h
v1/path.h
v1/types.h
v2/build.h
v2/conv.h
v2/message.h
v2/path.h
v2/types.h
message.c
types.c
conv.c
context.c
build.c
path.c
xact.c
util.c
xact.c
v1/build.c
v1/conv.c
v1/message.c
v1/path.c
v1/types.c
v2/build.c
v2/conv.c
v2/message.c
v2/path.c
v2/types.c
'''.split())
libgtp_inc = include_directories('.')

View File

@ -30,11 +30,17 @@
#define OGS_GTP_INSIDE
#include "gtp/message.h"
#include "gtp/types.h"
#include "gtp/conv.h"
#include "gtp/v1/message.h"
#include "gtp/v2/message.h"
#include "gtp/v1/types.h"
#include "gtp/v2/types.h"
#include "gtp/v1/conv.h"
#include "gtp/v2/conv.h"
#include "gtp/context.h"
#include "gtp/build.h"
#include "gtp/v1/build.h"
#include "gtp/v2/build.h"
#include "gtp/v1/path.h"
#include "gtp/v2/path.h"
#include "gtp/path.h"
#include "gtp/xact.h"
#include "gtp/util.h"

View File

@ -123,307 +123,15 @@ int ogs_gtp_sendto(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf)
return OGS_OK;
}
int ogs_gtp_send_user_plane(
ogs_gtp_node_t *gnode,
ogs_gtp_header_t *gtp_hdesc, ogs_gtp_extension_header_t *ext_hdesc,
ogs_pkbuf_t *pkbuf)
{
char buf[OGS_ADDRSTRLEN];
int rv;
ogs_gtp_header_t *gtp_h = NULL;
ogs_gtp_extension_header_t *ext_h = NULL;
uint8_t flags;
uint8_t gtp_hlen = 0;
ogs_assert(gnode);
ogs_assert(gtp_hdesc);
ogs_assert(ext_hdesc);
ogs_assert(pkbuf);
/* Processing GTP Flags */
flags = gtp_hdesc->flags;
flags |= OGS_GTPU_FLAGS_V | OGS_GTPU_FLAGS_PT;
if (ext_hdesc->qos_flow_identifier) flags |= OGS_GTPU_FLAGS_E;
/* Define GTP Header Size */
if (flags & OGS_GTPU_FLAGS_E)
gtp_hlen = OGS_GTPV1U_HEADER_LEN+8;
else if (flags & (OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_PN))
gtp_hlen = OGS_GTPV1U_HEADER_LEN+4;
else
gtp_hlen = OGS_GTPV1U_HEADER_LEN;
ogs_pkbuf_push(pkbuf, gtp_hlen);
/* Fill GTP Header */
gtp_h = (ogs_gtp_header_t *)pkbuf->data;
ogs_assert(gtp_h);
memset(gtp_h, 0, gtp_hlen);
gtp_h->flags = flags;
gtp_h->type = gtp_hdesc->type;
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ ||
gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_RSP ||
gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
/*
* TS29.281 5.1 General format in GTP-U header
*
* - The Echo Request/Response and Supported Extension Headers
* notification messages, where the Tunnel Endpoint Identifier
* shall be set to all zeroes.
* - The Error Indication message where the Tunnel Endpoint Identifier
* shall be set to all zeros.
*/
ogs_assert(gtp_hdesc->teid == 0);
}
gtp_h->teid = htobe32(gtp_hdesc->teid);
/*
* TS29.281 5.1 General format in GTP-U header
*
* Length: This field indicates the length in octets of the payload,
* i.e. the rest of the packet following the mandatory part of
* the GTP header (that is the first 8 octets). The Sequence Number,
* the N-PDU Number or any Extension headers shall be considered
* to be part of the payload, i.e. included in the length count.
*/
gtp_h->length = htobe16(pkbuf->len - OGS_GTPV1U_HEADER_LEN);
/* Fill Extention Header */
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
ext_h = (ogs_gtp_extension_header_t *)
(pkbuf->data + OGS_GTPV1U_HEADER_LEN);
ogs_assert(ext_h);
if (ext_hdesc->qos_flow_identifier) {
/* 5G Core */
ext_h->type = OGS_GTP_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER;
ext_h->len = 1;
ext_h->pdu_type = ext_hdesc->pdu_type;
ext_h->qos_flow_identifier = ext_hdesc->qos_flow_identifier;
ext_h->next_type =
OGS_GTP_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
} else {
/* EPC */
ext_h->type = ext_hdesc->type;
ext_h->len = 1;
ext_h->next_type =
OGS_GTP_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
}
}
ogs_debug("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
rv = ogs_gtp_sendto(gnode, pkbuf);
if (rv != OGS_OK) {
if (ogs_socket_errno != OGS_EAGAIN) {
ogs_error("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
}
}
ogs_pkbuf_free(pkbuf);
return rv;
}
ogs_pkbuf_t *ogs_gtp_handle_echo_req(ogs_pkbuf_t *pkb)
{
ogs_gtp_header_t *gtph = NULL;
ogs_pkbuf_t *pkb_resp = NULL;
ogs_gtp_header_t *gtph_resp = NULL;
uint16_t length;
int idx;
ogs_assert(pkb);
gtph = (ogs_gtp_header_t *)pkb->data;
/* Check GTP version. Now only support GTPv1(version = 1) */
if ((gtph->flags >> 5) != 1) {
return NULL;
}
if (gtph->type != OGS_GTPU_MSGTYPE_ECHO_REQ) {
return NULL;
}
pkb_resp = ogs_pkbuf_alloc(NULL,
100 /* enough for ECHO_RSP; use smaller buffer */);
ogs_expect_or_return_val(pkb_resp, NULL);
ogs_pkbuf_put(pkb_resp, 100);
gtph_resp = (ogs_gtp_header_t *)pkb_resp->data;
/* reply back immediately */
gtph_resp->flags = (1 << 5); /* set version */
gtph_resp->flags |= (1 << 4); /* set PT */
gtph_resp->type = OGS_GTPU_MSGTYPE_ECHO_RSP;
length = 0; /* length of Recovery IE */
gtph_resp->length = htobe16(length); /* to be overwriten */
gtph_resp->teid = 0;
idx = 8;
if (gtph->flags & (OGS_GTPU_FLAGS_PN | OGS_GTPU_FLAGS_S)) {
length += 4;
if (gtph->flags & OGS_GTPU_FLAGS_S) {
/* sequence exists */
gtph_resp->flags |= OGS_GTPU_FLAGS_S;
*((uint8_t *)pkb_resp->data + idx) = *((uint8_t *)pkb->data + idx);
*((uint8_t *)pkb_resp->data + idx + 1) =
*((uint8_t *)pkb->data + idx + 1);
} else {
*((uint8_t *)pkb_resp->data + idx) = 0;
*((uint8_t *)pkb_resp->data + idx + 1) = 0;
}
idx += 2;
if (gtph->flags & OGS_GTPU_FLAGS_PN) {
/* sequence exists */
gtph_resp->flags |= OGS_GTPU_FLAGS_PN;
*((uint8_t *)pkb_resp->data + idx) = *((uint8_t *)pkb->data + idx);
} else {
*((uint8_t *)pkb_resp->data + idx) = 0;
}
idx++;
*((uint8_t *)pkb_resp->data + idx) = 0; /* next-extension header */
idx++;
}
/* fill Recovery IE */
length += 2;
*((uint8_t *)pkb_resp->data + idx) = 14; idx++; /* type */
*((uint8_t *)pkb_resp->data + idx) = 0; idx++; /* restart counter */
gtph_resp->length = htobe16(length);
ogs_pkbuf_trim(pkb_resp, idx); /* buffer length */
return pkb_resp;
}
void ogs_gtp_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value)
{
int rv;
ogs_gtp_message_t errmsg;
ogs_gtp_cause_t cause;
ogs_gtp_tlv_cause_t *tlv = NULL;
ogs_pkbuf_t *pkbuf = NULL;
memset(&errmsg, 0, sizeof(ogs_gtp_message_t));
errmsg.h.teid = teid;
errmsg.h.type = type;
switch (type) {
case OGS_GTP_CREATE_SESSION_RESPONSE_TYPE:
tlv = &errmsg.create_session_response.cause;
switch (xact->gtp_version) {
case 1:
ogs_gtp1_send_error_message(xact, teid, type, cause_value);
break;
case OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE:
tlv = &errmsg.modify_bearer_response.cause;
case 2:
ogs_gtp2_send_error_message(xact, teid, type, cause_value);
break;
case OGS_GTP_DELETE_SESSION_RESPONSE_TYPE:
tlv = &errmsg.delete_session_response.cause;
break;
case OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
tlv = &errmsg.release_access_bearers_response.cause;
break;
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE:
tlv = &errmsg.downlink_data_notification_acknowledge.cause;
break;
case OGS_GTP_CREATE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.create_bearer_response.cause;
break;
case OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.update_bearer_response.cause;
break;
case OGS_GTP_DELETE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.delete_bearer_response.cause;
break;
case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.create_indirect_data_forwarding_tunnel_response.cause;
break;
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.delete_indirect_data_forwarding_tunnel_response.cause;
break;
case OGS_GTP_MODIFY_BEARER_FAILURE_INDICATION_TYPE:
tlv = &errmsg.modify_bearer_failure_indication.cause;
break;
case OGS_GTP_DELETE_BEARER_FAILURE_INDICATION_TYPE:
tlv = &errmsg.delete_bearer_failure_indication.cause;
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
tlv = &errmsg.bearer_resource_failure_indication.cause;
break;
default:
ogs_assert_if_reached();
return;
}
ogs_assert(tlv);
memset(&cause, 0, sizeof cause);
cause.value = cause_value;
tlv->presence = 1;
tlv->len = sizeof(cause);
tlv->data = &cause;
pkbuf = ogs_gtp_build_msg(&errmsg);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(xact, &errmsg.h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp_send_echo_request(
ogs_gtp_node_t *gnode, uint8_t recovery, uint8_t features)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_header_t h;
ogs_gtp_xact_t *xact = NULL;
ogs_assert(gnode);
ogs_debug("[GTP] Sending Echo Request");
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_ECHO_REQUEST_TYPE;
h.teid = 0;
pkbuf = ogs_gtp_build_echo_request(h.type, recovery, features);
ogs_expect_or_return(pkbuf);
xact = ogs_gtp_xact_local_create(gnode, &h, pkbuf, NULL, NULL);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp_send_echo_response(ogs_gtp_xact_t *xact,
uint8_t recovery, uint8_t features)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_header_t h;
ogs_assert(xact);
ogs_debug("[GTP] Sending Echo Response");
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_ECHO_RESPONSE_TYPE;
h.teid = 0;
pkbuf = ogs_gtp_build_echo_response(h.type, recovery, features);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}

View File

@ -66,28 +66,15 @@ extern "C" {
&ogs_gtp_self()->gtpu_ip); \
} while(0)
typedef struct ogs_gtp_xact_s ogs_gtp_xact_t;
ogs_sock_t *ogs_gtp_server(ogs_socknode_t *node);
int ogs_gtp_connect(ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_gtp_node_t *gnode);
int ogs_gtp_send(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf);
int ogs_gtp_sendto(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf);
int ogs_gtp_send_user_plane(
ogs_gtp_node_t *gnode,
ogs_gtp_header_t *gtp_hdesc, ogs_gtp_extension_header_t *ext_hdesc,
ogs_pkbuf_t *pkbuf);
ogs_pkbuf_t *ogs_gtp_handle_echo_req(ogs_pkbuf_t *pkt);
void ogs_gtp_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_gtp_send_echo_request(
ogs_gtp_node_t *gnode, uint8_t recovery, uint8_t features);
void ogs_gtp_send_echo_response(ogs_gtp_xact_t *xact,
uint8_t recovery, uint8_t features);
#ifdef __cplusplus
}
#endif

47
lib/gtp/v1/build.c Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#include "ogs-gtp.h"
ogs_pkbuf_t *ogs_gtp1_build_echo_request(uint8_t type)
{
ogs_gtp1_message_t gtp1_message;
memset(&gtp1_message, 0, sizeof(ogs_gtp1_message_t));
gtp1_message.h.type = type;
return ogs_gtp1_build_msg(&gtp1_message);
}
ogs_pkbuf_t *ogs_gtp1_build_echo_response(
uint8_t type, uint8_t recovery)
{
ogs_gtp1_message_t gtp1_message;
ogs_gtp1_echo_response_t *rsp = NULL;
rsp = &gtp1_message.echo_response;
memset(&gtp1_message, 0, sizeof(ogs_gtp1_message_t));
rsp->recovery.presence = 1;
rsp->recovery.u8 = recovery;
gtp1_message.h.type = type;
return ogs_gtp1_build_msg(&gtp1_message);
}

38
lib/gtp/v1/build.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#if !defined(OGS_GTP_INSIDE) && !defined(OGS_GTP_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_GTP1_BUILD_H
#define OGS_GTP1_BUILD_H
#ifdef __cplusplus
extern "C" {
#endif
ogs_pkbuf_t *ogs_gtp1_build_echo_request(uint8_t type);
ogs_pkbuf_t *ogs_gtp1_build_echo_response(uint8_t type, uint8_t recovery);
#ifdef __cplusplus
}
#endif
#endif /* OGS_GTP1_BUILD_H */

267
lib/gtp/v1/conv.c Normal file
View File

@ -0,0 +1,267 @@
/*
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#include "ogs-gtp.h"
int ogs_gtp1_gsn_addr_to_sockaddr(const ogs_gtp1_gsn_addr_t *gsnaddr,
uint16_t gsnaddr_len, uint16_t port, ogs_sockaddr_t **list)
{
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
ogs_assert(gsnaddr);
ogs_assert(list);
switch (gsnaddr_len) {
case OGS_GTP_GSN_ADDRESS_IPV4_LEN:
addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
ogs_expect_or_return_val(addr, OGS_ERROR);
addr->ogs_sa_family = AF_INET;
addr->ogs_sin_port = port;
addr->sin.sin_addr.s_addr = gsnaddr->addr;
*list = addr;
break;
case OGS_GTP_GSN_ADDRESS_IPV6_LEN:
addr6 = ogs_calloc(1, sizeof(ogs_sockaddr_t));
ogs_expect_or_return_val(addr6, OGS_ERROR);
addr6->ogs_sa_family = AF_INET6;
addr6->ogs_sin_port = port;
memcpy(addr6->sin6.sin6_addr.s6_addr, gsnaddr->addr6, OGS_IPV6_LEN);
*list = addr6;
break;
default:
ogs_error("No IPv4 or IPv6");
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_gtp1_sockaddr_to_gsn_addr(const ogs_sockaddr_t *addr,
const ogs_sockaddr_t *addr6, ogs_gtp1_gsn_addr_t *gsnaddr, int *len)
{
ogs_assert(gsnaddr);
if (addr && addr6) {
ogs_error("GSN Address: Both IPv4 and IPv6 not supported");
return OGS_ERROR;
} else if (addr) {
gsnaddr->addr = addr->sin.sin_addr.s_addr;
*len = OGS_GTP_GSN_ADDRESS_IPV4_LEN;
} else if (addr6) {
memcpy(gsnaddr->addr6, addr6->sin6.sin6_addr.s6_addr, OGS_IPV6_LEN);
*len = OGS_GTP_GSN_ADDRESS_IPV6_LEN;
} else {
ogs_error("No IPv4 or IPv6");
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_gtp1_gsn_addr_to_ip(const ogs_gtp1_gsn_addr_t *gsnaddr, uint16_t gsnaddr_len,
ogs_ip_t *ip)
{
ogs_assert(ip);
ogs_assert(gsnaddr);
memset(ip, 0, sizeof(ogs_ip_t));
if (gsnaddr_len == OGS_GTP_GSN_ADDRESS_IPV4_LEN) {
ip->ipv4 = 1;
ip->ipv6 = 0;
ip->addr = gsnaddr->addr;
} else if (gsnaddr_len == OGS_GTP_GSN_ADDRESS_IPV6_LEN) {
ip->ipv4 = 0;
ip->ipv6 = 1;
memcpy(ip->addr6, gsnaddr->addr6, OGS_IPV6_LEN);
} else {
ogs_error("No IPv4 or IPv6");
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_gtp1_eua_to_ip(const ogs_eua_t *eua, uint16_t eua_len, ogs_ip_t *ip,
uint8_t *pdu_session_type)
{
ogs_assert(eua);
ogs_assert(ip);
memset(ip, 0, sizeof *ip);
switch (eua->organization) {
case OGS_PDP_EUA_ORG_IETF:
break;
case OGS_PDP_EUA_ORG_ETSI:
default:
ogs_error("Unsupported EUA organization %u", eua->organization);
return OGS_ERROR;
}
eua_len -= 2;
switch (eua->type) {
case OGS_PDP_EUA_IETF_IPV4:
if (eua_len == OGS_IPV4_LEN) {
ip->addr = eua->addr;
} else if (eua_len != 0) {
ogs_error("Wrong IPv4 EUA length %u", eua_len);
return OGS_ERROR;
}
ip->ipv4 = 1;
ip->ipv6 = 0;
*pdu_session_type = OGS_PDU_SESSION_TYPE_IPV4;
break;
case OGS_PDP_EUA_IETF_IPV6:
if (eua_len == OGS_IPV6_LEN) {
memcpy(ip->addr6, eua->addr6, OGS_IPV6_LEN);
} else if (eua_len != 0) {
ogs_error("Wrong IPv6 EUA length %u", eua_len);
return OGS_ERROR;
}
ip->ipv4 = 0;
ip->ipv6 = 1;
*pdu_session_type = OGS_PDU_SESSION_TYPE_IPV6;
break;
case OGS_PDP_EUA_IETF_IPV4V6:
if (eua_len == OGS_IPV4_LEN) {
ip->addr = eua->addr;
} else if (eua_len == OGS_IPV6_LEN) {
memcpy(ip->addr6, eua->addr6, OGS_IPV6_LEN);
} else if (eua_len == OGS_IPV4_LEN + OGS_IPV6_LEN) {
ip->addr = eua->both.addr;
memcpy(ip->addr6, eua->both.addr6, OGS_IPV6_LEN);
} else if (eua_len != 0) {
ogs_error("Wrong IPv4v6 EUA length %u", eua_len);
return OGS_ERROR;
}
ip->ipv4 = 1;
ip->ipv6 = 1;
*pdu_session_type = OGS_PDU_SESSION_TYPE_IPV4V6;
break;
default:
ogs_error("No IPv4 or IPv6");
return OGS_ERROR;
}
return OGS_OK;
}
int ogs_gtp1_ip_to_eua(uint8_t pdu_session_type, const ogs_ip_t *ip,
ogs_eua_t *eua, uint8_t *eua_len)
{
ogs_assert(eua);
ogs_assert(ip);
ogs_assert(eua_len);
memset(eua, 0, sizeof *eua);
eua->organization = OGS_PDP_EUA_ORG_IETF;
switch (pdu_session_type)
{
case OGS_PDU_SESSION_TYPE_IPV4:
if (!ip->ipv4) {
ogs_error("EUA type IPv4 but no IPv4 address available");
return OGS_ERROR;
}
eua->addr = ip->addr;
*eua_len = 2 + OGS_IPV4_LEN;
eua->type = OGS_PDP_EUA_IETF_IPV4;
break;
case OGS_PDU_SESSION_TYPE_IPV6:
if (!ip->ipv6) {
ogs_error("EUA type IPv4 but no IPv6 address available");
return OGS_ERROR;
}
memcpy(eua->addr6, ip->addr6, OGS_IPV6_LEN);
*eua_len = 2 + OGS_IPV6_LEN;
eua->type = OGS_PDP_EUA_IETF_IPV6;
break;
case OGS_PDU_SESSION_TYPE_IPV4V6:
if (ip->ipv4 && ip->ipv6) {
eua->both.addr = ip->addr;
memcpy(eua->both.addr6, ip->addr6, OGS_IPV6_LEN);
*eua_len = 2 + OGS_IPV4_LEN + OGS_IPV6_LEN;
} else if (ip->ipv4) {
eua->addr = ip->addr;
*eua_len = 2 + OGS_IPV4_LEN;
} else if (ip->ipv6) {
memcpy(eua->addr6, ip->addr6, OGS_IPV6_LEN);
*eua_len = 2 + OGS_IPV6_LEN;
} else {
ogs_error("EUA type IPv4 but no IPv4 nor IPv6 address available");
return OGS_ERROR;
}
eua->type = OGS_PDP_EUA_IETF_IPV4V6;
break;
default:
ogs_error("Unexpected session type");
return OGS_ERROR;
}
return OGS_OK;
}
/* 3GPP TS 23.401 Table E.3 */
int ogs_gtp1_qos_profile_to_qci(const ogs_gtp1_qos_profile_decoded_t *decoded,
uint8_t *qci)
{
ogs_assert(decoded);
ogs_assert(qci);
if (!decoded->data_octet6_to_13_present) {
/* traffic class not present, take QCI 9 as default */
*qci = 9;
return OGS_OK;
}
switch (decoded->qos_profile.data.traffic_class) {
case OGS_GTP1_QOS_TRAFFIC_CLASS_CONVERSATIONAL:
if (decoded->qos_profile.data.source_statistics_descriptor == OGS_GTP1_QOS_SRC_STATS_DESC_SPEECH)
*qci = 1;
else if (decoded->dec_transfer_delay >= 150)
*qci = 2;
else
*qci = 3;
break;
case OGS_GTP1_QOS_TRAFFIC_CLASS_STREAMING:
*qci = 4;
break;
case OGS_GTP1_QOS_TRAFFIC_CLASS_INTERACTIVE:
switch (decoded->qos_profile.data.traffic_handling_priority) {
case 1:
*qci = decoded->qos_profile.data.signalling_indication ? 5 : 6;
break;
case 2:
*qci = 7;
break;
case 3:
*qci = 8;
break;
default:
*qci = 9;
}
break;
case OGS_GTP1_QOS_TRAFFIC_CLASS_SUBSCRIBED:
case OGS_GTP1_QOS_TRAFFIC_CLASS_BACKGROUND:
default:
*qci = 9;
}
return OGS_OK;
}

51
lib/gtp/v1/conv.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#if !defined(OGS_GTP_INSIDE) && !defined(OGS_GTP_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_GTP1_CONV_H
#define OGS_GTP1_CONV_H
#ifdef __cplusplus
extern "C" {
#endif
int ogs_gtp1_gsn_addr_to_sockaddr(const ogs_gtp1_gsn_addr_t *gsnaddr,
uint16_t gsnaddr_len, uint16_t port, ogs_sockaddr_t **list);
int ogs_gtp1_sockaddr_to_gsn_addr(const ogs_sockaddr_t *addr,
const ogs_sockaddr_t *addr6, ogs_gtp1_gsn_addr_t *gsnaddr, int *len);
int ogs_gtp1_gsn_addr_to_ip(const ogs_gtp1_gsn_addr_t *gsnaddr, uint16_t gsnaddr_len,
ogs_ip_t *ip);
int ogs_gtp1_eua_to_ip(const ogs_eua_t *eua, uint16_t eua_len, ogs_ip_t *ip,
uint8_t *pdu_session_type);
int ogs_gtp1_ip_to_eua(uint8_t pdu_session_type, const ogs_ip_t *ip,
ogs_eua_t *eua, uint8_t *eua_len);
int ogs_gtp1_qos_profile_to_qci(const ogs_gtp1_qos_profile_decoded_t *decoded,
uint8_t *qci);
#ifdef __cplusplus
}
#endif
#endif

2769
lib/gtp/v1/message.c Normal file

File diff suppressed because it is too large Load Diff

1250
lib/gtp/v1/message.h Normal file

File diff suppressed because it is too large Load Diff

184
lib/gtp/v1/path.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#include "ogs-gtp.h"
ogs_pkbuf_t *ogs_gtp1_handle_echo_req(ogs_pkbuf_t *pkb)
{
ogs_gtp1_header_t *gtph = NULL;
ogs_pkbuf_t *pkb_resp = NULL;
ogs_gtp1_header_t *gtph_resp = NULL;
uint16_t length;
int idx;
ogs_assert(pkb);
gtph = (ogs_gtp1_header_t *)pkb->data;
/* Check GTP version. Now only support GTPv1(version = 1) */
if (gtph->version != 1) {
return NULL;
}
if (gtph->type != OGS_GTP1_ECHO_REQUEST_TYPE) {
return NULL;
}
pkb_resp = ogs_pkbuf_alloc(NULL,
100 /* enough for ECHO_RSP; use smaller buffer */);
ogs_expect_or_return_val(pkb_resp, NULL);
ogs_pkbuf_put(pkb_resp, 100);
gtph_resp = (ogs_gtp1_header_t *)pkb_resp->data;
/* reply back immediately */
gtph_resp->version = 1; /* set version */
gtph_resp->pt = 1; /* set PT */
gtph_resp->type = OGS_GTP1_ECHO_RESPONSE_TYPE;
length = 0; /* length of Recovery IE */
gtph_resp->length = htobe16(length); /* to be overwriten */
gtph_resp->teid = 0;
idx = 8;
if (gtph->e || gtph->s || gtph->pn) {
length += 4;
if (gtph->s) {
/* sequence exists */
gtph_resp->s = 1;
*((uint8_t *)pkb_resp->data + idx) = *((uint8_t *)pkb->data + idx);
*((uint8_t *)pkb_resp->data + idx + 1) =
*((uint8_t *)pkb->data + idx + 1);
} else {
*((uint8_t *)pkb_resp->data + idx) = 0;
*((uint8_t *)pkb_resp->data + idx + 1) = 0;
}
idx += 2;
if (gtph->pn) {
/* sequence exists */
gtph_resp->pn = 1;
*((uint8_t *)pkb_resp->data + idx) = *((uint8_t *)pkb->data + idx);
} else {
*((uint8_t *)pkb_resp->data + idx) = 0;
}
idx++;
*((uint8_t *)pkb_resp->data + idx) = 0; /* next-extension header */
idx++;
}
/* fill Recovery IE */
length += 2;
*((uint8_t *)pkb_resp->data + idx) = 14; idx++; /* type */
*((uint8_t *)pkb_resp->data + idx) = 0; idx++; /* restart counter */
gtph_resp->length = htobe16(length);
ogs_pkbuf_trim(pkb_resp, idx); /* buffer length */
return pkb_resp;
}
void ogs_gtp1_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value)
{
int rv;
ogs_gtp1_message_t errmsg;
ogs_gtp1_tlv_cause_t *tlv = NULL;
ogs_pkbuf_t *pkbuf = NULL;
memset(&errmsg, 0, sizeof(ogs_gtp1_message_t));
errmsg.h.type = type;
errmsg.h.teid = teid;
switch (type) {
case OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE:
tlv = &errmsg.create_pdp_context_response.cause;
break;
case OGS_GTP1_UPDATE_PDP_CONTEXT_RESPONSE_TYPE:
tlv = &errmsg.update_pdp_context_response.cause;
break;
case OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE:
tlv = &errmsg.delete_pdp_context_response.cause;
break;
default:
ogs_assert_if_reached();
return;
}
ogs_assert(tlv);
tlv->presence = 1;
tlv->u8 = cause_value;
pkbuf = ogs_gtp1_build_msg(&errmsg);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp1_xact_update_tx(xact, &errmsg.h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp1_send_echo_request(
ogs_gtp_node_t *gnode)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp1_header_t h;
ogs_gtp_xact_t *xact = NULL;
ogs_assert(gnode);
ogs_debug("[GTP] Sending Echo Request");
memset(&h, 0, sizeof(ogs_gtp1_header_t));
h.type = OGS_GTP1_ECHO_REQUEST_TYPE;
h.teid = 0;
pkbuf = ogs_gtp1_build_echo_request(h.type);
ogs_expect_or_return(pkbuf);
xact = ogs_gtp1_xact_local_create(gnode, &h, pkbuf, NULL, NULL);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp1_send_echo_response(ogs_gtp_xact_t *xact, uint8_t recovery)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp1_header_t h;
ogs_assert(xact);
ogs_debug("[GTP] Sending Echo Response");
memset(&h, 0, sizeof(ogs_gtp1_header_t));
h.type = OGS_GTP1_ECHO_RESPONSE_TYPE;
h.teid = 0;
pkbuf = ogs_gtp1_build_echo_response(h.type, recovery);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp1_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}

46
lib/gtp/v1/path.h Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* 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/>.
*/
#if !defined(OGS_GTP_INSIDE) && !defined(OGS_GTP_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_GTP1_PATH_H
#define OGS_GTP1_PATH_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ogs_gtp_xact_s ogs_gtp_xact_t;
ogs_pkbuf_t *ogs_gtp1_handle_echo_req(ogs_pkbuf_t *pkt);
void ogs_gtp1_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_gtp1_send_echo_request(ogs_gtp_node_t *gnode);
void ogs_gtp1_send_echo_response(ogs_gtp_xact_t *xact, uint8_t recovery);
#ifdef __cplusplus
}
#endif
#endif /* OGS_GTP1_PATH_H */

Binary file not shown.

View File

@ -0,0 +1,12 @@
* Install python-docx
user@host ~/Documents/git/open5gs/lib/gtp/v1/support$ \
sudo pip3 install python-docx
* Change the format of standard specification
from 29060-g00.doc to 29060-g00.docx
using Microsoft Office 2007+
* Generate TLV support files
user@host ~/Documents/git/open5gs/lib/gtp/v1/support$ \
python3 gtp1-tlv.py -f 29060-g00.docx -o ..

23
lib/gtp/v1/support/cache/tlv-msg-100.py vendored Normal file
View File

@ -0,0 +1,23 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Routeing Area Identity", "presence" : "Mandatory", "reference" : "7.7.3"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Selection mode", "presence" : "Conditional", "reference" : "7.7.12"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "Trace Reference", "presence" : "Optional", "reference" : "7.7.24"})
ies.append({ "ie_value" : "Trace Type", "presence" : "Optional", "reference" : "7.7.25"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "SGSN Address for signalling", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "MSISDN", "presence" : "Conditional", "reference" : "7.7.33"})
ies.append({ "ie_value" : "Trigger Id", "presence" : "Optional", "reference" : "7.7.41"})
ies.append({ "ie_value" : "OMC Identity", "presence" : "Optional", "reference" : "7.7.42"})
ies.append({ "ie_value" : "RAT Type", "presence" : "Optional", "reference" : "7.7.50"})
ies.append({ "ie_value" : "User Location Information", "presence" : "Optional", "reference" : "7.7.51"})
ies.append({ "ie_value" : "MS Time Zone", "presence" : "Optional", "reference" : "7.7.52"})
ies.append({ "ie_value" : "IMEI", "presence" : "Optional", "reference" : "7.7.53"})
ies.append({ "ie_value" : "MBMS Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.58"})
ies.append({ "ie_value" : "Additonal Trace Info", "presence" : "Optional", "reference" : "7.7.62"})
ies.append({ "ie_value" : "Enhanced NSAPI", "presence" : "Mandatory", "reference" : "7.7.67"})
ies.append({ "ie_value" : "Additional MBMS Trace Info", "presence" : "Optional", "reference" : "7.7.68"})
msg_list[key]["ies"] = ies

11
lib/gtp/v1/support/cache/tlv-msg-101.py vendored Normal file
View File

@ -0,0 +1,11 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "Charging ID", "presence" : "Conditional", "reference" : "7.7.26"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "Alternative Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "MBMS Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.58"})
msg_list[key]["ies"] = ies

17
lib/gtp/v1/support/cache/tlv-msg-102.py vendored Normal file
View File

@ -0,0 +1,17 @@
ies = []
ies.append({ "ie_value" : "Routeing Area Identity", "presence" : "Mandatory", "reference" : "7.7.3"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "Trace Reference", "presence" : "Optional", "reference" : "7.7.24"})
ies.append({ "ie_value" : "Trace Type", "presence" : "Optional", "reference" : "7.7.25"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative SGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Trigger Id", "presence" : "Optional", "reference" : "7.7.41"})
ies.append({ "ie_value" : "OMC Identity", "presence" : "Optional", "reference" : "7.7.42"})
ies.append({ "ie_value" : "RAT Type", "presence" : "Optional", "reference" : "7.7.50"})
ies.append({ "ie_value" : "User Location Information", "presence" : "Optional ", "reference" : "7.7.51"})
ies.append({ "ie_value" : "MS Time Zone", "presence" : "Optional", "reference" : "7.7.52"})
ies.append({ "ie_value" : "Additional Trace Info", "presence" : "Optional", "reference" : "7.7.62"})
ies.append({ "ie_value" : "Enhanced NSAPI", "presence" : "Mandatory", "reference" : "7.7.67"})
ies.append({ "ie_value" : "Additional MBMS Trace Info", "presence" : "Optional", "reference" : "7.7.68"})
msg_list[key]["ies"] = ies

10
lib/gtp/v1/support/cache/tlv-msg-103.py vendored Normal file
View File

@ -0,0 +1,10 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "Charging ID", "presence" : "Conditional", "reference" : "7.7.26"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "Alternative Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,4 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "MBMS Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.58"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative SGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Temporary Mobile Group Identity", "presence" : "Conditional", "reference" : "7.7.56"})
ies.append({ "ie_value" : "Required MBMS bearer capabilities", "presence" : "Conditional", "reference" : "7.7.76"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,4 @@
ies = []
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

19
lib/gtp/v1/support/cache/tlv-msg-116.py vendored Normal file
View File

@ -0,0 +1,19 @@
ies = []
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Quality of Service Profile", "presence" : "Mandatory", "reference" : "7.7.34"})
ies.append({ "ie_value" : "Common Flags", "presence" : "Mandatory", "reference" : "7.7.48"})
ies.append({ "ie_value" : "Temporary Mobile Group Identity", "presence" : "Mandatory", "reference" : "7.7.56"})
ies.append({ "ie_value" : "MBMS Service Area", "presence" : "Mandatory", "reference" : "7.7.60"})
ies.append({ "ie_value" : "MBMS Session Identifier", "presence" : "Optional", "reference" : "7.7.65"})
ies.append({ "ie_value" : "MBMS 2G/3G Indicator", "presence" : "Mandatory", "reference" : "7.7.66"})
ies.append({ "ie_value" : "MBMS Session Duration ", "presence" : "Mandatory ", "reference" : "7.7.59"})
ies.append({ "ie_value" : "MBMS Session Repetition Number", "presence" : "Optional", "reference" : "7.7.69"})
ies.append({ "ie_value" : "MBMS Time To Data Transfer", "presence" : "Mandatory", "reference" : "7.7.70"})
ies.append({ "ie_value" : "MBMS Flow Identifier", "presence" : "Optional", "reference" : "7.7.84"})
ies.append({ "ie_value" : "MBMS IP Multicast Distribution ", "presence" : "Optional", "reference" : "7.7.85"})
msg_list[key]["ies"] = ies

10
lib/gtp/v1/support/cache/tlv-msg-117.py vendored Normal file
View File

@ -0,0 +1,10 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data I", "presence" : "Conditional", "reference" : "7.7.13"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Address for user traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative SGSN Address for user traffic", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "MBMS Distribution Acknowledgement", "presence" : "Optional", "reference" : "7.7.86"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,5 @@
ies = []
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "MBMS Flow Identifier", "presence" : "Optional", "reference" : "7.7.84"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

12
lib/gtp/v1/support/cache/tlv-msg-120.py vendored Normal file
View File

@ -0,0 +1,12 @@
ies = []
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Optional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Temporary Mobile Group Identity", "presence" : "Mandatory", "reference" : "7.7.56"})
ies.append({ "ie_value" : "MBMS Session Duration", "presence" : "Mandatory", "reference" : "7.7.59"})
ies.append({ "ie_value" : "MBMS Service Area", "presence" : "Mandatory", "reference" : "7.7.60"})
ies.append({ "ie_value" : "MBMS Session Identifier", "presence" : "Optional", "reference" : "7.7.65"})
ies.append({ "ie_value" : "MBMS Session Repetition Number", "presence" : "Optional", "reference" : "7.7.69"})
ies.append({ "ie_value" : "MBMS Flow Identifier", "presence" : "Optional", "reference" : "7.7.84"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data I", "presence" : "Optional", "reference" : "7.7.13"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Optional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "SGSN Address for Data I", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

40
lib/gtp/v1/support/cache/tlv-msg-16.py vendored Normal file
View File

@ -0,0 +1,40 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Routeing Area Identity", "presence" : "Optional", "reference" : "7.7.3"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Selection mode", "presence" : "Conditional", "reference" : "7.7.12"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data I", "presence" : "Mandatory", "reference" : "7.7.13"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "NSAPI", "presence" : "Mandatory", "reference" : "7.7.17"})
ies.append({ "ie_value" : "Linked NSAPI", "presence" : "Conditional", "reference" : "7.7.17"})
ies.append({ "ie_value" : "Charging Characteristics", "presence" : "Conditional", "reference" : "7.7.23"})
ies.append({ "ie_value" : "Trace Reference", "presence" : "Optional", "reference" : "7.7.24"})
ies.append({ "ie_value" : "Trace Type", "presence" : "Optional", "reference" : "7.7.25"})
ies.append({ "ie_value" : "End User Address", "presence" : "Conditional", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Conditional", "reference" : "7.7.30"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "SGSN Address for signalling", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Address for user traffic", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "MSISDN", "presence" : "Conditional", "reference" : "7.7.33"})
ies.append({ "ie_value" : "Quality of Service Profile", "presence" : "Mandatory", "reference" : "7.7.34"})
ies.append({ "ie_value" : "TFT", "presence" : "Conditional", "reference" : "7.7.36"})
ies.append({ "ie_value" : "Trigger Id", "presence" : "Optional", "reference" : "7.7.41"})
ies.append({ "ie_value" : "OMC Identity", "presence" : "Optional", "reference" : "7.7.42"})
ies.append({ "ie_value" : "Common Flags", "presence" : "Optional", "reference" : "7.7.48"})
ies.append({ "ie_value" : "APN Restriction", "presence" : "Optional", "reference" : "7.7.49"})
ies.append({ "ie_value" : "RAT Type", "presence" : "Optional", "reference" : "7.7.50"})
ies.append({ "ie_value" : "User Location Information", "presence" : "Optional", "reference" : "7.7.51"})
ies.append({ "ie_value" : "MS Time Zone", "presence" : "Optional", "reference" : "7.7.52"})
ies.append({ "ie_value" : "IMEI", "presence" : "Conditional", "reference" : "7.7.53"})
ies.append({ "ie_value" : "CAMEL Charging Information Container", "presence" : "Optional", "reference" : "7.7.54"})
ies.append({ "ie_value" : "Additional Trace Info", "presence" : "Optional", "reference" : "7.7.62"})
ies.append({ "ie_value" : "Correlation-ID", "presence" : "Optional", "reference" : "7.7.82"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority I", "presence" : "Optional", "reference" : "7.7.91"})
ies.append({ "ie_value" : "Extended Common Flags", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "User CSG Information", "presence" : "Optional", "reference" : "7.7.94"})
ies.append({ "ie_value" : "APN-AMBR", "presence" : "Optional", "reference" : "7.7.98"})
ies.append({ "ie_value" : "Signalling Priority Indication", "presence" : "Optional", "reference" : "7.7.103"})
ies.append({ "ie_value" : "CN Operator Selection Entity", "presence" : "Optional", "reference" : "7.7.116"})
ies.append({ "ie_value" : "Mapped UE Usage Type", "presence" : "Optional", "reference" : "7.7.123"})
ies.append({ "ie_value" : "UP Function Selection Indication Flags", "presence" : "Optional", "reference" : "7.7.124"})
msg_list[key]["ies"] = ies

28
lib/gtp/v1/support/cache/tlv-msg-17.py vendored Normal file
View File

@ -0,0 +1,28 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Reordering required", "presence" : "Conditional", "reference" : "7.7.6"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data I", "presence" : "Conditional", "reference" : "7.7.13"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "NSAPI", "presence" : "Optional", "reference" : "7.7.17"})
ies.append({ "ie_value" : "Charging ID", "presence" : "Conditional", "reference" : "7.7.26"})
ies.append({ "ie_value" : "End User Address", "presence" : "Conditional", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "GGSN Address for user traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for user traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Quality of Service Profile", "presence" : "Conditional", "reference" : "7.7.34"})
ies.append({ "ie_value" : "Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "Alternative Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "Common Flags", "presence" : "Optional", "reference" : "7.7.48"})
ies.append({ "ie_value" : "APN Restriction", "presence" : "Optional", "reference" : "7.7.49"})
ies.append({ "ie_value" : "MS Info Change Reporting Action", "presence" : "Optional", "reference" : "7.7.80"})
ies.append({ "ie_value" : "Bearer Control Mode", "presence" : "Optional", "reference" : "7.7.83"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority I", "presence" : "Optional", "reference" : "7.7.91"})
ies.append({ "ie_value" : "Extended Common Flag", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "CSG Information Reporting Action", "presence" : "Optional", "reference" : "7.7.95"})
ies.append({ "ie_value" : "APN-AMBR", "presence" : "Optional", "reference" : "7.7.98"})
ies.append({ "ie_value" : "GGSN Back-Off Time", "presence" : "Optional", "reference" : "7.7.102"})
ies.append({ "ie_value" : "Extended Common Flags II", "presence" : "Optional", "reference" : "7.7.118"})
msg_list[key]["ies"] = ies

32
lib/gtp/v1/support/cache/tlv-msg-18.py vendored Normal file
View File

@ -0,0 +1,32 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Optional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Routeing Area Identity", "presence" : "Optional", "reference" : "7.7.3"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data I", "presence" : "Mandatory", "reference" : "7.7.13"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "NSAPI", "presence" : "Mandatory", "reference" : "7.7.17"})
ies.append({ "ie_value" : "Trace Reference", "presence" : "Optional", "reference" : "7.7.24"})
ies.append({ "ie_value" : "Trace Type", "presence" : "Optional", "reference" : "7.7.25"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Address for User Traffic", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative SGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative SGSN Address for User Traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Quality of Service Profile", "presence" : "Mandatory", "reference" : "7.7.34"})
ies.append({ "ie_value" : "TFT", "presence" : "Optional", "reference" : "7.7.36"})
ies.append({ "ie_value" : "Trigger Id", "presence" : "Optional", "reference" : "7.7.41"})
ies.append({ "ie_value" : "OMC Identity", "presence" : "Optional", "reference" : "7.7.42"})
ies.append({ "ie_value" : "Common Flags", "presence" : "Optional", "reference" : "7.7.48"})
ies.append({ "ie_value" : "RAT Type", "presence" : "Optional", "reference" : "7.7.50"})
ies.append({ "ie_value" : "User Location Information", "presence" : "Optional", "reference" : "7.7.51"})
ies.append({ "ie_value" : "MS Time Zone", "presence" : "Optional", "reference" : "7.7.52"})
ies.append({ "ie_value" : "Additonal Trace Info", "presence" : "Optional", "reference" : "7.7.62"})
ies.append({ "ie_value" : "Direct Tunnel Flags", "presence" : "Optional", "reference" : "7.7.81"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority I", "presence" : "Optional", "reference" : "7.7.91"})
ies.append({ "ie_value" : "Extended Common Flags", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "User CSG Information", "presence" : "Optional", "reference" : "7.7.94"})
ies.append({ "ie_value" : "APN-AMBR", "presence" : "Optional", "reference" : "7.7.98"})
ies.append({ "ie_value" : "Signalling Priority Indication", "presence" : "Optional", "reference" : "7.7.103"})
ies.append({ "ie_value" : "CN Operator Selection Entity", "presence" : "Optional", "reference" : "7.7.116"})
ies.append({ "ie_value" : "IMEI", "presence" : "Optional", "reference" : "7.7.53"})
msg_list[key]["ies"] = ies

22
lib/gtp/v1/support/cache/tlv-msg-19.py vendored Normal file
View File

@ -0,0 +1,22 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Recovery", "presence" : "Optional", "reference" : "7.7.11"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data I", "presence" : "Conditional", "reference" : "7.7.13"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "Charging ID", "presence" : "Conditional", "reference" : "7.7.26"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "GGSN Address for User Traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for User Traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Quality of Service Profile", "presence" : "Conditional", "reference" : "7.7.34"})
ies.append({ "ie_value" : "Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "Alternative Charging Gateway Address", "presence" : "Optional", "reference" : "7.7.44"})
ies.append({ "ie_value" : "Common Flags", "presence" : "Optional", "reference" : "7.7.48"})
ies.append({ "ie_value" : "APN Restriction", "presence" : "Optional", "reference" : "7.7.49"})
ies.append({ "ie_value" : "Bearer Control Mode", "presence" : "Optional", "reference" : "7.7.83"})
ies.append({ "ie_value" : "MS Info Change Reporting Action", "presence" : "Optional", "reference" : "7.7.80"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority I", "presence" : "Optional", "reference" : "7.7.91"})
ies.append({ "ie_value" : "CSG Information Reporting Action", "presence" : "Optional", "reference" : "7.7.95"})
ies.append({ "ie_value" : "APN-AMBR", "presence" : "Optional", "reference" : "7.7.98"})
msg_list[key]["ies"] = ies

3
lib/gtp/v1/support/cache/tlv-msg-2.py vendored Normal file
View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Recovery", "presence" : "Mandatory", "reference" : "7.7.11"})
msg_list[key]["ies"] = ies

10
lib/gtp/v1/support/cache/tlv-msg-20.py vendored Normal file
View File

@ -0,0 +1,10 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Optional", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Teardown Ind", "presence" : "Conditional", "reference" : "7.7.16"})
ies.append({ "ie_value" : "NSAPI", "presence" : "Mandatory", "reference" : "7.7.17"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "User Location Information", "presence" : "Optional", "reference" : "7.7.51"})
ies.append({ "ie_value" : "MS Time Zone", "presence" : "Optional", "reference" : "7.7.52"})
ies.append({ "ie_value" : "Extended Common Flags", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "ULI Timestamp", "presence" : "Optional", "reference" : "7.7.114"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "User Location Information", "presence" : "Optional", "reference" : "7.7.51"})
ies.append({ "ie_value" : "MS Time Zone", "presence" : "Optional", "reference" : "7.7.52"})
ies.append({ "ie_value" : "ULI Timestamp", "presence" : "Optional", "reference" : "7.7.114"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,8 @@
ies = []
ies.append({ "ie_value" : "Linked NSAPI", "presence" : "Mandatory", "reference" : "7.7.17"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "Quality of Service Profile", "presence" : "Mandatory", "reference" : "7.7.34"})
ies.append({ "ie_value" : "TFT", "presence" : "Conditional", "reference" : "7.7.36"})
ies.append({ "ie_value" : "Correlation-ID", "presence" : "Mandatory", "reference" : "7.7.82"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority I", "presence" : "Optional", "reference" : "7.7.91"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,4 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Conditional", "reference" : "7.7.31"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,8 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Mandatory", "reference" : "7.7.14"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Mandatory", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Mandatory", "reference" : "7.7.14"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.31"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Extension Header Type List", "presence" : "Mandatory", "reference" : "7.7.40"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
ies.append({ "ie_value" : "MAP Cause", "presence" : "Optional", "reference" : "7.7.8"})
ies.append({ "ie_value" : "MS not Reachable Reason", "presence" : "Optional", "reference" : "7.7.25A"})
ies.append({ "ie_value" : "GSN Address", "presence" : "Optional", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,4 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "MAP Cause", "presence" : "Optional", "reference" : "7.7.8"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,4 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
ies.append({ "ie_value" : "GSN Address", "presence" : "Mandatory", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Routeing Area Identity", "presence" : "Mandatory", "reference" : "7.7.3"})
ies.append({ "ie_value" : "Packet TMSI", "presence" : "Mandatory", "reference" : "7.7.5"})
ies.append({ "ie_value" : "P-TMSI Signature", "presence" : "Conditional", "reference" : "7.7.9"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Hop Counter", "presence" : "Optional", "reference" : "7.7.63"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,8 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Authentication Triplet", "presence" : "Conditional", "reference" : "7.7.7"})
ies.append({ "ie_value" : "Authentication Quintuplet", "presence" : "Conditional", "reference" : "7.7.35"})
ies.append({ "ie_value" : "UE Usage Type", "presence" : "Optional", "reference" : "7.7.117"})
ies.append({ "ie_value" : "IOV_updates counter", "presence" : "Optional", "reference" : "7.7.122"})
msg_list[key]["ies"] = ies

14
lib/gtp/v1/support/cache/tlv-msg-50.py vendored Normal file
View File

@ -0,0 +1,14 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Routeing Area Identity", "presence" : "Mandatory", "reference" : "7.7.3"})
ies.append({ "ie_value" : "Temporary Logical Link Identifier", "presence" : "Conditional", "reference" : "7.7.4"})
ies.append({ "ie_value" : "Packet TMSI", "presence" : "Conditional", "reference" : "7.7.5"})
ies.append({ "ie_value" : "P-TMSI Signature", "presence" : "Conditional", "reference" : "7.7.9"})
ies.append({ "ie_value" : "MS Validated", "presence" : "Optional", "reference" : "7.7.10"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Mandatory", "reference" : "7.7.14"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative SGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Number", "presence" : "Optional", "reference" : "7.7.47"})
ies.append({ "ie_value" : "RAT Type", "presence" : "Optional", "reference" : "7.7.50"})
ies.append({ "ie_value" : "Hop Counter", "presence" : "Optional", "reference" : "7.7.63"})
msg_list[key]["ies"] = ies

34
lib/gtp/v1/support/cache/tlv-msg-51.py vendored Normal file
View File

@ -0,0 +1,34 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "RAB Context", "presence" : "Conditional", "reference" : "7.7.19"})
ies.append({ "ie_value" : "Radio Priority SMS", "presence" : "Optional", "reference" : "7.7.20"})
ies.append({ "ie_value" : "Radio Priority", "presence" : "Optional", "reference" : "7.7.21"})
ies.append({ "ie_value" : "Packet Flow Id", "presence" : "Optional", "reference" : "7.7.22"})
ies.append({ "ie_value" : "Charging Characteristics", "presence" : "Optional", "reference" : "7.7.23"})
ies.append({ "ie_value" : "Radio Priority LCS", "presence" : "Optional", "reference" : "7.7.25B"})
ies.append({ "ie_value" : "MM Context", "presence" : "Conditional", "reference" : "7.7.28"})
ies.append({ "ie_value" : "PDP Context", "presence" : "Conditional", "reference" : "7.7.29"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "PDP Context Prioritization ", "presence" : "Optional", "reference" : "7.7.45"})
ies.append({ "ie_value" : "MBMS UE Context", "presence" : "Optional", "reference" : "7.7.55"})
ies.append({ "ie_value" : "Subscribed RFSP Index", "presence" : "Optional", "reference" : "7.7.88"})
ies.append({ "ie_value" : "RFSP Index in use", "presence" : "Optional", "reference" : "7.7.88"})
ies.append({ "ie_value" : "Co-located GGSN-PGW FQDN", "presence" : "Optional", "reference" : "7.7.90"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority II", "presence" : "Optional", "reference" : "7.7.92"})
ies.append({ "ie_value" : "Extended Common Flags", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "UE Network Capability", "presence" : "Optional", "reference" : "7.7.99"})
ies.append({ "ie_value" : "UE-AMBR", "presence" : "Optional", "reference" : "7.7.100"})
ies.append({ "ie_value" : "APN-AMBR with NSAPI", "presence" : "Optional", "reference" : "7.7.101"})
ies.append({ "ie_value" : "Signalling Priority Indication with NSAPI", "presence" : "Optional", "reference" : "7.7.104"})
ies.append({ "ie_value" : "Higher bitrates than 16 Mbps flag", "presence" : "Optional", "reference" : "7.7.105"})
ies.append({ "ie_value" : "Selection Mode with NSAPI", "presence" : "Optional", "reference" : "7.7.113"})
ies.append({ "ie_value" : "Local Home Network ID with NSAPI", "presence" : "Optional", "reference" : "7.7.115"})
ies.append({ "ie_value" : "UE Usage Type", "presence" : "Optional", "reference" : "7.7.117"})
ies.append({ "ie_value" : "Extended Common Flags II", "presence" : "Optional", "reference" : "7.7.118"})
ies.append({ "ie_value" : "UE SCEF PDN Connection", "presence" : "Optional", "reference" : "7.7.121"})
ies.append({ "ie_value" : "IOV_updates counter", "presence" : "Optional", "reference" : "7.7.122"})
ies.append({ "ie_value" : "Alternative GGSN Address for control Plane", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for user traffic", "presence" : "Optional", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,7 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data II", "presence" : "Conditional", "reference" : "7.7.15"})
ies.append({ "ie_value" : "SGSN Address for user traffic", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Number", "presence" : "Optional", "reference" : "7.7.47"})
ies.append({ "ie_value" : "Node Identifier", "presence" : "Optional", "reference" : "7.7.119"})
msg_list[key]["ies"] = ies

45
lib/gtp/v1/support/cache/tlv-msg-53.py vendored Normal file
View File

@ -0,0 +1,45 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Mandatory", "reference" : "7.7.14"})
ies.append({ "ie_value" : "RANAP Cause", "presence" : "Mandatory", "reference" : "7.7.18"})
ies.append({ "ie_value" : "Packet Flow ID", "presence" : "Optional", "reference" : "7.7.22"})
ies.append({ "ie_value" : "Charging Characteristics", "presence" : "Optional", "reference" : "7.7.23"})
ies.append({ "ie_value" : "MM Context", "presence" : "Mandatory", "reference" : "7.7.28"})
ies.append({ "ie_value" : "PDP Context", "presence" : "Conditional", "reference" : "7.7.29"})
ies.append({ "ie_value" : "SGSN Address for Control plane", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Target Identification", "presence" : "Mandatory", "reference" : "7.7.37"})
ies.append({ "ie_value" : "UTRAN transparent container", "presence" : "Mandatory", "reference" : "7.7.38"})
ies.append({ "ie_value" : "PDP Context Prioritization ", "presence" : "Optional", "reference" : "7.7.45"})
ies.append({ "ie_value" : "MBMS UE Context", "presence" : "Optional", "reference" : "7.7.55"})
ies.append({ "ie_value" : "Selected PLMN ID", "presence" : "Optional", "reference" : "7.7.64"})
ies.append({ "ie_value" : "BSS Container", "presence" : "Optional", "reference" : "7.7.72"})
ies.append({ "ie_value" : "Cell Identification ", "presence" : "Optional ", "reference" : "7.7.73"})
ies.append({ "ie_value" : "BSSGP Cause", "presence" : "Optional ", "reference" : "7.7.75"})
ies.append({ "ie_value" : "PS Handover XID Parameters", "presence" : "Optional", "reference" : "7.7.79"})
ies.append({ "ie_value" : "Direct Tunnel Flags", "presence" : "Optional", "reference" : "7.7.81"})
ies.append({ "ie_value" : "Reliable INTER RAT HANDOVER INFO", "presence" : "Optional", "reference" : "7.7.87"})
ies.append({ "ie_value" : "Subscribed RFSP Index", "presence" : "Optional", "reference" : "7.7.88"})
ies.append({ "ie_value" : "RFSP Index in use", "presence" : "Optional", "reference" : "7.7.88"})
ies.append({ "ie_value" : "Co-located GGSN-PGW FQDN", "presence" : "Optional", "reference" : "7.7.90"})
ies.append({ "ie_value" : "Evolved Allocation/Retention Priority II", "presence" : "Optional", "reference" : "7.7.92"})
ies.append({ "ie_value" : "Extended Common Flags", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "CSG ID", "presence" : "Optional", "reference" : "7.7.96"})
ies.append({ "ie_value" : "CSG Membership Indication", "presence" : "Optional", "reference" : "7.7.97"})
ies.append({ "ie_value" : "UE Network Capability", "presence" : "Optional", "reference" : "7.7.99"})
ies.append({ "ie_value" : "UE-AMBR", "presence" : "Optional", "reference" : "7.7.100"})
ies.append({ "ie_value" : "APN-AMBR with NSAPI", "presence" : "Optional", "reference" : "7.7.101"})
ies.append({ "ie_value" : "Signalling Priority Indication with NSAPI", "presence" : "Optional", "reference" : "7.7.104"})
ies.append({ "ie_value" : "Higher bitrates than 16 Mbps flag", "presence" : "Optional", "reference" : "7.7.105"})
ies.append({ "ie_value" : "Additional MM context for SRVCC", "presence" : "Optional", "reference" : "7.7.107"})
ies.append({ "ie_value" : "Additional flags for SRVCC", "presence" : "Optional", "reference" : "7.7.108"})
ies.append({ "ie_value" : "STN-SR", "presence" : "Optional", "reference" : "7.7.109"})
ies.append({ "ie_value" : "C-MSISDN", "presence" : "Optional", "reference" : "7.7.110"})
ies.append({ "ie_value" : "Extended RANAP Cause", "presence" : "Optional", "reference" : "7.7.111"})
ies.append({ "ie_value" : "eNodeB ID", "presence" : "Optional", "reference" : "7.7.112"})
ies.append({ "ie_value" : "Selection Mode with NSAPI", "presence" : "Optional", "reference" : "7.7.113"})
ies.append({ "ie_value" : "UE Usage Type", "presence" : "Optional", "reference" : "7.7.117"})
ies.append({ "ie_value" : "Extended Common Flags II", "presence" : "Optional", "reference" : "7.7.118"})
ies.append({ "ie_value" : "UE SCEF PDN Connection", "presence" : "Optional", "reference" : "7.7.121"})
ies.append({ "ie_value" : "Alternative GGSN Address for control Plane", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "Alternative GGSN Address for user traffic", "presence" : "Optional", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

17
lib/gtp/v1/support/cache/tlv-msg-54.py vendored Normal file
View File

@ -0,0 +1,17 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Conditional", "reference" : "7.7.14"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Data II", "presence" : "Optional ", "reference" : "7.7.15"})
ies.append({ "ie_value" : "RANAP Cause", "presence" : "Conditional", "reference" : "7.7.18"})
ies.append({ "ie_value" : "SGSN Address for Control plane", "presence" : "Conditional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "SGSN Address for User Traffic", "presence" : "Optional", "reference" : "7.7.32"})
ies.append({ "ie_value" : "UTRAN transparent container", "presence" : "Optional", "reference" : "7.7.38"})
ies.append({ "ie_value" : "RAB Setup Information", "presence" : "Conditional", "reference" : "7.7.39"})
ies.append({ "ie_value" : "Additional RAB Setup Information", "presence" : "Conditional", "reference" : "7.7.45A"})
ies.append({ "ie_value" : "SGSN Number", "presence" : "Optional", "reference" : "7.7.47"})
ies.append({ "ie_value" : "BSS Container", "presence" : "Optional", "reference" : "7.7.72"})
ies.append({ "ie_value" : "BSSGP Cause", "presence" : "Optional ", "reference" : "7.7.75"})
ies.append({ "ie_value" : "List of set-up PFCs", "presence" : "Optional", "reference" : "7.7.78"})
ies.append({ "ie_value" : "Extended RANAP Cause", "presence" : "Optional", "reference" : "7.7.111"})
ies.append({ "ie_value" : "Node Identfiier", "presence" : "Optional", "reference" : "7.7.119"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,2 @@
ies = []
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,6 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Conditional", "reference" : "7.7.2"})
ies.append({ "ie_value" : "IMEI", "presence" : "Conditional", "reference" : "7.7.53"})
ies.append({ "ie_value" : "Extended Common Flags", "presence" : "Optional", "reference" : "7.7.93"})
ies.append({ "ie_value" : "Extended RANAP Cause", "presence" : "Optional", "reference" : "7.7.111"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,5 @@
ies = []
ies.append({ "ie_value" : "RAB Context", "presence" : "Mandatory", "reference" : "7.7.19"})
ies.append({ "ie_value" : "Source RNC PDCP context info", "presence" : "Optional", "reference" : "7.7.61"})
ies.append({ "ie_value" : "PDU Numbers", "presence" : "Optional", "reference" : "7.7.74"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,5 @@
ies = []
ies.append({ "ie_value" : "Cause ", "presence" : "Mandatory ", "reference" : "7.7.1"})
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Selected PLMN ID", "presence" : "Conditional", "reference" : "7.7.64"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,5 @@
ies = []
ies.append({ "ie_value" : "RAN Transparent Container", "presence" : "Mandatory", "reference" : "7.7.43"})
ies.append({ "ie_value" : "RIM Routing Address", "presence" : "Optional", "reference" : "7.7.57"})
ies.append({ "ie_value" : "RIM Routing Address Discriminator", "presence" : "Optional", "reference" : "7.7.77"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,9 @@
ies = []
ies.append({ "ie_value" : "IMSI", "presence" : "Mandatory", "reference" : "7.7.2"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Mandatory", "reference" : "7.7.14"})
ies.append({ "ie_value" : "NSAPI", "presence" : "Mandatory", "reference" : "7.7.17"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "GGSN Address for Control Plane", "presence" : "Mandatory", "reference" : "7.7.32"})
ies.append({ "ie_value" : "MBMS Protocol Configuration Options", "presence" : "Optional", "reference" : "7.7.58"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,8 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
ies.append({ "ie_value" : "Tunnel Endpoint Identifier Control Plane", "presence" : "Mandatory", "reference" : "7.7.14"})
ies.append({ "ie_value" : "NSAPI", "presence" : "Mandatory", "reference" : "7.7.17"})
ies.append({ "ie_value" : "End User Address", "presence" : "Mandatory", "reference" : "7.7.27"})
ies.append({ "ie_value" : "Access Point Name", "presence" : "Mandatory", "reference" : "7.7.30"})
ies.append({ "ie_value" : "SGSN Address for Control Plane", "presence" : "Optional", "reference" : "7.7.32"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,3 @@
ies = []
ies.append({ "ie_value" : "Cause", "presence" : "Mandatory", "reference" : "7.7.1"})
msg_list[key]["ies"] = ies

View File

@ -0,0 +1,64 @@
# [Table 1: Messages in GTP] Index = 11
msg_list["Echo Request"] = { "type" : "1" }
msg_list["Echo Response"] = { "type" : "2" }
msg_list["Version Not Supported"] = { "type" : "3" }
msg_list["Node Alive Request"] = { "type" : "4" }
msg_list["Node Alive Response"] = { "type" : "5" }
msg_list["Redirection Request"] = { "type" : "6" }
msg_list["Redirection Response"] = { "type" : "7" }
msg_list["Create PDP Context Request"] = { "type" : "16" }
msg_list["Create PDP Context Response"] = { "type" : "17" }
msg_list["Update PDP Context Request"] = { "type" : "18" }
msg_list["Update PDP Context Response"] = { "type" : "19" }
msg_list["Delete PDP Context Request"] = { "type" : "20" }
msg_list["Delete PDP Context Response"] = { "type" : "21" }
msg_list["Initiate PDP Context Activation Request"] = { "type" : "22" }
msg_list["Initiate PDP Context Activation Response"] = { "type" : "23" }
msg_list["Error Indication"] = { "type" : "26" }
msg_list["PDU Notification Request"] = { "type" : "27" }
msg_list["PDU Notification Response"] = { "type" : "28" }
msg_list["PDU Notification Reject Request"] = { "type" : "29" }
msg_list["PDU Notification Reject Response"] = { "type" : "30" }
msg_list["Supported Extension Headers Notification"] = { "type" : "31" }
msg_list["Send Routeing Information for GPRS Request"] = { "type" : "32" }
msg_list["Send Routeing Information for GPRS Response"] = { "type" : "33" }
msg_list["Failure Report Request"] = { "type" : "34" }
msg_list["Failure Report Response"] = { "type" : "35" }
msg_list["Note MS GPRS Present Request"] = { "type" : "36" }
msg_list["Note MS GPRS Present Response"] = { "type" : "37" }
msg_list["Identification Request"] = { "type" : "48" }
msg_list["Identification Response"] = { "type" : "49" }
msg_list["SGSN Context Request"] = { "type" : "50" }
msg_list["SGSN Context Response"] = { "type" : "51" }
msg_list["SGSN Context Acknowledge"] = { "type" : "52" }
msg_list["Forward Relocation Request"] = { "type" : "53" }
msg_list["Forward Relocation Response"] = { "type" : "54" }
msg_list["Forward Relocation Complete"] = { "type" : "55" }
msg_list["Relocation Cancel Request"] = { "type" : "56" }
msg_list["Relocation Cancel Response"] = { "type" : "57" }
msg_list["Forward SRNS Context"] = { "type" : "58" }
msg_list["Forward Relocation Complete Acknowledge"] = { "type" : "59" }
msg_list["Forward SRNS Context Acknowledge"] = { "type" : "60" }
msg_list["UE Registration Query Request"] = { "type" : "61" }
msg_list["UE Registration Query Response"] = { "type" : "62" }
msg_list["RAN Information Relay"] = { "type" : "70" }
msg_list["MBMS Notification Request"] = { "type" : "96" }
msg_list["MBMS Notification Response"] = { "type" : "97" }
msg_list["MBMS Notification Reject Request"] = { "type" : "98" }
msg_list["MBMS Notification Reject Response"] = { "type" : "99" }
msg_list["Create MBMS Context Request"] = { "type" : "100" }
msg_list["Create MBMS Context Response"] = { "type" : "101" }
msg_list["Update MBMS Context Request"] = { "type" : "102" }
msg_list["Update MBMS Context Response"] = { "type" : "103" }
msg_list["Delete MBMS Context Request"] = { "type" : "104" }
msg_list["Delete MBMS Context Response"] = { "type" : "105" }
msg_list["MBMS Registration Request"] = { "type" : "112" }
msg_list["MBMS Registration Response"] = { "type" : "113" }
msg_list["MBMS De-Registration Request"] = { "type" : "114" }
msg_list["MBMS De-Registration Response"] = { "type" : "115" }
msg_list["MBMS Session Start Request"] = { "type" : "116" }
msg_list["MBMS Session Start Response"] = { "type" : "117" }
msg_list["MBMS Session Stop Request"] = { "type" : "118" }
msg_list["MBMS Session Stop Response"] = { "type" : "119" }
msg_list["MBMS Session Update Request"] = { "type" : "120" }
msg_list["MBMS Session Update Response"] = { "type" : "121" }

View File

@ -0,0 +1,125 @@
# [Table 37: Information Elements] Index = 73
type_list["Cause"] = { "type" : "1", "reference" : "7.7.1", "format" : "TV", "size" : 1 }
type_list["IMSI"] = { "type" : "2", "reference" : "7.7.2", "format" : "TV", "size" : 8 }
type_list["RAI"] = { "type" : "3", "reference" : "7.7.3", "format" : "TV", "size" : 6 }
type_list["TLLI"] = { "type" : "4", "reference" : "7.7.4", "format" : "TV", "size" : 4 }
type_list["P-TMSI"] = { "type" : "5", "reference" : "7.7.5", "format" : "TV", "size" : 4 }
type_list["Reordering Required"] = { "type" : "8", "reference" : "7.7.6", "format" : "TV", "size" : 1 }
type_list["Authentication Triplet"] = { "type" : "9", "reference" : "7.7.7", "format" : "TV", "size" : 28 }
type_list["MAP Cause"] = { "type" : "11", "reference" : "7.7.8", "format" : "TV", "size" : 1 }
type_list["P-TMSI Signature"] = { "type" : "12", "reference" : "7.7.9", "format" : "TV", "size" : 3 }
type_list["MS Validated"] = { "type" : "13", "reference" : "7.7.10", "format" : "TV", "size" : 1 }
type_list["Recovery"] = { "type" : "14", "reference" : "7.7.11", "format" : "TV", "size" : 1 }
type_list["Selection Mode"] = { "type" : "15", "reference" : "7.7.12", "format" : "TV", "size" : 1 }
type_list["Tunnel Endpoint Identifier Data I"] = { "type" : "16", "reference" : "7.7.13", "format" : "TV", "size" : 4 }
type_list["Tunnel Endpoint Identifier Control Plane"] = { "type" : "17", "reference" : "7.7.14", "format" : "TV", "size" : 4 }
type_list["Tunnel Endpoint Identifier Data II"] = { "type" : "18", "reference" : "7.7.15", "format" : "TV", "size" : 5 }
type_list["Teardown Ind"] = { "type" : "19", "reference" : "7.7.16", "format" : "TV", "size" : 1 }
type_list["NSAPI"] = { "type" : "20", "reference" : "7.7.17", "format" : "TV", "size" : 1 }
type_list["RANAP Cause"] = { "type" : "21", "reference" : "7.7.18", "format" : "TV", "size" : 1 }
type_list["RAB Context"] = { "type" : "22", "reference" : "7.7.19", "format" : "TV", "size" : 9 }
type_list["Radio Priority SMS"] = { "type" : "23", "reference" : "7.7.20", "format" : "TV", "size" : 1 }
type_list["Radio Priority"] = { "type" : "24", "reference" : "7.7.21", "format" : "TV", "size" : 1 }
type_list["Packet Flow Id"] = { "type" : "25", "reference" : "7.7.22", "format" : "TV", "size" : 2 }
type_list["Charging Characteristics"] = { "type" : "26", "reference" : "7.7.23", "format" : "TV", "size" : 2 }
type_list["Trace Reference"] = { "type" : "27", "reference" : "7.7.24", "format" : "TV", "size" : 2 }
type_list["Trace Type"] = { "type" : "28", "reference" : "7.7.25", "format" : "TV", "size" : 2 }
type_list["MS Not Reachable Reason"] = { "type" : "29", "reference" : "7.7.25A", "format" : "TV", "size" : 1 }
type_list["Charging ID"] = { "type" : "127", "reference" : "7.7.26", "format" : "TV", "size" : 4 }
type_list["End User Address"] = { "type" : "128", "reference" : "7.7.27", "format" : "TLV" }
type_list["MM Context"] = { "type" : "129", "reference" : "7.7.28", "format" : "TLV" }
type_list["PDP Context"] = { "type" : "130", "reference" : "7.7.29", "format" : "TLV" }
type_list["Access Point Name"] = { "type" : "131", "reference" : "7.7.30", "format" : "TLV" }
type_list["Protocol Configuration Options"] = { "type" : "132", "reference" : "7.7.31", "format" : "TLV" }
type_list["GSN Address"] = { "type" : "133", "reference" : "7.7.32", "format" : "TLV" }
type_list["MSISDN"] = { "type" : "134", "reference" : "7.7.33", "format" : "TLV" }
type_list["Quality of Service Profile"] = { "type" : "135", "reference" : "7.7.34", "format" : "TLV" }
type_list["Authentication Quintuplet"] = { "type" : "136", "reference" : "7.7.35", "format" : "TLV" }
type_list["Traffic Flow Template"] = { "type" : "137", "reference" : "7.7.36", "format" : "TLV" }
type_list["Target Identification"] = { "type" : "138", "reference" : "7.7.37", "format" : "TLV" }
type_list["UTRAN Transparent Container"] = { "type" : "139", "reference" : "7.7.38", "format" : "TLV" }
type_list["RAB Setup Information"] = { "type" : "140", "reference" : "7.7.39", "format" : "TLV" }
type_list["Extension Header Type List"] = { "type" : "141", "reference" : "7.7.40", "format" : "TLV" }
type_list["Trigger Id"] = { "type" : "142", "reference" : "7.7.41", "format" : "TLV" }
type_list["OMC Identity"] = { "type" : "143", "reference" : "7.7.42", "format" : "TLV" }
type_list["RAN Transparent Container"] = { "type" : "144", "reference" : "7.7.43", "format" : "TLV" }
type_list["PDP Context Prioritization"] = { "type" : "145", "reference" : "7.7.45", "format" : "TLV", "size" : 0 }
type_list["Additional RAB Setup Information"] = { "type" : "146", "reference" : "7.7.45A", "format" : "TLV" }
type_list["SGSN Number"] = { "type" : "147", "reference" : "7.7.47", "format" : "TLV" }
type_list["Common Flags"] = { "type" : "148", "reference" : "7.7.48", "format" : "TLV", "size" : 1 }
type_list["APN Restriction"] = { "type" : "149", "reference" : "7.7.49", "format" : "TLV", "size" : 1 }
type_list["Radio Priority LCS"] = { "type" : "150", "reference" : "7.7.25B", "format" : "TLV", "size" : 1 }
type_list["RAT Type"] = { "type" : "151", "reference" : "7.7.50", "format" : "TLV", "size" : 1 }
type_list["User Location Information"] = { "type" : "152", "reference" : "7.7.51", "format" : "TLV" }
type_list["MS Time Zone"] = { "type" : "153", "reference" : "7.7.52", "format" : "TLV", "size" : 1 }
type_list["SV"] = { "type" : "154", "reference" : "7.7.53", "format" : "TLV", "size" : 8 }
type_list["CAMEL Charging Information Container"] = { "type" : "155", "reference" : "7.7.54", "format" : "TLV" }
type_list["MBMS UE Context"] = { "type" : "156", "reference" : "7.7.55", "format" : "TLV" }
type_list["TMGI"] = { "type" : "157", "reference" : "7.7.56", "format" : "TLV", "size" : 6 }
type_list["RIM Routing Address"] = { "type" : "158", "reference" : "7.7.57", "format" : "TLV" }
type_list["MBMS Protocol Configuration Options"] = { "type" : "159", "reference" : "7.7.58", "format" : "TLV" }
type_list["MBMS Service Area"] = { "type" : "160", "reference" : "7.7.60", "format" : "TLV" }
type_list["Source RNC PDCP context info"] = { "type" : "161", "reference" : "7.7.61", "format" : "TLV" }
type_list["Additional Trace Info"] = { "type" : "162", "reference" : "7.7.62", "format" : "TLV", "size" : 9 }
type_list["Hop Counter"] = { "type" : "163", "reference" : "7.7.63", "format" : "TLV", "size" : 1 }
type_list["Selected PLMN ID"] = { "type" : "164", "reference" : "7.7.64", "format" : "TLV", "size" : 3 }
type_list["MBMS Session Identifier"] = { "type" : "165", "reference" : "7.7.65", "format" : "TLV", "size" : 1 }
type_list["MBMS 2G/3G Indicator"] = { "type" : "166", "reference" : "7.7.66", "format" : "TLV", "size" : 1 }
type_list["Enhanced NSAPI"] = { "type" : "167", "reference" : "7.7.67", "format" : "TLV", "size" : 1 }
type_list["MBMS Session Duration"] = { "type" : "168", "reference" : "7.7.59", "format" : "TLV", "size" : 3 }
type_list["Additional MBMS Trace Info"] = { "type" : "169", "reference" : "7.7.68", "format" : "TLV", "size" : 8 }
type_list["MBMS Session Repetition Number"] = { "type" : "170", "reference" : "7.7.69", "format" : "TLV", "size" : 1 }
type_list["MBMS Time To Data Transfer"] = { "type" : "171", "reference" : "7.7.70", "format" : "TLV", "size" : 1 }
type_list["BSS Container"] = { "type" : "173", "reference" : "7.7.72", "format" : "TLV" }
type_list["Cell Identification"] = { "type" : "174", "reference" : "7.7.73", "format" : "TLV", "size" : 17 }
type_list["PDU Numbers"] = { "type" : "175", "reference" : "7.7.74", "format" : "TLV", "size" : 9 }
type_list["BSSGP Cause"] = { "type" : "176", "reference" : "7.7.75", "format" : "TLV", "size" : 1 }
type_list["Required MBMS bearer capabilities"] = { "type" : "177", "reference" : "7.7.76", "format" : "TLV" }
type_list["RIM Routing Address Discriminator"] = { "type" : "178", "reference" : "7.7.77", "format" : "TLV", "size" : 1 }
type_list["List of set-up PFCs"] = { "type" : "179", "reference" : "7.7.78", "format" : "TLV" }
type_list["PS Handover XID Parameters"] = { "type" : "180", "reference" : "7.7.79", "format" : "TLV" }
type_list["MS Info Change Reporting Action"] = { "type" : "181", "reference" : "7.7.80", "format" : "TLV", "size" : 1 }
type_list["Direct Tunnel Flags"] = { "type" : "182", "reference" : "7.7.81", "format" : "TLV" }
type_list["Correlation-ID"] = { "type" : "183", "reference" : "7.7.82", "format" : "TLV", "size" : 1 }
type_list["Bearer Control Mode"] = { "type" : "184", "reference" : "7.7.83", "format" : "TLV", "size" : 1 }
type_list["MBMS Flow Identifier"] = { "type" : "185", "reference" : "7.7.84", "format" : "TLV" }
type_list["MBMS IP Multicast Distribution"] = { "type" : "186", "reference" : "7.7.85", "format" : "TLV" }
type_list["MBMS Distribution Acknowledgement"] = { "type" : "187", "reference" : "7.7.86", "format" : "TLV", "size" : 1 }
type_list["Reliable INTER RAT HANDOVER INFO"] = { "type" : "188", "reference" : "7.7.87", "format" : "TLV", "size" : 1 }
type_list["RFSP Index"] = { "type" : "189", "reference" : "7.7.88", "format" : "TLV", "size" : 2 }
type_list["FQDN"] = { "type" : "190", "reference" : "7.7.90", "format" : "TLV" }
type_list["Evolved Allocation/Retention Priority I"] = { "type" : "191", "reference" : "7.7.91", "format" : "TLV", "size" : 1 }
type_list["Evolved Allocation/Retention Priority II"] = { "type" : "192", "reference" : "7.7.92", "format" : "TLV", "size" : 2 }
type_list["Extended Common Flags"] = { "type" : "193", "reference" : "7.7.93", "format" : "TLV" }
type_list["UCI"] = { "type" : "194", "reference" : "7.7.94", "format" : "TLV", "size" : 8 }
type_list["CSG Information Reporting Action"] = { "type" : "195", "reference" : "7.7.95", "format" : "TLV" }
type_list["CSG ID"] = { "type" : "196", "reference" : "7.7.96", "format" : "TLV", "size" : 4 }
type_list["CMI"] = { "type" : "197", "reference" : "7.7.97", "format" : "TLV", "size" : 1 }
type_list["AMBR"] = { "type" : "198", "reference" : "7.7.98", "format" : "TLV", "size" : 8 }
type_list["UE Network Capability"] = { "type" : "199", "reference" : "7.7.99", "format" : "TLV" }
type_list["UE-AMBR"] = { "type" : "200", "reference" : "7.7.100", "format" : "TLV" }
type_list["APN-AMBR with NSAPI"] = { "type" : "201", "reference" : "7.7.101", "format" : "TLV", "size" : 9 }
type_list["GGSN Back-Off Time"] = { "type" : "202", "reference" : "7.7.102", "format" : "TLV" }
type_list["Signalling Priority Indication"] = { "type" : "203", "reference" : "7.7.103", "format" : "TLV" }
type_list["Signalling Priority Indication with NSAPI"] = { "type" : "204", "reference" : "7.7.104", "format" : "TLV" }
type_list["Higher bitrates than 16 Mbps flag"] = { "type" : "205", "reference" : "7.7.105", "format" : "TLV", "size" : 1 }
type_list["Additional MM context for SRVCC"] = { "type" : "207", "reference" : "7.7.107", "format" : "TLV" }
type_list["Additional flags for SRVCC"] = { "type" : "208", "reference" : "7.7.108", "format" : "TLV" }
type_list["STN-SR"] = { "type" : "209", "reference" : "7.7.109", "format" : "TLV" }
type_list["C-MSISDN"] = { "type" : "210", "reference" : "7.7.110", "format" : "TLV" }
type_list["Extended RANAP Cause"] = { "type" : "211", "reference" : "7.7.111", "format" : "TLV" }
type_list["eNodeB ID"] = { "type" : "212", "reference" : "7.7.112", "format" : "TLV" }
type_list["Selection Mode with NSAPI"] = { "type" : "213", "reference" : "7.7.113", "format" : "TLV", "size" : 2 }
type_list["ULI Timestamp"] = { "type" : "214", "reference" : "7.7.114", "format" : "TLV" }
type_list["LHN-ID with NSAPI"] = { "type" : "215", "reference" : "7.7.115", "format" : "TLV" }
type_list["CN Operator Selection Entity"] = { "type" : "216", "reference" : "7.7.116", "format" : "TLV" }
type_list["UE Usage Type"] = { "type" : "217", "reference" : "7.7.117", "format" : "TLV" }
type_list["Extended Common Flags II"] = { "type" : "218", "reference" : "7.7.118", "format" : "TLV" }
type_list["Node Identifier"] = { "type" : "219", "reference" : "7.7.119", "format" : "TLV" }
type_list["CIoT Optimizations Support Indication"] = { "type" : "220", "reference" : "7.7.120", "format" : "TLV" }
type_list["SCEF PDN Connection"] = { "type" : "221", "reference" : "7.7.121", "format" : "TLV" }
type_list["IOV_updates counter"] = { "type" : "222", "reference" : "7.7.122", "format" : "TLV", "size" : 1 }
type_list["Mapped UE Usage Type"] = { "type" : "223", "reference" : "7.7.123", "format" : "TLV" }
type_list["UP Function Selection Indication Flags"] = { "type" : "224", "reference" : "7.7.124", "format" : "TLV" }
type_list["Special IE type for IE Type Extension"] = { "type" : "238", "reference" : "See NOTE3", "format" : "TLV" }
type_list["Charging Gateway Address"] = { "type" : "251", "reference" : "7.7.44", "format" : "TLV" }

View File

@ -0,0 +1,667 @@
# Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
# Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
# 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/>.
from docx import Document
from docx.document import Document as _Document
from docx.oxml.text.paragraph import CT_P
from docx.oxml.table import CT_Tbl
from docx.table import _Cell, Table
from docx.text.paragraph import Paragraph
import re, os, sys, string
import datetime
import getopt
import getpass
version = "0.1.0"
msg_list = {}
type_list = {}
verbosity = 0
filename = ""
outdir = './'
cachedir = './cache/'
FAIL = '\033[91m'
INFO = '\033[93m'
ENDC = '\033[0m'
def d_print(string):
if verbosity > 0:
sys.stdout.write(string)
def d_info(string):
sys.stdout.write(INFO + string + ENDC + "\n")
def d_error(string):
sys.stderr.write(FAIL + string + ENDC + "\n")
sys.exit(0)
def write_file(f, string):
f.write(string)
d_print(string)
def output_header_to_file(f):
now = datetime.datetime.now()
f.write("""/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
""")
f.write("/*******************************************************************************\n")
f.write(" * This file had been created by gtp1-tlv.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")
def usage():
print("Python generating TLV build/parser for GTPv2-C v%s" % (version))
print("Usage: python gtp-tlv.py [options]")
print("Available options:")
print("-d Enable script debug")
print("-f [file] Input file to parse")
print("-o [dir] Output files to given directory")
print("-c [dir] Cache files to given directory")
print("-h Print this help and return")
def v_upper(v):
return re.sub('3GPP', '', re.sub('\'', '_', re.sub('/', '_', re.sub('-', '_', re.sub(' ', '_', v)))).upper())
def v_lower(v):
return re.sub('3gpp', '', re.sub('\'', '_', re.sub('/', '_', re.sub('-', '_', re.sub(' ', '_', v)))).lower())
def ie_reference2type(reference):
ie_type = 'foobar'
for k, v in type_list.items():
if v["reference"] == reference:
return k
raise ValueError('no IE type found for reference \"%s\"' % reference)
def get_cells(cells):
if (len(cells) < 3):
#"FIXME: Table 7.5A.9: Information Elements in a Delete MBMS Context Request" format in document is broken:
d_info("Expected length 3: %r" % repr(cells))
return None
presence = cells[1].text
presence = re.sub('\n', '', presence);
ie_value = re.sub('\s*\n*\s*\([^\)]*\)*', '', cells[0].text)
ie_value = re.sub('\\xa0', ' ', ie_value) # drop unicode char "No-Break Space" in "Higher bitrates than 16 Mbps flag"
comment = cells[2].text.encode('ascii', 'ignore').decode('utf-8').rstrip()
comment = re.sub('\n|\"|\'|\\\\', '', comment);
if comment == 'GSN Address 7.7.32':
reference = '7.7.32'
else:
reference = comment
if ie_value == '' and reference == '7.7.16':
# For some unknown reason "cells[0].text" is '' in this row
ie_value = 'Teardown Ind'
return { "ie_value" : ie_value, "presence" : presence, "reference": reference, }
def write_cells_to_file(name, cells):
write_file(f, name + ".append({ " + \
"\"ie_value\" : \"" + cells["ie_value"] + \
"\", \"presence\" : \"" + cells["presence"] + \
"\", \"reference\" : \"" + cells["reference"] + "\"})\n")
def document_paragraph_tables(document):
tables = []
# iterate .docx objects
def iter_block_items(parent):
if isinstance(parent, _Document):
parent_elm = parent.element.body
elif isinstance(parent, _Cell):
parent_elm = parent._tc
elif isinstance(parent, _Row):
parent_elm = parent._tr
else:
raise ValueError("Document format error.")
for child in parent_elm.iterchildren():
if isinstance(child, CT_P):
yield Paragraph(child, parent)
elif isinstance(child, CT_Tbl):
yield Table(child, parent)
idx = -1
paragraph = ''
for block in iter_block_items(document):
table=[]
# memorize the paragraph
if isinstance(block, Paragraph):
paragraph = block.text
continue
# fetch the table
if isinstance(block, Table):
idx += 1
table = block
# store table having a paragraph name
tables.append([idx, paragraph, table])
return tables
try:
opts, args = getopt.getopt(sys.argv[1:], "df:ho:c:", ["debug", "file", "help", "output", "cache"])
except getopt.GetoptError as err:
# print help information and exit:
usage()
sys.exit(2)
for o, a in opts:
if o in ("-d", "--debug"):
verbosity = 1
if o in ("-f", "--file"):
filename = a
if o in ("-o", "--output"):
outdir = a
if outdir.rfind('/') != len(outdir):
outdir += '/'
if o in ("-c", "--cache"):
cachedir = a
if cachedir.rfind('/') != len(cachedir):
cachedir += '/'
if o in ("-h", "--help"):
usage()
sys.exit(2)
if os.path.isfile(filename) and os.access(filename, os.R_OK):
file = open(filename, 'r')
else:
d_error("Cannot find file : " + filename)
d_info("[Message List]")
cachefile = cachedir + 'tlv-msg-list.py'
if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK):
exec(open(cachefile).read())
print("Read from " + cachefile)
else:
document = Document(filename)
f = open(cachefile, 'w')
msg_table = ""
for i, paragraph, table in document_paragraph_tables(document):
cell = table.rows[0].cells[0]
if cell.text.find('Message Type value') != -1:
msg_table = table
d_print("Table Index = %d Name = [%s]\n" % (i, paragraph))
write_file(f, "# [%s] Index = %d\n" % (paragraph, i))
for row in msg_table.rows[2:-6]:
key = row.cells[1].text
type = row.cells[0].text
if type.isdigit() is False:
continue
if int(type) in range(128, 160):
continue
if int(type) in range(231, 240):
continue
if key.find('Reserved') != -1:
continue
key = re.sub('\s*\n*\s*\([^\)]*\)*', '', key)
msg_list[key] = { "type": type }
write_file(f, "msg_list[\"" + key + "\"] = { \"type\" : \"" + type + "\" }\n")
f.close()
d_info("[IE Type List]")
cachefile = cachedir + 'tlv-type-list.py'
if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK):
exec(open(cachefile).read())
print("Read from " + cachefile)
else:
document = Document(filename)
f = open(cachefile, 'w')
ie_table = ""
for i, paragraph, table in document_paragraph_tables(document):
d_print("iter: Table Index = %d Name = [%s]\n" % (i, paragraph))
cell = table.rows[0].cells[0]
if cell.text.find('IE Type Value') != -1:
ie_table = table
d_print("Table Index = %d Name = [%s]\n" % (i, paragraph))
write_file(f, "# [%s] Index = %d\n" % (paragraph, i))
for row in ie_table.rows[1:-3]:
type = row.cells[0].text
format = row.cells[1].text
key = row.cells[2].text
reference = row.cells[3].text
len_type = row.cells[4].text
if key.find('Reserved') != -1:
continue
if key.find('Spare') != -1:
continue
else:
key = re.sub('.*\(', '', row.cells[2].text)
key = re.sub('\)', '', key)
key = re.sub('\s*$', '', key)
if key == '' and type == '19':
# For some unknown reason "row.cells[2].text" is '' in this row
key = 'Teardown Ind'
type_list[key] = { 'type': type , 'reference': reference, 'format': format }
write_file(f, "type_list[\"" + key + "\"] = { \"type\" : \"" + type)
write_file(f, "\", \"reference\" : \"" + reference)
write_file(f, "\", \"format\" : \"" + format)
if (format.find('TLV') != -1 or format.find('TV') != -1) and len_type.find('Fixed') != -1:
size = int(row.cells[5].text)
type_list[key]['size'] = size
write_file(f, "\", \"size\" : " + str(size))
else:
write_file(f, "\"")
write_file(f, " }\n")
f.close()
#type_list['MM Context'] = { "type": "107", "reference": "7.7.28" }
def set_c_type(ie_name, c_type=''):
if len(c_type):
type_list[ie_name]["c_type"] = c_type
def set_size(ie_name, size, c_type=''):
type_list[ie_name]["size"] = size
set_size("MS Time Zone", 2) # Wrongly specified as 1 in spec table
set_c_type("Cause", 'uint')
set_c_type("TLLI", 'uint')
set_c_type("P-TMSI", 'uint')
set_c_type("Recovery", 'uint')
set_c_type("Tunnel Endpoint Identifier Data I", 'uint')
set_c_type("Tunnel Endpoint Identifier Control Plane", 'uint')
set_c_type("Teardown Ind", 'uint')
set_c_type("NSAPI", 'uint')
set_c_type("RAT Type", 'uint')
set_c_type("APN Restriction", 'uint')
set_c_type("RANAP Cause", 'uint')
set_c_type("Radio Priority SMS", 'uint')
set_c_type("Radio Priority", 'uint')
set_c_type("Packet Flow Id", 'uint')
set_c_type("Trace Reference", 'uint')
set_c_type("Trace Type", 'uint')
set_c_type("MS Not Reachable Reason", 'uint')
set_c_type("Charging ID", 'uint')
msg_list["Echo Request"]["table"] = 12
msg_list["Echo Response"]["table"] = 13
#msg_list["Version Not Supported"]["table"] = 3
#msg_list["Node Alive Request"]["table"] = 4
#msg_list["Node Alive Response"]["table"] = 5
#msg_list["Redirection Request"]["table"] = 6
#msg_list["Redirection Response"]["table"] = 7
msg_list["Create PDP Context Request"]["table"] = 15
msg_list["Create PDP Context Response"]["table"] = 16
msg_list["Update PDP Context Request"]["table"] = 17 # FIXME: + 18 " Information Elements in a GGSN-Initiated Update PDP Context Request"
msg_list["Update PDP Context Response"]["table"] = 19 # FIXME: + 20
msg_list["Delete PDP Context Request"]["table"] = 21
msg_list["Delete PDP Context Response"]["table"] = 22
msg_list["Initiate PDP Context Activation Request"]["table"] = 27
msg_list["Initiate PDP Context Activation Response"]["table"] = 28
#msg_list["Error Indication"]["table"] = specified in 3GPP TS 29.281 [42].
msg_list["PDU Notification Request"]["table"] = 23
msg_list["PDU Notification Response"]["table"] = 24
msg_list["PDU Notification Reject Request"]["table"] = 25
msg_list["PDU Notification Reject Response"]["table"] = 26
msg_list["Supported Extension Headers Notification"]["table"] = 14
msg_list["Send Routeing Information for GPRS Request"]["table"] = 29
msg_list["Send Routeing Information for GPRS Response"]["table"] = 30
msg_list["Failure Report Request"]["table"] = 31
msg_list["Failure Report Response"]["table"] = 32
msg_list["Note MS GPRS Present Request"]["table"] = 33
msg_list["Note MS GPRS Present Response"]["table"] = 34
msg_list["Identification Request"]["table"] = 35
msg_list["Identification Response"]["table"] = 36
msg_list["SGSN Context Request"]["table"] = 37
msg_list["SGSN Context Response"]["table"] = 38
msg_list["SGSN Context Acknowledge"]["table"] = 39
msg_list["Forward Relocation Request"]["table"] = 40
msg_list["Forward Relocation Response"]["table"] = 41
msg_list["Forward Relocation Complete"]["table"] = 42
msg_list["Relocation Cancel Request"]["table"] = 43
msg_list["Relocation Cancel Response"]["table"] = 44
msg_list["Forward SRNS Context"]["table"] = 45
msg_list["Forward Relocation Complete Acknowledge"]["table"] = 46
msg_list["Forward SRNS Context Acknowledge"]["table"] = 47
msg_list["UE Registration Query Request"]["table"] = 49
msg_list["UE Registration Query Response"]["table"] = 50
msg_list["RAN Information Relay"]["table"] = 48
msg_list["MBMS Notification Request"]["table"] = 51
msg_list["MBMS Notification Response"]["table"] = 52
msg_list["MBMS Notification Reject Request"]["table"] = 53
msg_list["MBMS Notification Reject Response"]["table"] = 54
msg_list["Create MBMS Context Request"]["table"] = 55
msg_list["Create MBMS Context Response"]["table"] = 56
msg_list["Update MBMS Context Request"]["table"] = 57
msg_list["Update MBMS Context Response"]["table"] = 58
msg_list["Delete MBMS Context Request"]["table"] = 59
msg_list["Delete MBMS Context Response"]["table"] = 60
msg_list["MBMS Registration Request"]["table"] = 61
msg_list["MBMS Registration Response"]["table"] = 62
msg_list["MBMS De-Registration Request"]["table"] = 63
msg_list["MBMS De-Registration Response"]["table"] = 64
msg_list["MBMS Session Start Request"]["table"] = 65
msg_list["MBMS Session Start Response"]["table"] = 66
msg_list["MBMS Session Stop Request"]["table"] = 67
msg_list["MBMS Session Stop Response"]["table"] = 68
msg_list["MBMS Session Update Request"]["table"] = 69
msg_list["MBMS Session Update Response"]["table"] = 70
for key in msg_list.keys():
if "table" in msg_list[key].keys():
d_info("[" + key + "]")
if key == "Delete MBMS Context Request":
d_info('skipping, broken in source document')
# FIXME: manually generate the cells for each row
continue
cachefile = cachedir + "tlv-msg-" + msg_list[key]["type"] + ".py"
if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK):
exec(open(cachefile).read())
print("Read from " + cachefile)
else:
document = Document(filename)
f = open(cachefile, 'w')
ies = []
write_file(f, "ies = []\n")
table = document.tables[msg_list[key]["table"]]
for row in table.rows[1:]:
cells = get_cells(row.cells)
if cells is None:
continue
if cells["ie_value"] == "Private Extension":
continue;
ies.append(cells)
write_cells_to_file("ies", cells)
msg_list[key]["ies"] = ies
write_file(f, "msg_list[key][\"ies\"] = ies\n")
f.close()
f = open(outdir + 'message.h', 'w')
output_header_to_file(f)
f.write("""#if !defined(OGS_GTP_INSIDE) && !defined(OGS_GTP_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_GTP1_MESSAGE_H
#define OGS_GTP1_MESSAGE_H
#ifdef __cplusplus
extern "C" {
#endif
/* 5.1 General format */
#define OGS_GTPV1U_HEADER_LEN 8
#define OGS_GTPV1C_HEADER_LEN 12
#define OGS_GTP1_TEID_LEN 4
typedef struct ogs_gtp1_header_s {
union {
struct {
#define OGS_GTP1_VERSION_0 0
#define OGS_GTP1_VERSION_1 1
ED6(uint8_t version:3;,
uint8_t pt:1;,
uint8_t spare1:1;,
uint8_t e:1;,
uint8_t s:1;,
uint8_t pn:1;)
};
/* GTU-U flags */
#define OGS_GTP1U_FLAGS_V 0x20
#define OGS_GTP1U_FLAGS_PT 0x10
#define OGS_GTP1U_FLAGS_E 0x04
#define OGS_GTP1U_FLAGS_S 0x02
#define OGS_GTP1U_FLAGS_PN 0x01
uint8_t flags;
};
/* GTP-U message type, defined in 3GPP TS 29.281 Release 11 */
#define OGS_GTP1U_MSGTYPE_ECHO_REQ 1
#define OGS_GTP1U_MSGTYPE_ECHO_RSP 2
#define OGS_GTP1U_MSGTYPE_ERR_IND 26
#define OGS_GTP1U_MSGTYPE_SUPP_EXTHDR_NOTI 31
#define OGS_GTP1U_MSGTYPE_END_MARKER 254
#define OGS_GTP1U_MSGTYPE_GPDU 255
uint8_t type;
uint16_t length;
uint32_t teid;
/* Optional based on flags: */
#define OGS_GTP1_XID_TO_SQN(__xid) htobe16((uint16_t)(__xid))
#define OGS_GTP1_SQN_TO_XID(__sqn) be16toh((uint16_t)__sqn)
uint16_t sqn;
uint8_t npdu;
uint8_t ext_hdr_type;
} __attribute__ ((packed)) ogs_gtp1_header_t;
/* GTPv1-C message type */
""")
tmp = [(k, v["type"]) for k, v in msg_list.items()]
sorted_msg_list = sorted(tmp, key=lambda tup: int(tup[1]))
for (k, v) in sorted_msg_list:
f.write("#define OGS_GTP1_" + v_upper(k) + "_TYPE " + v + "\n")
f.write("\n")
tmp = [(k, v["type"]) for k, v in type_list.items()]
sorted_type_list = sorted(tmp, key=lambda tup: int(tup[1]))
for (k, v) in sorted_type_list:
f.write("#define OGS_GTP1_" + v_upper(k) + "_TYPE " + v + "\n")
f.write("\n")
f.write("/* Information Element TLV Descriptor */\n")
for (k, v) in sorted_type_list:
f.write("extern ogs_tlv_desc_t ogs_gtp1_tlv_desc_" + v_lower(k) + ";\n")
f.write("\n")
f.write("/* Message Descriptor */\n")
for (k, v) in sorted_msg_list:
f.write("extern ogs_tlv_desc_t ogs_gtp1_tlv_desc_" + v_lower(k) + ";\n")
f.write("\n")
f.write("/* Structure for Information Element */\n")
for (k, v) in sorted_type_list:
if type_list[k].get('c_type', '') == 'uint' and "size" in type_list[k]:
if type_list[k]["size"] >= 1 and type_list[k]["size"] <= 4:
f.write("typedef ogs_tlv_uint" + str(type_list[k]["size"]*8) + "_t ogs_gtp1_tlv_" + v_lower(k) + "_t;\n")
else:
assert False, "Unknown uint size = %d for key = %s" % (type_list[k]["size"], k)
else:
f.write("typedef ogs_tlv_octet_t ogs_gtp1_tlv_" + v_lower(k) + "_t;\n")
f.write("\n")
f.write("/* Structure for Message */\n")
for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write("typedef struct ogs_gtp1_" + v_lower(k) + "_s {\n")
for ies in msg_list[k]["ies"]:
f.write(" ogs_gtp1_tlv_" + v_lower(ie_reference2type(ies["reference"])) + "_t " + \
v_lower(ies["ie_value"]) + ";\n")
f.write("} ogs_gtp1_" + v_lower(k) + "_t;\n")
f.write("\n")
f.write("typedef struct ogs_gtp1_message_s {\n")
f.write(" ogs_gtp1_header_t h;\n")
f.write(" union {\n")
for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write(" ogs_gtp1_" + v_lower(k) + "_t " + v_lower(k) + ";\n");
f.write(" };\n");
f.write("} ogs_gtp1_message_t;\n\n")
f.write("""int ogs_gtp1_parse_msg(ogs_gtp1_message_t *gtp1_message, ogs_pkbuf_t *pkbuf);
ogs_pkbuf_t *ogs_gtp1_build_msg(ogs_gtp1_message_t *gtp1_message);
#ifdef __cplusplus
}
#endif
#endif /* OGS_GTP1_MESSAGE_H */
""")
f.close()
f = open(outdir + 'message.c', 'w')
output_header_to_file(f)
f.write("""#include "ogs-gtp.h"
""")
for (k, v) in sorted_type_list:
f.write("ogs_tlv_desc_t ogs_gtp1_tlv_desc_%s =\n" % v_lower(k))
f.write("{\n")
if type_list[k]["format"] == 'TV':
if not "size" in type_list[k]:
assert False, "Unknown size for TV key = %s" % k
if type_list[k].get('c_type', '') == 'uint':
if type_list[k]["size"] >= 1 and type_list[k]["size"] <= 4:
f.write(" OGS_TV_UINT%d,\n" % (type_list[k]["size"]*8))
else:
assert False, "Unsupported %s size = %d for key = %s" % (type_list[k]["c_type"], type_list[k]["size"], k)
else:
f.write(" OGS_TV_FIXED_STR,\n")
elif type_list[k]["format"] == 'TLV':
if not "size" in type_list[k]:
f.write(" OGS_TLV_VAR_STR,\n")
else:
if type_list[k].get('c_type', '') == 'uint':
if type_list[k]["size"] >= 1 and type_list[k]["size"] <= 4:
f.write(" OGS_TLV_UINT%d,\n" % (type_list[k]["size"]*8))
else:
assert False, "Unsupported %s size = %d for key = %s" % (type_list[k]["c_type"], type_list[k]["size"], k)
else:
f.write(" OGS_TLV_FIXED_STR,\n")
else:
f.write(" OGS_TLV_VAR_STR,\n")
f.write(" \"%s\",\n" % k)
f.write(" OGS_GTP1_%s_TYPE,\n" % v_upper(k))
if "size" in type_list[k]:
f.write(" %d,\n" % type_list[k]["size"])
else:
f.write(" 0,\n")
f.write(" 0,\n")
f.write(" sizeof(ogs_gtp1_tlv_%s_t),\n" % v_lower(k))
f.write(" { NULL }\n")
f.write("};\n\n")
for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write("ogs_tlv_desc_t ogs_gtp1_tlv_desc_%s =\n" % v_lower(k))
f.write("{\n")
f.write(" OGS_TLV_MESSAGE,\n")
f.write(" \"%s\",\n" % k)
f.write(" 0, 0, 0, 0, {\n")
for ies in msg_list[k]["ies"]:
#if k == 'Create PDP Context Request' and ies["ie_value"] == 'SGSN Address for user traffic':
# f.write(" &ogs_tlv_desc_more1,\n")
#else:
f.write(" &ogs_gtp1_tlv_desc_%s,\n" % v_lower(ie_reference2type(ies["reference"])))
f.write(" NULL,\n")
f.write("}};\n\n")
f.write("\n")
f.write("""int ogs_gtp1_parse_msg(ogs_gtp1_message_t *gtp_message, ogs_pkbuf_t *pkbuf)
{
int rv = OGS_ERROR;
ogs_gtp1_header_t *h = NULL;
uint16_t size = 0;
ogs_assert(gtp_message);
ogs_assert(pkbuf);
ogs_assert(pkbuf->len);
h = (ogs_gtp1_header_t *)pkbuf->data;
ogs_assert(h);
memset(gtp_message, 0, sizeof(ogs_gtp1_message_t));
if (h->e || h->s || h->pn)
size = OGS_GTPV1C_HEADER_LEN;
else
size = OGS_GTPV1C_HEADER_LEN - 4;
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
memcpy(&gtp_message->h, pkbuf->data - size, size);
gtp_message->h.teid = be32toh(gtp_message->h.teid);
if (pkbuf->len == 0) {
ogs_assert(ogs_pkbuf_push(pkbuf, size));
return OGS_OK;
}
switch(gtp_message->h.type) {
""")
for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write(" case OGS_GTP1_%s_TYPE:\n" % v_upper(k))
f.write(" rv = ogs_tlv_parse_msg_desc(&gtp_message->%s,\n" % v_lower(k))
f.write(" &ogs_gtp1_tlv_desc_%s, pkbuf, OGS_TLV_MODE_T1_L2);\n" % v_lower(k))
f.write(" break;\n")
f.write(""" default:
ogs_warn("Not implmeneted(type:%d)", gtp_message->h.type);
break;
}
ogs_assert(ogs_pkbuf_push(pkbuf, size));
return rv;
}
""")
f.write("""ogs_pkbuf_t *ogs_gtp1_build_msg(ogs_gtp1_message_t *gtp_message)
{
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(gtp_message);
switch(gtp_message->h.type) {
""")
for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write(" case OGS_GTP1_%s_TYPE:\n" % v_upper(k))
f.write(" pkbuf = ogs_tlv_build_msg(&ogs_gtp1_tlv_desc_%s,\n" % v_lower(k))
f.write(" &gtp_message->%s, OGS_TLV_MODE_T1_L2);\n" % v_lower(k))
f.write(" break;\n")
f.write(""" default:
ogs_warn("Not implmeneted(type:%d)", gtp_message->h.type);
break;
}
return pkbuf;
}
""")
f.write("\n")
f.close()

366
lib/gtp/v1/types.c Normal file
View File

@ -0,0 +1,366 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#include "ogs-gtp.h"
/* 7.7.51 User Location Information (ULI) */
int16_t ogs_gtp1_parse_uli(ogs_gtp1_uli_t *uli, ogs_tlv_octet_t *octet)
{
ogs_gtp1_uli_t *source = (ogs_gtp1_uli_t *)octet->data;
int16_t size = 0;
ogs_assert(uli);
ogs_assert(octet);
memset(uli, 0, sizeof(ogs_gtp1_uli_t));
uli->geo_loc_type = source->geo_loc_type;
size++;
switch (uli->geo_loc_type) {
case OGS_GTP1_GEO_LOC_TYPE_CGI:
ogs_assert(size + sizeof(uli->cgi) <= octet->len);
memcpy(&uli->cgi,
(unsigned char *)octet->data + size, sizeof(uli->cgi));
uli->cgi.lac = be16toh(uli->cgi.lac);
uli->cgi.ci = be16toh(uli->cgi.ci);
size += sizeof(uli->cgi);
break;
case OGS_GTP1_GEO_LOC_TYPE_SAI:
ogs_assert(size + sizeof(uli->sai) <= octet->len);
memcpy(&uli->sai,
(unsigned char *)octet->data + size, sizeof(uli->sai));
uli->sai.lac = be16toh(uli->sai.lac);
uli->sai.sac = be16toh(uli->sai.sac);
size += sizeof(uli->sai);
break;
case OGS_GTP1_GEO_LOC_TYPE_RAI:
ogs_assert(size + sizeof(uli->rai) <= octet->len);
memcpy(&uli->rai,
(unsigned char *)octet->data + size, sizeof(uli->rai));
uli->rai.lac = be16toh(uli->rai.lac);
uli->rai.rac = be16toh(uli->rai.rac); //FIXME: Only the first octet (10) contains the RAC and the second octet (11) is coded as "11111111"
size += sizeof(uli->rai);
break;
default:
ogs_warn("Unknown Geographic Location Type 0x%x in User Location Information IE",
uli->geo_loc_type);
return 0;
}
ogs_assert(size == octet->len);
return size;
}
int16_t ogs_gtp1_build_uli(
ogs_tlv_octet_t *octet, ogs_gtp1_uli_t *uli, void *data, int data_len)
{
ogs_gtp1_uli_t target;
int16_t size = 0;
ogs_assert(uli);
ogs_assert(octet);
ogs_assert(data);
ogs_assert(data_len);
octet->data = data;
memcpy(&target, uli, sizeof(ogs_gtp1_uli_t));
ogs_assert(size + sizeof(target.geo_loc_type) <= data_len);
memcpy((unsigned char *)octet->data + size,
&target.geo_loc_type, sizeof(target.geo_loc_type));
size += sizeof(target.geo_loc_type);
if (target.geo_loc_type == OGS_GTP1_GEO_LOC_TYPE_CGI) {
ogs_assert(size + sizeof(target.cgi) <= data_len);
target.cgi.lac = htobe16(target.cgi.lac);
target.cgi.ci = htobe16(target.cgi.ci);
memcpy((unsigned char *)octet->data + size,
&target.cgi, sizeof(target.cgi));
size += sizeof(target.cgi);
}
if (target.geo_loc_type == OGS_GTP1_GEO_LOC_TYPE_SAI) {
ogs_assert(size + sizeof(target.sai) <= data_len);
target.sai.lac = htobe16(target.sai.lac);
target.sai.sac = htobe16(target.sai.sac);
memcpy((unsigned char *)octet->data + size,
&target.sai, sizeof(target.sai));
size += sizeof(target.sai);
}
if (target.geo_loc_type == OGS_GTP1_GEO_LOC_TYPE_RAI) {
ogs_assert(size + sizeof(target.rai) <= data_len);
target.rai.lac = htobe16(target.rai.lac);
target.rai.rac = htobe16(target.rai.rac); //FIXME: Only the first octet (10) contains the RAC and the second octet (11) is coded as "11111111"
memcpy((unsigned char *)octet->data + size,
&target.rai, sizeof(target.rai));
size += sizeof(target.rai);
}
octet->len = size;
return octet->len;
}
static uint32_t dec_mbr_kbps(uint8_t mbr_byte, const uint8_t *extended_mbr_byte, const uint8_t *extended2_mbr_byte)
{
uint8_t mbr, embr1, embr2;
mbr = mbr_byte;
embr1 = extended_mbr_byte ? *extended_mbr_byte : 0;
embr2 = extended2_mbr_byte ? *extended2_mbr_byte : 0;
if (mbr == 0)
return 0;
if (mbr == 0xff)
return UINT32_MAX;
if (mbr == 0xfe) { /* Check extended field */
if (extended_mbr_byte == NULL || embr1 == 0)
return 8640;
if (embr1 == 0xfa) { /* Check extended2 field */
if (extended2_mbr_byte == NULL || embr2 == 0)
return 256 * 1000;
if (embr2 == 0xf6)
return 10 * 1000 * 1000; /* TODO: check "extended quality of service" IE */
if (embr2 >= 0xa2 && embr2 <= 0xf6)
return (1500 + (embr2 - (0xa2 - 1)) * 100) * 1000;
if (embr2 >= 0x3e && embr2 <= 0xa1)
return (500 + (embr2 - (0x3e - 1)) * 10) * 1000;
return (256 + embr2 * 4) * 1000;
}
if (embr1 >= 0xbb && embr1 <= 0xfa)
return (128 + (embr1 - (0xbb - 1)) * 1000) * 1000;
if (embr1 >= 0x4b && embr1 <= 0xba)
return (16 + (embr1 - (0x4b - 1)) * 100) * 1000;
return 8600 + embr1 * 100;
}
if (mbr & 0x80) {
mbr &= ~0x80;
return 576 + mbr_byte * 64;
}
if (mbr & 0x40) {
mbr &= ~0x40;
return 64 + mbr * 8;
}
return mbr;
}
static uint16_t dec_transfer_delay_ms(uint8_t transfer_delay_byte)
{
transfer_delay_byte &= 0x3f; /* 6 bits */
if (transfer_delay_byte <= 0x0f)
return transfer_delay_byte;
if (transfer_delay_byte <= 0x1f)
return 200 + (transfer_delay_byte - 0x10) * 50;
return 1000 + (transfer_delay_byte - 0x20) * 100;
}
/* TS 29.060 7.7.34 Quality of Service (QoS) Profile */
/* TS 24.008 10.5.6.5 Quality of service */
int16_t ogs_gtp1_parse_qos_profile(
ogs_gtp1_qos_profile_decoded_t *decoded, const ogs_tlv_octet_t *octet)
{
ogs_gtp1_qos_profile_t *source = (ogs_gtp1_qos_profile_t *)octet->data;
ogs_assert(decoded);
ogs_assert(octet);
memset(decoded, 0, sizeof(ogs_gtp1_qos_profile_decoded_t));
switch (octet->len) {
case 21: /* ARP + octet 3 + octet 3-22 */
decoded->bit_rate_uplink_extended2_present = true;
OGS_GNUC_FALLTHROUGH;
case 19: /* ARP + octet 3 + octet 3-20 */
decoded->bit_rate_downlink_extended2_present = true;
OGS_GNUC_FALLTHROUGH;
case 17: /* ARP + octet 3 + octet 3-18 */
decoded->bit_rate_uplink_extended_present = true;
OGS_GNUC_FALLTHROUGH;
case 15: /* ARP + octet 3 + octet 3-16 */
decoded->bit_rate_downlink_extended_present = true;
OGS_GNUC_FALLTHROUGH;
case 13: /* ARP + octet 3-14 */
decoded->data_octet14_present = true;
OGS_GNUC_FALLTHROUGH;
case 12: /* ARP + octet 3-13 */
decoded->data_octet6_to_13_present = true;
OGS_GNUC_FALLTHROUGH;
case 4: /* ARP + octet 3 + octet 4 + octet 5 */
break;
default:
ogs_warn("Qos Profile wrong length %u", octet->len);
return -1;
}
memcpy(&decoded->qos_profile, source, octet->len);
/* Calculate resulting MBRs in kbps: */
if (decoded->data_octet6_to_13_present) {
decoded->dec_transfer_delay = dec_transfer_delay_ms(source->data.transfer_delay);
decoded->dec_mbr_kbps_dl = dec_mbr_kbps(
source->data.max_bit_rate_downlink,
decoded->bit_rate_downlink_extended_present ?
&source->data.extended.max_bit_rate_downlink : NULL,
decoded->bit_rate_downlink_extended2_present ?
&source->data.extended2.max_bit_rate_downlink : NULL);
decoded->dec_mbr_kbps_ul = dec_mbr_kbps(
source->data.max_bit_rate_uplink,
decoded->bit_rate_uplink_extended_present ?
&source->data.extended.max_bit_rate_uplink : NULL,
decoded->bit_rate_uplink_extended2_present ?
&source->data.extended2.max_bit_rate_uplink : NULL);
}
return octet->len;
}
static uint8_t enc_transfer_delay_ms(uint16_t transfer_delay_ms)
{
if (transfer_delay_ms >= 4000)
return 0x3e;
if (transfer_delay_ms >= 1000) {
transfer_delay_ms -= 1000;
return 0x20 + (transfer_delay_ms / 100);
}
if (transfer_delay_ms >= 200) {
transfer_delay_ms -= 200;
return 0x10 + (transfer_delay_ms / 50);
}
if (transfer_delay_ms > 150)
transfer_delay_ms = 150;
return transfer_delay_ms / 10;
}
#define CHECK_EXT1 0xfe
#define CHECK_EXT2 0xfa
static uint32_t enc_mbr_kbps(uint32_t mbr_kbps, uint8_t *mbr_byte, uint8_t *extended_mbr_byte, uint8_t *extended2_mbr_byte)
{
/* up to EXT2 byte: */
if (mbr_kbps > 10*1000*1000) {
*extended2_mbr_byte = 0xf6; /* TODO: need to set the real value somewhere else */
goto ret_check_ext2;
}
if (mbr_kbps >= 1600*1000) {
mbr_kbps -= 1500*1000;
*extended2_mbr_byte = 0xa1 + mbr_kbps/(100*1000);
goto ret_check_ext2;
}
if (mbr_kbps >= 510*1000) {
mbr_kbps -= 500*1000;
*extended2_mbr_byte = 0x2d + mbr_kbps/(10*1000);
goto ret_check_ext2;
}
if (mbr_kbps >= 260*1000) {
mbr_kbps -= 256*1000;
*extended2_mbr_byte = 0x00 + mbr_kbps/(4*1000);
goto ret_check_ext2;
}
/* up to EXT1 byte: */
if (mbr_kbps >= 130*1000) {
mbr_kbps -= 128*1000;
*extended_mbr_byte = 0xba + mbr_kbps/(2*1000);
goto ret_check_ext1;
}
if (mbr_kbps >= 17*1000) {
mbr_kbps -= 16*1000;
*extended_mbr_byte = 0x4a + mbr_kbps/(1*1000);
goto ret_check_ext1;
}
if (mbr_kbps >= 8700) {
mbr_kbps -= 8600;
*extended_mbr_byte = 0x00 + mbr_kbps/(100);
goto ret_check_ext1;
}
/* Only MBR byte: */
if (mbr_kbps >= 576) {
mbr_kbps -= 576;
*mbr_byte = 0x80 + mbr_kbps/(64);
goto ret_mbr;
}
if (mbr_kbps >= 64) {
mbr_kbps -= 64;
*mbr_byte = 0x40 + mbr_kbps/(8);
goto ret_mbr;
}
if (mbr_kbps > 0) {
*mbr_byte = mbr_kbps;
goto ret_mbr;
}
/* if (mbr_kpbs == 0) */
*mbr_byte = 0xff;
goto ret_mbr;
ret_check_ext2:
*extended_mbr_byte = CHECK_EXT2;
*mbr_byte = CHECK_EXT1;
return 2;
ret_check_ext1:
*extended2_mbr_byte = 0;
*mbr_byte = CHECK_EXT1;
return 1;
ret_mbr:
*extended2_mbr_byte = 0;
*extended_mbr_byte = 0;
return 0;
}
int16_t ogs_gtp1_build_qos_profile(ogs_tlv_octet_t *octet,
const ogs_gtp1_qos_profile_decoded_t *decoded, void *data, int data_len)
{
ogs_gtp1_qos_profile_t *target;
int extended_dl, extended_ul;
ogs_assert(octet);
ogs_assert(data);
ogs_assert((size_t)data_len >= sizeof(ogs_gtp1_qos_profile_t));
octet->data = data;
target = (ogs_gtp1_qos_profile_t *)octet->data;
/* First, encode in the target position the decoded-provided fields: */
if (decoded->data_octet6_to_13_present)
target->data.transfer_delay = enc_transfer_delay_ms(decoded->dec_transfer_delay);
/* TODO: prefill with default values the extended bytes */
extended_dl = enc_mbr_kbps(decoded->dec_mbr_kbps_dl,
&target->data.max_bit_rate_downlink,
&target->data.extended.max_bit_rate_downlink,
&target->data.extended2.max_bit_rate_downlink);
extended_ul = enc_mbr_kbps(decoded->dec_mbr_kbps_ul,
&target->data.max_bit_rate_uplink,
&target->data.extended.max_bit_rate_uplink,
&target->data.extended2.max_bit_rate_uplink);
memcpy(target, &decoded->qos_profile, sizeof(ogs_gtp1_qos_profile_t));
if (extended_ul == 2)
octet->len = 23;
else if (extended_dl == 2)
octet->len = 21;
else if (extended_ul == 1)
octet->len = 19;
else if (extended_dl == 1)
octet->len = 17;
else if (decoded->data_octet14_present)
octet->len = 15;
else if (decoded->data_octet6_to_13_present)
octet->len = 14;
else
octet->len = 6;
return octet->len;
}

289
lib/gtp/v1/types.h Normal file
View File

@ -0,0 +1,289 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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/>.
*/
#if !defined(OGS_GTP_INSIDE) && !defined(OGS_GTP_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_GTP1_TYPES_H
#define OGS_GTP1_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
#define OGS_GTP1_MAX_INDIRECT_TUNNEL 8
#define OGS_GTPV1U_5GC_HEADER_LEN 16
/*
* 5GC GTP Header (16byte)
* o Flags(1byte) : 0x34
* o Message Type(1byte) : T-PDU (0xff)
* o Length(2byte) : 36
* o TEID(4byte) : 0x00000001
* o Next extension header type(4byte)
* - Sequence Number(2byte) : 0x0000
* - N PDU Number(1byte) : 0x00
* - PDU Session container(1byte) : (0x85)
* o Extension header(4byte)
* - Extension HEader Length(1byte) : 1
* - PDU Session Container(2byte)
* ; PDU Type : UL PDU SESSION INFORMATION (1)
* ; QoS Flow Identifier (QFI) : 1
* - Next extension header type : No more extension headers (0x00)
*/
#define OGS_GTPV1U_EXTENSION_HEADER_LEN 4
typedef struct ogs_gtp1_extension_header_s {
#define OGS_GTP1_EXTENSION_HEADER_TYPE_UDP_PORT 0x40
#define OGS_GTP1_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER 0x85
#define OGS_GTP1_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS 0x0
uint16_t sequence_number;
uint8_t n_pdu_number;
uint8_t type;
uint8_t len;
#define OGS_GTP1_EXTENSION_HEADER_PDU_TYPE_DL_PDU_SESSION_INFORMATION 0
#define OGS_GTP1_EXTENSION_HEADER_PDU_TYPE_UL_PDU_SESSION_INFORMATION 1
ED2(uint8_t pdu_type:4;,
uint8_t spare1:4;);
ED3(uint8_t paging_policy_presence:1;,
uint8_t reflective_qos_indicator:1;,
uint8_t qos_flow_identifier:6;);
uint8_t next_type;
} __attribute__ ((packed)) ogs_gtp1_extension_header_t;
/* TS 29.060 16.0.0 Table 38: Cause Values */
#define OGS_GTP1_CAUSE_REQUEST_IMSI 0
#define OGS_GTP1_CAUSE_REQUEST_IMEI 1
#define OGS_GTP1_CAUSE_REQUEST_IMSI_IMEI 2
#define OGS_GTP1_CAUSE_NO_ID_NEEDED 3
#define OGS_GTP1_CAUSE_MS_REFUSES 4
#define OGS_GTP1_CAUSE_MS_NOT_GPRS_RESPONDING 5
#define OGS_GTP1_CAUSE_REACTIACTION_REQUESTED 6
#define OGS_GTP1_CAUSE_PDP_ADDRESS_INACTIVITY_TIMER_EXP 7
#define OGS_GTP1_CAUSE_NETWORK_FAILURE 8
#define OGS_GTP1_CAUSE_QOS_PARAMETER_MISMATCH 9
/* 10-48 for future use */
/* 49-63 reserved for GTP' */
/* 64-127 for future use */
#define OGS_GTP1_CAUSE_REQUEST_ACCEPTED 128
#define OGS_GTP1_CAUSE_NEW_PDP_TYPE_DUE_TO_NETWORK_PREFERENCE 129
#define OGS_GTP1_CAUSE_NEW_PDP_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY 130
/* 131-176 for future use */
/* 177-191 reserved for GTP' */
#define OGS_GTP1_CAUSE_NON_EXISTENT 192
#define OGS_GTP1_CAUSE_INVALID_MESSAGE_FORMAT 193
#define OGS_GTP1_CAUSE_IMSI_IMEI_NOT_KNOWN 194
#define OGS_GTP1_CAUSE_MS_GPRS_DETACHED 195
#define OGS_GTP1_CAUSE_REJ_MS_NOT_GPRS_RESPONDING 196
#define OGS_GTP1_CAUSE_REJ_MS_REFUSES 197
#define OGS_GTP1_CAUSE_VERSION_NOT_SUPPORTED 198
#define OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE 199
#define OGS_GTP1_CAUSE_SERVICE_NOT_SUPPORTED 200
#define OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT 201
#define OGS_GTP1_CAUSE_MANDATORY_IE_MISSING 202
#define OGS_GTP1_CAUSE_OPTIONAL_IE_INCORRECT 203
#define OGS_GTP1_CAUSE_SYSTEM_FAILURE 204
#define OGS_GTP1_CAUSE_ROAMING_RESTRICTION 205
#define OGS_GTP1_CAUSE_P_TMSI_SIGNATURE_MISMATCH 206
#define OGS_GTP1_CAUSE_GPRS_CONN_SUSPENDED 207
#define OGS_GTP1_CAUSE_AUTHENTICATION_FAILURE 208
#define OGS_GTP1_CAUSE_USER_AUTHENTICATION_FAILED 209
#define OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND 210
#define OGS_GTP1_CAUSE_ALL_DYNAMIC_PDP_ADDRS_OCCUPIED 211
#define OGS_GTP1_CAUSE_NO_MEMORY_AVAILABLE 212
#define OGS_GTP1_CAUSE_RELOCATION_FAILURE 213
#define OGS_GTP1_CAUSE_UNKNOWN_MANDATORY_EXTENSION_HEADER 214
#define OGS_GTP1_CAUSE_SEMANTIC_ERR_TFT_OPERATION 215
#define OGS_GTP1_CAUSE_SYNTATIC_ERR_TFT_OPERATION 216
#define OGS_GTP1_CAUSE_SEMANTIC_ERR_PKT_FILTER 217
#define OGS_GTP1_CAUSE_SYNTACTIC_ERR_PKT_FILTER 218
#define OGS_GTP1_CAUSE_MISSING_OR_UNKNOWN_APN 219
#define OGS_GTP1_CAUSE_UNKNWON_PDP_ADDR_OR_TYPE 220
#define OGS_GTP1_CAUSE_PDP_CONTEXT_WITHOUT_TFT_ACTIVATED 221
#define OGS_GTP1_CAUSE_APN_ACCESS_DENIED 222
#define OGS_GTP1_CAUSE_APN_INCOMPATIBLE_WITH_ACTIVE_PDP_CONTEXTS 223
#define OGS_GTP1_CAUSE_MS_MBMS_CAP_INSUFFICIENT 224
#define OGS_GTP1_CAUSE_INVALID_CORRELATION_ID 225
#define OGS_GTP1_CAUSE_MBMS_BEARER_CONTEXT_SUPERSEDED 226
#define OGS_GTP1_CAUSE_BEARER_CONTROL_MODE_VIOLATION 227
#define OGS_GTP1_CAUSE_COLLISION_WITH_NET_INITIATED_REQ 228
#define OGS_GTP1_CAUSE_APN_CONGESTION 229
#define OGS_GTP1_CAUSE_BEARER_HANDLING_NOT_SUPPORED 230
#define OGS_GTP1_CAUSE_TGT_ACC_RESTRICTED_SUBSCRIBER 231
#define OGS_GTP1_CAUSE_UE_TMP_NOT_REACHABLE_POWER_SAVING 232
#define OGS_GTP1_CAUSE_RELOCATION_FAILURE_NAS_MSG_REDIR 233
/* 234-240 for future use */
/* 241-255 reserved for GTP' */
/* TS 29.060 16.0.0 Table 39: Use of the Cause Values */
#define OGS_GTP1_CAUSE_ACCEPT 0x80
#define OGS_GTP1_CAUSE_REJECT 0xc0
typedef struct ogs_gtp1_cause_s {
uint8_t value;
ED4(uint8_t spare:5;,
uint8_t pce:1;,
uint8_t bce:1;,
uint8_t cs:1;)
} __attribute__ ((packed)) ogs_gtp1_cause_t;
/* TS 29.060 16.0.0 Table 7.7.50.1 RAT Type values */
#define OGS_GTP1_RAT_TYPE_RESERVED 0
#define OGS_GTP1_RAT_TYPE_UTRAN 1
#define OGS_GTP1_RAT_TYPE_GERAN 2
#define OGS_GTP1_RAT_TYPE_WLAN 3
#define OGS_GTP1_RAT_TYPE_GAN 4
#define OGS_GTP1_RAT_TYPE_HSPA_EVOLUTION 5
#define OGS_GTP1_RAT_TYPE_EUTRAN 6
/* 8.21 User Location Information (ULI) */
#define OGS_GTP1_MAX_ULI_LEN sizeof(ogs_gtp1_uli_t)
#define OGS_GTP1_GEO_LOC_TYPE_CGI 0
#define OGS_GTP1_GEO_LOC_TYPE_SAI 1
#define OGS_GTP1_GEO_LOC_TYPE_RAI 2
typedef struct ogs_gtp1_uli_cgi_s {
ogs_nas_plmn_id_t nas_plmn_id;
uint16_t lac;
uint16_t ci;
} __attribute__ ((packed)) ogs_gtp1_uli_cgi_t;
typedef struct ogs_gtp1_uli_sai_s {
ogs_nas_plmn_id_t nas_plmn_id;
uint16_t lac;
uint16_t sac;
} __attribute__ ((packed)) ogs_gtp1_uli_sai_t;
typedef struct ogs_gtp1_uli_rai_s {
ogs_nas_plmn_id_t nas_plmn_id;
uint16_t lac;
uint16_t rac;
} __attribute__ ((packed)) ogs_gtp1_uli_rai_t;
typedef struct ogs_gtp1_uli_s {
uint8_t geo_loc_type;
union {
ogs_gtp1_uli_cgi_t cgi;
ogs_gtp1_uli_sai_t sai;
ogs_gtp1_uli_rai_t rai;
};
} ogs_gtp1_uli_t;
int16_t ogs_gtp1_parse_uli(ogs_gtp1_uli_t *uli, ogs_tlv_octet_t *octet);
int16_t ogs_gtp1_build_uli(ogs_tlv_octet_t *octet,
ogs_gtp1_uli_t *uli, void *data, int data_len);
#define OGS_GTP_GSN_ADDRESS_IPV4_LEN OGS_IPV4_LEN
#define OGS_GTP_GSN_ADDRESS_IPV6_LEN OGS_IPV6_LEN
typedef struct ogs_gtp1_gsn_addr_s {
union {
/* OGS_GTP_F_TEID_IPV4 */
uint32_t addr;
/* OGS_GTP_F_TEID_IPV6 */
uint8_t addr6[OGS_IPV6_LEN];
};
} __attribute__ ((packed)) ogs_gtp1_gsn_addr_t;
#ifdef __cplusplus
}
#endif
/* TS 29.060 7.7.49 APN Restriction
* TS 23.060 15.4 APN Restriction */
#define OGS_GTP1_APN_NO_RESTRICTION 0
#define OGS_GTP1_APN_RESTRICTION_PUBLIC_1 1
#define OGS_GTP1_APN_RESTRICTION_PUBLIC_2 2
#define OGS_GTP1_APN_RESTRICTION_PRIVATE_1 3
#define OGS_GTP1_APN_RESTRICTION_PRIVATE_2 4
/* TS 29.060 7.7.34 Quality of Service (QoS) Profile */
#define OGS_GTP1_QOS_PROFILE_MAX_LEN 255
/* TS 24.008 10.5.6.5 Quality of service */
typedef struct ogs_gtp1_qos_profile_data_extended_bit_rate_s {
uint8_t max_bit_rate_uplink;
uint8_t guaranteed_bit_rate_uplink;
uint8_t max_bit_rate_downlink;
uint8_t guaranteed_bit_rate_downlink;
} __attribute__ ((packed)) ogs_gtp1_qos_profile_data_extended_bit_rate_t;
typedef struct ogs_gtp1_qos_profile_data_s {
ED3(uint8_t spare1:2;,
uint8_t delay_class:3;,
uint8_t reliability_class:3;)
ED3(uint8_t peak_throughput:4;,
uint8_t spare2:1;,
uint8_t precedence_class:3;)
ED2(uint8_t spare3:3;,
uint8_t mean_throughput:5;)
ED3(uint8_t traffic_class:3;,
uint8_t delivery_order:2;,
uint8_t delivery_erroneous_sdu:3;)
uint8_t max_sdu_size;
uint8_t max_bit_rate_uplink;
uint8_t max_bit_rate_downlink;
ED2(uint8_t residual_ber:4;,
uint8_t sdu_error_ratio:4;)
ED2(uint8_t transfer_delay:6;,
uint8_t traffic_handling_priority:2;)
uint8_t guaranteed_bit_rate_uplink;
uint8_t guaranteed_bit_rate_downlink;
ED3(uint8_t spare4:3;,
uint8_t signalling_indication:1;,
uint8_t source_statistics_descriptor:4;)
ogs_gtp1_qos_profile_data_extended_bit_rate_t extended;
ogs_gtp1_qos_profile_data_extended_bit_rate_t extended2;
} __attribute__ ((packed)) ogs_gtp1_qos_profile_data_t;
typedef struct ogs_gtp1_qos_profile_s {
uint8_t arp;
ogs_gtp1_qos_profile_data_t data;
} __attribute__ ((packed)) ogs_gtp1_qos_profile_t;
typedef struct ogs_gtp1_qos_profile_decoded_s {
ogs_gtp1_qos_profile_t qos_profile;
/* Filled in by the decoder function: */
bool data_octet6_to_13_present; /* from traffic_class to guaranteed_bit_rate_downlink */
bool data_octet14_present; /* byte containing signalling_indication */
bool bit_rate_downlink_extended_present;
bool bit_rate_uplink_extended_present;
bool bit_rate_downlink_extended2_present;
bool bit_rate_uplink_extended2_present;
uint16_t dec_transfer_delay;
uint32_t dec_mbr_kbps_dl; /* decoded MBR in kbps */
uint32_t dec_mbr_kbps_ul; /* decoded MBR in kbps */
} __attribute__ ((packed)) ogs_gtp1_qos_profile_decoded_t;
#define OGS_GTP1_QOS_TRAFFIC_CLASS_SUBSCRIBED 0
#define OGS_GTP1_QOS_TRAFFIC_CLASS_CONVERSATIONAL 1
#define OGS_GTP1_QOS_TRAFFIC_CLASS_STREAMING 2
#define OGS_GTP1_QOS_TRAFFIC_CLASS_INTERACTIVE 3
#define OGS_GTP1_QOS_TRAFFIC_CLASS_BACKGROUND 4
#define OGS_GTP1_QOS_SRC_STATS_DESC_UNKNOWN 0
#define OGS_GTP1_QOS_SRC_STATS_DESC_SPEECH 1
/* 7.7.98 APN Aggregate Maximum Bit Rate (APN-AMBR) */
typedef struct ogs_gtp1_apn_ambr_s {
uint32_t uplink;
uint32_t downlink;
} __attribute__ ((packed)) ogs_gtp1_apn_ambr_t;
int16_t ogs_gtp1_parse_qos_profile(
ogs_gtp1_qos_profile_decoded_t *decoded, const ogs_tlv_octet_t *octet);
int16_t ogs_gtp1_build_qos_profile(ogs_tlv_octet_t *octet,
const ogs_gtp1_qos_profile_decoded_t *decoded, void *data, int data_len);
#endif /* OGS_GTP1_TYPES_H */

325
lib/gtp/v2/path.c Normal file
View File

@ -0,0 +1,325 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* 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/>.
*/
#include "ogs-gtp.h"
int ogs_gtp_send_user_plane(
ogs_gtp_node_t *gnode,
ogs_gtp_header_t *gtp_hdesc, ogs_gtp_extension_header_t *ext_hdesc,
ogs_pkbuf_t *pkbuf)
{
char buf[OGS_ADDRSTRLEN];
int rv;
ogs_gtp_header_t *gtp_h = NULL;
ogs_gtp_extension_header_t *ext_h = NULL;
uint8_t flags;
uint8_t gtp_hlen = 0;
ogs_assert(gnode);
ogs_assert(gtp_hdesc);
ogs_assert(ext_hdesc);
ogs_assert(pkbuf);
/* Processing GTP Flags */
flags = gtp_hdesc->flags;
flags |= OGS_GTPU_FLAGS_V | OGS_GTPU_FLAGS_PT;
if (ext_hdesc->qos_flow_identifier) flags |= OGS_GTPU_FLAGS_E;
/* Define GTP Header Size */
if (flags & OGS_GTPU_FLAGS_E)
gtp_hlen = OGS_GTPV1U_HEADER_LEN+8;
else if (flags & (OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_PN))
gtp_hlen = OGS_GTPV1U_HEADER_LEN+4;
else
gtp_hlen = OGS_GTPV1U_HEADER_LEN;
ogs_pkbuf_push(pkbuf, gtp_hlen);
/* Fill GTP Header */
gtp_h = (ogs_gtp_header_t *)pkbuf->data;
ogs_assert(gtp_h);
memset(gtp_h, 0, gtp_hlen);
gtp_h->flags = flags;
gtp_h->type = gtp_hdesc->type;
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ ||
gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_RSP ||
gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
/*
* TS29.281 5.1 General format in GTP-U header
*
* - The Echo Request/Response and Supported Extension Headers
* notification messages, where the Tunnel Endpoint Identifier
* shall be set to all zeroes.
* - The Error Indication message where the Tunnel Endpoint Identifier
* shall be set to all zeros.
*/
ogs_assert(gtp_hdesc->teid == 0);
}
gtp_h->teid = htobe32(gtp_hdesc->teid);
/*
* TS29.281 5.1 General format in GTP-U header
*
* Length: This field indicates the length in octets of the payload,
* i.e. the rest of the packet following the mandatory part of
* the GTP header (that is the first 8 octets). The Sequence Number,
* the N-PDU Number or any Extension headers shall be considered
* to be part of the payload, i.e. included in the length count.
*/
gtp_h->length = htobe16(pkbuf->len - OGS_GTPV1U_HEADER_LEN);
/* Fill Extention Header */
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
ext_h = (ogs_gtp_extension_header_t *)
(pkbuf->data + OGS_GTPV1U_HEADER_LEN);
ogs_assert(ext_h);
if (ext_hdesc->qos_flow_identifier) {
/* 5G Core */
ext_h->type = OGS_GTP_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER;
ext_h->len = 1;
ext_h->pdu_type = ext_hdesc->pdu_type;
ext_h->qos_flow_identifier = ext_hdesc->qos_flow_identifier;
ext_h->next_type =
OGS_GTP_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
} else {
/* EPC */
ext_h->type = ext_hdesc->type;
ext_h->len = 1;
ext_h->next_type =
OGS_GTP_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
}
}
ogs_debug("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
rv = ogs_gtp_sendto(gnode, pkbuf);
if (rv != OGS_OK) {
if (ogs_socket_errno != OGS_EAGAIN) {
ogs_error("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
}
}
ogs_pkbuf_free(pkbuf);
return rv;
}
ogs_pkbuf_t *ogs_gtp_handle_echo_req(ogs_pkbuf_t *pkb)
{
ogs_gtp_header_t *gtph = NULL;
ogs_pkbuf_t *pkb_resp = NULL;
ogs_gtp_header_t *gtph_resp = NULL;
uint16_t length;
int idx;
ogs_assert(pkb);
gtph = (ogs_gtp_header_t *)pkb->data;
/* Check GTP version. Now only support GTPv1(version = 1) */
if ((gtph->flags >> 5) != 1) {
return NULL;
}
if (gtph->type != OGS_GTPU_MSGTYPE_ECHO_REQ) {
return NULL;
}
pkb_resp = ogs_pkbuf_alloc(NULL,
100 /* enough for ECHO_RSP; use smaller buffer */);
ogs_expect_or_return_val(pkb_resp, NULL);
ogs_pkbuf_put(pkb_resp, 100);
gtph_resp = (ogs_gtp_header_t *)pkb_resp->data;
/* reply back immediately */
gtph_resp->flags = (1 << 5); /* set version */
gtph_resp->flags |= (1 << 4); /* set PT */
gtph_resp->type = OGS_GTPU_MSGTYPE_ECHO_RSP;
length = 0; /* length of Recovery IE */
gtph_resp->length = htobe16(length); /* to be overwriten */
gtph_resp->teid = 0;
idx = 8;
if (gtph->flags & (OGS_GTPU_FLAGS_PN | OGS_GTPU_FLAGS_S)) {
length += 4;
if (gtph->flags & OGS_GTPU_FLAGS_S) {
/* sequence exists */
gtph_resp->flags |= OGS_GTPU_FLAGS_S;
*((uint8_t *)pkb_resp->data + idx) = *((uint8_t *)pkb->data + idx);
*((uint8_t *)pkb_resp->data + idx + 1) =
*((uint8_t *)pkb->data + idx + 1);
} else {
*((uint8_t *)pkb_resp->data + idx) = 0;
*((uint8_t *)pkb_resp->data + idx + 1) = 0;
}
idx += 2;
if (gtph->flags & OGS_GTPU_FLAGS_PN) {
/* sequence exists */
gtph_resp->flags |= OGS_GTPU_FLAGS_PN;
*((uint8_t *)pkb_resp->data + idx) = *((uint8_t *)pkb->data + idx);
} else {
*((uint8_t *)pkb_resp->data + idx) = 0;
}
idx++;
*((uint8_t *)pkb_resp->data + idx) = 0; /* next-extension header */
idx++;
}
/* fill Recovery IE */
length += 2;
*((uint8_t *)pkb_resp->data + idx) = 14; idx++; /* type */
*((uint8_t *)pkb_resp->data + idx) = 0; idx++; /* restart counter */
gtph_resp->length = htobe16(length);
ogs_pkbuf_trim(pkb_resp, idx); /* buffer length */
return pkb_resp;
}
void ogs_gtp2_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value)
{
int rv;
ogs_gtp_message_t errmsg;
ogs_gtp_cause_t cause;
ogs_gtp_tlv_cause_t *tlv = NULL;
ogs_pkbuf_t *pkbuf = NULL;
memset(&errmsg, 0, sizeof(ogs_gtp_message_t));
errmsg.h.teid = teid;
errmsg.h.type = type;
switch (type) {
case OGS_GTP_CREATE_SESSION_RESPONSE_TYPE:
tlv = &errmsg.create_session_response.cause;
break;
case OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE:
tlv = &errmsg.modify_bearer_response.cause;
break;
case OGS_GTP_DELETE_SESSION_RESPONSE_TYPE:
tlv = &errmsg.delete_session_response.cause;
break;
case OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
tlv = &errmsg.release_access_bearers_response.cause;
break;
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE:
tlv = &errmsg.downlink_data_notification_acknowledge.cause;
break;
case OGS_GTP_CREATE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.create_bearer_response.cause;
break;
case OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.update_bearer_response.cause;
break;
case OGS_GTP_DELETE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.delete_bearer_response.cause;
break;
case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.create_indirect_data_forwarding_tunnel_response.cause;
break;
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.delete_indirect_data_forwarding_tunnel_response.cause;
break;
case OGS_GTP_MODIFY_BEARER_FAILURE_INDICATION_TYPE:
tlv = &errmsg.modify_bearer_failure_indication.cause;
break;
case OGS_GTP_DELETE_BEARER_FAILURE_INDICATION_TYPE:
tlv = &errmsg.delete_bearer_failure_indication.cause;
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
tlv = &errmsg.bearer_resource_failure_indication.cause;
break;
default:
ogs_assert_if_reached();
return;
}
ogs_assert(tlv);
memset(&cause, 0, sizeof cause);
cause.value = cause_value;
tlv->presence = 1;
tlv->len = sizeof(cause);
tlv->data = &cause;
pkbuf = ogs_gtp_build_msg(&errmsg);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(xact, &errmsg.h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp_send_echo_request(
ogs_gtp_node_t *gnode, uint8_t recovery, uint8_t features)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_header_t h;
ogs_gtp_xact_t *xact = NULL;
ogs_assert(gnode);
ogs_debug("[GTP] Sending Echo Request");
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_ECHO_REQUEST_TYPE;
h.teid = 0;
pkbuf = ogs_gtp_build_echo_request(h.type, recovery, features);
ogs_expect_or_return(pkbuf);
xact = ogs_gtp_xact_local_create(gnode, &h, pkbuf, NULL, NULL);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp_send_echo_response(ogs_gtp_xact_t *xact,
uint8_t recovery, uint8_t features)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_header_t h;
ogs_assert(xact);
ogs_debug("[GTP] Sending Echo Response");
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_ECHO_RESPONSE_TYPE;
h.teid = 0;
pkbuf = ogs_gtp_build_echo_response(h.type, recovery, features);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}

52
lib/gtp/v2/path.h Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* 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/>.
*/
#if !defined(OGS_GTP_INSIDE) && !defined(OGS_GTP_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_GTP2_PATH_H
#define OGS_GTP2_PATH_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ogs_gtp_xact_s ogs_gtp_xact_t;
int ogs_gtp_send_user_plane(
ogs_gtp_node_t *gnode,
ogs_gtp_header_t *gtp_hdesc, ogs_gtp_extension_header_t *ext_hdesc,
ogs_pkbuf_t *pkbuf);
ogs_pkbuf_t *ogs_gtp_handle_echo_req(ogs_pkbuf_t *pkt);
void ogs_gtp2_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_gtp_send_echo_request(
ogs_gtp_node_t *gnode, uint8_t recovery, uint8_t features);
void ogs_gtp_send_echo_response(ogs_gtp_xact_t *xact,
uint8_t recovery, uint8_t features);
#ifdef __cplusplus
}
#endif
#endif /* OGS_GTP2_PATH_H */

View File

@ -1,12 +1,12 @@
* Install python-docx
user@host ~/Documents/git/open5gs/lib/gtp/support$ \
user@host ~/Documents/git/open5gs/lib/gtp/v2/support$ \
sudo pip3 install python-docx
* Change the format of standard specification
* Change the format of standard specification
from 29274-g30.doc to 29274-g30.docx
using Microsoft Office 2007+
* Generate TLV support files
user@host ~/Documents/git/open5gs/lib/gtp/support$ \
user@host ~/Documents/git/open5gs/lib/gtp/v2/support$ \
python3 gtp-tlv.py -f 29274-g30.docx -o ..

View File

@ -0,0 +1,2 @@
ies = []
msg_list[key]["ies"] = ies

Some files were not shown because too many files have changed in this diff Show More