Files
osmo-ggsn/gtp/gtp_sgsn_ctx.h
Alexander Couzens d46d0cc368 gtp: add support for SGSN Context Req/Resp/Ack
To handle both incoming and outgoing SGSN Context via GTPv1.
Introduce a FSM which handles the state of SGSN Context to simplify
the API for the SGSN which uses libgtp as well as the external SGSN
which communicates via GTP.

Change-Id: Idb8ed0bb87200a68bb8caedd734fc070df9179c0
2025-07-05 01:20:59 +02:00

105 lines
3.4 KiB
C

/*
* OsmoGGSN - Gateway GPRS Support Node
* Copyright (C) 2024 sysmocom s.f.m.c. GmbH
*
* Author: Alexander Couzens <lynxis@fe80.eu>
*
* The contents of this file may be used under the terms of the GNU
* General Public License Version 2, provided that the above copyright
* notice and this permission notice is included in all copies or
* substantial portions of the software.
*
*/
#include <netinet/in.h>
#include <osmocom/core/linuxlist.h>
struct gsn_t;
struct osmo_fsm_inst;
union gtpie_member;
enum gtp_sgsn_ctx_states {
SGSN_CTX_REQ_ST_START,
/* remote SGSN/MME request a Ctx from this peer */
SGSN_CTX_REQ_ST_WAIT_LOCAL_RESP, /*! wait for this peer to tx a SGSN Ctx Respond */
SGSN_CTX_REQ_ST_WAIT_REMOTE_ACK, /*! wait for remote peer SGSN Ctx Ack */
/* local SGSN request a Ctx from a remote peer (SGSN/MME) */
SGSN_CTX_REQ_ST_WAIT_REMOTE_RESP, /*! wait for remote peer to send this peer a SGSN Ctx Respond */
SGSN_CTX_REQ_ST_WAIT_LOCAL_ACK, /*! wait for the local peer to ack */
};
enum gtp_sgsn_ctx_req_event {
/* remote SGSN/MME request a Ctx from this peer */
SGSN_CTX_REQ_E_RX_REQ,
SGSN_CTX_REQ_E_TX_RESP, /* a response with a success reason */
SGSN_CTX_REQ_E_TX_RESP_FAIL,
SGSN_CTX_REQ_E_RX_ACK,
SGSN_CTX_REQ_E_RX_NACK, /* a nack with a reason != success */
/* local SGSN requests a Context from a remote peer (SGSN/MME) */
SGSN_CTX_REQ_E_TX_REQ,
SGSN_CTX_REQ_E_RX_RESP,
SGSN_CTX_REQ_E_RX_RESP_FAIL,
SGSN_CTX_REQ_E_TX_ACK,
SGSN_CTX_REQ_E_TX_NACK,
};
struct sgsn_ctx_reqs {
/*! contains SGSN Context Request which this peer started by requesting a Ctx */
struct llist_head local_reqs;
/*! contains SGSN Context Requests which the remote peer started by sending a Ctx */
struct llist_head remote_reqs;
/* TEID-C */
uint32_t lowest_teic; /*! lowest valid teic for Gn interface */
uint32_t next_teic;
uint32_t high_teic; /*! highest valid teic for Gn interface */
};
struct sgsn_ctx_req {
/*! entry in sgsn_ctx_reqs local or remote reqs */
struct llist_head list;
struct gsn_t *gsn;
struct osmo_fsm_inst *fi;
struct sockaddr_in peer;
uint32_t local_teic;
uint32_t remote_teic;
uint16_t seq;
};
struct sgsn_ctx_reqs *sgsn_ctx_reqs_init(void *ctx, uint32_t lowest_teic, uint32_t highest_teic);
/*! Received a SGSN Context Request from a peeer */
int sgsn_ctx_req_fsm_rx_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
uint16_t seq,
union gtpie_member * const *ie, unsigned int ie_size);
int sgsn_ctx_req_fsm_rx_resp(struct gsn_t *gsn, const struct sockaddr_in *peer,
uint16_t seq, uint32_t local_teic,
union gtpie_member * const *ie, unsigned int ie_size);
int sgsn_ctx_req_fsm_rx_ack(struct gsn_t *gsn, const struct sockaddr_in *peer,
uint16_t seq, uint32_t local_teic,
union gtpie_member * const *ie, unsigned int ie_size);
int sgsn_ctx_req_fsm_tx_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
union gtpie_member * const *ie, unsigned int ie_size,
uint32_t *local_teic, uint16_t seq);
int sgsn_ctx_req_fsm_tx_resp(struct gsn_t *gsn, struct sockaddr_in *peer,
uint16_t *seq, uint32_t local_teic, uint32_t *remote_teic,
union gtpie_member * const *ie, unsigned int ie_size);
int sgsn_ctx_req_fsm_tx_ack(struct gsn_t *gsn, struct sockaddr_in *peer,
uint16_t *seq, uint32_t local_teic, uint32_t *remote_teic,
union gtpie_member * const *ie, unsigned int ie_size);