pvtcp_off.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Linux 2.6.32 and later Kernel module for VMware MVP PVTCP Server
  3. *
  4. * Copyright (C) 2010-2013 VMware, Inc. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published by
  8. * the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program; see the file COPYING. If not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. #line 5
  20. /**
  21. * @file
  22. *
  23. * @brief Server (offload) side code.
  24. */
  25. #include "pvtcp.h"
  26. /**
  27. * @brief Allocates and initializes a net buffer.
  28. * @param size buffer size.
  29. * @param channel channel from which to copy.
  30. * @param header header of this payload.
  31. * @param copy function to use for copying.
  32. * @return address of buffer or NULL
  33. */
  34. void *
  35. PvtcpBufAlloc(unsigned int size,
  36. CommChannel channel,
  37. CommPacket *header,
  38. int (*copy)(CommChannel channel,
  39. void *dest,
  40. unsigned int size,
  41. int kern))
  42. {
  43. PvtcpOffBuf *buf;
  44. void *res = NULL;
  45. /* coverity[alloc_fn] */
  46. /* coverity[var_assign] */
  47. if (size == 0) {
  48. return NULL;
  49. }
  50. if ((header->opCode == PVTCP_OP_IO) && (size > PVTCP_SOCK_BUF_SIZE)) {
  51. /*
  52. * Since stream sockets always chunk payloads, this is a non-stream output
  53. * operation that needs fragment allocation. Non-stream payloads are never
  54. * enqueued, so we can overload the 'len' and 'off' fields.
  55. * Allocate the header with an iovec array, plus each iovec entry. Note that
  56. * there will be at least two fragments.
  57. * The 'off' field is set to USHRT_MAX to distinguish frag-allocations,
  58. * and 'len' stores the number of fragments.
  59. */
  60. unsigned int nmbFrags =
  61. (size + PVTCP_SOCK_BUF_SIZE - 1) / PVTCP_SOCK_BUF_SIZE;
  62. unsigned int i;
  63. struct kvec *vec;
  64. buf = CommOS_Kmalloc((sizeof(*buf) - sizeof(buf->data)) +
  65. (sizeof(*vec) * nmbFrags));
  66. if (buf) {
  67. CommOS_ListInit(&buf->link);
  68. buf->len = (unsigned short)nmbFrags;
  69. buf->off = USHRT_MAX;
  70. res = vec = PvtcpOffBufFromInternal(buf);
  71. for (i = 0; i < nmbFrags; i++) {
  72. unsigned int fragSize =
  73. size < PVTCP_SOCK_BUF_SIZE ? size : PVTCP_SOCK_BUF_SIZE;
  74. vec[i].iov_base = CommOS_Kmalloc(fragSize);
  75. vec[i].iov_len = fragSize;
  76. if (!vec[i].iov_base) {
  77. i++;
  78. goto undo;
  79. }
  80. if (copy(channel, vec[i].iov_base, vec[i].iov_len, 1) !=
  81. vec[i].iov_len) {
  82. CommOS_Log(("%s: Failed to copy from channel!\n", __func__));
  83. i++;
  84. goto undo;
  85. }
  86. size -= fragSize;
  87. }
  88. goto out;
  89. undo:
  90. while (i) {
  91. CommOS_Kfree(vec[--i].iov_base);
  92. }
  93. CommOS_Kfree(buf);
  94. res = NULL;
  95. }
  96. } else {
  97. buf = CommOS_Kmalloc(size + sizeof(*buf) - sizeof(buf->data));
  98. if (buf) {
  99. CommOS_ListInit(&buf->link);
  100. buf->len = (unsigned short)size;
  101. buf->off = 0;
  102. res = PvtcpOffBufFromInternal(buf);
  103. if (copy(channel, res, size, 1) != size) {
  104. CommOS_Kfree(buf);
  105. CommOS_Log(("%s: Failed to copy from channel!\n", __func__));
  106. res = NULL;
  107. }
  108. }
  109. }
  110. out:
  111. return res;
  112. }
  113. /**
  114. * @brief Deallocates given net buffer.
  115. * @param buf buffer to deallocate
  116. * @sideeffect Frees memory
  117. */
  118. void
  119. PvtcpBufFree(void *buf)
  120. {
  121. if (buf) {
  122. PvtcpOffBuf *internalBuf = PvtcpOffInternalFromBuf(buf);
  123. if (internalBuf->off == USHRT_MAX) {
  124. struct kvec *vec = buf;
  125. while (internalBuf->len) {
  126. CommOS_Kfree(vec[--internalBuf->len].iov_base);
  127. }
  128. }
  129. CommOS_Kfree(internalBuf);
  130. }
  131. }
  132. /**
  133. * @brief Initializes the Pvtcp socket offload common fields.
  134. * @param pvsk pvtcp socket.
  135. * @param channel Comm channel this socket is associated with.
  136. * @return 0 if successful, -1 otherwise.
  137. */
  138. int
  139. PvtcpOffSockInit(PvtcpSock *pvsk,
  140. CommChannel channel)
  141. {
  142. int rc = PvtcpSockInit(pvsk, channel);
  143. pvsk->opFlags = 0;
  144. pvsk->flags = 0;
  145. return rc;
  146. }