blob: a9ace5f9bae8fb2bf85abf6ce635759f71715eac [file] [log] [blame]
Alexander Couzens6a161492020-07-12 13:45:50 +02001/*! \file gprs_ns2_sns.c
2 * NS Sub-Network Service Protocol implementation
3 * 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05)
4 * as well as its successor 3GPP TS 48.016 */
5
Harald Weltec1c7e4a2021-03-02 20:47:29 +01006/* (C) 2018-2021 by Harald Welte <laforge@gnumonks.org>
Alexander Couzens6a161492020-07-12 13:45:50 +02007 * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
8 * Author: Alexander Couzens <lynxis@fe80.eu>
9 *
10 * All Rights Reserved
11 *
12 * SPDX-License-Identifier: GPL-2.0+
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 *
27 */
28
29/* The BSS NSE only has one SGSN IP address configured, and it will use the SNS procedures
30 * to communicated its local IPs/ports as well as all the SGSN side IPs/ports and
31 * associated weights. The BSS then uses this to establish a full mesh
32 * of NSVCs between all BSS-side IPs/ports and SGSN-side IPs/ports.
33 *
34 * Known limitation/expectation/bugs:
35 * - No concurrent dual stack. It supports either IPv4 or IPv6, but not both at the same time.
36 * - SNS Add/Change/Delete: Doesn't answer on the same NSVC as received SNS ADD/CHANGE/DELETE PDUs.
37 * - SNS Add/Change/Delete: Doesn't communicated the failed IPv4/IPv6 entries on the SNS_ACK.
38 */
39
40#include <errno.h>
41
42#include <netinet/in.h>
43#include <arpa/inet.h>
44#include <stdint.h>
45
46#include <osmocom/core/fsm.h>
47#include <osmocom/core/msgb.h>
48#include <osmocom/core/socket.h>
Alexander Couzens412bc342020-11-19 05:24:37 +010049#include <osmocom/core/sockaddr_str.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020050#include <osmocom/gsm/tlv.h>
51#include <osmocom/gprs/gprs_msgb.h>
52#include <osmocom/gprs/gprs_ns2.h>
53#include <osmocom/gprs/protocol/gsm_08_16.h>
54
55#include "gprs_ns2_internal.h"
56
57#define S(x) (1 << (x))
58
Harald Welte4f127462021-03-02 20:49:10 +010059enum ns2_sns_role {
60 GPRS_SNS_ROLE_BSS,
61 GPRS_SNS_ROLE_SGSN,
62};
63
Harald Welte694dad52021-03-23 15:22:16 +010064/* BSS-side-only states _ST_BSS_; SGSN-side only states _ST_SGSN_; others shared */
Alexander Couzens6a161492020-07-12 13:45:50 +020065enum gprs_sns_bss_state {
66 GPRS_SNS_ST_UNCONFIGURED,
Harald Welte694dad52021-03-23 15:22:16 +010067 GPRS_SNS_ST_BSS_SIZE, /*!< SNS-SIZE procedure ongoing */
68 GPRS_SNS_ST_BSS_CONFIG_BSS, /*!< SNS-CONFIG procedure (BSS->SGSN) ongoing */
69 GPRS_SNS_ST_BSS_CONFIG_SGSN, /*!< SNS-CONFIG procedure (SGSN->BSS) ongoing */
Alexander Couzens6a161492020-07-12 13:45:50 +020070 GPRS_SNS_ST_CONFIGURED,
Harald Welte4f127462021-03-02 20:49:10 +010071 GPRS_SNS_ST_SGSN_WAIT_CONFIG, /* !< SGSN role: Wait for CONFIG from BSS */
72 GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK, /* !< SGSN role: Wait for CONFIG-ACK from BSS */
Alexander Couzens6a161492020-07-12 13:45:50 +020073};
74
75enum gprs_sns_event {
Alexander Couzens67725e22021-02-15 02:37:03 +010076 GPRS_SNS_EV_REQ_SELECT_ENDPOINT, /*!< Select a SNS endpoint from the list */
77 GPRS_SNS_EV_RX_SIZE,
78 GPRS_SNS_EV_RX_SIZE_ACK,
79 GPRS_SNS_EV_RX_CONFIG,
80 GPRS_SNS_EV_RX_CONFIG_END, /*!< SNS-CONFIG with end flag received */
81 GPRS_SNS_EV_RX_CONFIG_ACK,
82 GPRS_SNS_EV_RX_ADD,
83 GPRS_SNS_EV_RX_DELETE,
84 GPRS_SNS_EV_RX_CHANGE_WEIGHT,
Harald Welteb9f23872021-03-02 20:48:54 +010085 GPRS_SNS_EV_RX_ACK, /*!< Rx of SNS-ACK (response to ADD/DELETE/CHG_WEIGHT */
Harald Welte04647e12021-03-02 18:50:40 +010086 GPRS_SNS_EV_REQ_NO_NSVC, /*!< no more NS-VC remaining (all dead) */
Alexander Couzens67725e22021-02-15 02:37:03 +010087 GPRS_SNS_EV_REQ_NSVC_ALIVE, /*!< a NS-VC became alive */
Harald Welte04647e12021-03-02 18:50:40 +010088 GPRS_SNS_EV_REQ_ADD_BIND, /*!< add a new local bind to this NSE */
89 GPRS_SNS_EV_REQ_DELETE_BIND, /*!< remove a local bind from this NSE */
Alexander Couzens6a161492020-07-12 13:45:50 +020090};
91
92static const struct value_string gprs_sns_event_names[] = {
Alexander Couzens67725e22021-02-15 02:37:03 +010093 { GPRS_SNS_EV_REQ_SELECT_ENDPOINT, "REQ_SELECT_ENDPOINT" },
94 { GPRS_SNS_EV_RX_SIZE, "RX_SIZE" },
95 { GPRS_SNS_EV_RX_SIZE_ACK, "RX_SIZE_ACK" },
96 { GPRS_SNS_EV_RX_CONFIG, "RX_CONFIG" },
97 { GPRS_SNS_EV_RX_CONFIG_END, "RX_CONFIG_END" },
98 { GPRS_SNS_EV_RX_CONFIG_ACK, "RX_CONFIG_ACK" },
99 { GPRS_SNS_EV_RX_ADD, "RX_ADD" },
100 { GPRS_SNS_EV_RX_DELETE, "RX_DELETE" },
Harald Welteb9f23872021-03-02 20:48:54 +0100101 { GPRS_SNS_EV_RX_ACK, "RX_ACK" },
Alexander Couzens67725e22021-02-15 02:37:03 +0100102 { GPRS_SNS_EV_RX_CHANGE_WEIGHT, "RX_CHANGE_WEIGHT" },
103 { GPRS_SNS_EV_REQ_NO_NSVC, "REQ_NO_NSVC" },
104 { GPRS_SNS_EV_REQ_NSVC_ALIVE, "REQ_NSVC_ALIVE"},
105 { GPRS_SNS_EV_REQ_ADD_BIND, "REQ_ADD_BIND"},
106 { GPRS_SNS_EV_REQ_DELETE_BIND, "REQ_DELETE_BIND"},
Alexander Couzens6a161492020-07-12 13:45:50 +0200107 { 0, NULL }
108};
109
Alexander Couzense769f522020-12-07 07:37:07 +0100110struct sns_endpoint {
111 struct llist_head list;
112 struct osmo_sockaddr saddr;
113};
114
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100115struct ns2_sns_bind {
116 struct llist_head list;
117 struct gprs_ns2_vc_bind *bind;
118};
119
Alexander Couzens71128672021-06-05 18:44:01 +0200120struct ns2_sns_elems {
121 struct gprs_ns_ie_ip4_elem *ip4;
122 unsigned int num_ip4;
123 struct gprs_ns_ie_ip6_elem *ip6;
124 unsigned int num_ip6;
125};
126
Alexander Couzens6a161492020-07-12 13:45:50 +0200127struct ns2_sns_state {
128 struct gprs_ns2_nse *nse;
129
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200130 /* containing the address family AF_* */
131 int family;
Harald Welte4f127462021-03-02 20:49:10 +0100132 enum ns2_sns_role role; /* local role: BSS or SGSN */
Alexander Couzens6a161492020-07-12 13:45:50 +0200133
Alexander Couzense769f522020-12-07 07:37:07 +0100134 /* holds the list of initial SNS endpoints */
135 struct llist_head sns_endpoints;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100136 /* list of used struct ns2_sns_bind */
137 struct llist_head binds;
138 /* pointer to the bind which was used to initiate the SNS connection */
139 struct ns2_sns_bind *initial_bind;
Alexander Couzense769f522020-12-07 07:37:07 +0100140 /* prevent recursive reselection */
141 bool reselection_running;
142
143 /* The current initial SNS endpoints.
144 * The initial connection will be moved into the NSE
145 * if configured via SNS. Otherwise it will be removed
146 * in configured state. */
147 struct sns_endpoint *initial;
Alexander Couzens6a161492020-07-12 13:45:50 +0200148 /* all SNS PDU will be sent over this nsvc */
149 struct gprs_ns2_vc *sns_nsvc;
Alexander Couzens90ee9632020-12-07 06:18:32 +0100150 /* timer N */
151 int N;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100152 /* true if at least one nsvc is alive */
153 bool alive;
Alexander Couzens6a161492020-07-12 13:45:50 +0200154
155 /* local configuration to send to the remote end */
Alexander Couzens71128672021-06-05 18:44:01 +0200156 struct ns2_sns_elems local;
Alexander Couzens6a161492020-07-12 13:45:50 +0200157
Alexander Couzens71128672021-06-05 18:44:01 +0200158 /* remote configuration as received */
159 struct ns2_sns_elems remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200160
161 /* local configuration about our capabilities in terms of connections to
162 * remote (SGSN) side */
163 size_t num_max_nsvcs;
164 size_t num_max_ip4_remote;
165 size_t num_max_ip6_remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200166};
167
168static inline struct gprs_ns2_nse *nse_inst_from_fi(struct osmo_fsm_inst *fi)
169{
170 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
171 return gss->nse;
172}
173
Alexander Couzens652ab4d2021-06-12 23:09:46 +0200174/* The SNS has failed. Etither restart the SNS (BSS) or remove the SNS (SGSN) */
175#define sns_failed(fi, reason) \
176 _sns_failed(fi, reason, __FILE__, __LINE__)
177static void _sns_failed(struct osmo_fsm_inst *fi, const char *reason, const char *file, int line)
178{
179 struct ns2_sns_state *gss = fi->priv;
180
181 if (reason)
182 LOGPFSML(fi, LOGL_ERROR, "NSE %d: SNS failed: %s\n", gss->nse->nsei, reason);
183
184 if (gss->role == GPRS_SNS_ROLE_SGSN) {
185 if (!gss->nse->persistent)
186 gprs_ns2_free_nse(gss->nse);
187 else
188 _osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0, file, line);
189 } else {
190 _osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_REQ_SELECT_ENDPOINT, NULL, file, line);
191 }
192}
193
Alexander Couzens6a161492020-07-12 13:45:50 +0200194/* helper function to compute the sum of all (data or signaling) weights */
Alexander Couzens62310552021-06-06 02:43:14 +0200195static int ip4_weight_sum(const struct ns2_sns_elems *elems, bool data_weight)
Alexander Couzens6a161492020-07-12 13:45:50 +0200196{
197 unsigned int i;
198 int weight_sum = 0;
199
Alexander Couzens62310552021-06-06 02:43:14 +0200200 for (i = 0; i < elems->num_ip4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200201 if (data_weight)
Alexander Couzens62310552021-06-06 02:43:14 +0200202 weight_sum += elems->ip4[i].data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200203 else
Alexander Couzens62310552021-06-06 02:43:14 +0200204 weight_sum += elems->ip4[i].sig_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200205 }
206 return weight_sum;
207}
Alexander Couzens62310552021-06-06 02:43:14 +0200208#define ip4_weight_sum_data(elems) ip4_weight_sum(elems, true)
209#define ip4_weight_sum_sig(elems) ip4_weight_sum(elems, false)
Alexander Couzens6a161492020-07-12 13:45:50 +0200210
211/* helper function to compute the sum of all (data or signaling) weights */
Alexander Couzens62310552021-06-06 02:43:14 +0200212static int ip6_weight_sum(const struct ns2_sns_elems *elems, bool data_weight)
Alexander Couzens6a161492020-07-12 13:45:50 +0200213{
214 unsigned int i;
215 int weight_sum = 0;
216
Alexander Couzens62310552021-06-06 02:43:14 +0200217 for (i = 0; i < elems->num_ip6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200218 if (data_weight)
Alexander Couzens62310552021-06-06 02:43:14 +0200219 weight_sum += elems->ip6[i].data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200220 else
Alexander Couzens62310552021-06-06 02:43:14 +0200221 weight_sum += elems->ip6[i].sig_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200222 }
223 return weight_sum;
224}
Alexander Couzens62310552021-06-06 02:43:14 +0200225#define ip6_weight_sum_data(elems) ip6_weight_sum(elems, true)
226#define ip6_weight_sum_sig(elems) ip6_weight_sum(elems, false)
Alexander Couzens6a161492020-07-12 13:45:50 +0200227
Alexander Couzens019da4b2021-06-06 02:48:18 +0200228static int ip46_weight_sum(const struct ns2_sns_elems *elems, bool data_weight)
Harald Weltec1c7e4a2021-03-02 20:47:29 +0100229{
Alexander Couzens019da4b2021-06-06 02:48:18 +0200230 return ip4_weight_sum(elems, data_weight) +
231 ip6_weight_sum(elems, data_weight);
Harald Weltec1c7e4a2021-03-02 20:47:29 +0100232}
Alexander Couzens019da4b2021-06-06 02:48:18 +0200233#define ip46_weight_sum_data(elems) ip46_weight_sum(elems, true)
234#define ip46_weight_sum_sig(elems) ip46_weight_sum(elems, false)
Harald Weltec1c7e4a2021-03-02 20:47:29 +0100235
Alexander Couzens6a161492020-07-12 13:45:50 +0200236static struct gprs_ns2_vc *nsvc_by_ip4_elem(struct gprs_ns2_nse *nse,
237 const struct gprs_ns_ie_ip4_elem *ip4)
238{
239 struct osmo_sockaddr sa;
240 /* copy over. Both data structures use network byte order */
241 sa.u.sin.sin_addr.s_addr = ip4->ip_addr;
242 sa.u.sin.sin_port = ip4->udp_port;
243 sa.u.sin.sin_family = AF_INET;
244
Alexander Couzens38b19e82020-09-23 23:56:37 +0200245 return gprs_ns2_nsvc_by_sockaddr_nse(nse, &sa);
Alexander Couzens6a161492020-07-12 13:45:50 +0200246}
247
248static struct gprs_ns2_vc *nsvc_by_ip6_elem(struct gprs_ns2_nse *nse,
249 const struct gprs_ns_ie_ip6_elem *ip6)
250{
251 struct osmo_sockaddr sa;
252 /* copy over. Both data structures use network byte order */
253 sa.u.sin6.sin6_addr = ip6->ip_addr;
254 sa.u.sin6.sin6_port = ip6->udp_port;
255 sa.u.sin6.sin6_family = AF_INET;
256
Alexander Couzens38b19e82020-09-23 23:56:37 +0200257 return gprs_ns2_nsvc_by_sockaddr_nse(nse, &sa);
Alexander Couzens6a161492020-07-12 13:45:50 +0200258}
259
Alexander Couzens125298f2020-10-11 21:22:42 +0200260/*! Return the initial SNS remote socket address
261 * \param nse NS Entity
262 * \return address of the initial SNS connection; NULL in case of error
263 */
264const struct osmo_sockaddr *gprs_ns2_nse_sns_remote(struct gprs_ns2_nse *nse)
265{
266 struct ns2_sns_state *gss;
267
268 if (!nse->bss_sns_fi)
269 return NULL;
270
271 gss = (struct ns2_sns_state *) nse->bss_sns_fi->priv;
Alexander Couzense769f522020-12-07 07:37:07 +0100272 return &gss->initial->saddr;
Alexander Couzens125298f2020-10-11 21:22:42 +0200273}
274
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100275/*! called when a nsvc is beeing freed or the nsvc became dead */
276void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc)
Alexander Couzens6a161492020-07-12 13:45:50 +0200277{
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100278 struct gprs_ns2_nse *nse = nsvc->nse;
Alexander Couzens6a161492020-07-12 13:45:50 +0200279 struct gprs_ns2_vc *tmp;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100280 struct osmo_fsm_inst *fi = nse->bss_sns_fi;
Alexander Couzens6a161492020-07-12 13:45:50 +0200281 struct ns2_sns_state *gss;
Alexander Couzens6a161492020-07-12 13:45:50 +0200282
283 if (!fi)
284 return;
285
286 gss = (struct ns2_sns_state *) fi->priv;
287 if (nsvc != gss->sns_nsvc)
288 return;
289
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100290 gss->sns_nsvc = NULL;
291 if (gss->alive) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200292 llist_for_each_entry(tmp, &nse->nsvc, list) {
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100293 if (ns2_vc_is_unblocked(tmp)) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200294 gss->sns_nsvc = tmp;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100295 return;
296 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200297 }
298 } else {
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100299 /* the SNS is waiting for its first NS-VC to come up
300 * choose any other nsvc */
301 llist_for_each_entry(tmp, &nse->nsvc, list) {
302 if (nsvc != tmp) {
303 gss->sns_nsvc = tmp;
304 return;
305 }
306 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200307 }
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100308
Alexander Couzens67725e22021-02-15 02:37:03 +0100309 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_REQ_NO_NSVC, NULL);
Alexander Couzens6a161492020-07-12 13:45:50 +0200310}
311
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200312static void ns2_clear_elems(struct ns2_sns_elems *elems)
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100313{
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200314 TALLOC_FREE(elems->ip4);
315 TALLOC_FREE(elems->ip6);
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100316
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200317 elems->num_ip4 = 0;
318 elems->num_ip6 = 0;
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100319}
320
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100321static void ns2_vc_create_ip(struct osmo_fsm_inst *fi, struct gprs_ns2_nse *nse, const struct osmo_sockaddr *remote,
322 uint8_t sig_weight, uint8_t data_weight)
Alexander Couzens6a161492020-07-12 13:45:50 +0200323{
324 struct gprs_ns2_inst *nsi = nse->nsi;
325 struct gprs_ns2_vc *nsvc;
326 struct gprs_ns2_vc_bind *bind;
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100327
328 /* for every bind, create a connection if bind type == IP */
329 llist_for_each_entry(bind, &nsi->binding, list) {
330 if (bind->ll != GPRS_NS2_LL_UDP)
331 continue;
332 /* ignore failed connection */
333 nsvc = gprs_ns2_ip_connect_inactive(bind,
334 remote,
335 nse, 0);
336 if (!nsvc) {
337 LOGPFSML(fi, LOGL_ERROR, "SNS-CONFIG: Failed to create NSVC\n");
338 continue;
339 }
340
341 nsvc->sig_weight = sig_weight;
342 nsvc->data_weight = data_weight;
343 }
344}
345
346static void ns2_nsvc_create_ip4(struct osmo_fsm_inst *fi,
347 struct gprs_ns2_nse *nse,
348 const struct gprs_ns_ie_ip4_elem *ip4)
349{
Alexander Couzensc068d862020-10-12 04:11:51 +0200350 struct osmo_sockaddr remote = { };
Alexander Couzens6a161492020-07-12 13:45:50 +0200351 /* copy over. Both data structures use network byte order */
352 remote.u.sin.sin_family = AF_INET;
353 remote.u.sin.sin_addr.s_addr = ip4->ip_addr;
354 remote.u.sin.sin_port = ip4->udp_port;
355
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100356 ns2_vc_create_ip(fi, nse, &remote, ip4->sig_weight, ip4->data_weight);
Alexander Couzens6a161492020-07-12 13:45:50 +0200357}
358
359static void ns2_nsvc_create_ip6(struct osmo_fsm_inst *fi,
360 struct gprs_ns2_nse *nse,
361 const struct gprs_ns_ie_ip6_elem *ip6)
362{
Alexander Couzens6a161492020-07-12 13:45:50 +0200363 struct osmo_sockaddr remote = {};
364 /* copy over. Both data structures use network byte order */
365 remote.u.sin6.sin6_family = AF_INET6;
366 remote.u.sin6.sin6_addr = ip6->ip_addr;
367 remote.u.sin6.sin6_port = ip6->udp_port;
368
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100369 ns2_vc_create_ip(fi, nse, &remote, ip6->sig_weight, ip6->data_weight);
Alexander Couzens6a161492020-07-12 13:45:50 +0200370}
371
Harald Weltee8c61062021-03-24 13:16:27 +0100372static struct gprs_ns2_vc *nsvc_for_bind_and_remote(struct gprs_ns2_nse *nse,
373 struct gprs_ns2_vc_bind *bind,
374 const struct osmo_sockaddr *remote)
375{
376 struct gprs_ns2_vc *nsvc;
377
378 llist_for_each_entry(nsvc, &nse->nsvc, list) {
379 if (nsvc->bind != bind)
380 continue;
381
382 if (!osmo_sockaddr_cmp(remote, gprs_ns2_ip_vc_remote(nsvc)))
383 return nsvc;
384 }
385 return NULL;
386}
Alexander Couzens6a161492020-07-12 13:45:50 +0200387
388static int create_missing_nsvcs(struct osmo_fsm_inst *fi)
389{
390 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
391 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
392 struct gprs_ns2_vc *nsvc;
Harald Welte3053bbb2021-03-24 13:22:18 +0100393 struct ns2_sns_bind *sbind;
Alexander Couzens6a161492020-07-12 13:45:50 +0200394 struct osmo_sockaddr remote = { };
395 unsigned int i;
396
Harald Weltee8c61062021-03-24 13:16:27 +0100397 /* iterate over all remote IPv4 endpoints */
Alexander Couzens71128672021-06-05 18:44:01 +0200398 for (i = 0; i < gss->remote.num_ip4; i++) {
399 const struct gprs_ns_ie_ip4_elem *ip4 = &gss->remote.ip4[i];
Alexander Couzens6a161492020-07-12 13:45:50 +0200400
401 remote.u.sin.sin_family = AF_INET;
402 remote.u.sin.sin_addr.s_addr = ip4->ip_addr;
403 remote.u.sin.sin_port = ip4->udp_port;
404
Harald Welte3053bbb2021-03-24 13:22:18 +0100405 /* iterate over all local binds within this SNS */
406 llist_for_each_entry(sbind, &gss->binds, list) {
407 struct gprs_ns2_vc_bind *bind = sbind->bind;
408
Harald Weltee8c61062021-03-24 13:16:27 +0100409 /* we only care about UDP binds */
Daniel Willmann967e2c12021-01-14 16:58:17 +0100410 if (bind->ll != GPRS_NS2_LL_UDP)
411 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200412
Harald Weltee8c61062021-03-24 13:16:27 +0100413 nsvc = nsvc_for_bind_and_remote(nse, bind, &remote);
414 if (!nsvc) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200415 nsvc = gprs_ns2_ip_connect_inactive(bind, &remote, nse, 0);
416 if (!nsvc) {
417 /* TODO: add to a list to send back a NS-STATUS */
418 continue;
419 }
420 }
421
422 /* update data / signalling weight */
423 nsvc->data_weight = ip4->data_weight;
424 nsvc->sig_weight = ip4->sig_weight;
425 nsvc->sns_only = false;
426 }
427 }
428
Harald Weltee8c61062021-03-24 13:16:27 +0100429 /* iterate over all remote IPv4 endpoints */
Alexander Couzens71128672021-06-05 18:44:01 +0200430 for (i = 0; i < gss->remote.num_ip6; i++) {
431 const struct gprs_ns_ie_ip6_elem *ip6 = &gss->remote.ip6[i];
Alexander Couzens6a161492020-07-12 13:45:50 +0200432
433 remote.u.sin6.sin6_family = AF_INET6;
434 remote.u.sin6.sin6_addr = ip6->ip_addr;
435 remote.u.sin6.sin6_port = ip6->udp_port;
436
Harald Welte3053bbb2021-03-24 13:22:18 +0100437 /* iterate over all local binds within this SNS */
438 llist_for_each_entry(sbind, &gss->binds, list) {
439 struct gprs_ns2_vc_bind *bind = sbind->bind;
440
Daniel Willmann967e2c12021-01-14 16:58:17 +0100441 if (bind->ll != GPRS_NS2_LL_UDP)
442 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200443
Harald Weltee8c61062021-03-24 13:16:27 +0100444 /* we only care about UDP binds */
445 nsvc = nsvc_for_bind_and_remote(nse, bind, &remote);
446 if (!nsvc) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200447 nsvc = gprs_ns2_ip_connect_inactive(bind, &remote, nse, 0);
448 if (!nsvc) {
449 /* TODO: add to a list to send back a NS-STATUS */
450 continue;
451 }
452 }
453
454 /* update data / signalling weight */
455 nsvc->data_weight = ip6->data_weight;
456 nsvc->sig_weight = ip6->sig_weight;
457 nsvc->sns_only = false;
458 }
459 }
460
461
462 return 0;
463}
464
465/* Add a given remote IPv4 element to gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200466static int add_ip4_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
467 const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +0200468{
Alexander Couzens6a161492020-07-12 13:45:50 +0200469 /* check for duplicates */
Alexander Couzenscc56ddc2021-06-06 03:33:35 +0200470 for (unsigned int i = 0; i < elems->num_ip4; i++) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200471 if (memcmp(&elems->ip4[i], ip4, sizeof(*ip4)))
Alexander Couzens6a161492020-07-12 13:45:50 +0200472 continue;
Alexander Couzensd3507e82021-06-06 03:32:32 +0200473 return -1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200474 }
475
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200476 elems->ip4 = talloc_realloc(gss, elems->ip4, struct gprs_ns_ie_ip4_elem,
477 elems->num_ip4+1);
478 elems->ip4[elems->num_ip4] = *ip4;
479 elems->num_ip4 += 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200480 return 0;
481}
482
483/* Remove a given remote IPv4 element from gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200484static int remove_ip4_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
485 const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +0200486{
487 unsigned int i;
488
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200489 for (i = 0; i < elems->num_ip4; i++) {
490 if (memcmp(&elems->ip4[i], ip4, sizeof(*ip4)))
Alexander Couzens6a161492020-07-12 13:45:50 +0200491 continue;
492 /* all array elements < i remain as they are; all > i are shifted left by one */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200493 memmove(&elems->ip4[i], &elems->ip4[i+1], elems->num_ip4-i-1);
494 elems->num_ip4 -= 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200495 return 0;
496 }
497 return -1;
498}
499
500/* update the weights for specified remote IPv4 */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200501static int update_ip4_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
502 const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +0200503{
504 unsigned int i;
505
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200506 for (i = 0; i < elems->num_ip4; i++) {
507 if (elems->ip4[i].ip_addr != ip4->ip_addr ||
508 elems->ip4[i].udp_port != ip4->udp_port)
Alexander Couzens6a161492020-07-12 13:45:50 +0200509 continue;
510
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200511 elems->ip4[i].sig_weight = ip4->sig_weight;
512 elems->ip4[i].data_weight = ip4->data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200513 return 0;
514 }
515 return -1;
516}
517
518/* Add a given remote IPv6 element to gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200519static int add_ip6_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
520 const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +0200521{
Alexander Couzenscc56ddc2021-06-06 03:33:35 +0200522 /* check for duplicates */
523 for (unsigned int i = 0; i < elems->num_ip6; i++) {
524 if (memcmp(&elems->ip6[i].ip_addr, &ip6->ip_addr, sizeof(ip6->ip_addr)) ||
525 elems->ip6[i].udp_port != ip6->udp_port)
526 continue;
527 return -1;
528 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200529
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200530 elems->ip6 = talloc_realloc(gss, elems->ip6, struct gprs_ns_ie_ip6_elem,
531 elems->num_ip6+1);
532 elems->ip6[elems->num_ip6] = *ip6;
533 elems->num_ip6 += 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200534 return 0;
535}
536
537/* Remove a given remote IPv6 element from gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200538static int remove_ip6_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
539 const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +0200540{
541 unsigned int i;
542
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200543 for (i = 0; i < elems->num_ip6; i++) {
544 if (memcmp(&elems->ip6[i], ip6, sizeof(*ip6)))
Alexander Couzens6a161492020-07-12 13:45:50 +0200545 continue;
546 /* all array elements < i remain as they are; all > i are shifted left by one */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200547 memmove(&elems->ip6[i], &elems->ip6[i+1], elems->num_ip6-i-1);
548 elems->num_ip6 -= 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200549 return 0;
550 }
551 return -1;
552}
553
554/* update the weights for specified remote IPv6 */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200555static int update_ip6_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
556 const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +0200557{
558 unsigned int i;
559
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200560 for (i = 0; i < elems->num_ip6; i++) {
561 if (memcmp(&elems->ip6[i].ip_addr, &ip6->ip_addr, sizeof(ip6->ip_addr)) ||
562 elems->ip6[i].udp_port != ip6->udp_port)
Alexander Couzens6a161492020-07-12 13:45:50 +0200563 continue;
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200564 elems->ip6[i].sig_weight = ip6->sig_weight;
565 elems->ip6[i].data_weight = ip6->data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200566 return 0;
567 }
568 return -1;
569}
570
571static int do_sns_change_weight(struct osmo_fsm_inst *fi, const struct gprs_ns_ie_ip4_elem *ip4, const struct gprs_ns_ie_ip6_elem *ip6)
572{
573 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
574 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
575 struct gprs_ns2_vc *nsvc;
576 struct osmo_sockaddr sa = {};
Alexander Couzens9a4cf272020-10-11 20:48:04 +0200577 const struct osmo_sockaddr *remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200578 uint8_t new_signal;
579 uint8_t new_data;
580
581 /* TODO: Upon receiving an SNS-CHANGEWEIGHT PDU, if the resulting sum of the
582 * signalling weights of all the peer IP endpoints configured for this NSE is
583 * equal to zero or if the resulting sum of the data weights of all the peer IP
584 * endpoints configured for this NSE is equal to zero, the BSS/SGSN shall send an
585 * SNS-ACK PDU with a cause code of "Invalid weights". */
586
587 if (ip4) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200588 if (update_ip4_elem(gss, &gss->remote, ip4))
Alexander Couzens6a161492020-07-12 13:45:50 +0200589 return -NS_CAUSE_UNKN_IP_EP;
590
591 /* copy over. Both data structures use network byte order */
592 sa.u.sin.sin_addr.s_addr = ip4->ip_addr;
593 sa.u.sin.sin_port = ip4->udp_port;
594 sa.u.sin.sin_family = AF_INET;
595 new_signal = ip4->sig_weight;
596 new_data = ip4->data_weight;
597 } else if (ip6) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200598 if (update_ip6_elem(gss, &gss->remote, ip6))
Alexander Couzens6a161492020-07-12 13:45:50 +0200599 return -NS_CAUSE_UNKN_IP_EP;
600
601 /* copy over. Both data structures use network byte order */
602 sa.u.sin6.sin6_addr = ip6->ip_addr;
603 sa.u.sin6.sin6_port = ip6->udp_port;
604 sa.u.sin6.sin6_family = AF_INET6;
605 new_signal = ip6->sig_weight;
606 new_data = ip6->data_weight;
607 } else {
608 OSMO_ASSERT(false);
609 }
610
611 llist_for_each_entry(nsvc, &nse->nsvc, list) {
Alexander Couzensc4229a42020-10-11 20:58:04 +0200612 remote = gprs_ns2_ip_vc_remote(nsvc);
Alexander Couzens6a161492020-07-12 13:45:50 +0200613 /* all nsvc in NSE should be IP/UDP nsvc */
614 OSMO_ASSERT(remote);
615
616 if (osmo_sockaddr_cmp(&sa, remote))
617 continue;
618
619 LOGPFSML(fi, LOGL_INFO, "CHANGE-WEIGHT NS-VC %s data_weight %u->%u, sig_weight %u->%u\n",
620 gprs_ns2_ll_str(nsvc), nsvc->data_weight, new_data,
621 nsvc->sig_weight, new_signal);
622
623 nsvc->data_weight = new_data;
624 nsvc->sig_weight = new_signal;
625 }
626
627 return 0;
628}
629
630static int do_sns_delete(struct osmo_fsm_inst *fi,
631 const struct gprs_ns_ie_ip4_elem *ip4,
632 const struct gprs_ns_ie_ip6_elem *ip6)
633{
634 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
635 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
636 struct gprs_ns2_vc *nsvc, *tmp;
Alexander Couzens9a4cf272020-10-11 20:48:04 +0200637 const struct osmo_sockaddr *remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200638 struct osmo_sockaddr sa = {};
639
640 if (ip4) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200641 if (remove_ip4_elem(gss, &gss->remote, ip4) < 0)
Alexander Couzens6a161492020-07-12 13:45:50 +0200642 return -NS_CAUSE_UNKN_IP_EP;
643 /* copy over. Both data structures use network byte order */
644 sa.u.sin.sin_addr.s_addr = ip4->ip_addr;
645 sa.u.sin.sin_port = ip4->udp_port;
646 sa.u.sin.sin_family = AF_INET;
647 } else if (ip6) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200648 if (remove_ip6_elem(gss, &gss->remote, ip6))
Alexander Couzens6a161492020-07-12 13:45:50 +0200649 return -NS_CAUSE_UNKN_IP_EP;
650
651 /* copy over. Both data structures use network byte order */
652 sa.u.sin6.sin6_addr = ip6->ip_addr;
653 sa.u.sin6.sin6_port = ip6->udp_port;
654 sa.u.sin6.sin6_family = AF_INET6;
655 } else {
656 OSMO_ASSERT(false);
657 }
658
659 llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {
Alexander Couzensc4229a42020-10-11 20:58:04 +0200660 remote = gprs_ns2_ip_vc_remote(nsvc);
Alexander Couzens6a161492020-07-12 13:45:50 +0200661 /* all nsvc in NSE should be IP/UDP nsvc */
662 OSMO_ASSERT(remote);
663 if (osmo_sockaddr_cmp(&sa, remote))
664 continue;
665
666 LOGPFSML(fi, LOGL_INFO, "DELETE NS-VC %s\n", gprs_ns2_ll_str(nsvc));
667 gprs_ns2_free_nsvc(nsvc);
668 }
669
670 return 0;
671}
672
673static int do_sns_add(struct osmo_fsm_inst *fi,
674 const struct gprs_ns_ie_ip4_elem *ip4,
675 const struct gprs_ns_ie_ip6_elem *ip6)
676{
677 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
678 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
679 struct gprs_ns2_vc *nsvc;
680 int rc = 0;
681
682 /* Upon receiving an SNS-ADD PDU, if the consequent number of IPv4 endpoints
683 * exceeds the number of IPv4 endpoints supported by the NSE, the NSE shall send
684 * an SNS-ACK PDU with a cause code set to "Invalid number of IP4 Endpoints". */
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200685 switch (gss->family) {
686 case AF_INET:
Alexander Couzensd3507e82021-06-06 03:32:32 +0200687 if (gss->remote.num_ip4 >= gss->num_max_ip4_remote)
688 return -NS_CAUSE_INVAL_NR_NS_VC;
689 /* TODO: log message duplicate */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200690 rc = add_ip4_elem(gss, &gss->remote, ip4);
Alexander Couzens6a161492020-07-12 13:45:50 +0200691 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200692 case AF_INET6:
Alexander Couzensd3507e82021-06-06 03:32:32 +0200693 if (gss->remote.num_ip6 >= gss->num_max_ip6_remote)
694 return -NS_CAUSE_INVAL_NR_NS_VC;
695 /* TODO: log message duplicate */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200696 rc = add_ip6_elem(gss, &gss->remote, ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +0200697 break;
698 default:
699 /* the gss->ip is initialized with the bss */
700 OSMO_ASSERT(false);
701 }
702
703 if (rc)
Alexander Couzensd3507e82021-06-06 03:32:32 +0200704 return -NS_CAUSE_PROTO_ERR_UNSPEC;
Alexander Couzens6a161492020-07-12 13:45:50 +0200705
706 /* Upon receiving an SNS-ADD PDU containing an already configured IP endpoint the
707 * NSE shall send an SNS-ACK PDU with the cause code "Protocol error -
708 * unspecified" */
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200709 switch (gss->family) {
710 case AF_INET:
Alexander Couzens6a161492020-07-12 13:45:50 +0200711 nsvc = nsvc_by_ip4_elem(nse, ip4);
712 if (nsvc) {
713 /* the nsvc should be already in sync with the ip4 / ip6 elements */
714 return -NS_CAUSE_PROTO_ERR_UNSPEC;
715 }
716
717 /* TODO: failure case */
718 ns2_nsvc_create_ip4(fi, nse, ip4);
719 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200720 case AF_INET6:
Alexander Couzens6a161492020-07-12 13:45:50 +0200721 nsvc = nsvc_by_ip6_elem(nse, ip6);
722 if (nsvc) {
723 /* the nsvc should be already in sync with the ip4 / ip6 elements */
724 return -NS_CAUSE_PROTO_ERR_UNSPEC;
725 }
726
727 /* TODO: failure case */
728 ns2_nsvc_create_ip6(fi, nse, ip6);
729 break;
730 }
731
732 gprs_ns2_start_alive_all_nsvcs(nse);
733
734 return 0;
735}
736
737
Harald Welte694dad52021-03-23 15:22:16 +0100738static void ns2_sns_st_bss_unconfigured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +0200739{
Harald Weltef61a9152021-03-02 22:20:17 +0100740 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
741 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
Alexander Couzense769f522020-12-07 07:37:07 +0100742 /* empty state - SNS Select will start by ns2_sns_st_all_action() */
Alexander Couzens6a161492020-07-12 13:45:50 +0200743}
744
Harald Welte694dad52021-03-23 15:22:16 +0100745static void ns2_sns_st_bss_size(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +0200746{
Harald Weltef61a9152021-03-02 22:20:17 +0100747 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +0200748 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
749 struct gprs_ns2_inst *nsi = nse->nsi;
750 struct tlv_parsed *tp = NULL;
751
Harald Weltef61a9152021-03-02 22:20:17 +0100752 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
753
Alexander Couzens6a161492020-07-12 13:45:50 +0200754 switch (event) {
Alexander Couzens67725e22021-02-15 02:37:03 +0100755 case GPRS_SNS_EV_RX_SIZE_ACK:
Alexander Couzens6a161492020-07-12 13:45:50 +0200756 tp = data;
757 if (TLVP_VAL_MINLEN(tp, NS_IE_CAUSE, 1)) {
758 LOGPFSML(fi, LOGL_ERROR, "SNS-SIZE-ACK with cause %s\n",
759 gprs_ns2_cause_str(*TLVP_VAL(tp, NS_IE_CAUSE)));
760 /* TODO: What to do? */
761 } else {
Harald Welte694dad52021-03-23 15:22:16 +0100762 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_CONFIG_BSS,
Alexander Couzens6a161492020-07-12 13:45:50 +0200763 nsi->timeout[NS_TOUT_TSNS_PROV], 2);
764 }
765 break;
766 default:
767 OSMO_ASSERT(0);
768 }
769}
770
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200771static int ns2_sns_count_num_local_ep(struct osmo_fsm_inst *fi, int ip_proto)
Harald Welte01fa6a32021-03-04 19:49:38 +0100772{
773 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
774 struct ns2_sns_bind *sbind;
775 int count = 0;
776
777 llist_for_each_entry(sbind, &gss->binds, list) {
778 const struct osmo_sockaddr *sa = gprs_ns2_ip_bind_sockaddr(sbind->bind);
779 if (!sa)
780 continue;
781
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200782 switch (ip_proto) {
783 case AF_INET:
Harald Welte01fa6a32021-03-04 19:49:38 +0100784 if (sa->u.sas.ss_family == AF_INET)
785 count++;
786 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200787 case AF_INET6:
Harald Welte01fa6a32021-03-04 19:49:38 +0100788 if (sa->u.sas.ss_family == AF_INET6)
789 count++;
790 break;
791 }
792 }
793 return count;
794}
795
Harald Welte24920e22021-03-04 13:03:27 +0100796static void ns2_sns_compute_local_ep_from_binds(struct osmo_fsm_inst *fi)
Alexander Couzens6a161492020-07-12 13:45:50 +0200797{
798 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzense769f522020-12-07 07:37:07 +0100799 struct gprs_ns_ie_ip4_elem *ip4_elems;
800 struct gprs_ns_ie_ip6_elem *ip6_elems;
801 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100802 struct ns2_sns_bind *sbind;
Harald Welte4f127462021-03-02 20:49:10 +0100803 const struct osmo_sockaddr *remote;
Alexander Couzense769f522020-12-07 07:37:07 +0100804 const struct osmo_sockaddr *sa;
805 struct osmo_sockaddr local;
806 int count;
Alexander Couzens6a161492020-07-12 13:45:50 +0200807
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200808 ns2_clear_elems(&gss->local);
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100809
Alexander Couzense769f522020-12-07 07:37:07 +0100810 /* no initial available */
Harald Welte4f127462021-03-02 20:49:10 +0100811 if (gss->role == GPRS_SNS_ROLE_BSS) {
812 if (!gss->initial)
813 return;
814 remote = &gss->initial->saddr;
815 } else
816 remote = gprs_ns2_ip_vc_remote(gss->sns_nsvc);
Alexander Couzense769f522020-12-07 07:37:07 +0100817
818 /* count how many bindings are available (only UDP binds) */
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100819 count = llist_count(&gss->binds);
Alexander Couzense769f522020-12-07 07:37:07 +0100820 if (count == 0) {
Harald Welte05992872021-03-04 15:49:21 +0100821 LOGPFSML(fi, LOGL_ERROR, "No local binds for this NSE -> cannot determine IP endpoints\n");
Alexander Couzense769f522020-12-07 07:37:07 +0100822 return;
823 }
824
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200825 switch (gss->family) {
826 case AF_INET:
Alexander Couzens71128672021-06-05 18:44:01 +0200827 ip4_elems = talloc_realloc(fi, gss->local.ip4, struct gprs_ns_ie_ip4_elem, count);
Alexander Couzense769f522020-12-07 07:37:07 +0100828 if (!ip4_elems)
829 return;
830
Alexander Couzens71128672021-06-05 18:44:01 +0200831 gss->local.ip4 = ip4_elems;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100832 llist_for_each_entry(sbind, &gss->binds, list) {
833 bind = sbind->bind;
Alexander Couzense769f522020-12-07 07:37:07 +0100834 sa = gprs_ns2_ip_bind_sockaddr(bind);
835 if (!sa)
836 continue;
837
838 if (sa->u.sas.ss_family != AF_INET)
839 continue;
840
841 /* check if this is an specific bind */
842 if (sa->u.sin.sin_addr.s_addr == 0) {
843 if (osmo_sockaddr_local_ip(&local, remote))
844 continue;
845
846 ip4_elems->ip_addr = local.u.sin.sin_addr.s_addr;
847 } else {
848 ip4_elems->ip_addr = sa->u.sin.sin_addr.s_addr;
849 }
850
851 ip4_elems->udp_port = sa->u.sin.sin_port;
Alexander Couzensc4704762021-02-08 23:13:12 +0100852 ip4_elems->sig_weight = bind->sns_sig_weight;
853 ip4_elems->data_weight = bind->sns_data_weight;
Alexander Couzense769f522020-12-07 07:37:07 +0100854 ip4_elems++;
855 }
856
Alexander Couzens71128672021-06-05 18:44:01 +0200857 gss->local.num_ip4 = count;
858 gss->num_max_nsvcs = OSMO_MAX(gss->num_max_ip4_remote * gss->local.num_ip4, 8);
Alexander Couzense769f522020-12-07 07:37:07 +0100859 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200860 case AF_INET6:
Alexander Couzense769f522020-12-07 07:37:07 +0100861 /* IPv6 */
Alexander Couzens71128672021-06-05 18:44:01 +0200862 ip6_elems = talloc_realloc(fi, gss->local.ip6, struct gprs_ns_ie_ip6_elem, count);
Alexander Couzense769f522020-12-07 07:37:07 +0100863 if (!ip6_elems)
864 return;
865
Alexander Couzens71128672021-06-05 18:44:01 +0200866 gss->local.ip6 = ip6_elems;
Alexander Couzense769f522020-12-07 07:37:07 +0100867
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100868 llist_for_each_entry(sbind, &gss->binds, list) {
869 bind = sbind->bind;
Alexander Couzense769f522020-12-07 07:37:07 +0100870 sa = gprs_ns2_ip_bind_sockaddr(bind);
871 if (!sa)
872 continue;
873
874 if (sa->u.sas.ss_family != AF_INET6)
875 continue;
876
877 /* check if this is an specific bind */
878 if (IN6_IS_ADDR_UNSPECIFIED(&sa->u.sin6.sin6_addr)) {
879 if (osmo_sockaddr_local_ip(&local, remote))
880 continue;
881
882 ip6_elems->ip_addr = local.u.sin6.sin6_addr;
883 } else {
884 ip6_elems->ip_addr = sa->u.sin6.sin6_addr;
885 }
886
887 ip6_elems->udp_port = sa->u.sin.sin_port;
Alexander Couzensc4704762021-02-08 23:13:12 +0100888 ip6_elems->sig_weight = bind->sns_sig_weight;
889 ip6_elems->data_weight = bind->sns_data_weight;
Alexander Couzense769f522020-12-07 07:37:07 +0100890
891 ip6_elems++;
892 }
Alexander Couzens71128672021-06-05 18:44:01 +0200893 gss->local.num_ip6 = count;
894 gss->num_max_nsvcs = OSMO_MAX(gss->num_max_ip6_remote * gss->local.num_ip6, 8);
Alexander Couzense769f522020-12-07 07:37:07 +0100895 break;
896 }
Harald Welte24920e22021-03-04 13:03:27 +0100897}
898
Alexander Couzens6608ce92021-04-26 20:39:46 +0200899static void ns2_sns_choose_next_bind(struct ns2_sns_state *gss)
900{
901 /* take the first bind or take the next bind */
902 if (!gss->initial_bind || gss->initial_bind->list.next == &gss->binds)
903 gss->initial_bind = llist_first_entry_or_null(&gss->binds, struct ns2_sns_bind, list);
904 else
905 gss->initial_bind = llist_entry(gss->initial_bind->list.next, struct ns2_sns_bind, list);
906}
907
Harald Welte24920e22021-03-04 13:03:27 +0100908/* setup all dynamic SNS settings, create a new nsvc and send the SIZE */
Harald Welte694dad52021-03-23 15:22:16 +0100909static void ns2_sns_st_bss_size_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
Harald Welte24920e22021-03-04 13:03:27 +0100910{
911 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
912
Harald Weltef61a9152021-03-02 22:20:17 +0100913 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
914
Harald Welte24920e22021-03-04 13:03:27 +0100915 /* on a generic failure, the timer callback will recover */
916 if (old_state != GPRS_SNS_ST_UNCONFIGURED)
917 ns2_prim_status_ind(gss->nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_FAILURE);
Harald Welte694dad52021-03-23 15:22:16 +0100918 if (old_state != GPRS_SNS_ST_BSS_SIZE)
Harald Welte24920e22021-03-04 13:03:27 +0100919 gss->N = 0;
920
921 gss->alive = false;
922
923 ns2_sns_compute_local_ep_from_binds(fi);
Alexander Couzens6608ce92021-04-26 20:39:46 +0200924 ns2_sns_choose_next_bind(gss);
Harald Welte24920e22021-03-04 13:03:27 +0100925
926 /* setup the NSVC */
927 if (!gss->sns_nsvc) {
928 struct gprs_ns2_vc_bind *bind = gss->initial_bind->bind;
929 struct osmo_sockaddr *remote = &gss->initial->saddr;
930 gss->sns_nsvc = ns2_ip_bind_connect(bind, gss->nse, remote);
931 if (!gss->sns_nsvc)
932 return;
Harald Weltec962a2e2021-03-05 08:09:08 +0100933 /* A pre-configured endpoint shall not be used for NSE data or signalling traffic
934 * (with the exception of Size and Configuration procedures) unless it is configured
935 * by the SGSN using the auto-configuration procedures */
Harald Welte24920e22021-03-04 13:03:27 +0100936 gss->sns_nsvc->sns_only = true;
937 }
938
Alexander Couzens6a161492020-07-12 13:45:50 +0200939 if (gss->num_max_ip4_remote > 0)
Alexander Couzens71128672021-06-05 18:44:01 +0200940 ns2_tx_sns_size(gss->sns_nsvc, true, gss->num_max_nsvcs, gss->local.num_ip4, -1);
Alexander Couzens6a161492020-07-12 13:45:50 +0200941 else
Alexander Couzens71128672021-06-05 18:44:01 +0200942 ns2_tx_sns_size(gss->sns_nsvc, true, gss->num_max_nsvcs, -1, gss->local.num_ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +0200943}
944
Harald Welte694dad52021-03-23 15:22:16 +0100945static void ns2_sns_st_bss_config_bss(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +0200946{
Harald Weltef61a9152021-03-02 22:20:17 +0100947 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens3df58862021-02-05 17:18:08 +0100948 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
Harald Weltef61a9152021-03-02 22:20:17 +0100949 struct tlv_parsed *tp = NULL;
950
951 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
Alexander Couzens6a161492020-07-12 13:45:50 +0200952
953 switch (event) {
Alexander Couzens67725e22021-02-15 02:37:03 +0100954 case GPRS_SNS_EV_RX_CONFIG_ACK:
Alexander Couzens6a161492020-07-12 13:45:50 +0200955 tp = (struct tlv_parsed *) data;
956 if (TLVP_VAL_MINLEN(tp, NS_IE_CAUSE, 1)) {
957 LOGPFSML(fi, LOGL_ERROR, "SNS-CONFIG-ACK with cause %s\n",
958 gprs_ns2_cause_str(*TLVP_VAL(tp, NS_IE_CAUSE)));
959 /* TODO: What to do? */
960 } else {
Harald Welte694dad52021-03-23 15:22:16 +0100961 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_CONFIG_SGSN, nse->nsi->timeout[NS_TOUT_TSNS_PROV], 3);
Alexander Couzens6a161492020-07-12 13:45:50 +0200962 }
963 break;
964 default:
965 OSMO_ASSERT(0);
966 }
967}
968
Harald Welte694dad52021-03-23 15:22:16 +0100969static void ns2_sns_st_bss_config_bss_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
Alexander Couzens6a161492020-07-12 13:45:50 +0200970{
971 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens790a9632021-02-05 17:18:39 +0100972
Harald Weltef61a9152021-03-02 22:20:17 +0100973 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
974
Harald Welte694dad52021-03-23 15:22:16 +0100975 if (old_state != GPRS_SNS_ST_BSS_CONFIG_BSS)
Alexander Couzens790a9632021-02-05 17:18:39 +0100976 gss->N = 0;
977
Alexander Couzens6a161492020-07-12 13:45:50 +0200978 /* Transmit SNS-CONFIG */
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200979 switch (gss->family) {
980 case AF_INET:
Alexander Couzens6a161492020-07-12 13:45:50 +0200981 ns2_tx_sns_config(gss->sns_nsvc, true,
Alexander Couzens71128672021-06-05 18:44:01 +0200982 gss->local.ip4, gss->local.num_ip4,
Alexander Couzense78207f2020-12-07 06:19:29 +0100983 NULL, 0);
Alexander Couzens6a161492020-07-12 13:45:50 +0200984 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200985 case AF_INET6:
Alexander Couzens6a161492020-07-12 13:45:50 +0200986 ns2_tx_sns_config(gss->sns_nsvc, true,
Alexander Couzense78207f2020-12-07 06:19:29 +0100987 NULL, 0,
Alexander Couzens71128672021-06-05 18:44:01 +0200988 gss->local.ip6, gss->local.num_ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +0200989 break;
990 }
991}
992
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100993/* calculate the timeout of the configured state. the configured
994 * state will fail if not at least one NS-VC is alive within X second.
995 */
996static inline int ns_sns_configured_timeout(struct osmo_fsm_inst *fi)
997{
998 int secs;
999 struct gprs_ns2_inst *nsi = nse_inst_from_fi(fi)->nsi;
1000 secs = nsi->timeout[NS_TOUT_TNS_ALIVE] * nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES];
1001 secs += nsi->timeout[NS_TOUT_TNS_TEST];
1002
1003 return secs;
1004}
Alexander Couzens6a161492020-07-12 13:45:50 +02001005
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001006/* append the remote endpoints from the parsed TLV array to the ns2_sns_state */
1007static int ns_sns_append_remote_eps(struct osmo_fsm_inst *fi, const struct tlv_parsed *tp)
Alexander Couzens6a161492020-07-12 13:45:50 +02001008{
1009 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +02001010
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001011 if (TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1012 const struct gprs_ns_ie_ip4_elem *v4_list;
1013 unsigned int num_v4;
1014 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1015 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Alexander Couzens6a161492020-07-12 13:45:50 +02001016
Alexander Couzens71128672021-06-05 18:44:01 +02001017 if (num_v4 && gss->remote.ip6)
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001018 return -NS_CAUSE_INVAL_NR_IPv4_EP;
Alexander Couzens6a161492020-07-12 13:45:50 +02001019
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001020 /* realloc to the new size */
Alexander Couzens71128672021-06-05 18:44:01 +02001021 gss->remote.ip4 = talloc_realloc(gss, gss->remote.ip4,
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001022 struct gprs_ns_ie_ip4_elem,
Alexander Couzens71128672021-06-05 18:44:01 +02001023 gss->remote.num_ip4 + num_v4);
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001024 /* append the new entries to the end of the list */
Alexander Couzens71128672021-06-05 18:44:01 +02001025 memcpy(&gss->remote.ip4[gss->remote.num_ip4], v4_list, num_v4*sizeof(*v4_list));
1026 gss->remote.num_ip4 += num_v4;
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001027
1028 LOGPFSML(fi, LOGL_INFO, "Rx SNS-CONFIG: Remote IPv4 list now %u entries\n",
Alexander Couzens71128672021-06-05 18:44:01 +02001029 gss->remote.num_ip4);
Alexander Couzens6a161492020-07-12 13:45:50 +02001030 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001031
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001032 if (TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1033 const struct gprs_ns_ie_ip6_elem *v6_list;
1034 unsigned int num_v6;
1035 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1036 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
1037
Alexander Couzens71128672021-06-05 18:44:01 +02001038 if (num_v6 && gss->remote.ip4)
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001039 return -NS_CAUSE_INVAL_NR_IPv6_EP;
1040
1041 /* realloc to the new size */
Alexander Couzens71128672021-06-05 18:44:01 +02001042 gss->remote.ip6 = talloc_realloc(gss, gss->remote.ip6,
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001043 struct gprs_ns_ie_ip6_elem,
Alexander Couzens71128672021-06-05 18:44:01 +02001044 gss->remote.num_ip6 + num_v6);
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001045 /* append the new entries to the end of the list */
Alexander Couzens71128672021-06-05 18:44:01 +02001046 memcpy(&gss->remote.ip6[gss->remote.num_ip6], v6_list, num_v6*sizeof(*v6_list));
1047 gss->remote.num_ip6 += num_v6;
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001048
Alexander Couzens71128672021-06-05 18:44:01 +02001049 LOGPFSML(fi, LOGL_INFO, "Rx SNS-CONFIG: Remote IPv6 list now %d entries\n",
1050 gss->remote.num_ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +02001051 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001052
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001053 return 0;
Alexander Couzens6a161492020-07-12 13:45:50 +02001054}
1055
Harald Welte694dad52021-03-23 15:22:16 +01001056static void ns2_sns_st_bss_config_sgsn_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
Alexander Couzens790a9632021-02-05 17:18:39 +01001057{
1058 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1059
Harald Weltef61a9152021-03-02 22:20:17 +01001060 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
1061
Harald Welte694dad52021-03-23 15:22:16 +01001062 if (old_state != GPRS_SNS_ST_BSS_CONFIG_SGSN)
Alexander Couzens790a9632021-02-05 17:18:39 +01001063 gss->N = 0;
1064}
1065
Harald Welte694dad52021-03-23 15:22:16 +01001066static void ns2_sns_st_bss_config_sgsn(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +02001067{
1068 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001069 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
1070 uint8_t cause;
1071 int rc;
Alexander Couzens6a161492020-07-12 13:45:50 +02001072
Harald Weltef61a9152021-03-02 22:20:17 +01001073 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
1074
Alexander Couzens6a161492020-07-12 13:45:50 +02001075 switch (event) {
Alexander Couzens67725e22021-02-15 02:37:03 +01001076 case GPRS_SNS_EV_RX_CONFIG_END:
1077 case GPRS_SNS_EV_RX_CONFIG:
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001078 rc = ns_sns_append_remote_eps(fi, data);
1079 if (rc < 0) {
1080 cause = -rc;
1081 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
1082 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
1083 return;
Alexander Couzens6a161492020-07-12 13:45:50 +02001084 }
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001085 if (event == GPRS_SNS_EV_RX_CONFIG_END) {
1086 /* check if sum of data / sig weights == 0 */
Alexander Couzens019da4b2021-06-06 02:48:18 +02001087 if (ip46_weight_sum_data(&gss->remote) == 0 || ip46_weight_sum_sig(&gss->remote) == 0) {
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001088 cause = NS_CAUSE_INVAL_WEIGH;
1089 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
1090 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
1091 return;
1092 }
1093 create_missing_nsvcs(fi);
1094 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
1095 /* start the test procedure on ALL NSVCs! */
1096 gprs_ns2_start_alive_all_nsvcs(nse);
1097 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0);
1098 } else {
1099 /* just send CONFIG-ACK */
1100 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
1101 osmo_timer_schedule(&fi->timer, nse->nsi->timeout[NS_TOUT_TSNS_PROV], 0);
Alexander Couzens6a161492020-07-12 13:45:50 +02001102 }
1103 break;
1104 default:
1105 OSMO_ASSERT(0);
1106 }
1107}
1108
Alexander Couzens67725e22021-02-15 02:37:03 +01001109/* called when receiving GPRS_SNS_EV_RX_ADD in state configure */
Alexander Couzens6a161492020-07-12 13:45:50 +02001110static void ns2_sns_st_configured_add(struct osmo_fsm_inst *fi,
1111 struct ns2_sns_state *gss,
1112 struct tlv_parsed *tp)
1113{
1114 const struct gprs_ns_ie_ip4_elem *v4_list = NULL;
1115 const struct gprs_ns_ie_ip6_elem *v6_list = NULL;
1116 int num_v4 = 0, num_v6 = 0;
1117 uint8_t trans_id, cause = 0xff;
Harald Welte7da6ace2020-09-18 09:48:05 +02001118 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001119 int rc = 0;
1120
1121 /* TODO: refactor EV_ADD/CHANGE/REMOVE by
1122 * check uniqueness within the lists (no doublicate entries)
1123 * check not-known-by-us and sent back a list of unknown/known values
1124 * (abnormal behaviour according to 48.016)
1125 */
1126
1127 trans_id = *TLVP_VAL(tp, NS_IE_TRANS_ID);
Alexander Couzens077ce5a2021-06-06 01:32:45 +02001128 if (gss->family == AF_INET) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001129 if (!TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1130 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
1131 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1132 return;
1133 }
1134
1135 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1136 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001137 for (i = 0; i < num_v4; i++) {
1138 unsigned int j;
Alexander Couzens6a161492020-07-12 13:45:50 +02001139 rc = do_sns_add(fi, &v4_list[i], NULL);
1140 if (rc < 0) {
1141 /* rollback/undo to restore previous state */
Harald Welte7da6ace2020-09-18 09:48:05 +02001142 for (j = 0; j < i; j++)
Alexander Couzens6a161492020-07-12 13:45:50 +02001143 do_sns_delete(fi, &v4_list[j], NULL);
1144 cause = -rc;
1145 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1146 break;
1147 }
1148 }
1149 } else { /* IPv6 */
1150 if (!TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1151 cause = NS_CAUSE_INVAL_NR_IPv6_EP;
1152 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1153 return;
1154 }
1155
1156 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1157 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001158 for (i = 0; i < num_v6; i++) {
1159 unsigned int j;
Alexander Couzens6a161492020-07-12 13:45:50 +02001160 rc = do_sns_add(fi, NULL, &v6_list[i]);
1161 if (rc < 0) {
1162 /* rollback/undo to restore previous state */
Harald Welte7da6ace2020-09-18 09:48:05 +02001163 for (j = 0; j < i; j++)
Alexander Couzens6a161492020-07-12 13:45:50 +02001164 do_sns_delete(fi, NULL, &v6_list[j]);
1165 cause = -rc;
1166 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1167 break;
1168 }
1169 }
1170 }
1171
1172 /* TODO: correct behaviour is to answer to the *same* NSVC from which the SNS_ADD was received */
1173 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, NULL, v4_list, num_v4, v6_list, num_v6);
1174}
1175
1176static void ns2_sns_st_configured_delete(struct osmo_fsm_inst *fi,
1177 struct ns2_sns_state *gss,
1178 struct tlv_parsed *tp)
1179{
1180 const struct gprs_ns_ie_ip4_elem *v4_list = NULL;
1181 const struct gprs_ns_ie_ip6_elem *v6_list = NULL;
1182 int num_v4 = 0, num_v6 = 0;
1183 uint8_t trans_id, cause = 0xff;
Harald Welte7da6ace2020-09-18 09:48:05 +02001184 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001185 int rc = 0;
1186
1187 /* TODO: split up delete into v4 + v6
1188 * TODO: check if IPv4_LIST or IP_ADDR(v4) is present on IPv6 and vice versa
1189 * TODO: check if IPv4_LIST/IPv6_LIST and IP_ADDR is present at the same time
1190 */
1191 trans_id = *TLVP_VAL(tp, NS_IE_TRANS_ID);
Alexander Couzens077ce5a2021-06-06 01:32:45 +02001192 if (gss->family == AF_INET) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001193 if (TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1194 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1195 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001196 for ( i = 0; i < num_v4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001197 rc = do_sns_delete(fi, &v4_list[i], NULL);
1198 if (rc < 0) {
1199 cause = -rc;
1200 /* continue to delete others */
1201 }
1202 }
1203 if (cause != 0xff) {
1204 /* TODO: create list of not-deleted and return it */
1205 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1206 return;
1207 }
1208
1209 } else if (TLVP_PRESENT(tp, NS_IE_IP_ADDR) && TLVP_LEN(tp, NS_IE_IP_ADDR) == 5) {
1210 /* delete all NS-VCs for given IPv4 address */
1211 const uint8_t *ie = TLVP_VAL(tp, NS_IE_IP_ADDR);
1212 struct gprs_ns_ie_ip4_elem *ip4_remote;
1213 uint32_t ip_addr = *(uint32_t *)(ie+1);
1214 if (ie[0] != 0x01) { /* Address Type != IPv4 */
1215 cause = NS_CAUSE_UNKN_IP_ADDR;
1216 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1217 return;
1218 }
1219 /* make a copy as do_sns_delete() will change the array underneath us */
Alexander Couzens71128672021-06-05 18:44:01 +02001220 ip4_remote = talloc_memdup(fi, gss->remote.ip4,
1221 gss->remote.num_ip4 * sizeof(*v4_list));
1222 for (i = 0; i < gss->remote.num_ip4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001223 if (ip4_remote[i].ip_addr == ip_addr) {
1224 rc = do_sns_delete(fi, &ip4_remote[i], NULL);
1225 if (rc < 0) {
1226 cause = -rc;
1227 /* continue to delete others */
1228 }
1229 }
1230 }
1231 talloc_free(ip4_remote);
1232 if (cause != 0xff) {
1233 /* TODO: create list of not-deleted and return it */
1234 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1235 return;
1236 }
1237 } else {
1238 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
1239 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1240 return;
1241 }
1242 } else { /* IPv6 */
1243 if (TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1244 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1245 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001246 for (i = 0; i < num_v6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001247 rc = do_sns_delete(fi, NULL, &v6_list[i]);
1248 if (rc < 0) {
1249 cause = -rc;
1250 /* continue to delete others */
1251 }
1252 }
1253 if (cause != 0xff) {
1254 /* TODO: create list of not-deleted and return it */
1255 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1256 return;
1257 }
1258 } else if (TLVP_PRES_LEN(tp, NS_IE_IP_ADDR, 17)) {
1259 /* delete all NS-VCs for given IPv4 address */
1260 const uint8_t *ie = TLVP_VAL(tp, NS_IE_IP_ADDR);
1261 struct gprs_ns_ie_ip6_elem *ip6_remote;
1262 struct in6_addr ip6_addr;
Harald Welte7da6ace2020-09-18 09:48:05 +02001263 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001264 if (ie[0] != 0x02) { /* Address Type != IPv6 */
1265 cause = NS_CAUSE_UNKN_IP_ADDR;
1266 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1267 return;
1268 }
1269 memcpy(&ip6_addr, (ie+1), sizeof(struct in6_addr));
1270 /* make a copy as do_sns_delete() will change the array underneath us */
Alexander Couzens71128672021-06-05 18:44:01 +02001271 ip6_remote = talloc_memdup(fi, gss->remote.ip6,
1272 gss->remote.num_ip6 * sizeof(*v4_list));
1273 for (i = 0; i < gss->remote.num_ip6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001274 if (!memcmp(&ip6_remote[i].ip_addr, &ip6_addr, sizeof(struct in6_addr))) {
1275 rc = do_sns_delete(fi, NULL, &ip6_remote[i]);
1276 if (rc < 0) {
1277 cause = -rc;
1278 /* continue to delete others */
1279 }
1280 }
1281 }
1282
1283 talloc_free(ip6_remote);
1284 if (cause != 0xff) {
1285 /* TODO: create list of not-deleted and return it */
1286 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1287 return;
1288 }
1289 } else {
1290 cause = NS_CAUSE_INVAL_NR_IPv6_EP;
1291 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1292 return;
1293 }
1294 }
1295 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, NULL, v4_list, num_v4, v6_list, num_v6);
1296}
1297
1298static void ns2_sns_st_configured_change(struct osmo_fsm_inst *fi,
1299 struct ns2_sns_state *gss,
1300 struct tlv_parsed *tp)
1301{
1302 const struct gprs_ns_ie_ip4_elem *v4_list = NULL;
1303 const struct gprs_ns_ie_ip6_elem *v6_list = NULL;
1304 int num_v4 = 0, num_v6 = 0;
1305 uint8_t trans_id, cause = 0xff;
1306 int rc = 0;
Harald Welte7da6ace2020-09-18 09:48:05 +02001307 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001308
1309 trans_id = *TLVP_VAL(tp, NS_IE_TRANS_ID);
1310 if (TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1311 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1312 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001313 for (i = 0; i < num_v4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001314 rc = do_sns_change_weight(fi, &v4_list[i], NULL);
1315 if (rc < 0) {
1316 cause = -rc;
1317 /* continue to others */
1318 }
1319 }
1320 if (cause != 0xff) {
1321 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1322 return;
1323 }
1324 } else if (TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1325 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1326 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001327 for (i = 0; i < num_v6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001328 rc = do_sns_change_weight(fi, NULL, &v6_list[i]);
1329 if (rc < 0) {
1330 cause = -rc;
1331 /* continue to others */
1332 }
1333 }
1334 if (cause != 0xff) {
1335 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1336 return;
1337 }
1338 } else {
1339 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
1340 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1341 return;
1342 }
1343 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, NULL, v4_list, num_v4, v6_list, num_v6);
1344}
1345
1346static void ns2_sns_st_configured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1347{
1348 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1349 struct tlv_parsed *tp = data;
1350
1351 switch (event) {
Alexander Couzens67725e22021-02-15 02:37:03 +01001352 case GPRS_SNS_EV_RX_ADD:
Alexander Couzens6a161492020-07-12 13:45:50 +02001353 ns2_sns_st_configured_add(fi, gss, tp);
1354 break;
Alexander Couzens67725e22021-02-15 02:37:03 +01001355 case GPRS_SNS_EV_RX_DELETE:
Alexander Couzens6a161492020-07-12 13:45:50 +02001356 ns2_sns_st_configured_delete(fi, gss, tp);
1357 break;
Alexander Couzens67725e22021-02-15 02:37:03 +01001358 case GPRS_SNS_EV_RX_CHANGE_WEIGHT:
Alexander Couzens6a161492020-07-12 13:45:50 +02001359 ns2_sns_st_configured_change(fi, gss, tp);
1360 break;
Alexander Couzens67725e22021-02-15 02:37:03 +01001361 case GPRS_SNS_EV_REQ_NSVC_ALIVE:
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001362 osmo_timer_del(&fi->timer);
1363 break;
Alexander Couzens6a161492020-07-12 13:45:50 +02001364 }
1365}
1366
1367static void ns2_sns_st_configured_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
1368{
Alexander Couzenscdb2baa2021-04-01 15:29:16 +02001369 struct gprs_ns2_vc *nsvc;
1370 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +02001371 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
Alexander Couzenscdb2baa2021-04-01 15:29:16 +02001372 /* NS-VC status updates are only parsed in ST_CONFIGURED.
1373 * Do an initial check if there are any nsvc alive atm */
1374 llist_for_each_entry(nsvc, &nse->nsvc, list) {
1375 if (ns2_vc_is_unblocked(nsvc)) {
1376 gss->alive = true;
1377 osmo_timer_del(&fi->timer);
1378 break;
1379 }
1380 }
1381
Alexander Couzens53e70092021-04-06 15:45:47 +02001382 /* remove the initial NSVC if the NSVC isn't part of the configuration */
1383 if (gss->sns_nsvc->sns_only)
1384 gprs_ns2_free_nsvc(gss->sns_nsvc);
1385
Alexander Couzens138b96f2021-01-25 16:23:29 +01001386 ns2_prim_status_ind(nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_CONFIGURED);
Alexander Couzens6a161492020-07-12 13:45:50 +02001387}
1388
1389static const struct osmo_fsm_state ns2_sns_bss_states[] = {
1390 [GPRS_SNS_ST_UNCONFIGURED] = {
Alexander Couzense769f522020-12-07 07:37:07 +01001391 .in_event_mask = 0, /* handled by all_state_action */
Alexander Couzens0a7c5ee2021-04-10 18:20:21 +02001392 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
1393 S(GPRS_SNS_ST_BSS_SIZE),
Alexander Couzens6a161492020-07-12 13:45:50 +02001394 .name = "UNCONFIGURED",
Harald Welte694dad52021-03-23 15:22:16 +01001395 .action = ns2_sns_st_bss_unconfigured,
Alexander Couzens6a161492020-07-12 13:45:50 +02001396 },
Harald Welte694dad52021-03-23 15:22:16 +01001397 [GPRS_SNS_ST_BSS_SIZE] = {
Alexander Couzens67725e22021-02-15 02:37:03 +01001398 .in_event_mask = S(GPRS_SNS_EV_RX_SIZE_ACK),
Alexander Couzens6a161492020-07-12 13:45:50 +02001399 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001400 S(GPRS_SNS_ST_BSS_SIZE) |
1401 S(GPRS_SNS_ST_BSS_CONFIG_BSS),
1402 .name = "BSS_SIZE",
1403 .action = ns2_sns_st_bss_size,
1404 .onenter = ns2_sns_st_bss_size_onenter,
Alexander Couzens6a161492020-07-12 13:45:50 +02001405 },
Harald Welte694dad52021-03-23 15:22:16 +01001406 [GPRS_SNS_ST_BSS_CONFIG_BSS] = {
Alexander Couzens67725e22021-02-15 02:37:03 +01001407 .in_event_mask = S(GPRS_SNS_EV_RX_CONFIG_ACK),
Alexander Couzens6a161492020-07-12 13:45:50 +02001408 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001409 S(GPRS_SNS_ST_BSS_CONFIG_BSS) |
1410 S(GPRS_SNS_ST_BSS_CONFIG_SGSN) |
1411 S(GPRS_SNS_ST_BSS_SIZE),
1412 .name = "BSS_CONFIG_BSS",
1413 .action = ns2_sns_st_bss_config_bss,
1414 .onenter = ns2_sns_st_bss_config_bss_onenter,
Alexander Couzens6a161492020-07-12 13:45:50 +02001415 },
Harald Welte694dad52021-03-23 15:22:16 +01001416 [GPRS_SNS_ST_BSS_CONFIG_SGSN] = {
Alexander Couzens67725e22021-02-15 02:37:03 +01001417 .in_event_mask = S(GPRS_SNS_EV_RX_CONFIG) |
1418 S(GPRS_SNS_EV_RX_CONFIG_END),
Alexander Couzens6a161492020-07-12 13:45:50 +02001419 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001420 S(GPRS_SNS_ST_BSS_CONFIG_SGSN) |
Alexander Couzens6a161492020-07-12 13:45:50 +02001421 S(GPRS_SNS_ST_CONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001422 S(GPRS_SNS_ST_BSS_SIZE),
1423 .name = "BSS_CONFIG_SGSN",
1424 .action = ns2_sns_st_bss_config_sgsn,
1425 .onenter = ns2_sns_st_bss_config_sgsn_onenter,
Alexander Couzens6a161492020-07-12 13:45:50 +02001426 },
1427 [GPRS_SNS_ST_CONFIGURED] = {
Alexander Couzens67725e22021-02-15 02:37:03 +01001428 .in_event_mask = S(GPRS_SNS_EV_RX_ADD) |
1429 S(GPRS_SNS_EV_RX_DELETE) |
1430 S(GPRS_SNS_EV_RX_CHANGE_WEIGHT) |
1431 S(GPRS_SNS_EV_REQ_NSVC_ALIVE),
Alexander Couzense03d8632020-12-06 03:31:44 +01001432 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001433 S(GPRS_SNS_ST_BSS_SIZE),
Alexander Couzens6a161492020-07-12 13:45:50 +02001434 .name = "CONFIGURED",
1435 .action = ns2_sns_st_configured,
1436 .onenter = ns2_sns_st_configured_onenter,
1437 },
1438};
1439
1440static int ns2_sns_fsm_bss_timer_cb(struct osmo_fsm_inst *fi)
1441{
Alexander Couzens90ee9632020-12-07 06:18:32 +01001442 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +02001443 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
1444 struct gprs_ns2_inst *nsi = nse->nsi;
1445
Alexander Couzens90ee9632020-12-07 06:18:32 +01001446 gss->N++;
Alexander Couzens6a161492020-07-12 13:45:50 +02001447 switch (fi->T) {
1448 case 1:
Alexander Couzensa367d082020-12-21 14:06:24 +01001449 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_SIZE_RETRIES]) {
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001450 sns_failed(fi, "Size retries failed. Selecting next IP-SNS endpoint.");
Alexander Couzensa367d082020-12-21 14:06:24 +01001451 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001452 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_SIZE, nsi->timeout[NS_TOUT_TSNS_PROV], 1);
Alexander Couzensa367d082020-12-21 14:06:24 +01001453 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001454 break;
1455 case 2:
Alexander Couzensa367d082020-12-21 14:06:24 +01001456 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001457 sns_failed(fi, "BSS Config retries failed. Selecting next IP-SNS endpoint");
Alexander Couzensa367d082020-12-21 14:06:24 +01001458 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001459 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_CONFIG_BSS, nsi->timeout[NS_TOUT_TSNS_PROV], 2);
Alexander Couzensa367d082020-12-21 14:06:24 +01001460 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001461 break;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001462 case 3:
Alexander Couzens3df58862021-02-05 17:18:08 +01001463 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001464 sns_failed(fi, "SGSN Config retries failed. Selecting next IP-SNS endpoint.");
Alexander Couzens3df58862021-02-05 17:18:08 +01001465 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001466 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_CONFIG_SGSN, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
Alexander Couzens3df58862021-02-05 17:18:08 +01001467 }
1468 break;
1469 case 4:
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001470 sns_failed(fi, "Config succeeded but no NS-VC came online. Selecting next IP-SNS endpoint.");
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001471 break;
Alexander Couzens6a161492020-07-12 13:45:50 +02001472 }
1473 return 0;
1474}
1475
Harald Welte9e37bf42021-03-02 20:48:31 +01001476/* common allstate-action for both roles */
Alexander Couzens6a161492020-07-12 13:45:50 +02001477static void ns2_sns_st_all_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1478{
1479 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001480 struct ns2_sns_bind *sbind;
1481 struct gprs_ns2_vc *nsvc, *nsvc2;
Alexander Couzens6a161492020-07-12 13:45:50 +02001482
Alexander Couzense769f522020-12-07 07:37:07 +01001483 switch (event) {
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001484 case GPRS_SNS_EV_REQ_ADD_BIND:
1485 sbind = data;
1486 switch (fi->state) {
1487 case GPRS_SNS_ST_UNCONFIGURED:
Alexander Couzens67725e22021-02-15 02:37:03 +01001488 osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_SELECT_ENDPOINT, NULL);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001489 break;
Harald Welte694dad52021-03-23 15:22:16 +01001490 case GPRS_SNS_ST_BSS_SIZE:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001491 /* TODO: add the ip4 element to the list */
1492 break;
Harald Welte694dad52021-03-23 15:22:16 +01001493 case GPRS_SNS_ST_BSS_CONFIG_BSS:
1494 case GPRS_SNS_ST_BSS_CONFIG_SGSN:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001495 case GPRS_SNS_ST_CONFIGURED:
1496 /* TODO: add to SNS-IP procedure queue & add nsvc() */
1497 break;
1498 }
1499 break;
1500 case GPRS_SNS_EV_REQ_DELETE_BIND:
1501 sbind = data;
1502 switch (fi->state) {
1503 case GPRS_SNS_ST_UNCONFIGURED:
1504 break;
Harald Welte694dad52021-03-23 15:22:16 +01001505 case GPRS_SNS_ST_BSS_SIZE:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001506 /* TODO: remove the ip4 element from the list */
1507 llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {
1508 if (nsvc->bind == sbind->bind) {
1509 gprs_ns2_free_nsvc(nsvc);
1510 }
1511 }
1512 break;
Harald Welte694dad52021-03-23 15:22:16 +01001513 case GPRS_SNS_ST_BSS_CONFIG_BSS:
1514 case GPRS_SNS_ST_BSS_CONFIG_SGSN:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001515 case GPRS_SNS_ST_CONFIGURED:
1516 /* TODO: do an delete SNS-IP procedure */
1517 /* TODO: remove the ip4 element to the list */
1518 llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {
1519 if (nsvc->bind == sbind->bind) {
1520 gprs_ns2_free_nsvc(nsvc);
1521 }
1522 }
1523 break;
1524 }
1525 /* if this is the last bind, the free_nsvc() will trigger a reselection */
1526 talloc_free(sbind);
1527 break;
Alexander Couzense769f522020-12-07 07:37:07 +01001528 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001529}
1530
Alexander Couzens31d52e12021-06-05 20:04:04 +02001531/* validate the bss configuration (sns endpoint and binds)
1532 * - no endpoints -> invalid
1533 * - no binds -> invalid
1534 * - only v4 sns endpoints, only v6 binds -> invalid
1535 * - only v4 sns endpoints, but v4 sig weights == 0 -> invalid ...
1536 */
1537static int ns2_sns_bss_valid_configuration(struct ns2_sns_state *gss)
1538{
1539 struct ns2_sns_bind *sbind;
1540 struct sns_endpoint *endpoint;
1541 const struct osmo_sockaddr *addr;
1542 int v4_sig = 0, v4_data = 0, v6_sig = 0, v6_data = 0;
1543 bool v4_endpoints = false;
1544 bool v6_endpoints = false;
1545
1546 if (llist_empty(&gss->sns_endpoints) || llist_empty(&gss->binds))
1547 return 0;
1548
1549 llist_for_each_entry(sbind, &gss->binds, list) {
1550 addr = gprs_ns2_ip_bind_sockaddr(sbind->bind);
1551 if (!addr)
1552 continue;
1553 switch (addr->u.sa.sa_family) {
1554 case AF_INET:
1555 v4_sig += sbind->bind->sns_sig_weight;
1556 v4_data += sbind->bind->sns_data_weight;
1557 break;
1558 case AF_INET6:
1559 v6_sig += sbind->bind->sns_sig_weight;
1560 v6_data += sbind->bind->sns_data_weight;
1561 break;
1562 }
1563 }
1564
1565 llist_for_each_entry(endpoint, &gss->sns_endpoints, list) {
1566 switch (endpoint->saddr.u.sa.sa_family) {
1567 case AF_INET:
1568 v4_endpoints = true;
1569 break;
1570 case AF_INET6:
1571 v6_endpoints = true;
1572 break;
1573 }
1574 }
1575
1576 return (v4_endpoints && v4_sig && v4_data) || (v6_endpoints && v6_sig && v6_data);
1577}
1578
Harald Welte9e37bf42021-03-02 20:48:31 +01001579/* allstate-action for BSS role */
1580static void ns2_sns_st_all_action_bss(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1581{
1582 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1583 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
1584
1585 /* reset when receiving GPRS_SNS_EV_REQ_NO_NSVC */
1586 switch (event) {
1587 case GPRS_SNS_EV_REQ_NO_NSVC:
1588 /* ignore reselection running */
1589 if (gss->reselection_running)
1590 break;
1591
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001592 sns_failed(fi, "no remaining NSVC, resetting SNS FSM");
Harald Welte9e37bf42021-03-02 20:48:31 +01001593 break;
1594 case GPRS_SNS_EV_REQ_SELECT_ENDPOINT:
1595 /* tear down previous state
1596 * gprs_ns2_free_nsvcs() will trigger NO_NSVC, prevent this from triggering a reselection */
1597 gss->reselection_running = true;
1598 gprs_ns2_free_nsvcs(nse);
Alexander Couzensd2c6c492021-06-06 01:57:52 +02001599 ns2_clear_elems(&gss->local);
1600 ns2_clear_elems(&gss->remote);
Harald Welte9e37bf42021-03-02 20:48:31 +01001601
1602 /* Choose the next sns endpoint. */
Alexander Couzens31d52e12021-06-05 20:04:04 +02001603 if (!ns2_sns_bss_valid_configuration(gss)) {
Harald Welte9e37bf42021-03-02 20:48:31 +01001604 gss->initial = NULL;
1605 ns2_prim_status_ind(gss->nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_NO_ENDPOINTS);
1606 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 3);
1607 return;
1608 } else if (!gss->initial) {
1609 gss->initial = llist_first_entry(&gss->sns_endpoints, struct sns_endpoint, list);
1610 } else if (gss->initial->list.next == &gss->sns_endpoints) {
1611 /* last entry, continue with first */
1612 gss->initial = llist_first_entry(&gss->sns_endpoints, struct sns_endpoint, list);
1613 } else {
1614 /* next element is an entry */
1615 gss->initial = llist_entry(gss->initial->list.next, struct sns_endpoint, list);
1616 }
1617
Alexander Couzens68ab9c42021-06-06 03:03:40 +02001618 gss->family = gss->initial->saddr.u.sa.sa_family;
Harald Welte9e37bf42021-03-02 20:48:31 +01001619 gss->reselection_running = false;
Harald Welte694dad52021-03-23 15:22:16 +01001620 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_SIZE, nse->nsi->timeout[NS_TOUT_TSNS_PROV], 1);
Harald Welte9e37bf42021-03-02 20:48:31 +01001621 break;
1622 default:
1623 ns2_sns_st_all_action(fi, event, data);
1624 break;
1625 }
1626}
1627
Alexander Couzens6a161492020-07-12 13:45:50 +02001628static struct osmo_fsm gprs_ns2_sns_bss_fsm = {
1629 .name = "GPRS-NS2-SNS-BSS",
1630 .states = ns2_sns_bss_states,
1631 .num_states = ARRAY_SIZE(ns2_sns_bss_states),
Alexander Couzens67725e22021-02-15 02:37:03 +01001632 .allstate_event_mask = S(GPRS_SNS_EV_REQ_NO_NSVC) |
1633 S(GPRS_SNS_EV_REQ_SELECT_ENDPOINT) |
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001634 S(GPRS_SNS_EV_REQ_ADD_BIND) |
1635 S(GPRS_SNS_EV_REQ_DELETE_BIND),
Harald Welte9e37bf42021-03-02 20:48:31 +01001636 .allstate_action = ns2_sns_st_all_action_bss,
Alexander Couzens6a161492020-07-12 13:45:50 +02001637 .cleanup = NULL,
1638 .timer_cb = ns2_sns_fsm_bss_timer_cb,
Alexander Couzens6a161492020-07-12 13:45:50 +02001639 .event_names = gprs_sns_event_names,
1640 .pre_term = NULL,
1641 .log_subsys = DLNS,
1642};
1643
Harald Welte5bef2cc2020-09-18 22:33:24 +02001644/*! Allocate an IP-SNS FSM for the BSS side.
1645 * \param[in] nse NS Entity in which the FSM runs
1646 * \param[in] id string identifier
Alexander Couzens23aec352021-02-15 05:05:15 +01001647 * \returns FSM instance on success; NULL on error */
Alexander Couzens6a161492020-07-12 13:45:50 +02001648struct osmo_fsm_inst *ns2_sns_bss_fsm_alloc(struct gprs_ns2_nse *nse,
1649 const char *id)
1650{
1651 struct osmo_fsm_inst *fi;
1652 struct ns2_sns_state *gss;
1653
1654 fi = osmo_fsm_inst_alloc(&gprs_ns2_sns_bss_fsm, nse, NULL, LOGL_DEBUG, id);
1655 if (!fi)
1656 return fi;
1657
1658 gss = talloc_zero(fi, struct ns2_sns_state);
1659 if (!gss)
1660 goto err;
1661
1662 fi->priv = gss;
1663 gss->nse = nse;
Harald Welte4f127462021-03-02 20:49:10 +01001664 gss->role = GPRS_SNS_ROLE_BSS;
Harald Welte24f4df52021-03-04 18:02:54 +01001665 /* The SGSN doesn't tell the BSS, so we assume there's always sufficient */
1666 gss->num_max_ip4_remote = 8192;
1667 gss->num_max_ip6_remote = 8192;
Alexander Couzense769f522020-12-07 07:37:07 +01001668 INIT_LLIST_HEAD(&gss->sns_endpoints);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001669 INIT_LLIST_HEAD(&gss->binds);
Alexander Couzens6a161492020-07-12 13:45:50 +02001670
1671 return fi;
1672err:
1673 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
1674 return NULL;
1675}
1676
Harald Welte5bef2cc2020-09-18 22:33:24 +02001677/*! main entry point for receiving SNS messages from the network.
1678 * \param[in] nsvc NS-VC on which the message was received
1679 * \param[in] msg message buffer of the IP-SNS message
1680 * \param[in] tp parsed TLV structure of message
Alexander Couzens23aec352021-02-15 05:05:15 +01001681 * \returns 0 on success; negative on error */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001682int ns2_sns_rx(struct gprs_ns2_vc *nsvc, struct msgb *msg, struct tlv_parsed *tp)
Alexander Couzens6a161492020-07-12 13:45:50 +02001683{
1684 struct gprs_ns2_nse *nse = nsvc->nse;
1685 struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h;
1686 uint16_t nsei = nsvc->nse->nsei;
Harald Welte4f127462021-03-02 20:49:10 +01001687 struct ns2_sns_state *gss;
Alexander Couzens6a161492020-07-12 13:45:50 +02001688 struct osmo_fsm_inst *fi;
Alexander Couzens7619ed42021-03-24 17:44:03 +01001689 int rc = 0;
Alexander Couzens6a161492020-07-12 13:45:50 +02001690
1691 if (!nse->bss_sns_fi) {
Harald Weltef2949742021-01-20 14:54:14 +01001692 LOGNSVC(nsvc, LOGL_NOTICE, "Rx %s for NS Instance that has no SNS!\n",
1693 get_value_string(gprs_ns_pdu_strings, nsh->pdu_type));
Alexander Couzens7619ed42021-03-24 17:44:03 +01001694 rc = -EINVAL;
1695 goto out;
Alexander Couzens6a161492020-07-12 13:45:50 +02001696 }
1697
Alexander Couzens6a161492020-07-12 13:45:50 +02001698 /* FIXME: how to resolve SNS FSM Instance by NSEI (SGSN)? */
1699 fi = nse->bss_sns_fi;
Harald Welte4f127462021-03-02 20:49:10 +01001700 gss = (struct ns2_sns_state *) fi->priv;
1701 if (!gss->sns_nsvc)
1702 gss->sns_nsvc = nsvc;
Alexander Couzens6a161492020-07-12 13:45:50 +02001703
Harald Weltef2949742021-01-20 14:54:14 +01001704 LOGPFSML(fi, LOGL_DEBUG, "NSEI=%u Rx SNS PDU type %s\n", nsei,
1705 get_value_string(gprs_ns_pdu_strings, nsh->pdu_type));
1706
Alexander Couzens6a161492020-07-12 13:45:50 +02001707 switch (nsh->pdu_type) {
1708 case SNS_PDUT_SIZE:
Alexander Couzens67725e22021-02-15 02:37:03 +01001709 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_SIZE, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001710 break;
1711 case SNS_PDUT_SIZE_ACK:
Alexander Couzens67725e22021-02-15 02:37:03 +01001712 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_SIZE_ACK, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001713 break;
1714 case SNS_PDUT_CONFIG:
1715 if (nsh->data[0] & 0x01)
Alexander Couzens67725e22021-02-15 02:37:03 +01001716 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_CONFIG_END, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001717 else
Alexander Couzens67725e22021-02-15 02:37:03 +01001718 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_CONFIG, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001719 break;
1720 case SNS_PDUT_CONFIG_ACK:
Alexander Couzens67725e22021-02-15 02:37:03 +01001721 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_CONFIG_ACK, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001722 break;
1723 case SNS_PDUT_ADD:
Alexander Couzens67725e22021-02-15 02:37:03 +01001724 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_ADD, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001725 break;
1726 case SNS_PDUT_DELETE:
Alexander Couzens67725e22021-02-15 02:37:03 +01001727 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_DELETE, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001728 break;
1729 case SNS_PDUT_CHANGE_WEIGHT:
Alexander Couzens67725e22021-02-15 02:37:03 +01001730 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_CHANGE_WEIGHT, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001731 break;
1732 case SNS_PDUT_ACK:
Harald Welteb9f23872021-03-02 20:48:54 +01001733 osmo_fsm_inst_dispatch(fi, GPRS_SNS_EV_RX_ACK, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02001734 break;
1735 default:
Harald Weltef2949742021-01-20 14:54:14 +01001736 LOGPFSML(fi, LOGL_ERROR, "NSEI=%u Rx unknown SNS PDU type %s\n", nsei,
1737 get_value_string(gprs_ns_pdu_strings, nsh->pdu_type));
Alexander Couzens7619ed42021-03-24 17:44:03 +01001738 rc = -EINVAL;
Alexander Couzens6a161492020-07-12 13:45:50 +02001739 }
1740
Alexander Couzens7619ed42021-03-24 17:44:03 +01001741out:
1742 msgb_free(msg);
1743
1744 return rc;
Alexander Couzens6a161492020-07-12 13:45:50 +02001745}
1746
1747#include <osmocom/vty/vty.h>
1748#include <osmocom/vty/misc.h>
1749
Harald Welte1262c4f2021-01-19 20:58:33 +01001750static void vty_dump_sns_ip4(struct vty *vty, const char *prefix, const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +02001751{
1752 struct in_addr in = { .s_addr = ip4->ip_addr };
Harald Welte1262c4f2021-01-19 20:58:33 +01001753 vty_out(vty, "%s %s:%u, Signalling Weight: %u, Data Weight: %u%s", prefix,
Alexander Couzens6a161492020-07-12 13:45:50 +02001754 inet_ntoa(in), ntohs(ip4->udp_port), ip4->sig_weight, ip4->data_weight, VTY_NEWLINE);
1755}
1756
Harald Welte1262c4f2021-01-19 20:58:33 +01001757static void vty_dump_sns_ip6(struct vty *vty, const char *prefix, const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +02001758{
1759 char ip_addr[INET6_ADDRSTRLEN] = {};
1760 if (!inet_ntop(AF_INET6, &ip6->ip_addr, ip_addr, (INET6_ADDRSTRLEN)))
1761 strcpy(ip_addr, "Invalid IPv6");
1762
Harald Welte1262c4f2021-01-19 20:58:33 +01001763 vty_out(vty, "%s %s:%u, Signalling Weight: %u, Data Weight: %u%s", prefix,
Alexander Couzens6a161492020-07-12 13:45:50 +02001764 ip_addr, ntohs(ip6->udp_port), ip6->sig_weight, ip6->data_weight, VTY_NEWLINE);
1765}
1766
Harald Welte5bef2cc2020-09-18 22:33:24 +02001767/*! Dump the IP-SNS state to a vty.
1768 * \param[in] vty VTY to which the state shall be printed
Harald Welte1262c4f2021-01-19 20:58:33 +01001769 * \param[in] prefix prefix to print at start of each line (typically indenting)
Harald Welte5bef2cc2020-09-18 22:33:24 +02001770 * \param[in] nse NS Entity whose IP-SNS state shall be printed
1771 * \param[in] stats Whether or not statistics shall also be printed */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001772void ns2_sns_dump_vty(struct vty *vty, const char *prefix, const struct gprs_ns2_nse *nse, bool stats)
Alexander Couzens6a161492020-07-12 13:45:50 +02001773{
1774 struct ns2_sns_state *gss;
1775 unsigned int i;
1776
1777 if (!nse->bss_sns_fi)
1778 return;
1779
Harald Welte1262c4f2021-01-19 20:58:33 +01001780 vty_out_fsm_inst2(vty, prefix, nse->bss_sns_fi);
Alexander Couzens6a161492020-07-12 13:45:50 +02001781 gss = (struct ns2_sns_state *) nse->bss_sns_fi->priv;
1782
Harald Welte1262c4f2021-01-19 20:58:33 +01001783 vty_out(vty, "%sMaximum number of remote NS-VCs: %zu, IPv4 Endpoints: %zu, IPv6 Endpoints: %zu%s",
1784 prefix, gss->num_max_nsvcs, gss->num_max_ip4_remote, gss->num_max_ip6_remote, VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +02001785
Alexander Couzens71128672021-06-05 18:44:01 +02001786 if (gss->local.num_ip4 && gss->remote.num_ip4) {
Harald Welte1262c4f2021-01-19 20:58:33 +01001787 vty_out(vty, "%sLocal IPv4 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02001788 for (i = 0; i < gss->local.num_ip4; i++)
1789 vty_dump_sns_ip4(vty, prefix, &gss->local.ip4[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02001790
Harald Welte1262c4f2021-01-19 20:58:33 +01001791 vty_out(vty, "%sRemote IPv4 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02001792 for (i = 0; i < gss->remote.num_ip4; i++)
1793 vty_dump_sns_ip4(vty, prefix, &gss->remote.ip4[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02001794 }
1795
Alexander Couzens71128672021-06-05 18:44:01 +02001796 if (gss->local.num_ip6 && gss->remote.num_ip6) {
Harald Welte1262c4f2021-01-19 20:58:33 +01001797 vty_out(vty, "%sLocal IPv6 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02001798 for (i = 0; i < gss->local.num_ip6; i++)
1799 vty_dump_sns_ip6(vty, prefix, &gss->local.ip6[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02001800
Harald Welte1262c4f2021-01-19 20:58:33 +01001801 vty_out(vty, "%sRemote IPv6 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02001802 for (i = 0; i < gss->remote.num_ip6; i++)
1803 vty_dump_sns_ip6(vty, prefix, &gss->remote.ip6[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02001804 }
1805}
1806
Alexander Couzens412bc342020-11-19 05:24:37 +01001807/*! write IP-SNS to a vty
1808 * \param[in] vty VTY to which the state shall be printed
1809 * \param[in] nse NS Entity whose IP-SNS state shall be printed */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001810void ns2_sns_write_vty(struct vty *vty, const struct gprs_ns2_nse *nse)
Alexander Couzens412bc342020-11-19 05:24:37 +01001811{
1812 struct ns2_sns_state *gss;
1813 struct osmo_sockaddr_str addr_str;
1814 struct sns_endpoint *endpoint;
1815
1816 if (!nse->bss_sns_fi)
1817 return;
1818
1819 gss = (struct ns2_sns_state *) nse->bss_sns_fi->priv;
1820 llist_for_each_entry(endpoint, &gss->sns_endpoints, list) {
Vadim Yanitskiyd8b70032021-01-05 14:24:09 +01001821 /* It's unlikely that an error happens, but let's better be safe. */
1822 if (osmo_sockaddr_str_from_sockaddr(&addr_str, &endpoint->saddr.u.sas) != 0)
1823 addr_str = (struct osmo_sockaddr_str) { .ip = "<INVALID>" };
Alexander Couzens5fa431c2021-02-08 23:21:54 +01001824 vty_out(vty, " ip-sns-remote %s %u%s", addr_str.ip, addr_str.port, VTY_NEWLINE);
Alexander Couzens412bc342020-11-19 05:24:37 +01001825 }
1826}
1827
Alexander Couzense769f522020-12-07 07:37:07 +01001828static struct sns_endpoint *ns2_get_sns_endpoint(struct ns2_sns_state *state,
1829 const struct osmo_sockaddr *saddr)
1830{
1831 struct sns_endpoint *endpoint;
1832
1833 llist_for_each_entry(endpoint, &state->sns_endpoints, list) {
1834 if (!osmo_sockaddr_cmp(saddr, &endpoint->saddr))
1835 return endpoint;
1836 }
1837
1838 return NULL;
1839}
1840
1841/*! gprs_ns2_sns_add_endpoint
1842 * \param[in] nse
1843 * \param[in] sockaddr
1844 * \return
1845 */
1846int gprs_ns2_sns_add_endpoint(struct gprs_ns2_nse *nse,
1847 const struct osmo_sockaddr *saddr)
1848{
1849 struct ns2_sns_state *gss;
1850 struct sns_endpoint *endpoint;
1851 bool do_selection = false;
1852
1853 if (nse->ll != GPRS_NS2_LL_UDP) {
1854 return -EINVAL;
1855 }
1856
Alexander Couzens138b96f2021-01-25 16:23:29 +01001857 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
Alexander Couzense769f522020-12-07 07:37:07 +01001858 return -EINVAL;
1859 }
1860
1861 gss = nse->bss_sns_fi->priv;
1862
1863 if (ns2_get_sns_endpoint(gss, saddr))
1864 return -EADDRINUSE;
1865
1866 endpoint = talloc_zero(nse->bss_sns_fi->priv, struct sns_endpoint);
1867 if (!endpoint)
1868 return -ENOMEM;
1869
1870 endpoint->saddr = *saddr;
1871 if (llist_empty(&gss->sns_endpoints))
1872 do_selection = true;
1873
1874 llist_add_tail(&endpoint->list, &gss->sns_endpoints);
1875 if (do_selection)
Alexander Couzens67725e22021-02-15 02:37:03 +01001876 osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_SELECT_ENDPOINT, NULL);
Alexander Couzense769f522020-12-07 07:37:07 +01001877
1878 return 0;
1879}
1880
1881/*! gprs_ns2_sns_del_endpoint
1882 * \param[in] nse
1883 * \param[in] sockaddr
1884 * \return 0 on success, otherwise < 0
1885 */
1886int gprs_ns2_sns_del_endpoint(struct gprs_ns2_nse *nse,
1887 const struct osmo_sockaddr *saddr)
1888{
1889 struct ns2_sns_state *gss;
1890 struct sns_endpoint *endpoint;
1891
1892 if (nse->ll != GPRS_NS2_LL_UDP) {
1893 return -EINVAL;
1894 }
1895
Alexander Couzens138b96f2021-01-25 16:23:29 +01001896 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
Alexander Couzense769f522020-12-07 07:37:07 +01001897 return -EINVAL;
1898 }
1899
1900 gss = nse->bss_sns_fi->priv;
1901 endpoint = ns2_get_sns_endpoint(gss, saddr);
1902 if (!endpoint)
1903 return -ENOENT;
1904
1905 /* if this is an unused SNS endpoint it's done */
1906 if (gss->initial != endpoint) {
1907 llist_del(&endpoint->list);
1908 talloc_free(endpoint);
1909 return 0;
1910 }
1911
Alexander Couzens67725e22021-02-15 02:37:03 +01001912 /* gprs_ns2_free_nsvcs() will trigger GPRS_SNS_EV_REQ_NO_NSVC on the last NS-VC
Alexander Couzense769f522020-12-07 07:37:07 +01001913 * and restart SNS SIZE procedure which selects a new initial */
Harald Weltef2949742021-01-20 14:54:14 +01001914 LOGNSE(nse, LOGL_INFO, "Current in-use SNS endpoint is being removed."
Alexander Couzense769f522020-12-07 07:37:07 +01001915 "Closing all NS-VC and restart SNS-SIZE procedure"
1916 "with a remaining SNS endpoint.\n");
1917
1918 /* Continue with the next endpoint in the list.
1919 * Special case if the endpoint is at the start or end of the list */
1920 if (endpoint->list.prev == &gss->sns_endpoints ||
1921 endpoint->list.next == &gss->sns_endpoints)
1922 gss->initial = NULL;
1923 else
1924 gss->initial = llist_entry(endpoint->list.next->prev,
1925 struct sns_endpoint,
1926 list);
1927
1928 llist_del(&endpoint->list);
1929 gprs_ns2_free_nsvcs(nse);
1930 talloc_free(endpoint);
1931
1932 return 0;
1933}
1934
1935/*! gprs_ns2_sns_count
1936 * \param[in] nse NS Entity whose IP-SNS endpoints shall be printed
1937 * \return the count of endpoints or < 0 if NSE doesn't contain sns.
1938 */
1939int gprs_ns2_sns_count(struct gprs_ns2_nse *nse)
1940{
1941 struct ns2_sns_state *gss;
1942 struct sns_endpoint *endpoint;
1943 int count = 0;
1944
1945 if (nse->ll != GPRS_NS2_LL_UDP) {
1946 return -EINVAL;
1947 }
1948
Alexander Couzens138b96f2021-01-25 16:23:29 +01001949 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
Alexander Couzense769f522020-12-07 07:37:07 +01001950 return -EINVAL;
1951 }
1952
1953 gss = nse->bss_sns_fi->priv;
1954 llist_for_each_entry(endpoint, &gss->sns_endpoints, list)
1955 count++;
1956
1957 return count;
1958}
1959
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001960void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive)
1961{
1962 struct ns2_sns_state *gss;
1963 struct gprs_ns2_vc *tmp;
1964
1965 if (!nse->bss_sns_fi)
1966 return;
1967
1968 gss = nse->bss_sns_fi->priv;
1969 if(nse->bss_sns_fi->state != GPRS_SNS_ST_CONFIGURED)
1970 return;
1971
1972 if (alive == gss->alive)
1973 return;
1974
1975 /* check if this is the current SNS NS-VC */
1976 if (nsvc == gss->sns_nsvc) {
1977 /* only replace the SNS NS-VC if there are other alive NS-VC.
1978 * There aren't any other alive NS-VC when the SNS fsm just reached CONFIGURED
1979 * and couldn't confirm yet if the NS-VC comes up */
1980 if (gss->alive && !alive)
1981 ns2_sns_replace_nsvc(nsvc);
1982 }
1983
1984 if (alive) {
1985 gss->alive = true;
Alexander Couzens67725e22021-02-15 02:37:03 +01001986 osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_NSVC_ALIVE, NULL);
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001987 } else {
1988 /* is there at least another alive nsvc? */
1989 llist_for_each_entry(tmp, &nse->nsvc, list) {
1990 if (ns2_vc_is_unblocked(tmp))
1991 return;
1992 }
1993
1994 /* all NS-VC have failed */
1995 gss->alive = false;
Alexander Couzens67725e22021-02-15 02:37:03 +01001996 osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_NO_NSVC, NULL);
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001997 }
1998}
1999
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002000int gprs_ns2_sns_add_bind(struct gprs_ns2_nse *nse,
2001 struct gprs_ns2_vc_bind *bind)
2002{
2003 struct ns2_sns_state *gss;
2004 struct ns2_sns_bind *tmp;
2005
2006 OSMO_ASSERT(nse->bss_sns_fi);
2007 gss = nse->bss_sns_fi->priv;
2008
2009 if (!gprs_ns2_is_ip_bind(bind)) {
2010 return -EINVAL;
2011 }
2012
2013 if (!llist_empty(&gss->binds)) {
2014 llist_for_each_entry(tmp, &gss->binds, list) {
2015 if (tmp->bind == bind)
2016 return -EALREADY;
2017 }
2018 }
2019
2020 tmp = talloc_zero(gss, struct ns2_sns_bind);
2021 if (!tmp)
2022 return -ENOMEM;
2023 tmp->bind = bind;
2024 llist_add_tail(&tmp->list, &gss->binds);
2025
2026 osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_ADD_BIND, tmp);
2027 return 0;
2028}
2029
2030/* Remove a bind from the SNS. All assosiated NSVC must be removed. */
2031int gprs_ns2_sns_del_bind(struct gprs_ns2_nse *nse,
2032 struct gprs_ns2_vc_bind *bind)
2033{
2034 struct ns2_sns_state *gss;
2035 struct ns2_sns_bind *tmp, *tmp2;
2036 bool found = false;
2037
2038 if (!nse->bss_sns_fi)
2039 return -EINVAL;
2040
2041 gss = nse->bss_sns_fi->priv;
2042 if (gss->initial_bind && gss->initial_bind->bind == bind) {
2043 if (gss->initial_bind->list.prev == &gss->binds)
2044 gss->initial_bind = NULL;
2045 else
2046 gss->initial_bind = llist_entry(gss->initial_bind->list.prev, struct ns2_sns_bind, list);
2047 }
2048
2049 llist_for_each_entry_safe(tmp, tmp2, &gss->binds, list) {
2050 if (tmp->bind == bind) {
2051 llist_del(&tmp->list);
2052 found = true;
Alexander Couzensa35c2962021-04-19 03:30:15 +02002053 break;
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002054 }
2055 }
2056
2057 if (!found)
2058 return -ENOENT;
2059
2060 osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_DELETE_BIND, tmp);
2061 return 0;
2062}
2063
Alexander Couzens71128672021-06-05 18:44:01 +02002064/* Update SNS weights for a bind (local endpoint).
2065 * \param[in] bind the bind which has been updated
Alexander Couzensc4704762021-02-08 23:13:12 +01002066 */
2067void ns2_sns_update_weights(struct gprs_ns2_vc_bind *bind)
2068{
2069 /* TODO: implement weights after binds per sns implemented */
2070}
2071
Harald Welte4f127462021-03-02 20:49:10 +01002072
2073
2074
2075/***********************************************************************
2076 * SGSN role
2077 ***********************************************************************/
2078
2079static void ns2_sns_st_sgsn_unconfigured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2080{
2081 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2082 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2083 /* do nothing; Rx SNS-SIZE handled in ns2_sns_st_all_action_sgsn() */
2084}
2085
2086/* We're waiting for inbound SNS-CONFIG from the BSS */
2087static void ns2_sns_st_sgsn_wait_config(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2088{
2089 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2090 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2091 struct gprs_ns2_inst *nsi = nse->nsi;
2092 uint8_t cause;
2093 int rc;
2094
2095 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2096
2097 switch (event) {
2098 case GPRS_SNS_EV_RX_CONFIG:
2099 case GPRS_SNS_EV_RX_CONFIG_END:
2100 rc = ns_sns_append_remote_eps(fi, data);
2101 if (rc < 0) {
2102 cause = -rc;
2103 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
2104 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
2105 return;
2106 }
2107 /* only change state if last CONFIG was received */
2108 if (event == GPRS_SNS_EV_RX_CONFIG_END) {
2109 /* ensure sum of data weight / sig weights is > 0 */
Alexander Couzens019da4b2021-06-06 02:48:18 +02002110 if (ip46_weight_sum_data(&gss->remote) == 0 || ip46_weight_sum_sig(&gss->remote) == 0) {
Harald Welte4f127462021-03-02 20:49:10 +01002111 cause = NS_CAUSE_INVAL_WEIGH;
2112 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
2113 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
2114 break;
2115 }
2116 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
2117 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
2118 } else {
2119 /* just send CONFIG-ACK */
2120 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
2121 osmo_timer_schedule(&fi->timer, nse->nsi->timeout[NS_TOUT_TSNS_PROV], 0);
2122 }
2123 break;
2124 }
2125}
2126
2127static void ns2_sns_st_sgsn_wait_config_ack_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
2128{
2129 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2130 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2131
Harald Welte4f127462021-03-02 20:49:10 +01002132 /* transmit SGSN-oriented SNS-CONFIG */
Alexander Couzens71128672021-06-05 18:44:01 +02002133 ns2_tx_sns_config(gss->sns_nsvc, true, gss->local.ip4, gss->local.num_ip4,
2134 gss->local.ip6, gss->local.num_ip6);
Harald Welte4f127462021-03-02 20:49:10 +01002135}
2136
2137/* We're waiting for SNS-CONFIG-ACK from the BSS (in response to our outbound SNS-CONFIG) */
2138static void ns2_sns_st_sgsn_wait_config_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2139{
2140 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2141 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2142 struct tlv_parsed *tp = NULL;
2143
2144 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2145
2146 switch (event) {
2147 case GPRS_SNS_EV_RX_CONFIG_ACK:
2148 tp = data;
2149 if (TLVP_VAL_MINLEN(tp, NS_IE_CAUSE, 1)) {
2150 LOGPFSML(fi, LOGL_ERROR, "Rx SNS-CONFIG-ACK with cause %s\n",
2151 gprs_ns2_cause_str(*TLVP_VAL(tp, NS_IE_CAUSE)));
2152 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
2153 break;
2154 }
2155 /* we currently only send one SNS-CONFIG with END FLAG */
2156 if (true) {
2157 create_missing_nsvcs(fi);
2158 /* start the test procedure on ALL NSVCs! */
2159 gprs_ns2_start_alive_all_nsvcs(nse);
2160 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, ns_sns_configured_timeout(fi), 4);
2161 }
2162 break;
2163 }
2164}
2165
2166/* SGSN-side SNS state machine */
2167static const struct osmo_fsm_state ns2_sns_sgsn_states[] = {
2168 [GPRS_SNS_ST_UNCONFIGURED] = {
2169 .in_event_mask = 0, /* handled by all_state_action */
2170 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
2171 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG),
2172 .name = "UNCONFIGURED",
2173 .action = ns2_sns_st_sgsn_unconfigured,
2174 },
2175 [GPRS_SNS_ST_SGSN_WAIT_CONFIG] = {
2176 .in_event_mask = S(GPRS_SNS_EV_RX_CONFIG) |
2177 S(GPRS_SNS_EV_RX_CONFIG_END),
2178 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
2179 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG) |
2180 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK),
2181 .name = "SGSN_WAIT_CONFIG",
2182 .action = ns2_sns_st_sgsn_wait_config,
2183 },
2184 [GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK] = {
2185 .in_event_mask = S(GPRS_SNS_EV_RX_CONFIG_ACK),
2186 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
2187 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK) |
2188 S(GPRS_SNS_ST_CONFIGURED),
2189 .name = "SGSN_WAIT_CONFIG_ACK",
2190 .action = ns2_sns_st_sgsn_wait_config_ack,
2191 .onenter = ns2_sns_st_sgsn_wait_config_ack_onenter,
2192 },
2193 [GPRS_SNS_ST_CONFIGURED] = {
2194 .in_event_mask = S(GPRS_SNS_EV_RX_ADD) |
2195 S(GPRS_SNS_EV_RX_DELETE) |
2196 S(GPRS_SNS_EV_RX_CHANGE_WEIGHT) |
2197 S(GPRS_SNS_EV_REQ_NSVC_ALIVE),
2198 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED),
2199 .name = "CONFIGURED",
2200 /* shared with BSS side; once configured there's no difference */
2201 .action = ns2_sns_st_configured,
2202 .onenter = ns2_sns_st_configured_onenter,
2203 },
2204};
2205
2206static int ns2_sns_fsm_sgsn_timer_cb(struct osmo_fsm_inst *fi)
2207{
2208 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2209 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2210 struct gprs_ns2_inst *nsi = nse->nsi;
2211
2212 gss->N++;
2213 switch (fi->T) {
2214 case 3:
2215 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
2216 LOGPFSML(fi, LOGL_ERROR, "NSE %d: SGSN Config retries failed. Giving up.\n", nse->nsei);
2217 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
2218 } else {
2219 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
2220 }
2221 break;
2222 case 4:
2223 LOGPFSML(fi, LOGL_ERROR, "NSE %d: Config succeeded but no NS-VC came online.\n", nse->nsei);
2224 break;
2225 }
2226 return 0;
2227}
2228
2229
2230/* allstate-action for SGSN role */
2231static void ns2_sns_st_all_action_sgsn(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2232{
2233 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2234 struct tlv_parsed *tp = NULL;
Harald Welte01fa6a32021-03-04 19:49:38 +01002235 size_t num_local_eps, num_remote_eps;
Harald Welte4f127462021-03-02 20:49:10 +01002236 uint8_t flag;
Harald Weltea2c5af52021-03-04 17:59:35 +01002237 uint8_t cause;
Harald Welte4f127462021-03-02 20:49:10 +01002238
2239 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2240
2241 switch (event) {
2242 case GPRS_SNS_EV_RX_SIZE:
2243 tp = (struct tlv_parsed *) data;
Harald Weltea2c5af52021-03-04 17:59:35 +01002244 /* check for mandatory / conditional IEs */
2245 if (!TLVP_PRES_LEN(tp, NS_IE_RESET_FLAG, 1) ||
2246 !TLVP_PRES_LEN(tp, NS_IE_MAX_NR_NSVC, 2)) {
2247 cause = NS_CAUSE_MISSING_ESSENT_IE;
2248 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002249 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2250 sns_failed(fi, "Rx Size: Missing essential IE");
Harald Weltea2c5af52021-03-04 17:59:35 +01002251 break;
2252 }
2253 if (!TLVP_PRES_LEN(tp, NS_IE_IPv4_EP_NR, 2) &&
2254 !TLVP_PRES_LEN(tp, NS_IE_IPv6_EP_NR, 2)) {
2255 cause = NS_CAUSE_MISSING_ESSENT_IE;
Harald Welte4f127462021-03-02 20:49:10 +01002256 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002257 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2258 sns_failed(fi, "Rx Size: Missing essential IE");
Harald Welte4f127462021-03-02 20:49:10 +01002259 break;
2260 }
Harald Welte01fa6a32021-03-04 19:49:38 +01002261 if (TLVP_PRES_LEN(tp, NS_IE_IPv4_EP_NR, 2))
2262 gss->num_max_ip4_remote = tlvp_val16be(tp, NS_IE_IPv4_EP_NR);
2263 if (TLVP_PRES_LEN(tp, NS_IE_IPv6_EP_NR, 2))
2264 gss->num_max_ip6_remote = tlvp_val16be(tp, NS_IE_IPv6_EP_NR);
2265 /* decide if we go for IPv4 or IPv6 */
Alexander Couzens077ce5a2021-06-06 01:32:45 +02002266 if (gss->num_max_ip6_remote && ns2_sns_count_num_local_ep(fi, AF_INET6)) {
2267 gss->family = AF_INET6;
Harald Welte2d807b62021-03-24 01:57:30 +01002268 ns2_sns_compute_local_ep_from_binds(fi);
Alexander Couzens71128672021-06-05 18:44:01 +02002269 num_local_eps = gss->local.num_ip6;
Harald Welte01fa6a32021-03-04 19:49:38 +01002270 num_remote_eps = gss->num_max_ip6_remote;
Alexander Couzens077ce5a2021-06-06 01:32:45 +02002271 } else if (gss->num_max_ip4_remote && ns2_sns_count_num_local_ep(fi, AF_INET)) {
2272 gss->family = AF_INET;
Harald Welte2d807b62021-03-24 01:57:30 +01002273 ns2_sns_compute_local_ep_from_binds(fi);
Alexander Couzens71128672021-06-05 18:44:01 +02002274 num_local_eps = gss->local.num_ip4;
Harald Welte01fa6a32021-03-04 19:49:38 +01002275 num_remote_eps = gss->num_max_ip4_remote;
2276 } else {
Alexander Couzens71128672021-06-05 18:44:01 +02002277 if (gss->local.num_ip4 && !gss->num_max_ip4_remote)
Harald Welte01fa6a32021-03-04 19:49:38 +01002278 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
2279 else
2280 cause = NS_CAUSE_INVAL_NR_IPv6_EP;
2281 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002282 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2283 sns_failed(fi, "Rx Size: Invalid Nr of IPv4/IPv6 EPs");
Harald Welte01fa6a32021-03-04 19:49:38 +01002284 break;
2285 }
Harald Welte01fa6a32021-03-04 19:49:38 +01002286 /* ensure number of NS-VCs is sufficient for full mesh */
2287 gss->num_max_nsvcs = tlvp_val16be(tp, NS_IE_MAX_NR_NSVC);
2288 if (gss->num_max_nsvcs < num_remote_eps * num_local_eps) {
2289 LOGPFSML(fi, LOGL_ERROR, "%zu local and %zu remote EPs, requires %zu NS-VC, "
2290 "but BSS supports only %zu maximum NS-VCs\n", num_local_eps,
2291 num_remote_eps, num_local_eps * num_remote_eps, gss->num_max_nsvcs);
2292 cause = NS_CAUSE_INVAL_NR_NS_VC;
2293 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002294 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2295 sns_failed(fi, NULL);
Harald Welte01fa6a32021-03-04 19:49:38 +01002296 break;
2297 }
2298 /* perform state reset, if requested */
Harald Welte4f127462021-03-02 20:49:10 +01002299 flag = *TLVP_VAL(tp, NS_IE_RESET_FLAG);
2300 if (flag & 1) {
2301 struct gprs_ns2_vc *nsvc, *nsvc2;
2302 /* clear all state */
Harald Welte46eb7642021-03-04 17:49:59 +01002303 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
Harald Welte4f127462021-03-02 20:49:10 +01002304 gss->N = 0;
Alexander Couzensd2c6c492021-06-06 01:57:52 +02002305 ns2_clear_elems(&gss->local);
2306 ns2_clear_elems(&gss->remote);
Harald Welte4f127462021-03-02 20:49:10 +01002307 llist_for_each_entry_safe(nsvc, nsvc2, &gss->nse->nsvc, list) {
2308 if (nsvc == gss->sns_nsvc) {
2309 /* keep the NSVC we need for SNS, but unconfigure it */
2310 nsvc->sig_weight = 0;
2311 nsvc->data_weight = 0;
2312 ns2_vc_force_unconfigured(nsvc);
2313 } else {
2314 /* free all other NS-VCs */
2315 gprs_ns2_free_nsvc(nsvc);
2316 }
2317 }
Harald Welte2d807b62021-03-24 01:57:30 +01002318 ns2_sns_compute_local_ep_from_binds(fi);
Harald Welte4f127462021-03-02 20:49:10 +01002319 }
Alexander Couzens1c405252021-06-13 00:14:48 +02002320
2321 if (fi->state == GPRS_SNS_ST_UNCONFIGURED && !(flag & 1)) {
2322 sns_failed(fi, "Rx Size without Reset flag, but NSE is unknown");
2323 break;
2324 }
2325
Harald Welte4f127462021-03-02 20:49:10 +01002326 /* send SIZE_ACK */
2327 ns2_tx_sns_size_ack(gss->sns_nsvc, NULL);
2328 /* only wait for SNS-CONFIG in case of Reset flag */
2329 if (flag & 1)
2330 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG, 0, 0);
2331 break;
2332 default:
2333 ns2_sns_st_all_action(fi, event, data);
2334 break;
2335 }
2336}
2337
2338static struct osmo_fsm gprs_ns2_sns_sgsn_fsm = {
2339 .name = "GPRS-NS2-SNS-SGSN",
2340 .states = ns2_sns_sgsn_states,
2341 .num_states = ARRAY_SIZE(ns2_sns_sgsn_states),
2342 .allstate_event_mask = S(GPRS_SNS_EV_RX_SIZE) |
2343 S(GPRS_SNS_EV_REQ_NO_NSVC) |
2344 S(GPRS_SNS_EV_REQ_ADD_BIND) |
2345 S(GPRS_SNS_EV_REQ_DELETE_BIND),
2346 .allstate_action = ns2_sns_st_all_action_sgsn,
2347 .cleanup = NULL,
2348 .timer_cb = ns2_sns_fsm_sgsn_timer_cb,
2349 .event_names = gprs_sns_event_names,
2350 .pre_term = NULL,
2351 .log_subsys = DLNS,
2352};
2353
2354/*! Allocate an IP-SNS FSM for the SGSN side.
2355 * \param[in] nse NS Entity in which the FSM runs
2356 * \param[in] id string identifier
2357 * \returns FSM instance on success; NULL on error */
2358struct osmo_fsm_inst *ns2_sns_sgsn_fsm_alloc(struct gprs_ns2_nse *nse, const char *id)
2359{
2360 struct osmo_fsm_inst *fi;
2361 struct ns2_sns_state *gss;
2362
2363 fi = osmo_fsm_inst_alloc(&gprs_ns2_sns_sgsn_fsm, nse, NULL, LOGL_DEBUG, id);
2364 if (!fi)
2365 return fi;
2366
2367 gss = talloc_zero(fi, struct ns2_sns_state);
2368 if (!gss)
2369 goto err;
2370
2371 fi->priv = gss;
2372 gss->nse = nse;
2373 gss->role = GPRS_SNS_ROLE_SGSN;
2374 INIT_LLIST_HEAD(&gss->sns_endpoints);
2375 INIT_LLIST_HEAD(&gss->binds);
2376
2377 return fi;
2378err:
2379 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
2380 return NULL;
2381}
2382
2383
2384
2385
Alexander Couzens6a161492020-07-12 13:45:50 +02002386/* initialize osmo_ctx on main tread */
2387static __attribute__((constructor)) void on_dso_load_ctx(void)
2388{
2389 OSMO_ASSERT(osmo_fsm_register(&gprs_ns2_sns_bss_fsm) == 0);
Harald Welte4f127462021-03-02 20:49:10 +01002390 OSMO_ASSERT(osmo_fsm_register(&gprs_ns2_sns_sgsn_fsm) == 0);
Alexander Couzens6a161492020-07-12 13:45:50 +02002391}