Add GTPv2 ECHO REQ/RSP Message (#378)

This is only handling ECHO REQ/RSP message.
The related function is not implemented at this point.
This commit is contained in:
Sukchan Lee 2020-03-25 17:43:02 -04:00
parent 9c150253d9
commit 557d9532b0
19 changed files with 283 additions and 20 deletions

58
lib/gtp/build.c Normal file
View File

@ -0,0 +1,58 @@
/*
* 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"
ogs_pkbuf_t *ogs_gtp_build_echo_request(
uint8_t type, uint8_t recovery, uint8_t features)
{
ogs_gtp_message_t gtp_message;
ogs_gtp_echo_request_t *req = NULL;
req = &gtp_message.echo_request;
memset(&gtp_message, 0, sizeof(ogs_gtp_message_t));
req->recovery.presence = 1;
req->recovery.u8 = recovery;
req->sending_node_features.presence = 1;
req->sending_node_features.u8 = features;
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
}
ogs_pkbuf_t *ogs_gtp_build_echo_response(
uint8_t type, uint8_t recovery, uint8_t features)
{
ogs_gtp_message_t gtp_message;
ogs_gtp_echo_response_t *rsp = NULL;
rsp = &gtp_message.echo_response;
memset(&gtp_message, 0, sizeof(ogs_gtp_message_t));
rsp->recovery.presence = 1;
rsp->recovery.u8 = recovery;
rsp->sending_node_features.presence = 1;
rsp->sending_node_features.u8 = features;
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
}

40
lib/gtp/build.h Normal file
View File

@ -0,0 +1,40 @@
/*
* 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_GTP_BUILD_H
#define OGS_GTP_BUILD_H
#ifdef __cplusplus
extern "C" {
#endif
ogs_pkbuf_t *ogs_gtp_build_echo_request(
uint8_t type, uint8_t recovery, uint8_t features);
ogs_pkbuf_t *ogs_gtp_build_echo_response(
uint8_t type, uint8_t recovery, uint8_t features);
#ifdef __cplusplus
}
#endif
#endif /* OGS_GTP_BUILD_H */

View File

@ -22,6 +22,7 @@ libgtp_sources = files('''
types.h
conv.h
node.h
build.h
path.h
xact.h
@ -29,6 +30,7 @@ libgtp_sources = files('''
types.c
conv.c
node.c
build.c
path.c
xact.c
'''.split())

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-12-23 11:28:04.952636 by acetcom
* Created on: 2020-03-25 15:39:06.344431 by acetcom
* from 29274-d80.docx
******************************************************************************/
@ -1084,10 +1084,10 @@ ogs_tlv_desc_t ogs_gtp_tlv_desc_ldn_3 =
ogs_tlv_desc_t ogs_gtp_tlv_desc_node_features_0 =
{
OGS_TLV_VAR_STR,
OGS_TLV_UINT8,
"Node Features",
OGS_GTP_NODE_FEATURES_TYPE,
0,
1,
0,
sizeof(ogs_gtp_tlv_node_features_t),
{ NULL }

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-12-23 11:28:04.943360 by acetcom
* Created on: 2020-03-25 15:39:06.337683 by acetcom
* from 29274-d80.docx
******************************************************************************/
@ -547,7 +547,7 @@ typedef ogs_tlv_octet_t ogs_gtp_tlv_cmi_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_service_indicator_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_detach_type_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_ldn_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_node_features_t;
typedef ogs_tlv_uint8_t ogs_gtp_tlv_node_features_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_mbms_time_to_data_transfer_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_throttling_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_arp_t;

View File

@ -34,6 +34,7 @@
#include "gtp/types.h"
#include "gtp/conv.h"
#include "gtp/node.h"
#include "gtp/build.h"
#include "gtp/path.h"
#include "gtp/xact.h"

View File

@ -264,3 +264,52 @@ void ogs_gtp_send_error_message(
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

@ -40,6 +40,11 @@ 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

View File

@ -372,6 +372,7 @@ type_list["Port Number"]["size"] = 2 # Type : 126
type_list["APN Restriction"]["size"] = 1 # Type : 127
type_list["Selection Mode"]["size"] = 1 # Type : 128
type_list["Node Type"]["size"] = 1 # Type : 135
type_list["Node Features"]["size"] = 1 # Type : 152
f = open(outdir + 'message.h', 'w')
output_header_to_file(f)

View File

@ -176,6 +176,7 @@ int ogs_gtp_xact_update_tx(ogs_gtp_xact_t *xact,
char buf[OGS_ADDRSTRLEN];
ogs_gtp_xact_stage_t stage;
ogs_gtp_header_t *h = NULL;
int gtp_hlen = 0;
ogs_assert(xact);
ogs_assert(xact->gnode);
@ -244,17 +245,28 @@ int ogs_gtp_xact_update_tx(ogs_gtp_xact_t *xact,
return OGS_ERROR;
}
ogs_pkbuf_push(pkbuf, OGS_GTPV2C_HEADER_LEN);
h = (ogs_gtp_header_t *)pkbuf->data;
ogs_assert(h);
if (hdesc->type > OGS_GTP_VERSION_NOT_SUPPORTED_INDICATION_TYPE) {
gtp_hlen = OGS_GTPV2C_HEADER_LEN;
} else {
gtp_hlen = OGS_GTPV2C_HEADER_LEN - OGS_GTP_TEID_LEN;
}
ogs_pkbuf_push(pkbuf, gtp_hlen);
h = (ogs_gtp_header_t *)pkbuf->data;
memset(h, 0, gtp_hlen);
memset(h, 0, sizeof(ogs_gtp_header_t));
h->version = 2;
h->teid_presence = 1;
h->type = hdesc->type;
h->length = htons(pkbuf->len - 4);
h->teid = htonl(hdesc->teid);
h->sqn = OGS_GTP_XID_TO_SQN(xact->xid);
if (hdesc->type > OGS_GTP_VERSION_NOT_SUPPORTED_INDICATION_TYPE) {
h->teid_presence = 1;
h->teid = htobe32(hdesc->teid);
h->sqn = OGS_GTP_XID_TO_SQN(xact->xid);
} else {
h->teid_presence = 0;
h->sqn_only = OGS_GTP_XID_TO_SQN(xact->xid);
}
h->length = htobe16(pkbuf->len - 4);
/* Save Message type and packet of this step */
xact->seq[xact->step].type = h->type;
@ -636,13 +648,17 @@ int ogs_gtp_xact_receive(
char buf[OGS_ADDRSTRLEN];
int rv;
ogs_gtp_xact_t *new = NULL;
uint32_t sqn;
ogs_assert(gnode);
ogs_assert(h);
new = ogs_gtp_xact_find_by_xid(gnode, h->type, OGS_GTP_SQN_TO_XID(h->sqn));
if (h->teid_presence) sqn = h->sqn;
else sqn = h->sqn_only;
new = ogs_gtp_xact_find_by_xid(gnode, h->type, OGS_GTP_SQN_TO_XID(sqn));
if (!new)
new = ogs_gtp_xact_remote_create(gnode, h->sqn);
new = ogs_gtp_xact_remote_create(gnode, sqn);
ogs_assert(new);
ogs_debug("[%d] %s Receive peer [%s]:%d",
@ -685,6 +701,7 @@ static ogs_gtp_xact_stage_t ogs_gtp_xact_get_stage(uint8_t type, uint32_t xid)
case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE:
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE:
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_TYPE:
case OGS_GTP_ECHO_REQUEST_TYPE:
stage = GTP_XACT_INITIAL_STAGE;
break;
case OGS_GTP_CREATE_BEARER_REQUEST_TYPE:
@ -708,6 +725,7 @@ static ogs_gtp_xact_stage_t ogs_gtp_xact_get_stage(uint8_t type, uint32_t xid)
case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE:
case OGS_GTP_ECHO_RESPONSE_TYPE:
stage = GTP_XACT_FINAL_STAGE;
break;

View File

@ -31,6 +31,24 @@
#include "mme-s11-build.h"
#include "mme-s11-handler.h"
void mme_s11_handle_echo_request(
ogs_gtp_xact_t *xact, ogs_gtp_echo_request_t *req)
{
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[MME] Receiving Echo Request");
/* FIXME : Before implementing recovery counter correctly,
* I'll re-use the recovery value in request message */
ogs_gtp_send_echo_response(xact, req->recovery.u8, 0);
}
void mme_s11_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp_echo_response_t *rsp)
{
/* Not Implemented */
}
void mme_s11_handle_create_session_response(
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp_create_session_response_t *rsp)

View File

@ -26,6 +26,10 @@
extern "C" {
#endif
void mme_s11_handle_echo_request(
ogs_gtp_xact_t *xact, ogs_gtp_echo_request_t *req);
void mme_s11_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp_echo_response_t *rsp);
void mme_s11_handle_create_session_response(
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp_create_session_response_t *rsp);

View File

@ -530,6 +530,12 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
}
switch (gtp_message.h.type) {
case OGS_GTP_ECHO_REQUEST_TYPE:
mme_s11_handle_echo_request(xact, &gtp_message.echo_request);
break;
case OGS_GTP_ECHO_RESPONSE_TYPE:
mme_s11_handle_echo_response(xact, &gtp_message.echo_response);
break;
case OGS_GTP_CREATE_SESSION_RESPONSE_TYPE:
mme_s11_handle_create_session_response(
xact, mme_ue, &gtp_message.create_session_response);

View File

@ -26,6 +26,24 @@
#include "ipfw/ipfw2.h"
void pgw_s5c_handle_echo_request(
ogs_gtp_xact_t *xact, ogs_gtp_echo_request_t *req)
{
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[PGW] Receiving Echo Request");
/* FIXME : Before implementing recovery counter correctly,
* I'll re-use the recovery value in request message */
ogs_gtp_send_echo_response(xact, req->recovery.u8, 0);
}
void pgw_s5c_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp_echo_response_t *req)
{
/* Not Implemented */
}
void pgw_s5c_handle_create_session_request(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req)

View File

@ -26,6 +26,11 @@
extern "C" {
#endif
void pgw_s5c_handle_echo_request(
ogs_gtp_xact_t *xact, ogs_gtp_echo_request_t *req);
void pgw_s5c_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp_echo_response_t *req);
void pgw_s5c_handle_create_session_request(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req);

View File

@ -132,6 +132,12 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
}
switch(message->h.type) {
case OGS_GTP_ECHO_REQUEST_TYPE:
pgw_s5c_handle_echo_request(xact, &message->echo_request);
break;
case OGS_GTP_ECHO_RESPONSE_TYPE:
pgw_s5c_handle_echo_response(xact, &message->echo_response);
break;
case OGS_GTP_CREATE_SESSION_REQUEST_TYPE:
if (message->h.teid == 0) {
ogs_assert(!sess);

View File

@ -227,7 +227,7 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
ogs_assert(s11_xact);
ogs_assert(req);
ogs_debug("[SGW] Modify Bearer Reqeust");
ogs_debug("[SGW] Modify Bearer Request");
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
@ -384,7 +384,7 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
ogs_assert(s11_xact);
ogs_assert(message);
ogs_debug("[SGW] Delete Session Reqeust");
ogs_debug("[SGW] Delete Session Request");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
req = &message->delete_session_request;
@ -1284,3 +1284,4 @@ void sgw_s11_handle_bearer_resource_command(ogs_gtp_xact_t *s11_xact,
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
}

View File

@ -24,6 +24,25 @@
#include "sgw-s11-handler.h"
#include "sgw-s5c-handler.h"
static void sgw_handle_echo_request(
ogs_gtp_xact_t *xact, ogs_gtp_echo_request_t *req)
{
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[SGW] Receiving Echo Request");
/* FIXME : Before implementing recovery counter correctly,
* I'll re-use the recovery value in request message */
ogs_gtp_send_echo_response(xact, req->recovery.u8, 0);
}
static void sgw_handle_echo_response(
ogs_gtp_xact_t *s11_xact, ogs_gtp_echo_response_t *rsp)
{
/* Not Implemented */
}
void sgw_state_initial(ogs_fsm_t *s, sgw_event_t *e)
{
sgw_sm_debug(e);
@ -93,6 +112,12 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
}
switch(message.h.type) {
case OGS_GTP_ECHO_REQUEST_TYPE:
sgw_handle_echo_request(xact, &message.echo_request);
break;
case OGS_GTP_ECHO_RESPONSE_TYPE:
sgw_handle_echo_response(xact, &message.echo_response);
break;
case OGS_GTP_CREATE_SESSION_REQUEST_TYPE:
if (message.h.teid == 0) {
ogs_assert(!sgw_ue);
@ -144,7 +169,7 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
sgw_s11_handle_bearer_resource_command(xact, sgw_ue, &message);
break;
default:
ogs_warn("Not implmeneted(type:%d)", message.h.type);
ogs_warn("Not implemented(type:%d)", message.h.type);
break;
}
ogs_pkbuf_free(pkbuf);
@ -177,6 +202,12 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
}
switch(message.h.type) {
case OGS_GTP_ECHO_REQUEST_TYPE:
sgw_handle_echo_request(xact, &message.echo_request);
break;
case OGS_GTP_ECHO_RESPONSE_TYPE:
sgw_handle_echo_response(xact, &message.echo_response);
break;
case OGS_GTP_CREATE_SESSION_RESPONSE_TYPE:
sgw_s5c_handle_create_session_response(xact, sess,
&message);

View File

@ -883,7 +883,7 @@ int tests1ap_build_esm_information_response(ogs_pkbuf_t **pkbuf, int i)
/* 15 */
"000d"
"4044000005000000 05c001a001020008 00020018001a0018 1727fe1c46890102"
"4044000005000000 05c001a001020008 00020018001a0018 1727675df9c50102"
"01da280c07737461 72656e7403636f6d 0064400800130041 8d01b78000434006"
"001300410033",
"",
@ -1366,7 +1366,7 @@ int tests1ap_build_attach_complete(ogs_pkbuf_t **pkbuf, int i)
/* 15 */
"000d"
"403a000005000000 05c001a001020008 00020018001a000e 0d2735fbc1e30207"
"403a000005000000 05c001a001020008 00020018001a000e 0d27be5dbbc90207"
"4300035200c20064 4008001300418d01 b780004340060013 00410033",
"",
"",