Skip to content

Commit 54191c8

Browse files
authored
Merge pull request #813 from ZettaScaleLabs/feat/fragment_marker
feat: support start/stop fragment marker
2 parents b63ffa3 + 9320775 commit 54191c8

File tree

17 files changed

+293
-35
lines changed

17 files changed

+293
-35
lines changed

include/zenoh-pico/protocol/definitions/transport.h

+21-4
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ extern "C" {
9191
// Z Extensions if Z==1 then Zenoh extensions are present
9292
#define _Z_FLAG_T_CLOSE_S 0x20 // 1 << 5
9393

94+
/*=============================*/
95+
/* Patch */
96+
/*=============================*/
97+
/// Used to negotiate the patch version of the protocol
98+
/// if not present (or 0), then protocol as released with 1.0.0
99+
/// if >= 1, then fragmentation start/stop marker
100+
#define _Z_NO_PATCH 0x00
101+
#define _Z_CURRENT_PATCH 0x01
102+
#define _Z_PATCH_HAS_FRAGMENT_MARKERS(patch) (patch >= 1)
103+
94104
/*=============================*/
95105
/* Transport Messages */
96106
/*=============================*/
@@ -235,6 +245,9 @@ typedef struct {
235245
uint8_t _req_id_res;
236246
uint8_t _seq_num_res;
237247
uint8_t _version;
248+
#if Z_FEATURE_FRAGMENTATION == 1
249+
uint8_t _patch;
250+
#endif
238251
} _z_t_msg_join_t;
239252
void _z_t_msg_join_clear(_z_t_msg_join_t *msg);
240253

@@ -315,6 +328,9 @@ typedef struct {
315328
uint8_t _req_id_res;
316329
uint8_t _seq_num_res;
317330
uint8_t _version;
331+
#if Z_FEATURE_FRAGMENTATION == 1
332+
uint8_t _patch;
333+
#endif
318334
} _z_t_msg_init_t;
319335
void _z_t_msg_init_clear(_z_t_msg_init_t *msg);
320336

@@ -478,11 +494,11 @@ void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg);
478494
typedef struct {
479495
_z_slice_t _payload;
480496
_z_zint_t _sn;
497+
bool first;
498+
bool drop;
481499
} _z_t_msg_fragment_t;
482500
void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg);
483501

484-
#define _Z_FRAGMENT_HEADER_SIZE 12
485-
486502
/*------------------ Transport Message ------------------*/
487503
typedef union {
488504
_z_t_msg_join_t _join;
@@ -514,9 +530,10 @@ _z_transport_message_t _z_t_msg_make_keep_alive(void);
514530
_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages,
515531
z_reliability_t reliability);
516532
_z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t reliability);
517-
_z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, z_reliability_t reliability, bool is_last);
533+
_z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, z_reliability_t reliability, bool is_last,
534+
bool first, bool drop);
518535
_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_slice_t messages, z_reliability_t reliability,
519-
bool is_last);
536+
bool is_last, bool first, bool drop);
520537

521538
/*------------------ Copy ------------------*/
522539
void _z_t_msg_copy(_z_transport_message_t *clone, _z_transport_message_t *msg);

include/zenoh-pico/protocol/ext.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ extern "C" {
4343
/*=============================*/
4444
/* Extension IDs */
4545
/*=============================*/
46-
// #define _Z_MSG_EXT_ID_FOO 0x00 // Hex(ENC|M|ID)
46+
#define _Z_MSG_EXT_ID_JOIN_QOS (0x01 | _Z_MSG_EXT_FLAG_M | _Z_MSG_EXT_ENC_ZBUF)
47+
#define _Z_MSG_EXT_ID_JOIN_PATCH (0x07 | _Z_MSG_EXT_ENC_ZINT)
48+
#define _Z_MSG_EXT_ID_INIT_PATCH (0x07 | _Z_MSG_EXT_ENC_ZINT)
49+
#define _Z_MSG_EXT_ID_FRAGMENT_FIRST (0x02 | _Z_MSG_EXT_ENC_UNIT)
50+
#define _Z_MSG_EXT_ID_FRAGMENT_DROP (0x03 | _Z_MSG_EXT_ENC_UNIT)
4751

4852
/*=============================*/
4953
/* Extension Encodings */
@@ -58,6 +62,7 @@ extern "C" {
5862
#define _Z_MSG_EXT_FLAG_M 0x10
5963
#define _Z_MSG_EXT_IS_MANDATORY(h) ((h & _Z_MSG_EXT_FLAG_M) != 0)
6064
#define _Z_MSG_EXT_FLAG_Z 0x80
65+
#define _Z_MSG_EXT_MORE(more) (more ? _Z_MSG_EXT_FLAG_Z : 0)
6166

6267
typedef struct {
6368
uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior

include/zenoh-pico/transport/common/tx.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ void __unsafe_z_prepare_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability);
2727
void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability);
2828
/*This function is unsafe because it operates in potentially concurrent
2929
data.*Make sure that the following mutexes are locked before calling this function : *-ztu->mutex_tx */
30-
z_result_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn);
30+
z_result_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn,
31+
bool first);
3132

