xorp

buffer.h

00001 /* -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- */
00002 /* vim:set sts=4 ts=8: */
00003 
00004 /*
00005  * Copyright (c) 2001-2011 XORP, Inc and Others
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License, Version 2, June
00009  * 1991 as published by the Free Software Foundation. Redistribution
00010  * and/or modification of this program under the terms of any other
00011  * version of the GNU General Public License is not permitted.
00012  * 
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016  * see the GNU General Public License, Version 2, a copy of which can be
00017  * found in the XORP LICENSE.gpl file.
00018  * 
00019  * XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020  * http://xorp.net
00021  */
00022 
00023 
00024 #ifndef __MRT_BUFFER_H__
00025 #define __MRT_BUFFER_H__
00026 
00027 
00028 /*
00029  * Buffer management header file.
00030  */
00031 
00032 
00033 #include "netstream_access.h"
00034 
00035 
00036 /*
00037  * Constants definitions
00038  */
00039 #ifndef BUF_SIZE_DEFAULT
00040 #define BUF_SIZE_DEFAULT (64*1024)
00041 #endif
00042 
00043 /*
00044  * Structures, typedefs and macros
00045  */
00046 typedef struct buffer_ {
00047     uint8_t *_data;     /* The real data stream              */
00048     uint8_t *_data_head;    /* The head of the data on the stream        */
00049     uint8_t *_data_tail;    /* The tail of the data on the stream
00050                  * (actually, the first unused octet after the
00051                  * real data on the stream).
00052                  */
00053     size_t _buffer_size;    /* The allocated buffer size for the data    */
00054 } buffer_t;
00055 
00056 #define BUFFER_DATA_HEAD(buffer)    ((buffer)->_data_head)
00057 #define BUFFER_DATA_TAIL(buffer)    ((buffer)->_data_tail)
00058 #define BUFFER_DATA_SIZE(buffer)    ((size_t)((buffer)->_data_tail        \
00059                         - (buffer)->_data_head))
00060 #define BUFFER_AVAIL_HEAD(buffer)   ((size_t)((buffer)->_data_head        \
00061                         - (buffer)->_data))
00062 #define BUFFER_AVAIL_TAIL(buffer)   ((size_t)((buffer)->_data         \
00063                         + (buffer)->_buffer_size      \
00064                         - (buffer)->_data_tail))
00065 #define BUFFER_RESET_TAIL(buffer)                         \
00066 do {                                          \
00067     (buffer)->_data_tail = (buffer)->_data_head;                  \
00068 } while (0)
00069 
00070 #define BUFFER_COPYPUT_INET_CKSUM(cksum, buffer, offset)              \
00071 do {                                          \
00072     BUFFER_COPYPUT_DATA_OFFSET(&(cksum), (buffer), (offset), 2);          \
00073 } while (0)
00074 
00075 #define BUFFER_COPY(buffer_from, buffer_to)                   \
00076 do {                                          \
00077     size_t buffer_data_size_;                         \
00078                                           \
00079     buffer_data_size_ = BUFFER_DATA_SIZE(buffer_from);            \
00080     BUFFER_RESET(buffer_to);                          \
00081     BUFFER_PUT_DATA(BUFFER_DATA_HEAD(buffer_from),                \
00082             (buffer_to),                          \
00083             buffer_data_size_);                   \
00084 } while (0)
00085 
00086 #define BUFFER_COMPARE(buffer1, buffer2)                      \
00087     ((BUFFER_DATA_SIZE(buffer1) == BUFFER_DATA_SIZE(buffer2)) ?       \
00088      memcmp(BUFFER_DATA_HEAD(buffer1), BUFFER_DATA_HEAD(buffer2),         \
00089         BUFFER_DATA_SIZE(buffer1))                    \
00090      : ((BUFFER_DATA_SIZE(buffer1) < BUFFER_DATA_SIZE(buffer2)) ? -1 : 1))
00091 
00092 #define BUFFER_COPYGET_DATA(to, buffer, datalen)                  \
00093 do {                                          \
00094     size_t rcvlen_;                               \
00095     uint8_t *cp_;                                 \
00096                                           \
00097     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00098     cp_ = BUFFER_DATA_HEAD(buffer);                       \
00099     GET_DATA((to), cp_, rcvlen_, (datalen));                  \
00100 } while (0)
00101 #define BUFFER_COPYPUT_DATA(from, buffer, datalen)                \
00102 do {                                          \
00103     size_t buflen_;                               \
00104     uint8_t *cp_;                                 \
00105                                           \
00106     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00107     cp_ = BUFFER_DATA_TAIL(buffer);                       \
00108     PUT_DATA((from), cp_, buflen_, (datalen));                \
00109 } while (0)
00110 #define BUFFER_COPYGET_DATA_OFFSET(to, buffer, offset, datalen)           \
00111 do {                                          \
00112     size_t rcvlen_;                               \
00113     uint8_t *cp_;                                 \
00114                                           \
00115     if (BUFFER_DATA_SIZE(buffer) < (offset))                  \
00116         goto rcvlen_error;                        \
00117     rcvlen_ = BUFFER_DATA_SIZE(buffer) - (offset);                \
00118     cp_ = BUFFER_DATA_HEAD(buffer) + (offset);                \
00119     GET_DATA((to), cp_, rcvlen_, (datalen));                  \
00120 } while (0)
00121 #define BUFFER_COPYPUT_DATA_OFFSET(from, buffer, offset, datalen)         \
00122 do {                                          \
00123     size_t buflen_;                               \
00124     uint8_t *cp_;                                 \
00125                                           \
00126     if (BUFFER_DATA_SIZE(buffer) + BUFFER_AVAIL_TAIL(buffer) < (offset))  \
00127         goto buflen_error;                        \
00128     buflen_ = BUFFER_DATA_SIZE(buffer) + BUFFER_AVAIL_TAIL(buffer)        \
00129             - (offset);                       \
00130     cp_ = BUFFER_DATA_HEAD(buffer) + (offset);                \
00131     PUT_DATA((from), cp_, buflen_, (datalen));                \
00132 } while (0)
00133 
00134 #define BUFFER_GET_DATA(to, buffer, datalen)                      \
00135 do {                                          \
00136     size_t rcvlen_;                               \
00137                                           \
00138     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00139     GET_DATA((to), BUFFER_DATA_HEAD(buffer), rcvlen_, (datalen));         \
00140 } while (0)
00141 #define BUFFER_PUT_DATA(from, buffer, datalen)                    \
00142 do {                                          \
00143     size_t buflen_;                               \
00144                                           \
00145     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00146     PUT_DATA((from), BUFFER_DATA_TAIL(buffer), buflen_, (datalen));       \
00147 } while (0)
00148 
00149 #define BUFFER_GET_SKIP(octets, buffer)                       \
00150 do {                                          \
00151     size_t rcvlen_;                               \
00152                                           \
00153     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00154     GET_SKIP((octets), BUFFER_DATA_HEAD(buffer), rcvlen_);            \
00155 } while (0)
00156 #define BUFFER_PUT_SKIP(octets, buffer)                       \
00157 do {                                          \
00158     size_t buflen_;                               \
00159                                           \
00160     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00161     PUT_SKIP((octets), BUFFER_DATA_TAIL(buffer), buflen_);            \
00162 } while (0)
00163 
00164 #define BUFFER_GET_SKIP_REVERSE(octets, buffer)                   \
00165 do {                                          \
00166     size_t avail_head_;                           \
00167                                           \
00168     avail_head_ = BUFFER_AVAIL_HEAD(buffer);                  \
00169     if (avail_head_ < (octets))                       \
00170         goto rcvlen_error;                        \
00171     (buffer)->_data_head -= (octets);                     \
00172 } while (0)
00173 #define BUFFER_PUT_SKIP_REVERSE(octets, buffer)                   \
00174 do {                                          \
00175     size_t rcvlen_;                               \
00176                                           \
00177     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00178     if (rcvlen_ < (octets))                           \
00179         goto buflen_error;                        \
00180     (buffer)->_data_tail -= (octets);                     \
00181 } while (0)
00182 
00183 #define BUFFER_GET_OCTET(val, buffer)                         \
00184 do {                                          \
00185     size_t rcvlen_;                               \
00186                                           \
00187     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00188     GET_OCTET((val), BUFFER_DATA_HEAD(buffer), rcvlen_);              \
00189 } while (0)
00190 #define BUFFER_PUT_OCTET(val, buffer)                         \
00191 do {                                          \
00192     size_t buflen_;                               \
00193                                           \
00194     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00195     PUT_OCTET((val), BUFFER_DATA_TAIL(buffer), buflen_);              \
00196 } while (0)
00197 
00198 #define BUFFER_GET_HOST_16(val, buffer)                       \
00199 do {                                          \
00200     size_t rcvlen_;                               \
00201                                           \
00202     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00203     GET_HOST_16((val), BUFFER_DATA_HEAD(buffer), rcvlen_);            \
00204 } while (0)
00205 #define BUFFER_PUT_HOST_16(val, buffer)                       \
00206 do {                                          \
00207     size_t buflen_;                               \
00208                                           \
00209     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00210     PUT_HOST_16((val), BUFFER_DATA_TAIL(buffer), buflen_);            \
00211 } while (0)
00212 
00213 #define BUFFER_GET_NET_16(val, buffer)                        \
00214 do {                                          \
00215     size_t rcvlen_;                               \
00216                                           \
00217     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00218     GET_NET_16((val), BUFFER_DATA_HEAD(buffer), rcvlen_);             \
00219 } while (0)
00220 #define BUFFER_PUT_NET_16(val, buffer)                        \
00221 do {                                          \
00222     size_t buflen_;                               \
00223                                           \
00224     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00225     PUT_NET_16((val), BUFFER_DATA_TAIL(buffer), buflen_);             \
00226 } while (0)
00227 
00228 #define BUFFER_GET_HOST_32(val, buffer)                       \
00229 do {                                          \
00230     size_t rcvlen_;                               \
00231                                           \
00232     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00233     GET_HOST_32((val), BUFFER_DATA_HEAD(buffer), rcvlen_);            \
00234 } while (0)
00235 #define BUFFER_PUT_HOST_32(val, buffer)                       \
00236 do {                                          \
00237     size_t buflen_;                               \
00238                                           \
00239     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00240     PUT_HOST_32((val), BUFFER_DATA_TAIL(buffer), buflen_);            \
00241 } while (0)
00242 
00243 #define BUFFER_GET_NET_32(val, buffer)                        \
00244 do {                                          \
00245     size_t rcvlen_;                               \
00246                                           \
00247     rcvlen_ = BUFFER_DATA_SIZE(buffer);                   \
00248     GET_NET_32((val), BUFFER_DATA_HEAD(buffer), rcvlen_);             \
00249 } while (0)
00250 #define BUFFER_PUT_NET_32(val, buffer)                        \
00251 do {                                          \
00252     size_t buflen_;                               \
00253                                           \
00254     buflen_ = BUFFER_AVAIL_TAIL(buffer);                      \
00255     PUT_NET_32((val), BUFFER_DATA_TAIL(buffer), buflen_);             \
00256 } while (0)
00257 
00258 #ifndef __cplusplus
00259 #define BUFFER_GET_IPADDR(family, ipaddr, buffer)                 \
00260                 _BUFFER_GET_IPADDR_C(family, ipaddr, buffer)
00261 #define BUFFER_PUT_IPADDR(ipaddr, buffer)                     \
00262                 _BUFFER_PUT_IPADDR_C(ipaddr, buffer)
00263 #else   /* C++ */
00264 #define BUFFER_GET_IPADDR(family, ipaddr, buffer)                 \
00265                 _BUFFER_GET_IPADDR_CPP(family, ipaddr, buffer)
00266 #define BUFFER_PUT_IPADDR(ipaddr, buffer)                     \
00267                 _BUFFER_PUT_IPADDR_CPP(ipaddr, buffer)
00268 #define BUFFER_GET_IPVX(family, ipaddr, buffer)                   \
00269                 BUFFER_GET_IPADDR(family, ipaddr, buffer)
00270 #define BUFFER_PUT_IPVX(ipaddr, buffer)                       \
00271                 BUFFER_PUT_IPADDR(ipaddr, buffer)
00272 #endif /* __cplusplus */
00273 
00274 /* C version of IP addresses */
00275 #define _BUFFER_GET_IPADDR_C(family, ipaddr, buffer)                  \
00276 do {                                          \
00277     if (BUFFER_DATA_SIZE(buffer) < FAMILY2ADDRSIZE((family)))         \
00278         goto rcvlen_error;                        \
00279     MEMORY2IPADDR((family), BUFFER_DATA_HEAD((buffer)), (ipaddr));        \
00280     BUFFER_GET_SKIP(FAMILY2ADDRSIZE((family)), (buffer));             \
00281 } while (0)
00282 #define _BUFFER_PUT_IPADDR_C(ipaddr, buffer)                      \
00283 do {                                          \
00284     if (BUFFER_AVAIL_TAIL((buffer))                       \
00285         < FAMILY2ADDRSIZE(IPADDR2FAMILY((ipaddr))))           \
00286         goto buflen_error;                        \
00287     IPADDR2MEMORY((ipaddr), BUFFER_DATA_TAIL((buffer)));              \
00288     BUFFER_PUT_SKIP(FAMILY2ADDRSIZE(IPADDR2FAMILY((ipaddr))), (buffer));  \
00289 } while (0)
00290 
00291 /* C++ version of IP addresses */
00292 #define _BUFFER_GET_IPADDR_CPP(family, ipvx, buffer)                  \
00293 do {                                          \
00294     if (BUFFER_DATA_SIZE(buffer) < family2addr_bytelen((family)))         \
00295         goto rcvlen_error;                        \
00296     (ipvx).copy_in(family, BUFFER_DATA_HEAD((buffer)));           \
00297     BUFFER_GET_SKIP(family2addr_bytelen((family)), (buffer));             \
00298 } while (0)
00299 #define _BUFFER_PUT_IPADDR_CPP(ipvx, buffer)                      \
00300 do {                                          \
00301     if (BUFFER_AVAIL_TAIL((buffer)) < (ipvx).addr_bytelen())              \
00302         goto buflen_error;                        \
00303     (ipvx).copy_out(BUFFER_DATA_TAIL((buffer)));                  \
00304     BUFFER_PUT_SKIP((ipvx).addr_bytelen(), (buffer));                 \
00305 } while (0)
00306 
00307 /*
00308  * Wrappers for the buffer functions.
00309  */
00310 #define BUFFER_MALLOC(buffer_size)  (buffer_malloc_utils_((buffer_size)))
00311 #define BUFFER_FREE(buffer)                           \
00312 do {                                          \
00313     buffer_free_utils_((buffer));                         \
00314     (buffer) = NULL;                              \
00315 } while (0)
00316 #define BUFFER_RESET(buffer)        (buffer_reset_utils_((buffer)))
00317 
00318 /*
00319  * Global variables
00320  */
00321 
00322 /*
00323  * Global functions prototypes
00324  */
00325 __BEGIN_DECLS
00326 extern buffer_t *   buffer_malloc_utils_(size_t buffer_size);
00327 extern void     buffer_free_utils_(buffer_t *buffer);
00328 extern buffer_t *   buffer_reset_utils_(buffer_t *buffer);
00329 __END_DECLS
00330 
00331 #endif /* __MRT_BUFFER_H__ */
 All Classes Namespaces Functions Variables Typedefs Enumerations