blob: 0cb24c564b49a950b53b9e44d46bedbf468bc68b [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 Couzens1f3193d2021-06-05 22:08:11 +020073 GPRS_SNS_ST_LOCAL_PROCEDURE, /*!< in process of a ADD/DEL/CHANGE procedure towards SGSN (BSS->SGSN) */
Alexander Couzens6a161492020-07-12 13:45:50 +020074};
75
Alexander Couzens6a161492020-07-12 13:45:50 +020076static const struct value_string gprs_sns_event_names[] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +020077 { NS2_SNS_EV_REQ_SELECT_ENDPOINT, "REQ_SELECT_ENDPOINT" },
78 { NS2_SNS_EV_RX_SIZE, "RX_SIZE" },
79 { NS2_SNS_EV_RX_SIZE_ACK, "RX_SIZE_ACK" },
80 { NS2_SNS_EV_RX_CONFIG, "RX_CONFIG" },
81 { NS2_SNS_EV_RX_CONFIG_END, "RX_CONFIG_END" },
82 { NS2_SNS_EV_RX_CONFIG_ACK, "RX_CONFIG_ACK" },
83 { NS2_SNS_EV_RX_ADD, "RX_ADD" },
84 { NS2_SNS_EV_RX_DELETE, "RX_DELETE" },
85 { NS2_SNS_EV_RX_ACK, "RX_ACK" },
86 { NS2_SNS_EV_RX_CHANGE_WEIGHT, "RX_CHANGE_WEIGHT" },
87 { NS2_SNS_EV_REQ_NO_NSVC, "REQ_NO_NSVC" },
Alexander Couzens83f06ce2021-08-06 19:50:09 +020088 { NS2_SNS_EV_REQ_FREE_NSVCS, "REQ_FREE_NSVCS" },
Alexander Couzens175eb7b2021-07-20 18:41:14 +020089 { NS2_SNS_EV_REQ_NSVC_ALIVE, "REQ_NSVC_ALIVE"},
90 { NS2_SNS_EV_REQ_ADD_BIND, "REQ_ADD_BIND"},
91 { NS2_SNS_EV_REQ_DELETE_BIND, "REQ_DELETE_BIND"},
Alexander Couzens1f3193d2021-06-05 22:08:11 +020092 { NS2_SNS_EV_REQ_CHANGE_WEIGHT, "REQ_CHANGE_WEIGHT"},
Alexander Couzens6a161492020-07-12 13:45:50 +020093 { 0, NULL }
94};
95
Alexander Couzens9cd39ac2021-06-06 18:57:56 +020096#define GPRS_SNS_FLAG_KEEP_SELECT_ENDPOINT_ORDER (void *) 1
97
Alexander Couzens1f3193d2021-06-05 22:08:11 +020098enum sns_procedure {
99 SNS_PROC_NONE, /*!< used as invalid/idle value */
100 SNS_PROC_ADD,
101 SNS_PROC_DEL,
102 SNS_PROC_CHANGE_WEIGHT,
103};
104
Alexander Couzense769f522020-12-07 07:37:07 +0100105struct sns_endpoint {
106 struct llist_head list;
107 struct osmo_sockaddr saddr;
108};
109
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100110struct ns2_sns_bind {
111 struct llist_head list;
112 struct gprs_ns2_vc_bind *bind;
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200113 uint8_t change_weight_state;
114};
115
116struct ns2_sns_procedure {
117 struct llist_head list;
118 struct ns2_sns_bind *sbind;
119 uint16_t sig_weight;
120 uint16_t data_weight;
121 /* copy entry to protect against changes of gss->local */
122 struct gprs_ns_ie_ip4_elem ip4;
123 struct gprs_ns_ie_ip6_elem ip6;
124 enum sns_procedure procedure;
125 uint8_t trans_id;
126 /* is the procedure in process */
127 bool running;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100128};
129
Alexander Couzens71128672021-06-05 18:44:01 +0200130struct ns2_sns_elems {
131 struct gprs_ns_ie_ip4_elem *ip4;
132 unsigned int num_ip4;
133 struct gprs_ns_ie_ip6_elem *ip6;
134 unsigned int num_ip6;
135};
136
Alexander Couzens6a161492020-07-12 13:45:50 +0200137struct ns2_sns_state {
138 struct gprs_ns2_nse *nse;
139
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200140 /* containing the address family AF_* */
141 int family;
Harald Welte4f127462021-03-02 20:49:10 +0100142 enum ns2_sns_role role; /* local role: BSS or SGSN */
Alexander Couzens6a161492020-07-12 13:45:50 +0200143
Alexander Couzense769f522020-12-07 07:37:07 +0100144 /* holds the list of initial SNS endpoints */
145 struct llist_head sns_endpoints;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100146 /* list of used struct ns2_sns_bind */
147 struct llist_head binds;
148 /* pointer to the bind which was used to initiate the SNS connection */
149 struct ns2_sns_bind *initial_bind;
Alexander Couzense769f522020-12-07 07:37:07 +0100150 /* prevent recursive reselection */
151 bool reselection_running;
152
153 /* The current initial SNS endpoints.
154 * The initial connection will be moved into the NSE
155 * if configured via SNS. Otherwise it will be removed
156 * in configured state. */
157 struct sns_endpoint *initial;
Alexander Couzens6a161492020-07-12 13:45:50 +0200158 /* all SNS PDU will be sent over this nsvc */
159 struct gprs_ns2_vc *sns_nsvc;
Alexander Couzens90ee9632020-12-07 06:18:32 +0100160 /* timer N */
161 int N;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100162 /* true if at least one nsvc is alive */
163 bool alive;
Alexander Couzens6a161492020-07-12 13:45:50 +0200164
165 /* local configuration to send to the remote end */
Alexander Couzens71128672021-06-05 18:44:01 +0200166 struct ns2_sns_elems local;
Alexander Couzens6a161492020-07-12 13:45:50 +0200167
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200168 /* local configuration after all local procedures applied */
169 struct ns2_sns_elems local_procedure;
170
Alexander Couzens71128672021-06-05 18:44:01 +0200171 /* remote configuration as received */
172 struct ns2_sns_elems remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200173
174 /* local configuration about our capabilities in terms of connections to
175 * remote (SGSN) side */
176 size_t num_max_nsvcs;
177 size_t num_max_ip4_remote;
178 size_t num_max_ip6_remote;
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200179
180 struct llist_head procedures;
181 struct ns2_sns_procedure *current_procedure;
182 uint8_t trans_id;
Alexander Couzens6a161492020-07-12 13:45:50 +0200183};
184
185static inline struct gprs_ns2_nse *nse_inst_from_fi(struct osmo_fsm_inst *fi)
186{
187 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
188 return gss->nse;
189}
190
Alexander Couzens652ab4d2021-06-12 23:09:46 +0200191/* The SNS has failed. Etither restart the SNS (BSS) or remove the SNS (SGSN) */
192#define sns_failed(fi, reason) \
193 _sns_failed(fi, reason, __FILE__, __LINE__)
194static void _sns_failed(struct osmo_fsm_inst *fi, const char *reason, const char *file, int line)
195{
196 struct ns2_sns_state *gss = fi->priv;
197
198 if (reason)
199 LOGPFSML(fi, LOGL_ERROR, "NSE %d: SNS failed: %s\n", gss->nse->nsei, reason);
200
201 if (gss->role == GPRS_SNS_ROLE_SGSN) {
202 if (!gss->nse->persistent)
203 gprs_ns2_free_nse(gss->nse);
204 else
205 _osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0, file, line);
206 } else {
Alexander Couzens175eb7b2021-07-20 18:41:14 +0200207 _osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_REQ_SELECT_ENDPOINT, NULL, file, line);
Alexander Couzens652ab4d2021-06-12 23:09:46 +0200208 }
209}
210
Alexander Couzens6a161492020-07-12 13:45:50 +0200211/* helper function to compute the sum of all (data or signaling) weights */
Alexander Couzens62310552021-06-06 02:43:14 +0200212static int ip4_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_ip4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200218 if (data_weight)
Alexander Couzens62310552021-06-06 02:43:14 +0200219 weight_sum += elems->ip4[i].data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200220 else
Alexander Couzens62310552021-06-06 02:43:14 +0200221 weight_sum += elems->ip4[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 ip4_weight_sum_data(elems) ip4_weight_sum(elems, true)
226#define ip4_weight_sum_sig(elems) ip4_weight_sum(elems, false)
Alexander Couzens6a161492020-07-12 13:45:50 +0200227
228/* helper function to compute the sum of all (data or signaling) weights */
Alexander Couzens62310552021-06-06 02:43:14 +0200229static int ip6_weight_sum(const struct ns2_sns_elems *elems, bool data_weight)
Alexander Couzens6a161492020-07-12 13:45:50 +0200230{
231 unsigned int i;
232 int weight_sum = 0;
233
Alexander Couzens62310552021-06-06 02:43:14 +0200234 for (i = 0; i < elems->num_ip6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200235 if (data_weight)
Alexander Couzens62310552021-06-06 02:43:14 +0200236 weight_sum += elems->ip6[i].data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200237 else
Alexander Couzens62310552021-06-06 02:43:14 +0200238 weight_sum += elems->ip6[i].sig_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200239 }
240 return weight_sum;
241}
Alexander Couzens62310552021-06-06 02:43:14 +0200242#define ip6_weight_sum_data(elems) ip6_weight_sum(elems, true)
243#define ip6_weight_sum_sig(elems) ip6_weight_sum(elems, false)
Alexander Couzens6a161492020-07-12 13:45:50 +0200244
Alexander Couzens019da4b2021-06-06 02:48:18 +0200245static int ip46_weight_sum(const struct ns2_sns_elems *elems, bool data_weight)
Harald Weltec1c7e4a2021-03-02 20:47:29 +0100246{
Alexander Couzens019da4b2021-06-06 02:48:18 +0200247 return ip4_weight_sum(elems, data_weight) +
248 ip6_weight_sum(elems, data_weight);
Harald Weltec1c7e4a2021-03-02 20:47:29 +0100249}
Alexander Couzens019da4b2021-06-06 02:48:18 +0200250#define ip46_weight_sum_data(elems) ip46_weight_sum(elems, true)
251#define ip46_weight_sum_sig(elems) ip46_weight_sum(elems, false)
Harald Weltec1c7e4a2021-03-02 20:47:29 +0100252
Alexander Couzens6a161492020-07-12 13:45:50 +0200253static struct gprs_ns2_vc *nsvc_by_ip4_elem(struct gprs_ns2_nse *nse,
254 const struct gprs_ns_ie_ip4_elem *ip4)
255{
256 struct osmo_sockaddr sa;
257 /* copy over. Both data structures use network byte order */
258 sa.u.sin.sin_addr.s_addr = ip4->ip_addr;
259 sa.u.sin.sin_port = ip4->udp_port;
260 sa.u.sin.sin_family = AF_INET;
261
Alexander Couzens38b19e82020-09-23 23:56:37 +0200262 return gprs_ns2_nsvc_by_sockaddr_nse(nse, &sa);
Alexander Couzens6a161492020-07-12 13:45:50 +0200263}
264
265static struct gprs_ns2_vc *nsvc_by_ip6_elem(struct gprs_ns2_nse *nse,
266 const struct gprs_ns_ie_ip6_elem *ip6)
267{
268 struct osmo_sockaddr sa;
269 /* copy over. Both data structures use network byte order */
270 sa.u.sin6.sin6_addr = ip6->ip_addr;
271 sa.u.sin6.sin6_port = ip6->udp_port;
272 sa.u.sin6.sin6_family = AF_INET;
273
Alexander Couzens38b19e82020-09-23 23:56:37 +0200274 return gprs_ns2_nsvc_by_sockaddr_nse(nse, &sa);
Alexander Couzens6a161492020-07-12 13:45:50 +0200275}
276
Alexander Couzens125298f2020-10-11 21:22:42 +0200277/*! Return the initial SNS remote socket address
278 * \param nse NS Entity
279 * \return address of the initial SNS connection; NULL in case of error
280 */
281const struct osmo_sockaddr *gprs_ns2_nse_sns_remote(struct gprs_ns2_nse *nse)
282{
283 struct ns2_sns_state *gss;
284
285 if (!nse->bss_sns_fi)
286 return NULL;
287
288 gss = (struct ns2_sns_state *) nse->bss_sns_fi->priv;
Alexander Couzense769f522020-12-07 07:37:07 +0100289 return &gss->initial->saddr;
Alexander Couzens125298f2020-10-11 21:22:42 +0200290}
291
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100292/*! called when a nsvc is beeing freed or the nsvc became dead */
293void ns2_sns_replace_nsvc(struct gprs_ns2_vc *nsvc)
Alexander Couzens6a161492020-07-12 13:45:50 +0200294{
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100295 struct gprs_ns2_nse *nse = nsvc->nse;
Alexander Couzens6a161492020-07-12 13:45:50 +0200296 struct gprs_ns2_vc *tmp;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100297 struct osmo_fsm_inst *fi = nse->bss_sns_fi;
Alexander Couzens6a161492020-07-12 13:45:50 +0200298 struct ns2_sns_state *gss;
Alexander Couzens6a161492020-07-12 13:45:50 +0200299
300 if (!fi)
301 return;
302
303 gss = (struct ns2_sns_state *) fi->priv;
304 if (nsvc != gss->sns_nsvc)
305 return;
306
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100307 gss->sns_nsvc = NULL;
308 if (gss->alive) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200309 llist_for_each_entry(tmp, &nse->nsvc, list) {
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100310 if (ns2_vc_is_unblocked(tmp)) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200311 gss->sns_nsvc = tmp;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100312 return;
313 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200314 }
315 } else {
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100316 /* the SNS is waiting for its first NS-VC to come up
317 * choose any other nsvc */
318 llist_for_each_entry(tmp, &nse->nsvc, list) {
319 if (nsvc != tmp) {
320 gss->sns_nsvc = tmp;
321 return;
322 }
323 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200324 }
Alexander Couzensbe7cecc2021-02-03 18:25:27 +0100325
Alexander Couzens175eb7b2021-07-20 18:41:14 +0200326 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_REQ_NO_NSVC, NULL);
Alexander Couzens6a161492020-07-12 13:45:50 +0200327}
328
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200329static void ns2_clear_elems(struct ns2_sns_elems *elems)
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100330{
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200331 TALLOC_FREE(elems->ip4);
332 TALLOC_FREE(elems->ip6);
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100333
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200334 elems->num_ip4 = 0;
335 elems->num_ip6 = 0;
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100336}
337
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200338static void ns2_clear_procedures(struct ns2_sns_state *gss)
339{
340 struct ns2_sns_procedure *procedure, *tmp;
341 gss->current_procedure = NULL;
342 llist_for_each_entry_safe(procedure, tmp, &gss->procedures, list) {
343 llist_del(&procedure->list);
344 talloc_free(procedure);
345 }
346}
347
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100348static void ns2_vc_create_ip(struct osmo_fsm_inst *fi, struct gprs_ns2_nse *nse, const struct osmo_sockaddr *remote,
349 uint8_t sig_weight, uint8_t data_weight)
Alexander Couzens6a161492020-07-12 13:45:50 +0200350{
351 struct gprs_ns2_inst *nsi = nse->nsi;
352 struct gprs_ns2_vc *nsvc;
353 struct gprs_ns2_vc_bind *bind;
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100354
355 /* for every bind, create a connection if bind type == IP */
356 llist_for_each_entry(bind, &nsi->binding, list) {
357 if (bind->ll != GPRS_NS2_LL_UDP)
358 continue;
359 /* ignore failed connection */
360 nsvc = gprs_ns2_ip_connect_inactive(bind,
361 remote,
362 nse, 0);
363 if (!nsvc) {
364 LOGPFSML(fi, LOGL_ERROR, "SNS-CONFIG: Failed to create NSVC\n");
365 continue;
366 }
367
368 nsvc->sig_weight = sig_weight;
369 nsvc->data_weight = data_weight;
370 }
371}
372
373static void ns2_nsvc_create_ip4(struct osmo_fsm_inst *fi,
374 struct gprs_ns2_nse *nse,
375 const struct gprs_ns_ie_ip4_elem *ip4)
376{
Alexander Couzensc068d862020-10-12 04:11:51 +0200377 struct osmo_sockaddr remote = { };
Alexander Couzens6a161492020-07-12 13:45:50 +0200378 /* copy over. Both data structures use network byte order */
379 remote.u.sin.sin_family = AF_INET;
380 remote.u.sin.sin_addr.s_addr = ip4->ip_addr;
381 remote.u.sin.sin_port = ip4->udp_port;
382
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100383 ns2_vc_create_ip(fi, nse, &remote, ip4->sig_weight, ip4->data_weight);
Alexander Couzens6a161492020-07-12 13:45:50 +0200384}
385
386static void ns2_nsvc_create_ip6(struct osmo_fsm_inst *fi,
387 struct gprs_ns2_nse *nse,
388 const struct gprs_ns_ie_ip6_elem *ip6)
389{
Alexander Couzens6a161492020-07-12 13:45:50 +0200390 struct osmo_sockaddr remote = {};
391 /* copy over. Both data structures use network byte order */
392 remote.u.sin6.sin6_family = AF_INET6;
393 remote.u.sin6.sin6_addr = ip6->ip_addr;
394 remote.u.sin6.sin6_port = ip6->udp_port;
395
Daniel Willmanncf8371a2021-01-16 15:13:51 +0100396 ns2_vc_create_ip(fi, nse, &remote, ip6->sig_weight, ip6->data_weight);
Alexander Couzens6a161492020-07-12 13:45:50 +0200397}
398
Harald Weltee8c61062021-03-24 13:16:27 +0100399static struct gprs_ns2_vc *nsvc_for_bind_and_remote(struct gprs_ns2_nse *nse,
400 struct gprs_ns2_vc_bind *bind,
401 const struct osmo_sockaddr *remote)
402{
403 struct gprs_ns2_vc *nsvc;
404
405 llist_for_each_entry(nsvc, &nse->nsvc, list) {
406 if (nsvc->bind != bind)
407 continue;
408
409 if (!osmo_sockaddr_cmp(remote, gprs_ns2_ip_vc_remote(nsvc)))
410 return nsvc;
411 }
412 return NULL;
413}
Alexander Couzens6a161492020-07-12 13:45:50 +0200414
415static int create_missing_nsvcs(struct osmo_fsm_inst *fi)
416{
417 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
418 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
419 struct gprs_ns2_vc *nsvc;
Harald Welte3053bbb2021-03-24 13:22:18 +0100420 struct ns2_sns_bind *sbind;
Alexander Couzens6a161492020-07-12 13:45:50 +0200421 struct osmo_sockaddr remote = { };
422 unsigned int i;
423
Harald Weltee8c61062021-03-24 13:16:27 +0100424 /* iterate over all remote IPv4 endpoints */
Alexander Couzens71128672021-06-05 18:44:01 +0200425 for (i = 0; i < gss->remote.num_ip4; i++) {
426 const struct gprs_ns_ie_ip4_elem *ip4 = &gss->remote.ip4[i];
Alexander Couzens6a161492020-07-12 13:45:50 +0200427
428 remote.u.sin.sin_family = AF_INET;
429 remote.u.sin.sin_addr.s_addr = ip4->ip_addr;
430 remote.u.sin.sin_port = ip4->udp_port;
431
Harald Welte3053bbb2021-03-24 13:22:18 +0100432 /* iterate over all local binds within this SNS */
433 llist_for_each_entry(sbind, &gss->binds, list) {
434 struct gprs_ns2_vc_bind *bind = sbind->bind;
435
Harald Weltee8c61062021-03-24 13:16:27 +0100436 /* we only care about UDP binds */
Daniel Willmann967e2c12021-01-14 16:58:17 +0100437 if (bind->ll != GPRS_NS2_LL_UDP)
438 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200439
Harald Weltee8c61062021-03-24 13:16:27 +0100440 nsvc = nsvc_for_bind_and_remote(nse, bind, &remote);
441 if (!nsvc) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200442 nsvc = gprs_ns2_ip_connect_inactive(bind, &remote, nse, 0);
443 if (!nsvc) {
444 /* TODO: add to a list to send back a NS-STATUS */
445 continue;
446 }
447 }
448
449 /* update data / signalling weight */
450 nsvc->data_weight = ip4->data_weight;
451 nsvc->sig_weight = ip4->sig_weight;
452 nsvc->sns_only = false;
453 }
454 }
455
Harald Weltee8c61062021-03-24 13:16:27 +0100456 /* iterate over all remote IPv4 endpoints */
Alexander Couzens71128672021-06-05 18:44:01 +0200457 for (i = 0; i < gss->remote.num_ip6; i++) {
458 const struct gprs_ns_ie_ip6_elem *ip6 = &gss->remote.ip6[i];
Alexander Couzens6a161492020-07-12 13:45:50 +0200459
460 remote.u.sin6.sin6_family = AF_INET6;
461 remote.u.sin6.sin6_addr = ip6->ip_addr;
462 remote.u.sin6.sin6_port = ip6->udp_port;
463
Harald Welte3053bbb2021-03-24 13:22:18 +0100464 /* iterate over all local binds within this SNS */
465 llist_for_each_entry(sbind, &gss->binds, list) {
466 struct gprs_ns2_vc_bind *bind = sbind->bind;
467
Daniel Willmann967e2c12021-01-14 16:58:17 +0100468 if (bind->ll != GPRS_NS2_LL_UDP)
469 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200470
Harald Weltee8c61062021-03-24 13:16:27 +0100471 /* we only care about UDP binds */
472 nsvc = nsvc_for_bind_and_remote(nse, bind, &remote);
473 if (!nsvc) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200474 nsvc = gprs_ns2_ip_connect_inactive(bind, &remote, nse, 0);
475 if (!nsvc) {
476 /* TODO: add to a list to send back a NS-STATUS */
477 continue;
478 }
479 }
480
481 /* update data / signalling weight */
482 nsvc->data_weight = ip6->data_weight;
483 nsvc->sig_weight = ip6->sig_weight;
484 nsvc->sns_only = false;
485 }
486 }
487
488
489 return 0;
490}
491
492/* Add a given remote IPv4 element to gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200493static int add_ip4_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
494 const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +0200495{
Alexander Couzens6a161492020-07-12 13:45:50 +0200496 /* check for duplicates */
Alexander Couzenscc56ddc2021-06-06 03:33:35 +0200497 for (unsigned int i = 0; i < elems->num_ip4; i++) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200498 if (memcmp(&elems->ip4[i], ip4, sizeof(*ip4)))
Alexander Couzens6a161492020-07-12 13:45:50 +0200499 continue;
Alexander Couzensd3507e82021-06-06 03:32:32 +0200500 return -1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200501 }
502
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200503 elems->ip4 = talloc_realloc(gss, elems->ip4, struct gprs_ns_ie_ip4_elem,
504 elems->num_ip4+1);
505 elems->ip4[elems->num_ip4] = *ip4;
506 elems->num_ip4 += 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200507 return 0;
508}
509
510/* Remove a given remote IPv4 element from gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200511static int remove_ip4_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
512 const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +0200513{
514 unsigned int i;
515
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200516 for (i = 0; i < elems->num_ip4; i++) {
517 if (memcmp(&elems->ip4[i], ip4, sizeof(*ip4)))
Alexander Couzens6a161492020-07-12 13:45:50 +0200518 continue;
519 /* all array elements < i remain as they are; all > i are shifted left by one */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200520 memmove(&elems->ip4[i], &elems->ip4[i+1], elems->num_ip4-i-1);
521 elems->num_ip4 -= 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200522 return 0;
523 }
524 return -1;
525}
526
527/* update the weights for specified remote IPv4 */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200528static int update_ip4_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
529 const struct gprs_ns_ie_ip4_elem *ip4)
Alexander Couzens6a161492020-07-12 13:45:50 +0200530{
531 unsigned int i;
532
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200533 for (i = 0; i < elems->num_ip4; i++) {
534 if (elems->ip4[i].ip_addr != ip4->ip_addr ||
535 elems->ip4[i].udp_port != ip4->udp_port)
Alexander Couzens6a161492020-07-12 13:45:50 +0200536 continue;
537
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200538 elems->ip4[i].sig_weight = ip4->sig_weight;
539 elems->ip4[i].data_weight = ip4->data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200540 return 0;
541 }
542 return -1;
543}
544
545/* Add a given remote IPv6 element to gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200546static int add_ip6_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
547 const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +0200548{
Alexander Couzenscc56ddc2021-06-06 03:33:35 +0200549 /* check for duplicates */
550 for (unsigned int i = 0; i < elems->num_ip6; i++) {
551 if (memcmp(&elems->ip6[i].ip_addr, &ip6->ip_addr, sizeof(ip6->ip_addr)) ||
552 elems->ip6[i].udp_port != ip6->udp_port)
553 continue;
554 return -1;
555 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200556
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200557 elems->ip6 = talloc_realloc(gss, elems->ip6, struct gprs_ns_ie_ip6_elem,
558 elems->num_ip6+1);
559 elems->ip6[elems->num_ip6] = *ip6;
560 elems->num_ip6 += 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200561 return 0;
562}
563
564/* Remove a given remote IPv6 element from gprs_sns_state */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200565static int remove_ip6_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
566 const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +0200567{
568 unsigned int i;
569
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200570 for (i = 0; i < elems->num_ip6; i++) {
571 if (memcmp(&elems->ip6[i], ip6, sizeof(*ip6)))
Alexander Couzens6a161492020-07-12 13:45:50 +0200572 continue;
573 /* all array elements < i remain as they are; all > i are shifted left by one */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200574 memmove(&elems->ip6[i], &elems->ip6[i+1], elems->num_ip6-i-1);
575 elems->num_ip6 -= 1;
Alexander Couzens6a161492020-07-12 13:45:50 +0200576 return 0;
577 }
578 return -1;
579}
580
581/* update the weights for specified remote IPv6 */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200582static int update_ip6_elem(struct ns2_sns_state *gss, struct ns2_sns_elems *elems,
583 const struct gprs_ns_ie_ip6_elem *ip6)
Alexander Couzens6a161492020-07-12 13:45:50 +0200584{
585 unsigned int i;
586
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200587 for (i = 0; i < elems->num_ip6; i++) {
588 if (memcmp(&elems->ip6[i].ip_addr, &ip6->ip_addr, sizeof(ip6->ip_addr)) ||
589 elems->ip6[i].udp_port != ip6->udp_port)
Alexander Couzens6a161492020-07-12 13:45:50 +0200590 continue;
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200591 elems->ip6[i].sig_weight = ip6->sig_weight;
592 elems->ip6[i].data_weight = ip6->data_weight;
Alexander Couzens6a161492020-07-12 13:45:50 +0200593 return 0;
594 }
595 return -1;
596}
597
598static 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)
599{
600 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
601 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
602 struct gprs_ns2_vc *nsvc;
603 struct osmo_sockaddr sa = {};
Alexander Couzens9a4cf272020-10-11 20:48:04 +0200604 const struct osmo_sockaddr *remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200605 uint8_t new_signal;
606 uint8_t new_data;
607
608 /* TODO: Upon receiving an SNS-CHANGEWEIGHT PDU, if the resulting sum of the
609 * signalling weights of all the peer IP endpoints configured for this NSE is
610 * equal to zero or if the resulting sum of the data weights of all the peer IP
611 * endpoints configured for this NSE is equal to zero, the BSS/SGSN shall send an
612 * SNS-ACK PDU with a cause code of "Invalid weights". */
613
614 if (ip4) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200615 if (update_ip4_elem(gss, &gss->remote, ip4))
Alexander Couzens6a161492020-07-12 13:45:50 +0200616 return -NS_CAUSE_UNKN_IP_EP;
617
618 /* copy over. Both data structures use network byte order */
619 sa.u.sin.sin_addr.s_addr = ip4->ip_addr;
620 sa.u.sin.sin_port = ip4->udp_port;
621 sa.u.sin.sin_family = AF_INET;
622 new_signal = ip4->sig_weight;
623 new_data = ip4->data_weight;
624 } else if (ip6) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200625 if (update_ip6_elem(gss, &gss->remote, ip6))
Alexander Couzens6a161492020-07-12 13:45:50 +0200626 return -NS_CAUSE_UNKN_IP_EP;
627
628 /* copy over. Both data structures use network byte order */
629 sa.u.sin6.sin6_addr = ip6->ip_addr;
630 sa.u.sin6.sin6_port = ip6->udp_port;
631 sa.u.sin6.sin6_family = AF_INET6;
632 new_signal = ip6->sig_weight;
633 new_data = ip6->data_weight;
634 } else {
635 OSMO_ASSERT(false);
636 }
637
638 llist_for_each_entry(nsvc, &nse->nsvc, list) {
Alexander Couzensc4229a42020-10-11 20:58:04 +0200639 remote = gprs_ns2_ip_vc_remote(nsvc);
Alexander Couzens6a161492020-07-12 13:45:50 +0200640 /* all nsvc in NSE should be IP/UDP nsvc */
641 OSMO_ASSERT(remote);
642
643 if (osmo_sockaddr_cmp(&sa, remote))
644 continue;
645
646 LOGPFSML(fi, LOGL_INFO, "CHANGE-WEIGHT NS-VC %s data_weight %u->%u, sig_weight %u->%u\n",
647 gprs_ns2_ll_str(nsvc), nsvc->data_weight, new_data,
648 nsvc->sig_weight, new_signal);
649
650 nsvc->data_weight = new_data;
651 nsvc->sig_weight = new_signal;
652 }
653
654 return 0;
655}
656
657static int do_sns_delete(struct osmo_fsm_inst *fi,
658 const struct gprs_ns_ie_ip4_elem *ip4,
659 const struct gprs_ns_ie_ip6_elem *ip6)
660{
661 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
662 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
663 struct gprs_ns2_vc *nsvc, *tmp;
Alexander Couzens9a4cf272020-10-11 20:48:04 +0200664 const struct osmo_sockaddr *remote;
Alexander Couzens6a161492020-07-12 13:45:50 +0200665 struct osmo_sockaddr sa = {};
666
667 if (ip4) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200668 if (remove_ip4_elem(gss, &gss->remote, ip4) < 0)
Alexander Couzens6a161492020-07-12 13:45:50 +0200669 return -NS_CAUSE_UNKN_IP_EP;
670 /* copy over. Both data structures use network byte order */
671 sa.u.sin.sin_addr.s_addr = ip4->ip_addr;
672 sa.u.sin.sin_port = ip4->udp_port;
673 sa.u.sin.sin_family = AF_INET;
674 } else if (ip6) {
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200675 if (remove_ip6_elem(gss, &gss->remote, ip6))
Alexander Couzens6a161492020-07-12 13:45:50 +0200676 return -NS_CAUSE_UNKN_IP_EP;
677
678 /* copy over. Both data structures use network byte order */
679 sa.u.sin6.sin6_addr = ip6->ip_addr;
680 sa.u.sin6.sin6_port = ip6->udp_port;
681 sa.u.sin6.sin6_family = AF_INET6;
682 } else {
683 OSMO_ASSERT(false);
684 }
685
686 llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {
Alexander Couzensc4229a42020-10-11 20:58:04 +0200687 remote = gprs_ns2_ip_vc_remote(nsvc);
Alexander Couzens6a161492020-07-12 13:45:50 +0200688 /* all nsvc in NSE should be IP/UDP nsvc */
689 OSMO_ASSERT(remote);
690 if (osmo_sockaddr_cmp(&sa, remote))
691 continue;
692
693 LOGPFSML(fi, LOGL_INFO, "DELETE NS-VC %s\n", gprs_ns2_ll_str(nsvc));
694 gprs_ns2_free_nsvc(nsvc);
695 }
696
697 return 0;
698}
699
700static int do_sns_add(struct osmo_fsm_inst *fi,
701 const struct gprs_ns_ie_ip4_elem *ip4,
702 const struct gprs_ns_ie_ip6_elem *ip6)
703{
704 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
705 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
706 struct gprs_ns2_vc *nsvc;
707 int rc = 0;
708
709 /* Upon receiving an SNS-ADD PDU, if the consequent number of IPv4 endpoints
710 * exceeds the number of IPv4 endpoints supported by the NSE, the NSE shall send
711 * an SNS-ACK PDU with a cause code set to "Invalid number of IP4 Endpoints". */
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200712 switch (gss->family) {
713 case AF_INET:
Alexander Couzensd3507e82021-06-06 03:32:32 +0200714 if (gss->remote.num_ip4 >= gss->num_max_ip4_remote)
715 return -NS_CAUSE_INVAL_NR_NS_VC;
716 /* TODO: log message duplicate */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200717 rc = add_ip4_elem(gss, &gss->remote, ip4);
Alexander Couzens6a161492020-07-12 13:45:50 +0200718 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200719 case AF_INET6:
Alexander Couzensd3507e82021-06-06 03:32:32 +0200720 if (gss->remote.num_ip6 >= gss->num_max_ip6_remote)
721 return -NS_CAUSE_INVAL_NR_NS_VC;
722 /* TODO: log message duplicate */
Alexander Couzensc2ba25e2021-06-06 02:26:40 +0200723 rc = add_ip6_elem(gss, &gss->remote, ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +0200724 break;
725 default:
726 /* the gss->ip is initialized with the bss */
727 OSMO_ASSERT(false);
728 }
729
730 if (rc)
Alexander Couzensd3507e82021-06-06 03:32:32 +0200731 return -NS_CAUSE_PROTO_ERR_UNSPEC;
Alexander Couzens6a161492020-07-12 13:45:50 +0200732
733 /* Upon receiving an SNS-ADD PDU containing an already configured IP endpoint the
734 * NSE shall send an SNS-ACK PDU with the cause code "Protocol error -
735 * unspecified" */
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200736 switch (gss->family) {
737 case AF_INET:
Alexander Couzens6a161492020-07-12 13:45:50 +0200738 nsvc = nsvc_by_ip4_elem(nse, ip4);
739 if (nsvc) {
740 /* the nsvc should be already in sync with the ip4 / ip6 elements */
741 return -NS_CAUSE_PROTO_ERR_UNSPEC;
742 }
743
744 /* TODO: failure case */
745 ns2_nsvc_create_ip4(fi, nse, ip4);
746 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200747 case AF_INET6:
Alexander Couzens6a161492020-07-12 13:45:50 +0200748 nsvc = nsvc_by_ip6_elem(nse, ip6);
749 if (nsvc) {
750 /* the nsvc should be already in sync with the ip4 / ip6 elements */
751 return -NS_CAUSE_PROTO_ERR_UNSPEC;
752 }
753
754 /* TODO: failure case */
755 ns2_nsvc_create_ip6(fi, nse, ip6);
756 break;
757 }
758
759 gprs_ns2_start_alive_all_nsvcs(nse);
760
761 return 0;
762}
763
764
Harald Welte694dad52021-03-23 15:22:16 +0100765static void ns2_sns_st_bss_unconfigured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +0200766{
Harald Weltef61a9152021-03-02 22:20:17 +0100767 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
768 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
Alexander Couzense769f522020-12-07 07:37:07 +0100769 /* empty state - SNS Select will start by ns2_sns_st_all_action() */
Alexander Couzens6a161492020-07-12 13:45:50 +0200770}
771
Harald Welte694dad52021-03-23 15:22:16 +0100772static void ns2_sns_st_bss_size(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +0200773{
Harald Weltef61a9152021-03-02 22:20:17 +0100774 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +0200775 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
776 struct gprs_ns2_inst *nsi = nse->nsi;
777 struct tlv_parsed *tp = NULL;
778
Harald Weltef61a9152021-03-02 22:20:17 +0100779 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
780
Alexander Couzens6a161492020-07-12 13:45:50 +0200781 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +0200782 case NS2_SNS_EV_RX_SIZE_ACK:
Alexander Couzens6a161492020-07-12 13:45:50 +0200783 tp = data;
784 if (TLVP_VAL_MINLEN(tp, NS_IE_CAUSE, 1)) {
785 LOGPFSML(fi, LOGL_ERROR, "SNS-SIZE-ACK with cause %s\n",
786 gprs_ns2_cause_str(*TLVP_VAL(tp, NS_IE_CAUSE)));
787 /* TODO: What to do? */
788 } else {
Harald Welte694dad52021-03-23 15:22:16 +0100789 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_BSS_CONFIG_BSS,
Alexander Couzens6a161492020-07-12 13:45:50 +0200790 nsi->timeout[NS_TOUT_TSNS_PROV], 2);
791 }
792 break;
793 default:
794 OSMO_ASSERT(0);
795 }
796}
797
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200798static int ns2_sns_count_num_local_ep(struct osmo_fsm_inst *fi, int ip_proto)
Harald Welte01fa6a32021-03-04 19:49:38 +0100799{
800 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
801 struct ns2_sns_bind *sbind;
802 int count = 0;
803
804 llist_for_each_entry(sbind, &gss->binds, list) {
805 const struct osmo_sockaddr *sa = gprs_ns2_ip_bind_sockaddr(sbind->bind);
806 if (!sa)
807 continue;
808
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200809 switch (ip_proto) {
810 case AF_INET:
Harald Welte01fa6a32021-03-04 19:49:38 +0100811 if (sa->u.sas.ss_family == AF_INET)
812 count++;
813 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200814 case AF_INET6:
Harald Welte01fa6a32021-03-04 19:49:38 +0100815 if (sa->u.sas.ss_family == AF_INET6)
816 count++;
817 break;
818 }
819 }
820 return count;
821}
822
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200823static int ns2_sns_copy_local_endpoints(struct ns2_sns_state *gss)
824{
825 switch (gss->family) {
826 case AF_INET:
827 gss->local_procedure.ip4 = talloc_realloc(gss, gss->local_procedure.ip4, struct gprs_ns_ie_ip4_elem,
828 gss->local.num_ip4);
829 if (!gss->local_procedure.ip4)
830 return -ENOMEM;
831
832 gss->local_procedure.num_ip4 = gss->local.num_ip4;
833 memcpy(gss->local_procedure.ip4, gss->local.ip4,
834 sizeof(struct gprs_ns_ie_ip4_elem) * gss->local.num_ip4);
835 break;
836 case AF_INET6:
837 gss->local_procedure.ip6 = talloc_realloc(gss, gss->local_procedure.ip6, struct gprs_ns_ie_ip6_elem,
838 gss->local.num_ip6);
839 if (!gss->local_procedure.ip6)
840 return -ENOMEM;
841
842 gss->local_procedure.num_ip6 = gss->local.num_ip6;
843 memcpy(gss->local_procedure.ip6, gss->local.ip6,
844 sizeof(struct gprs_ns_ie_ip6_elem) * gss->local.num_ip6);
845 break;
846 default:
847 OSMO_ASSERT(0);
848 }
849
850 return 0;
851}
852
Harald Welte24920e22021-03-04 13:03:27 +0100853static void ns2_sns_compute_local_ep_from_binds(struct osmo_fsm_inst *fi)
Alexander Couzens6a161492020-07-12 13:45:50 +0200854{
855 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzense769f522020-12-07 07:37:07 +0100856 struct gprs_ns_ie_ip4_elem *ip4_elems;
857 struct gprs_ns_ie_ip6_elem *ip6_elems;
858 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100859 struct ns2_sns_bind *sbind;
Harald Welte4f127462021-03-02 20:49:10 +0100860 const struct osmo_sockaddr *remote;
Alexander Couzense769f522020-12-07 07:37:07 +0100861 const struct osmo_sockaddr *sa;
862 struct osmo_sockaddr local;
863 int count;
Alexander Couzens6a161492020-07-12 13:45:50 +0200864
Alexander Couzensd2c6c492021-06-06 01:57:52 +0200865 ns2_clear_elems(&gss->local);
Alexander Couzens7a7b20b2021-01-18 10:47:33 +0100866
Alexander Couzense769f522020-12-07 07:37:07 +0100867 /* no initial available */
Harald Welte4f127462021-03-02 20:49:10 +0100868 if (gss->role == GPRS_SNS_ROLE_BSS) {
869 if (!gss->initial)
870 return;
871 remote = &gss->initial->saddr;
872 } else
873 remote = gprs_ns2_ip_vc_remote(gss->sns_nsvc);
Alexander Couzense769f522020-12-07 07:37:07 +0100874
875 /* count how many bindings are available (only UDP binds) */
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100876 count = llist_count(&gss->binds);
Alexander Couzense769f522020-12-07 07:37:07 +0100877 if (count == 0) {
Harald Welte05992872021-03-04 15:49:21 +0100878 LOGPFSML(fi, LOGL_ERROR, "No local binds for this NSE -> cannot determine IP endpoints\n");
Alexander Couzense769f522020-12-07 07:37:07 +0100879 return;
880 }
881
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200882 switch (gss->family) {
883 case AF_INET:
Alexander Couzens71128672021-06-05 18:44:01 +0200884 ip4_elems = talloc_realloc(fi, gss->local.ip4, struct gprs_ns_ie_ip4_elem, count);
Alexander Couzense769f522020-12-07 07:37:07 +0100885 if (!ip4_elems)
886 return;
887
Alexander Couzens71128672021-06-05 18:44:01 +0200888 gss->local.ip4 = ip4_elems;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100889 llist_for_each_entry(sbind, &gss->binds, list) {
890 bind = sbind->bind;
Alexander Couzense769f522020-12-07 07:37:07 +0100891 sa = gprs_ns2_ip_bind_sockaddr(bind);
892 if (!sa)
893 continue;
894
895 if (sa->u.sas.ss_family != AF_INET)
896 continue;
897
898 /* check if this is an specific bind */
899 if (sa->u.sin.sin_addr.s_addr == 0) {
900 if (osmo_sockaddr_local_ip(&local, remote))
901 continue;
902
903 ip4_elems->ip_addr = local.u.sin.sin_addr.s_addr;
904 } else {
905 ip4_elems->ip_addr = sa->u.sin.sin_addr.s_addr;
906 }
907
908 ip4_elems->udp_port = sa->u.sin.sin_port;
Alexander Couzensc4704762021-02-08 23:13:12 +0100909 ip4_elems->sig_weight = bind->sns_sig_weight;
910 ip4_elems->data_weight = bind->sns_data_weight;
Alexander Couzense769f522020-12-07 07:37:07 +0100911 ip4_elems++;
912 }
913
Alexander Couzens71128672021-06-05 18:44:01 +0200914 gss->local.num_ip4 = count;
915 gss->num_max_nsvcs = OSMO_MAX(gss->num_max_ip4_remote * gss->local.num_ip4, 8);
Alexander Couzense769f522020-12-07 07:37:07 +0100916 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +0200917 case AF_INET6:
Alexander Couzense769f522020-12-07 07:37:07 +0100918 /* IPv6 */
Alexander Couzens71128672021-06-05 18:44:01 +0200919 ip6_elems = talloc_realloc(fi, gss->local.ip6, struct gprs_ns_ie_ip6_elem, count);
Alexander Couzense769f522020-12-07 07:37:07 +0100920 if (!ip6_elems)
921 return;
922
Alexander Couzens71128672021-06-05 18:44:01 +0200923 gss->local.ip6 = ip6_elems;
Alexander Couzense769f522020-12-07 07:37:07 +0100924
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100925 llist_for_each_entry(sbind, &gss->binds, list) {
926 bind = sbind->bind;
Alexander Couzense769f522020-12-07 07:37:07 +0100927 sa = gprs_ns2_ip_bind_sockaddr(bind);
928 if (!sa)
929 continue;
930
931 if (sa->u.sas.ss_family != AF_INET6)
932 continue;
933
934 /* check if this is an specific bind */
935 if (IN6_IS_ADDR_UNSPECIFIED(&sa->u.sin6.sin6_addr)) {
936 if (osmo_sockaddr_local_ip(&local, remote))
937 continue;
938
939 ip6_elems->ip_addr = local.u.sin6.sin6_addr;
940 } else {
941 ip6_elems->ip_addr = sa->u.sin6.sin6_addr;
942 }
943
944 ip6_elems->udp_port = sa->u.sin.sin_port;
Alexander Couzensc4704762021-02-08 23:13:12 +0100945 ip6_elems->sig_weight = bind->sns_sig_weight;
946 ip6_elems->data_weight = bind->sns_data_weight;
Alexander Couzense769f522020-12-07 07:37:07 +0100947
948 ip6_elems++;
949 }
Alexander Couzens71128672021-06-05 18:44:01 +0200950 gss->local.num_ip6 = count;
951 gss->num_max_nsvcs = OSMO_MAX(gss->num_max_ip6_remote * gss->local.num_ip6, 8);
Alexander Couzense769f522020-12-07 07:37:07 +0100952 break;
953 }
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200954
955 ns2_sns_copy_local_endpoints(gss);
Harald Welte24920e22021-03-04 13:03:27 +0100956}
957
Alexander Couzens6608ce92021-04-26 20:39:46 +0200958static void ns2_sns_choose_next_bind(struct ns2_sns_state *gss)
959{
960 /* take the first bind or take the next bind */
961 if (!gss->initial_bind || gss->initial_bind->list.next == &gss->binds)
962 gss->initial_bind = llist_first_entry_or_null(&gss->binds, struct ns2_sns_bind, list);
963 else
964 gss->initial_bind = llist_entry(gss->initial_bind->list.next, struct ns2_sns_bind, list);
965}
966
Harald Welte24920e22021-03-04 13:03:27 +0100967/* setup all dynamic SNS settings, create a new nsvc and send the SIZE */
Harald Welte694dad52021-03-23 15:22:16 +0100968static void ns2_sns_st_bss_size_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
Harald Welte24920e22021-03-04 13:03:27 +0100969{
970 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
971
Harald Weltef61a9152021-03-02 22:20:17 +0100972 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
973
Harald Welte24920e22021-03-04 13:03:27 +0100974 /* on a generic failure, the timer callback will recover */
975 if (old_state != GPRS_SNS_ST_UNCONFIGURED)
976 ns2_prim_status_ind(gss->nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_FAILURE);
Harald Welte694dad52021-03-23 15:22:16 +0100977 if (old_state != GPRS_SNS_ST_BSS_SIZE)
Harald Welte24920e22021-03-04 13:03:27 +0100978 gss->N = 0;
979
Alexander Couzens1f3193d2021-06-05 22:08:11 +0200980 ns2_clear_procedures(gss);
Harald Welte24920e22021-03-04 13:03:27 +0100981 gss->alive = false;
982
983 ns2_sns_compute_local_ep_from_binds(fi);
Alexander Couzens6608ce92021-04-26 20:39:46 +0200984 ns2_sns_choose_next_bind(gss);
Harald Welte24920e22021-03-04 13:03:27 +0100985
986 /* setup the NSVC */
987 if (!gss->sns_nsvc) {
988 struct gprs_ns2_vc_bind *bind = gss->initial_bind->bind;
989 struct osmo_sockaddr *remote = &gss->initial->saddr;
990 gss->sns_nsvc = ns2_ip_bind_connect(bind, gss->nse, remote);
991 if (!gss->sns_nsvc)
992 return;
Harald Weltec962a2e2021-03-05 08:09:08 +0100993 /* A pre-configured endpoint shall not be used for NSE data or signalling traffic
994 * (with the exception of Size and Configuration procedures) unless it is configured
995 * by the SGSN using the auto-configuration procedures */
Harald Welte24920e22021-03-04 13:03:27 +0100996 gss->sns_nsvc->sns_only = true;
997 }
998
Alexander Couzens6a161492020-07-12 13:45:50 +0200999 if (gss->num_max_ip4_remote > 0)
Alexander Couzens71128672021-06-05 18:44:01 +02001000 ns2_tx_sns_size(gss->sns_nsvc, true, gss->num_max_nsvcs, gss->local.num_ip4, -1);
Alexander Couzens6a161492020-07-12 13:45:50 +02001001 else
Alexander Couzens71128672021-06-05 18:44:01 +02001002 ns2_tx_sns_size(gss->sns_nsvc, true, gss->num_max_nsvcs, -1, gss->local.num_ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +02001003}
1004
Harald Welte694dad52021-03-23 15:22:16 +01001005static void ns2_sns_st_bss_config_bss(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +02001006{
Harald Weltef61a9152021-03-02 22:20:17 +01001007 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens3df58862021-02-05 17:18:08 +01001008 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
Harald Weltef61a9152021-03-02 22:20:17 +01001009 struct tlv_parsed *tp = NULL;
1010
1011 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
Alexander Couzens6a161492020-07-12 13:45:50 +02001012
1013 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001014 case NS2_SNS_EV_RX_CONFIG_ACK:
Alexander Couzens6a161492020-07-12 13:45:50 +02001015 tp = (struct tlv_parsed *) data;
1016 if (TLVP_VAL_MINLEN(tp, NS_IE_CAUSE, 1)) {
1017 LOGPFSML(fi, LOGL_ERROR, "SNS-CONFIG-ACK with cause %s\n",
1018 gprs_ns2_cause_str(*TLVP_VAL(tp, NS_IE_CAUSE)));
1019 /* TODO: What to do? */
1020 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001021 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 +02001022 }
1023 break;
1024 default:
1025 OSMO_ASSERT(0);
1026 }
1027}
1028
Harald Welte694dad52021-03-23 15:22:16 +01001029static void ns2_sns_st_bss_config_bss_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
Alexander Couzens6a161492020-07-12 13:45:50 +02001030{
1031 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens790a9632021-02-05 17:18:39 +01001032
Harald Weltef61a9152021-03-02 22:20:17 +01001033 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
1034
Harald Welte694dad52021-03-23 15:22:16 +01001035 if (old_state != GPRS_SNS_ST_BSS_CONFIG_BSS)
Alexander Couzens790a9632021-02-05 17:18:39 +01001036 gss->N = 0;
1037
Alexander Couzens6a161492020-07-12 13:45:50 +02001038 /* Transmit SNS-CONFIG */
Alexander Couzens077ce5a2021-06-06 01:32:45 +02001039 switch (gss->family) {
1040 case AF_INET:
Alexander Couzens6a161492020-07-12 13:45:50 +02001041 ns2_tx_sns_config(gss->sns_nsvc, true,
Alexander Couzens71128672021-06-05 18:44:01 +02001042 gss->local.ip4, gss->local.num_ip4,
Alexander Couzense78207f2020-12-07 06:19:29 +01001043 NULL, 0);
Alexander Couzens6a161492020-07-12 13:45:50 +02001044 break;
Alexander Couzens077ce5a2021-06-06 01:32:45 +02001045 case AF_INET6:
Alexander Couzens6a161492020-07-12 13:45:50 +02001046 ns2_tx_sns_config(gss->sns_nsvc, true,
Alexander Couzense78207f2020-12-07 06:19:29 +01001047 NULL, 0,
Alexander Couzens71128672021-06-05 18:44:01 +02001048 gss->local.ip6, gss->local.num_ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +02001049 break;
1050 }
1051}
1052
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001053/* calculate the timeout of the configured state. the configured
1054 * state will fail if not at least one NS-VC is alive within X second.
1055 */
1056static inline int ns_sns_configured_timeout(struct osmo_fsm_inst *fi)
1057{
1058 int secs;
1059 struct gprs_ns2_inst *nsi = nse_inst_from_fi(fi)->nsi;
1060 secs = nsi->timeout[NS_TOUT_TNS_ALIVE] * nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES];
1061 secs += nsi->timeout[NS_TOUT_TNS_TEST];
1062
1063 return secs;
1064}
Alexander Couzens6a161492020-07-12 13:45:50 +02001065
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001066/* append the remote endpoints from the parsed TLV array to the ns2_sns_state */
1067static int ns_sns_append_remote_eps(struct osmo_fsm_inst *fi, const struct tlv_parsed *tp)
Alexander Couzens6a161492020-07-12 13:45:50 +02001068{
1069 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +02001070
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001071 if (TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1072 const struct gprs_ns_ie_ip4_elem *v4_list;
1073 unsigned int num_v4;
1074 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1075 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Alexander Couzens6a161492020-07-12 13:45:50 +02001076
Alexander Couzens71128672021-06-05 18:44:01 +02001077 if (num_v4 && gss->remote.ip6)
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001078 return -NS_CAUSE_INVAL_NR_IPv4_EP;
Alexander Couzens6a161492020-07-12 13:45:50 +02001079
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001080 /* realloc to the new size */
Alexander Couzens71128672021-06-05 18:44:01 +02001081 gss->remote.ip4 = talloc_realloc(gss, gss->remote.ip4,
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001082 struct gprs_ns_ie_ip4_elem,
Alexander Couzens71128672021-06-05 18:44:01 +02001083 gss->remote.num_ip4 + num_v4);
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001084 /* append the new entries to the end of the list */
Alexander Couzens71128672021-06-05 18:44:01 +02001085 memcpy(&gss->remote.ip4[gss->remote.num_ip4], v4_list, num_v4*sizeof(*v4_list));
1086 gss->remote.num_ip4 += num_v4;
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001087
1088 LOGPFSML(fi, LOGL_INFO, "Rx SNS-CONFIG: Remote IPv4 list now %u entries\n",
Alexander Couzens71128672021-06-05 18:44:01 +02001089 gss->remote.num_ip4);
Alexander Couzens6a161492020-07-12 13:45:50 +02001090 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001091
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001092 if (TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1093 const struct gprs_ns_ie_ip6_elem *v6_list;
1094 unsigned int num_v6;
1095 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1096 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
1097
Alexander Couzens71128672021-06-05 18:44:01 +02001098 if (num_v6 && gss->remote.ip4)
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001099 return -NS_CAUSE_INVAL_NR_IPv6_EP;
1100
1101 /* realloc to the new size */
Alexander Couzens71128672021-06-05 18:44:01 +02001102 gss->remote.ip6 = talloc_realloc(gss, gss->remote.ip6,
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001103 struct gprs_ns_ie_ip6_elem,
Alexander Couzens71128672021-06-05 18:44:01 +02001104 gss->remote.num_ip6 + num_v6);
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001105 /* append the new entries to the end of the list */
Alexander Couzens71128672021-06-05 18:44:01 +02001106 memcpy(&gss->remote.ip6[gss->remote.num_ip6], v6_list, num_v6*sizeof(*v6_list));
1107 gss->remote.num_ip6 += num_v6;
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001108
Alexander Couzens71128672021-06-05 18:44:01 +02001109 LOGPFSML(fi, LOGL_INFO, "Rx SNS-CONFIG: Remote IPv6 list now %d entries\n",
1110 gss->remote.num_ip6);
Alexander Couzens6a161492020-07-12 13:45:50 +02001111 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001112
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001113 return 0;
Alexander Couzens6a161492020-07-12 13:45:50 +02001114}
1115
Harald Welte694dad52021-03-23 15:22:16 +01001116static void ns2_sns_st_bss_config_sgsn_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
Alexander Couzens790a9632021-02-05 17:18:39 +01001117{
1118 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1119
Harald Weltef61a9152021-03-02 22:20:17 +01001120 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
1121
Harald Welte694dad52021-03-23 15:22:16 +01001122 if (old_state != GPRS_SNS_ST_BSS_CONFIG_SGSN)
Alexander Couzens790a9632021-02-05 17:18:39 +01001123 gss->N = 0;
1124}
1125
Harald Welte694dad52021-03-23 15:22:16 +01001126static void ns2_sns_st_bss_config_sgsn(struct osmo_fsm_inst *fi, uint32_t event, void *data)
Alexander Couzens6a161492020-07-12 13:45:50 +02001127{
1128 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001129 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
1130 uint8_t cause;
1131 int rc;
Alexander Couzens6a161492020-07-12 13:45:50 +02001132
Harald Weltef61a9152021-03-02 22:20:17 +01001133 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_BSS);
1134
Alexander Couzens6a161492020-07-12 13:45:50 +02001135 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001136 case NS2_SNS_EV_RX_CONFIG_END:
1137 case NS2_SNS_EV_RX_CONFIG:
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001138 rc = ns_sns_append_remote_eps(fi, data);
1139 if (rc < 0) {
1140 cause = -rc;
1141 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
1142 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
1143 return;
Alexander Couzens6a161492020-07-12 13:45:50 +02001144 }
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001145 if (event == NS2_SNS_EV_RX_CONFIG_END) {
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001146 /* check if sum of data / sig weights == 0 */
Alexander Couzens019da4b2021-06-06 02:48:18 +02001147 if (ip46_weight_sum_data(&gss->remote) == 0 || ip46_weight_sum_sig(&gss->remote) == 0) {
Harald Weltec1c7e4a2021-03-02 20:47:29 +01001148 cause = NS_CAUSE_INVAL_WEIGH;
1149 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
1150 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
1151 return;
1152 }
1153 create_missing_nsvcs(fi);
1154 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
1155 /* start the test procedure on ALL NSVCs! */
1156 gprs_ns2_start_alive_all_nsvcs(nse);
1157 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0);
1158 } else {
1159 /* just send CONFIG-ACK */
1160 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
1161 osmo_timer_schedule(&fi->timer, nse->nsi->timeout[NS_TOUT_TSNS_PROV], 0);
Alexander Couzens6a161492020-07-12 13:45:50 +02001162 }
1163 break;
1164 default:
1165 OSMO_ASSERT(0);
1166 }
1167}
1168
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001169/* called when receiving NS2_SNS_EV_RX_ADD in state configure */
Alexander Couzens6a161492020-07-12 13:45:50 +02001170static void ns2_sns_st_configured_add(struct osmo_fsm_inst *fi,
1171 struct ns2_sns_state *gss,
1172 struct tlv_parsed *tp)
1173{
1174 const struct gprs_ns_ie_ip4_elem *v4_list = NULL;
1175 const struct gprs_ns_ie_ip6_elem *v6_list = NULL;
1176 int num_v4 = 0, num_v6 = 0;
1177 uint8_t trans_id, cause = 0xff;
Harald Welte7da6ace2020-09-18 09:48:05 +02001178 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001179 int rc = 0;
1180
1181 /* TODO: refactor EV_ADD/CHANGE/REMOVE by
1182 * check uniqueness within the lists (no doublicate entries)
1183 * check not-known-by-us and sent back a list of unknown/known values
1184 * (abnormal behaviour according to 48.016)
1185 */
1186
1187 trans_id = *TLVP_VAL(tp, NS_IE_TRANS_ID);
Alexander Couzens077ce5a2021-06-06 01:32:45 +02001188 if (gss->family == AF_INET) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001189 if (!TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1190 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
1191 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1192 return;
1193 }
1194
1195 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1196 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001197 for (i = 0; i < num_v4; i++) {
1198 unsigned int j;
Alexander Couzens6a161492020-07-12 13:45:50 +02001199 rc = do_sns_add(fi, &v4_list[i], NULL);
1200 if (rc < 0) {
1201 /* rollback/undo to restore previous state */
Harald Welte7da6ace2020-09-18 09:48:05 +02001202 for (j = 0; j < i; j++)
Alexander Couzens6a161492020-07-12 13:45:50 +02001203 do_sns_delete(fi, &v4_list[j], NULL);
1204 cause = -rc;
1205 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1206 break;
1207 }
1208 }
1209 } else { /* IPv6 */
1210 if (!TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1211 cause = NS_CAUSE_INVAL_NR_IPv6_EP;
1212 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1213 return;
1214 }
1215
1216 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1217 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001218 for (i = 0; i < num_v6; i++) {
1219 unsigned int j;
Alexander Couzens6a161492020-07-12 13:45:50 +02001220 rc = do_sns_add(fi, NULL, &v6_list[i]);
1221 if (rc < 0) {
1222 /* rollback/undo to restore previous state */
Harald Welte7da6ace2020-09-18 09:48:05 +02001223 for (j = 0; j < i; j++)
Alexander Couzens6a161492020-07-12 13:45:50 +02001224 do_sns_delete(fi, NULL, &v6_list[j]);
1225 cause = -rc;
1226 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1227 break;
1228 }
1229 }
1230 }
1231
1232 /* TODO: correct behaviour is to answer to the *same* NSVC from which the SNS_ADD was received */
1233 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, NULL, v4_list, num_v4, v6_list, num_v6);
1234}
1235
1236static void ns2_sns_st_configured_delete(struct osmo_fsm_inst *fi,
1237 struct ns2_sns_state *gss,
1238 struct tlv_parsed *tp)
1239{
1240 const struct gprs_ns_ie_ip4_elem *v4_list = NULL;
1241 const struct gprs_ns_ie_ip6_elem *v6_list = NULL;
1242 int num_v4 = 0, num_v6 = 0;
1243 uint8_t trans_id, cause = 0xff;
Harald Welte7da6ace2020-09-18 09:48:05 +02001244 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001245 int rc = 0;
1246
1247 /* TODO: split up delete into v4 + v6
1248 * TODO: check if IPv4_LIST or IP_ADDR(v4) is present on IPv6 and vice versa
1249 * TODO: check if IPv4_LIST/IPv6_LIST and IP_ADDR is present at the same time
1250 */
1251 trans_id = *TLVP_VAL(tp, NS_IE_TRANS_ID);
Alexander Couzens077ce5a2021-06-06 01:32:45 +02001252 if (gss->family == AF_INET) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001253 if (TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1254 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1255 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001256 for ( i = 0; i < num_v4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001257 rc = do_sns_delete(fi, &v4_list[i], NULL);
1258 if (rc < 0) {
1259 cause = -rc;
1260 /* continue to delete others */
1261 }
1262 }
1263 if (cause != 0xff) {
1264 /* TODO: create list of not-deleted and return it */
1265 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1266 return;
1267 }
1268
1269 } else if (TLVP_PRESENT(tp, NS_IE_IP_ADDR) && TLVP_LEN(tp, NS_IE_IP_ADDR) == 5) {
1270 /* delete all NS-VCs for given IPv4 address */
1271 const uint8_t *ie = TLVP_VAL(tp, NS_IE_IP_ADDR);
1272 struct gprs_ns_ie_ip4_elem *ip4_remote;
1273 uint32_t ip_addr = *(uint32_t *)(ie+1);
1274 if (ie[0] != 0x01) { /* Address Type != IPv4 */
1275 cause = NS_CAUSE_UNKN_IP_ADDR;
1276 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1277 return;
1278 }
1279 /* make a copy as do_sns_delete() will change the array underneath us */
Alexander Couzens71128672021-06-05 18:44:01 +02001280 ip4_remote = talloc_memdup(fi, gss->remote.ip4,
1281 gss->remote.num_ip4 * sizeof(*v4_list));
1282 for (i = 0; i < gss->remote.num_ip4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001283 if (ip4_remote[i].ip_addr == ip_addr) {
1284 rc = do_sns_delete(fi, &ip4_remote[i], NULL);
1285 if (rc < 0) {
1286 cause = -rc;
1287 /* continue to delete others */
1288 }
1289 }
1290 }
1291 talloc_free(ip4_remote);
1292 if (cause != 0xff) {
1293 /* TODO: create list of not-deleted and return it */
1294 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1295 return;
1296 }
1297 } else {
1298 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
1299 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1300 return;
1301 }
1302 } else { /* IPv6 */
1303 if (TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1304 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1305 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001306 for (i = 0; i < num_v6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001307 rc = do_sns_delete(fi, NULL, &v6_list[i]);
1308 if (rc < 0) {
1309 cause = -rc;
1310 /* continue to delete others */
1311 }
1312 }
1313 if (cause != 0xff) {
1314 /* TODO: create list of not-deleted and return it */
1315 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1316 return;
1317 }
1318 } else if (TLVP_PRES_LEN(tp, NS_IE_IP_ADDR, 17)) {
1319 /* delete all NS-VCs for given IPv4 address */
1320 const uint8_t *ie = TLVP_VAL(tp, NS_IE_IP_ADDR);
1321 struct gprs_ns_ie_ip6_elem *ip6_remote;
1322 struct in6_addr ip6_addr;
Harald Welte7da6ace2020-09-18 09:48:05 +02001323 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001324 if (ie[0] != 0x02) { /* Address Type != IPv6 */
1325 cause = NS_CAUSE_UNKN_IP_ADDR;
1326 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1327 return;
1328 }
1329 memcpy(&ip6_addr, (ie+1), sizeof(struct in6_addr));
1330 /* make a copy as do_sns_delete() will change the array underneath us */
Alexander Couzens71128672021-06-05 18:44:01 +02001331 ip6_remote = talloc_memdup(fi, gss->remote.ip6,
1332 gss->remote.num_ip6 * sizeof(*v4_list));
1333 for (i = 0; i < gss->remote.num_ip6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001334 if (!memcmp(&ip6_remote[i].ip_addr, &ip6_addr, sizeof(struct in6_addr))) {
1335 rc = do_sns_delete(fi, NULL, &ip6_remote[i]);
1336 if (rc < 0) {
1337 cause = -rc;
1338 /* continue to delete others */
1339 }
1340 }
1341 }
1342
1343 talloc_free(ip6_remote);
1344 if (cause != 0xff) {
1345 /* TODO: create list of not-deleted and return it */
1346 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1347 return;
1348 }
1349 } else {
1350 cause = NS_CAUSE_INVAL_NR_IPv6_EP;
1351 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1352 return;
1353 }
1354 }
1355 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, NULL, v4_list, num_v4, v6_list, num_v6);
1356}
1357
1358static void ns2_sns_st_configured_change(struct osmo_fsm_inst *fi,
1359 struct ns2_sns_state *gss,
1360 struct tlv_parsed *tp)
1361{
1362 const struct gprs_ns_ie_ip4_elem *v4_list = NULL;
1363 const struct gprs_ns_ie_ip6_elem *v6_list = NULL;
1364 int num_v4 = 0, num_v6 = 0;
1365 uint8_t trans_id, cause = 0xff;
1366 int rc = 0;
Harald Welte7da6ace2020-09-18 09:48:05 +02001367 unsigned int i;
Alexander Couzens6a161492020-07-12 13:45:50 +02001368
1369 trans_id = *TLVP_VAL(tp, NS_IE_TRANS_ID);
1370 if (TLVP_PRESENT(tp, NS_IE_IPv4_LIST)) {
1371 v4_list = (const struct gprs_ns_ie_ip4_elem *) TLVP_VAL(tp, NS_IE_IPv4_LIST);
1372 num_v4 = TLVP_LEN(tp, NS_IE_IPv4_LIST) / sizeof(*v4_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001373 for (i = 0; i < num_v4; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001374 rc = do_sns_change_weight(fi, &v4_list[i], NULL);
1375 if (rc < 0) {
1376 cause = -rc;
1377 /* continue to others */
1378 }
1379 }
1380 if (cause != 0xff) {
1381 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1382 return;
1383 }
1384 } else if (TLVP_PRESENT(tp, NS_IE_IPv6_LIST)) {
1385 v6_list = (const struct gprs_ns_ie_ip6_elem *) TLVP_VAL(tp, NS_IE_IPv6_LIST);
1386 num_v6 = TLVP_LEN(tp, NS_IE_IPv6_LIST) / sizeof(*v6_list);
Harald Welte7da6ace2020-09-18 09:48:05 +02001387 for (i = 0; i < num_v6; i++) {
Alexander Couzens6a161492020-07-12 13:45:50 +02001388 rc = do_sns_change_weight(fi, NULL, &v6_list[i]);
1389 if (rc < 0) {
1390 cause = -rc;
1391 /* continue to others */
1392 }
1393 }
1394 if (cause != 0xff) {
1395 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1396 return;
1397 }
1398 } else {
1399 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
1400 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, &cause, NULL, 0, NULL, 0);
1401 return;
1402 }
1403 ns2_tx_sns_ack(gss->sns_nsvc, trans_id, NULL, v4_list, num_v4, v6_list, num_v6);
1404}
1405
1406static void ns2_sns_st_configured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1407{
1408 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1409 struct tlv_parsed *tp = data;
1410
1411 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001412 case NS2_SNS_EV_RX_ADD:
Alexander Couzens6a161492020-07-12 13:45:50 +02001413 ns2_sns_st_configured_add(fi, gss, tp);
1414 break;
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001415 case NS2_SNS_EV_RX_DELETE:
Alexander Couzens6a161492020-07-12 13:45:50 +02001416 ns2_sns_st_configured_delete(fi, gss, tp);
1417 break;
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001418 case NS2_SNS_EV_RX_CHANGE_WEIGHT:
Alexander Couzens6a161492020-07-12 13:45:50 +02001419 ns2_sns_st_configured_change(fi, gss, tp);
1420 break;
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001421 case NS2_SNS_EV_REQ_NSVC_ALIVE:
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001422 osmo_timer_del(&fi->timer);
1423 break;
Alexander Couzens6a161492020-07-12 13:45:50 +02001424 }
1425}
1426
1427static void ns2_sns_st_configured_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
1428{
Alexander Couzenscdb2baa2021-04-01 15:29:16 +02001429 struct gprs_ns2_vc *nsvc;
1430 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +02001431 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
Alexander Couzenscdb2baa2021-04-01 15:29:16 +02001432 /* NS-VC status updates are only parsed in ST_CONFIGURED.
1433 * Do an initial check if there are any nsvc alive atm */
1434 llist_for_each_entry(nsvc, &nse->nsvc, list) {
1435 if (ns2_vc_is_unblocked(nsvc)) {
1436 gss->alive = true;
1437 osmo_timer_del(&fi->timer);
1438 break;
1439 }
1440 }
1441
Alexander Couzens53e70092021-04-06 15:45:47 +02001442 /* remove the initial NSVC if the NSVC isn't part of the configuration */
1443 if (gss->sns_nsvc->sns_only)
1444 gprs_ns2_free_nsvc(gss->sns_nsvc);
1445
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001446 if (old_state != GPRS_SNS_ST_LOCAL_PROCEDURE)
1447 ns2_prim_status_ind(nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_CONFIGURED);
1448
1449 if (!llist_empty(&gss->procedures)) {
1450 osmo_fsm_inst_state_chg(gss->nse->bss_sns_fi, GPRS_SNS_ST_LOCAL_PROCEDURE,
1451 gss->nse->nsi->timeout[NS_TOUT_TSNS_PROV], 5);
1452 }
1453}
1454
1455static void ns2_sns_st_local_procedure_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
1456{
1457 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1458
1459 /* check if resend or not */
1460 if (!gss->current_procedure) {
1461 /* take next procedure */
1462 gss->current_procedure = llist_first_entry_or_null(&gss->procedures,
1463 struct ns2_sns_procedure, list);
1464 if (!gss->current_procedure) {
1465 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0);
1466 return;
1467 }
1468 gss->N = 0;
1469 gss->current_procedure->running = true;
1470 gss->current_procedure->trans_id = ++gss->trans_id;
1471 if (gss->trans_id == 0)
1472 gss->trans_id = gss->current_procedure->trans_id = 1;
1473
1474 }
1475
1476 /* also takes care of retransmitting */
1477 switch (gss->current_procedure->procedure) {
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001478 case SNS_PROC_ADD:
1479 if (gss->family == AF_INET)
1480 ns2_tx_sns_add(gss->sns_nsvc, gss->current_procedure->trans_id, &gss->current_procedure->ip4, 1, NULL, 0);
1481 else
1482 ns2_tx_sns_add(gss->sns_nsvc, gss->current_procedure->trans_id, NULL, 0, &gss->current_procedure->ip6, 1);
1483 break;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001484 case SNS_PROC_CHANGE_WEIGHT:
1485 if (gss->family == AF_INET)
1486 ns2_tx_sns_change_weight(gss->sns_nsvc, gss->current_procedure->trans_id, &gss->current_procedure->ip4, 1, NULL, 0);
1487 else
1488 ns2_tx_sns_change_weight(gss->sns_nsvc, gss->current_procedure->trans_id, NULL, 0, &gss->current_procedure->ip6, 1);
1489 break;
1490 default:
1491 break;
1492 }
1493}
1494
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001495static void create_nsvc_for_new_sbind(struct ns2_sns_state *gss, struct ns2_sns_bind *sbind)
1496{
1497 struct gprs_ns2_nse *nse = gss->nse;
1498 struct gprs_ns2_vc_bind *bind = sbind->bind;
1499 struct gprs_ns2_vc *nsvc;
1500 struct osmo_sockaddr remote = { };
1501 unsigned int i;
1502
1503 /* iterate over all remote IPv4 endpoints */
1504 for (i = 0; i < gss->remote.num_ip4; i++) {
1505 const struct gprs_ns_ie_ip4_elem *ip4 = &gss->remote.ip4[i];
1506
1507 remote.u.sin.sin_family = AF_INET;
1508 remote.u.sin.sin_addr.s_addr = ip4->ip_addr;
1509 remote.u.sin.sin_port = ip4->udp_port;
1510 /* we only care about UDP binds */
1511 if (bind->ll != GPRS_NS2_LL_UDP)
1512 continue;
1513
1514 nsvc = nsvc_for_bind_and_remote(nse, bind, &remote);
1515 if (!nsvc) {
1516 nsvc = gprs_ns2_ip_connect_inactive(bind, &remote, nse, 0);
1517 if (!nsvc) {
1518 /* TODO: add to a list to send back a NS-STATUS */
1519 continue;
1520 }
1521 }
1522
1523 /* update data / signalling weight */
1524 nsvc->data_weight = ip4->data_weight;
1525 nsvc->sig_weight = ip4->sig_weight;
1526 nsvc->sns_only = false;
1527 }
1528
1529 /* iterate over all remote IPv4 endpoints */
1530 for (i = 0; i < gss->remote.num_ip6; i++) {
1531 const struct gprs_ns_ie_ip6_elem *ip6 = &gss->remote.ip6[i];
1532
1533 remote.u.sin6.sin6_family = AF_INET6;
1534 remote.u.sin6.sin6_addr = ip6->ip_addr;
1535 remote.u.sin6.sin6_port = ip6->udp_port;
1536
1537 /* we only care about UDP binds */
1538 nsvc = nsvc_for_bind_and_remote(nse, bind, &remote);
1539 if (!nsvc) {
1540 nsvc = gprs_ns2_ip_connect_inactive(bind, &remote, nse, 0);
1541 if (!nsvc) {
1542 /* TODO: add to a list to send back a NS-STATUS */
1543 continue;
1544 }
1545 }
1546
1547 /* update data / signalling weight */
1548 nsvc->data_weight = ip6->data_weight;
1549 nsvc->sig_weight = ip6->sig_weight;
1550 nsvc->sns_only = false;
1551 }
1552}
1553
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001554static void ns2_sns_st_local_procedure(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1555{
1556 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
1557 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
1558 struct gprs_ns_ie_ip4_elem *ip4, *proc4;
1559 struct gprs_ns_ie_ip6_elem *ip6, *proc6;
1560 struct tlv_parsed *tp = data;
1561 uint8_t trans_id;
1562 uint8_t cause;
1563
1564 switch (event) {
1565 case NS2_SNS_EV_RX_ADD:
1566 ns2_sns_st_configured_add(fi, gss, tp);
1567 break;
1568 case NS2_SNS_EV_RX_DELETE:
1569 ns2_sns_st_configured_delete(fi, gss, tp);
1570 break;
1571 case NS2_SNS_EV_RX_CHANGE_WEIGHT:
1572 ns2_sns_st_configured_change(fi, gss, tp);
1573 break;
1574 case NS2_SNS_EV_RX_ACK:
1575 /* presence of trans_id is already checked here */
1576 trans_id = tlvp_val8(tp, NS_IE_TRANS_ID, 0);
1577 if (trans_id != gss->current_procedure->trans_id) {
1578 LOGPFSML(fi, LOGL_INFO, "NSEI=%u Rx SNS ACK with invalid transaction id %d. Valid %d\n",
1579 nse->nsei, trans_id, gss->current_procedure->trans_id);
1580 break;
1581 }
1582
1583 if (TLVP_PRESENT(tp, NS_IE_CAUSE)) {
1584 /* what happend on error cause? return to size? */
1585 cause = tlvp_val8(tp, NS_IE_CAUSE, 0);
1586 LOGPFSML(fi, LOGL_ERROR, "NSEI=%u Rx SNS ACK trans %d with cause code %d.\n",
1587 nse->nsei, trans_id, cause);
1588 sns_failed(fi, NULL);
1589 break;
1590 }
1591
1592 switch (gss->current_procedure->procedure) {
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001593 case SNS_PROC_ADD:
1594 switch (gss->family) {
1595 case AF_INET:
1596 add_ip4_elem(gss, &gss->local, &gss->current_procedure->ip4);
1597 break;
1598 case AF_INET6:
1599 add_ip6_elem(gss, &gss->local, &gss->current_procedure->ip6);
1600 break;
1601 }
1602 create_nsvc_for_new_sbind(gss, gss->current_procedure->sbind);
1603 gprs_ns2_start_alive_all_nsvcs(nse);
1604 break;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001605 case SNS_PROC_CHANGE_WEIGHT:
1606 switch (gss->family) {
1607 case AF_INET:
1608 proc4 = &gss->current_procedure->ip4;
1609 for (unsigned int i=0; i<gss->local.num_ip4; i++) {
1610 ip4 = &gss->local.ip4[i];
1611 if (ip4->ip_addr != proc4->ip_addr ||
1612 ip4->udp_port != proc4->udp_port)
1613 continue;
1614 ip4->sig_weight = proc4->sig_weight;
1615 ip4->data_weight = proc4->data_weight;
1616 break;
1617 }
1618 break;
1619 case AF_INET6:
1620 proc6 = &gss->current_procedure->ip6;
1621 for (unsigned int i=0; i<gss->local.num_ip6; i++) {
1622 ip6 = &gss->local.ip6[i];
1623 if (memcmp(&ip6->ip_addr, &proc6->ip_addr, sizeof(proc6->ip_addr)) ||
1624 ip6->udp_port != proc6->udp_port) {
1625 continue;
1626 }
1627 ip6->sig_weight = proc6->sig_weight;
1628 ip6->data_weight = proc6->data_weight;
1629 break;
1630 }
1631 break;
1632 default:
1633 OSMO_ASSERT(0);
1634 }
1635 break;
1636 default:
1637 break;
1638 }
1639
1640 llist_del(&gss->current_procedure->list);
1641 talloc_free(gss->current_procedure);
1642 gss->current_procedure = NULL;
1643
1644 if (llist_empty(&gss->procedures))
1645 osmo_fsm_inst_state_chg(gss->nse->bss_sns_fi, GPRS_SNS_ST_CONFIGURED,
1646 0, 0);
1647 else
1648 osmo_fsm_inst_state_chg(gss->nse->bss_sns_fi, GPRS_SNS_ST_LOCAL_PROCEDURE,
1649 gss->nse->nsi->timeout[NS_TOUT_TSNS_PROV], 5);
1650 break;
1651 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001652}
1653
1654static const struct osmo_fsm_state ns2_sns_bss_states[] = {
1655 [GPRS_SNS_ST_UNCONFIGURED] = {
Alexander Couzense769f522020-12-07 07:37:07 +01001656 .in_event_mask = 0, /* handled by all_state_action */
Alexander Couzens0a7c5ee2021-04-10 18:20:21 +02001657 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
1658 S(GPRS_SNS_ST_BSS_SIZE),
Alexander Couzens6a161492020-07-12 13:45:50 +02001659 .name = "UNCONFIGURED",
Harald Welte694dad52021-03-23 15:22:16 +01001660 .action = ns2_sns_st_bss_unconfigured,
Alexander Couzens6a161492020-07-12 13:45:50 +02001661 },
Harald Welte694dad52021-03-23 15:22:16 +01001662 [GPRS_SNS_ST_BSS_SIZE] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001663 .in_event_mask = S(NS2_SNS_EV_RX_SIZE_ACK),
Alexander Couzens6a161492020-07-12 13:45:50 +02001664 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001665 S(GPRS_SNS_ST_BSS_SIZE) |
1666 S(GPRS_SNS_ST_BSS_CONFIG_BSS),
1667 .name = "BSS_SIZE",
1668 .action = ns2_sns_st_bss_size,
1669 .onenter = ns2_sns_st_bss_size_onenter,
Alexander Couzens6a161492020-07-12 13:45:50 +02001670 },
Harald Welte694dad52021-03-23 15:22:16 +01001671 [GPRS_SNS_ST_BSS_CONFIG_BSS] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001672 .in_event_mask = S(NS2_SNS_EV_RX_CONFIG_ACK),
Alexander Couzens6a161492020-07-12 13:45:50 +02001673 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001674 S(GPRS_SNS_ST_BSS_CONFIG_BSS) |
1675 S(GPRS_SNS_ST_BSS_CONFIG_SGSN) |
1676 S(GPRS_SNS_ST_BSS_SIZE),
1677 .name = "BSS_CONFIG_BSS",
1678 .action = ns2_sns_st_bss_config_bss,
1679 .onenter = ns2_sns_st_bss_config_bss_onenter,
Alexander Couzens6a161492020-07-12 13:45:50 +02001680 },
Harald Welte694dad52021-03-23 15:22:16 +01001681 [GPRS_SNS_ST_BSS_CONFIG_SGSN] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001682 .in_event_mask = S(NS2_SNS_EV_RX_CONFIG) |
1683 S(NS2_SNS_EV_RX_CONFIG_END),
Alexander Couzens6a161492020-07-12 13:45:50 +02001684 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001685 S(GPRS_SNS_ST_BSS_CONFIG_SGSN) |
Alexander Couzens6a161492020-07-12 13:45:50 +02001686 S(GPRS_SNS_ST_CONFIGURED) |
Harald Welte694dad52021-03-23 15:22:16 +01001687 S(GPRS_SNS_ST_BSS_SIZE),
1688 .name = "BSS_CONFIG_SGSN",
1689 .action = ns2_sns_st_bss_config_sgsn,
1690 .onenter = ns2_sns_st_bss_config_sgsn_onenter,
Alexander Couzens6a161492020-07-12 13:45:50 +02001691 },
1692 [GPRS_SNS_ST_CONFIGURED] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001693 .in_event_mask = S(NS2_SNS_EV_RX_ADD) |
1694 S(NS2_SNS_EV_RX_DELETE) |
1695 S(NS2_SNS_EV_RX_CHANGE_WEIGHT) |
1696 S(NS2_SNS_EV_REQ_NSVC_ALIVE),
Alexander Couzense03d8632020-12-06 03:31:44 +01001697 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001698 S(GPRS_SNS_ST_BSS_SIZE) |
1699 S(GPRS_SNS_ST_LOCAL_PROCEDURE),
Alexander Couzens6a161492020-07-12 13:45:50 +02001700 .name = "CONFIGURED",
1701 .action = ns2_sns_st_configured,
1702 .onenter = ns2_sns_st_configured_onenter,
1703 },
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001704 [GPRS_SNS_ST_LOCAL_PROCEDURE] = {
1705 .in_event_mask = S(NS2_SNS_EV_RX_ADD) |
1706 S(NS2_SNS_EV_RX_DELETE) |
1707 S(NS2_SNS_EV_RX_CHANGE_WEIGHT) |
1708 S(NS2_SNS_EV_RX_ACK) |
1709 S(NS2_SNS_EV_REQ_NSVC_ALIVE),
1710 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
1711 S(GPRS_SNS_ST_BSS_SIZE) |
1712 S(GPRS_SNS_ST_CONFIGURED) |
1713 S(GPRS_SNS_ST_LOCAL_PROCEDURE),
1714 .name = "LOCAL_PROCEDURE",
1715 .action = ns2_sns_st_local_procedure,
1716 .onenter = ns2_sns_st_local_procedure_onenter,
1717 },
1718
Alexander Couzens6a161492020-07-12 13:45:50 +02001719};
1720
1721static int ns2_sns_fsm_bss_timer_cb(struct osmo_fsm_inst *fi)
1722{
Alexander Couzens90ee9632020-12-07 06:18:32 +01001723 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6a161492020-07-12 13:45:50 +02001724 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
1725 struct gprs_ns2_inst *nsi = nse->nsi;
1726
Alexander Couzens90ee9632020-12-07 06:18:32 +01001727 gss->N++;
Alexander Couzens6a161492020-07-12 13:45:50 +02001728 switch (fi->T) {
1729 case 1:
Alexander Couzensa367d082020-12-21 14:06:24 +01001730 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_SIZE_RETRIES]) {
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001731 sns_failed(fi, "Size retries failed. Selecting next IP-SNS endpoint.");
Alexander Couzensa367d082020-12-21 14:06:24 +01001732 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001733 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 +01001734 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001735 break;
1736 case 2:
Alexander Couzensa367d082020-12-21 14:06:24 +01001737 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001738 sns_failed(fi, "BSS Config retries failed. Selecting next IP-SNS endpoint");
Alexander Couzensa367d082020-12-21 14:06:24 +01001739 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001740 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 +01001741 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001742 break;
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001743 case 3:
Alexander Couzens3df58862021-02-05 17:18:08 +01001744 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001745 sns_failed(fi, "SGSN Config retries failed. Selecting next IP-SNS endpoint.");
Alexander Couzens3df58862021-02-05 17:18:08 +01001746 } else {
Harald Welte694dad52021-03-23 15:22:16 +01001747 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 +01001748 }
1749 break;
1750 case 4:
Alexander Couzens652ab4d2021-06-12 23:09:46 +02001751 sns_failed(fi, "Config succeeded but no NS-VC came online. Selecting next IP-SNS endpoint.");
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01001752 break;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001753 case 5:
1754 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
1755 sns_failed(fi, "SNS Procedure retries failed.");
1756 } else {
1757 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_LOCAL_PROCEDURE, nsi->timeout[NS_TOUT_TSNS_PROV], 5);
1758 }
1759 break;
Alexander Couzens6a161492020-07-12 13:45:50 +02001760 }
1761 return 0;
1762}
1763
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001764static struct gprs_ns_ie_ip4_elem *ns2_get_sbind_ip4_entry(struct ns2_sns_state *gss,
1765 struct ns2_sns_bind *sbind,
1766 struct ns2_sns_elems *endpoints)
1767{
1768 const struct osmo_sockaddr *addr;
1769 struct gprs_ns_ie_ip4_elem *ip4;
1770
1771 if (gss->family != AF_INET)
1772 return NULL;
1773
1774 addr = gprs_ns2_ip_bind_sockaddr(sbind->bind);
1775 if (addr->u.sa.sa_family != AF_INET)
1776 return NULL;
1777
1778 for (unsigned int i=0; i<endpoints->num_ip4; i++) {
1779 ip4 = &endpoints->ip4[i];
1780 if (ip4->ip_addr == addr->u.sin.sin_addr.s_addr &&
1781 ip4->udp_port == addr->u.sin.sin_port)
1782 return ip4;
1783 }
1784
1785 return NULL;
1786}
1787
1788static struct gprs_ns_ie_ip6_elem *ns2_get_sbind_ip6_entry(struct ns2_sns_state *gss,
1789 struct ns2_sns_bind *sbind,
1790 struct ns2_sns_elems *endpoints)
1791{
1792 const struct osmo_sockaddr *addr;
1793 struct gprs_ns_ie_ip6_elem *ip6;
1794
1795 if (gss->family != AF_INET6)
1796 return NULL;
1797
1798 addr = gprs_ns2_ip_bind_sockaddr(sbind->bind);
1799 if (addr->u.sa.sa_family != AF_INET6)
1800 return NULL;
1801
1802 for (unsigned int i=0; i<endpoints->num_ip6; i++) {
1803 ip6 = &endpoints->ip6[i];
1804 if (memcmp(&ip6->ip_addr, &addr->u.sin6.sin6_addr, sizeof(ip6->ip_addr)) ||
1805 ip6->udp_port != addr->u.sin6.sin6_port)
1806 return ip6;
1807 }
1808
1809 return NULL;
1810}
1811
1812/* return != 0 if the resulting weight is invalid. return 1 if sbind doesn't have an entry */
1813static int ns2_update_weight_entry(struct ns2_sns_state *gss, struct ns2_sns_bind *sbind,
1814 struct ns2_sns_elems *endpoints)
1815{
1816 struct gprs_ns_ie_ip4_elem *ip4;
1817 struct gprs_ns_ie_ip6_elem *ip6;
1818
1819 switch (gss->family) {
1820 case AF_INET:
1821 ip4 = ns2_get_sbind_ip4_entry(gss, sbind, endpoints);
1822 if (!ip4)
1823 return 1;
1824 ip4->sig_weight = sbind->bind->sns_sig_weight;
1825 ip4->data_weight = sbind->bind->sns_data_weight;
1826 return (ip4_weight_sum_sig(endpoints) != 0 && ip4_weight_sum_data(endpoints) != 0);
1827 break;
1828 case AF_INET6:
1829 ip6 = ns2_get_sbind_ip6_entry(gss, sbind, endpoints);
1830 if (!ip6)
1831 return 1;
1832 ip6->sig_weight = sbind->bind->sns_sig_weight;
1833 ip6->data_weight = sbind->bind->sns_data_weight;
1834 return (ip6_weight_sum_sig(endpoints) != 0 && ip6_weight_sum_data(endpoints) != 0);
1835 break;
1836 default:
1837 OSMO_ASSERT(0);
1838 }
1839}
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001840static void ns2_add_procedure(struct ns2_sns_state *gss, struct ns2_sns_bind *sbind,
1841 enum sns_procedure procedure_type)
1842{
1843 struct ns2_sns_procedure *procedure = NULL;
1844 const struct osmo_sockaddr *saddr;
1845 saddr = gprs_ns2_ip_bind_sockaddr(sbind->bind);
1846
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001847 OSMO_ASSERT(saddr->u.sa.sa_family == gss->family);
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001848
1849 switch (procedure_type) {
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001850 case SNS_PROC_ADD:
1851 break;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001852 case SNS_PROC_CHANGE_WEIGHT:
1853 llist_for_each_entry(procedure, &gss->procedures, list) {
1854 if (procedure->sbind == sbind && procedure->procedure == procedure_type &&
1855 !procedure->running) {
1856 switch(gss->family) {
1857 case AF_INET:
1858 /* merge it with a previous procedure */
1859 procedure->ip4.ip_addr = sbind->bind->sns_sig_weight;
1860 procedure->ip4.data_weight = sbind->bind->sns_data_weight;
1861 break;
1862 case AF_INET6:
1863 /* merge it with a previous procedure */
1864 procedure->ip6.sig_weight = sbind->bind->sns_sig_weight;
1865 procedure->ip6.data_weight = sbind->bind->sns_data_weight;
1866 break;
1867 default:
1868 OSMO_ASSERT(0);
1869 }
1870 return;
1871 }
1872 }
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001873 break;
1874 default:
1875 return;
1876 }
1877
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001878 procedure = talloc_zero(gss, struct ns2_sns_procedure);
1879 if (!procedure)
1880 return;
1881
1882 llist_add_tail(&procedure->list, &gss->procedures);
1883 procedure->sbind = sbind;
1884 procedure->procedure = procedure_type;
1885 procedure->sig_weight = sbind->bind->sns_sig_weight;
1886 procedure->data_weight = sbind->bind->sns_data_weight;
1887
1888 switch(gss->family) {
1889 case AF_INET:
1890 procedure->ip4.ip_addr = saddr->u.sin.sin_addr.s_addr;
1891 procedure->ip4.udp_port = saddr->u.sin.sin_port;
1892 procedure->ip4.sig_weight = sbind->bind->sns_sig_weight;
1893 procedure->ip4.data_weight = sbind->bind->sns_data_weight;
1894 break;
1895 case AF_INET6:
1896
1897 memcpy(&procedure->ip6.ip_addr, &saddr->u.sin6.sin6_addr, sizeof(struct in6_addr));
1898 procedure->ip6.udp_port = saddr->u.sin.sin_port;
1899 procedure->ip6.sig_weight = sbind->bind->sns_sig_weight;
1900 procedure->ip6.data_weight = sbind->bind->sns_data_weight;
1901 break;
1902 default:
1903 OSMO_ASSERT(0);
1904 }
1905
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001906 if (gss->nse->bss_sns_fi->state == GPRS_SNS_ST_CONFIGURED) {
1907 osmo_fsm_inst_state_chg(gss->nse->bss_sns_fi, GPRS_SNS_ST_LOCAL_PROCEDURE,
1908 gss->nse->nsi->timeout[NS_TOUT_TSNS_PROV], 5);
1909 }
1910}
1911
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001912/* add an entrypoint to sns_endpoints */
1913static int ns2_sns_add_elements(struct ns2_sns_state *gss, struct ns2_sns_bind *sbind,
1914 struct ns2_sns_elems *elems)
1915{
1916 const struct osmo_sockaddr *saddr;
1917 struct gprs_ns_ie_ip4_elem ip4;
1918 struct gprs_ns_ie_ip6_elem ip6;
1919 int rc = -1;
1920
1921 saddr = gprs_ns2_ip_bind_sockaddr(sbind->bind);
1922 OSMO_ASSERT(saddr->u.sa.sa_family == gss->family);
1923
1924 switch (gss->family) {
1925 case AF_INET:
1926 ip4.ip_addr = saddr->u.sin.sin_addr.s_addr;
1927 ip4.udp_port= saddr->u.sin.sin_port;
1928 ip4.sig_weight = sbind->bind->sns_sig_weight;
1929 ip4.data_weight = sbind->bind->sns_data_weight;
1930 rc = add_ip4_elem(gss, elems, &ip4);
1931 break;
1932 case AF_INET6:
1933 memcpy(&ip6.ip_addr, &saddr->u.sin6.sin6_addr, sizeof(struct in6_addr));
1934 ip6.udp_port= saddr->u.sin.sin_port;
1935 ip6.sig_weight = sbind->bind->sns_sig_weight;
1936 ip6.data_weight = sbind->bind->sns_data_weight;
1937 rc = add_ip6_elem(gss, elems, &ip6);
1938 break;
1939 }
1940
1941 return rc;
1942}
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001943
Harald Welte9e37bf42021-03-02 20:48:31 +01001944/* common allstate-action for both roles */
Alexander Couzens6a161492020-07-12 13:45:50 +02001945static void ns2_sns_st_all_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1946{
1947 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
Alexander Couzens1f3193d2021-06-05 22:08:11 +02001948 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001949 struct ns2_sns_bind *sbind;
1950 struct gprs_ns2_vc *nsvc, *nsvc2;
Alexander Couzens6a161492020-07-12 13:45:50 +02001951
Alexander Couzense769f522020-12-07 07:37:07 +01001952 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02001953 case NS2_SNS_EV_REQ_ADD_BIND:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001954 sbind = data;
1955 switch (fi->state) {
1956 case GPRS_SNS_ST_UNCONFIGURED:
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001957 if (gss->role == GPRS_SNS_ROLE_BSS)
1958 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_SELECT_ENDPOINT, NULL);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001959 break;
Harald Welte694dad52021-03-23 15:22:16 +01001960 case GPRS_SNS_ST_BSS_SIZE:
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001961 switch (gss->family) {
1962 case AF_INET:
1963 if (gss->num_max_ip4_remote <= gss->local.num_ip4 ||
1964 gss->num_max_ip4_remote * (gss->local.num_ip4 + 1) > gss->num_max_nsvcs) {
1965 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_SELECT_ENDPOINT, GPRS_SNS_FLAG_KEEP_SELECT_ENDPOINT_ORDER);
1966 return;
1967 }
1968 break;
1969 case AF_INET6:
1970 if (gss->num_max_ip6_remote <= gss->local.num_ip6 ||
1971 gss->num_max_ip6_remote * (gss->local.num_ip6 + 1) > gss->num_max_nsvcs) {
1972 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_SELECT_ENDPOINT, GPRS_SNS_FLAG_KEEP_SELECT_ENDPOINT_ORDER);
1973 return;
1974 }
1975 break;
1976 }
1977 ns2_sns_add_elements(gss, sbind, &gss->local);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001978 break;
Harald Welte694dad52021-03-23 15:22:16 +01001979 case GPRS_SNS_ST_BSS_CONFIG_BSS:
1980 case GPRS_SNS_ST_BSS_CONFIG_SGSN:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001981 case GPRS_SNS_ST_CONFIGURED:
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02001982 switch (gss->family) {
1983 case AF_INET:
1984 if (gss->num_max_ip4_remote <= gss->local.num_ip4) {
1985 LOGPFSML(fi, LOGL_ERROR,
1986 "NSE %d: ignoring bind %s because there are too many endpoints for the SNS.\n",
1987 nse->nsei, sbind->bind->name);
1988 return;
1989 }
1990 if (gss->remote.num_ip4 * (gss->local.num_ip4 + 1) > gss->num_max_nsvcs) {
1991 LOGPFSML(fi, LOGL_ERROR,
1992 "NSE %d: ignoring bind %s because there are too many endpoints for the SNS.\n",
1993 nse->nsei, sbind->bind->name);
1994 return;
1995 }
1996 break;
1997 case AF_INET6:
1998 if (gss->num_max_ip6_remote <= gss->local.num_ip6) {
1999 LOGPFSML(fi, LOGL_ERROR,
2000 "NSE %d: ignoring bind %s because there are too many endpoints for the SNS.\n",
2001 nse->nsei, sbind->bind->name);
2002 return;
2003 }
2004 if (gss->remote.num_ip6 * (gss->local.num_ip6 + 1) > gss->num_max_nsvcs) {
2005 LOGPFSML(fi, LOGL_ERROR,
2006 "NSE %d: ignoring bind %s because there are too many endpoints for the SNS.\n",
2007 nse->nsei, sbind->bind->name);
2008 return;
2009 }
2010 break;
2011 }
2012 ns2_sns_add_elements(gss, sbind, &gss->local_procedure);
2013 ns2_add_procedure(gss, sbind, SNS_PROC_ADD);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002014 break;
2015 }
2016 break;
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002017 case NS2_SNS_EV_REQ_DELETE_BIND:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002018 sbind = data;
2019 switch (fi->state) {
2020 case GPRS_SNS_ST_UNCONFIGURED:
2021 break;
Harald Welte694dad52021-03-23 15:22:16 +01002022 case GPRS_SNS_ST_BSS_SIZE:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002023 /* TODO: remove the ip4 element from the list */
2024 llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {
2025 if (nsvc->bind == sbind->bind) {
2026 gprs_ns2_free_nsvc(nsvc);
2027 }
2028 }
2029 break;
Harald Welte694dad52021-03-23 15:22:16 +01002030 case GPRS_SNS_ST_BSS_CONFIG_BSS:
2031 case GPRS_SNS_ST_BSS_CONFIG_SGSN:
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002032 case GPRS_SNS_ST_CONFIGURED:
2033 /* TODO: do an delete SNS-IP procedure */
2034 /* TODO: remove the ip4 element to the list */
2035 llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {
2036 if (nsvc->bind == sbind->bind) {
2037 gprs_ns2_free_nsvc(nsvc);
2038 }
2039 }
2040 break;
2041 }
2042 /* if this is the last bind, the free_nsvc() will trigger a reselection */
2043 talloc_free(sbind);
2044 break;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002045 case NS2_SNS_EV_REQ_CHANGE_WEIGHT:
2046 sbind = data;
2047 switch (fi->state) {
2048 case GPRS_SNS_ST_UNCONFIGURED:
2049 /* select_endpoint will check if this is a valid configuration */
2050 if (gss->role == GPRS_SNS_ROLE_BSS)
2051 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_REQ_SELECT_ENDPOINT, NULL);
2052 break;
2053 case GPRS_SNS_ST_BSS_SIZE:
2054 /* invalid weight? */
2055 if (!ns2_update_weight_entry(gss, sbind, &gss->local))
2056 sns_failed(fi, "updating weights results in an invalid configuration.");
2057 break;
2058 default:
2059 if (!ns2_update_weight_entry(gss, sbind, &gss->local_procedure)) {
2060 sns_failed(fi, "updating weights results in an invalid configuration.");
2061 break;
2062 }
2063 ns2_add_procedure(gss, sbind, SNS_PROC_CHANGE_WEIGHT);
2064 break;
2065 }
Alexander Couzense769f522020-12-07 07:37:07 +01002066 }
Alexander Couzens6a161492020-07-12 13:45:50 +02002067}
2068
Alexander Couzens31d52e12021-06-05 20:04:04 +02002069/* validate the bss configuration (sns endpoint and binds)
2070 * - no endpoints -> invalid
2071 * - no binds -> invalid
2072 * - only v4 sns endpoints, only v6 binds -> invalid
2073 * - only v4 sns endpoints, but v4 sig weights == 0 -> invalid ...
2074 */
2075static int ns2_sns_bss_valid_configuration(struct ns2_sns_state *gss)
2076{
2077 struct ns2_sns_bind *sbind;
2078 struct sns_endpoint *endpoint;
2079 const struct osmo_sockaddr *addr;
2080 int v4_sig = 0, v4_data = 0, v6_sig = 0, v6_data = 0;
2081 bool v4_endpoints = false;
2082 bool v6_endpoints = false;
2083
2084 if (llist_empty(&gss->sns_endpoints) || llist_empty(&gss->binds))
2085 return 0;
2086
2087 llist_for_each_entry(sbind, &gss->binds, list) {
2088 addr = gprs_ns2_ip_bind_sockaddr(sbind->bind);
2089 if (!addr)
2090 continue;
2091 switch (addr->u.sa.sa_family) {
2092 case AF_INET:
2093 v4_sig += sbind->bind->sns_sig_weight;
2094 v4_data += sbind->bind->sns_data_weight;
2095 break;
2096 case AF_INET6:
2097 v6_sig += sbind->bind->sns_sig_weight;
2098 v6_data += sbind->bind->sns_data_weight;
2099 break;
2100 }
2101 }
2102
2103 llist_for_each_entry(endpoint, &gss->sns_endpoints, list) {
2104 switch (endpoint->saddr.u.sa.sa_family) {
2105 case AF_INET:
2106 v4_endpoints = true;
2107 break;
2108 case AF_INET6:
2109 v6_endpoints = true;
2110 break;
2111 }
2112 }
2113
2114 return (v4_endpoints && v4_sig && v4_data) || (v6_endpoints && v6_sig && v6_data);
2115}
2116
Harald Welte9e37bf42021-03-02 20:48:31 +01002117/* allstate-action for BSS role */
2118static void ns2_sns_st_all_action_bss(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2119{
2120 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2121 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2122
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002123 /* reset when receiving NS2_SNS_EV_REQ_NO_NSVC */
Harald Welte9e37bf42021-03-02 20:48:31 +01002124 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002125 case NS2_SNS_EV_REQ_NO_NSVC:
Harald Welte9e37bf42021-03-02 20:48:31 +01002126 /* ignore reselection running */
2127 if (gss->reselection_running)
2128 break;
2129
Alexander Couzens652ab4d2021-06-12 23:09:46 +02002130 sns_failed(fi, "no remaining NSVC, resetting SNS FSM");
Harald Welte9e37bf42021-03-02 20:48:31 +01002131 break;
Alexander Couzens83f06ce2021-08-06 19:50:09 +02002132 case NS2_SNS_EV_REQ_FREE_NSVCS:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002133 case NS2_SNS_EV_REQ_SELECT_ENDPOINT:
Alexander Couzens9cd39ac2021-06-06 18:57:56 +02002134 /* TODO: keep the order of binds when data == GPRS_SNS_FLAG_KEEP_SELECT_ENDPOINT_ORDER */
Harald Welte9e37bf42021-03-02 20:48:31 +01002135 /* tear down previous state
2136 * gprs_ns2_free_nsvcs() will trigger NO_NSVC, prevent this from triggering a reselection */
2137 gss->reselection_running = true;
Alexander Couzensf0746592021-07-20 19:05:45 +02002138 ns2_free_nsvcs(nse);
Alexander Couzensd2c6c492021-06-06 01:57:52 +02002139 ns2_clear_elems(&gss->local);
2140 ns2_clear_elems(&gss->remote);
Harald Welte9e37bf42021-03-02 20:48:31 +01002141
2142 /* Choose the next sns endpoint. */
Alexander Couzens31d52e12021-06-05 20:04:04 +02002143 if (!ns2_sns_bss_valid_configuration(gss)) {
Harald Welte9e37bf42021-03-02 20:48:31 +01002144 gss->initial = NULL;
2145 ns2_prim_status_ind(gss->nse, NULL, 0, GPRS_NS2_AFF_CAUSE_SNS_NO_ENDPOINTS);
2146 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 3);
2147 return;
2148 } else if (!gss->initial) {
2149 gss->initial = llist_first_entry(&gss->sns_endpoints, struct sns_endpoint, list);
2150 } else if (gss->initial->list.next == &gss->sns_endpoints) {
2151 /* last entry, continue with first */
2152 gss->initial = llist_first_entry(&gss->sns_endpoints, struct sns_endpoint, list);
2153 } else {
2154 /* next element is an entry */
2155 gss->initial = llist_entry(gss->initial->list.next, struct sns_endpoint, list);
2156 }
2157
Alexander Couzens68ab9c42021-06-06 03:03:40 +02002158 gss->family = gss->initial->saddr.u.sa.sa_family;
Harald Welte9e37bf42021-03-02 20:48:31 +01002159 gss->reselection_running = false;
Harald Welte694dad52021-03-23 15:22:16 +01002160 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 +01002161 break;
2162 default:
2163 ns2_sns_st_all_action(fi, event, data);
2164 break;
2165 }
2166}
2167
Alexander Couzens6a161492020-07-12 13:45:50 +02002168static struct osmo_fsm gprs_ns2_sns_bss_fsm = {
2169 .name = "GPRS-NS2-SNS-BSS",
2170 .states = ns2_sns_bss_states,
2171 .num_states = ARRAY_SIZE(ns2_sns_bss_states),
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002172 .allstate_event_mask = S(NS2_SNS_EV_REQ_NO_NSVC) |
Alexander Couzens83f06ce2021-08-06 19:50:09 +02002173 S(NS2_SNS_EV_REQ_FREE_NSVCS) |
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002174 S(NS2_SNS_EV_REQ_SELECT_ENDPOINT) |
2175 S(NS2_SNS_EV_REQ_ADD_BIND) |
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002176 S(NS2_SNS_EV_REQ_CHANGE_WEIGHT) |
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002177 S(NS2_SNS_EV_REQ_DELETE_BIND),
Harald Welte9e37bf42021-03-02 20:48:31 +01002178 .allstate_action = ns2_sns_st_all_action_bss,
Alexander Couzens6a161492020-07-12 13:45:50 +02002179 .cleanup = NULL,
2180 .timer_cb = ns2_sns_fsm_bss_timer_cb,
Alexander Couzens6a161492020-07-12 13:45:50 +02002181 .event_names = gprs_sns_event_names,
2182 .pre_term = NULL,
2183 .log_subsys = DLNS,
2184};
2185
Harald Welte5bef2cc2020-09-18 22:33:24 +02002186/*! Allocate an IP-SNS FSM for the BSS side.
2187 * \param[in] nse NS Entity in which the FSM runs
2188 * \param[in] id string identifier
Alexander Couzens23aec352021-02-15 05:05:15 +01002189 * \returns FSM instance on success; NULL on error */
Alexander Couzens6a161492020-07-12 13:45:50 +02002190struct osmo_fsm_inst *ns2_sns_bss_fsm_alloc(struct gprs_ns2_nse *nse,
2191 const char *id)
2192{
2193 struct osmo_fsm_inst *fi;
2194 struct ns2_sns_state *gss;
2195
2196 fi = osmo_fsm_inst_alloc(&gprs_ns2_sns_bss_fsm, nse, NULL, LOGL_DEBUG, id);
2197 if (!fi)
2198 return fi;
2199
2200 gss = talloc_zero(fi, struct ns2_sns_state);
2201 if (!gss)
2202 goto err;
2203
2204 fi->priv = gss;
2205 gss->nse = nse;
Harald Welte4f127462021-03-02 20:49:10 +01002206 gss->role = GPRS_SNS_ROLE_BSS;
Harald Welte24f4df52021-03-04 18:02:54 +01002207 /* The SGSN doesn't tell the BSS, so we assume there's always sufficient */
2208 gss->num_max_ip4_remote = 8192;
2209 gss->num_max_ip6_remote = 8192;
Alexander Couzense769f522020-12-07 07:37:07 +01002210 INIT_LLIST_HEAD(&gss->sns_endpoints);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002211 INIT_LLIST_HEAD(&gss->binds);
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002212 INIT_LLIST_HEAD(&gss->procedures);
Alexander Couzens6a161492020-07-12 13:45:50 +02002213
2214 return fi;
2215err:
2216 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
2217 return NULL;
2218}
2219
Harald Welte5bef2cc2020-09-18 22:33:24 +02002220/*! main entry point for receiving SNS messages from the network.
2221 * \param[in] nsvc NS-VC on which the message was received
2222 * \param[in] msg message buffer of the IP-SNS message
2223 * \param[in] tp parsed TLV structure of message
Alexander Couzens23aec352021-02-15 05:05:15 +01002224 * \returns 0 on success; negative on error */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01002225int ns2_sns_rx(struct gprs_ns2_vc *nsvc, struct msgb *msg, struct tlv_parsed *tp)
Alexander Couzens6a161492020-07-12 13:45:50 +02002226{
2227 struct gprs_ns2_nse *nse = nsvc->nse;
2228 struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h;
2229 uint16_t nsei = nsvc->nse->nsei;
Harald Welte4f127462021-03-02 20:49:10 +01002230 struct ns2_sns_state *gss;
Alexander Couzens6a161492020-07-12 13:45:50 +02002231 struct osmo_fsm_inst *fi;
Alexander Couzens7619ed42021-03-24 17:44:03 +01002232 int rc = 0;
Alexander Couzens6a161492020-07-12 13:45:50 +02002233
2234 if (!nse->bss_sns_fi) {
Harald Weltef2949742021-01-20 14:54:14 +01002235 LOGNSVC(nsvc, LOGL_NOTICE, "Rx %s for NS Instance that has no SNS!\n",
2236 get_value_string(gprs_ns_pdu_strings, nsh->pdu_type));
Alexander Couzens7619ed42021-03-24 17:44:03 +01002237 rc = -EINVAL;
2238 goto out;
Alexander Couzens6a161492020-07-12 13:45:50 +02002239 }
2240
Alexander Couzens6a161492020-07-12 13:45:50 +02002241 /* FIXME: how to resolve SNS FSM Instance by NSEI (SGSN)? */
2242 fi = nse->bss_sns_fi;
Harald Welte4f127462021-03-02 20:49:10 +01002243 gss = (struct ns2_sns_state *) fi->priv;
2244 if (!gss->sns_nsvc)
2245 gss->sns_nsvc = nsvc;
Alexander Couzens6a161492020-07-12 13:45:50 +02002246
Harald Weltef2949742021-01-20 14:54:14 +01002247 LOGPFSML(fi, LOGL_DEBUG, "NSEI=%u Rx SNS PDU type %s\n", nsei,
2248 get_value_string(gprs_ns_pdu_strings, nsh->pdu_type));
2249
Alexander Couzens6a161492020-07-12 13:45:50 +02002250 switch (nsh->pdu_type) {
2251 case SNS_PDUT_SIZE:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002252 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_SIZE, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002253 break;
2254 case SNS_PDUT_SIZE_ACK:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002255 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_SIZE_ACK, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002256 break;
2257 case SNS_PDUT_CONFIG:
2258 if (nsh->data[0] & 0x01)
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002259 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_CONFIG_END, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002260 else
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002261 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_CONFIG, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002262 break;
2263 case SNS_PDUT_CONFIG_ACK:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002264 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_CONFIG_ACK, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002265 break;
2266 case SNS_PDUT_ADD:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002267 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_ADD, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002268 break;
2269 case SNS_PDUT_DELETE:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002270 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_DELETE, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002271 break;
2272 case SNS_PDUT_CHANGE_WEIGHT:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002273 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_CHANGE_WEIGHT, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002274 break;
2275 case SNS_PDUT_ACK:
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002276 osmo_fsm_inst_dispatch(fi, NS2_SNS_EV_RX_ACK, tp);
Alexander Couzens6a161492020-07-12 13:45:50 +02002277 break;
2278 default:
Harald Weltef2949742021-01-20 14:54:14 +01002279 LOGPFSML(fi, LOGL_ERROR, "NSEI=%u Rx unknown SNS PDU type %s\n", nsei,
2280 get_value_string(gprs_ns_pdu_strings, nsh->pdu_type));
Alexander Couzens7619ed42021-03-24 17:44:03 +01002281 rc = -EINVAL;
Alexander Couzens6a161492020-07-12 13:45:50 +02002282 }
2283
Alexander Couzens7619ed42021-03-24 17:44:03 +01002284out:
2285 msgb_free(msg);
2286
2287 return rc;
Alexander Couzens6a161492020-07-12 13:45:50 +02002288}
2289
2290#include <osmocom/vty/vty.h>
2291#include <osmocom/vty/misc.h>
2292
Harald Welte1262c4f2021-01-19 20:58:33 +01002293static 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 +02002294{
2295 struct in_addr in = { .s_addr = ip4->ip_addr };
Harald Welte1262c4f2021-01-19 20:58:33 +01002296 vty_out(vty, "%s %s:%u, Signalling Weight: %u, Data Weight: %u%s", prefix,
Alexander Couzens6a161492020-07-12 13:45:50 +02002297 inet_ntoa(in), ntohs(ip4->udp_port), ip4->sig_weight, ip4->data_weight, VTY_NEWLINE);
2298}
2299
Harald Welte1262c4f2021-01-19 20:58:33 +01002300static 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 +02002301{
2302 char ip_addr[INET6_ADDRSTRLEN] = {};
2303 if (!inet_ntop(AF_INET6, &ip6->ip_addr, ip_addr, (INET6_ADDRSTRLEN)))
2304 strcpy(ip_addr, "Invalid IPv6");
2305
Harald Welte1262c4f2021-01-19 20:58:33 +01002306 vty_out(vty, "%s %s:%u, Signalling Weight: %u, Data Weight: %u%s", prefix,
Alexander Couzens6a161492020-07-12 13:45:50 +02002307 ip_addr, ntohs(ip6->udp_port), ip6->sig_weight, ip6->data_weight, VTY_NEWLINE);
2308}
2309
Harald Welte5bef2cc2020-09-18 22:33:24 +02002310/*! Dump the IP-SNS state to a vty.
2311 * \param[in] vty VTY to which the state shall be printed
Harald Welte1262c4f2021-01-19 20:58:33 +01002312 * \param[in] prefix prefix to print at start of each line (typically indenting)
Harald Welte5bef2cc2020-09-18 22:33:24 +02002313 * \param[in] nse NS Entity whose IP-SNS state shall be printed
2314 * \param[in] stats Whether or not statistics shall also be printed */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01002315void 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 +02002316{
2317 struct ns2_sns_state *gss;
2318 unsigned int i;
2319
2320 if (!nse->bss_sns_fi)
2321 return;
2322
Harald Welte1262c4f2021-01-19 20:58:33 +01002323 vty_out_fsm_inst2(vty, prefix, nse->bss_sns_fi);
Alexander Couzens6a161492020-07-12 13:45:50 +02002324 gss = (struct ns2_sns_state *) nse->bss_sns_fi->priv;
2325
Harald Welte1262c4f2021-01-19 20:58:33 +01002326 vty_out(vty, "%sMaximum number of remote NS-VCs: %zu, IPv4 Endpoints: %zu, IPv6 Endpoints: %zu%s",
2327 prefix, gss->num_max_nsvcs, gss->num_max_ip4_remote, gss->num_max_ip6_remote, VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +02002328
Alexander Couzens71128672021-06-05 18:44:01 +02002329 if (gss->local.num_ip4 && gss->remote.num_ip4) {
Harald Welte1262c4f2021-01-19 20:58:33 +01002330 vty_out(vty, "%sLocal IPv4 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02002331 for (i = 0; i < gss->local.num_ip4; i++)
2332 vty_dump_sns_ip4(vty, prefix, &gss->local.ip4[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02002333
Harald Welte1262c4f2021-01-19 20:58:33 +01002334 vty_out(vty, "%sRemote IPv4 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02002335 for (i = 0; i < gss->remote.num_ip4; i++)
2336 vty_dump_sns_ip4(vty, prefix, &gss->remote.ip4[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02002337 }
2338
Alexander Couzens71128672021-06-05 18:44:01 +02002339 if (gss->local.num_ip6 && gss->remote.num_ip6) {
Harald Welte1262c4f2021-01-19 20:58:33 +01002340 vty_out(vty, "%sLocal IPv6 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02002341 for (i = 0; i < gss->local.num_ip6; i++)
2342 vty_dump_sns_ip6(vty, prefix, &gss->local.ip6[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02002343
Harald Welte1262c4f2021-01-19 20:58:33 +01002344 vty_out(vty, "%sRemote IPv6 Endpoints:%s", prefix, VTY_NEWLINE);
Alexander Couzens71128672021-06-05 18:44:01 +02002345 for (i = 0; i < gss->remote.num_ip6; i++)
2346 vty_dump_sns_ip6(vty, prefix, &gss->remote.ip6[i]);
Alexander Couzens6a161492020-07-12 13:45:50 +02002347 }
2348}
2349
Alexander Couzens412bc342020-11-19 05:24:37 +01002350/*! write IP-SNS to a vty
2351 * \param[in] vty VTY to which the state shall be printed
2352 * \param[in] nse NS Entity whose IP-SNS state shall be printed */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01002353void ns2_sns_write_vty(struct vty *vty, const struct gprs_ns2_nse *nse)
Alexander Couzens412bc342020-11-19 05:24:37 +01002354{
2355 struct ns2_sns_state *gss;
2356 struct osmo_sockaddr_str addr_str;
2357 struct sns_endpoint *endpoint;
2358
2359 if (!nse->bss_sns_fi)
2360 return;
2361
2362 gss = (struct ns2_sns_state *) nse->bss_sns_fi->priv;
2363 llist_for_each_entry(endpoint, &gss->sns_endpoints, list) {
Vadim Yanitskiyd8b70032021-01-05 14:24:09 +01002364 /* It's unlikely that an error happens, but let's better be safe. */
2365 if (osmo_sockaddr_str_from_sockaddr(&addr_str, &endpoint->saddr.u.sas) != 0)
2366 addr_str = (struct osmo_sockaddr_str) { .ip = "<INVALID>" };
Alexander Couzens5fa431c2021-02-08 23:21:54 +01002367 vty_out(vty, " ip-sns-remote %s %u%s", addr_str.ip, addr_str.port, VTY_NEWLINE);
Alexander Couzens412bc342020-11-19 05:24:37 +01002368 }
2369}
2370
Alexander Couzense769f522020-12-07 07:37:07 +01002371static struct sns_endpoint *ns2_get_sns_endpoint(struct ns2_sns_state *state,
2372 const struct osmo_sockaddr *saddr)
2373{
2374 struct sns_endpoint *endpoint;
2375
2376 llist_for_each_entry(endpoint, &state->sns_endpoints, list) {
2377 if (!osmo_sockaddr_cmp(saddr, &endpoint->saddr))
2378 return endpoint;
2379 }
2380
2381 return NULL;
2382}
2383
2384/*! gprs_ns2_sns_add_endpoint
2385 * \param[in] nse
2386 * \param[in] sockaddr
2387 * \return
2388 */
2389int gprs_ns2_sns_add_endpoint(struct gprs_ns2_nse *nse,
2390 const struct osmo_sockaddr *saddr)
2391{
2392 struct ns2_sns_state *gss;
2393 struct sns_endpoint *endpoint;
2394 bool do_selection = false;
2395
2396 if (nse->ll != GPRS_NS2_LL_UDP) {
2397 return -EINVAL;
2398 }
2399
Alexander Couzens138b96f2021-01-25 16:23:29 +01002400 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
Alexander Couzense769f522020-12-07 07:37:07 +01002401 return -EINVAL;
2402 }
2403
2404 gss = nse->bss_sns_fi->priv;
2405
2406 if (ns2_get_sns_endpoint(gss, saddr))
2407 return -EADDRINUSE;
2408
2409 endpoint = talloc_zero(nse->bss_sns_fi->priv, struct sns_endpoint);
2410 if (!endpoint)
2411 return -ENOMEM;
2412
2413 endpoint->saddr = *saddr;
2414 if (llist_empty(&gss->sns_endpoints))
2415 do_selection = true;
2416
2417 llist_add_tail(&endpoint->list, &gss->sns_endpoints);
2418 if (do_selection)
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002419 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_SELECT_ENDPOINT, NULL);
Alexander Couzense769f522020-12-07 07:37:07 +01002420
2421 return 0;
2422}
2423
2424/*! gprs_ns2_sns_del_endpoint
2425 * \param[in] nse
2426 * \param[in] sockaddr
2427 * \return 0 on success, otherwise < 0
2428 */
2429int gprs_ns2_sns_del_endpoint(struct gprs_ns2_nse *nse,
2430 const struct osmo_sockaddr *saddr)
2431{
2432 struct ns2_sns_state *gss;
2433 struct sns_endpoint *endpoint;
2434
2435 if (nse->ll != GPRS_NS2_LL_UDP) {
2436 return -EINVAL;
2437 }
2438
Alexander Couzens138b96f2021-01-25 16:23:29 +01002439 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
Alexander Couzense769f522020-12-07 07:37:07 +01002440 return -EINVAL;
2441 }
2442
2443 gss = nse->bss_sns_fi->priv;
2444 endpoint = ns2_get_sns_endpoint(gss, saddr);
2445 if (!endpoint)
2446 return -ENOENT;
2447
2448 /* if this is an unused SNS endpoint it's done */
2449 if (gss->initial != endpoint) {
2450 llist_del(&endpoint->list);
2451 talloc_free(endpoint);
2452 return 0;
2453 }
2454
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002455 /* gprs_ns2_free_nsvcs() will trigger NS2_SNS_EV_REQ_NO_NSVC on the last NS-VC
Alexander Couzense769f522020-12-07 07:37:07 +01002456 * and restart SNS SIZE procedure which selects a new initial */
Harald Weltef2949742021-01-20 14:54:14 +01002457 LOGNSE(nse, LOGL_INFO, "Current in-use SNS endpoint is being removed."
Alexander Couzense769f522020-12-07 07:37:07 +01002458 "Closing all NS-VC and restart SNS-SIZE procedure"
2459 "with a remaining SNS endpoint.\n");
2460
2461 /* Continue with the next endpoint in the list.
2462 * Special case if the endpoint is at the start or end of the list */
2463 if (endpoint->list.prev == &gss->sns_endpoints ||
2464 endpoint->list.next == &gss->sns_endpoints)
2465 gss->initial = NULL;
2466 else
2467 gss->initial = llist_entry(endpoint->list.next->prev,
2468 struct sns_endpoint,
2469 list);
2470
2471 llist_del(&endpoint->list);
2472 gprs_ns2_free_nsvcs(nse);
2473 talloc_free(endpoint);
2474
2475 return 0;
2476}
2477
2478/*! gprs_ns2_sns_count
2479 * \param[in] nse NS Entity whose IP-SNS endpoints shall be printed
2480 * \return the count of endpoints or < 0 if NSE doesn't contain sns.
2481 */
2482int gprs_ns2_sns_count(struct gprs_ns2_nse *nse)
2483{
2484 struct ns2_sns_state *gss;
2485 struct sns_endpoint *endpoint;
2486 int count = 0;
2487
2488 if (nse->ll != GPRS_NS2_LL_UDP) {
2489 return -EINVAL;
2490 }
2491
Alexander Couzens138b96f2021-01-25 16:23:29 +01002492 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
Alexander Couzense769f522020-12-07 07:37:07 +01002493 return -EINVAL;
2494 }
2495
2496 gss = nse->bss_sns_fi->priv;
2497 llist_for_each_entry(endpoint, &gss->sns_endpoints, list)
2498 count++;
2499
2500 return count;
2501}
2502
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01002503void ns2_sns_notify_alive(struct gprs_ns2_nse *nse, struct gprs_ns2_vc *nsvc, bool alive)
2504{
2505 struct ns2_sns_state *gss;
2506 struct gprs_ns2_vc *tmp;
2507
2508 if (!nse->bss_sns_fi)
2509 return;
2510
2511 gss = nse->bss_sns_fi->priv;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002512 if (nse->bss_sns_fi->state != GPRS_SNS_ST_CONFIGURED && nse->bss_sns_fi->state != GPRS_SNS_ST_LOCAL_PROCEDURE)
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01002513 return;
2514
2515 if (alive == gss->alive)
2516 return;
2517
2518 /* check if this is the current SNS NS-VC */
2519 if (nsvc == gss->sns_nsvc) {
2520 /* only replace the SNS NS-VC if there are other alive NS-VC.
2521 * There aren't any other alive NS-VC when the SNS fsm just reached CONFIGURED
2522 * and couldn't confirm yet if the NS-VC comes up */
2523 if (gss->alive && !alive)
2524 ns2_sns_replace_nsvc(nsvc);
2525 }
2526
2527 if (alive) {
2528 gss->alive = true;
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002529 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_NSVC_ALIVE, NULL);
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01002530 } else {
2531 /* is there at least another alive nsvc? */
2532 llist_for_each_entry(tmp, &nse->nsvc, list) {
2533 if (ns2_vc_is_unblocked(tmp))
2534 return;
2535 }
2536
2537 /* all NS-VC have failed */
2538 gss->alive = false;
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002539 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_NO_NSVC, NULL);
Alexander Couzensbe7cecc2021-02-03 18:25:27 +01002540 }
2541}
2542
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002543int gprs_ns2_sns_add_bind(struct gprs_ns2_nse *nse,
2544 struct gprs_ns2_vc_bind *bind)
2545{
2546 struct ns2_sns_state *gss;
2547 struct ns2_sns_bind *tmp;
2548
2549 OSMO_ASSERT(nse->bss_sns_fi);
2550 gss = nse->bss_sns_fi->priv;
2551
2552 if (!gprs_ns2_is_ip_bind(bind)) {
2553 return -EINVAL;
2554 }
2555
2556 if (!llist_empty(&gss->binds)) {
2557 llist_for_each_entry(tmp, &gss->binds, list) {
2558 if (tmp->bind == bind)
2559 return -EALREADY;
2560 }
2561 }
2562
2563 tmp = talloc_zero(gss, struct ns2_sns_bind);
2564 if (!tmp)
2565 return -ENOMEM;
2566 tmp->bind = bind;
2567 llist_add_tail(&tmp->list, &gss->binds);
2568
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002569 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_ADD_BIND, tmp);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002570 return 0;
2571}
2572
2573/* Remove a bind from the SNS. All assosiated NSVC must be removed. */
2574int gprs_ns2_sns_del_bind(struct gprs_ns2_nse *nse,
2575 struct gprs_ns2_vc_bind *bind)
2576{
2577 struct ns2_sns_state *gss;
2578 struct ns2_sns_bind *tmp, *tmp2;
2579 bool found = false;
2580
2581 if (!nse->bss_sns_fi)
2582 return -EINVAL;
2583
2584 gss = nse->bss_sns_fi->priv;
2585 if (gss->initial_bind && gss->initial_bind->bind == bind) {
2586 if (gss->initial_bind->list.prev == &gss->binds)
2587 gss->initial_bind = NULL;
2588 else
2589 gss->initial_bind = llist_entry(gss->initial_bind->list.prev, struct ns2_sns_bind, list);
2590 }
2591
2592 llist_for_each_entry_safe(tmp, tmp2, &gss->binds, list) {
2593 if (tmp->bind == bind) {
2594 llist_del(&tmp->list);
2595 found = true;
Alexander Couzensa35c2962021-04-19 03:30:15 +02002596 break;
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002597 }
2598 }
2599
2600 if (!found)
2601 return -ENOENT;
2602
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002603 osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_DELETE_BIND, tmp);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002604 return 0;
2605}
2606
Alexander Couzens71128672021-06-05 18:44:01 +02002607/* Update SNS weights for a bind (local endpoint).
2608 * \param[in] bind the bind which has been updated
Alexander Couzensc4704762021-02-08 23:13:12 +01002609 */
2610void ns2_sns_update_weights(struct gprs_ns2_vc_bind *bind)
2611{
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002612 struct ns2_sns_bind *sbind;
2613 struct gprs_ns2_nse *nse;
2614 struct ns2_sns_state *gss;
2615 const struct osmo_sockaddr *addr = gprs_ns2_ip_bind_sockaddr(bind);
2616
2617 llist_for_each_entry(nse, &bind->nsi->nse, list) {
2618 if (!nse->bss_sns_fi)
2619 continue;
2620
2621 gss = nse->bss_sns_fi->priv;
2622 if (addr->u.sa.sa_family != gss->family)
2623 return;
2624
2625 llist_for_each_entry(sbind, &gss->binds, list) {
2626 if (sbind->bind == bind) {
2627 osmo_fsm_inst_dispatch(gss->nse->bss_sns_fi, NS2_SNS_EV_REQ_CHANGE_WEIGHT, sbind);
2628 break;
2629 }
2630 }
2631 }
Alexander Couzensc4704762021-02-08 23:13:12 +01002632}
2633
Harald Welte4f127462021-03-02 20:49:10 +01002634
2635
2636
2637/***********************************************************************
2638 * SGSN role
2639 ***********************************************************************/
2640
Alexander Couzensa2707822021-07-20 18:59:40 +02002641/* cleanup all state. If nsvc is given, don't remove this nsvc. (nsvc is given when a SIZE PDU received) */
2642static void ns2_clear_sgsn(struct ns2_sns_state *gss, struct gprs_ns2_vc *size_nsvc)
2643{
2644 struct gprs_ns2_vc *nsvc, *nsvc2;
2645
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002646 ns2_clear_procedures(gss);
Alexander Couzensa2707822021-07-20 18:59:40 +02002647 ns2_clear_elems(&gss->local);
2648 ns2_clear_elems(&gss->remote);
2649 llist_for_each_entry_safe(nsvc, nsvc2, &gss->nse->nsvc, list) {
2650 /* Ignore the NSVC over which the SIZE PDU got received */
2651 if (size_nsvc && size_nsvc == nsvc)
2652 continue;
2653
2654 gprs_ns2_free_nsvc(nsvc);
2655 }
2656}
2657
2658static void ns2_sns_st_sgsn_unconfigured_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
2659{
2660 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2661
2662 ns2_clear_sgsn(gss, NULL);
2663}
2664
Harald Welte4f127462021-03-02 20:49:10 +01002665static void ns2_sns_st_sgsn_unconfigured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2666{
2667 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2668 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2669 /* do nothing; Rx SNS-SIZE handled in ns2_sns_st_all_action_sgsn() */
2670}
2671
2672/* We're waiting for inbound SNS-CONFIG from the BSS */
2673static void ns2_sns_st_sgsn_wait_config(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2674{
2675 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2676 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2677 struct gprs_ns2_inst *nsi = nse->nsi;
2678 uint8_t cause;
2679 int rc;
2680
2681 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2682
2683 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002684 case NS2_SNS_EV_RX_CONFIG:
2685 case NS2_SNS_EV_RX_CONFIG_END:
Harald Welte4f127462021-03-02 20:49:10 +01002686 rc = ns_sns_append_remote_eps(fi, data);
2687 if (rc < 0) {
2688 cause = -rc;
2689 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
2690 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
2691 return;
2692 }
2693 /* only change state if last CONFIG was received */
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002694 if (event == NS2_SNS_EV_RX_CONFIG_END) {
Harald Welte4f127462021-03-02 20:49:10 +01002695 /* ensure sum of data weight / sig weights is > 0 */
Alexander Couzens019da4b2021-06-06 02:48:18 +02002696 if (ip46_weight_sum_data(&gss->remote) == 0 || ip46_weight_sum_sig(&gss->remote) == 0) {
Harald Welte4f127462021-03-02 20:49:10 +01002697 cause = NS_CAUSE_INVAL_WEIGH;
2698 ns2_tx_sns_config_ack(gss->sns_nsvc, &cause);
2699 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
2700 break;
2701 }
2702 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
2703 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
2704 } else {
2705 /* just send CONFIG-ACK */
2706 ns2_tx_sns_config_ack(gss->sns_nsvc, NULL);
2707 osmo_timer_schedule(&fi->timer, nse->nsi->timeout[NS_TOUT_TSNS_PROV], 0);
2708 }
2709 break;
2710 }
2711}
2712
2713static void ns2_sns_st_sgsn_wait_config_ack_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
2714{
2715 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2716 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2717
Harald Welte4f127462021-03-02 20:49:10 +01002718 /* transmit SGSN-oriented SNS-CONFIG */
Alexander Couzens71128672021-06-05 18:44:01 +02002719 ns2_tx_sns_config(gss->sns_nsvc, true, gss->local.ip4, gss->local.num_ip4,
2720 gss->local.ip6, gss->local.num_ip6);
Harald Welte4f127462021-03-02 20:49:10 +01002721}
2722
2723/* We're waiting for SNS-CONFIG-ACK from the BSS (in response to our outbound SNS-CONFIG) */
2724static void ns2_sns_st_sgsn_wait_config_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2725{
2726 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2727 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2728 struct tlv_parsed *tp = NULL;
2729
2730 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2731
2732 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002733 case NS2_SNS_EV_RX_CONFIG_ACK:
Harald Welte4f127462021-03-02 20:49:10 +01002734 tp = data;
2735 if (TLVP_VAL_MINLEN(tp, NS_IE_CAUSE, 1)) {
2736 LOGPFSML(fi, LOGL_ERROR, "Rx SNS-CONFIG-ACK with cause %s\n",
2737 gprs_ns2_cause_str(*TLVP_VAL(tp, NS_IE_CAUSE)));
2738 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, 0, 0);
2739 break;
2740 }
2741 /* we currently only send one SNS-CONFIG with END FLAG */
2742 if (true) {
2743 create_missing_nsvcs(fi);
2744 /* start the test procedure on ALL NSVCs! */
2745 gprs_ns2_start_alive_all_nsvcs(nse);
2746 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, ns_sns_configured_timeout(fi), 4);
2747 }
2748 break;
2749 }
2750}
2751
2752/* SGSN-side SNS state machine */
2753static const struct osmo_fsm_state ns2_sns_sgsn_states[] = {
2754 [GPRS_SNS_ST_UNCONFIGURED] = {
2755 .in_event_mask = 0, /* handled by all_state_action */
2756 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
2757 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG),
2758 .name = "UNCONFIGURED",
2759 .action = ns2_sns_st_sgsn_unconfigured,
Alexander Couzensa2707822021-07-20 18:59:40 +02002760 .onenter = ns2_sns_st_sgsn_unconfigured_onenter,
Harald Welte4f127462021-03-02 20:49:10 +01002761 },
2762 [GPRS_SNS_ST_SGSN_WAIT_CONFIG] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002763 .in_event_mask = S(NS2_SNS_EV_RX_CONFIG) |
2764 S(NS2_SNS_EV_RX_CONFIG_END),
Harald Welte4f127462021-03-02 20:49:10 +01002765 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
2766 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG) |
2767 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK),
2768 .name = "SGSN_WAIT_CONFIG",
2769 .action = ns2_sns_st_sgsn_wait_config,
2770 },
2771 [GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002772 .in_event_mask = S(NS2_SNS_EV_RX_CONFIG_ACK),
Harald Welte4f127462021-03-02 20:49:10 +01002773 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Alexander Couzensa2707822021-07-20 18:59:40 +02002774 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG) |
Harald Welte4f127462021-03-02 20:49:10 +01002775 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK) |
2776 S(GPRS_SNS_ST_CONFIGURED),
2777 .name = "SGSN_WAIT_CONFIG_ACK",
2778 .action = ns2_sns_st_sgsn_wait_config_ack,
2779 .onenter = ns2_sns_st_sgsn_wait_config_ack_onenter,
2780 },
2781 [GPRS_SNS_ST_CONFIGURED] = {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002782 .in_event_mask = S(NS2_SNS_EV_RX_ADD) |
2783 S(NS2_SNS_EV_RX_DELETE) |
2784 S(NS2_SNS_EV_RX_CHANGE_WEIGHT) |
2785 S(NS2_SNS_EV_REQ_NSVC_ALIVE),
Alexander Couzensa2707822021-07-20 18:59:40 +02002786 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002787 S(GPRS_SNS_ST_SGSN_WAIT_CONFIG) |
2788 S(GPRS_SNS_ST_LOCAL_PROCEDURE),
Harald Welte4f127462021-03-02 20:49:10 +01002789 .name = "CONFIGURED",
2790 /* shared with BSS side; once configured there's no difference */
2791 .action = ns2_sns_st_configured,
2792 .onenter = ns2_sns_st_configured_onenter,
2793 },
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002794 [GPRS_SNS_ST_LOCAL_PROCEDURE] = {
2795 .in_event_mask = S(NS2_SNS_EV_RX_ADD) |
2796 S(NS2_SNS_EV_RX_DELETE) |
2797 S(NS2_SNS_EV_RX_CHANGE_WEIGHT) |
2798 S(NS2_SNS_EV_RX_ACK) |
2799 S(NS2_SNS_EV_REQ_CHANGE_WEIGHT) |
2800 S(NS2_SNS_EV_REQ_NSVC_ALIVE),
2801 .out_state_mask = S(GPRS_SNS_ST_UNCONFIGURED) |
2802 S(GPRS_SNS_ST_CONFIGURED) |
2803 S(GPRS_SNS_ST_LOCAL_PROCEDURE),
2804 .name = "LOCAL_PROCEDURE",
2805 /* shared with BSS side; once configured there's no difference */
2806 .action = ns2_sns_st_local_procedure,
2807 .onenter = ns2_sns_st_local_procedure_onenter,
2808 },
Harald Welte4f127462021-03-02 20:49:10 +01002809};
2810
2811static int ns2_sns_fsm_sgsn_timer_cb(struct osmo_fsm_inst *fi)
2812{
2813 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2814 struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
2815 struct gprs_ns2_inst *nsi = nse->nsi;
2816
2817 gss->N++;
2818 switch (fi->T) {
2819 case 3:
2820 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_CONFIG_RETRIES]) {
2821 LOGPFSML(fi, LOGL_ERROR, "NSE %d: SGSN Config retries failed. Giving up.\n", nse->nsei);
2822 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_UNCONFIGURED, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
2823 } else {
2824 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG_ACK, nsi->timeout[NS_TOUT_TSNS_PROV], 3);
2825 }
2826 break;
2827 case 4:
2828 LOGPFSML(fi, LOGL_ERROR, "NSE %d: Config succeeded but no NS-VC came online.\n", nse->nsei);
2829 break;
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002830 case 5:
2831 if (gss->N >= nsi->timeout[NS_TOUT_TSNS_PROCEDURES_RETRIES]) {
2832 sns_failed(fi, "SNS Procedure retries failed.");
2833 } else {
2834 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_LOCAL_PROCEDURE, nsi->timeout[NS_TOUT_TSNS_PROV],
2835 fi->T);
2836 }
2837 break;
Harald Welte4f127462021-03-02 20:49:10 +01002838 }
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002839
Harald Welte4f127462021-03-02 20:49:10 +01002840 return 0;
2841}
2842
Harald Welte4f127462021-03-02 20:49:10 +01002843/* allstate-action for SGSN role */
2844static void ns2_sns_st_all_action_sgsn(struct osmo_fsm_inst *fi, uint32_t event, void *data)
2845{
2846 struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
2847 struct tlv_parsed *tp = NULL;
Harald Welte01fa6a32021-03-04 19:49:38 +01002848 size_t num_local_eps, num_remote_eps;
Harald Welte4f127462021-03-02 20:49:10 +01002849 uint8_t flag;
Harald Weltea2c5af52021-03-04 17:59:35 +01002850 uint8_t cause;
Harald Welte4f127462021-03-02 20:49:10 +01002851
2852 OSMO_ASSERT(gss->role == GPRS_SNS_ROLE_SGSN);
2853
2854 switch (event) {
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002855 case NS2_SNS_EV_RX_SIZE:
Harald Welte4f127462021-03-02 20:49:10 +01002856 tp = (struct tlv_parsed *) data;
Harald Weltea2c5af52021-03-04 17:59:35 +01002857 /* check for mandatory / conditional IEs */
2858 if (!TLVP_PRES_LEN(tp, NS_IE_RESET_FLAG, 1) ||
2859 !TLVP_PRES_LEN(tp, NS_IE_MAX_NR_NSVC, 2)) {
2860 cause = NS_CAUSE_MISSING_ESSENT_IE;
2861 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002862 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2863 sns_failed(fi, "Rx Size: Missing essential IE");
Harald Weltea2c5af52021-03-04 17:59:35 +01002864 break;
2865 }
2866 if (!TLVP_PRES_LEN(tp, NS_IE_IPv4_EP_NR, 2) &&
2867 !TLVP_PRES_LEN(tp, NS_IE_IPv6_EP_NR, 2)) {
2868 cause = NS_CAUSE_MISSING_ESSENT_IE;
Harald Welte4f127462021-03-02 20:49:10 +01002869 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002870 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2871 sns_failed(fi, "Rx Size: Missing essential IE");
Harald Welte4f127462021-03-02 20:49:10 +01002872 break;
2873 }
Harald Welte01fa6a32021-03-04 19:49:38 +01002874 if (TLVP_PRES_LEN(tp, NS_IE_IPv4_EP_NR, 2))
2875 gss->num_max_ip4_remote = tlvp_val16be(tp, NS_IE_IPv4_EP_NR);
2876 if (TLVP_PRES_LEN(tp, NS_IE_IPv6_EP_NR, 2))
2877 gss->num_max_ip6_remote = tlvp_val16be(tp, NS_IE_IPv6_EP_NR);
2878 /* decide if we go for IPv4 or IPv6 */
Alexander Couzens077ce5a2021-06-06 01:32:45 +02002879 if (gss->num_max_ip6_remote && ns2_sns_count_num_local_ep(fi, AF_INET6)) {
2880 gss->family = AF_INET6;
Harald Welte2d807b62021-03-24 01:57:30 +01002881 ns2_sns_compute_local_ep_from_binds(fi);
Alexander Couzens71128672021-06-05 18:44:01 +02002882 num_local_eps = gss->local.num_ip6;
Harald Welte01fa6a32021-03-04 19:49:38 +01002883 num_remote_eps = gss->num_max_ip6_remote;
Alexander Couzens077ce5a2021-06-06 01:32:45 +02002884 } else if (gss->num_max_ip4_remote && ns2_sns_count_num_local_ep(fi, AF_INET)) {
2885 gss->family = AF_INET;
Harald Welte2d807b62021-03-24 01:57:30 +01002886 ns2_sns_compute_local_ep_from_binds(fi);
Alexander Couzens71128672021-06-05 18:44:01 +02002887 num_local_eps = gss->local.num_ip4;
Harald Welte01fa6a32021-03-04 19:49:38 +01002888 num_remote_eps = gss->num_max_ip4_remote;
2889 } else {
Alexander Couzens71128672021-06-05 18:44:01 +02002890 if (gss->local.num_ip4 && !gss->num_max_ip4_remote)
Harald Welte01fa6a32021-03-04 19:49:38 +01002891 cause = NS_CAUSE_INVAL_NR_IPv4_EP;
2892 else
2893 cause = NS_CAUSE_INVAL_NR_IPv6_EP;
2894 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002895 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2896 sns_failed(fi, "Rx Size: Invalid Nr of IPv4/IPv6 EPs");
Harald Welte01fa6a32021-03-04 19:49:38 +01002897 break;
2898 }
Harald Welte01fa6a32021-03-04 19:49:38 +01002899 /* ensure number of NS-VCs is sufficient for full mesh */
2900 gss->num_max_nsvcs = tlvp_val16be(tp, NS_IE_MAX_NR_NSVC);
2901 if (gss->num_max_nsvcs < num_remote_eps * num_local_eps) {
2902 LOGPFSML(fi, LOGL_ERROR, "%zu local and %zu remote EPs, requires %zu NS-VC, "
2903 "but BSS supports only %zu maximum NS-VCs\n", num_local_eps,
2904 num_remote_eps, num_local_eps * num_remote_eps, gss->num_max_nsvcs);
2905 cause = NS_CAUSE_INVAL_NR_NS_VC;
2906 ns2_tx_sns_size_ack(gss->sns_nsvc, &cause);
Alexander Couzens1c405252021-06-13 00:14:48 +02002907 if (fi->state == GPRS_SNS_ST_UNCONFIGURED)
2908 sns_failed(fi, NULL);
Harald Welte01fa6a32021-03-04 19:49:38 +01002909 break;
2910 }
2911 /* perform state reset, if requested */
Harald Welte4f127462021-03-02 20:49:10 +01002912 flag = *TLVP_VAL(tp, NS_IE_RESET_FLAG);
2913 if (flag & 1) {
Harald Welte4f127462021-03-02 20:49:10 +01002914 /* clear all state */
Alexander Couzensa2707822021-07-20 18:59:40 +02002915 /* TODO: ensure gss->sns_nsvc is always the NSVC on which we received the SIZE PDU */
Harald Welte4f127462021-03-02 20:49:10 +01002916 gss->N = 0;
Alexander Couzensa2707822021-07-20 18:59:40 +02002917 ns2_clear_sgsn(gss, gss->sns_nsvc);
2918 /* keep the NSVC we need for SNS, but unconfigure it */
2919 gss->sns_nsvc->sig_weight = 0;
2920 gss->sns_nsvc->data_weight = 0;
2921 ns2_vc_force_unconfigured(gss->sns_nsvc);
Harald Welte2d807b62021-03-24 01:57:30 +01002922 ns2_sns_compute_local_ep_from_binds(fi);
Harald Welte4f127462021-03-02 20:49:10 +01002923 }
Alexander Couzens1c405252021-06-13 00:14:48 +02002924
2925 if (fi->state == GPRS_SNS_ST_UNCONFIGURED && !(flag & 1)) {
2926 sns_failed(fi, "Rx Size without Reset flag, but NSE is unknown");
2927 break;
2928 }
2929
Harald Welte4f127462021-03-02 20:49:10 +01002930 /* send SIZE_ACK */
2931 ns2_tx_sns_size_ack(gss->sns_nsvc, NULL);
2932 /* only wait for SNS-CONFIG in case of Reset flag */
2933 if (flag & 1)
2934 osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG, 0, 0);
2935 break;
Alexander Couzens83f06ce2021-08-06 19:50:09 +02002936 case NS2_SNS_EV_REQ_FREE_NSVCS:
2937 sns_failed(fi, "On user request to free all NSVCs");
2938 break;
Harald Welte4f127462021-03-02 20:49:10 +01002939 default:
2940 ns2_sns_st_all_action(fi, event, data);
2941 break;
2942 }
2943}
2944
2945static struct osmo_fsm gprs_ns2_sns_sgsn_fsm = {
2946 .name = "GPRS-NS2-SNS-SGSN",
2947 .states = ns2_sns_sgsn_states,
2948 .num_states = ARRAY_SIZE(ns2_sns_sgsn_states),
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002949 .allstate_event_mask = S(NS2_SNS_EV_RX_SIZE) |
2950 S(NS2_SNS_EV_REQ_NO_NSVC) |
Alexander Couzens83f06ce2021-08-06 19:50:09 +02002951 S(NS2_SNS_EV_REQ_FREE_NSVCS) |
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002952 S(NS2_SNS_EV_REQ_ADD_BIND) |
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002953 S(NS2_SNS_EV_REQ_CHANGE_WEIGHT) |
Alexander Couzens175eb7b2021-07-20 18:41:14 +02002954 S(NS2_SNS_EV_REQ_DELETE_BIND),
Harald Welte4f127462021-03-02 20:49:10 +01002955 .allstate_action = ns2_sns_st_all_action_sgsn,
2956 .cleanup = NULL,
2957 .timer_cb = ns2_sns_fsm_sgsn_timer_cb,
2958 .event_names = gprs_sns_event_names,
2959 .pre_term = NULL,
2960 .log_subsys = DLNS,
2961};
2962
2963/*! Allocate an IP-SNS FSM for the SGSN side.
2964 * \param[in] nse NS Entity in which the FSM runs
2965 * \param[in] id string identifier
2966 * \returns FSM instance on success; NULL on error */
2967struct osmo_fsm_inst *ns2_sns_sgsn_fsm_alloc(struct gprs_ns2_nse *nse, const char *id)
2968{
2969 struct osmo_fsm_inst *fi;
2970 struct ns2_sns_state *gss;
2971
2972 fi = osmo_fsm_inst_alloc(&gprs_ns2_sns_sgsn_fsm, nse, NULL, LOGL_DEBUG, id);
2973 if (!fi)
2974 return fi;
2975
2976 gss = talloc_zero(fi, struct ns2_sns_state);
2977 if (!gss)
2978 goto err;
2979
2980 fi->priv = gss;
2981 gss->nse = nse;
2982 gss->role = GPRS_SNS_ROLE_SGSN;
2983 INIT_LLIST_HEAD(&gss->sns_endpoints);
2984 INIT_LLIST_HEAD(&gss->binds);
Alexander Couzens1f3193d2021-06-05 22:08:11 +02002985 INIT_LLIST_HEAD(&gss->procedures);
Harald Welte4f127462021-03-02 20:49:10 +01002986
2987 return fi;
2988err:
2989 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
2990 return NULL;
2991}
2992
2993
2994
2995
Alexander Couzens6a161492020-07-12 13:45:50 +02002996/* initialize osmo_ctx on main tread */
2997static __attribute__((constructor)) void on_dso_load_ctx(void)
2998{
2999 OSMO_ASSERT(osmo_fsm_register(&gprs_ns2_sns_bss_fsm) == 0);
Harald Welte4f127462021-03-02 20:49:10 +01003000 OSMO_ASSERT(osmo_fsm_register(&gprs_ns2_sns_sgsn_fsm) == 0);
Alexander Couzens6a161492020-07-12 13:45:50 +02003001}