blob: b96c90df2ba002145b70b96061fd8379dd7d3ee9 [file] [log] [blame]
Pau Espin Pedrole5c89982021-05-03 18:16:42 +02001/* TS 29.060 ยง 7.5.14 RAN Information Management Messages */
2/*
3 * (C) 2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * SPDX-License-Identifier: AGPL-3.0+
7 *
8 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <talloc.h>
25
26#include <osmocom/sgsn/gtp_mme.h>
27#include <osmocom/sgsn/sgsn.h>
28
Pau Espin Pedrole5c89982021-05-03 18:16:42 +020029static bool _eutran_tai_equal(const struct osmo_eutran_tai *t1, const struct osmo_eutran_tai *t2)
30{
31 return t1->mcc == t2->mcc &&
32 t1->mnc == t2->mnc &&
33 t1->mnc_3_digits == t2->mnc_3_digits &&
34 t1->tac == t2->tac;
35}
36
37struct sgsn_mme_ctx *sgsn_mme_ctx_alloc(struct sgsn_instance *sgsn, const char *name)
38{
39 struct sgsn_mme_ctx *mme;
Pau Espin Pedrol69569872023-01-05 19:39:01 +010040 mme = talloc_zero(sgsn, struct sgsn_mme_ctx);
Pau Espin Pedrole5c89982021-05-03 18:16:42 +020041 if (!mme)
42 return NULL;
43
44 /* if we are called from config file parse, this gsn doesn't exist yet */
45 mme->sgsn = sgsn;
46
47 mme->name = talloc_strdup(mme, name);
48
49 INIT_LLIST_HEAD(&mme->routes);
50 llist_add_tail(&mme->list, &sgsn->mme_list);
51
52 return mme;
53}
54
55void sgsn_mme_ctx_free(struct sgsn_mme_ctx *mme)
56{
57 struct mme_rim_route *rt, *rt2;
58 llist_del(&mme->list);
59
60 llist_for_each_entry_safe(rt, rt2, &mme->routes, list) {
61 llist_del(&rt->list);
62 talloc_free(rt);
63 }
64
65 talloc_free(mme);
66}
67
68struct sgsn_mme_ctx *sgsn_mme_ctx_find_alloc(struct sgsn_instance *sgsn, const char *name)
69{
70 struct sgsn_mme_ctx *mme;
71
72 mme = sgsn_mme_ctx_by_name(sgsn, name);
73 if (!mme)
74 mme = sgsn_mme_ctx_alloc(sgsn, name);
75 return mme;
76}
77
78void sgsn_mme_ctx_route_add(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai)
79{
80 struct mme_rim_route *rt = talloc_zero(mme, struct mme_rim_route);
81 rt->tai = *tai;
82 llist_add_tail(&rt->list, &mme->routes);
83}
84
85void sgsn_mme_ctx_route_del(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai)
86{
87 struct mme_rim_route *rt;
88
89 llist_for_each_entry(rt, &mme->routes, list) {
90 if (_eutran_tai_equal(tai, &rt->tai)) {
91 llist_del(&rt->list);
92 talloc_free(rt);
93 return;
94 }
95 }
96}
97
98struct sgsn_mme_ctx *sgsn_mme_ctx_by_name(const struct sgsn_instance *sgsn, const char *name)
99{
100 struct sgsn_mme_ctx *mme;
101
102 llist_for_each_entry(mme, &sgsn->mme_list, list) {
103 if (!strcmp(name, mme->name))
104 return mme;
105 }
106 return NULL;
107}
108
109struct sgsn_mme_ctx *sgsn_mme_ctx_by_addr(const struct sgsn_instance *sgsn, const struct in_addr *addr)
110{
111 struct sgsn_mme_ctx *mme;
112
113 llist_for_each_entry(mme, &sgsn->mme_list, list) {
114 if (!memcmp(addr, &mme->remote_addr, sizeof(*addr)))
115 return mme;
116 }
117 return NULL;
118}
119
120struct sgsn_mme_ctx *sgsn_mme_ctx_by_route(const struct sgsn_instance *sgsn, const struct osmo_eutran_tai *tai)
121{
122 struct sgsn_mme_ctx *mme;
123 llist_for_each_entry(mme, &sgsn->mme_list, list) {
124 struct mme_rim_route *rt;
125 llist_for_each_entry(rt, &mme->routes, list) {
126 if (_eutran_tai_equal(tai, &rt->tai)) {
127 return mme;
128 }
129 }
130 }
131 return NULL;
132}
133
134struct sgsn_mme_ctx *sgsn_mme_ctx_by_default_route(const struct sgsn_instance *sgsn)
135{
136 struct sgsn_mme_ctx *mme;
137
138 llist_for_each_entry(mme, &sgsn->mme_list, list) {
139 if (mme->default_route)
140 return mme;
141 }
142 return NULL;
143}