pkt.h
6.73 KB
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
/*
* Copyright (C) 2014, 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
* 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup net_gnrc_pkt Packet
* @ingroup net_gnrc_pktbuf
* @brief Network packet abstraction type and helper functions
* @{
*
* @file
* @brief General definitions for network packets and their helper functions
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef GNRC_PKT_H_
#define GNRC_PKT_H_
#include <inttypes.h>
#include <stdlib.h>
#include "kernel_types.h"
#include "net/gnrc/nettype.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type to represent parts (either headers or payload) of a packet,
* called snips.
* @details The idea behind the packet snips is that they either can represent
* protocol-specific headers or payload. A packet can be comprised of
* multiple pktsnip_t elements.
*
* Example:
*
* buffer
* +---------------------------+ +------+
* | size = 14 | data +-------------->| |
* | type = NETTYPE_ETHERNET |------+ +------+
* +---------------------------+ . .
* | next . .
* v +------+
* +---------------------------+ +----------->| |
* | size = 40 | data | | |
* | type = NETTYPE_IPV6 |---------+ +------+
* +---------------------------+ . .
* | next . .
* v +------+
* +---------------------------+ +-------->| |
* | size = 8 | data | +------+
* | type = NETTYPE_UDP |------------+ . .
* +---------------------------+ . .
* | next +------+
* v +----->| |
* +---------------------------+ | | |
* | size = 59 | data | . .
* | type = NETTYPE_UNDEF |---------------+ . .
* +---------------------------+ . .
*
* To keep data duplication as low as possible the order of the snips
* in a packet will be reversed depending on if you send the packet or if
* you received it. For sending the order is from (in the network stack) lowest
* protocol snip to the highest, for receiving the order is from highest
* snip to the lowest. This way, if a layer needs to duplicate the packet
* a tree is created rather than a duplication of the whole package.
*
* A very extreme example for this (we only expect one or two duplications at
* maximum per package) can be seen here:
*
* Sending Receiving
* ======= =========
*
* * Payload * L2 header
* ^ ^
* | |
* |\ |\
* | * L4 header 1 | * L2.5 header 1
* | * L3 header 1 | * L3 header 1
* | * netif header 1 | * L4 header 1
* * L4 header 2 | * Payload 1
* ^ * L3 header 2
* | ^
* |\ |
* | * L3 header 2 |\
* | * L2 header 2 | * L4 header 2
* * L2 header 3 | * Payload 2
* |\ * Payload 3
* | * L2 header 3
* * L2 header 4
*
* @note This type has no initializer on purpose. Please use @ref net_gnrc_pktbuf
* as factory.
*/
/* packed to be aligned correctly in the static packet buffer */
typedef struct gnrc_pktsnip {
/**
* @brief Counter of threads currently having control over this packet.
*
* @internal
*/
unsigned int users;
struct gnrc_pktsnip *next; /**< next snip in the packet */
void *data; /**< pointer to the data of the snip */
size_t size; /**< the length of the snip in byte */
gnrc_nettype_t type; /**< protocol of the packet snip */
#ifdef MODULE_GNRC_NETERR
kernel_pid_t err_sub; /**< subscriber to errors related to this
* packet snip */
#endif
} gnrc_pktsnip_t;
/**
* @brief Calculates length of a packet in byte.
*
* @param[in] pkt list of packet snips.
*
* @return length of the list of headers.
*/
static inline size_t gnrc_pkt_len(gnrc_pktsnip_t *pkt)
{
size_t len = 0;
while (pkt) {
len += pkt->size;
pkt = pkt->next;
}
return len;
}
/**
* @brief Calculates length of a packet in byte upto (including) a snip with the given type.
*
* @param[in] pkt list of packet snips.
* @param[in] type type of snip to stop calculation.
*
* @return length of the list of headers.
*/
static inline size_t gnrc_pkt_len_upto(gnrc_pktsnip_t *pkt, gnrc_nettype_t type)
{
size_t len = 0;
while (pkt) {
len += pkt->size;
if (pkt->type == type) {
break;
}
pkt = pkt->next;
}
return len;
}
/**
* @brief Count the numbers of snips in the given packet
*
* @param[in] pkt first snip in the packet
*
* @return number of snips in the given packet
*/
static inline size_t gnrc_pkt_count(const gnrc_pktsnip_t *pkt)
{
size_t count = 0;
while (pkt) {
++count;
pkt = pkt->next;
}
return count;
}
/**
* @brief Searches the packet for a packet snip of a specific type
*
* @param[in] pkt list of packet snips
* @param[in] type the type to search for
*
* @return the packet snip in @p pkt with @ref gnrc_nettype_t @p type
* @return NULL, if none of the snips in @p pkt is of @p type
*/
gnrc_pktsnip_t *gnrc_pktsnip_search_type(gnrc_pktsnip_t *pkt,
gnrc_nettype_t type);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_PKT_H_ */
/** @} */