blob: ffc2ad8e64c3d8580651f8717e1089021e69b726 [file] [log] [blame]
Alexander Couzens6a161492020-07-12 13:45:50 +02001/*! \file gprs_ns2.h */
2
3
4#pragma once
5
6#include <stdint.h>
7#include <netinet/in.h>
8
9#include <osmocom/core/prim.h>
Alexander Couzensb3b837c2020-10-27 15:12:25 +010010#include <osmocom/gprs/protocol/gsm_08_16.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020011
12struct osmo_sockaddr;
Alexander Couzens1fac6f72020-10-01 19:08:38 +020013struct osmo_sockaddr_str;
Alexander Couzens6a161492020-07-12 13:45:50 +020014
15struct gprs_ns2_inst;
16struct gprs_ns2_nse;
17struct gprs_ns2_vc;
18struct gprs_ns2_vc_bind;
19struct gprs_ns2_vc_driver;
20struct gprs_ns_ie_ip4_elem;
21struct gprs_ns_ie_ip6_elem;
22
23enum gprs_ns2_vc_mode {
Harald Weltefa2d66c2020-10-17 13:09:34 +020024 /*! The VC will use RESET/BLOCK/UNBLOCK to start the connection and do ALIVE/ACK.
25 * This is what is needed for Frame Relay transport, and if you use a R97/R99 Gb
26 * interface over an IP transport (never standardized by 3GPP) */
27 NS2_VC_MODE_BLOCKRESET,
28 /*! The VC will only use ALIVE/ACK (no RESET/BLOCK/UNBLOCK), which is for Gb-IP
29 * interface compliant to 3GPP Rel=4 or later. */
30 NS2_VC_MODE_ALIVE,
Alexander Couzens6a161492020-07-12 13:45:50 +020031};
32
33/*! Osmocom NS primitives according to 48.016 5.2 Service primitves */
34enum gprs_ns2_prim {
35 PRIM_NS_UNIT_DATA,
36 PRIM_NS_CONGESTION,
37 PRIM_NS_STATUS,
38};
39
Alexander Couzens2498f1d2020-10-27 01:09:01 +010040extern const struct value_string ns2_prim_strs[];
41
42/*! Obtain a human-readable string for NS primitives */
43static inline const char *gprs_ns2_prim_str(enum gprs_ns2_prim val)
44{ return get_value_string(ns2_prim_strs, val); }
45
Alexander Couzens6a161492020-07-12 13:45:50 +020046/*! Osmocom NS primitives according to 48.016 5.2.2.4 Service primitves */
47enum gprs_ns2_congestion_cause {
48 NS_CONG_CAUSE_BACKWARD_BEGIN,
49 NS_CONG_CAUSE_BACKWARD_END,
50 NS_CONG_CAUSE_FORWARD_BEGIN,
51 NS_CONG_CAUSE_FORWARD_END,
52};
53
54/*! Osmocom NS primitives according to 48.016 5.2.2.6 Service primitves */
55enum gprs_ns2_affecting_cause {
56 NS_AFF_CAUSE_VC_FAILURE,
57 NS_AFF_CAUSE_VC_RECOVERY,
58 NS_AFF_CAUSE_FAILURE,
59 NS_AFF_CAUSE_RECOVERY,
60 /* osmocom own causes */
61 NS_AFF_CAUSE_SNS_CONFIGURED,
62 NS_AFF_CAUSE_SNS_FAILURE,
63};
64
Alexander Couzens2498f1d2020-10-27 01:09:01 +010065extern const struct value_string gprs_ns2_aff_cause_prim_strs[];
66
67/*! Obtain a human-readable string for NS affective cause in primitives */
68static inline const char *gprs_ns2_aff_cause_prim_str(enum gprs_ns2_affecting_cause val)
69{ return get_value_string(gprs_ns2_aff_cause_prim_strs, val); }
70
Alexander Couzens6a161492020-07-12 13:45:50 +020071/*! Osmocom NS primitives according to 48.016 5.2.2.7 Service primitves */
72enum gprs_ns2_change_ip_endpoint {
73 NS_ENDPOINT_NO_CHANGE,
74 NS_ENDPOINT_REQUEST_CHANGE,
75 NS_ENDPOINT_CONFIRM_CHANGE,
76};
77
Alexander Couzensb3b837c2020-10-27 15:12:25 +010078extern const struct value_string gprs_ns2_cause_strs[];
79
80/*! Obtain a human-readable string for NS primitives */
81static inline const char *gprs_ns2_cause_str(enum ns_cause val)
82{ return get_value_string(gprs_ns2_cause_strs, val); }
83
Alexander Couzens6a161492020-07-12 13:45:50 +020084struct osmo_gprs_ns2_prim {
85 struct osmo_prim_hdr oph;
86
87 uint16_t nsei;
88 uint16_t bvci;
89
90 union {
91 struct {
92 enum gprs_ns2_change_ip_endpoint change;
93 /* TODO: implement resource distribution
94 * add place holder for the link selector */
95 long long _resource_distribution_placeholder1;
96 long long _resource_distribution_placeholder2;
97 long long _resource_distribution_placeholder3;
98 } unitdata;
99 struct {
100 enum gprs_ns2_congestion_cause cause;
101 } congestion;
102 struct {
103 enum gprs_ns2_affecting_cause cause;
104 /* 48.016 5.2.2.6 transfer capability */
105 int transfer;
Alexander Couzensda0a2852020-10-01 23:24:07 +0200106 /* osmocom specific */
107 /* Persistent NSE/NSVC are configured by vty */
108 bool persistent;
109 /* Only true on the first time it's available.
110 * Allow the BSSGP layer to reset persistent NSE */
111 bool first;
Alexander Couzens6a161492020-07-12 13:45:50 +0200112 } status;
113 } u;
114};
115
116/* instance */
117struct gprs_ns2_inst *gprs_ns2_instantiate(void *ctx, osmo_prim_cb cb, void *cb_data);
118void gprs_ns2_free(struct gprs_ns2_inst *inst);
119int gprs_ns2_dynamic_create_nse(struct gprs_ns2_inst *nsi, bool create_nse);
120
121/* Entrypoint for primitives from the NS USER */
122int gprs_ns2_recv_prim(struct gprs_ns2_inst *nsi, struct osmo_prim_hdr *oph);
123
Alexander Couzens6cb5d5f2020-10-11 23:23:31 +0200124/*! a callback to iterate over all NSVC */
125typedef int (*gprs_ns2_foreach_nsvc_cb)(struct gprs_ns2_vc *nsvc, void *ctx);
126
127int gprs_ns2_nse_foreach_nsvc(struct gprs_ns2_nse *nse,
128 gprs_ns2_foreach_nsvc_cb cb, void *cb_data);
Alexander Couzens6a161492020-07-12 13:45:50 +0200129struct gprs_ns2_nse *gprs_ns2_nse_by_nsei(struct gprs_ns2_inst *nsi, uint16_t nsei);
130struct gprs_ns2_nse *gprs_ns2_create_nse(struct gprs_ns2_inst *nsi, uint16_t nsei);
Alexander Couzens05e7f7d2020-10-11 19:51:46 +0200131uint16_t gprs_ns2_nse_nsei(struct gprs_ns2_nse *nse);
Alexander Couzens6a161492020-07-12 13:45:50 +0200132void gprs_ns2_free_nse(struct gprs_ns2_nse *nse);
Alexander Couzens4b6c8af2020-10-11 20:15:25 +0200133void gprs_ns2_free_nses(struct gprs_ns2_inst *nsi);
Alexander Couzens6a161492020-07-12 13:45:50 +0200134
135/* create vc */
136void gprs_ns2_free_nsvc(struct gprs_ns2_vc *nsvc);
137struct gprs_ns2_vc *gprs_ns2_nsvc_by_nsvci(struct gprs_ns2_inst *nsi, uint16_t nsvci);
138
139/* IP VL driver */
140int gprs_ns2_ip_bind(struct gprs_ns2_inst *nsi,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700141 const struct osmo_sockaddr *local,
Alexander Couzens6a161492020-07-12 13:45:50 +0200142 int dscp,
143 struct gprs_ns2_vc_bind **result);
Alexander Couzens4f608452020-10-11 18:41:24 +0200144struct gprs_ns2_vc_bind *gprs_ns2_ip_bind_by_sockaddr(struct gprs_ns2_inst *nsi,
145 const struct osmo_sockaddr *sockaddr);
Alexander Couzens6a161492020-07-12 13:45:50 +0200146void gprs_ns2_bind_set_mode(struct gprs_ns2_vc_bind *bind, enum gprs_ns2_vc_mode mode);
147
148/* create a VC connection */
149struct gprs_ns2_vc *gprs_ns2_ip_connect(struct gprs_ns2_vc_bind *bind,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700150 const struct osmo_sockaddr *remote,
Alexander Couzens6a161492020-07-12 13:45:50 +0200151 struct gprs_ns2_nse *nse,
152 uint16_t nsvci);
153
154struct gprs_ns2_vc *gprs_ns2_ip_connect2(struct gprs_ns2_vc_bind *bind,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700155 const struct osmo_sockaddr *remote,
Alexander Couzens6a161492020-07-12 13:45:50 +0200156 uint16_t nsei,
157 uint16_t nsvci);
158struct gprs_ns2_vc *gprs_ns2_ip_connect_inactive(struct gprs_ns2_vc_bind *bind,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700159 const struct osmo_sockaddr *remote,
Alexander Couzens6a161492020-07-12 13:45:50 +0200160 struct gprs_ns2_nse *nse,
161 uint16_t nsvci);
162
163void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind);
Alexander Couzens896fcd52020-10-11 19:52:36 +0200164void gprs_ns2_free_binds(struct gprs_ns2_inst *nsi);
Alexander Couzens6a161492020-07-12 13:45:50 +0200165
166/* create a VC SNS connection */
167int gprs_ns2_ip_connect_sns(struct gprs_ns2_vc_bind *bind,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700168 const struct osmo_sockaddr *remote,
Alexander Couzens6a161492020-07-12 13:45:50 +0200169 uint16_t nsei);
Alexander Couzens125298f2020-10-11 21:22:42 +0200170const struct osmo_sockaddr *gprs_ns2_nse_sns_remote(struct gprs_ns2_nse *nse);
Alexander Couzens6a161492020-07-12 13:45:50 +0200171
Alexander Couzensd33512b2020-10-11 21:42:11 +0200172const struct osmo_sockaddr *gprs_ns2_ip_vc_remote(const struct gprs_ns2_vc *nsvc);
Alexander Couzens979f5f52020-10-11 21:01:48 +0200173const struct osmo_sockaddr *gprs_ns2_ip_vc_local(const struct gprs_ns2_vc *nsvc);
Alexander Couzensd420ea92020-10-12 01:11:05 +0200174bool gprs_ns2_ip_vc_equal(const struct gprs_ns2_vc *nsvc,
175 const struct osmo_sockaddr *local,
176 const struct osmo_sockaddr *remote,
177 uint16_t nsvci);
Alexander Couzens9a4cf272020-10-11 20:48:04 +0200178const struct osmo_sockaddr *gprs_ns2_ip_bind_sockaddr(struct gprs_ns2_vc_bind *bind);
Alexander Couzens6a161492020-07-12 13:45:50 +0200179int gprs_ns2_is_ip_bind(struct gprs_ns2_vc_bind *bind);
180int gprs_ns2_ip_bind_set_dscp(struct gprs_ns2_vc_bind *bind, int dscp);
Alexander Couzens38b19e82020-09-23 23:56:37 +0200181struct gprs_ns2_vc *gprs_ns2_nsvc_by_sockaddr_bind(
Alexander Couzens6a161492020-07-12 13:45:50 +0200182 struct gprs_ns2_vc_bind *bind,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700183 const struct osmo_sockaddr *saddr);
Alexander Couzens6a161492020-07-12 13:45:50 +0200184
185int gprs_ns2_frgre_bind(struct gprs_ns2_inst *nsi,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700186 const struct osmo_sockaddr *local,
Alexander Couzens6a161492020-07-12 13:45:50 +0200187 int dscp,
188 struct gprs_ns2_vc_bind **result);
189int gprs_ns2_is_frgre_bind(struct gprs_ns2_vc_bind *bind);
190
Alexander Couzens38b19e82020-09-23 23:56:37 +0200191struct gprs_ns2_vc *gprs_ns2_nsvc_by_sockaddr_nse(
192 struct gprs_ns2_nse *nse,
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700193 const struct osmo_sockaddr *sockaddr);
Alexander Couzens6a161492020-07-12 13:45:50 +0200194void gprs_ns2_start_alive_all_nsvcs(struct gprs_ns2_nse *nse);
Alexander Couzens6a161492020-07-12 13:45:50 +0200195const char *gprs_ns2_ll_str(struct gprs_ns2_vc *nsvc);
196char *gprs_ns2_ll_str_buf(char *buf, size_t buf_len, struct gprs_ns2_vc *nsvc);
197char *gprs_ns2_ll_str_c(const void *ctx, struct gprs_ns2_vc *nsvc);
198
199/* vty */
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700200int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi,
201 const struct osmo_sockaddr_str *default_bind);
Alexander Couzens6a161492020-07-12 13:45:50 +0200202int gprs_ns2_vty_create();
Daniel Willmann4fb27a82020-09-25 15:39:46 +0200203void gprs_ns2_vty_force_vc_mode(bool force, enum gprs_ns2_vc_mode mode, const char *reason);
Alexander Couzens6a161492020-07-12 13:45:50 +0200204
205
206/*! @} */