Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 1 | #ifndef _GPRS_NS_H |
| 2 | #define _GPRS_NS_H |
| 3 | |
Harald Welte | eaa614c | 2010-05-02 11:26:34 +0200 | [diff] [blame] | 4 | #include <stdint.h> |
| 5 | |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 6 | /* GPRS Networks Service (NS) messages on the Gb interface |
| 7 | * 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) |
| 8 | * 3GPP TS 48.016 version 6.5.0 Release 6 / ETSI TS 148 016 V6.5.0 (2005-11) */ |
| 9 | |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 10 | struct gprs_ns_hdr { |
Harald Welte | eaa614c | 2010-05-02 11:26:34 +0200 | [diff] [blame] | 11 | uint8_t pdu_type; |
| 12 | uint8_t data[0]; |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 13 | } __attribute__((packed)); |
| 14 | |
| 15 | /* TS 08.16, Section 10.3.7, Table 14 */ |
| 16 | enum ns_pdu_type { |
| 17 | NS_PDUT_UNITDATA = 0x00, |
| 18 | NS_PDUT_RESET = 0x02, |
| 19 | NS_PDUT_RESET_ACK = 0x03, |
| 20 | NS_PDUT_BLOCK = 0x04, |
| 21 | NS_PDUT_BLOCK_ACK = 0x05, |
| 22 | NS_PDUT_UNBLOCK = 0x06, |
| 23 | NS_PDUT_UNBLOCK_ACK = 0x07, |
| 24 | NS_PDUT_STATUS = 0x08, |
| 25 | NS_PDUT_ALIVE = 0x0a, |
| 26 | NS_PDUT_ALIVE_ACK = 0x0b, |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 27 | /* TS 48.016 Section 10.3.7, Table 10.3.7.1 */ |
| 28 | SNS_PDUT_ACK = 0x0c, |
| 29 | SNS_PDUT_ADD = 0x0d, |
| 30 | SNS_PDUT_CHANGE_WEIGHT = 0x0e, |
| 31 | SNS_PDUT_CONFIG = 0x0f, |
| 32 | SNS_PDUT_CONFIG_ACK = 0x10, |
| 33 | SNS_PDUT_DELETE = 0x11, |
| 34 | SNS_PDUT_SIZE = 0x12, |
| 35 | SNS_PDUT_SIZE_ACK = 0x13, |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 36 | }; |
| 37 | |
| 38 | /* TS 08.16, Section 10.3, Table 12 */ |
| 39 | enum ns_ctrl_ie { |
| 40 | NS_IE_CAUSE = 0x00, |
| 41 | NS_IE_VCI = 0x01, |
| 42 | NS_IE_PDU = 0x02, |
| 43 | NS_IE_BVCI = 0x03, |
| 44 | NS_IE_NSEI = 0x04, |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 45 | /* TS 48.016 Section 10.3, Table 10.3.1 */ |
| 46 | NS_IE_IPv4_LIST = 0x05, |
| 47 | NS_IE_IPv6_LIST = 0x06, |
| 48 | NS_IE_MAX_NR_NSVC = 0x07, |
| 49 | NS_IE_IPv4_EP_NR = 0x08, |
| 50 | NS_IE_IPv6_EP_NR = 0x09, |
| 51 | NS_IE_RESET_FLAG = 0x0a, |
| 52 | NS_IE_IP_ADDR = 0x0b, |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 53 | }; |
| 54 | |
| 55 | /* TS 08.16, Section 10.3.2, Table 13 */ |
| 56 | enum ns_cause { |
| 57 | NS_CAUSE_TRANSIT_FAIL = 0x00, |
| 58 | NS_CAUSE_OM_INTERVENTION = 0x01, |
| 59 | NS_CAUSE_EQUIP_FAIL = 0x02, |
| 60 | NS_CAUSE_NSVC_BLOCKED = 0x03, |
| 61 | NS_CAUSE_NSVC_UNKNOWN = 0x04, |
| 62 | NS_CAUSE_BVCI_UNKNOWN = 0x05, |
| 63 | NS_CAUSE_SEM_INCORR_PDU = 0x08, |
| 64 | NS_CAUSE_PDU_INCOMP_PSTATE = 0x0a, |
| 65 | NS_CAUSE_PROTO_ERR_UNSPEC = 0x0b, |
| 66 | NS_CAUSE_INVAL_ESSENT_IE = 0x0c, |
| 67 | NS_CAUSE_MISSING_ESSENT_IE = 0x0d, |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 68 | /* TS 48.016 Section 10.3.2, Table 10.3.2.1 */ |
| 69 | NS_CAUSE_INVAL_NR_IPv4_EP = 0x0e, |
| 70 | NS_CAUSE_INVAL_NR_IPv6_EP = 0x0f, |
| 71 | NS_CAUSE_INVAL_NR_NS_VC = 0x10, |
| 72 | NS_CAUSE_INVAL_WEIGH = 0x11, |
| 73 | NS_CAUSE_UNKN_IP_EP = 0x12, |
| 74 | NS_CAUSE_UNKN_IP_ADDR = 0x13, |
| 75 | NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14, |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 76 | }; |
| 77 | |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 78 | |
| 79 | /* Our Implementation */ |
| 80 | #include <netinet/in.h> |
Harald Welte | b77c697 | 2010-05-01 11:28:43 +0200 | [diff] [blame] | 81 | #include <osmocore/linuxlist.h> |
| 82 | #include <osmocore/msgb.h> |
| 83 | #include <osmocore/timer.h> |
| 84 | #include <osmocore/select.h> |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 85 | |
| 86 | #define NSE_S_BLOCKED 0x0001 |
| 87 | #define NSE_S_ALIVE 0x0002 |
| 88 | |
Harald Welte | b77c697 | 2010-05-01 11:28:43 +0200 | [diff] [blame] | 89 | enum gprs_ns_ll { |
| 90 | GPRS_NS_LL_UDP, |
| 91 | GPRS_NS_LL_E1, |
| 92 | }; |
| 93 | |
| 94 | enum gprs_ns_evt { |
| 95 | GPRS_NS_EVT_UNIT_DATA, |
| 96 | }; |
| 97 | |
| 98 | struct gprs_nsvc; |
| 99 | typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, |
Harald Welte | eaa614c | 2010-05-02 11:26:34 +0200 | [diff] [blame] | 100 | struct msgb *msg, uint16_t bvci); |
Harald Welte | b77c697 | 2010-05-01 11:28:43 +0200 | [diff] [blame] | 101 | |
| 102 | /* An instance of the NS protocol stack */ |
| 103 | struct gprs_ns_inst { |
| 104 | /* callback to the user for incoming UNIT DATA IND */ |
| 105 | gprs_ns_cb_t *cb; |
| 106 | |
| 107 | /* linked lists of all NSVC in this instance */ |
| 108 | struct llist_head gprs_nsvcs; |
| 109 | |
| 110 | /* which link-layer are we based on? */ |
| 111 | enum gprs_ns_ll ll; |
| 112 | |
| 113 | union { |
| 114 | /* NS-over-IP specific bits */ |
| 115 | struct { |
| 116 | struct bsc_fd fd; |
| 117 | } nsip; |
| 118 | }; |
| 119 | }; |
| 120 | |
Harald Welte | 05b320a | 2010-05-03 20:16:13 +0200 | [diff] [blame^] | 121 | enum nsvc_timer_mode { |
| 122 | /* standard timers */ |
| 123 | NSVC_TIMER_TNS_TEST, |
| 124 | NSVC_TIMER_TNS_ALIVE, |
| 125 | /* custom timer */ |
| 126 | NSVC_TIMER_RESET, |
| 127 | }; |
| 128 | |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 129 | struct gprs_nsvc { |
| 130 | struct llist_head list; |
| 131 | struct gprs_ns_inst *nsi; |
| 132 | |
Harald Welte | eaa614c | 2010-05-02 11:26:34 +0200 | [diff] [blame] | 133 | uint16_t nsei; /* end-to-end significance */ |
| 134 | uint16_t nsvci; /* uniquely identifies NS-VC at SGSN */ |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 135 | |
Harald Welte | eaa614c | 2010-05-02 11:26:34 +0200 | [diff] [blame] | 136 | uint32_t state; |
| 137 | uint32_t remote_state; |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 138 | |
Harald Welte | 05b320a | 2010-05-03 20:16:13 +0200 | [diff] [blame^] | 139 | struct timer_list timer; |
| 140 | enum nsvc_timer_mode timer_mode; |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 141 | int alive_retries; |
| 142 | |
| 143 | int remote_end_is_sgsn; |
| 144 | |
| 145 | union { |
| 146 | struct { |
| 147 | struct sockaddr_in bts_addr; |
| 148 | } ip; |
| 149 | }; |
| 150 | }; |
| 151 | |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 152 | /* Create a new NS protocol instance */ |
| 153 | struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb); |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 154 | |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 155 | /* Destroy a NS protocol instance */ |
| 156 | void gprs_ns_destroy(struct gprs_ns_inst *nsi); |
| 157 | |
| 158 | /* Listen for incoming GPRS packets */ |
| 159 | int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); |
| 160 | |
| 161 | struct sockaddr_in; |
| 162 | |
| 163 | /* main entry point, here incoming NS frames enter */ |
| 164 | int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, |
| 165 | struct sockaddr_in *saddr); |
| 166 | |
| 167 | /* main function for higher layers (BSSGP) to send NS messages */ |
Harald Welte | 44f1c27 | 2010-04-30 19:54:29 +0200 | [diff] [blame] | 168 | int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg); |
Harald Welte | cb99163 | 2010-04-26 19:18:54 +0200 | [diff] [blame] | 169 | |
Harald Welte | 9f75c35 | 2010-04-30 20:26:32 +0200 | [diff] [blame] | 170 | |
| 171 | /* Listen for incoming GPRS packets */ |
| 172 | int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port); |
| 173 | |
| 174 | /* Establish a connection (from the BSS) to the SGSN */ |
| 175 | struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi, |
Harald Welte | b77c697 | 2010-05-01 11:28:43 +0200 | [diff] [blame] | 176 | struct sockaddr_in *dest, uint16_t nsei, |
| 177 | uint16_t nsvci); |
Harald Welte | 9b455bf | 2010-03-14 15:45:01 +0800 | [diff] [blame] | 178 | #endif |