Neels Hofmeyr | 17518fe | 2017-06-20 04:35:06 +0200 | [diff] [blame] | 1 | /*! \file lapd_core.h |
| 2 | * primitive related stuff |
| 3 | */ |
Sylvain Munaut | 12ba778 | 2014-06-16 10:13:40 +0200 | [diff] [blame] | 4 | #pragma once |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 5 | |
| 6 | #include <stdint.h> |
| 7 | |
| 8 | #include <osmocom/core/timer.h> |
| 9 | #include <osmocom/core/msgb.h> |
| 10 | #include <osmocom/gsm/prim.h> |
| 11 | |
| 12 | /*! \defgroup lapd LAPD implementation common part |
| 13 | * @{ |
Neels Hofmeyr | 17518fe | 2017-06-20 04:35:06 +0200 | [diff] [blame] | 14 | * \file lapd_core.h |
Katerina Barone-Adesi | c28c6a0 | 2013-02-15 13:27:59 +0100 | [diff] [blame] | 15 | */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 16 | |
Harald Welte | 00b2faf | 2020-05-02 19:56:36 +0200 | [diff] [blame] | 17 | #define LOGDL(dl, level, fmt, args...) \ |
| 18 | LOGP(DLLAPD, level, "(%s) " fmt, (dl)->name, ## args) |
| 19 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 20 | /*! LAPD related primitives (L2<->L3 SAP)*/ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 21 | enum osmo_dl_prim { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 22 | PRIM_DL_UNIT_DATA, /*!< DL-UNIT-DATA */ |
| 23 | PRIM_DL_DATA, /*!< DL-DATA */ |
| 24 | PRIM_DL_EST, /*!< DL-ESTABLISH */ |
| 25 | PRIM_DL_REL, /*!< DL-RLEEASE */ |
| 26 | PRIM_DL_SUSP, /*!< DL-SUSPEND */ |
| 27 | PRIM_DL_RES, /*!< DL-RESUME */ |
| 28 | PRIM_DL_RECON, /*!< DL-RECONNECT */ |
| 29 | PRIM_MDL_ERROR, /*!< MDL-ERROR */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 30 | }; |
| 31 | |
| 32 | /* Uses the same values as RLL, so no conversion for GSM is required. */ |
| 33 | #define MDL_CAUSE_T200_EXPIRED 0x01 |
| 34 | #define MDL_CAUSE_REEST_REQ 0x02 |
| 35 | #define MDL_CAUSE_UNSOL_UA_RESP 0x03 |
| 36 | #define MDL_CAUSE_UNSOL_DM_RESP 0x04 |
| 37 | #define MDL_CAUSE_UNSOL_DM_RESP_MF 0x05 |
| 38 | #define MDL_CAUSE_UNSOL_SPRV_RESP 0x06 |
| 39 | #define MDL_CAUSE_SEQ_ERR 0x07 |
| 40 | #define MDL_CAUSE_UFRM_INC_PARAM 0x08 |
| 41 | #define MDL_CAUSE_SFRM_INC_PARAM 0x09 |
| 42 | #define MDL_CAUSE_IFRM_INC_MBITS 0x0a |
| 43 | #define MDL_CAUSE_IFRM_INC_LEN 0x0b |
| 44 | #define MDL_CAUSE_FRM_UNIMPL 0x0c |
| 45 | #define MDL_CAUSE_SABM_MF 0x0d |
| 46 | #define MDL_CAUSE_SABM_INFO_NOTALL 0x0e |
| 47 | #define MDL_CAUSE_FRMR 0x0f |
| 48 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 49 | /*! for MDL-ERROR.ind */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 50 | struct mdl_error_ind_param { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 51 | uint8_t cause; /*!< generic cause value */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 52 | }; |
| 53 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 54 | /*! for DL-REL.req */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 55 | struct dl_rel_req_param { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 56 | uint8_t mode; /*!< release mode */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 57 | }; |
| 58 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 59 | /*! primitive header for LAPD DL-SAP primitives */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 60 | struct osmo_dlsap_prim { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 61 | struct osmo_prim_hdr oph; /*!< generic primitive header */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 62 | union { |
| 63 | struct mdl_error_ind_param error_ind; |
| 64 | struct dl_rel_req_param rel_req; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 65 | } u; /*!< request-specific data */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 66 | }; |
| 67 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 68 | /*! LAPD mode/role */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 69 | enum lapd_mode { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 70 | LAPD_MODE_USER, /*!< behave like user */ |
| 71 | LAPD_MODE_NETWORK, /*!< behave like network */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 72 | }; |
| 73 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 74 | /*! LAPD state (Figure B.2/Q.921)*/ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 75 | enum lapd_state { |
| 76 | LAPD_STATE_NULL = 0, |
| 77 | LAPD_STATE_TEI_UNASS, |
| 78 | LAPD_STATE_ASS_TEI_WAIT, |
| 79 | LAPD_STATE_EST_TEI_WAIT, |
| 80 | LAPD_STATE_IDLE, |
| 81 | LAPD_STATE_SABM_SENT, |
| 82 | LAPD_STATE_DISC_SENT, |
| 83 | LAPD_STATE_MF_EST, |
| 84 | LAPD_STATE_TIMER_RECOV, |
| 85 | }; |
| 86 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 87 | /*! LAPD message format (I / S / U) */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 88 | enum lapd_format { |
| 89 | LAPD_FORM_UKN = 0, |
| 90 | LAPD_FORM_I, |
| 91 | LAPD_FORM_S, |
| 92 | LAPD_FORM_U, |
| 93 | }; |
| 94 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 95 | /*! LAPD message context */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 96 | struct lapd_msg_ctx { |
| 97 | struct lapd_datalink *dl; |
| 98 | int n201; |
| 99 | /* address */ |
| 100 | uint8_t cr; |
| 101 | uint8_t sapi; |
| 102 | uint8_t tei; |
| 103 | uint8_t lpd; |
| 104 | /* control */ |
| 105 | uint8_t format; |
| 106 | uint8_t p_f; /* poll / final bit */ |
| 107 | uint8_t n_send; |
| 108 | uint8_t n_recv; |
| 109 | uint8_t s_u; /* S or repectivly U function bits */ |
| 110 | /* length */ |
| 111 | int length; |
| 112 | uint8_t more; |
| 113 | }; |
| 114 | |
| 115 | struct lapd_cr_ent { |
| 116 | uint8_t cmd; |
| 117 | uint8_t resp; |
| 118 | }; |
| 119 | |
| 120 | struct lapd_history { |
| 121 | struct msgb *msg; /* message to be sent / NULL, if histoy is empty */ |
| 122 | int more; /* if message is fragmented */ |
| 123 | }; |
| 124 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 125 | /*! LAPD datalink */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 126 | struct lapd_datalink { |
| 127 | int (*send_dlsap)(struct osmo_dlsap_prim *dp, |
| 128 | struct lapd_msg_ctx *lctx); |
| 129 | int (*send_ph_data_req)(struct lapd_msg_ctx *lctx, struct msgb *msg); |
Daniel Willmann | 3dc4e16 | 2014-03-20 19:24:48 +0100 | [diff] [blame] | 130 | int (*update_pending_frames)(struct lapd_msg_ctx *lctx); |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 131 | struct { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 132 | /*! filled-in once we set the lapd_mode above */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 133 | struct lapd_cr_ent loc2rem; |
| 134 | struct lapd_cr_ent rem2loc; |
| 135 | } cr; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 136 | enum lapd_mode mode; /*!< current mode of link */ |
| 137 | int use_sabme; /*!< use SABME instead of SABM */ |
| 138 | int reestablish; /*!< enable reestablish support */ |
| 139 | int n200, n200_est_rel; /*!< number of retranmissions */ |
| 140 | struct lapd_msg_ctx lctx; /*!< LAPD context */ |
| 141 | int maxf; /*!< maximum frame size (after defragmentation) */ |
| 142 | uint8_t k; /*!< maximum number of unacknowledged frames */ |
| 143 | uint8_t v_range; /*!< range of sequence numbers */ |
| 144 | uint8_t v_send; /*!< seq nr of next I frame to be transmitted */ |
| 145 | uint8_t v_ack; /*!< last frame ACKed by peer */ |
| 146 | uint8_t v_recv; /*!< seq nr of next I frame expected to be received */ |
| 147 | uint32_t state; /*!< LAPD state (\ref lapd_state) */ |
| 148 | int seq_err_cond; /*!< condition of sequence error */ |
| 149 | uint8_t own_busy; /*!< receiver busy on our side */ |
| 150 | uint8_t peer_busy; /*!< receiver busy on remote side */ |
| 151 | int t200_sec, t200_usec; /*!< retry timer (default 1 sec) */ |
| 152 | int t203_sec, t203_usec; /*!< retry timer (default 10 secs) */ |
| 153 | struct osmo_timer_list t200; /*!< T200 timer */ |
| 154 | struct osmo_timer_list t203; /*!< T203 timer */ |
| 155 | uint8_t retrans_ctr; /*!< re-transmission counter */ |
| 156 | struct llist_head tx_queue; /*!< frames to L1 */ |
| 157 | struct llist_head send_queue; /*!< frames from L3 */ |
| 158 | struct msgb *send_buffer; /*!< current frame transmitting */ |
| 159 | int send_out; /*!< how much was sent from send_buffer */ |
| 160 | struct lapd_history *tx_hist; /*!< tx history structure array */ |
| 161 | uint8_t range_hist; /*!< range of history buffer 2..2^n */ |
| 162 | struct msgb *rcv_buffer; /*!< buffer to assemble the received message */ |
| 163 | struct msgb *cont_res; /*!< buffer to store content resolution data on network side, to detect multiple phones on same channel */ |
Harald Welte | 00b2faf | 2020-05-02 19:56:36 +0200 | [diff] [blame] | 164 | char *name; /*!< user-provided name */ |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 165 | }; |
| 166 | |
Harald Welte | 00b2faf | 2020-05-02 19:56:36 +0200 | [diff] [blame] | 167 | void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf) |
| 168 | OSMO_DEPRECATED("Use lapd_dl_init2() instead"); |
| 169 | void lapd_dl_init2(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf, const char *name); |
| 170 | void lapd_dl_set_name(struct lapd_datalink *dl, const char *name); |
root | af48bed | 2011-09-26 11:23:06 +0200 | [diff] [blame] | 171 | void lapd_dl_exit(struct lapd_datalink *dl); |
| 172 | void lapd_dl_reset(struct lapd_datalink *dl); |
| 173 | int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode); |
| 174 | int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx); |
| 175 | int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx); |
| 176 | |
Katerina Barone-Adesi | c28c6a0 | 2013-02-15 13:27:59 +0100 | [diff] [blame] | 177 | /*! @} */ |