您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

iobuf.h 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 <errno.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. assert ( iobuf->tail <= iobuf->end );
  65. return iobuf->data;
  66. }
  67. /**
  68. * Add data to start of I/O buffer
  69. *
  70. * @v iobuf I/O buffer
  71. * @v len Length to add
  72. * @ret data Pointer to new start of buffer
  73. */
  74. static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
  75. iobuf->data -= len;
  76. assert ( iobuf->data >= iobuf->head );
  77. return iobuf->data;
  78. }
  79. /**
  80. * Remove data from start of I/O buffer
  81. *
  82. * @v iobuf I/O buffer
  83. * @v len Length to remove
  84. * @ret data Pointer to new start of buffer
  85. */
  86. static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
  87. iobuf->data += len;
  88. assert ( iobuf->data <= iobuf->tail );
  89. return iobuf->data;
  90. }
  91. /**
  92. * Add data to end of I/O buffer
  93. *
  94. * @v iobuf I/O buffer
  95. * @v len Length to add
  96. * @ret data Pointer to newly added space
  97. */
  98. static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
  99. void *old_tail = iobuf->tail;
  100. iobuf->tail += len;
  101. assert ( iobuf->tail <= iobuf->end );
  102. return old_tail;
  103. }
  104. /**
  105. * Remove data from end of I/O buffer
  106. *
  107. * @v iobuf I/O buffer
  108. * @v len Length to remove
  109. */
  110. static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
  111. iobuf->tail -= len;
  112. assert ( iobuf->tail >= iobuf->data );
  113. }
  114. /**
  115. * Empty an I/O buffer
  116. *
  117. * @v iobuf I/O buffer
  118. */
  119. static inline void iob_empty ( struct io_buffer *iobuf ) {
  120. iobuf->tail = iobuf->data;
  121. }
  122. /**
  123. * Calculate length of data in an I/O buffer
  124. *
  125. * @v iobuf I/O buffer
  126. * @ret len Length of data in buffer
  127. */
  128. static inline size_t iob_len ( struct io_buffer *iobuf ) {
  129. return ( iobuf->tail - iobuf->data );
  130. }
  131. /**
  132. * Calculate available space at start of an I/O buffer
  133. *
  134. * @v iobuf I/O buffer
  135. * @ret len Length of data available at start of buffer
  136. */
  137. static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
  138. return ( iobuf->data - iobuf->head );
  139. }
  140. /**
  141. * Calculate available space at end of an I/O buffer
  142. *
  143. * @v iobuf I/O buffer
  144. * @ret len Length of data available at end of buffer
  145. */
  146. static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
  147. return ( iobuf->end - iobuf->tail );
  148. }
  149. /**
  150. * Ensure I/O buffer has sufficient headroom
  151. *
  152. * @v iobuf I/O buffer
  153. * @v len Required headroom
  154. *
  155. * This function currently only checks for the required headroom; it
  156. * does not reallocate the I/O buffer if required. If we ever have a
  157. * code path that requires this functionality, it's a fairly trivial
  158. * change to make.
  159. */
  160. static inline __attribute__ (( always_inline )) int
  161. iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) {
  162. if ( iob_headroom ( iobuf ) >= len )
  163. return 0;
  164. return -ENOBUFS;
  165. }
  166. extern struct io_buffer * alloc_iob ( size_t len );
  167. extern void free_iob ( struct io_buffer *iobuf );
  168. extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
  169. #endif /* _GPXE_IOBUF_H */