packet.c 16.6 KB
Newer Older
1
2
3
4
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
5
#include <netinet/in.h>
Andreas Schmidt's avatar
Andreas Schmidt committed
6
#include <src/util/dbg.h>
7
#include <src/util/common.h>
Andreas Schmidt's avatar
Andreas Schmidt committed
8
#include "packet.h"
9

10
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet);
11

12
void *encode_data_header(void *buf_ptr, const void *payload);
13

14
void *encode_redundancy_header(void *buf_ptr, const void *payload);
15

16
void *encode_feedback_header(void *buf_ptr, const void *payload);
17

Andreas Schmidt's avatar
Andreas Schmidt committed
18
19
void *decode_data_header(void *buf_ptr, const void *payload_ptr);

20
21
void *decode_redundancy_header(void *buf_ptr, const void *payload_ptr);

22
void *decode_feedback_header(void *buf_ptr, const void *payload_ptr);
Andreas Schmidt's avatar
Andreas Schmidt committed
23

24
25
uint8_t PrrtPacket_type(PrrtPacket *packet_ptr)
{
26
27
28
    return (uint8_t) ((packet_ptr->type_priority >> 4) & 0x0F);
}

29
30
uint8_t PrrtPacket_priority(PrrtPacket *packet_ptr)
{
31
32
33
    return (uint8_t) (packet_ptr->type_priority & 0x0F);
}

34
35
uint16_t PrrtPacket_size(PrrtPacket *packet_ptr)
{
Andreas Schmidt's avatar
Andreas Schmidt committed
36
    return (uint16_t) (packet_ptr->payload_len + PRRT_PACKET_GENERAL_HEADER_SIZE);
37
38
}

39
40
int PrrtPacket_print(PrrtPacket *packet_ptr)
{
41
42
    printf(" 0                   1                   2                   3\n"
                   " 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n"
43
                   "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
44
    uint8_t type = PrrtPacket_type(packet_ptr);
45

46
47
    printf("| %5u | %5u | %13u | %29u |\n", type, PrrtPacket_priority(packet_ptr), packet_ptr->index,
           packet_ptr->seqno);
48
    printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
49

50
    if(type == PACKET_TYPE_DATA) {
51
        PrrtPacketDataPayload *payload = packet_ptr->payload;
52
53
54
55
        printf("| %61u |\n", payload->timestamp);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
        printf("| %29u | %29u |\n", payload->group_round_trip_time, payload->packet_timeout);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
56
57
        printf("| %29u | %29u |\n", payload->decoding_timeout, payload->feedback_timeout);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
58
59
        printf("| %61s |\n", (char *) (packet_ptr->payload + PRRT_PACKET_DATA_HEADER_SIZE));
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
60
    } else if(type == PACKET_TYPE_REDUNDANCY) {
61
62
63
        PrrtPacketRedundancyPayload *payload = packet_ptr->payload;
        printf("| %29u | %13u | %13u |\n", payload->base_seqno, payload->n, payload->k);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
64
    } else if(type == PACKET_TYPE_FEEDBACK) {
65
        PrrtPacketFeedbackPayload *payload = packet_ptr->payload;
66
        printf("| %61u |\n", payload->group_round_trip_time);
67
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
68
        printf("| %61u |\n", payload->forward_trip_time);
69
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
70
        printf("| %61u |\n", payload->packet_loss_rate);
71
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
72
        printf("| %29u | %29u |\n", payload->gap, payload->ngap);
73
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
74
        printf("| %29u | %29u |\n", payload->burst, payload->nburst);
75
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
76
        printf("| %61u |\n", payload->bandwidth_estimate);
77
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
78
79
        printf("| %61u |\n", payload->buffer_feedback);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
80
    } else {
81
82
        printf("| Unhandeled Type                                               |\n");
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
83
84
85
86
87
    }

    return 0;
}

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
PrrtPacket *PrrtPacket_copy(PrrtPacket *original)
{
    PrrtPacket *newPacket = calloc(1, sizeof(PrrtPacket));
    check_mem(newPacket);
    void *payload = calloc(1, original->payload_len);
    check_mem(payload);

    newPacket->payload = payload;
    newPacket->payload_len = original->payload_len;
    memcpy(newPacket->payload, original->payload, original->payload_len);

    newPacket->index = original->index;
    newPacket->seqno = original->seqno;
    newPacket->type_priority = original->type_priority;


    return newPacket;
    error:
    PERROR("Not enough memory for packet copies.");
}

int PrrtPacket_encode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr)
{
111
    void *payload = packet_ptr->payload;
112

113
    check(packet_ptr->payload_len + PRRT_PACKET_GENERAL_HEADER_SIZE <= buf_size, "Buffer too small.");
114

115
116
    buf_ptr = encode_general_header(buf_ptr, packet_ptr);

117
    uint8_t type = PrrtPacket_type(packet_ptr);
118
    if(type == PACKET_TYPE_DATA) {
119
        buf_ptr = encode_data_header(buf_ptr, payload);
120
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_DATA_HEADER_SIZE);
121
    } else if(type == PACKET_TYPE_REDUNDANCY) {
122
        buf_ptr = encode_redundancy_header(buf_ptr, payload);
123
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
124
    } else if(type == PACKET_TYPE_FEEDBACK) {
125
        buf_ptr = encode_feedback_header(buf_ptr, payload);
126
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_FEEDBACK_HEADER_SIZE);
127
128
129
130
131
    } else {
        perror("NOT IMPLEMENTED");
        return -1;
    }
    return 0;
