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