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

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