You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

iobuf.h 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #ifndef _GPXE_IOBUF_H
  2. #define _GPXE_IOBUF_H
  3. /** @file
  4. *
  5. * I/O buffers
  6. *
  7. */
  8. #include <stdint.h>
  9. #include <assert.h>
  10. #include <gpxe/list.h>
  11. /**
  12. * I/O buffer alignment
  13. *
  14. * I/O buffers allocated via alloc_iob() are guaranteed to be
  15. * physically aligned to this boundary. Some cards cannot DMA across
  16. * a 4kB boundary. With a standard Ethernet MTU, aligning to a 2kB
  17. * boundary is sufficient to guarantee no 4kB boundary crossings. For
  18. * a jumbo Ethernet MTU, a packet may be larger than 4kB anyway.
  19. */
  20. #define IOB_ALIGN 2048
  21. /**
  22. * Minimum I/O buffer length
  23. *
  24. * alloc_iob() will round up the allocated length to this size if
  25. * necessary. This is used on behalf of hardware that is not capable
  26. * of auto-padding.
  27. */
  28. #define IOB_ZLEN 64
  29. /**
  30. * A persistent I/O buffer
  31. *
  32. * This data structure encapsulates a long-lived I/O buffer. The
  33. * buffer may be passed between multiple owners, queued for possible
  34. * retransmission, etc.
  35. */
  36. struct io_buffer {
  37. /** List of which this buffer is a member
  38. *
  39. * The list must belong to the current owner of the buffer.
  40. * Different owners may maintain different lists (e.g. a
  41. * retransmission list for TCP).
  42. */
  43. struct list_head list;
  44. /** Start of the buffer */
  45. void *head;
  46. /** Start of data */
  47. void *data;
  48. /** End of data */
  49. void *tail;
  50. /** End of the buffer */
  51. void *end;
  52. };
  53. /**
  54. * Reserve space at start of I/O buffer
  55. *
  56. * @v iobuf I/O buffer
  57. * @v len Length to reserve
  58. * @ret data Pointer to new start of buffer
  59. */
  60. static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
  61. iobuf->data += len;
  62. iobuf->tail += len;
  63. return iobuf->data;
  64. }
  65. #define iob_reserve( iobuf, len ) ( { \
  66. void *__result; \
  67. __result = iob_reserve ( (iobuf), (len) ); \
  68. assert ( (iobuf)->tail <= (iobuf)->end ); \
  69. __result; } )
  70. /**
  71. * Add data to start of I/O buffer
  72. *
  73. * @v iobuf I/O buffer
  74. * @v len Length to add
  75. * @ret data Pointer to new start of buffer
  76. */
  77. static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
  78. iobuf->data -= len;
  79. return iobuf->data;
  80. }
  81. #define iob_push( iobuf, len ) ( { \
  82. void *__result; \
  83. __result = iob_push ( (iobuf), (len) ); \
  84. assert ( (iobuf)->data >= (iobuf)->head ); \
  85. __result; } )
  86. /**
  87. * Remove data from start of I/O buffer
  88. *
  89. * @v iobuf I/O buffer
  90. * @v len Length to remove
  91. * @ret data Pointer to new start of buffer
  92. */
  93. static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
  94. iobuf->data += len;
  95. assert ( iobuf->data <= iobuf->tail );
  96. return iobuf->data;
  97. }
  98. #define iob_pull( iobuf, len ) ( { \
  99. void *__result; \
  100. __result = iob_pull ( (iobuf), (len) ); \
  101. assert ( (iobuf)->data <= (iobuf)->tail ); \
  102. __result; } )
  103. /**
  104. * Add data to end of I/O buffer
  105. *
  106. * @v iobuf I/O buffer
  107. * @v len Length to add
  108. * @ret data Pointer to newly added space
  109. */
  110. static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
  111. void *old_tail = iobuf->tail;
  112. iobuf->tail += len;
  113. return old_tail;
  114. }
  115. #define iob_put( iobuf, len ) ( { \
  116. void *__result; \
  117. __result = iob_put ( (iobuf), (len) ); \
  118. assert ( (iobuf)->tail <= (iobuf)->end ); \
  119. __result; } )
  120. /**
  121. * Remove data from end of I/O buffer
  122. *
  123. * @v iobuf I/O buffer
  124. * @v len Length to remove
  125. */
  126. static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
  127. iobuf->tail -= len;
  128. }
  129. #define iob_unput( iobuf, len ) do { \
  130. iob_unput ( (iobuf), (len) ); \
  131. assert ( (iobuf)->tail >= (iobuf)->data ); \
  132. } while ( 0 )
  133. /**
  134. * Empty an I/O buffer
  135. *
  136. * @v iobuf I/O buffer
  137. */
  138. static inline void iob_empty ( struct io_buffer *iobuf ) {
  139. iobuf->tail = iobuf->data;
  140. }
  141. /**
  142. * Calculate length of data in an I/O buffer
  143. *
  144. * @v iobuf I/O buffer
  145. * @ret len Length of data in buffer
  146. */
  147. static inline size_t iob_len ( struct io_buffer *iobuf ) {
  148. return ( iobuf->tail - iobuf->data );
  149. }
  150. /**
  151. * Calculate available space at start of an I/O buffer
  152. *
  153. * @v iobuf I/O buffer
  154. * @ret len Length of data available at start of buffer
  155. */
  156. static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
  157. return ( iobuf->data - iobuf->head );
  158. }
  159. /**
  160. * Calculate available space at end of an I/O buffer
  161. *
  162. * @v iobuf I/O buffer
  163. * @ret len Length of data available at end of buffer
  164. */
  165. static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
  166. return ( iobuf->end - iobuf->tail );
  167. }
  168. /**
  169. * Create a temporary I/O buffer
  170. *
  171. * @v iobuf I/O buffer
  172. * @v data Data buffer
  173. * @v len Length of data
  174. * @v max_len Length of buffer
  175. *
  176. * It is sometimes useful to use the iob_xxx() methods on temporary
  177. * data buffers.
  178. */
  179. static inline void iob_populate ( struct io_buffer *iobuf,
  180. void *data, size_t len, size_t max_len ) {
  181. iobuf->head = iobuf->data = data;
  182. iobuf->tail = ( data + len );
  183. iobuf->end = ( data + max_len );
  184. }
  185. /**
  186. * Disown an I/O buffer
  187. *
  188. * @v iobuf I/O buffer
  189. *
  190. * There are many functions that take ownership of the I/O buffer they
  191. * are passed as a parameter. The caller should not retain a pointer
  192. * to the I/O buffer. Use iob_disown() to automatically nullify the
  193. * caller's pointer, e.g.:
  194. *
  195. * xfer_deliver_iob ( xfer, iob_disown ( iobuf ) );
  196. *
  197. * This will ensure that iobuf is set to NULL for any code after the
  198. * call to xfer_deliver_iob().
  199. */
  200. #define iob_disown( iobuf ) ( { \
  201. struct io_buffer *__iobuf = (iobuf); \
  202. (iobuf) = NULL; \
  203. __iobuf; } )
  204. extern struct io_buffer * __malloc alloc_iob ( size_t len );
  205. extern void free_iob ( struct io_buffer *iobuf );
  206. extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
  207. extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
  208. #endif /* _GPXE_IOBUF_H */