From f32c6a9095c5fc60c1e31a1a5164d239f5cbe387 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 3 May 2021 17:58:55 +0200 Subject: [PATCH] gtp: Support tx/rx RAN Information Relay message See 3GPP TS 29.060 sec 7.5.14.1 RAN Information Relay. Related: SYS#5314 Change-Id: Iea3eb032ccd4aed5187baca7f7719349d76039d4 --- TODO-RELEASE | 1 + gtp/gtp.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gtp/gtp.h | 11 ++++++++++ 3 files changed, 73 insertions(+) diff --git a/TODO-RELEASE b/TODO-RELEASE index d0852fc..23c9b6d 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,4 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libgtp ADD gtp_ran_info_relay_req, gtp_set_cb_ran_info_relay_ind diff --git a/gtp/gtp.c b/gtp/gtp.c index caee5a6..59fd355 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -196,6 +196,13 @@ int gtp_set_cb_extheader_ind(struct gsn_t *gsn, return 0; } +int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn, + int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie)) +{ + gsn->cb_ran_info_relay_ind = cb; + return 0; +} + /* API: Initialise delete context callback */ /* Called whenever a pdp context is deleted for any reason */ int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp)) @@ -1200,6 +1207,57 @@ static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer, return 0; } +/* Handle a RAN Information Relay message */ +static int gtp_ran_info_relay_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer, + void *pack, unsigned len) +{ + union gtpie_member *ie[GTPIE_SIZE]; + + if (version != 1) { + LOGP(DLGTP, LOGL_NOTICE, + "RAN Information Relay expected only on GTPCv1: %u\n", version); + return -EINVAL; + } + + int hlen = get_hlen(pack); + + /* Decode information elements */ + if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) { + gsn->invalid++; + GTP_LOGPKG(LOGL_ERROR, peer, pack, len, + "Invalid message format (AN Information Relay)\n"); + return -EINVAL; + } + + if (gsn->cb_ran_info_relay_ind) + gsn->cb_ran_info_relay_ind(peer, ie); + + return 0; +} + +/* Send off a RAN Information Relay message */ +int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer, + const uint8_t *ran_container, size_t ran_container_len, + const uint8_t *rim_route_addr, size_t rim_route_addr_len, + uint8_t rim_route_addr_discr) +{ + union gtp_packet packet; + + /* GTP 1 is the highest supported protocol */ + unsigned int length = get_default_gtp(1, GTP_RAN_INFO_RELAY, &packet); + + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAN_T_CONTAIN, ran_container_len, + ran_container); + if (rim_route_addr) { + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RIM_ROUT_ADDR, + rim_route_addr_len, rim_route_addr); + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RIM_RA_DISCR, 1, + &rim_route_addr_discr); + } + + return gtp_notification(gsn, 1, &packet, length, peer, gsn->fd1c, 0); +} + /* *********************************************************** * Session management messages * Messages: create, update and delete PDP context @@ -3202,6 +3260,9 @@ int gtp_decaps1c(struct gsn_t *gsn) case GTP_ERROR: gtp_error_ind_conf(gsn, version, &peer, buffer, status); break; + case GTP_RAN_INFO_RELAY: + gtp_ran_info_relay_ind(gsn, version, &peer, buffer, status); + break; default: gsn->unknown++; GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status, diff --git a/gtp/gtp.h b/gtp/gtp.h index 45eb285..0583025 100644 --- a/gtp/gtp.h +++ b/gtp/gtp.h @@ -16,6 +16,7 @@ #include #include +#include "gtpie.h" #include "pdp.h" #define GTP_MODE_GGSN 1 @@ -85,6 +86,7 @@ #define GTP_FWD_SRNS 58 /* Forward SRNS Context */ #define GTP_FWD_RELOC_ACK 59 /* Forward Relocation Complete Acknowledge */ #define GTP_FWD_SRNS_ACK 60 /* Forward SRNS Context Acknowledge */ +#define GTP_RAN_INFO_RELAY 70 /* RAN Information Relay */ /* 61-239 For future use. */ #define GTP_DATA_TRAN_REQ 240 /* Data Record Transfer Request */ #define GTP_DATA_TRAN_RSP 241 /* Data Record Transfer Response */ @@ -276,6 +278,7 @@ struct gsn_t { int (*cb_create_context_ind) (struct pdp_t *); int (*cb_unsup_ind) (struct sockaddr_in * peer); int (*cb_extheader_ind) (struct sockaddr_in * peer); + int (*cb_ran_info_relay_ind) (struct sockaddr_in *peer, union gtpie_member **ie); int (*cb_conf) (int type, int cause, struct pdp_t * pdp, void *cbp); int (*cb_data_ind) (struct pdp_t * pdp, void *pack, unsigned len); int (*cb_recovery) (struct sockaddr_in * peer, uint8_t recovery); @@ -343,6 +346,11 @@ extern int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len); +extern int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer, + const uint8_t *ran_container, size_t ran_container_len, + const uint8_t *rim_route_addr, size_t rim_route_addr_len, + uint8_t rim_route_addr_discr); + extern int gtp_set_cb_data_ind(struct gsn_t *gsn, int (*cb_data_ind) (struct pdp_t * pdp, void *pack, unsigned len)); @@ -366,6 +374,9 @@ extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn, extern int gtp_set_cb_extheader_ind(struct gsn_t *gsn, int (*cb) (struct sockaddr_in * peer)); +extern int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn, + int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie)); + extern int gtp_set_cb_conf(struct gsn_t *gsn, int (*cb) (int type, int cause, struct pdp_t * pdp, void *cbp));