-
Notifications
You must be signed in to change notification settings - Fork 9
/
schc.h
executable file
·278 lines (249 loc) · 6.7 KB
/
schc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#ifndef __SCHC_H__
#define __SCHC_H__
#include "schc_config.h"
// protocol definitions
#define UDP_HLEN 8
#define IP6_HLEN 40
// UDP can only be used in conjunction with IPv6
#define USE_UDP USE_IP6_UDP
#define USE_IP6 USE_IP6_UDP
#define NUMBER_OF_LAYERS USE_COAP + USE_UDP + USE_IP6
/* fixed fragmentation definitions */
#define MIC_C_SIZE_BITS 1
/* maximum number of bytes a rule id can take */
#define RULE_SIZE_BYTES 4
/* maximum number of bytes the ACK DTAG field can be */
#define DTAG_SIZE_BYTES 1
/* maximum number of bytes the ACK W field can be */
#define WINDOW_SIZE_BYTES 1
/* maximum number of bytes the RCS field can be */
#define MAX_RCS_SIZE_BYTES 4
typedef struct schc_bitarray_t {
uint8_t* ptr;
uint32_t offset; // in bits
uint8_t padding;
uint16_t len; // in bytes
uint32_t bit_len;
} schc_bitarray_t;
#define SCHC_DEFAULT_BIT_ARRAY(_len, _ptr) \
{ \
.ptr = (_ptr), \
.offset = 0, \
.padding = 0, \
.len = (_len), \
.bit_len = (_len * 8), \
}
typedef enum {
COAP_IFMATCH = 1,
COAP_URIHOST = 3,
COAP_ETAG = 4,
COAP_IFNOMATCH = 5,
COAP_URIPORT = 7,
COAP_LOCPATH = 8,
COAP_URIPATH = 11,
COAP_CONTENTF = 12,
COAP_MAXAGE = 14,
COAP_URIQUERY = 15,
COAP_ACCEPT = 17,
COAP_LOCQUERY = 20,
COAP_PROXYURI = 35,
COAP_PROXYSCH = 39,
COAP_SIZE1 = 60,
COAP_NORESP = 258,
COAP_OPTIONS_MAX = 259 /* set this to the largest CoAP option value + 1 */
} COAPO_fields;
typedef enum {
IP6_V = 1024, /* this must be larger than the largest CoAP Option Value in order not to interfere with it */
IP6_TC,
IP6_FL,
IP6_LEN,
IP6_NH,
IP6_HL,
IP6_DEVPRE,
IP6_DEVIID,
IP6_APPPRE,
IP6_APPIID,
UDP_DEV,
UDP_APP,
UDP_LEN,
UDP_CHK,
COAP_V,
COAP_T,
COAP_TKL,
COAP_C,
COAP_MID,
COAP_TKN,
COAP_PAYLOAD
} schc_header_fields;
static const char * const schc_header_field_names[] = {
[IP6_V] = "IPv6 Version",
[IP6_TC] = "IPv6 Traffic Class",
[IP6_FL] = "IPv6 Field Length",
[IP6_LEN] = "IPv6 Length",
[IP6_NH] = "IPv6 Next Header",
[IP6_HL] = "IPv6 Hop Limit",
[IP6_DEVPRE] = "IPv6 Device Prefix",
[IP6_DEVIID] = "IPv6 Device IID",
[IP6_APPPRE] = "IPv6 Application Prefix",
[IP6_APPIID] = "IPv6 Application IID",
[UDP_DEV] = "UDP Device Port",
[UDP_APP] = "UDP Application Port",
[UDP_LEN] = "UDP Length",
[UDP_CHK] = "UDP Checksum",
[COAP_V] = "CoAP Version",
[COAP_T] = "CoAP Type",
[COAP_TKL] = "CoAP Token Length",
[COAP_C] = "CoAP Code",
[COAP_MID] = "CoAP Message ID",
[COAP_TKN] = "CoAP Token",
[COAP_PAYLOAD] = "CoAP Payload Marker"
};
typedef enum {
UP = 0, DOWN = 1, BI = 2
} direction;
typedef enum {
NOTSENT = 0,
VALUESENT = 1,
MAPPINGSENT = 2,
LSB = 3,
COMPLENGTH = 4,
COMPCHK = 5,
DEVIID = 6,
APPIID = 7
} CDA;
typedef enum {
SCHC_IPV6 = 0,
SCHC_UDP = 1,
SCHC_COAP = 2
} schc_layer_t;
typedef enum {
ACK_ALWAYS = 1, ACK_ON_ERROR = 2, NO_ACK = 3, NOT_FRAGMENTED = 4, MAX_RELIABILITY_MODES
} reliability_mode;
struct schc_field {
uint16_t field;
uint8_t MO_param_length; // indicate number of bits for MSB and LSB or list length for MATCH-MAP
uint8_t field_length; // in bits
uint8_t field_pos;
direction dir;
unsigned char target_value[MAX_FIELD_LENGTH];
uint8_t (*MO)(struct schc_field* target_field, unsigned char* field_value, uint16_t field_offset);
CDA action;
};
// specific protocol layer structure
#if USE_IP6 == 1
struct schc_ipv6_rule_t {
uint8_t up;
uint8_t down;
uint8_t length;
struct schc_field content[IP6_FIELDS];
};
#endif
#if USE_UDP == 1
struct schc_udp_rule_t {
uint8_t up;
uint8_t down;
uint8_t length;
struct schc_field content[UDP_FIELDS];
};
#endif
#if USE_COAP == 1
struct schc_coap_rule_t {
uint8_t up;
uint8_t down;
uint8_t length;
struct schc_field content[COAP_FIELDS];
};
#endif
// structure to allow generic compression of each layer
struct schc_layer_rule_t {
uint8_t up;
uint8_t down;
uint8_t length;
struct schc_field content[];
};
struct schc_compression_rule_t {
/* the rule id, can be maximum 4 bytes wide, defined by the profile */
uint32_t rule_id;
#if USE_IP6 == 1
/* a pointer to the IPv6 rule */
const struct schc_ipv6_rule_t* ipv6_rule;
#endif
#if USE_UDP == 1
/* a pointer to the UDP rule */
const struct schc_udp_rule_t* udp_rule;
#endif
#if USE_COAP == 1
/* a pointer to the CoAP rule */
const struct schc_coap_rule_t* coap_rule;
#endif
};
struct schc_fragmentation_rule_t {
/* the rule id, can be maximum 4 bytes wide, defined by the profile */
uint32_t rule_id;
/* the reliability mode */
reliability_mode mode;
/* the direction */
direction dir;
/* the fcn size in bits */
uint8_t FCN_SIZE;
/* the maximum number of fragments per window */
uint8_t MAX_WND_FCN;
/* the window size in bits */
uint8_t WINDOW_SIZE;
/* the tile size in bytes; required when using ACK_ON_ERR */
uint16_t tile_size;
/* the inactivity timer expiration time in ms */
uint32_t inactivity_timer_ms;
/* the retransmission timer expiration time in ms */
uint32_t retransmission_timer_ms;
/* the RCS size in bytes */
uint8_t RCS_SIZE_BYTES;
};
struct schc_profile_t {
/* the rule id size in bits */
uint8_t RULE_ID_SIZE;
/* the uncompressed rule id */
uint8_t UNCOMPRESSED_RULE_ID;
/* the dtag size in bits */
uint8_t DTAG_SIZE;
};
struct schc_device {
/* the device id (e.g. EUI) */
uint32_t device_id;
/* the rule id to use when a packet remains uncompressed */
uint32_t uncomp_rule_id;
/* the total number of compression rules for a device */
uint8_t compression_rule_count;
/* a pointer to the collection of compression rules for a device */
const struct schc_compression_rule_t *(*compression_context)[];
/* the total number of fragmentation rules for a device */
uint8_t fragmentation_rule_count;
/* a pointer to the collection of compression rules for a device */
const struct schc_fragmentation_rule_t *(*fragmentation_context)[];
/* a pointer to the device profile */
const struct schc_profile_t* profile;
};
typedef uint8_t schc_ip6addr_t[16];
typedef schc_ip6addr_t schc_ipaddr_t;
struct schc_udpip_hdr {
/* IPv6 header. */
uint8_t vtc,
tcf;
uint16_t flow;
uint8_t len[2];
uint8_t proto, ttl;
schc_ip6addr_t srcipaddr, destipaddr;
/* UDP header. */
uint16_t srcport,
destport;
uint16_t udplen;
uint16_t udpchksum;
};
uint8_t mo_equal(struct schc_field* target_field, unsigned char* field_value, uint16_t field_offset);
uint8_t mo_ignore(struct schc_field* target_field, unsigned char* field_value, uint16_t field_offset);
uint8_t mo_MSB(struct schc_field* target_field, unsigned char* field_value, uint16_t field_offset);
uint8_t mo_matchmap(struct schc_field* target_field, unsigned char* field_value, uint16_t field_offset);
struct schc_device* get_device_by_id(uint32_t device_id);
void uint32_rule_id_to_uint8_buf(uint32_t rule_id, uint8_t* out, uint8_t len);
uint8_t rm_revise_rule_context(void);
#endif