blob: 4fe804d947f860d44fc7e60474168eecf1e3cc98 [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
29extern void *tall_sgsn_ctx;
30
31static bool _eutran_tai_equal(const struct osmo_eutran_tai *t1, const struct osmo_eutran_tai *t2)
32{
33 return t1->mcc == t2->mcc &&
34 t1->mnc == t2->mnc &&
35 t1->mnc_3_digits == t2->mnc_3_digits &&
36 t1->tac == t2->tac;
37}
38
39struct sgsn_mme_ctx *sgsn_mme_ctx_alloc(struct sgsn_instance *sgsn, const char *name)
40{
41 struct sgsn_mme_ctx *mme;
42 mme = talloc_zero(tall_sgsn_ctx, struct sgsn_mme_ctx);
43 if (!mme)
44 return NULL;
45
46 /* if we are called from config file parse, this gsn doesn't exist yet */
47 mme->sgsn = sgsn;
48
49 mme->name = talloc_strdup(mme, name);
50
51 INIT_LLIST_HEAD(&mme->routes);
52 llist_add_tail(&mme->list, &sgsn->mme_list);
53
54 return mme;
55}
56
57void sgsn_mme_ctx_free(struct sgsn_mme_ctx *mme)
58{
59 struct mme_rim_route *rt, *rt2;
60 llist_del(&mme->list);
61
62 llist_for_each_entry_safe(rt, rt2, &mme->routes, list) {
63 llist_del(&rt->list);
64 talloc_free(rt);
65 }
66
67 talloc_free(mme);
68}
69
70struct sgsn_mme_ctx *sgsn_mme_ctx_find_alloc(struct sgsn_instance *sgsn, const char *name)
71{
72 struct sgsn_mme_ctx *mme;
73
74 mme = sgsn_mme_ctx_by_name(sgsn, name);
75 if (!mme)
76 mme = sgsn_mme_ctx_alloc(sgsn, name);
77 return mme;
78}
79
80void sgsn_mme_ctx_route_add(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai)
81{
82 struct mme_rim_route *rt = talloc_zero(mme, struct mme_rim_route);
83 rt->tai = *tai;
84 llist_add_tail(&rt->list, &mme->routes);
85}
86
87void sgsn_mme_ctx_route_del(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai)
88{
89 struct mme_rim_route *rt;
90
91 llist_for_each_entry(rt, &mme->routes, list) {
92 if (_eutran_tai_equal(tai, &rt->tai)) {
93 llist_del(&rt->list);
94 talloc_free(rt);
95 return;
96 }
97 }
98}
99
100struct sgsn_mme_ctx *sgsn_mme_ctx_by_name(const struct sgsn_instance *sgsn, const char *name)
101{
102 struct sgsn_mme_ctx *mme;
103
104 llist_for_each_entry(mme, &sgsn->mme_list, list) {
105 if (!strcmp(name, mme->name))
106 return mme;
107 }
108 return NULL;
109}
110
111struct sgsn_mme_ctx *sgsn_mme_ctx_by_addr(const struct sgsn_instance *sgsn, const struct in_addr *addr)
112{
113 struct sgsn_mme_ctx *mme;
114
115 llist_for_each_entry(mme, &sgsn->mme_list, list) {
116 if (!memcmp(addr, &mme->remote_addr, sizeof(*addr)))
117 return mme;
118 }
119 return NULL;
120}
121
122struct sgsn_mme_ctx *sgsn_mme_ctx_by_route(const struct sgsn_instance *sgsn, const struct osmo_eutran_tai *tai)
123{
124 struct sgsn_mme_ctx *mme;
125 llist_for_each_entry(mme, &sgsn->mme_list, list) {
126 struct mme_rim_route *rt;
127 llist_for_each_entry(rt, &mme->routes, list) {
128 if (_eutran_tai_equal(tai, &rt->tai)) {
129 return mme;
130 }
131 }
132 }
133 return NULL;
134}
135
136struct sgsn_mme_ctx *sgsn_mme_ctx_by_default_route(const struct sgsn_instance *sgsn)
137{
138 struct sgsn_mme_ctx *mme;
139
140 llist_for_each_entry(mme, &sgsn->mme_list, list) {
141 if (mme->default_route)
142 return mme;
143 }
144 return NULL;
145}