mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn.git
synced 2025-10-23 00:12:08 +00:00
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
105 lines
3.4 KiB
C
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);
|