Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 1 | |
| 2 | #include <stdio.h> |
| 3 | |
| 4 | #include <errno.h> |
| 5 | #include <stdint.h> |
| 6 | |
| 7 | #include <osmocom/core/msgb.h> |
| 8 | #include <osmocom/gsm/tlv.h> |
| 9 | #include <osmocom/vty/logging.h> |
| 10 | #include <osmocom/gprs/gprs_ns.h> |
| 11 | #include <osmocom/gprs/gprs_bssgp.h> |
| 12 | #include <osmocom/gprs/gprs_bssgp_rim.h> |
| 13 | #include <osmocom/sgsn/sgsn_rim.h> |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 14 | #include <osmocom/sgsn/gtp_mme.h> |
Pau Espin Pedrol | 8ec269a | 2023-01-05 19:19:32 +0100 | [diff] [blame^] | 15 | #include <osmocom/sgsn/gtp.h> |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 16 | #include <osmocom/sgsn/debug.h> |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 17 | #include <osmocom/sgsn/sgsn.h> |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 18 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 19 | static int sgsn_bssgp_fwd_rim_to_geran(const struct bssgp_ran_information_pdu *pdu) |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 20 | { |
| 21 | struct bssgp_bvc_ctx *bvc_ctx; |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 22 | OSMO_ASSERT(pdu->routing_info_dest.discr == BSSGP_RIM_ROUTING_INFO_GERAN); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 23 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 24 | bvc_ctx = btsctx_by_raid_cid(&pdu->routing_info_dest.geran.raid, pdu->routing_info_dest.geran.cid); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 25 | if (!bvc_ctx) { |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 26 | LOGP(DRIM, LOGL_ERROR, "Unable to find NSEI for destination cell %s\n", |
| 27 | bssgp_rim_ri_name(&pdu->routing_info_dest)); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 28 | return -EINVAL; |
| 29 | } |
| 30 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 31 | /* Forward PDU as it is to the correct interface */ |
| 32 | return bssgp_tx_rim(pdu, bvc_ctx->nsei); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 33 | } |
| 34 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 35 | static int sgsn_bssgp_fwd_rim_to_eutran(const struct bssgp_ran_information_pdu *pdu) |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 36 | { |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 37 | struct sgsn_mme_ctx *mme; |
| 38 | OSMO_ASSERT(pdu->routing_info_dest.discr == BSSGP_RIM_ROUTING_INFO_EUTRAN); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 39 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 40 | mme = sgsn_mme_ctx_by_route(sgsn, &pdu->routing_info_dest.eutran.tai); |
| 41 | if (!mme) { /* See if we have a default route configured */ |
| 42 | mme = sgsn_mme_ctx_by_default_route(sgsn); |
| 43 | if (!mme) { |
| 44 | LOGP(DRIM, LOGL_ERROR, "Unable to find MME for destination cell %s\n", |
| 45 | bssgp_rim_ri_name(&pdu->routing_info_dest)); |
| 46 | return -EINVAL; |
| 47 | } |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 48 | } |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 49 | |
| 50 | return sgsn_mme_ran_info_req(mme, pdu); |
| 51 | } |
| 52 | |
| 53 | /* Receive a RIM PDU from BSSGP (GERAN) */ |
| 54 | int sgsn_rim_rx_from_gb(struct osmo_bssgp_prim *bp, struct msgb *msg) |
| 55 | { |
| 56 | uint16_t nsei = msgb_nsei(msg); |
| 57 | struct bssgp_ran_information_pdu *pdu = &bp->u.rim_pdu; |
| 58 | |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 59 | if (pdu->routing_info_src.discr != BSSGP_RIM_ROUTING_INFO_GERAN) { |
| 60 | LOGP(DRIM, LOGL_ERROR, |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 61 | "Rx BSSGP RIM (NSEI=%u): Expected src %s, got %s\n", nsei, |
| 62 | bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_GERAN), |
| 63 | bssgp_rim_routing_info_discr_str(pdu->routing_info_src.discr)); |
| 64 | goto err; |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 65 | } |
| 66 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 67 | switch (pdu->routing_info_dest.discr) { |
| 68 | case BSSGP_RIM_ROUTING_INFO_GERAN: |
| 69 | return sgsn_bssgp_fwd_rim_to_geran(pdu); |
| 70 | case BSSGP_RIM_ROUTING_INFO_EUTRAN: |
| 71 | return sgsn_bssgp_fwd_rim_to_eutran(pdu); |
| 72 | default: |
| 73 | /* At the moment we can only handle GERAN/EUTRAN addresses, any |
| 74 | * other type of address will be considered as an invalid |
| 75 | * address. see also: 3GPP TS 48.018, section 8c.3.1.3 |
| 76 | */ |
| 77 | LOGP(DRIM, LOGL_ERROR, |
| 78 | "Rx BSSGP RIM (NSEI=%u): Unsupported dst %s\n", nsei, |
| 79 | bssgp_rim_routing_info_discr_str(pdu->routing_info_dest.discr)); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 80 | } |
| 81 | |
Pau Espin Pedrol | e5c8998 | 2021-05-03 18:16:42 +0200 | [diff] [blame] | 82 | LOGP(DRIM, LOGL_INFO, "Rx BSSGP RIM (NSEI=%u): for dest cell %s\n", nsei, |
| 83 | bssgp_rim_ri_name(&pdu->routing_info_dest)); |
| 84 | |
| 85 | err: |
| 86 | /* In case of an invalid destination address we respond with |
| 87 | * a BSSGP STATUS PDU, see also: 3GPP TS 48.018, section 8c.3.1.3 */ |
| 88 | bssgp_tx_status(BSSGP_CAUSE_UNKN_RIM_AI, NULL, msg); |
| 89 | return -1; |
| 90 | } |
| 91 | |
| 92 | /* Receive a RIM PDU from GTPvC1 (EUTRAN) */ |
| 93 | int sgsn_rim_rx_from_gtp(struct bssgp_ran_information_pdu *pdu, struct sgsn_mme_ctx *mme) |
| 94 | { |
| 95 | struct sgsn_mme_ctx *mme_tmp; |
| 96 | if (pdu->routing_info_src.discr != BSSGP_RIM_ROUTING_INFO_EUTRAN) { |
| 97 | LOGMME(mme, DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected src %s, got %s\n", |
| 98 | bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_EUTRAN), |
| 99 | bssgp_rim_routing_info_discr_str(pdu->routing_info_src.discr)); |
| 100 | return -EINVAL; |
| 101 | } |
| 102 | |
| 103 | if (pdu->routing_info_dest.discr != BSSGP_RIM_ROUTING_INFO_GERAN) { |
| 104 | LOGMME(mme, DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected dst %s, got %s\n", |
| 105 | bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_GERAN), |
| 106 | bssgp_rim_routing_info_discr_str(pdu->routing_info_dest.discr)); |
| 107 | return -EINVAL; |
| 108 | } |
| 109 | |
| 110 | mme_tmp = sgsn_mme_ctx_by_route(sgsn, &pdu->routing_info_src.eutran.tai); |
| 111 | if (!mme_tmp)/* See if we have a default route configured */ |
| 112 | mme_tmp = sgsn_mme_ctx_by_default_route(sgsn); |
| 113 | if (mme != mme_tmp) { |
| 114 | LOGP(DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: " |
| 115 | "Source MME doesn't have RIM routing configured for TAI: %s\n", |
| 116 | bssgp_rim_ri_name(&pdu->routing_info_src)); |
| 117 | return -EINVAL; |
| 118 | } |
| 119 | |
| 120 | LOGMME(mme, DRIM, LOGL_INFO, "Rx GTP RAN Information Relay for dest cell %s\n", |
| 121 | bssgp_rim_ri_name(&pdu->routing_info_dest)); |
| 122 | |
| 123 | return sgsn_bssgp_fwd_rim_to_geran(pdu); |
Philipp Maier | 2ce050b | 2020-12-14 23:27:47 +0100 | [diff] [blame] | 124 | } |