132
133

    error:
134
    return -1;
135
136
}

137
138
void *encode_redundancy_header(void *buf_ptr, const void *payload)
{
139
    const PrrtPacketRedundancyPayload *redundancyPayload = payload;
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

    uint16_t *baseSeqNo = (uint16_t *) buf_ptr;
    *baseSeqNo = htons(redundancyPayload->base_seqno);
    buf_ptr += 2;

    uint8_t *n = (uint8_t *) buf_ptr;
    *n = redundancyPayload->n;
    buf_ptr += 1;

    uint8_t *k = (uint8_t *) buf_ptr;
    *k = redundancyPayload->k;
    buf_ptr += 1;

    return buf_ptr;
}

156
157
void *encode_feedback_header(void *buf_ptr, const void *payload)
{
158
    const PrrtPacketFeedbackPayload *feedbackPayload = payload;
159
160

    uint32_t *receiver_ip = (uint32_t *) buf_ptr;
161
    *receiver_ip = htonl(feedbackPayload->receiver_addr);
162
163
164
    buf_ptr += 4;

    uint32_t *group_round_trip_time = (uint32_t *) buf_ptr;
165
166
    *group_round_trip_time = htonl(feedbackPayload->group_round_trip_time);
    buf_ptr += 4;
167
168

    uint32_t *forward_trip_time = (uint32_t *) buf_ptr;
169
170
    *forward_trip_time = htonl(feedbackPayload->forward_trip_time);
    buf_ptr += 4;
171
172

    uint32_t *packet_loss_rate = (uint32_t *) buf_ptr;
173
174
    *packet_loss_rate = htonl(feedbackPayload->packet_loss_rate);
    buf_ptr += 4;
175
176

    uint16_t *gap = (uint16_t *) buf_ptr;
177
178
    *gap = htons(feedbackPayload->gap);
    buf_ptr += 2;
179
180

    uint16_t *ngap = (uint16_t *) buf_ptr;
181
182
    *ngap = htons(feedbackPayload->ngap);
    buf_ptr += 2;
183
184

    uint16_t *burst = (uint16_t *) buf_ptr;
185
186
    *burst = htons(feedbackPayload->burst);
    buf_ptr += 2;
187
188

    uint16_t *nburst = (uint16_t *) buf_ptr;
189
190
    *nburst = htons(feedbackPayload->nburst);
    buf_ptr += 2;
191
192

    uint32_t *bandwidth_estimate = (uint32_t *) buf_ptr;
193
194
    *bandwidth_estimate = htonl(feedbackPayload->bandwidth_estimate);
    buf_ptr += 4;
195
196

    uint32_t *buffer_feedback = (uint32_t *) buf_ptr;
197
198
    *buffer_feedback = htonl(feedbackPayload->buffer_feedback);
    buf_ptr += 4;
199
200
201
202

    return buf_ptr;
}

