On Thu, Dec 1, 2016 at 7:01 AM, Matias Elo <matias....@nokia.com> wrote: > Add new test application for ordered queue functionality and performance > validation. The application sets sequence numbers to incoming packets using > ordered pktin queues and ordered context locks. After being tagged packets > are enqueued to atomic queues based on flow hash (IPv4 5-tuple). In atomic > flow processing the sequence number is validated and packet is sent to > selected output interface. > > Main options: > -m: Input queue type can be changed to atomic or parallel to enable easy > performance comparison. With parallel input queues the packet order is > not maintained. > -r: Number of input queues per interface > -f: Number of atomic flow queues per interface > -e: Number of extra input processing rounds. This can be used to simulate > "fat pipe" traffic processing. > > Signed-off-by: Matias Elo <matias....@nokia.com> > --- > > V3: > - Fixed clang build error > > test/common_plat/performance/.gitignore | 1 + > test/common_plat/performance/Makefile.am | 7 +- > test/common_plat/performance/dummy_crc.h | 493 ++++++++ > test/common_plat/performance/odp_pktio_ordered.c | 1337 > ++++++++++++++++++++++ > 4 files changed, 1837 insertions(+), 1 deletion(-) > create mode 100644 test/common_plat/performance/dummy_crc.h > create mode 100644 test/common_plat/performance/odp_pktio_ordered.c > > diff --git a/test/common_plat/performance/.gitignore > b/test/common_plat/performance/.gitignore > index 1527d25..8bb18f5 100644 > --- a/test/common_plat/performance/.gitignore > +++ b/test/common_plat/performance/.gitignore > @@ -3,6 +3,7 @@ > odp_atomic > odp_crypto > odp_l2fwd > +odp_pktio_ordered > odp_pktio_perf > odp_sched_latency > odp_scheduling > diff --git a/test/common_plat/performance/Makefile.am > b/test/common_plat/performance/Makefile.am > index f184609..790ddae 100644 > --- a/test/common_plat/performance/Makefile.am > +++ b/test/common_plat/performance/Makefile.am > @@ -5,6 +5,7 @@ TESTS_ENVIRONMENT += TEST_DIR=${builddir} > EXECUTABLES = odp_crypto$(EXEEXT) odp_pktio_perf$(EXEEXT) > > COMPILE_ONLY = odp_l2fwd$(EXEEXT) \ > + odp_pktio_ordered$(EXEEXT) \ > odp_sched_latency$(EXEEXT) \ > odp_scheduling$(EXEEXT) > > @@ -22,15 +23,19 @@ bin_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY) > > odp_crypto_LDFLAGS = $(AM_LDFLAGS) -static > odp_crypto_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test > +odp_pktio_ordered_LDFLAGS = $(AM_LDFLAGS) -static > +odp_pktio_ordered_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test > odp_sched_latency_LDFLAGS = $(AM_LDFLAGS) -static > odp_sched_latency_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test > odp_scheduling_LDFLAGS = $(AM_LDFLAGS) -static > odp_scheduling_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test > > noinst_HEADERS = \ > - $(top_srcdir)/test/test_debug.h > + $(top_srcdir)/test/test_debug.h \ > + dummy_crc.h > > dist_odp_crypto_SOURCES = odp_crypto.c > +dist_odp_pktio_ordered_SOURCES = odp_pktio_ordered.c > dist_odp_sched_latency_SOURCES = odp_sched_latency.c > dist_odp_scheduling_SOURCES = odp_scheduling.c > dist_odp_pktio_perf_SOURCES = odp_pktio_perf.c > diff --git a/test/common_plat/performance/dummy_crc.h > b/test/common_plat/performance/dummy_crc.h > new file mode 100644 > index 0000000..38da444 > --- /dev/null > +++ b/test/common_plat/performance/dummy_crc.h > @@ -0,0 +1,493 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +/** > + * @file > + * > + * This file is meant only for generating dummy processing work. > + */ > + > +#include <stdint.h> > +#include <stddef.h> > + > +static const uint32_t dummy_crc32c_tables[8][256] = {{ > + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, > 0x35F1141C, > + 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, > 0x9989AB3B, > + 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, > 0xE235446C, > + 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, > 0xC494A384, > + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, > 0xAF768BBC, > + 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, > 0x33ED7D2A, > + 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, > 0x580F5512, > + 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, > 0x7EAEB2FA, > + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, > 0x05125DAD, > + 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, > 0xA96AE28A, > + 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, > 0xB3109EBF, > + 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, > 0x95B17957, > + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, > 0xFE53516F, > + 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, > 0x42752927, > + 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, > 0x2997011F, > + 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, > 0x0F36E6F7, > + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, > 0x5437877E, > + 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, > 0xF84F3859, > + 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, > 0x83F3D70E, > + 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, > 0xA55230E6, > + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, > 0xCEB018DE, > + 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, > 0x91A6C88C, > + 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, > 0xFA44E0B4, > + 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, > 0xDCE5075C, > + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, > 0xA759E80B, > + 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, > 0x0B21572C, > + 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, > 0x502036A5, > + 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, > 0x7681D14D, > + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, > 0x1D63F975, > + 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, > 0xA145813D, > + 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, > 0xCAA7A905, > + 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, > 0xEC064EED, > + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, > 0xF67C32D8, > + 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, > 0x5A048DFF, > + 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, > 0x21B862A8, > + 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, > 0x07198540, > + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, > 0x6CFBAD78, > + 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, > 0xF0605BEE, > + 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, > 0x9B8273D6, > + 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, > 0xBD23943E, > + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, > 0xC69F7B69, > + 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, > 0x6AE7C44E, > + 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, > +}, > +{ > + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, > 0x5D28F9AB, > + 0x69CF5132, 0x7A6DC945, 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, > 0xA9F36B21, > + 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, 0x3FC5F181, > 0x2C6769F6, > + 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, > 0x45A838C4, > + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, > 0xFFF9CB92, > + 0xCB1E630B, 0xD8BCFB7C, 0x7F8BE302, 0x6C297B75, 0x58CED3EC, > 0x4B6C4B9B, > + 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, 0xE29F20BA, > 0xF13DB8CD, > + 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, > 0x98F2E9FF, > + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, > 0x1D66EB28, > + 0x298143B1, 0x3A23DBC6, 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, > 0xE9BD79A2, > + 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, 0xFF17C604, > 0xECB55E73, > + 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, > 0x857A0F41, > + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, > 0x3F2BFC17, > + 0x0BCC548E, 0x186ECCF9, 0xC0D23785, 0xD370AFF2, 0xE797076B, > 0xF4359F1C, > + 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, 0x5DC6F43D, > 0x4E646C4A, > + 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, > 0x27AB3D78, > + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, > 0xDDB4DCAD, > + 0xE9537434, 0xFAF1EC43, 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, > 0x296F4E27, > + 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, 0xBF59D487, > 0xACFB4CF0, > + 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, > 0xC5341DC2, > + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, > 0x7F65EE94, > + 0x4B82460D, 0x5820DE7A, 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, > 0xCF245260, > + 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, 0x66D73941, > 0x7575A136, > + 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, > 0x1CBAF004, > + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, > 0x992EF2D3, > + 0xADC95A4A, 0xBE6BC23D, 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, > 0x6DF56059, > + 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, 0x844819FB, > 0x97EA818C, > + 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, > 0xFE25D0BE, > + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, > 0x447423E8, > + 0x70938B71, 0x63311306, 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, > 0x8F6A40E3, > + 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, 0x26992BC2, > 0x353BB3B5, > + 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, > 0x5CF4E287, > + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, > 0x59FCC556, > + 0x6D1B6DCF, 0x7EB9F5B8, 0x99C0FF45, 0x8A626732, 0xBE85CFAB, > 0xAD2757DC, > + 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, 0x3B11CD7C, > 0x28B3550B, > + 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, > 0x417C0439, > + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, > 0xFB2DF76F, > + 0xCFCA5FF6, 0xDC68C781, 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, > 0x4FB87766, > + 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, 0xE64B1C47, > 0xF5E98430, > + 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, > 0x9C26D502, > + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, > 0x19B2D7D5, > + 0x2D557F4C, 0x3EF7E73B, 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, > 0xED69455F, > + 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, > +}, > +{ > + 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, > 0x3B9F3664, > + 0xD1B1F617, 0x74F06469, 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, > 0xD27FFEB6, > + 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, 0x70A27D8A, > 0xD5E3EFF4, > + 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, > 0x045219E3, > + 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, > 0x736C752B, > + 0x9942B558, 0x3C032726, 0xE144FB14, 0x4405696A, 0xAE2BA919, > 0x0B6A3B67, > + 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, 0xD915C5D1, > 0x7C5457AF, > + 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, > 0xADE5A1B8, > + 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, > 0xAA79B0FA, > + 0x40577089, 0xE516E2F7, 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, > 0x43997828, > + 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, 0xC76580D9, > 0x622412A7, > + 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, > 0xB395E4B0, > + 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, > 0xC4AB8878, > + 0x2E85480B, 0x8BC4DA75, 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, > 0x5DE93D20, > + 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, 0x8F96C396, > 0x2AD751E8, > + 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, > 0xFB66A7FF, > + 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, > 0x1DBE4DA9, > + 0xF7908DDA, 0x52D11FA4, 0x1E704508, 0xBB31D776, 0x511F1705, > 0xF45E857B, > + 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, 0x56830647, > 0xF3C29439, > + 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, > 0x2273622E, > + 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, > 0x554D0EE6, > + 0xBF63CE95, 0x1A225CEB, 0x8B277743, 0x2E66E53D, 0xC448254E, > 0x6109B730, > + 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, 0xB3764986, > 0x1637DBF8, > + 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, > 0xC7862DEF, > + 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, > 0xC01A3CAD, > + 0x2A34FCDE, 0x8F756EA0, 0xC3D4340C, 0x6695A672, 0x8CBB6601, > 0x29FAF47F, > + 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, 0x6A638C57, > 0xCF221E29, > + 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, > 0x1E93E83E, > + 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, > 0x69AD84F6, > + 0x83834485, 0x26C2D6FB, 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, > 0xF0EF31AE, > + 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, 0x2290CF18, > 0x87D15D66, > + 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, > 0x5660AB71, > + 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, > 0x77DDC1FE, > + 0x9DF3018D, 0x38B293F3, 0x7413C95F, 0xD1525B21, 0x3B7C9B52, > 0x9E3D092C, > + 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, 0x3CE08A10, > 0x99A1186E, > + 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, > 0x4810EE79, > + 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, > 0x3F2E82B1, > + 0xD50042C2, 0x7041D0BC, 0xAD060C8E, 0x08479EF0, 0xE2695E83, > 0x4728CCFD, > + 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, 0x9557324B, > 0x3016A035, > + 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, > 0xE1A75622, > + 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, > 0xE63B4760, > + 0x0C158713, 0xA954156D, 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, > 0x0FDB8FB2, > + 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8, > +}, > +{ > + 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, > 0xA6679B4B, > + 0xC4451272, 0x1900B8CA, 0xF64463E6, 0x2B01C95E, 0x49234067, > 0x9466EADF, > + 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, 0xE964B13D, > 0x34211B85, > + 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, > 0xF06409F7, > + 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, > 0xB9474990, > + 0xDB65C0A9, 0x06206A11, 0xD725148B, 0x0A60BE33, 0x6842370A, > 0xB5079DB2, > + 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, 0x2161776D, > 0xFC24DDD5, > + 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, > 0x3861CFA7, > + 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, > 0x98263EFD, > + 0xFA04B7C4, 0x27411D7C, 0xC805C650, 0x15406CE8, 0x7762E5D1, > 0xAA274F69, > + 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, 0xABA65FE7, > 0x76E3F55F, > + 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, > 0xB2A6E72D, > + 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, > 0xFB85A74A, > + 0x99A72E73, 0x44E284CB, 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, > 0x20E067E3, > + 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, 0xB4868D3C, > 0x69C32784, > + 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, > 0xAD8635F6, > + 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, > 0xDAE4D027, > + 0xB8C6591E, 0x6583F3A6, 0x8AC7288A, 0x57828232, 0x35A00B0B, > 0xE8E5A1B3, > + 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, 0x95E7FA51, > 0x48A250E9, > + 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, > 0x8CE7429B, > + 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, > 0xC5C402FC, > + 0xA7E68BC5, 0x7AA3217D, 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, > 0x30824006, > + 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, 0xA4E4AAD9, > 0x79A10061, > + 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, > 0xBDE41213, > + 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, > 0x1DA3E349, > + 0x7F816A70, 0xA2C4C0C8, 0x4D801BE4, 0x90C5B15C, 0xF2E73865, > 0x2FA292DD, > + 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, 0x8585DDB4, > 0x58C0770C, > + 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, > 0x9C85657E, > + 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, > 0xD5A62519, > + 0xB784AC20, 0x6AC10698, 0x6CE16C89, 0xB1A4C631, 0xD3864F08, > 0x0EC3E5B0, > + 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, 0x9AA50F6F, > 0x47E0A5D7, > + 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, > 0x83A5B7A5, > + 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, > 0x5F610D93, > + 0x3D4384AA, 0xE0062E12, 0x0F42F53E, 0xD2075F86, 0xB025D6BF, > 0x6D607C07, > + 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, 0x106227E5, > 0xCD278D5D, > + 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, > 0x09629F2F, > + 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, > 0x4041DF48, > + 0x22635671, 0xFF26FCC9, 0x2E238253, 0xF36628EB, 0x9144A1D2, > 0x4C010B6A, > + 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, 0xD867E1B5, > 0x05224B0D, > + 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, > 0xC167597F, > + 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, > 0x6120A825, > + 0x0302211C, 0xDE478BA4, 0x31035088, 0xEC46FA30, 0x8E647309, > 0x5321D9B1, > + 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842, > +}, > +{ > + 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, > 0xD854D11C, > + 0x906761E8, 0xA8760E44, 0xC5670B91, 0xFD76643D, 0xB545D4C9, > 0x8D54BB65, > + 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, 0x8F2261D3, > 0xB7330E7F, > + 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, > 0x27546F97, > + 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, > 0x9211BB5E, > + 0xDA220BAA, 0xE2336406, 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, > 0x539B05A3, > + 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, 0xDECFBEC6, > 0xE6DED16A, > + 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, > 0x76B9B082, > + 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, > 0x4CDE0598, > + 0x04EDB56C, 0x3CFCDAC0, 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, > 0x19DE6FE1, > + 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, 0x37516AAE, > 0x0F400502, > + 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, > 0x9F2764EA, > + 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, > 0x2A62B023, > + 0x625100D7, 0x5A406F7B, 0xB8730B7D, 0x806264D1, 0xC851D425, > 0xF040BB89, > + 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, 0x7D1400EC, > 0x45056F40, > + 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, > 0xD5620EA8, > + 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, > 0xF4AD0EE5, > + 0xBC9EBE11, 0x848FD1BD, 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, > 0xA1AD649C, > + 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, 0xA3DBBE2A, > 0x9BCAD186, > + 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, > 0x0BADB06E, > + 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, > 0xBEE864A7, > + 0xF6DBD453, 0xCECABBFF, 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, > 0x269165A8, > + 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, 0xABC5DECD, > 0x93D4B161, > + 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, > 0x03B3D089, > + 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, > 0x39D46593, > + 0x71E7D567, 0x49F6BACB, 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, > 0x6CD40FEA, > + 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, 0x750A600B, > 0x4D1B0FA7, > + 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, > 0xDD7C6E4F, > + 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, > 0x6839BA86, > + 0x200A0A72, 0x181B65DE, 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, > 0xB21BB12C, > + 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, 0x3F4F0A49, > 0x075E65E5, > + 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, > 0x9739040D, > + 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, > 0x81A76EEE, > + 0xC994DE1A, 0xF185B1B6, 0x9C94B463, 0xA485DBCF, 0xECB66B3B, > 0xD4A70497, > + 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, 0xD6D1DE21, > 0xEEC0B18D, > + 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, > 0x7EA7D065, > + 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, > 0xCBE204AC, > + 0x83D1B458, 0xBBC0DBF4, 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, > 0x0A68BA51, > + 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, 0x873C0134, > 0xBF2D6E98, > + 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, > 0x2F4A0F70, > + 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, > 0x152DBA6A, > + 0x5D1E0A9E, 0x650F6532, 0x081E60E7, 0x300F0F4B, 0x783CBFBF, > 0x402DD013, > + 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3, > +}, > +{ > + 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, > 0x5DC55C6E, > + 0x697997B4, 0x8649FCAD, 0x6006181F, 0x8F367306, 0xBB8AB8DC, > 0x54BAD3C5, > + 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, 0xC00C303E, > 0x2F3C5B27, > + 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, > 0x4645CC93, > + 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, > 0xFDCF744F, > + 0xC973BF95, 0x2643D48C, 0x85F4168D, 0x6AC47D94, 0x5E78B64E, > 0xB148DD57, > + 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, 0xE5F20E92, > 0x0AC2658B, > + 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, > 0x63BBF23F, > + 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, > 0x183D7ADD, > + 0x2C81B107, 0xC3B1DA1E, 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, > 0x1142F576, > + 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, 0x0E045BEB, > 0xE13430F2, > + 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, > 0x884DA746, > + 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, > 0x33C71F9A, > + 0x077BD440, 0xE84BBF59, 0xCE086BD5, 0x213800CC, 0x1584CB16, > 0xFAB4A00F, > + 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, 0xAE0E73CA, > 0x413E18D3, > + 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, > 0x28478F67, > + 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, > 0xD6351108, > + 0xE289DAD2, 0x0DB9B1CB, 0xEBF65579, 0x04C63E60, 0x307AF5BA, > 0xDF4A9EA3, > + 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, 0x4BFC7D58, > 0xA4CC1641, > + 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, > 0xCDB581F5, > + 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, > 0x763F3929, > + 0x4283F2F3, 0xADB399EA, 0x1C08B7D6, 0xF338DCCF, 0xC7841715, > 0x28B47C0C, > + 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, 0x7C0EAFC9, > 0x933EC4D0, > + 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, > 0xFA475364, > + 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, > 0x81C1DB86, > + 0xB57D105C, 0x5A4D7B45, 0xBC029FF7, 0x5332F4EE, 0x678E3F34, > 0x88BE542D, > + 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, 0x99FCA15B, > 0x76CCCA42, > + 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, > 0x1FB55DF6, > + 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, > 0xA43FE52A, > + 0x90832EF0, 0x7FB345E9, 0x59F09165, 0xB6C0FA7C, 0x827C31A6, > 0x6D4C5ABF, > + 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, 0x39F6897A, > 0xD6C6E263, > + 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, > 0xBFBF75D7, > + 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, > 0x4FC9B053, > + 0x7B757B89, 0x94451090, 0x720AF422, 0x9D3A9F3B, 0xA98654E1, > 0x46B63FF8, > + 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, 0xD200DC03, > 0x3D30B71A, > + 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, > 0x544920AE, > + 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, > 0xEFC39872, > + 0xDB7F53A8, 0x344F38B1, 0x97F8FAB0, 0x78C891A9, 0x4C745A73, > 0xA344316A, > + 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, 0xF7FEE2AF, > 0x18CE89B6, > + 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, > 0x71B71E02, > + 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, > 0x0A3196E0, > + 0x3E8D5D3A, 0xD1BD3623, 0x37F2D291, 0xD8C2B988, 0xEC7E7252, > 0x034E194B, > + 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C, > +}, > +{ > + 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, > 0xCDE3E919, > + 0x75E69C41, 0x1DE5B089, 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, > 0xF628880B, > + 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, 0x9C5BFAA6, > 0xF458D66E, > + 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, > 0x81BE4A2F, > + 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, > 0x1F95EEEC, > + 0xA7909BB4, 0xCF93B77C, 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, > 0x855EF6E5, > + 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, 0x73767EEE, > 0x1B755226, > + 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, > 0x6E93CE67, > + 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, > 0x6CE39002, > + 0xD4E6E55A, 0xBCE5C992, 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, > 0x5728F110, > + 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, 0x7AB7077A, > 0x12B42BB2, > + 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, > 0x6752B7F3, > + 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, > 0xF9791330, > + 0x417C6668, 0x297F4AA0, 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, > 0x5EE98884, > + 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, 0xA8C1008F, > 0xC0C22C47, > + 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, > 0xB524B006, > + 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, > 0x8A0F6DDE, > + 0x320A1886, 0x5A09344E, 0x09C17994, 0x61C2555C, 0xD9C72004, > 0xB1C40CCC, > + 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, 0xDBB77E61, > 0xB3B452A9, > + 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, > 0xC652CEE8, > + 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, > 0x58796A2B, > + 0xE07C1F73, 0x887F33BB, 0xF56E0EF4, 0x9D6D223C, 0x25685764, > 0x4D6B7BAC, > + 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, 0xBB43F3A7, > 0xD340DF6F, > + 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, > 0xA6A6432E, > + 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, > 0xA4D61D4B, > + 0x1CD36813, 0x74D044DB, 0x27180901, 0x4F1B25C9, 0xF71E5091, > 0x9F1D7C59, > + 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, 0xC8358D49, > 0xA036A181, > + 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, > 0xD5D03DC0, > + 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, > 0x4BFB9903, > + 0xF3FEEC5B, 0x9BFDC093, 0x546E77EF, 0x3C6D5B27, 0x84682E7F, > 0xEC6B02B7, > + 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, 0x1A438ABC, > 0x7240A674, > + 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, > 0x07A63A35, > + 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, > 0x423AE097, > + 0xFA3F95CF, 0x923CB907, 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, > 0x79F18185, > + 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, 0x1382F328, > 0x7B81DFE0, > + 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, > 0x0E6743A1, > + 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, > 0x904CE762, > + 0x2849923A, 0x404ABEF2, 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, > 0x0A87FF6B, > + 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, 0xFCAF7760, > 0x94AC5BA8, > + 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, > 0xE14AC7E9, > + 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, > 0xE33A998C, > + 0x5B3FECD4, 0x333CC01C, 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, > 0xD8F1F89E, > + 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F, > +}, > +{ > + 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, > 0x6821FF4A, > + 0xB3657823, 0xFA590504, 0x423B04DA, 0x0B0779FD, 0xD043FE94, > 0x997F83B3, > + 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, 0x847609B4, > 0xCD4A7493, > + 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, > 0x7E2F0CB0, > + 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, > 0xAE6CF224, > + 0x7528754D, 0x3C14086A, 0x0D006599, 0x443C18BE, 0x9F789FD7, > 0xD644E2F0, > + 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, 0x4F3B6143, > 0x06071C64, > + 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, > 0xB5626447, > + 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, > 0xE1579367, > + 0x3A13140E, 0x732F6929, 0xCB4D68F7, 0x827115D0, 0x593592B9, > 0x1009EF9E, > + 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, 0x1A00CB32, > 0x533CB615, > + 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, > 0xE059CE36, > + 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, > 0x301A30A2, > + 0xEB5EB7CB, 0xA262CAEC, 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, > 0x453245EF, > + 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, 0xDC4DC65C, > 0x9571BB7B, > + 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, > 0x2614C358, > + 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, > 0x7F2151E1, > + 0xA465D688, 0xED59ABAF, 0x553BAA71, 0x1C07D756, 0xC743503F, > 0x8E7F2D18, > + 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, 0x9376A71F, > 0xDA4ADA38, > + 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, > 0x692FA21B, > + 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, > 0xB96C5C8F, > + 0x6228DBE6, 0x2B14A6C1, 0x34019664, 0x7D3DEB43, 0xA6796C2A, > 0xEF45110D, > + 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, 0x763A92BE, > 0x3F06EF99, > + 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, > 0x8C6397BA, > + 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, > 0xD856609A, > + 0x0312E7F3, 0x4A2E9AD4, 0xF24C9B0A, 0xBB70E62D, 0x60346144, > 0x29081C63, > + 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, 0x3901F3FD, > 0x703D8EDA, > + 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, > 0xC358F6F9, > + 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, > 0x131B086D, > + 0xC85F8F04, 0x8163F223, 0xBD77FA49, 0xF44B876E, 0x2F0F0007, > 0x66337D20, > + 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, 0xFF4CFE93, > 0xB67083B4, > + 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, > 0x0515FB97, > + 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, > 0x4620A21C, > + 0x9D642575, 0xD4585852, 0x6C3A598C, 0x250624AB, 0xFE42A3C2, > 0xB77EDEE5, > + 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, 0xAA7754E2, > 0xE34B29C5, > + 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, > 0x502E51E6, > + 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, > 0x806DAF72, > + 0x5B29281B, 0x1215553C, 0x230138CF, 0x6A3D45E8, 0xB179C281, > 0xF845BFA6, > + 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, 0x613A3C15, > 0x28064132, > + 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, > 0x9B633911, > + 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, > 0xCF56CE31, > + 0x14124958, 0x5D2E347F, 0xE54C35A1, 0xAC704886, 0x7734CFEF, > 0x3E08B2C8, > + 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5, > +} }; > + > +#define DUMMY_CRC32_UPD(crc, n) \ > + (dummy_crc32c_tables[(n)][(crc) & 0xff] ^ \ > + dummy_crc32c_tables[(n) - 1][((crc) >> 8) & 0xff]) > + > +static inline uint32_t dummy_crc32c_u32(uint32_t data, uint32_t init_val) > +{ > + uint32_t crc, term1, term2; > + > + crc = init_val; > + crc ^= data; > + > + term1 = DUMMY_CRC32_UPD(crc, 3); > + term2 = crc >> 16; > + crc = term1 ^ DUMMY_CRC32_UPD(term2, 1); > + > + return crc; > +} > + > +static inline uint32_t dummy_crc32c_u64(uint64_t data, uint32_t init_val) > +{ > + union { > + uint64_t u64; > + uint32_t u32[2]; > + } d; > + d.u64 = data; > + > + uint32_t crc, term1, term2; > + > + crc = init_val; > + crc ^= d.u32[0]; > + > + term1 = DUMMY_CRC32_UPD(crc, 7); > + term2 = crc >> 16; > + crc = term1 ^ DUMMY_CRC32_UPD(term2, 5); > + term1 = DUMMY_CRC32_UPD(d.u32[1], 3); > + term2 = d.u32[1] >> 16; > + crc ^= term1 ^ DUMMY_CRC32_UPD(term2, 1); > + > + return crc; > +} > + > +static inline uint32_t dummy_hash_crc32c(const void *data, uint32_t data_len, > + uint32_t init_val) > +{ > + size_t i; > + uint64_t temp = 0; > + uintptr_t pd = (uintptr_t)data; > + > + for (i = 0; i < data_len / 8; i++) { > + init_val = dummy_crc32c_u64(*(const uint64_t *)pd, init_val); > + pd += 8; > + } > + > + switch (7 - (data_len & 0x07)) { > + case 0: > + temp |= (uint64_t)*((const uint8_t *)pd + 6) << 48; > + /* Fallthrough */ > + case 1: > + temp |= (uint64_t)*((const uint8_t *)pd + 5) << 40; > + /* Fallthrough */ > + case 2: > + temp |= (uint64_t)*((const uint8_t *)pd + 4) << 32; > + temp |= *(const uint32_t *)pd; > + init_val = dummy_crc32c_u64(temp, init_val); > + break; > + case 3: > + init_val = dummy_crc32c_u32(*(const uint32_t *)pd, init_val); > + break; > + case 4: > + temp |= *((const uint8_t *)pd + 2) << 16; > + /* Fallthrough */ > + case 5: > + temp |= *((const uint8_t *)pd + 1) << 8; > + /* Fallthrough */ > + case 6: > + temp |= *(const uint8_t *)pd; > + init_val = dummy_crc32c_u32(temp, init_val); > + /* Fallthrough */ > + default: > + break; > + } > + > + return init_val; > +} > diff --git a/test/common_plat/performance/odp_pktio_ordered.c > b/test/common_plat/performance/odp_pktio_ordered.c > new file mode 100644 > index 0000000..08b840d > --- /dev/null > +++ b/test/common_plat/performance/odp_pktio_ordered.c > @@ -0,0 +1,1337 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * @example odp_pktio_ordered.c ODP ordered pktio test application > + */ > + > +/** enable strtok */ > +#ifndef _GNU_SOURCE > +#define _GNU_SOURCE > +#endif > + > +#include <stdlib.h> > +#include <getopt.h> > +#include <unistd.h> > +#include <errno.h> > +#include <inttypes.h> > + > +#include <test_debug.h> > +#include <dummy_crc.h> > + > +#include <odp_api.h> > +#include <odp/helper/linux.h> > +#include <odp/helper/eth.h> > +#include <odp/helper/ip.h> > +#include <odp/helper/udp.h> > + > +/** Jenkins hash support. > + * > + * Copyright (C) 2006 Bob Jenkins (bob_jenk...@burtleburtle.net) > + * > + * http://burtleburtle.net/bob/hash/ > + * > + * These are the credits from Bob's sources: > + * > + * lookup3.c, by Bob Jenkins, May 2006, Public Domain. > + * > + * These are functions for producing 32-bit hashes for hash table lookup. > + * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() > + * are externally useful functions. Routines to test the hash are included > + * if SELF_TEST is defined. You can use this free for any purpose. It's in > + * the public domain. It has no warranty. > + * > + * $FreeBSD$ > + */ > +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) > + > +#define mix(a, b, c) \ > +{ \ > + a -= c; a ^= rot(c, 4); c += b; \ > + b -= a; b ^= rot(a, 6); a += c; \ > + c -= b; c ^= rot(b, 8); b += a; \ > + a -= c; a ^= rot(c, 16); c += b; \ > + b -= a; b ^= rot(a, 19); a += c; \ > + c -= b; c ^= rot(b, 4); b += a; \ > +} > + > +#define final(a, b, c) \ > +{ \ > + c ^= b; c -= rot(b, 14); \ > + a ^= c; a -= rot(c, 11); \ > + b ^= a; b -= rot(a, 25); \ > + c ^= b; c -= rot(b, 16); \ > + a ^= c; a -= rot(c, 4); \ > + b ^= a; b -= rot(a, 14); \ > + c ^= b; c -= rot(b, 24); \ > +} > + > +#define JHASH_GOLDEN_RATIO 0x9e3779b9 > + > +/** Maximum number of worker threads */ > +#define MAX_WORKERS 64 > + > +/** Number of packet buffers in the memory pool */ > +#define PKT_POOL_SIZE 8192 > + > +/** Buffer size of the packet pool buffer in bytes*/ > +#define PKT_POOL_BUF_SIZE 1856 > + > +/** Packet user area size in bytes */ > +#define PKT_UAREA_SIZE 32 > + > +/** Maximum number of packets in a burst */ > +#define MAX_PKT_BURST 32 > + > +/** Maximum number of pktio queues per interface */ > +#define MAX_QUEUES 32 > + > +/** Maximum number of pktio interfaces */ > +#define MAX_PKTIOS 8 > + > +/** Maximum number of packet flows */ > +#define MAX_FLOWS 128 > + > +ODP_STATIC_ASSERT(MAX_PKTIOS < MAX_FLOWS, > + "MAX_FLOWS must be greater than MAX_PKTIOS\n"); > + > +/** Minimum valid packet length */ > +#define MIN_PACKET_LEN (ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN + ODPH_UDPHDR_LEN) > + > +/** Default number of input queues */ > +#define DEF_NUM_RX_QUEUES 1 > + > +/** Default number of flows */ > +#define DEF_NUM_FLOWS 12 > + > +/** Default number of extra processing rounds */ > +#define DEF_EXTRA_ROUNDS 15 > + > +/** Default statistics print interval in seconds */ > +#define DEF_STATS_INT 1 > + > +/** Get rid of path in filename - only for unix-type paths using '/' */ > +#define NO_PATH(file_name) (strrchr((file_name), '/') ? \ > + strrchr((file_name), '/') + 1 : (file_name)) > + > +/** > + * Packet input mode > + */ > +typedef enum pktin_mode_t { > + SCHED_ORDERED = 0, > + SCHED_ATOMIC, > + SCHED_PARALLEL > +} pktin_mode_t; > + > +/** > + * Parsed command line application arguments > + */ > +typedef struct { > + int cpu_count; /**< CPU count */ > + int if_count; /**< Number of interfaces to be used */ > + int addr_count; /**< Number of dst addresses to be used */ > + int num_rx_q; /**< Number of input queues per interface */ > + int num_flows; /**< Number of packet flows */ > + int extra_rounds; /**< Number of extra input processing rounds > */ > + char **if_names; /**< Array of pointers to interface names */ > + odph_ethaddr_t addrs[MAX_PKTIOS]; /**< Array of dst addresses */ > + pktin_mode_t in_mode; /**< Packet input mode */ > + int time; /**< Time in seconds to run. */ > + int accuracy; /**< Statistics print interval */ > + char *if_str; /**< Storage for interface names */ > +} appl_args_t; > + > +static int exit_threads; /**< Break workers loop if set to 1 */ > + > +/** > + * Queue context > + */ > +typedef struct { > + odp_bool_t input_queue; /**< Input queue */ > + uint64_t idx; /**< Queue index */ > + uint64_t seq[MAX_FLOWS]; /**< Per flow sequence numbers */ > +} qcontext_t; > + > +/** > + * Flow info stored in the packet user area > + */ > +typedef struct { > + uint64_t seq; /**< Sequence number */ > + uint32_t crc; /**< CRC hash */ > + uint16_t idx; /**< Flow index */ > + uint8_t src_idx; /**< Source port index */ > + uint8_t dst_idx; /**< Destination port index */ > + > +} flow_t; > +ODP_STATIC_ASSERT(sizeof(flow_t) <= PKT_UAREA_SIZE, > + "Flow data doesn't fit in the packet user area\n"); > + > +/** > + * Statistics > + */ > +typedef union { > + struct { > + /** Number of forwarded packets */ > + uint64_t packets; > + /** Packets dropped due to a receive error */ > + uint64_t rx_drops; > + /** Packets dropped due to a transmit error */ > + uint64_t tx_drops; > + /** Packets with invalid sequence number */ > + uint64_t invalid_seq; > + } s; > + > + uint8_t padding[ODP_CACHE_LINE_SIZE]; > +} stats_t ODP_ALIGNED_CACHE; > + > +/** > + * IPv4 5-tuple > + */ > +typedef struct { > + int32_t src_ip; > + int32_t dst_ip; > + int16_t src_port; > + int16_t dst_port; > + int8_t proto; > + int8_t pad0; > + int16_t pad1; > +} ipv4_tuple5_t; > + > +/** > + * Packet headers > + */ > +typedef struct { > + odph_ethhdr_t *eth; > + odph_ipv4hdr_t *ipv4; > + odph_udphdr_t *udp; > +} packet_hdr_t; > + > +/** > + * Thread specific arguments > + */ > +typedef struct thread_args_t { > + stats_t *stats; /**< Pointer to per thread statistics */ > +} thread_args_t; > + > +/** > + * Grouping of all global data > + */ > +typedef struct { > + /** Per thread packet stats */ > + stats_t stats[MAX_WORKERS]; > + /** Application (parsed) arguments */ > + appl_args_t appl; > + /** Thread specific arguments */ > + thread_args_t thread[MAX_WORKERS]; > + /** Table of port ethernet addresses */ > + odph_ethaddr_t port_eth_addr[MAX_PKTIOS]; > + /** Table of dst ethernet addresses */ > + odph_ethaddr_t dst_eth_addr[MAX_PKTIOS]; > + /** Table of dst ports */ > + int dst_port[MAX_PKTIOS]; > + /** Table of atomic queues for flows */ > + odp_queue_t fqueue[MAX_PKTIOS][MAX_FLOWS]; > + /** Table of flow queue contexts */ > + qcontext_t flow_qcontext[MAX_PKTIOS][MAX_FLOWS]; > + /** Table of input queue contexts */ > + qcontext_t input_qcontext[MAX_PKTIOS][MAX_QUEUES]; > + /** Table of pktio handles */ > + struct { > + odp_pktio_t pktio; > + odp_pktout_queue_t pktout[MAX_FLOWS]; > + odp_queue_t pktin[MAX_QUEUES]; > + int num_rx_queue; > + int num_tx_queue; > + } pktios[MAX_PKTIOS]; > +} args_t; > + > +/** Global pointer to args */ > +static args_t *gbl_args; > + > +/** Global barrier to synchronize main and workers */ > +static odp_barrier_t barrier; > + > +/** > + * Lookup the destination port for a given packet > + * > + * @param pkt ODP packet handle > + */ > +static inline int lookup_dest_port(odp_packet_t pkt) > +{ > + int i, src_idx; > + odp_pktio_t pktio_src; > + > + pktio_src = odp_packet_input(pkt); > + > + for (src_idx = -1, i = 0; gbl_args->pktios[i].pktio > + != ODP_PKTIO_INVALID; i++) > + if (gbl_args->pktios[i].pktio == pktio_src) > + src_idx = i; > + > + if (src_idx == -1) > + LOG_ABORT("Failed to determine pktio input\n"); > + > + return gbl_args->dst_port[src_idx]; > +} > + > +/** > + * Map required packet headers > + * > + * @param pkt Packet handle > + * @param hdr[out] Packet headers > + * > + * @retval 0 on success > + * @retval -1 on failure > + */ > +static inline int packet_hdr(odp_packet_t pkt, packet_hdr_t *hdr) > +{ > + uint8_t *udp; > + uint16_t eth_type; > + uint8_t ihl; > + > + if (odp_unlikely(odp_packet_seg_len(pkt) < MIN_PACKET_LEN)) > + return -1; > + > + if (odp_unlikely(!odp_packet_has_eth(pkt))) > + return -1; > + > + hdr->eth = odp_packet_l2_ptr(pkt, NULL); > + eth_type = odp_be_to_cpu_16(hdr->eth->type); > + if (odp_unlikely(eth_type != ODPH_ETHTYPE_IPV4)) > + return -1; > + > + hdr->ipv4 = (odph_ipv4hdr_t *)(hdr->eth + 1); > + if (odp_unlikely(hdr->ipv4->proto != ODPH_IPPROTO_UDP)) > + return -1; > + > + ihl = ODPH_IPV4HDR_IHL(hdr->ipv4->ver_ihl); > + if (odp_unlikely(ihl < ODPH_IPV4HDR_IHL_MIN)) > + return -1; > + > + udp = (uint8_t *)hdr->ipv4 + (ihl * 4); > + > + hdr->udp = (odph_udphdr_t *)udp; > + > + return 0; > +} > + > +/** > + * Compute hash from a 5-tuple > + * > + * @param key IPv4 5-tuple > + * > + * @return 32-bit hash value > + */ > +static inline uint64_t calc_ipv4_5tuple_hash(ipv4_tuple5_t *tuple) > +{ > + uint32_t a, b, c; > + > + a = tuple->proto + JHASH_GOLDEN_RATIO; > + b = tuple->src_ip + JHASH_GOLDEN_RATIO; > + c = tuple->dst_ip + JHASH_GOLDEN_RATIO; > + > + mix(a, b, c); > + > + a += (tuple->src_port << 16) + tuple->dst_port + JHASH_GOLDEN_RATIO; > + final(a, b, c); > + > + return c; > +} > + > +/** > + * Compute packet flow index > + * > + * @param hdr Packet headers > + * > + * @return Flow index > + */ > +static inline uint64_t calc_flow_idx(packet_hdr_t *hdr) > +{ > + ipv4_tuple5_t tuple; > + uint64_t idx; > + > + tuple.dst_ip = odp_be_to_cpu_32(hdr->ipv4->dst_addr); > + tuple.src_ip = odp_be_to_cpu_32(hdr->ipv4->src_addr); > + tuple.proto = hdr->ipv4->proto; > + tuple.src_port = odp_be_to_cpu_16(hdr->udp->src_port); > + tuple.dst_port = odp_be_to_cpu_16(hdr->udp->dst_port); > + tuple.pad0 = 0; > + tuple.pad1 = 0; > + idx = calc_ipv4_5tuple_hash(&tuple); > + > + return idx % gbl_args->appl.num_flows; > +} > + > +/** > + * Fill packet's eth addresses according to the destination port > + * > + * @param hdr[out] Packet headers > + * @param dst_port Destination port > + */ > +static inline void fill_eth_addrs(packet_hdr_t *hdr, int dst_port) > +{ > + hdr->eth->src = gbl_args->port_eth_addr[dst_port]; > + hdr->eth->dst = gbl_args->dst_eth_addr[dst_port]; > +} > + > +/** > + * Process flow queue > + * > + * @param ev_tbl Array of events > + * @param num Number of events in the array > + * @param stats Pointer for storing thread statistics > + * @param qcontext Source queue context > + * @param pktout Arrays of output queues > + */ > +static inline void process_flow(odp_event_t ev_tbl[], int num, stats_t > *stats, > + qcontext_t *qcontext, > + odp_pktout_queue_t pktout[][MAX_FLOWS]) > +{ > + odp_packet_t pkt; > + flow_t *flow; > + uint64_t queue_seq; > + int dst_if; > + int i; > + int sent; > + > + for (i = 0; i < num; i++) { > + pkt = odp_packet_from_event(ev_tbl[i]); > + > + flow = odp_packet_user_area(pkt); > + > + queue_seq = qcontext->seq[flow->src_idx]; > + > + /* Check sequence number */ > + if (gbl_args->appl.in_mode != SCHED_PARALLEL && > + odp_unlikely(flow->seq != queue_seq)) { > + printf("Invalid sequence number: packet_seq=%" PRIu64 > "" > + " queue_seq=%" PRIu64 ", src_if=%" PRIu8 ", " > + "dst_if=%" PRIu8 ", flow=%" PRIu16 "\n", > + flow->seq, queue_seq, flow->src_idx, > + flow->dst_idx, flow->idx); > + qcontext->seq[flow->src_idx] = flow->seq + 1; > + stats->s.invalid_seq++; > + } else { > + qcontext->seq[flow->src_idx]++; > + } > + > + dst_if = flow->dst_idx; > + sent = odp_pktout_send(pktout[dst_if][flow->idx], &pkt, 1); > + > + if (odp_unlikely(sent != 1)) { > + stats->s.tx_drops++; > + odp_packet_free(pkt); > + } > + stats->s.packets++; > + } > +} > + > +/** > + * Process input queue > + * > + * @param ev_tbl Array of events > + * @param num Number of events in the array > + * @param stats Pointer for storing thread statistics > + * @param qcontext Source queue context > + */ > +static inline void process_input(odp_event_t ev_tbl[], int num, stats_t > *stats, > + qcontext_t *qcontext) > +{ > + flow_t *flow; > + flow_t *flow_tbl[MAX_PKT_BURST]; > + int ret; > + int i, j; > + int pkts = 0; > + > + for (i = 0; i < num; i++) { > + odp_packet_t pkt; > + packet_hdr_t hdr; > + int flow_idx; > + > + pkt = odp_packet_from_event(ev_tbl[i]); > + > + odp_packet_prefetch(pkt, 0, MIN_PACKET_LEN); > + > + ret = packet_hdr(pkt, &hdr); > + if (odp_unlikely(ret)) { > + odp_packet_free(pkt); > + stats->s.rx_drops++; > + continue; > + } > + > + flow_idx = calc_flow_idx(&hdr); > + > + fill_eth_addrs(&hdr, flow_idx); > + > + flow = odp_packet_user_area(pkt); > + flow->idx = flow_idx; > + flow->src_idx = qcontext->idx; > + flow->dst_idx = lookup_dest_port(pkt); > + flow_tbl[pkts] = flow; > + > + /* Simulate "fat pipe" processing by generating extra work */ > + for (j = 0; j < gbl_args->appl.extra_rounds; j++) > + flow->crc = dummy_hash_crc32c(odp_packet_data(pkt), > + odp_packet_len(pkt), 0); > + pkts++; > + } > + > + if (odp_unlikely(!pkts)) > + return; > + > + /* Set sequence numbers */ > + if (gbl_args->appl.in_mode == SCHED_ORDERED) > + odp_schedule_order_lock(0); > + > + for (i = 0; i < pkts; i++) { > + flow = flow_tbl[i]; > + flow->seq = qcontext->seq[flow->idx]++; > + } > + > + if (gbl_args->appl.in_mode == SCHED_ORDERED) > + odp_schedule_order_unlock(0); > + > + for (i = 0; i < pkts; i++) { > + flow = flow_tbl[i]; > + ret = > odp_queue_enq(gbl_args->fqueue[flow->dst_idx][flow->idx], > + ev_tbl[i]); > + > + if (odp_unlikely(ret != 0)) { > + LOG_ERR("odp_queue_enq() failed\n"); > + stats->s.tx_drops++; > + odp_event_free(ev_tbl[i]); > + } else { > + stats->s.packets++; > + } > + } > +} > + > +/** > + * Worker thread > + * > + * @param arg Thread arguments of type 'thread_args_t *' > + */ > +static int run_worker(void *arg) > +{ > + odp_event_t ev_tbl[MAX_PKT_BURST]; > + odp_queue_t queue; > + odp_pktout_queue_t pktout[MAX_PKTIOS][MAX_FLOWS]; > + qcontext_t *qcontext; > + thread_args_t *thr_args = arg; > + stats_t *stats = thr_args->stats; > + int pkts; > + int i, j; > + > + memset(pktout, 0, sizeof(pktout)); > + > + for (i = 0; i < gbl_args->appl.if_count; i++) { > + for (j = 0; j < gbl_args->appl.num_flows; j++) { > + pktout[i][j] = gbl_args->pktios[i].pktout[j % > + gbl_args->pktios[i].num_tx_queue]; > + } > + } > + odp_barrier_wait(&barrier); > + > + /* Loop packets */ > + while (!exit_threads) { > + pkts = odp_schedule_multi(&queue, ODP_SCHED_NO_WAIT, ev_tbl, > + MAX_PKT_BURST); > + if (pkts <= 0) > + continue; > + > + qcontext = odp_queue_context(queue); > + > + if (qcontext->input_queue) > + process_input(ev_tbl, pkts, stats, qcontext); > + else > + process_flow(ev_tbl, pkts, stats, qcontext, pktout); > + } > + > + /* Free remaining events in queues */ > + while (1) { > + odp_event_t ev; > + > + ev = odp_schedule(NULL, > + odp_schedule_wait_time(ODP_TIME_SEC_IN_NS)); > + > + if (ev == ODP_EVENT_INVALID) > + break; > + > + odp_event_free(ev); > + } > + > + return 0; > +} > + > +/** > + * Create a pktio handle and associate with input queues > + * > + * @param dev Name of device to open > + * @param index Pktio index > + * @param num_rx Number of input queues > + * @param num_tx Number of output queues > + * @param pool Pool to associate with device for packet RX/TX > + * > + * @retval 0 on success > + * @retval -1 on failure > + */ > +static int create_pktio(const char *dev, int idx, int num_rx, int num_tx, > + odp_pool_t pool) > +{ > + odp_pktio_t pktio; > + odp_pktio_param_t pktio_param; > + odp_pktio_capability_t capa; > + odp_pktin_queue_param_t pktin_param; > + odp_pktout_queue_param_t pktout_param; > + odp_pktio_op_mode_t mode_rx; > + odp_pktio_op_mode_t mode_tx; > + int i; > + > + odp_pktio_param_init(&pktio_param); > + > + pktio_param.in_mode = ODP_PKTIN_MODE_SCHED; > + > + pktio = odp_pktio_open(dev, pool, &pktio_param); > + if (pktio == ODP_PKTIO_INVALID) { > + LOG_ERR("Error: failed to open %s\n", dev); > + return -1; > + } > + > + printf("Created pktio %" PRIu64 " (%s)\n", > + odp_pktio_to_u64(pktio), dev); > + > + if (odp_pktio_capability(pktio, &capa)) { > + LOG_ERR("Error: capability query failed %s\n", dev); > + odp_pktio_close(pktio); > + return -1; > + } > + > + odp_pktin_queue_param_init(&pktin_param); > + odp_pktout_queue_param_init(&pktout_param); > + > + mode_tx = ODP_PKTIO_OP_MT; > + mode_rx = ODP_PKTIO_OP_MT; > + > + if (gbl_args->appl.in_mode == SCHED_ATOMIC) { > + pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; > + } else if (gbl_args->appl.in_mode == SCHED_PARALLEL) { > + pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_PARALLEL; > + } else { > + pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ORDERED; > + pktin_param.queue_param.sched.lock_count = 1; > + } > + pktin_param.queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + pktin_param.queue_param.sched.group = ODP_SCHED_GROUP_ALL; > + > + if (num_rx > (int)capa.max_input_queues) { > + printf("Allocating %i shared input queues, %i requested\n", > + capa.max_input_queues, num_rx); > + num_rx = capa.max_input_queues; > + mode_rx = ODP_PKTIO_OP_MT; > + } > + > + if (num_tx > (int)capa.max_output_queues) { > + printf("Allocating %i shared output queues, %i requested\n", > + capa.max_output_queues, num_tx); > + num_tx = capa.max_output_queues; > + mode_tx = ODP_PKTIO_OP_MT; > + } > + > + pktin_param.hash_enable = 1; > + pktin_param.hash_proto.proto.ipv4_udp = 1; > + pktin_param.num_queues = num_rx; > + pktin_param.op_mode = mode_rx; > + > + pktout_param.op_mode = mode_tx; > + pktout_param.num_queues = num_tx; > + > + if (odp_pktin_queue_config(pktio, &pktin_param)) { > + LOG_ERR("Error: input queue config failed %s\n", dev); > + return -1; > + } > + > + if (odp_pktout_queue_config(pktio, &pktout_param)) { > + LOG_ERR("Error: output queue config failed %s\n", dev); > + return -1; > + } > + > + if (odp_pktin_event_queue(pktio, gbl_args->pktios[idx].pktin, > + num_rx) != num_rx) { > + LOG_ERR("Error: pktin event queue query failed %s\n", > + dev); > + return -1; > + } > + > + /* Set queue contexts */ > + for (i = 0; i < num_rx; i++) { > + gbl_args->input_qcontext[idx][i].idx = idx; > + gbl_args->input_qcontext[idx][i].input_queue = 1; > + > + if (odp_queue_context_set(gbl_args->pktios[idx].pktin[i], > + &gbl_args->input_qcontext[idx][i], > + sizeof(qcontext_t))) { > + LOG_ERR("Error: pktin queue context set failed %s\n", > + dev); > + return -1; > + } > + } > + > + if (odp_pktout_queue(pktio, > + gbl_args->pktios[idx].pktout, > + num_tx) != num_tx) { > + LOG_ERR("Error: pktout queue query failed %s\n", dev); > + return -1; > + } > + > + printf("Created %i input and %i output queues on (%s)\n", > + num_rx, num_tx, dev); > + > + gbl_args->pktios[idx].num_rx_queue = num_rx; > + gbl_args->pktios[idx].num_tx_queue = num_tx; > + gbl_args->pktios[idx].pktio = pktio; > + > + return 0; > +} > + > +/** > + * Print statistics > + * > + * @param num_workers Number of worker threads > + * @param thr_stats Pointer to stats storage > + * @param duration Number of seconds to loop in > + * @param timeout Number of seconds for stats calculation > + * > + */ > +static int print_speed_stats(int num_workers, stats_t *thr_stats, > + int duration, int timeout) > +{ > + uint64_t pkts = 0; > + uint64_t pkts_prev = 0; > + uint64_t pps; > + uint64_t rx_drops, tx_drops, invalid_seq; > + uint64_t maximum_pps = 0; > + int i; > + int elapsed = 0; > + int stats_enabled = 1; > + int loop_forever = (duration == 0); > + > + if (timeout <= 0) { > + stats_enabled = 0; > + timeout = 1; > + } > + /* Wait for all threads to be ready*/ > + odp_barrier_wait(&barrier); > + > + do { > + pkts = 0; > + rx_drops = 0; > + tx_drops = 0; > + invalid_seq = 0; > + > + sleep(timeout); > + > + for (i = 0; i < num_workers; i++) { > + pkts += thr_stats[i].s.packets; > + rx_drops += thr_stats[i].s.rx_drops; > + tx_drops += thr_stats[i].s.tx_drops; > + invalid_seq += thr_stats[i].s.invalid_seq; > + } > + if (stats_enabled) { > + pps = (pkts - pkts_prev) / timeout; > + if (pps > maximum_pps) > + maximum_pps = pps; > + printf("%" PRIu64 " pps, %" PRIu64 " max pps, ", pps, > + maximum_pps); > + > + printf("%" PRIu64 " rx drops, %" PRIu64 " tx drops, ", > + rx_drops, tx_drops); > + > + printf("%" PRIu64 " invalid seq\n", invalid_seq); > + > + pkts_prev = pkts; > + } > + elapsed += timeout; > + } while (loop_forever || (elapsed < duration)); > + > + if (stats_enabled) > + printf("TEST RESULT: %" PRIu64 " maximum packets per > second.\n", > + maximum_pps); > + > + return (pkts > 100 && !invalid_seq) ? 0 : -1; > +} > + > +/** > + * Find the destination port for a given input port > + * > + * @param port Input port index > + */ > +static int find_dest_port(int port) > +{ > + /* Even number of ports */ > + if (gbl_args->appl.if_count % 2 == 0) > + return (port % 2 == 0) ? port + 1 : port - 1; > + > + /* Odd number of ports */ > + if (port == gbl_args->appl.if_count - 1) > + return 0; > + else > + return port + 1; > +} > + > +/** > + * Initialize port forwarding table > + */ > +static void init_forwarding_tbl(void) > +{ > + int rx_idx; > + > + for (rx_idx = 0; rx_idx < gbl_args->appl.if_count; rx_idx++) > + gbl_args->dst_port[rx_idx] = find_dest_port(rx_idx); > +} > + > +/** > + * Prinf usage information > + */ > +static void usage(char *progname) > +{ > + printf("\n" > + "OpenDataPlane ordered pktio application.\n" > + "\n" > + "Usage: %s OPTIONS\n" > + " E.g. %s -i eth0,eth1\n" > + " In the above example,\n" > + " eth0 will send pkts to eth1 and vice versa\n" > + "\n" > + "Mandatory OPTIONS:\n" > + " -i, --interface Eth interfaces (comma-separated, no > spaces)\n" > + " Interface count min 1, max %i\n" > + "\n" > + "Optional OPTIONS:\n" > + " -m, --mode Packet input mode\n" > + " 0: Scheduled ordered queues (default)\n" > + " 1: Scheduled atomic queues\n" > + " 2: Scheduled parallel queues (packet order > not maintained)\n" > + " -r, --num_rx_q Number of RX queues per interface\n" > + " -f, --num_flows Number of packet flows\n" > + " -e, --extra_input <number> Number of extra input > processing rounds\n" > + " -c, --count <number> CPU count.\n" > + " -t, --time <number> Time in seconds to run.\n" > + " -a, --accuracy <number> Statistics print interval in > seconds\n" > + " (default is 1 second).\n" > + " -d, --dst_addr Destination addresses (comma-separated, no > spaces)\n" > + " -h, --help Display help and exit.\n\n" > + "\n", NO_PATH(progname), NO_PATH(progname), MAX_PKTIOS > + ); > +} > + > +/** > + * Parse and store the command line arguments > + * > + * @param argc argument count > + * @param argv[] argument vector > + * @param appl_args Store application arguments here > + */ > +static void parse_args(int argc, char *argv[], appl_args_t *appl_args) > +{ > + int opt; > + int long_index; > + char *token; > + char *addr_str; > + size_t len; > + int i; > + static const struct option longopts[] = { > + {"count", required_argument, NULL, 'c'}, > + {"time", required_argument, NULL, 't'}, > + {"accuracy", required_argument, NULL, 'a'}, > + {"interface", required_argument, NULL, 'i'}, > + {"mode", required_argument, NULL, 'm'}, > + {"dst_addr", required_argument, NULL, 'd'}, > + {"num_rx_q", required_argument, NULL, 'r'}, > + {"num_flows", required_argument, NULL, 'f'}, > + {"extra_input", required_argument, NULL, 'e'}, > + {"help", no_argument, NULL, 'h'}, > + {NULL, 0, NULL, 0} > + }; > + > + static const char *shortopts = "+c:+t:+a:i:m:d:r:f:e:h"; > + > + /* let helper collect its own arguments (e.g. --odph_proc) */ > + odph_parse_options(argc, argv, shortopts, longopts); > + > + appl_args->time = 0; /* loop forever if time to run is 0 */ > + appl_args->accuracy = DEF_STATS_INT; > + appl_args->num_rx_q = DEF_NUM_RX_QUEUES; > + appl_args->num_flows = DEF_NUM_FLOWS; > + appl_args->extra_rounds = DEF_EXTRA_ROUNDS; > + > + opterr = 0; /* do not issue errors on helper options */ > + > + while (1) { > + opt = getopt_long(argc, argv, shortopts, longopts, > &long_index); > + > + if (opt == -1) > + break; /* No more options */ > + > + switch (opt) { > + case 'c': > + appl_args->cpu_count = atoi(optarg); > + break; > + case 't': > + appl_args->time = atoi(optarg); > + break; > + case 'a': > + appl_args->accuracy = atoi(optarg); > + break; > + /* parse packet-io interface names */ > + case 'd': > + len = strlen(optarg); > + if (len == 0) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + len += 1; /* add room for '\0' */ > + > + addr_str = malloc(len); > + if (addr_str == NULL) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + > + /* store the mac addresses names */ > + strcpy(addr_str, optarg); > + for (token = strtok(addr_str, ","), i = 0; > + token != NULL; token = strtok(NULL, ","), i++) { > + if (i >= MAX_PKTIOS) { > + printf("too many MAC addresses\n"); > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + if (odph_eth_addr_parse(&appl_args->addrs[i], > + token) != 0) { > + printf("invalid MAC address\n"); > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + } > + appl_args->addr_count = i; > + if (appl_args->addr_count < 1) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + free(addr_str); > + break; > + case 'i': > + len = strlen(optarg); > + if (len == 0) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + len += 1; /* add room for '\0' */ > + > + appl_args->if_str = malloc(len); > + if (appl_args->if_str == NULL) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + > + /* count the number of tokens separated by ',' */ > + strcpy(appl_args->if_str, optarg); > + for (token = strtok(appl_args->if_str, ","), i = 0; > + token != NULL; > + token = strtok(NULL, ","), i++) > + ; > + > + appl_args->if_count = i; > + > + if (appl_args->if_count < 1 || > + appl_args->if_count > MAX_PKTIOS) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + > + /* allocate storage for the if names */ > + appl_args->if_names = > + calloc(appl_args->if_count, sizeof(char *)); > + > + /* store the if names (reset names string) */ > + strcpy(appl_args->if_str, optarg); > + for (token = strtok(appl_args->if_str, ","), i = 0; > + token != NULL; token = strtok(NULL, ","), i++) { > + appl_args->if_names[i] = token; > + } > + break; > + case 'm': > + i = atoi(optarg); > + if (i == 1) > + appl_args->in_mode = SCHED_ATOMIC; > + else if (i == 2) > + appl_args->in_mode = SCHED_PARALLEL; > + else > + appl_args->in_mode = SCHED_ORDERED; > + break; > + case 'r': > + appl_args->num_rx_q = atoi(optarg); > + break; > + case 'f': > + appl_args->num_flows = atoi(optarg); > + break; > + case 'e': > + appl_args->extra_rounds = atoi(optarg); > + break; > + case 'h': > + usage(argv[0]); > + exit(EXIT_SUCCESS); > + break; > + default: > + break; > + } > + } > + > + if (appl_args->cpu_count > MAX_WORKERS) { > + printf("Too many workers requested %d, max: %d\n", > + appl_args->cpu_count, MAX_WORKERS); > + exit(EXIT_FAILURE); > + } > + > + if (appl_args->num_flows > MAX_FLOWS) { > + printf("Too many flows requested %d, max: %d\n", > + appl_args->num_flows, MAX_FLOWS); > + exit(EXIT_FAILURE); > + } > + > + if (appl_args->if_count == 0 || appl_args->num_flows == 0 || > + appl_args->num_rx_q == 0) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + if (appl_args->addr_count != 0 && > + appl_args->addr_count != appl_args->if_count) { > + printf("Number of destination addresses differs from number" > + " of interfaces\n"); > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } > + > + optind = 1; /* reset 'extern optind' from the getopt lib > */ > +} > + > +/** > + * Print system and application info > + */ > +static void print_info(char *progname, appl_args_t *appl_args) > +{ > + int i; > + > + printf("\n" > + "ODP system info\n" > + "---------------\n" > + "ODP API version: %s\n" > + "ODP impl name: %s\n" > + "CPU model: %s\n" > + "CPU freq (hz): %" PRIu64 "\n" > + "Cache line size: %i\n" > + "CPU count: %i\n" > + "\n", > + odp_version_api_str(), odp_version_impl_name(), > + odp_cpu_model_str(), odp_cpu_hz_max(), > + odp_sys_cache_line_size(), odp_cpu_count()); > + > + printf("Running ODP appl: \"%s\"\n" > + "-----------------\n" > + "IF-count: %i\n" > + "Using IFs: ", > + progname, appl_args->if_count); > + for (i = 0; i < appl_args->if_count; ++i) > + printf(" %s", appl_args->if_names[i]); > + printf("\n\n"); > + fflush(NULL); > +} > + > +static void gbl_args_init(args_t *args) > +{ > + int pktio, queue; > + > + memset(args, 0, sizeof(args_t)); > + > + for (pktio = 0; pktio < MAX_PKTIOS; pktio++) { > + args->pktios[pktio].pktio = ODP_PKTIO_INVALID; > + > + for (queue = 0; queue < MAX_QUEUES; queue++) > + args->pktios[pktio].pktin[queue] = ODP_QUEUE_INVALID; > + } > +} > + > +/** > + * ODP ordered pktio application > + */ > +int main(int argc, char *argv[]) > +{ > + odp_cpumask_t cpumask; > + odp_instance_t instance; > + odp_pool_t pool; > + odp_pool_param_t params; > + odp_shm_t shm; > + odp_queue_capability_t capa; > + odph_ethaddr_t new_addr; > + odph_odpthread_t thread_tbl[MAX_WORKERS]; > + stats_t *stats; > + char cpumaskstr[ODP_CPUMASK_STR_SIZE]; > + int cpu; > + int i, j; > + int if_count; > + int ret; > + int num_workers; > + int in_mode; > + > + /* Init ODP before calling anything else */ > + if (odp_init_global(&instance, NULL, NULL)) { > + LOG_ERR("Error: ODP global init failed.\n"); > + exit(EXIT_FAILURE); > + } > + > + /* Init this thread */ > + if (odp_init_local(instance, ODP_THREAD_CONTROL)) { > + LOG_ERR("Error: ODP local init failed.\n"); > + exit(EXIT_FAILURE); > + } > + > + /* Reserve memory for args from shared mem */ > + shm = odp_shm_reserve("shm_args", sizeof(args_t), > + ODP_CACHE_LINE_SIZE, 0);
shm_args is allocated here, but never freed. > + > + if (shm == ODP_SHM_INVALID) { > + LOG_ERR("Error: shared mem reserve failed.\n"); > + exit(EXIT_FAILURE); > + } > + > + gbl_args = odp_shm_addr(shm); > + > + if (gbl_args == NULL) { > + LOG_ERR("Error: shared mem alloc failed.\n"); > + odp_shm_free(shm); > + exit(EXIT_FAILURE); > + } > + gbl_args_init(gbl_args); > + > + /* Parse and store the application arguments */ > + parse_args(argc, argv, &gbl_args->appl); > + > + if (gbl_args->appl.in_mode == SCHED_ORDERED) { > + /* At least one ordered lock required */ > + odp_queue_capability(&capa); > + if (capa.max_ordered_locks < 1) { > + LOG_ERR("Error: Ordered locks not available.\n"); > + exit(EXIT_FAILURE); > + } > + } > + /* Print both system and application information */ > + print_info(NO_PATH(argv[0]), &gbl_args->appl); > + > + /* Default to system CPU count unless user specified */ > + num_workers = MAX_WORKERS; > + if (gbl_args->appl.cpu_count) > + num_workers = gbl_args->appl.cpu_count; > + > + /* Get default worker cpumask */ > + num_workers = odp_cpumask_default_worker(&cpumask, num_workers); > + (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); > + > + if_count = gbl_args->appl.if_count; > + > + printf("Num worker threads: %i\n", num_workers); > + printf("First CPU: %i\n", odp_cpumask_first(&cpumask)); > + printf("CPU mask: %s\n\n", cpumaskstr); > + > + /* Create packet pool */ > + odp_pool_param_init(¶ms); > + params.pkt.seg_len = PKT_POOL_BUF_SIZE; > + params.pkt.len = PKT_POOL_BUF_SIZE; > + params.pkt.num = PKT_POOL_SIZE; > + params.pkt.uarea_size = PKT_UAREA_SIZE; > + params.type = ODP_POOL_PACKET; > + > + pool = odp_pool_create("packet pool", ¶ms); > + > + if (pool == ODP_POOL_INVALID) { > + LOG_ERR("Error: packet pool create failed.\n"); > + exit(EXIT_FAILURE); > + } > + odp_pool_print(pool); > + > + init_forwarding_tbl(); > + > + for (i = 0; i < if_count; ++i) { > + const char *dev = gbl_args->appl.if_names[i]; > + int num_rx, num_tx; > + > + num_rx = gbl_args->appl.num_rx_q; > + num_tx = gbl_args->appl.num_flows; > + > + if (create_pktio(dev, i, num_rx, num_tx, pool)) > + exit(EXIT_FAILURE); > + > + /* Save interface ethernet address */ > + if (odp_pktio_mac_addr(gbl_args->pktios[i].pktio, > + gbl_args->port_eth_addr[i].addr, > + ODPH_ETHADDR_LEN) != ODPH_ETHADDR_LEN) > { > + LOG_ERR("Error: interface ethernet address > unknown\n"); > + exit(EXIT_FAILURE); > + } > + > + odp_pktio_print(gbl_args->pktios[i].pktio); > + > + /* Save destination eth address */ > + /* 02:00:00:00:00:XX */ > + memset(&new_addr, 0, sizeof(odph_ethaddr_t)); > + if (gbl_args->appl.addr_count) { > + memcpy(&new_addr, &gbl_args->appl.addrs[i], > + sizeof(odph_ethaddr_t)); > + } else { > + new_addr.addr[0] = 0x02; > + new_addr.addr[5] = i; > + } > + gbl_args->dst_eth_addr[i] = new_addr; > + } > + > + gbl_args->pktios[i].pktio = ODP_PKTIO_INVALID; > + > + /* Allocate the same number of flows to each interface */ > + for (i = 0; i < if_count; i++) { > + odp_pktio_capability_t capa; > + > + if (odp_pktio_capability(gbl_args->pktios[i].pktio, &capa)) { > + LOG_ERR("Error: pktio capability failed.\n"); > + exit(EXIT_FAILURE); > + } > + > + if ((unsigned)gbl_args->appl.num_flows > > capa.max_output_queues) > + gbl_args->appl.num_flows = capa.max_output_queues; > + } > + > + /* Create atomic queues for packet tagging */ > + for (i = 0; i < if_count; i++) { > + for (j = 0; j < gbl_args->appl.num_flows; j++) { > + odp_queue_t queue; > + odp_queue_param_t qparam; > + char qname[ODP_QUEUE_NAME_LEN]; > + > + snprintf(qname, sizeof(qname), "flow_%d_%d", i, j); > + > + odp_queue_param_init(&qparam); > + qparam.type = ODP_QUEUE_TYPE_SCHED; > + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + > + gbl_args->flow_qcontext[i][j].idx = i; > + gbl_args->flow_qcontext[i][j].input_queue = 0; > + qparam.context = &gbl_args->flow_qcontext[i][j]; > + qparam.context_len = sizeof(qcontext_t); > + > + queue = odp_queue_create(qname, &qparam); > + if (queue == ODP_QUEUE_INVALID) { > + LOG_ERR("Error: flow queue create failed.\n"); > + exit(EXIT_FAILURE); > + } > + > + gbl_args->fqueue[i][j] = queue; > + } > + } > + > + in_mode = gbl_args->appl.in_mode; > + printf("\nApplication parameters\n" > + "----------------------\n" > + "Input queues: %d\n" > + "Mode: %s\n" > + "Flows: %d\n" > + "Extra rounds: %d\n\n", gbl_args->appl.num_rx_q, > + (in_mode == SCHED_ATOMIC) ? "PKTIN_SCHED_ATOMIC" : > + (in_mode == SCHED_PARALLEL ? "PKTIN_SCHED_PARALLEL" : > + "PKTIN_SCHED_ORDERED"), gbl_args->appl.num_flows, > + gbl_args->appl.extra_rounds); > + > + memset(thread_tbl, 0, sizeof(thread_tbl)); > + > + stats = gbl_args->stats; > + > + odp_barrier_init(&barrier, num_workers + 1); > + > + /* Create worker threads */ > + cpu = odp_cpumask_first(&cpumask); > + for (i = 0; i < num_workers; ++i) { > + odp_cpumask_t thd_mask; > + odph_odpthread_params_t thr_params; > + > + memset(&thr_params, 0, sizeof(thr_params)); > + thr_params.start = run_worker; > + thr_params.arg = &gbl_args->thread[i]; > + thr_params.thr_type = ODP_THREAD_WORKER; > + thr_params.instance = instance; > + > + gbl_args->thread[i].stats = &stats[i]; > + > + odp_cpumask_zero(&thd_mask); > + odp_cpumask_set(&thd_mask, cpu); > + odph_odpthreads_create(&thread_tbl[i], &thd_mask, > + &thr_params); > + cpu = odp_cpumask_next(&cpumask, cpu); > + } > + > + /* Start packet receive and transmit */ > + for (i = 0; i < if_count; ++i) { > + odp_pktio_t pktio; > + > + pktio = gbl_args->pktios[i].pktio; > + ret = odp_pktio_start(pktio); > + if (ret) { > + LOG_ERR("Error: unable to start %s\n", > + gbl_args->appl.if_names[i]); > + exit(EXIT_FAILURE); > + } > + } > + > + ret = print_speed_stats(num_workers, stats, gbl_args->appl.time, > + gbl_args->appl.accuracy); > + > + /* Stop receiving new packet */ > + for (i = 0; i < if_count; i++) > + odp_pktio_stop(gbl_args->pktios[i].pktio); > + > + exit_threads = 1; > + > + /* Master thread waits for other threads to exit */ > + for (i = 0; i < num_workers; ++i) > + odph_odpthreads_join(&thread_tbl[i]); > + > + for (i = 0; i < if_count; i++) { > + odp_pktio_close(gbl_args->pktios[i].pktio); > + > + for (j = 0; j < gbl_args->appl.num_flows; j++) > + odp_queue_destroy(gbl_args->fqueue[i][j]); > + } > + > + free(gbl_args->appl.if_names); > + free(gbl_args->appl.if_str); > + > + if (odp_pool_destroy(pool)) { > + LOG_ERR("Error: pool destroy\n"); > + exit(EXIT_FAILURE); > + } > + odp_shm_free(shm) belongs here for normal termination. > + if (odp_term_local()) { > + LOG_ERR("Error: term local\n"); > + exit(EXIT_FAILURE); > + } > + > + if (odp_term_global(instance)) { > + LOG_ERR("Error: term global\n"); > + exit(EXIT_FAILURE); > + } > + > + return ret; > +} > -- > 2.7.4 >