Blame view

RIOT/sys/include/net/gnrc/pkt.h 6.77 KB
a752c7ab   elopes   add first test an...
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 NET_GNRC_PKT_H
  #define NET_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 != NULL) {
          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 != NULL) {
          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 != NULL) {
          ++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 /* NET_GNRC_PKT_H */
  /** @} */