blob: ce0e63c51033bc3ddc5f3ebfca0143d9a3eb1907 [file] [log] [blame]
Harald Welte9b455bf2010-03-14 15:45:01 +08001#ifndef _GPRS_LLC_H
2#define _GPRS_LLC_H
3
Harald Welteeaa614c2010-05-02 11:26:34 +02004#include <stdint.h>
Max82040102016-07-06 11:59:18 +02005#include <stdbool.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +02006#include <osmocom/sgsn/gprs_sgsn.h>
7#include <osmocom/sgsn/gprs_llc_xid.h>
Harald Welteeaa614c2010-05-02 11:26:34 +02008
Harald Welte9b455bf2010-03-14 15:45:01 +08009/* Section 4.7 LLC Layer Structure */
10enum gprs_llc_sapi {
11 GPRS_SAPI_GMM = 1,
12 GPRS_SAPI_TOM2 = 2,
13 GPRS_SAPI_SNDCP3 = 3,
14 GPRS_SAPI_SNDCP5 = 5,
15 GPRS_SAPI_SMS = 7,
16 GPRS_SAPI_TOM8 = 8,
17 GPRS_SAPI_SNDCP9 = 9,
18 GPRS_SAPI_SNDCP11 = 11,
19};
20
Harald Welte10997d02010-05-03 12:28:12 +020021/* Section 6.4 Commands and Responses */
22enum gprs_llc_u_cmd {
23 GPRS_LLC_U_DM_RESP = 0x01,
24 GPRS_LLC_U_DISC_CMD = 0x04,
25 GPRS_LLC_U_UA_RESP = 0x06,
26 GPRS_LLC_U_SABM_CMD = 0x07,
27 GPRS_LLC_U_FRMR_RESP = 0x08,
28 GPRS_LLC_U_XID = 0x0b,
29 GPRS_LLC_U_NULL_CMD = 0x00,
30};
Harald Welte9b455bf2010-03-14 15:45:01 +080031
Harald Welte0c1a3032011-10-16 18:49:05 +020032/* Section 6.4.1.6 / Table 6 */
33enum gprs_llc_xid_type {
34 GPRS_LLC_XID_T_VERSION = 0,
35 GPRS_LLC_XID_T_IOV_UI = 1,
36 GPRS_LLC_XID_T_IOV_I = 2,
37 GPRS_LLC_XID_T_T200 = 3,
38 GPRS_LLC_XID_T_N200 = 4,
39 GPRS_LLC_XID_T_N201_U = 5,
40 GPRS_LLC_XID_T_N201_I = 6,
41 GPRS_LLC_XID_T_mD = 7,
42 GPRS_LLC_XID_T_mU = 8,
43 GPRS_LLC_XID_T_kD = 9,
44 GPRS_LLC_XID_T_kU = 10,
45 GPRS_LLC_XID_T_L3_PAR = 11,
46 GPRS_LLC_XID_T_RESET = 12,
47};
48
Max549ebc72016-11-18 14:07:04 +010049extern const struct value_string gprs_llc_xid_type_names[];
50
Harald Welte1ae09c72010-05-13 19:22:55 +020051/* TS 04.64 Section 7.1.2 Table 7: LLC layer primitives (GMM/SNDCP/SMS/TOM) */
52/* TS 04.65 Section 5.1.2 Table 2: Service primitives used by SNDCP */
53enum gprs_llc_primitive {
54 /* GMM <-> LLME */
55 LLGMM_ASSIGN_REQ, /* GMM tells us new TLLI: TLLI old, TLLI new, Kc, CiphAlg */
56 LLGMM_RESET_REQ, /* GMM tells us to perform XID negotiation: TLLI */
57 LLGMM_RESET_CNF, /* LLC informs GMM that XID has completed: TLLI */
58 LLGMM_SUSPEND_REQ, /* GMM tells us MS has suspended: TLLI, Page */
59 LLGMM_RESUME_REQ, /* GMM tells us MS has resumed: TLLI */
60 LLGMM_PAGE_IND, /* LLC asks GMM to page MS: TLLI */
61 LLGMM_IOV_REQ, /* GMM tells us to perform XID: TLLI */
62 LLGMM_STATUS_IND, /* LLC informs GMM about error: TLLI, Cause */
63 /* LLE <-> (GMM/SNDCP/SMS/TOM) */
64 LL_RESET_IND, /* TLLI */
65 LL_ESTABLISH_REQ, /* TLLI, XID Req */
66 LL_ESTABLISH_IND, /* TLLI, XID Req, N201-I, N201-U */
67 LL_ESTABLISH_RESP, /* TLLI, XID Negotiated */
68 LL_ESTABLISH_CONF, /* TLLI, XID Neg, N201-i, N201-U */
69 LL_RELEASE_REQ, /* TLLI, Local */
70 LL_RELEASE_IND, /* TLLI, Cause */
71 LL_RELEASE_CONF, /* TLLI */
72 LL_XID_REQ, /* TLLI, XID Requested */
73 LL_XID_IND, /* TLLI, XID Req, N201-I, N201-U */
74 LL_XID_RESP, /* TLLI, XID Negotiated */
75 LL_XID_CONF, /* TLLI, XID Neg, N201-I, N201-U */
76 LL_DATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
77 LL_DATA_IND, /* TLLI, SN-PDU */
78 LL_DATA_CONF, /* TLLI, Ref */
79 LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
80 LL_UNITDATA_IND, /* TLLI, SN-PDU */
81 LL_STATUS_IND, /* TLLI, Cause */
82};
83
Harald Welte2e918a82010-05-18 12:20:12 +020084/* Section 4.5.2 Logical Link States + Annex C.2 */
Harald Welte807a5d82010-06-01 11:53:01 +020085enum gprs_llc_lle_state {
86 GPRS_LLES_UNASSIGNED = 1, /* No TLLI yet */
87 GPRS_LLES_ASSIGNED_ADM = 2, /* TLLI assigned */
88 GPRS_LLES_LOCAL_EST = 3, /* Local Establishment */
89 GPRS_LLES_REMOTE_EST = 4, /* Remote Establishment */
90 GPRS_LLES_ABM = 5,
91 GPRS_LLES_LOCAL_REL = 6, /* Local Release */
92 GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
93};
94
95enum gprs_llc_llme_state {
96 GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
97 GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */
Harald Welte2e918a82010-05-18 12:20:12 +020098};
Pau Espin Pedrol5b6c4b82019-08-14 16:08:15 +020099extern const struct value_string gprs_llc_llme_state_names[];
Harald Welte2e918a82010-05-18 12:20:12 +0200100
Harald Welte1d9d9442010-06-03 07:11:04 +0200101/* Section 8.9.9 LLC layer parameter default values */
102struct gprs_llc_params {
103 uint16_t iov_i_exp;
104 uint16_t t200_201;
105 uint16_t n200;
106 uint16_t n201_u;
107 uint16_t n201_i;
108 uint16_t mD;
109 uint16_t mU;
110 uint16_t kD;
111 uint16_t kU;
112};
113
Pau Espin Pedrol39aa9ee2019-08-12 16:23:04 +0200114/* 3GPP TS 44.064 § 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
Harald Welte2e918a82010-05-18 12:20:12 +0200115struct gprs_llc_lle {
116 struct llist_head list;
117
Harald Welte807a5d82010-06-01 11:53:01 +0200118 uint32_t sapi;
119
Pau Espin Pedrol39aa9ee2019-08-12 16:23:04 +0200120 struct gprs_llc_llme *llme; /* backpointer to the Logical Link Management Entity */
Harald Welte807a5d82010-06-01 11:53:01 +0200121
122 enum gprs_llc_lle_state state;
123
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200124 struct osmo_timer_list t200;
125 struct osmo_timer_list t201; /* wait for acknowledgement */
Harald Welte2e918a82010-05-18 12:20:12 +0200126
Harald Welte6bdee6a2010-05-30 21:51:58 +0200127 uint16_t v_sent;
128 uint16_t v_ack;
129 uint16_t v_recv;
130
131 uint16_t vu_send;
132 uint16_t vu_recv;
Harald Welte2e918a82010-05-18 12:20:12 +0200133
Harald Welteabadd542013-06-21 14:06:18 +0200134 /* non-standard LLC state */
135 uint16_t vu_recv_last;
136 uint16_t vu_recv_duplicates;
137
Harald Welted07b4f92010-06-30 23:07:59 +0200138 /* Overflow Counter for ABM */
139 uint32_t oc_i_send;
140 uint32_t oc_i_recv;
141
142 /* Overflow Counter for unconfirmed transfer */
143 uint32_t oc_ui_send;
144 uint32_t oc_ui_recv;
145
Harald Welte2e918a82010-05-18 12:20:12 +0200146 unsigned int retrans_ctr;
Harald Welte1d9d9442010-06-03 07:11:04 +0200147
148 struct gprs_llc_params params;
Harald Welteaf779d22019-04-12 16:56:04 +0200149
150 /* Copy of the XID fields we have sent with the last
151 * network originated XID-Request. Since the phone
152 * may strip the optional fields in the confirmation
153 * we need to remeber those fields in order to be
154 * able to create the compression entity. */
155 struct llist_head *xid;
Harald Welte807a5d82010-06-01 11:53:01 +0200156};
157
158#define NUM_SAPIS 16
159
Pau Espin Pedrol39aa9ee2019-08-12 16:23:04 +0200160/* 3GPP TS 44.064 § 4.7.3: Logical Link Management Entity: One per TLLI */
Harald Welte807a5d82010-06-01 11:53:01 +0200161struct gprs_llc_llme {
162 struct llist_head list;
163
164 enum gprs_llc_llme_state state;
165
166 uint32_t tlli;
167 uint32_t old_tlli;
Harald Welte2e918a82010-05-18 12:20:12 +0200168
Harald Welted07b4f92010-06-30 23:07:59 +0200169 /* Crypto parameters */
170 enum gprs_ciph_algo algo;
Max5aa51962016-07-06 11:33:04 +0200171 uint8_t kc[16];
172 uint8_t cksn;
173 /* 3GPP TS 44.064 § 8.9.2: */
174 uint32_t iov_ui;
Harald Welted07b4f92010-06-30 23:07:59 +0200175
Harald Welte2e918a82010-05-18 12:20:12 +0200176 /* over which BSSGP BTS ctx do we need to transmit */
177 uint16_t bvci;
178 uint16_t nsei;
Harald Welte807a5d82010-06-01 11:53:01 +0200179 struct gprs_llc_lle lle[NUM_SAPIS];
Jacob Erlbeck81ffb742015-01-23 11:33:51 +0100180
Philippf1f34362016-08-26 17:00:21 +0200181 /* Compression entities */
182 struct {
183 /* In these two list_heads we will store the
184 * data and protocol compression entities,
185 * together with their compression states */
186 struct llist_head *proto;
187 struct llist_head *data;
188 } comp;
189
Jacob Erlbeck81ffb742015-01-23 11:33:51 +0100190 /* Internal management */
191 uint32_t age_timestamp;
Harald Welte2e918a82010-05-18 12:20:12 +0200192};
193
Jacob Erlbeck81ffb742015-01-23 11:33:51 +0100194#define GPRS_LLME_RESET_AGE (0)
195
Pau Espin Pedrol404d9b82019-08-12 17:49:09 +0200196/* 3GPP TS 44.064 § 8.3 TLLI assignment procedures */
197#define TLLI_UNASSIGNED (0xffffffff)
198
Harald Welte807a5d82010-06-01 11:53:01 +0200199extern struct llist_head gprs_llc_llmes;
Harald Welte2e918a82010-05-18 12:20:12 +0200200
Jacob Erlbeckb492d392014-06-02 10:49:01 +0200201/* LLC low level types */
202
203enum gprs_llc_cmd {
204 GPRS_LLC_NULL,
205 GPRS_LLC_RR,
206 GPRS_LLC_ACK,
207 GPRS_LLC_RNR,
208 GPRS_LLC_SACK,
209 GPRS_LLC_DM,
210 GPRS_LLC_DISC,
211 GPRS_LLC_UA,
212 GPRS_LLC_SABM,
213 GPRS_LLC_FRMR,
214 GPRS_LLC_XID,
215 GPRS_LLC_UI,
216};
217
218struct gprs_llc_hdr_parsed {
219 uint8_t sapi;
220 uint8_t is_cmd:1,
221 ack_req:1,
222 is_encrypted:1;
223 uint32_t seq_rx;
224 uint32_t seq_tx;
225 uint32_t fcs;
226 uint32_t fcs_calc;
227 uint8_t *data;
228 uint16_t data_len;
229 uint16_t crc_length;
230 enum gprs_llc_cmd cmd;
231};
232
233
Harald Welte1ae09c72010-05-13 19:22:55 +0200234/* BSSGP-UL-UNITDATA.ind */
Harald Welte9b455bf2010-03-14 15:45:01 +0800235int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv);
Harald Welte1ae09c72010-05-13 19:22:55 +0200236
237/* LL-UNITDATA.req */
Harald Welte56a01452010-05-31 22:12:30 +0200238int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
Max82040102016-07-06 11:59:18 +0200239 struct sgsn_mm_ctx *mmctx, bool encryptable);
Harald Welte9b455bf2010-03-14 15:45:01 +0800240
Harald Welte0c1a3032011-10-16 18:49:05 +0200241/* Chapter 7.2.1.2 LLGMM-RESET.req */
242int gprs_llgmm_reset(struct gprs_llc_llme *llme);
Maxb997f842016-07-06 15:57:01 +0200243int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
244 struct gprs_llc_llme *llme);
Harald Welte0c1a3032011-10-16 18:49:05 +0200245
Philipp4ac3aee2016-08-10 12:24:09 +0200246/* Set of LL-XID negotiation (See also: TS 101 351, Section 7.2.2.4) */
247int gprs_ll_xid_req(struct gprs_llc_lle *lle,
248 struct gprs_llc_xid_field *l3_xid_field);
249
Harald Welte807a5d82010-06-01 11:53:01 +0200250/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
251int gprs_llgmm_assign(struct gprs_llc_llme *llme,
Max5aa51962016-07-06 11:33:04 +0200252 uint32_t old_tlli, uint32_t new_tlli);
Max39550252016-06-28 17:39:20 +0200253int gprs_llgmm_unassign(struct gprs_llc_llme *llme);
Harald Welte807a5d82010-06-01 11:53:01 +0200254
Harald Welte496aee42010-06-30 19:59:55 +0200255int gprs_llc_init(const char *cipher_plugin_path);
Harald Welte2e918a82010-05-18 12:20:12 +0200256int gprs_llc_vty_init(void);
257
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400258/**
259 * \short Check if N(U) should be considered a retransmit
260 *
261 * Implements the range check as of GSM 04.64 8.4.2
262 * Receipt of unacknowledged information.
263 *
264 * @returns Returns 1 if (V(UR)-32) <= N(U) < V(UR)
265 * @param nu N(U) unconfirmed sequence number of the UI frame
266 * @param vur V(UR) unconfirmend received state variable
267 */
268static inline int gprs_llc_is_retransmit(uint16_t nu, uint16_t vur)
269{
270 int delta = (vur - nu) & 0x1ff;
271 return 0 < delta && delta < 32;
272}
273
Jacob Erlbeckb492d392014-06-02 10:49:01 +0200274/* LLC low level functions */
Max5aa51962016-07-06 11:33:04 +0200275void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
Jacob Erlbeckb492d392014-06-02 10:49:01 +0200276
277/* parse a GPRS LLC header, also check for invalid frames */
278int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
279 uint8_t *llc_hdr, int len);
Max549ebc72016-11-18 14:07:04 +0100280void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle);
Jacob Erlbeckb492d392014-06-02 10:49:01 +0200281int gprs_llc_fcs(uint8_t *data, unsigned int len);
282
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200283
284/* LLME handling routines */
285struct llist_head *gprs_llme_list(void);
286struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi);
287
288
Harald Welte9b455bf2010-03-14 15:45:01 +0800289#endif