14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <stdint.h>
64418919fSjohnjiang #include <stdio.h>
74418919fSjohnjiang #include <string.h>
84418919fSjohnjiang #include <stdlib.h>
94418919fSjohnjiang
104418919fSjohnjiang #include <rte_common.h>
114418919fSjohnjiang #include <rte_random.h>
124418919fSjohnjiang #include <rte_memcpy.h>
134418919fSjohnjiang
144418919fSjohnjiang #include "test.h"
154418919fSjohnjiang
164418919fSjohnjiang /*
174418919fSjohnjiang * Set this to the maximum buffer size you want to test. If it is 0, then the
184418919fSjohnjiang * values in the buf_sizes[] array below will be used.
194418919fSjohnjiang */
204418919fSjohnjiang #define TEST_VALUE_RANGE 0
214418919fSjohnjiang
224418919fSjohnjiang /* List of buffer sizes to test */
234418919fSjohnjiang #if TEST_VALUE_RANGE == 0
244418919fSjohnjiang static size_t buf_sizes[] = {
254418919fSjohnjiang 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255,
264418919fSjohnjiang 256, 257, 320, 384, 511, 512, 513, 1023, 1024, 1025, 1518, 1522, 1600,
274418919fSjohnjiang 2048, 3072, 4096, 5120, 6144, 7168, 8192
284418919fSjohnjiang };
294418919fSjohnjiang /* MUST be as large as largest packet size above */
304418919fSjohnjiang #define SMALL_BUFFER_SIZE 8192
314418919fSjohnjiang #else /* TEST_VALUE_RANGE != 0 */
324418919fSjohnjiang static size_t buf_sizes[TEST_VALUE_RANGE];
334418919fSjohnjiang #define SMALL_BUFFER_SIZE TEST_VALUE_RANGE
344418919fSjohnjiang #endif /* TEST_VALUE_RANGE == 0 */
354418919fSjohnjiang
364418919fSjohnjiang /* Data is aligned on this many bytes (power of 2) */
374418919fSjohnjiang #define ALIGNMENT_UNIT 32
384418919fSjohnjiang
394418919fSjohnjiang
404418919fSjohnjiang /*
414418919fSjohnjiang * Create two buffers, and initialise one with random values. These are copied
424418919fSjohnjiang * to the second buffer and then compared to see if the copy was successful.
434418919fSjohnjiang * The bytes outside the copied area are also checked to make sure they were not
444418919fSjohnjiang * changed.
454418919fSjohnjiang */
464418919fSjohnjiang static int
test_single_memcpy(unsigned int off_src,unsigned int off_dst,size_t size)474418919fSjohnjiang test_single_memcpy(unsigned int off_src, unsigned int off_dst, size_t size)
484418919fSjohnjiang {
494418919fSjohnjiang unsigned int i;
504418919fSjohnjiang uint8_t dest[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT];
514418919fSjohnjiang uint8_t src[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT];
524418919fSjohnjiang void * ret;
534418919fSjohnjiang
544418919fSjohnjiang /* Setup buffers */
554418919fSjohnjiang for (i = 0; i < SMALL_BUFFER_SIZE + ALIGNMENT_UNIT; i++) {
564418919fSjohnjiang dest[i] = 0;
574418919fSjohnjiang src[i] = (uint8_t) rte_rand();
584418919fSjohnjiang }
594418919fSjohnjiang
604418919fSjohnjiang /* Do the copy */
614418919fSjohnjiang ret = rte_memcpy(dest + off_dst, src + off_src, size);
624418919fSjohnjiang if (ret != (dest + off_dst)) {
634418919fSjohnjiang printf("rte_memcpy() returned %p, not %p\n",
644418919fSjohnjiang ret, dest + off_dst);
654418919fSjohnjiang }
664418919fSjohnjiang
674418919fSjohnjiang /* Check nothing before offset is affected */
684418919fSjohnjiang for (i = 0; i < off_dst; i++) {
694418919fSjohnjiang if (dest[i] != 0) {
704418919fSjohnjiang printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
714418919fSjohnjiang "[modified before start of dst].\n",
724418919fSjohnjiang (unsigned)size, off_src, off_dst);
734418919fSjohnjiang return -1;
744418919fSjohnjiang }
754418919fSjohnjiang }
764418919fSjohnjiang
774418919fSjohnjiang /* Check everything was copied */
784418919fSjohnjiang for (i = 0; i < size; i++) {
794418919fSjohnjiang if (dest[i + off_dst] != src[i + off_src]) {
804418919fSjohnjiang printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
814418919fSjohnjiang "[didn't copy byte %u].\n",
824418919fSjohnjiang (unsigned)size, off_src, off_dst, i);
834418919fSjohnjiang return -1;
844418919fSjohnjiang }
854418919fSjohnjiang }
864418919fSjohnjiang
874418919fSjohnjiang /* Check nothing after copy was affected */
884418919fSjohnjiang for (i = size; i < SMALL_BUFFER_SIZE; i++) {
894418919fSjohnjiang if (dest[i + off_dst] != 0) {
904418919fSjohnjiang printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
914418919fSjohnjiang "[copied too many].\n",
924418919fSjohnjiang (unsigned)size, off_src, off_dst);
934418919fSjohnjiang return -1;
944418919fSjohnjiang }
954418919fSjohnjiang }
964418919fSjohnjiang return 0;
974418919fSjohnjiang }
984418919fSjohnjiang
994418919fSjohnjiang /*
1004418919fSjohnjiang * Check functionality for various buffer sizes and data offsets/alignments.
1014418919fSjohnjiang */
1024418919fSjohnjiang static int
func_test(void)1034418919fSjohnjiang func_test(void)
1044418919fSjohnjiang {
1054418919fSjohnjiang unsigned int off_src, off_dst, i;
1064418919fSjohnjiang int ret;
1074418919fSjohnjiang
1084418919fSjohnjiang for (off_src = 0; off_src < ALIGNMENT_UNIT; off_src++) {
1094418919fSjohnjiang for (off_dst = 0; off_dst < ALIGNMENT_UNIT; off_dst++) {
110*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(buf_sizes); i++) {
1114418919fSjohnjiang ret = test_single_memcpy(off_src, off_dst,
1124418919fSjohnjiang buf_sizes[i]);
1134418919fSjohnjiang if (ret != 0)
1144418919fSjohnjiang return -1;
1154418919fSjohnjiang }
1164418919fSjohnjiang }
1174418919fSjohnjiang }
1184418919fSjohnjiang return 0;
1194418919fSjohnjiang }
1204418919fSjohnjiang
1214418919fSjohnjiang static int
test_memcpy(void)1224418919fSjohnjiang test_memcpy(void)
1234418919fSjohnjiang {
1244418919fSjohnjiang int ret;
1254418919fSjohnjiang
1264418919fSjohnjiang ret = func_test();
1274418919fSjohnjiang if (ret != 0)
1284418919fSjohnjiang return -1;
1294418919fSjohnjiang return 0;
1304418919fSjohnjiang }
1314418919fSjohnjiang
1324418919fSjohnjiang REGISTER_TEST_COMMAND(memcpy_autotest, test_memcpy);
133