3233
/*------------------ Transmission and Reception helpers ------------------*/
3334
z_result_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg);

include/zenoh-pico/transport/transport.h

+13
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ typedef struct {
4747

4848
uint16_t _peer_id;
4949
volatile bool _received;
50+
51+
#if Z_FEATURE_FRAGMENTATION == 1
52+
// Patch
53+
uint8_t _patch;
54+
#endif
5055
} _z_transport_peer_entry_t;
5156

5257
size_t _z_transport_peer_entry_size(const _z_transport_peer_entry_t *src);
@@ -108,6 +113,11 @@ typedef struct {
108113

109114
volatile bool _received;
110115
volatile bool _transmitted;
116+
117+
#if Z_FEATURE_FRAGMENTATION == 1
118+
// Patch
119+
uint8_t _patch;
120+
#endif
111121
} _z_transport_unicast_t;
112122

113123
typedef struct _z_transport_multicast_t {
@@ -175,6 +185,9 @@ typedef struct {
175185
uint8_t _req_id_res;
176186
uint8_t _seq_num_res;
177187
bool _is_qos;
188+
#if Z_FEATURE_FRAGMENTATION == 1
189+
uint8_t _patch;
190+
#endif
178191
} _z_transport_unicast_establish_param_t;
179192

180193
typedef struct {

include/zenoh-pico/transport/utils.h

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ _z_zint_t _z_sn_max(uint8_t bits);
2929
_z_zint_t _z_sn_half(_z_zint_t sn);
3030
_z_zint_t _z_sn_modulo_mask(uint8_t bits);
3131
bool _z_sn_precedes(const _z_zint_t sn_resolution, const _z_zint_t sn_left, const _z_zint_t sn_right);
32+
bool _z_sn_consecutive(const _z_zint_t sn_resolution, const _z_zint_t sn_left, const _z_zint_t sn_right);
3233
_z_zint_t _z_sn_increment(const _z_zint_t sn_resolution, const _z_zint_t sn);
3334
_z_zint_t _z_sn_decrement(const _z_zint_t sn_resolution, const _z_zint_t sn);
3435

src/protocol/codec/transport.c

+84-9
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,14 @@ z_result_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t
6464
}
6565
_Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_next_sn._val._plain._reliable));
6666
_Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_next_sn._val._plain._best_effort));
67+
#if Z_FEATURE_FRAGMENTATION == 1
68+
bool has_patch = msg->_patch != _Z_NO_PATCH;
69+
#else
70+
bool has_patch = false;
71+
#endif
6772
if (msg->_next_sn._is_qos) {
6873
if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) {
69-
_Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 1));
74+
_Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ID_JOIN_QOS | _Z_MSG_EXT_MORE(has_patch)));
7075
size_t len = 0;
7176
for (uint8_t i = 0; (i < Z_PRIORITIES_NUM) && (ret == _Z_RES_OK); i++) {
7277
len += _z_zint_len(msg->_next_sn._val._qos[i]._reliable) +
@@ -82,21 +87,35 @@ z_result_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t
8287
ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED;
8388
}
8489
}
90+
#if Z_FEATURE_FRAGMENTATION == 1
91+
if (has_patch) {
92+
if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) {
93+
_Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ID_JOIN_PATCH));
94+
_Z_RETURN_IF_ERR(_z_zint64_encode(wbf, msg->_patch));
95+
} else {
96+
_Z_DEBUG("Attempted to serialize Patch extension, but the header extension flag was unset");
97+
ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED;
98+
}
99+
}
100+
#endif
85101

86102
return ret;
87103
}
88104

89105
z_result_t _z_join_decode_ext(_z_msg_ext_t *extension, void *ctx) {
90106
z_result_t ret = _Z_RES_OK;
91107
_z_t_msg_join_t *msg = (_z_t_msg_join_t *)ctx;
92-
if (_Z_EXT_FULL_ID(extension->_header) ==
93-
(_Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 1)) { // QOS: (enc=zbuf)(mandatory=true)(id=1)
108+
if (_Z_EXT_FULL_ID(extension->_header) == _Z_MSG_EXT_ID_JOIN_QOS) {
94109
msg->_next_sn._is_qos = true;
95110
_z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val);
96111
for (int i = 0; (ret == _Z_RES_OK) && (i < Z_PRIORITIES_NUM); ++i) {
97112
ret |= _z_zsize_decode(&msg->_next_sn._val._qos[i]._reliable, &zbf);
98113
ret |= _z_zsize_decode(&msg->_next_sn._val._qos[i]._best_effort, &zbf);
99114
}
115+
#if Z_FEATURE_FRAGMENTATION == 1
116+
} else if (_Z_EXT_FULL_ID(extension->_header) == _Z_MSG_EXT_ID_JOIN_PATCH) {
117+
msg->_patch = (uint8_t)extension->_body._zint._val;
118+
#endif
100119
} else if (_Z_MSG_EXT_IS_MANDATORY(extension->_header)) {
101120
ret = _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN;
102121
}
@@ -147,6 +166,7 @@ z_result_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header)
147166
ret |= _z_zsize_decode(&msg->_next_sn._val._plain._reliable, zbf);
148167
ret |= _z_zsize_decode(&msg->_next_sn._val._plain._best_effort, zbf);
149168
}
169+
msg->_patch = _Z_NO_PATCH;
150170
if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_T_Z)) {
151171
ret |= _z_msg_ext_decode_iter(zbf, _z_join_decode_ext, msg);
152172
}
@@ -180,6 +200,32 @@ z_result_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t
180200
_Z_RETURN_IF_ERR(_z_slice_encode(wbf, &msg->_cookie))
181201
}
182202