203
204
void *encode_data_header(void *buf_ptr, const void *payload)
{
205
    const PrrtPacketDataPayload *data_payload = payload;
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

    uint32_t *timestamp = (uint32_t *) buf_ptr;
    *timestamp = htonl(data_payload->timestamp);
    buf_ptr += 4;

    uint16_t *group_round_trip_time = (uint16_t *) buf_ptr;
    *group_round_trip_time = htons(data_payload->group_round_trip_time);
    buf_ptr += 2;

    uint16_t *packet_timeout = (uint16_t *) buf_ptr;
    *packet_timeout = htons(data_payload->packet_timeout);
    buf_ptr += 2;

    uint16_t *decoding_timeout = (uint16_t *) buf_ptr;
    *decoding_timeout = htons(data_payload->decoding_timeout);
    buf_ptr += 2;

    uint16_t *feedback_timeout = (uint16_t *) buf_ptr;
    *feedback_timeout = htons(data_payload->feedback_timeout);
    buf_ptr += 2;
    return buf_ptr;
}

229
230
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet)
{
231
    uint8_t *type_priority = (uint8_t *) buf_ptr;
232
233
    *type_priority = packet->type_priority;
    buf_ptr += 1;
234

235
    uint8_t *index = (uint8_t *) buf_ptr;
236
237
    *index = packet->index;
    buf_ptr += 1;
238

239
    uint16_t *seqno = (uint16_t *) buf_ptr;
240
241
    *seqno = htons(packet->seqno);
    buf_ptr += 2;
242

243
    return buf_ptr;
244
245
}

