dpdk/app/test/test_graph.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(C) 2020 Marvell International Ltd.
   3 */
   4#include <assert.h>
   5#include <inttypes.h>
   6#include <signal.h>
   7#include <stdio.h>
   8#include <string.h>
   9#include <unistd.h>
  10
  11#include <rte_errno.h>
  12#include <rte_graph.h>
  13#include <rte_graph_worker.h>
  14#include <rte_mbuf.h>
  15#include <rte_mbuf_dyn.h>
  16#include <rte_random.h>
  17
  18#include "test.h"
  19
  20static uint16_t test_node_worker_source(struct rte_graph *graph,
  21                                        struct rte_node *node, void **objs,
  22                                        uint16_t nb_objs);
  23
  24static uint16_t test_node0_worker(struct rte_graph *graph,
  25                                  struct rte_node *node, void **objs,
  26                                  uint16_t nb_objs);
  27
  28static uint16_t test_node1_worker(struct rte_graph *graph,
  29                                  struct rte_node *node, void **objs,
  30                                  uint16_t nb_objs);
  31
  32static uint16_t test_node2_worker(struct rte_graph *graph,
  33                                  struct rte_node *node, void **objs,
  34                                  uint16_t nb_objs);
  35
  36static uint16_t test_node3_worker(struct rte_graph *graph,
  37                                  struct rte_node *node, void **objs,
  38                                  uint16_t nb_objs);
  39
  40#define MBUFF_SIZE 512
  41#define MAX_NODES  4
  42
  43typedef uint64_t graph_dynfield_t;
  44static int graph_dynfield_offset = -1;
  45
  46static inline graph_dynfield_t *
  47graph_field(struct rte_mbuf *mbuf)
  48{
  49        return RTE_MBUF_DYNFIELD(mbuf, \
  50                        graph_dynfield_offset, graph_dynfield_t *);
  51}
  52
  53static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE];
  54static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE];
  55static rte_graph_t graph_id;
  56static uint64_t obj_stats[MAX_NODES + 1];
  57static uint64_t fn_calls[MAX_NODES + 1];
  58
  59const char *node_patterns[] = {
  60        "test_node_source1",       "test_node00",
  61        "test_node00-test_node11", "test_node00-test_node22",
  62        "test_node00-test_node33",
  63};
  64
  65const char *node_names[] = {
  66        "test_node00",
  67        "test_node00-test_node11",
  68        "test_node00-test_node22",
  69        "test_node00-test_node33",
  70};
  71
  72struct test_node_register {
  73        char name[RTE_NODE_NAMESIZE];
  74        rte_node_process_t process;
  75        uint16_t nb_edges;
  76        const char *next_nodes[MAX_NODES];
  77};
  78
  79typedef struct {
  80        uint32_t idx;
  81        struct test_node_register node;
  82} test_node_t;
  83
  84typedef struct {
  85        test_node_t test_node[MAX_NODES];
  86} test_main_t;
  87
  88static test_main_t test_main = {
  89        .test_node = {
  90                {
  91                        .node = {
  92                                        .name = "test_node00",
  93                                        .process = test_node0_worker,
  94                                        .nb_edges = 2,
  95                                        .next_nodes = {"test_node00-"
  96                                                       "test_node11",
  97                                                       "test_node00-"
  98                                                       "test_node22"},
  99                                },
 100                },
 101                {
 102                        .node = {
 103                                        .name = "test_node11",
 104                                        .process = test_node1_worker,
 105                                        .nb_edges = 1,
 106                                        .next_nodes = {"test_node00-"
 107                                                       "test_node22"},
 108                                },
 109                },
 110                {
 111                        .node = {
 112                                        .name = "test_node22",
 113                                        .process = test_node2_worker,
 114                                        .nb_edges = 1,
 115                                        .next_nodes = {"test_node00-"
 116                                                       "test_node33"},
 117                                },
 118                },
 119                {
 120                        .node = {
 121                                        .name = "test_node33",
 122                                        .process = test_node3_worker,
 123                                        .nb_edges = 1,
 124                                        .next_nodes = {"test_node00"},
 125                                },
 126                },
 127        },
 128};
 129
 130static int
 131node_init(const struct rte_graph *graph, struct rte_node *node)
 132{
 133        RTE_SET_USED(graph);
 134        *(uint32_t *)node->ctx = node->id;
 135
 136        return 0;
 137}
 138
 139static struct rte_node_register test_node_source = {
 140        .name = "test_node_source1",
 141        .process = test_node_worker_source,
 142        .flags = RTE_NODE_SOURCE_F,
 143        .nb_edges = 2,
 144        .init = node_init,
 145        .next_nodes = {"test_node00", "test_node00-test_node11"},
 146};
 147RTE_NODE_REGISTER(test_node_source);
 148
 149static struct rte_node_register test_node0 = {
 150        .name = "test_node00",
 151        .process = test_node0_worker,
 152        .init = node_init,
 153};
 154RTE_NODE_REGISTER(test_node0);
 155
 156uint16_t
 157test_node_worker_source(struct rte_graph *graph, struct rte_node *node,
 158                        void **objs, uint16_t nb_objs)
 159{
 160        uint32_t obj_node0 = rte_rand() % 100, obj_node1;
 161        test_main_t *tm = &test_main;
 162        struct rte_mbuf *data;
 163        void **next_stream;
 164        rte_node_t next;
 165        uint32_t i;
 166
 167        RTE_SET_USED(objs);
 168        nb_objs = RTE_GRAPH_BURST_SIZE;
 169
 170        /* Prepare stream for next node 0 */
 171        obj_node0 = nb_objs * obj_node0 * 0.01;
 172        next = 0;
 173        next_stream = rte_node_next_stream_get(graph, node, next, obj_node0);
 174        for (i = 0; i < obj_node0; i++) {
 175                data = &mbuf[0][i];
 176                *graph_field(data) = ((uint64_t)tm->test_node[0].idx << 32) | i;
 177                if ((i + 1) == obj_node0)
 178                        *graph_field(data) |= (1 << 16);
 179                next_stream[i] = &mbuf[0][i];
 180        }
 181        rte_node_next_stream_put(graph, node, next, obj_node0);
 182
 183        /* Prepare stream for next node 1 */
 184        obj_node1 = nb_objs - obj_node0;
 185        next = 1;
 186        next_stream = rte_node_next_stream_get(graph, node, next, obj_node1);
 187        for (i = 0; i < obj_node1; i++) {
 188                data = &mbuf[0][obj_node0 + i];
 189                *graph_field(data) = ((uint64_t)tm->test_node[1].idx << 32) | i;
 190                if ((i + 1) == obj_node1)
 191                        *graph_field(data) |= (1 << 16);
 192                next_stream[i] = &mbuf[0][obj_node0 + i];
 193        }
 194
 195        rte_node_next_stream_put(graph, node, next, obj_node1);
 196        obj_stats[0] += nb_objs;
 197        fn_calls[0] += 1;
 198        return nb_objs;
 199}
 200
 201uint16_t
 202test_node0_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
 203                  uint16_t nb_objs)
 204{
 205        test_main_t *tm = &test_main;
 206
 207        if (*(uint32_t *)node->ctx == test_node0.id) {
 208                uint32_t obj_node0 = rte_rand() % 100, obj_node1;
 209                struct rte_mbuf *data;
 210                uint8_t second_pass = 0;
 211                uint32_t count = 0;
 212                uint32_t i;
 213
 214                obj_stats[1] += nb_objs;
 215                fn_calls[1] += 1;
 216
 217                for (i = 0; i < nb_objs; i++) {
 218                        data = (struct rte_mbuf *)objs[i];
 219                        if ((*graph_field(data) >> 32) != tm->test_node[0].idx) {
 220                                printf("Data idx miss match at node 0, expected"
 221                                       " = %u got = %u\n",
 222                                       tm->test_node[0].idx,
 223                                       (uint32_t)(*graph_field(data) >> 32));
 224                                goto end;
 225                        }
 226
 227                        if ((*graph_field(data) & 0xffff) != (i - count)) {
 228                                printf("Expected buff count miss match at "
 229                                       "node 0\n");
 230                                goto end;
 231                        }
 232
 233                        if (*graph_field(data) & (0x1 << 16))
 234                                count = i + 1;
 235                        if (*graph_field(data) & (0x1 << 17))
 236                                second_pass = 1;
 237                }
 238
 239                if (count != i) {
 240                        printf("Count mismatch at node 0\n");
 241                        goto end;
 242                }
 243
 244                obj_node0 = nb_objs * obj_node0 * 0.01;
 245                for (i = 0; i < obj_node0; i++) {
 246                        data = &mbuf[1][i];
 247                        *graph_field(data) =
 248                                ((uint64_t)tm->test_node[1].idx << 32) | i;
 249                        if ((i + 1) == obj_node0)
 250                                *graph_field(data) |= (1 << 16);
 251                        if (second_pass)
 252                                *graph_field(data) |= (1 << 17);
 253                }
 254                rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[1][0],
 255                                 obj_node0);
 256
 257                obj_node1 = nb_objs - obj_node0;
 258                for (i = 0; i < obj_node1; i++) {
 259                        data = &mbuf[1][obj_node0 + i];
 260                        *graph_field(data) =
 261                                ((uint64_t)tm->test_node[2].idx << 32) | i;
 262                        if ((i + 1) == obj_node1)
 263                                *graph_field(data) |= (1 << 16);
 264                        if (second_pass)
 265                                *graph_field(data) |= (1 << 17);
 266                }
 267                rte_node_enqueue(graph, node, 1, (void **)&mbuf_p[1][obj_node0],
 268                                 obj_node1);
 269
 270        } else if (*(uint32_t *)node->ctx == tm->test_node[1].idx) {
 271                test_node1_worker(graph, node, objs, nb_objs);
 272        } else if (*(uint32_t *)node->ctx == tm->test_node[2].idx) {
 273                test_node2_worker(graph, node, objs, nb_objs);
 274        } else if (*(uint32_t *)node->ctx == tm->test_node[3].idx) {
 275                test_node3_worker(graph, node, objs, nb_objs);
 276        } else {
 277                printf("Unexpected node context\n");
 278        }
 279
 280end:
 281        return nb_objs;
 282}
 283
 284uint16_t
 285test_node1_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
 286                  uint16_t nb_objs)
 287{
 288        test_main_t *tm = &test_main;
 289        uint8_t second_pass = 0;
 290        uint32_t obj_node0 = 0;
 291        struct rte_mbuf *data;
 292        uint32_t count = 0;
 293        uint32_t i;
 294
 295        obj_stats[2] += nb_objs;
 296        fn_calls[2] += 1;
 297        for (i = 0; i < nb_objs; i++) {
 298                data = (struct rte_mbuf *)objs[i];
 299                if ((*graph_field(data) >> 32) != tm->test_node[1].idx) {
 300                        printf("Data idx miss match at node 1, expected = %u"
 301                               " got = %u\n",
 302                               tm->test_node[1].idx,
 303                               (uint32_t)(*graph_field(data) >> 32));
 304                        goto end;
 305                }
 306
 307                if ((*graph_field(data) & 0xffff) != (i - count)) {
 308                        printf("Expected buff count miss match at node 1\n");
 309                        goto end;
 310                }
 311
 312                if (*graph_field(data) & (0x1 << 16))
 313                        count = i + 1;
 314                if (*graph_field(data) & (0x1 << 17))
 315                        second_pass = 1;
 316        }
 317
 318        if (count != i) {
 319                printf("Count mismatch at node 1\n");
 320                goto end;
 321        }
 322
 323        obj_node0 = nb_objs;
 324        for (i = 0; i < obj_node0; i++) {
 325                data = &mbuf[2][i];
 326                *graph_field(data) = ((uint64_t)tm->test_node[2].idx << 32) | i;
 327                if ((i + 1) == obj_node0)
 328                        *graph_field(data) |= (1 << 16);
 329                if (second_pass)
 330                        *graph_field(data) |= (1 << 17);
 331        }
 332        rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[2][0], obj_node0);
 333
 334end:
 335        return nb_objs;
 336}
 337
 338uint16_t
 339test_node2_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
 340                  uint16_t nb_objs)
 341{
 342        test_main_t *tm = &test_main;
 343        uint8_t second_pass = 0;
 344        struct rte_mbuf *data;
 345        uint32_t count = 0;
 346        uint32_t obj_node0;
 347        uint32_t i;
 348
 349        obj_stats[3] += nb_objs;
 350        fn_calls[3] += 1;
 351        for (i = 0; i < nb_objs; i++) {
 352                data = (struct rte_mbuf *)objs[i];
 353                if ((*graph_field(data) >> 32) != tm->test_node[2].idx) {
 354                        printf("Data idx miss match at node 2, expected = %u"
 355                               " got = %u\n",
 356                               tm->test_node[2].idx,
 357                               (uint32_t)(*graph_field(data) >> 32));
 358                        goto end;
 359                }
 360
 361                if ((*graph_field(data) & 0xffff) != (i - count)) {
 362                        printf("Expected buff count miss match at node 2\n");
 363                        goto end;
 364                }
 365
 366                if (*graph_field(data) & (0x1 << 16))
 367                        count = i + 1;
 368                if (*graph_field(data) & (0x1 << 17))
 369                        second_pass = 1;
 370        }
 371
 372        if (count != i) {
 373                printf("Count mismatch at node 2\n");
 374                goto end;
 375        }
 376
 377        if (!second_pass) {
 378                obj_node0 = nb_objs;
 379                for (i = 0; i < obj_node0; i++) {
 380                        data = &mbuf[3][i];
 381                        *graph_field(data) =
 382                                ((uint64_t)tm->test_node[3].idx << 32) | i;
 383                        if ((i + 1) == obj_node0)
 384                                *graph_field(data) |= (1 << 16);
 385                }
 386                rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[3][0],
 387                                 obj_node0);
 388        }
 389
 390end:
 391        return nb_objs;
 392}
 393
 394uint16_t
 395test_node3_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
 396                  uint16_t nb_objs)
 397{
 398        test_main_t *tm = &test_main;
 399        uint8_t second_pass = 0;
 400        struct rte_mbuf *data;
 401        uint32_t count = 0;
 402        uint32_t obj_node0;
 403        uint32_t i;
 404
 405        obj_stats[4] += nb_objs;
 406        fn_calls[4] += 1;
 407        for (i = 0; i < nb_objs; i++) {
 408                data = (struct rte_mbuf *)objs[i];
 409                if ((*graph_field(data) >> 32) != tm->test_node[3].idx) {
 410                        printf("Data idx miss match at node 3, expected = %u"
 411                               " got = %u\n",
 412                               tm->test_node[3].idx,
 413                               (uint32_t)(*graph_field(data) >> 32));
 414                        goto end;
 415                }
 416
 417                if ((*graph_field(data) & 0xffff) != (i - count)) {
 418                        printf("Expected buff count miss match at node 3\n");
 419                        goto end;
 420                }
 421
 422                if (*graph_field(data) & (0x1 << 16))
 423                        count = i + 1;
 424                if (*graph_field(data) & (0x1 << 17))
 425                        second_pass = 1;
 426        }
 427
 428        if (count != i) {
 429                printf("Count mismatch at node 3\n");
 430                goto end;
 431        }
 432
 433        if (second_pass) {
 434                printf("Unexpected buffers are at node 3\n");
 435                goto end;
 436        } else {
 437                obj_node0 = nb_objs * 2;
 438                for (i = 0; i < obj_node0; i++) {
 439                        data = &mbuf[4][i];
 440                        *graph_field(data) =
 441                                ((uint64_t)tm->test_node[0].idx << 32) | i;
 442                        *graph_field(data) |= (1 << 17);
 443                        if ((i + 1) == obj_node0)
 444                                *graph_field(data) |= (1 << 16);
 445                }
 446                rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[4][0],
 447                                 obj_node0);
 448        }
 449
 450end:
 451        return nb_objs;
 452}
 453
 454static int
 455test_lookup_functions(void)
 456{
 457        test_main_t *tm = &test_main;
 458        int i;
 459
 460        /* Verify the name with ID */
 461        for (i = 1; i < MAX_NODES; i++) {
 462                char *name = rte_node_id_to_name(tm->test_node[i].idx);
 463                if (strcmp(name, node_names[i]) != 0) {
 464                        printf("Test node name verify by ID = %d failed "
 465                               "Expected = %s, got %s\n",
 466                               i, node_names[i], name);
 467                        return -1;
 468                }
 469        }
 470
 471        /* Verify by name */
 472        for (i = 1; i < MAX_NODES; i++) {
 473                uint32_t idx = rte_node_from_name(node_names[i]);
 474                if (idx != tm->test_node[i].idx) {
 475                        printf("Test node ID verify by name = %s failed "
 476                               "Expected = %d, got %d\n",
 477                               node_names[i], tm->test_node[i].idx, idx);
 478                        return -1;
 479                }
 480        }
 481
 482        /* Verify edge count */
 483        for (i = 1; i < MAX_NODES; i++) {
 484                uint32_t count = rte_node_edge_count(tm->test_node[i].idx);
 485                if (count != tm->test_node[i].node.nb_edges) {
 486                        printf("Test number of edges for node = %s failed Expected = %d, got = %d\n",
 487                               tm->test_node[i].node.name,
 488                               tm->test_node[i].node.nb_edges, count);
 489                        return -1;
 490                }
 491        }
 492
 493        /* Verify edge names */
 494        for (i = 1; i < MAX_NODES; i++) {
 495                uint32_t j, count;
 496                char **next_edges;
 497
 498                count = rte_node_edge_get(tm->test_node[i].idx, NULL);
 499                if (count != tm->test_node[i].node.nb_edges * sizeof(char *)) {
 500                        printf("Test number of edge count for node = %s failed Expected = %d, got = %d\n",
 501                               tm->test_node[i].node.name,
 502                               tm->test_node[i].node.nb_edges, count);
 503                        return -1;
 504                }
 505                next_edges = malloc(count);
 506                count = rte_node_edge_get(tm->test_node[i].idx, next_edges);
 507                if (count != tm->test_node[i].node.nb_edges) {
 508                        printf("Test number of edges for node = %s failed Expected = %d, got %d\n",
 509                               tm->test_node[i].node.name,
 510                               tm->test_node[i].node.nb_edges, count);
 511                        free(next_edges);
 512                        return -1;
 513                }
 514
 515                for (j = 0; j < count; j++) {
 516                        if (strcmp(next_edges[j],
 517                                   tm->test_node[i].node.next_nodes[j]) != 0) {
 518                                printf("Edge name miss match, expected = %s got = %s\n",
 519                                       tm->test_node[i].node.next_nodes[j],
 520                                       next_edges[j]);
 521                                free(next_edges);
 522                                return -1;
 523                        }
 524                }
 525                free(next_edges);
 526        }
 527
 528        return 0;
 529}
 530
 531static int
 532test_node_clone(void)
 533{
 534        test_main_t *tm = &test_main;
 535        uint32_t node_id, dummy_id;
 536        int i;
 537
 538        node_id = rte_node_from_name("test_node00");
 539        tm->test_node[0].idx = node_id;
 540
 541        /* Clone with same name, should fail */
 542        dummy_id = rte_node_clone(node_id, "test_node00");
 543        if (!rte_node_is_invalid(dummy_id)) {
 544                printf("Got valid id when clone with same name, Expecting fail\n");
 545                return -1;
 546        }
 547
 548        for (i = 1; i < MAX_NODES; i++) {
 549                tm->test_node[i].idx =
 550                        rte_node_clone(node_id, tm->test_node[i].node.name);
 551                if (rte_node_is_invalid(tm->test_node[i].idx)) {
 552                        printf("Got invalid node id\n");
 553                        return -1;
 554                }
 555        }
 556
 557        /* Clone from cloned node should fail */
 558        dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node");
 559        if (!rte_node_is_invalid(dummy_id)) {
 560                printf("Got valid node id when cloning from cloned node, expected fail\n");
 561                return -1;
 562        }
 563
 564        return 0;
 565}
 566
 567static int
 568test_update_edges(void)
 569{
 570        test_main_t *tm = &test_main;
 571        uint32_t node_id;
 572        uint16_t count;
 573        int i;
 574
 575        node_id = rte_node_from_name("test_node00");
 576        count = rte_node_edge_update(node_id, 0,
 577                                     tm->test_node[0].node.next_nodes,
 578                                     tm->test_node[0].node.nb_edges);
 579        if (count != tm->test_node[0].node.nb_edges) {
 580                printf("Update edges failed expected: %d got = %d\n",
 581                       tm->test_node[0].node.nb_edges, count);
 582                return -1;
 583        }
 584
 585        for (i = 1; i < MAX_NODES; i++) {
 586                count = rte_node_edge_update(tm->test_node[i].idx, 0,
 587                                             tm->test_node[i].node.next_nodes,
 588                                             tm->test_node[i].node.nb_edges);
 589                if (count != tm->test_node[i].node.nb_edges) {
 590                        printf("Update edges failed expected: %d got = %d\n",
 591                               tm->test_node[i].node.nb_edges, count);
 592                        return -1;
 593                }
 594
 595                count = rte_node_edge_shrink(tm->test_node[i].idx,
 596                                             tm->test_node[i].node.nb_edges);
 597                if (count != tm->test_node[i].node.nb_edges) {
 598                        printf("Shrink edges failed\n");
 599                        return -1;
 600                }
 601        }
 602
 603        return 0;
 604}
 605
 606static int
 607test_create_graph(void)
 608{
 609        static const char *node_patterns_dummy[] = {
 610                "test_node_source1",       "test_node00",
 611                "test_node00-test_node11", "test_node00-test_node22",
 612                "test_node00-test_node33", "test_node00-dummy_node",
 613        };
 614        struct rte_graph_param gconf = {
 615                .socket_id = SOCKET_ID_ANY,
 616                .nb_node_patterns = 6,
 617                .node_patterns = node_patterns_dummy,
 618        };
 619        uint32_t dummy_node_id;
 620        uint32_t node_id;
 621
 622        node_id = rte_node_from_name("test_node00");
 623        dummy_node_id = rte_node_clone(node_id, "dummy_node");
 624        if (rte_node_is_invalid(dummy_node_id)) {
 625                printf("Got invalid node id\n");
 626                return -1;
 627        }
 628
 629        graph_id = rte_graph_create("worker0", &gconf);
 630        if (graph_id != RTE_GRAPH_ID_INVALID) {
 631                printf("Graph creation success with isolated node, expected graph creation fail\n");
 632                return -1;
 633        }
 634
 635        gconf.nb_node_patterns = 5;
 636        gconf.node_patterns = node_patterns;
 637        graph_id = rte_graph_create("worker0", &gconf);
 638        if (graph_id == RTE_GRAPH_ID_INVALID) {
 639                printf("Graph creation failed with error = %d\n", rte_errno);
 640                return -1;
 641        }
 642        return 0;
 643}
 644
 645static int
 646test_graph_walk(void)
 647{
 648        struct rte_graph *graph = rte_graph_lookup("worker0");
 649        int i;
 650
 651        if (!graph) {
 652                printf("Graph lookup failed\n");
 653                return -1;
 654        }
 655
 656        for (i = 0; i < 5; i++)
 657                rte_graph_walk(graph);
 658        return 0;
 659}
 660
 661static int
 662test_graph_lookup_functions(void)
 663{
 664        test_main_t *tm = &test_main;
 665        struct rte_node *node;
 666        int i;
 667
 668        for (i = 0; i < MAX_NODES; i++) {
 669                node = rte_graph_node_get(graph_id, tm->test_node[i].idx);
 670                if (!node) {
 671                        printf("rte_graph_node_get, failed for node = %d\n",
 672                               tm->test_node[i].idx);
 673                        return -1;
 674                }
 675
 676                if (tm->test_node[i].idx != node->id) {
 677                        printf("Node id didn't match, expected = %d got = %d\n",
 678                               tm->test_node[i].idx, node->id);
 679                        return 0;
 680                }
 681
 682                if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
 683                        printf("Node name didn't match, expected = %s got %s\n",
 684                               node_names[i], node->name);
 685                        return -1;
 686                }
 687        }
 688
 689        for (i = 0; i < MAX_NODES; i++) {
 690                node = rte_graph_node_get_by_name("worker0", node_names[i]);
 691                if (!node) {
 692                        printf("rte_graph_node_get, failed for node = %d\n",
 693                               tm->test_node[i].idx);
 694                        return -1;
 695                }
 696
 697                if (tm->test_node[i].idx != node->id) {
 698                        printf("Node id didn't match, expected = %d got = %d\n",
 699                               tm->test_node[i].idx, node->id);
 700                        return 0;
 701                }
 702
 703                if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
 704                        printf("Node name didn't match, expected = %s got %s\n",
 705                               node_names[i], node->name);
 706                        return -1;
 707                }
 708        }
 709
 710        return 0;
 711}
 712
 713static int
 714graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie,
 715                         const struct rte_graph_cluster_node_stats *st)
 716{
 717        int i;
 718
 719        RTE_SET_USED(is_first);
 720        RTE_SET_USED(is_last);
 721        RTE_SET_USED(cookie);
 722
 723        for (i = 0; i < MAX_NODES + 1; i++) {
 724                rte_node_t id = rte_node_from_name(node_patterns[i]);
 725                if (id == st->id) {
 726                        if (obj_stats[i] != st->objs) {
 727                                printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n",
 728                                       node_patterns[i], obj_stats[i],
 729                                       st->objs);
 730                                return -1;
 731                        }
 732
 733                        if (fn_calls[i] != st->calls) {
 734                                printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n",
 735                                       node_patterns[i], fn_calls[i],
 736                                       st->calls);
 737                                return -1;
 738                        }
 739                }
 740        }
 741        return 0;
 742}
 743
 744static int
 745test_print_stats(void)
 746{
 747        struct rte_graph_cluster_stats_param s_param;
 748        struct rte_graph_cluster_stats *stats;
 749        const char *pattern = "worker0";
 750
 751        if (!rte_graph_has_stats_feature())
 752                return 0;
 753
 754        /* Prepare stats object */
 755        memset(&s_param, 0, sizeof(s_param));
 756        s_param.f = stdout;
 757        s_param.socket_id = SOCKET_ID_ANY;
 758        s_param.graph_patterns = &pattern;
 759        s_param.nb_graph_patterns = 1;
 760        s_param.fn = graph_cluster_stats_cb_t;
 761
 762        stats = rte_graph_cluster_stats_create(&s_param);
 763        if (stats == NULL) {
 764                printf("Unable to get stats\n");
 765                return -1;
 766        }
 767        /* Clear screen and move to top left */
 768        rte_graph_cluster_stats_get(stats, 0);
 769        rte_graph_cluster_stats_destroy(stats);
 770
 771        return 0;
 772}
 773
 774static int
 775graph_setup(void)
 776{
 777        int i, j;
 778
 779        static const struct rte_mbuf_dynfield graph_dynfield_desc = {
 780                .name = "test_graph_dynfield",
 781                .size = sizeof(graph_dynfield_t),
 782                .align = __alignof__(graph_dynfield_t),
 783        };
 784        graph_dynfield_offset =
 785                rte_mbuf_dynfield_register(&graph_dynfield_desc);
 786        if (graph_dynfield_offset < 0) {
 787                printf("Cannot register mbuf field\n");
 788                return TEST_FAILED;
 789        }
 790
 791        for (i = 0; i <= MAX_NODES; i++) {
 792                for (j = 0; j < MBUFF_SIZE; j++)
 793                        mbuf_p[i][j] = &mbuf[i][j];
 794        }
 795        if (test_node_clone()) {
 796                printf("test_node_clone: fail\n");
 797                return -1;
 798        }
 799        printf("test_node_clone: pass\n");
 800
 801        return 0;
 802}
 803
 804static void
 805graph_teardown(void)
 806{
 807        int id;
 808
 809        id = rte_graph_destroy(rte_graph_from_name("worker0"));
 810        if (id)
 811                printf("Graph Destroy failed\n");
 812}
 813
 814static struct unit_test_suite graph_testsuite = {
 815        .suite_name = "Graph library test suite",
 816        .setup = graph_setup,
 817        .teardown = graph_teardown,
 818        .unit_test_cases = {
 819                TEST_CASE(test_update_edges),
 820                TEST_CASE(test_lookup_functions),
 821                TEST_CASE(test_create_graph),
 822                TEST_CASE(test_graph_lookup_functions),
 823                TEST_CASE(test_graph_walk),
 824                TEST_CASE(test_print_stats),
 825                TEST_CASES_END(), /**< NULL terminate unit test array */
 826        },
 827};
 828
 829static int
 830graph_autotest_fn(void)
 831{
 832        return unit_test_suite_runner(&graph_testsuite);
 833}
 834
 835REGISTER_TEST_COMMAND(graph_autotest, graph_autotest_fn);
 836
 837static int
 838test_node_list_dump(void)
 839{
 840        rte_node_list_dump(stdout);
 841
 842        return TEST_SUCCESS;
 843}
 844REGISTER_TEST_COMMAND(node_list_dump, test_node_list_dump);
 845