[v3,1/1] linux-gen: pool: avoid allocating packets which cross huge page boundaries

Message ID 1507640407-354-2-git-send-email-odpbot@yandex.ru
State New
Headers show
Series
  • linux-gen: pool: avoid allocating packets which cross page boundaries
Related show

Commit Message

Github ODP bot Oct. 10, 2017, 1 p.m.
From: Matias Elo <matias.elo@nokia.com>


When packet pool memory page size is >= FIRST_HP_SIZE, leave those memory
buffers unused which cross page boundary. This is required by zero-copy
dpdk pktio (NIC drivers don't support buffers which cross page boundaries).

Signed-off-by: Matias Elo <matias.elo@nokia.com>

---
/** Email created from pull request 223 (matiaselo:fix/pool_create)
 ** https://github.com/Linaro/odp/pull/223
 ** Patch: https://github.com/Linaro/odp/pull/223.patch
 ** Base sha: 37b430cb9e8f6834a3c76ab108489cec719b9e32
 ** Merge commit sha: 1619c61c5d289d14ea8266a22b889484a980827f
 **/
 platform/linux-generic/odp_pool.c | 47 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 42 insertions(+), 5 deletions(-)

Patch

diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index 2a0a35e40..40cbb397c 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -32,6 +32,10 @@ 
 #define CACHE_BURST    32
 #define RING_SIZE_MIN  (2 * CACHE_BURST)
 
+/* Make sure packet buffers don't cross huge page boundaries starting from this
+ * page size. 2MB is typically the smallest used huge page size. */
+#define FIRST_HP_SIZE (2 * 1024 * 1024)
+
 /* Define a practical limit for contiguous memory allocations */
 #define MAX_SIZE   (10 * 1024 * 1024)
 
@@ -224,6 +228,7 @@  static void init_buffers(pool_t *pool)
 	uint32_t i;
 	odp_buffer_hdr_t *buf_hdr;
 	odp_packet_hdr_t *pkt_hdr;
+	odp_shm_info_t shm_info;
 	void *addr;
 	void *uarea = NULL;
 	uint8_t *data;
@@ -232,19 +237,41 @@  static void init_buffers(pool_t *pool)
 	uint32_t mask;
 	int type;
 	uint32_t seg_size;
+	uint64_t page_size;
+	int skipped_blocks = 0;
+
+	if (odp_shm_info(pool->shm, &shm_info))
+		ODP_ABORT("Shm info failed\n");
 
+	page_size = shm_info.page_size;
 	ring = &pool->ring->hdr;
 	mask = pool->ring_mask;
 	type = pool->params.type;
 
-	for (i = 0; i < pool->num; i++) {
+	for (i = 0; i < pool->num + skipped_blocks ; i++) {
 		addr    = &pool->base_addr[i * pool->block_size];
 		buf_hdr = addr;
 		pkt_hdr = addr;
-
+		/* Skip packet buffers which cross huge page boundaries. Some
+		 * NICs cannot handle buffers which cross page boundaries. */
+		if (pool->params.type == ODP_POOL_PACKET &&
+		    page_size >= FIRST_HP_SIZE) {
+			uint64_t first_page;
+			uint64_t last_page;
+
+			first_page = ((uint64_t)(uintptr_t)addr &
+					~(page_size - 1));
+			last_page = (((uint64_t)(uintptr_t)addr +
+					pool->block_size - 1) &
+					~(page_size - 1));
+			if (last_page != first_page) {
+				skipped_blocks++;
+				continue;
+			}
+		}
 		if (pool->uarea_size)
-			uarea = &pool->uarea_base_addr[i * pool->uarea_size];
-
+			uarea = &pool->uarea_base_addr[(i - skipped_blocks) *
+						       pool->uarea_size];
 		data = buf_hdr->data;
 
 		if (type == ODP_POOL_PACKET)
@@ -317,6 +344,7 @@  static odp_pool_t pool_create(const char *name, odp_pool_param_t *params,
 	uint32_t data_size, align, num, hdr_size, block_size;
 	uint32_t max_len, max_seg_len;
 	uint32_t ring_size;
+	uint32_t num_extra = 0;
 	int name_len;
 	const char *postfix = "_uarea";
 	char uarea_name[ODP_POOL_NAME_LEN + sizeof(postfix)];
@@ -403,6 +431,15 @@  static odp_pool_t pool_create(const char *name, odp_pool_param_t *params,
 	block_size = ROUNDUP_CACHE_LINE(hdr_size + align + headroom +
 					data_size + tailroom);
 
+	/* Allocate extra memory for skipping packet buffers which cross huge
+	 * page boundaries. */
+	if (params->type == ODP_POOL_PACKET) {
+		num_extra = (((uint64_t)(num * block_size) +
+				FIRST_HP_SIZE - 1) / FIRST_HP_SIZE);
+		num_extra += (((uint64_t)(num_extra * block_size) +
+				FIRST_HP_SIZE - 1) / FIRST_HP_SIZE);
+	}
+
 	if (num <= RING_SIZE_MIN)
 		ring_size = RING_SIZE_MIN;
 	else
@@ -418,7 +455,7 @@  static odp_pool_t pool_create(const char *name, odp_pool_param_t *params,
 	pool->tailroom       = tailroom;
 	pool->block_size     = block_size;
 	pool->uarea_size     = uarea_size;
-	pool->shm_size       = num * block_size;
+	pool->shm_size       = (num + num_extra) * block_size;
 	pool->uarea_shm_size = num * uarea_size;
 	pool->ext_desc       = NULL;
 	pool->ext_destroy    = NULL;