246
247
int PrrtPacket_decode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr)
{
248
    uint32_t payload_len = (uint32_t) (buf_size - PRRT_PACKET_GENERAL_HEADER_SIZE);
249
    packet_ptr->type_priority = *(uint8_t *) buf_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
250
    buf_ptr += 1;
251
    uint8_t *index_ptr = (uint8_t *) buf_ptr;
252
    packet_ptr->index = *index_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
253
    buf_ptr += 1;
254
    uint16_t *seqno_prt = (uint16_t *) buf_ptr;
255
    packet_ptr->seqno = ntohs(*seqno_prt);
Andreas Schmidt's avatar
Andreas Schmidt committed
256
    buf_ptr += 2;
257

Andreas Schmidt's avatar
Andreas Schmidt committed
258
    void *payload_buffer = calloc(1, payload_len);
259
260
    check_mem(payload_buffer);

Andreas Schmidt's avatar
Andreas Schmidt committed
261
262
    packet_ptr->payload = payload_buffer;
    packet_ptr->payload_len = payload_len;
263

264
    if(PrrtPacket_type(packet_ptr) == PACKET_TYPE_DATA) {
Andreas Schmidt's avatar
Andreas Schmidt committed
265
        buf_ptr = decode_data_header(buf_ptr, payload_buffer);
266
        PrrtPacket_copy_buffer_to_payload(packet_ptr, buf_ptr, PRRT_PACKET_DATA_HEADER_SIZE);
267
    } else if(PrrtPacket_type(packet_ptr)) {
268
        buf_ptr = decode_redundancy_header(buf_ptr, payload_buffer);
269
        PrrtPacket_copy_buffer_to_payload(packet_ptr, buf_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
270
    } else if(PrrtPacket_type(packet_ptr) == PACKET_TYPE_FEEDBACK) {
Andreas Schmidt's avatar
Andreas Schmidt committed
271
        buf_ptr = decode_feedback_header(buf_ptr, payload_buffer);
272
        PrrtPacket_copy_buffer_to_payload(packet_ptr, buf_ptr, PRRT_PACKET_FEEDBACK_HEADER_SIZE);
Andreas Schmidt's avatar
Andreas Schmidt committed
273
    } else {
274
        printf("NOT IMPLEMENTED\n");
Andreas Schmidt's avatar
Andreas Schmidt committed
275
276
    }
    return 0;
277
278

    error:
279
    return EXIT_FAILURE;
Andreas Schmidt's avatar
Andreas Schmidt committed
280
}
281

282
283
void *decode_redundancy_header(void *buf_ptr, const void *payload_ptr)
{
284
    PrrtPacketRedundancyPayload *redundancyPayload = (PrrtPacketRedundancyPayload *) payload_ptr;
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

    uint16_t *baseSeqNo = (uint16_t *) buf_ptr;
    redundancyPayload->base_seqno = ntohs(*baseSeqNo);
    buf_ptr += 2;

    uint8_t *n = (uint8_t *) buf_ptr;
    redundancyPayload->n = *n;
    buf_ptr += 1;

    uint8_t *k = (uint8_t *) buf_ptr;
    redundancyPayload->k = *k;
    buf_ptr += 1;

    return buf_ptr;
}

301
302
void *decode_feedback_header(void *buf_ptr, const void *payload_ptr)
{
303
    PrrtPacketFeedbackPayload *feedback_payload = (PrrtPacketFeedbackPayload *) payload_ptr;
304

Andreas Schmidt's avatar
Andreas Schmidt committed
305
306
307
    uint32_t *receiver_addr = (uint32_t *) buf_ptr;
    feedback_payload->receiver_addr = ntohl(*receiver_addr);
    buf_ptr += 4;
308

Andreas Schmidt's avatar
Andreas Schmidt committed
309
310
311
    uint32_t *group_round_trip_time = (uint32_t *) buf_ptr;
    feedback_payload->group_round_trip_time = ntohl(*group_round_trip_time);
    buf_ptr += 4;
312

Andreas Schmidt's avatar
Andreas Schmidt committed
313
314
315
    uint32_t *forward_trip_time = (uint32_t *) buf_ptr;
    feedback_payload->forward_trip_time = ntohl(*forward_trip_time);
    buf_ptr += 4;
316

Andreas Schmidt's avatar
Andreas Schmidt committed
317
318
319
    uint32_t *packet_loss_rate = (uint32_t *) buf_ptr;
    feedback_payload->packet_loss_rate = ntohl(*packet_loss_rate);
    buf_ptr += 4;
320

Andreas Schmidt's avatar
Andreas Schmidt committed
321
322
323
    uint16_t *gap = (uint16_t *) buf_ptr;
    feedback_payload->gap = ntohs(*gap);
    buf_ptr += 2;
324

Andreas Schmidt's avatar
Andreas Schmidt committed
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
    uint16_t *ngap = (uint16_t *) buf_ptr;
    feedback_payload->ngap = ntohs(*ngap);
    buf_ptr += 2;

    uint16_t *burst = (uint16_t *) buf_ptr;
    feedback_payload->burst = ntohs(*burst);
    buf_ptr += 2;

    uint16_t *nburst = (uint16_t *) buf_ptr;
    feedback_payload->nburst = ntohs(*nburst);
    buf_ptr += 2;

    uint32_t *bandwidth_estimate = (uint32_t *) buf_ptr;
    feedback_payload->bandwidth_estimate = ntohl(*bandwidth_estimate);
    buf_ptr += 4;

    uint32_t *buffer_feedback = (uint32_t *) buf_ptr;
    feedback_payload->buffer_feedback = ntohl(*buffer_feedback);
    buf_ptr += 4;

    return buf_ptr;
}

348
349
void *decode_data_header(void *buf_ptr, const void *payload_ptr)
{
350
    PrrtPacketDataPayload *data_payload = (PrrtPacketDataPayload *) payload_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

    uint32_t *timestamp = (uint32_t *) buf_ptr;
    data_payload->timestamp = ntohl(*timestamp);
    buf_ptr += 4;

    uint16_t *group_round_trip_time = (uint16_t *) buf_ptr;
    data_payload->group_round_trip_time = ntohs(*group_round_trip_time);
    buf_ptr += 2;

    uint16_t *packet_timeout = (uint16_t *) buf_ptr;
    data_payload->packet_timeout = ntohs(*packet_timeout);
    buf_ptr += 2;

    uint16_t *decoding_timeout = (uint16_t *) buf_ptr;
    data_payload->decoding_timeout = ntohs(*decoding_timeout);
    buf_ptr += 2;

    uint16_t *feedback_timeout = (uint16_t *) buf_ptr;
    data_payload->feedback_timeout = ntohs(*feedback_timeout);
    buf_ptr += 2;
    return buf_ptr;
372
373
}

374
375
376
int PrrtPacket_destroy(PrrtPacket *packet_ptr)
{
    if(packet_ptr->payload != NULL) {
377
378
379
        free(packet_ptr->payload);
    }
    free(packet_ptr);
380
381
382
    return 0;
}

383
int PrrtPacket_create_data_packet(PrrtPacket *packet_ptr, uint8_t priority, const void *data_ptr,
384
385
                                  uint32_t data_len, uint16_t seqno)
{
386
    uint32_t payload_length = (uint32_t) (data_len + PRRT_PACKET_DATA_HEADER_SIZE);
387

388
    packet_ptr->type_priority = PACKET_TYPE_DATA << 4;
389
    packet_ptr->type_priority |= priority & 0x0F;
390
    packet_ptr->index = 0;
391
    packet_ptr->seqno = seqno;
392

393
    void *content_buf = calloc(1, payload_length);
394
    check_mem(content_buf);
395

396
    PrrtPacketDataPayload *source_payload = content_buf;
397
398

    struct timeval tv;
399
    gettimeofday(&tv, NULL);
400
401
    unsigned long time_in_micros = (unsigned long) (1000000 * tv.tv_sec + tv.tv_usec);

402
    source_payload->timestamp = (uint32_t) time_in_micros;
403
404
405
406
    source_payload->group_round_trip_time = 95; // TODO: payload->rtt = CURRENT ESTIMATE
    source_payload->packet_timeout = 110; // TODO: payload->packet_timeout = NOW + maximum delay
    source_payload->decoding_timeout = 150; // TODO: payload->decoding_timeout
    source_payload->feedback_timeout = 170; // TODO: payload->feedback_timer
407

408
409
    packet_ptr->payload = content_buf;
    packet_ptr->payload_len = payload_length;
410
    PrrtPacket_copy_buffer_to_payload(packet_ptr, data_ptr, PRRT_PACKET_DATA_HEADER_SIZE)
411

412
    error:
413
    return -1;
414
415
}

416
PrrtPacket *PrrtPacket_create_redundancy_packet(uint8_t priority, void *data_ptr, uint32_t data_len,
417
                                                uint16_t seqno, uint8_t index, uint16_t base_seqno,
418
419
                                                PrrtCodingParams codingParams)
{
420
    uint32_t payload_length = (uint32_t) (data_len + PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
421

Andreas Schmidt's avatar
Andreas Schmidt committed
422
    PrrtPacket *packet_ptr = calloc(1, sizeof(PrrtPacket));
423
424
    check_mem(packet_ptr);

425
    packet_ptr->type_priority = PACKET_TYPE_REDUNDANCY << 4;
426
427
428
429
    packet_ptr->type_priority |= priority & 0x0F;
    packet_ptr->index = index;
    packet_ptr->seqno = seqno;

430
    void *content_buf = calloc(1, PRRT_PACKET_REDUNDANCY_HEADER_SIZE + data_len);
431
    check_mem(content_buf);
432
433
434
435

    PrrtPacketRedundancyPayload *redundancy_payload = content_buf;

    redundancy_payload->base_seqno = base_seqno;
436
437
    redundancy_payload->k = codingParams.k;
    redundancy_payload->n = codingParams.n;
438
439
440

    packet_ptr->payload = content_buf;
    packet_ptr->payload_len = payload_length;
441
    PrrtPacket_copy_buffer_to_payload(packet_ptr, data_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
442
443

    return packet_ptr;
444
445

    error:
446
    return NULL;
447
448
}

449
450
451
452
PrrtPacket *PrrtPacket_create_feedback_packet(uint8_t priority, uint8_t index, uint16_t seqno, uint32_t round_trip_time,
                                              uint32_t forward_trip_time, uint32_t packet_loss_rate, uint16_t gap,
                                              uint16_t ngap,
                                              uint16_t burst, uint16_t nburst, uint32_t bandwidth,
453
454
                                              uint32_t buffer_feedback)
{
Andreas Schmidt's avatar
Andreas Schmidt committed
455
    PrrtPacket *packet_ptr = calloc(1, sizeof(PrrtPacket));
456
    check_mem(packet_ptr);
457
458
459
460
    packet_ptr->type_priority = PACKET_TYPE_FEEDBACK << 4;
    packet_ptr->type_priority |= priority & 0x0F;
    packet_ptr->index = index;
    packet_ptr->seqno = seqno;
461

462
    PrrtPacketFeedbackPayload *payload = calloc(1, PRRT_PACKET_FEEDBACK_HEADER_SIZE);
463
    check_mem(payload);
464

465
466
    payload->group_round_trip_time = round_trip_time;
    payload->forward_trip_time = forward_trip_time;
467
    payload->packet_loss_rate = packet_loss_rate;
468
469
470
471
    payload->gap = gap;
    payload->ngap = ngap;
    payload->burst = burst;
    payload->nburst = nburst;
472
    payload->bandwidth_estimate = bandwidth;
473
    payload->buffer_feedback = buffer_feedback;
474

475
    packet_ptr->payload = (void *) payload;
476
    packet_ptr->payload_len = (uint32_t) (PRRT_PACKET_FEEDBACK_HEADER_SIZE);
477

478
    return packet_ptr;
479
480

    error:
481
    return NULL;
482
}