lib/ofpbuf: Remove 'l7' pointer.
[sliver-openvswitch.git] / lib / ofpbuf.h
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef OFPBUF_H
18 #define OFPBUF_H 1
19
20 #include <stddef.h>
21 #include <stdint.h>
22 #include "list.h"
23 #include "packets.h"
24 #include "util.h"
25
26 #ifdef  __cplusplus
27 extern "C" {
28 #endif
29
30 enum ofpbuf_source {
31     OFPBUF_MALLOC,              /* Obtained via malloc(). */
32     OFPBUF_STACK,               /* Un-movable stack space or static buffer. */
33     OFPBUF_STUB,                /* Starts on stack, may expand into heap. */
34     OFPBUF_DPDK,                /* buffer data is from DPDK allocated memory.
35                                    ref to build_ofpbuf() in netdev-dpdk. */
36 };
37
38 /* Buffer for holding arbitrary data.  An ofpbuf is automatically reallocated
39  * as necessary if it grows too large for the available memory. */
40 struct ofpbuf {
41     void *base;                 /* First byte of allocated space. */
42     size_t allocated;           /* Number of bytes allocated. */
43     enum ofpbuf_source source;  /* Source of memory allocated as 'base'. */
44
45     void *data;                 /* First byte actually in use. */
46     size_t size;                /* Number of bytes in use. */
47
48     void *l2;                   /* Link-level header. */
49     void *l2_5;                 /* MPLS label stack */
50     void *l3;                   /* Network-level header. */
51     void *l4;                   /* Transport-level header. */
52
53     struct list list_node;      /* Private list element for use by owner. */
54     void *private_p;            /* Private pointer for use by owner. */
55 };
56
57 void ofpbuf_use(struct ofpbuf *, void *, size_t);
58 void ofpbuf_use_stack(struct ofpbuf *, void *, size_t);
59 void ofpbuf_use_stub(struct ofpbuf *, void *, size_t);
60 void ofpbuf_use_const(struct ofpbuf *, const void *, size_t);
61
62 void ofpbuf_init(struct ofpbuf *, size_t);
63 void ofpbuf_uninit(struct ofpbuf *);
64 static inline void *ofpbuf_get_uninit_pointer(struct ofpbuf *);
65 void ofpbuf_reinit(struct ofpbuf *, size_t);
66
67 struct ofpbuf *ofpbuf_new(size_t);
68 struct ofpbuf *ofpbuf_new_with_headroom(size_t, size_t headroom);
69 struct ofpbuf *ofpbuf_clone(const struct ofpbuf *);
70 struct ofpbuf *ofpbuf_clone_with_headroom(const struct ofpbuf *,
71                                           size_t headroom);
72 struct ofpbuf *ofpbuf_clone_data(const void *, size_t);
73 struct ofpbuf *ofpbuf_clone_data_with_headroom(const void *, size_t,
74                                                size_t headroom);
75 static inline void ofpbuf_delete(struct ofpbuf *);
76
77 static inline void *ofpbuf_at(const struct ofpbuf *, size_t offset,
78                               size_t size);
79 static inline void *ofpbuf_at_assert(const struct ofpbuf *, size_t offset,
80                                      size_t size);
81 static inline void *ofpbuf_tail(const struct ofpbuf *);
82 static inline void *ofpbuf_end(const struct ofpbuf *);
83
84 void *ofpbuf_put_uninit(struct ofpbuf *, size_t);
85 void *ofpbuf_put_zeros(struct ofpbuf *, size_t);
86 void *ofpbuf_put(struct ofpbuf *, const void *, size_t);
87 char *ofpbuf_put_hex(struct ofpbuf *, const char *s, size_t *n);
88 void ofpbuf_reserve(struct ofpbuf *, size_t);
89 void ofpbuf_reserve_with_tailroom(struct ofpbuf *b, size_t headroom,
90                                   size_t tailroom);
91 void *ofpbuf_push_uninit(struct ofpbuf *b, size_t);
92 void *ofpbuf_push_zeros(struct ofpbuf *, size_t);
93 void *ofpbuf_push(struct ofpbuf *b, const void *, size_t);
94
95 static inline size_t ofpbuf_headroom(const struct ofpbuf *);
96 static inline size_t ofpbuf_tailroom(const struct ofpbuf *);
97 void ofpbuf_prealloc_headroom(struct ofpbuf *, size_t);
98 void ofpbuf_prealloc_tailroom(struct ofpbuf *, size_t);
99 void ofpbuf_trim(struct ofpbuf *);
100 void ofpbuf_padto(struct ofpbuf *, size_t);
101 void ofpbuf_shift(struct ofpbuf *, int);
102
103 static inline void ofpbuf_clear(struct ofpbuf *);
104 static inline void *ofpbuf_pull(struct ofpbuf *, size_t);
105 static inline void *ofpbuf_try_pull(struct ofpbuf *, size_t);
106
107 void *ofpbuf_steal_data(struct ofpbuf *);
108
109 char *ofpbuf_to_string(const struct ofpbuf *, size_t maxbytes);
110 static inline struct ofpbuf *ofpbuf_from_list(const struct list *);
111 void ofpbuf_list_delete(struct list *);
112 static inline bool ofpbuf_equal(const struct ofpbuf *, const struct ofpbuf *);
113
114 \f
115 /* Returns a pointer that may be passed to free() to accomplish the same thing
116  * as ofpbuf_uninit(b).  The return value is a null pointer if ofpbuf_uninit()
117  * would not free any memory. */
118 static inline void *ofpbuf_get_uninit_pointer(struct ofpbuf *b)
119 {
120     /* XXX: If 'source' is OFPBUF_DPDK memory gets leaked! */
121     return b && b->source == OFPBUF_MALLOC ? b->base : NULL;
122 }
123
124 /* Frees memory that 'b' points to, as well as 'b' itself. */
125 static inline void ofpbuf_delete(struct ofpbuf *b)
126 {
127     if (b) {
128         ofpbuf_uninit(b);
129         free(b);
130     }
131 }
132
133 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
134  * byte 'offset'.  Otherwise, returns a null pointer. */
135 static inline void *ofpbuf_at(const struct ofpbuf *b, size_t offset,
136                               size_t size)
137 {
138     return offset + size <= b->size ? (char *) b->data + offset : NULL;
139 }
140
141 /* Returns a pointer to byte 'offset' in 'b', which must contain at least
142  * 'offset + size' bytes of data. */
143 static inline void *ofpbuf_at_assert(const struct ofpbuf *b, size_t offset,
144                                      size_t size)
145 {
146     ovs_assert(offset + size <= b->size);
147     return ((char *) b->data) + offset;
148 }
149
150 /* Returns the byte following the last byte of data in use in 'b'. */
151 static inline void *ofpbuf_tail(const struct ofpbuf *b)
152 {
153     return (char *) b->data + b->size;
154 }
155
156 /* Returns the byte following the last byte allocated for use (but not
157  * necessarily in use) by 'b'. */
158 static inline void *ofpbuf_end(const struct ofpbuf *b)
159 {
160     return (char *) b->base + b->allocated;
161 }
162
163 /* Returns the number of bytes of headroom in 'b', that is, the number of bytes
164  * of unused space in ofpbuf 'b' before the data that is in use.  (Most
165  * commonly, the data in a ofpbuf is at its beginning, and thus the ofpbuf's
166  * headroom is 0.) */
167 static inline size_t ofpbuf_headroom(const struct ofpbuf *b)
168 {
169     return (char*)b->data - (char*)b->base;
170 }
171
172 /* Returns the number of bytes that may be appended to the tail end of ofpbuf
173  * 'b' before the ofpbuf must be reallocated. */
174 static inline size_t ofpbuf_tailroom(const struct ofpbuf *b)
175 {
176     return (char*)ofpbuf_end(b) - (char*)ofpbuf_tail(b);
177 }
178
179 /* Clears any data from 'b'. */
180 static inline void ofpbuf_clear(struct ofpbuf *b)
181 {
182     b->data = b->base;
183     b->size = 0;
184 }
185
186 /* Removes 'size' bytes from the head end of 'b', which must contain at least
187  * 'size' bytes of data.  Returns the first byte of data removed. */
188 static inline void *ofpbuf_pull(struct ofpbuf *b, size_t size)
189 {
190     void *data = b->data;
191     ovs_assert(b->size >= size);
192     b->data = (char*)b->data + size;
193     b->size -= size;
194     return data;
195 }
196
197 /* If 'b' has at least 'size' bytes of data, removes that many bytes from the
198  * head end of 'b' and returns the first byte removed.  Otherwise, returns a
199  * null pointer without modifying 'b'. */
200 static inline void *ofpbuf_try_pull(struct ofpbuf *b, size_t size)
201 {
202     return b->size >= size ? ofpbuf_pull(b, size) : NULL;
203 }
204
205 static inline struct ofpbuf *ofpbuf_from_list(const struct list *list)
206 {
207     return CONTAINER_OF(list, struct ofpbuf, list_node);
208 }
209
210 static inline bool ofpbuf_equal(const struct ofpbuf *a, const struct ofpbuf *b)
211 {
212     return a->size == b->size && memcmp(a->data, b->data, a->size) == 0;
213 }
214
215 static inline size_t ofpbuf_get_l4_size(const struct ofpbuf *b)
216 {
217     return b->l4 ? (const char *)ofpbuf_tail(b) - (const char *)b->l4 : 0;
218 }
219
220 static inline const void *ofpbuf_get_tcp_payload(const struct ofpbuf *b)
221 {
222     size_t l4_size = ofpbuf_get_l4_size(b);
223
224     if (OVS_LIKELY(l4_size >= TCP_HEADER_LEN)) {
225         struct tcp_header *tcp = b->l4;
226         int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
227
228         if (OVS_LIKELY(tcp_len >= TCP_HEADER_LEN && tcp_len <= l4_size)) {
229             return (const char *)tcp + tcp_len;
230         }
231     }
232     return NULL;
233 }
234
235 static inline const void *ofpbuf_get_udp_payload(const struct ofpbuf *b)
236 {
237     return OVS_LIKELY(ofpbuf_get_l4_size(b) >= UDP_HEADER_LEN)
238         ? (const char *)b->l4 + UDP_HEADER_LEN : NULL;
239 }
240
241 static inline const void *ofpbuf_get_sctp_payload(const struct ofpbuf *b)
242 {
243     return OVS_LIKELY(ofpbuf_get_l4_size(b) >= SCTP_HEADER_LEN)
244         ? (const char *)b->l4 + SCTP_HEADER_LEN : NULL;
245 }
246
247 static inline const void *ofpbuf_get_icmp_payload(const struct ofpbuf *b)
248 {
249     return OVS_LIKELY(ofpbuf_get_l4_size(b) >= ICMP_HEADER_LEN)
250         ? (const char *)b->l4 + ICMP_HEADER_LEN : NULL;
251 }
252
253 #ifdef  __cplusplus
254 }
255 #endif
256
257 #endif /* ofpbuf.h */