203+
#if Z_FEATURE_FRAGMENTATION == 1
204+
if (msg->_patch != _Z_NO_PATCH) {
205+
if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) {
206+
_Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ID_JOIN_PATCH));
207+
_Z_RETURN_IF_ERR(_z_zint64_encode(wbf, msg->_patch));
208+
} else {
209+
_Z_DEBUG("Attempted to serialize Patch extension, but the header extension flag was unset");
210+
ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED;
211+
}
212+
}
213+
#endif
214+
215+
return ret;
216+
}
217+
218+
z_result_t _z_init_decode_ext(_z_msg_ext_t *extension, void *ctx) {
219+
z_result_t ret = _Z_RES_OK;
220+
_z_t_msg_init_t *msg = (_z_t_msg_init_t *)ctx;
221+
if (false) {
222+
#if Z_FEATURE_FRAGMENTATION == 1
223+
} else if (_Z_EXT_FULL_ID(extension->_header) == _Z_MSG_EXT_ID_INIT_PATCH) {
224+
msg->_patch = (uint8_t)extension->_body._zint._val;
225+
#endif
226+
} else if (_Z_MSG_EXT_IS_MANDATORY(extension->_header)) {
227+
ret = _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN;
228+
}
183229
return ret;
184230
}
185231

@@ -222,8 +268,9 @@ z_result_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header)
222268
msg->_cookie = _z_slice_empty();
223269
}
224270

225-
if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) {
226-
ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x01);
271+
msg->_patch = _Z_NO_PATCH;
272+
if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_T_Z)) {
273+
ret |= _z_msg_ext_decode_iter(zbf, _z_init_decode_ext, msg);
227274
}
228275

229276
return ret;
@@ -388,25 +435,53 @@ z_result_t _z_fragment_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_fra
388435
z_result_t ret = _Z_RES_OK;
389436
_Z_DEBUG("Encoding _Z_TRANSPORT_FRAGMENT");
390437
_Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_sn))
391-
if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) {
392-
ret = _Z_ERR_MESSAGE_SERIALIZATION_FAILED;
438+
if (msg->first) {
439+
if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true) {
440+
_Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ID_FRAGMENT_FIRST | _Z_MSG_EXT_MORE(msg->drop)));
441+
} else {
442+
_Z_DEBUG("Attempted to serialize Start extension, but the header extension flag was unset");
443+
ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED;
444+
}
445+
}
446+
if (msg->drop) {
447+
if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true) {
448+
_Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ID_FRAGMENT_DROP));
449+
} else {
450+
_Z_DEBUG("Attempted to serialize Stop extension, but the header extension flag was unset");
451+
ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED;
452+
}
393453
}
394-
if (ret == _Z_RES_OK && _z_slice_check(&msg->_payload)) {
454+
if (_z_slice_check(&msg->_payload)) {
395455
_Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, msg->_payload.start, 0, msg->_payload.len));
396456
}
397457

398458
return ret;
399459
}
400460

461+
z_result_t _z_fragment_decode_ext(_z_msg_ext_t *extension, void *ctx) {
462+
z_result_t ret = _Z_RES_OK;
463+
_z_t_msg_fragment_t *msg = (_z_t_msg_fragment_t *)ctx;
464+
if (_Z_EXT_FULL_ID(extension->_header) == _Z_MSG_EXT_ID_FRAGMENT_FIRST) {
465+
msg->first = true;
466+
} else if (_Z_EXT_FULL_ID(extension->_header) == _Z_MSG_EXT_ID_FRAGMENT_DROP) {
467+
msg->drop = true;
468+
} else if (_Z_MSG_EXT_IS_MANDATORY(extension->_header)) {
469+
ret = _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN;
470+
}
471+
return ret;
472+
}
473+
401474
z_result_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t header) {
402475
z_result_t ret = _Z_RES_OK;
403476
*msg = (_z_t_msg_fragment_t){0};
404477

405478
_Z_DEBUG("Decoding _Z_TRANSPORT_FRAGMENT");
406479
ret |= _z_zsize_decode(&msg->_sn, zbf);
407480

481+
msg->first = false;
482+
msg->drop = false;
408483
if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) {
409-
ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x05);
484+
ret |= _z_msg_ext_decode_iter(zbf, _z_fragment_decode_ext, msg);
410485
}
411486

412487
_z_slice_t slice = _z_slice_alias_buf((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf));

0 commit comments

Comments
 (0)