diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 00000000000..e4c94ea02b8 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,221 @@ +load("@dpdk_pip//:requirements.bzl", "requirement") +load("@rules_foreign_cc//foreign_cc:meson.bzl", "meson_with_requirements") + +filegroup( + name = "srcs", + srcs = glob(["**"]), + visibility = ["//visibility:private"], +) + +meson_with_requirements( + name = "dpdk", + lib_source = ":srcs", + out_headers_only = True, + out_static_libs = [ + "librte_acl.a", + "librte_dispatcher.a", + "librte_metrics.a", + "librte_net_tap.a", + "librte_argparse.a", + "librte_distributor.a", + "librte_ml_cnxk.a", + "librte_net_thunderx.a", + "librte_baseband_acc.a", + "librte_dma_cnxk.a", + "librte_mldev.a", + "librte_net_txgbe.a", + "librte_baseband_fpga_5gnr_fec.a", + "librte_dmadev.a", + "librte_net.a", + "librte_net_vdev_netvsc.a", + "librte_baseband_fpga_lte_fec.a", + "librte_dma_dpaa2.a", + "librte_net_af_packet.a", + "librte_net_vhost.a", + "librte_baseband_la12xx.a", + "librte_dma_dpaa.a", + "librte_net_ark.a", + "librte_net_virtio.a", + "librte_baseband_null.a", + "librte_dma_hisilicon.a", + "librte_net_atlantic.a", + "librte_net_vmxnet3.a", + "librte_baseband_turbo_sw.a", + "librte_dma_idxd.a", + "librte_net_avp.a", + "librte_net_xsc.a", + "librte_bbdev.a", + "librte_dma_ioat.a", + "librte_net_axgbe.a", + "librte_net_zxdh.a", + "librte_bitratestats.a", + "librte_dma_odm.a", + "librte_net_bnxt.a", + "librte_node.a", + "librte_bpf.a", + "librte_dma_skeleton.a", + "librte_net_bond.a", + "librte_pcapng.a", + "librte_bus_auxiliary.a", + "librte_eal.a", + "librte_net_cnxk.a", + "librte_pci.a", + "librte_bus_cdx.a", + "librte_efd.a", + "librte_net_cpfl.a", + "librte_pdcp.a", + "librte_bus_dpaa.a", + "librte_ethdev.a", + "librte_net_cxgbe.a", + "librte_pdump.a", + "librte_bus_fslmc.a", + "librte_event_cnxk.a", + "librte_net_dpaa2.a", + "librte_pipeline.a", + "librte_bus_ifpga.a", + "librte_eventdev.a", + "librte_net_dpaa.a", + "librte_pmu.a", + "librte_bus_pci.a", + "librte_event_dlb2.a", + "librte_net_e1000.a", + "librte_port.a", + "librte_bus_platform.a", + "librte_event_dpaa2.a", + "librte_net_ena.a", + "librte_power.a", + "librte_bus_uacce.a", + "librte_event_dpaa.a", + "librte_net_enetc.a", + "librte_power_acpi.a", + "librte_bus_vdev.a", + "librte_event_dsw.a", + "librte_net_enetfec.a", + "librte_power_amd_pstate.a", + "librte_bus_vmbus.a", + "librte_event_octeontx.a", + "librte_net_enic.a", + "librte_power_cppc.a", + "librte_cfgfile.a", + "librte_event_opdl.a", + "librte_net_failsafe.a", + "librte_power_intel_pstate.a", + "librte_cmdline.a", + "librte_event_skeleton.a", + "librte_net_fm10k.a", + "librte_power_intel_uncore.a", + "librte_common_cnxk.a", + "librte_event_sw.a", + "librte_net_gve.a", + "librte_power_kvm_vm.a", + "librte_common_cpt.a", + "librte_fib.a", + "librte_net_hinic3.a", + "librte_raw_cnxk_bphy.a", + "librte_common_dpaax.a", + "librte_gpudev.a", + "librte_net_hinic.a", + "librte_raw_cnxk_gpio.a", + "librte_common_ionic.a", + "librte_graph.a", + "librte_net_hns3.a", + "librte_raw_cnxk_rvu_lf.a", + "librte_common_nfp.a", + "librte_gro.a", + "librte_net_i40e.a", + "librte_rawdev.a", + "librte_common_nitrox.a", + "librte_gso.a", + "librte_net_iavf.a", + "librte_raw_dpaa2_cmdif.a", + "librte_common_octeontx.a", + "librte_hash.a", + "librte_net_ice.a", + "librte_raw_gdtc.a", + "librte_common_qat.a", + "librte_ip_frag.a", + "librte_net_idpf.a", + "librte_raw_ntb.a", + "librte_common_sfc_efx.a", + "librte_ipsec.a", + "librte_net_ionic.a", + "librte_raw_skeleton.a", + "librte_common_zsda.a", + "librte_jobstats.a", + "librte_net_ixgbe.a", + "librte_rcu.a", + "librte_compressdev.a", + "librte_kvargs.a", + "librte_net_memif.a", + "librte_regex_cn9k.a", + "librte_compress_nitrox.a", + "librte_latencystats.a", + "librte_net_netvsc.a", + "librte_regexdev.a", + "librte_compress_octeontx.a", + "librte_log.a", + "librte_net_nfp.a", + "librte_reorder.a", + "librte_crypto_bcmfs.a", + "librte_lpm.a", + "librte_net_ngbe.a", + "librte_rib.a", + "librte_crypto_caam_jr.a", + "librte_mbuf.a", + "librte_net_ntnic.a", + "librte_ring.a", + "librte_crypto_cnxk.a", + "librte_member.a", + "librte_net_null.a", + "librte_sched.a", + "librte_cryptodev.a", + "librte_mempool.a", + "librte_net_octeon_ep.a", + "librte_security.a", + "librte_crypto_dpaa2_sec.a", + "librte_mempool_bucket.a", + "librte_net_octeontx.a", + "librte_stack.a", + "librte_crypto_dpaa_sec.a", + "librte_mempool_cnxk.a", + "librte_net_pfe.a", + "librte_table.a", + "librte_crypto_ionic.a", + "librte_mempool_dpaa2.a", + "librte_net_qede.a", + "librte_telemetry.a", + "librte_crypto_nitrox.a", + "librte_mempool_dpaa.a", + "librte_net_r8169.a", + "librte_timer.a", + "librte_crypto_null.a", + "librte_mempool_octeontx.a", + "librte_net_ring.a", + "librte_vdpa_ifc.a", + "librte_crypto_octeontx.a", + "librte_mempool_ring.a", + "librte_net_rnp.a", + "librte_vdpa_nfp.a", + "librte_crypto_scheduler.a", + "librte_mempool_stack.a", + "librte_net_sfc.a", + "librte_vdpa_sfc.a", + "librte_crypto_virtio.a", + "librte_meter.a", + "librte_net_softnic.a", + "librte_vhost.a", + ], + postfix_script = "ninja", + requirements = [ + requirement("pyelftools"), + ], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + visibility = ["//visibility:public"], + deps = [ + "@libnuma", + "@openssl//:crypto", + ], +) diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 00000000000..f3b2ef3cd14 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,29 @@ +module( + name = "dpdk", + repo_name = "dpdk", +) + +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_foreign_cc", version = "0.15.1") +bazel_dep(name = "rules_python", version = "1.6.3") +bazel_dep(name = "openssl", version = "3.3.1.bcr.7") + +tools = use_extension("@rules_foreign_cc//foreign_cc:extensions.bzl", "tools") +use_repo(tools, "meson_src") + +python = use_extension("@rules_python//python/extensions:python.bzl", "python") +python.toolchain( + python_version = "3.12", +) +use_repo(python, "python_versions") + +pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") +pip.parse( + hub_name = "dpdk_pip", + python_version = "3.12", + requirements_lock = "//bazel:requirements.txt", +) +use_repo(pip, "dpdk_pip") + +cpp_deps = use_extension("//bazel:deps.bzl", "cpp_deps_extension") +use_repo(cpp_deps, "libnuma") diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel new file mode 100644 index 00000000000..2b99d1f375c --- /dev/null +++ b/bazel/BUILD.bazel @@ -0,0 +1,14 @@ +load("@python_versions//3.12:defs.bzl", "compile_pip_requirements") + +exports_files(["pytest.ini"]) + +# This stanza calls a rule that generates targets for managing pip dependencies +# with pip-compile. +compile_pip_requirements( + name = "requirements", + timeout = "moderate", # prevent flaky requirements_test + src = "requirements.in", + extra_args = ["--allow-unsafe"], + requirements_txt = "requirements.txt", + # requirements_windows = "requirements_windows.txt", # uncomment if windows support is needed +) diff --git a/bazel/deps.bzl b/bazel/deps.bzl new file mode 100644 index 00000000000..bd29aefe477 --- /dev/null +++ b/bazel/deps.bzl @@ -0,0 +1,19 @@ +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + +def cpp_deps(): + git_repository( + name = "libnuma", + remote = "https://github.com/numactl/numactl", + patch_cmds = [ + "./autogen.sh", + ], + build_file = "//bazel:numactl.BUILD", + commit = "b34da01b0017946a1a77057c247cfc6d231a0215", + ) + +def _cpp_deps_extension_impl(_): + cpp_deps() + +cpp_deps_extension = module_extension( + implementation = _cpp_deps_extension_impl, +) diff --git a/bazel/numactl.BUILD b/bazel/numactl.BUILD new file mode 100644 index 00000000000..ebfe94e92af --- /dev/null +++ b/bazel/numactl.BUILD @@ -0,0 +1,18 @@ +load("@rules_foreign_cc//foreign_cc:configure.bzl", "configure_make") + +filegroup( + name = "srcs", + srcs = glob(["**"]), + visibility = ["//visibility:private"], +) + +configure_make( + name = "libnuma", + # bazel will throw error: use of undeclared identifier 'redacted' because bazel sets __DATE__ to "redacted". + # https://github.com/bazel-contrib/rules_foreign_cc/issues/239 + configure_options = ["CFLAGS='-Dredacted=\"redacted\"'"], + lib_source = ":srcs", + out_headers_only = True, + visibility = ["//visibility:public"], + alwayslink = True, +) diff --git a/bazel/requirements.in b/bazel/requirements.in new file mode 100644 index 00000000000..22922d712d7 --- /dev/null +++ b/bazel/requirements.in @@ -0,0 +1 @@ +pyelftools==0.32 \ No newline at end of file diff --git a/bazel/requirements.txt b/bazel/requirements.txt new file mode 100644 index 00000000000..911decbff66 --- /dev/null +++ b/bazel/requirements.txt @@ -0,0 +1,10 @@ +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# bazel run //bazel:requirements.update +# +pyelftools==0.32 \ + --hash=sha256:013df952a006db5e138b1edf6d8a68ecc50630adbd0d83a2d41e7f846163d738 \ + --hash=sha256:6de90ee7b8263e740c8715a925382d4099b354f29ac48ea40d840cf7aa14ace5 + # via -r bazel/requirements.in diff --git a/buildtools/coff.py b/buildtools/coff.py deleted file mode 100644 index 86fb0602b7f..00000000000 --- a/buildtools/coff.py +++ /dev/null @@ -1,154 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright (c) 2020 Dmitry Kozlyuk - -import ctypes - -# x86_64 little-endian -COFF_MAGIC = 0x8664 - -# Names up to this length are stored immediately in symbol table entries. -COFF_NAMELEN = 8 - -# Special "section numbers" changing the meaning of symbol table entry. -COFF_SN_UNDEFINED = 0 -COFF_SN_ABSOLUTE = -1 -COFF_SN_DEBUG = -2 - - -class CoffFileHeader(ctypes.LittleEndianStructure): - _pack_ = True - _fields_ = [ - ("magic", ctypes.c_uint16), - ("section_count", ctypes.c_uint16), - ("timestamp", ctypes.c_uint32), - ("symbol_table_offset", ctypes.c_uint32), - ("symbol_count", ctypes.c_uint32), - ("optional_header_size", ctypes.c_uint16), - ("flags", ctypes.c_uint16), - ] - - -class CoffName(ctypes.Union): - class Reference(ctypes.LittleEndianStructure): - _pack_ = True - _fields_ = [ - ("zeroes", ctypes.c_uint32), - ("offset", ctypes.c_uint32), - ] - - Immediate = ctypes.c_char * 8 - - _pack_ = True - _fields_ = [ - ("immediate", Immediate), - ("reference", Reference), - ] - - -class CoffSection(ctypes.LittleEndianStructure): - _pack_ = True - _fields_ = [ - ("name", CoffName), - ("physical_address", ctypes.c_uint32), - ("physical_address", ctypes.c_uint32), - ("size", ctypes.c_uint32), - ("data_offset", ctypes.c_uint32), - ("relocations_offset", ctypes.c_uint32), - ("line_numbers_offset", ctypes.c_uint32), - ("relocation_count", ctypes.c_uint16), - ("line_number_count", ctypes.c_uint16), - ("flags", ctypes.c_uint32), - ] - - -class CoffSymbol(ctypes.LittleEndianStructure): - _pack_ = True - _fields_ = [ - ("name", CoffName), - ("value", ctypes.c_uint32), - ("section_number", ctypes.c_int16), - ("type", ctypes.c_uint16), - ("storage_class", ctypes.c_uint8), - ("auxiliary_count", ctypes.c_uint8), - ] - - -class Symbol: - def __init__(self, image, symbol: CoffSymbol): - self._image = image - self._coff = symbol - - @property - def name(self): - if self._coff.name.reference.zeroes: - return decode_asciiz(bytes(self._coff.name.immediate)) - - offset = self._coff.name.reference.offset - offset -= ctypes.sizeof(ctypes.c_uint32) - return self._image.get_string(offset) - - def get_value(self, offset): - section_number = self._coff.section_number - - if section_number == COFF_SN_UNDEFINED: - return None - - if section_number == COFF_SN_DEBUG: - return None - - if section_number == COFF_SN_ABSOLUTE: - return bytes(ctypes.c_uint32(self._coff.value)) - - section_data = self._image.get_section_data(section_number) - section_offset = self._coff.value + offset - return section_data[section_offset:] - - -class Image: - def __init__(self, data): - header = CoffFileHeader.from_buffer_copy(data) - header_size = ctypes.sizeof(header) + header.optional_header_size - - sections_desc = CoffSection * header.section_count - sections = sections_desc.from_buffer_copy(data, header_size) - - symbols_desc = CoffSymbol * header.symbol_count - symbols = symbols_desc.from_buffer_copy(data, header.symbol_table_offset) - - strings_offset = header.symbol_table_offset + ctypes.sizeof(symbols) - strings = Image._parse_strings(data[strings_offset:]) - - self._data = data - self._header = header - self._sections = sections - self._symbols = symbols - self._strings = strings - - @staticmethod - def _parse_strings(data): - full_size = ctypes.c_uint32.from_buffer_copy(data) - header_size = ctypes.sizeof(full_size) - return data[header_size : full_size.value] - - @property - def symbols(self): - i = 0 - while i < self._header.symbol_count: - symbol = self._symbols[i] - yield Symbol(self, symbol) - i += symbol.auxiliary_count + 1 - - def get_section_data(self, number): - # section numbers are 1-based - section = self._sections[number - 1] - base = section.data_offset - return self._data[base : base + section.size] - - def get_string(self, offset): - return decode_asciiz(self._strings[offset:]) - - -def decode_asciiz(data): - index = data.find(b'\x00') - end = index if index >= 0 else len(data) - return data[:end].decode() diff --git a/buildtools/pmdinfogen.py b/buildtools/pmdinfogen.py index 63e0a8b364a..6cb9f8b3302 100755 --- a/buildtools/pmdinfogen.py +++ b/buildtools/pmdinfogen.py @@ -17,8 +17,156 @@ except ImportError: pass -import coff +# x86_64 little-endian +COFF_MAGIC = 0x8664 + +# Names up to this length are stored immediately in symbol table entries. +COFF_NAMELEN = 8 + +# Special "section numbers" changing the meaning of symbol table entry. +COFF_SN_UNDEFINED = 0 +COFF_SN_ABSOLUTE = -1 +COFF_SN_DEBUG = -2 + + +class CoffFileHeader(ctypes.LittleEndianStructure): + _pack_ = True + _fields_ = [ + ("magic", ctypes.c_uint16), + ("section_count", ctypes.c_uint16), + ("timestamp", ctypes.c_uint32), + ("symbol_table_offset", ctypes.c_uint32), + ("symbol_count", ctypes.c_uint32), + ("optional_header_size", ctypes.c_uint16), + ("flags", ctypes.c_uint16), + ] + + +class CoffName(ctypes.Union): + class Reference(ctypes.LittleEndianStructure): + _pack_ = True + _fields_ = [ + ("zeroes", ctypes.c_uint32), + ("offset", ctypes.c_uint32), + ] + + Immediate = ctypes.c_char * 8 + + _pack_ = True + _fields_ = [ + ("immediate", Immediate), + ("reference", Reference), + ] + + +class CoffSection(ctypes.LittleEndianStructure): + _pack_ = True + _fields_ = [ + ("name", CoffName), + ("physical_address", ctypes.c_uint32), + ("physical_address", ctypes.c_uint32), + ("size", ctypes.c_uint32), + ("data_offset", ctypes.c_uint32), + ("relocations_offset", ctypes.c_uint32), + ("line_numbers_offset", ctypes.c_uint32), + ("relocation_count", ctypes.c_uint16), + ("line_number_count", ctypes.c_uint16), + ("flags", ctypes.c_uint32), + ] + + +class CoffSymbol(ctypes.LittleEndianStructure): + _pack_ = True + _fields_ = [ + ("name", CoffName), + ("value", ctypes.c_uint32), + ("section_number", ctypes.c_int16), + ("type", ctypes.c_uint16), + ("storage_class", ctypes.c_uint8), + ("auxiliary_count", ctypes.c_uint8), + ] + + +class Symbol: + def __init__(self, image, symbol: CoffSymbol): + self._image = image + self._coff = symbol + + @property + def name(self): + if self._coff.name.reference.zeroes: + return decode_asciiz(bytes(self._coff.name.immediate)) + + offset = self._coff.name.reference.offset + offset -= ctypes.sizeof(ctypes.c_uint32) + return self._image.get_string(offset) + + def get_value(self, offset): + section_number = self._coff.section_number + + if section_number == COFF_SN_UNDEFINED: + return None + + if section_number == COFF_SN_DEBUG: + return None + + if section_number == COFF_SN_ABSOLUTE: + return bytes(ctypes.c_uint32(self._coff.value)) + + section_data = self._image.get_section_data(section_number) + section_offset = self._coff.value + offset + return section_data[section_offset:] + + +class Image: + def __init__(self, data): + header = CoffFileHeader.from_buffer_copy(data) + header_size = ctypes.sizeof(header) + header.optional_header_size + + sections_desc = CoffSection * header.section_count + sections = sections_desc.from_buffer_copy(data, header_size) + + symbols_desc = CoffSymbol * header.symbol_count + symbols = symbols_desc.from_buffer_copy(data, header.symbol_table_offset) + + strings_offset = header.symbol_table_offset + ctypes.sizeof(symbols) + strings = Image._parse_strings(data[strings_offset:]) + + self._data = data + self._header = header + self._sections = sections + self._symbols = symbols + self._strings = strings + + @staticmethod + def _parse_strings(data): + full_size = ctypes.c_uint32.from_buffer_copy(data) + header_size = ctypes.sizeof(full_size) + return data[header_size : full_size.value] + + @property + def symbols(self): + i = 0 + while i < self._header.symbol_count: + symbol = self._symbols[i] + yield Symbol(self, symbol) + i += symbol.auxiliary_count + 1 + + def get_section_data(self, number): + # section numbers are 1-based + section = self._sections[number - 1] + base = section.data_offset + return self._data[base : base + section.size] + + def get_string(self, offset): + return decode_asciiz(self._strings[offset:]) + + +def decode_asciiz(data): + index = data.find(b'\x00') + end = index if index >= 0 else len(data) + return data[:end].decode() class ELFSymbol: def __init__(self, image, symbol): @@ -29,7 +177,7 @@ def __init__(self, image, symbol): def string_value(self): size = self._symbol["st_size"] value = self.get_value(0, size) - return coff.decode_asciiz(value) # not COFF-specific + return decode_asciiz(value) # not COFF-specific def get_value(self, offset, size): section = self._symbol["st_shndx"] @@ -87,12 +235,12 @@ def get_value(self, offset, size): @property def string_value(self): value = self._symbol.get_value(0) - return coff.decode_asciiz(value) if value else "" + return decode_asciiz(value) if value else "" class COFFImage: def __init__(self, data): - self._image = coff.Image(data) + self._image = Image(data) @property def is_big_endian(self): diff --git a/config/meson.build b/config/meson.build index b8c1f127a2a..5d2d78894db 100644 --- a/config/meson.build +++ b/config/meson.build @@ -231,6 +231,7 @@ endif # check for libraries used in multiple places in DPDK has_libnuma = false find_libnuma = true +ext_libnuma = false if meson.is_cross_build() and not meson.get_external_property('numa', true) # don't look for libnuma if explicitly disabled in cross build find_libnuma = false @@ -242,6 +243,13 @@ if find_libnuma has_libnuma = true add_project_link_arguments('-lnuma', language: 'c') dpdk_extra_ldflags += '-lnuma' + else + numa_dep = dependency('numa', required: false, method: 'pkg-config') + if numa_dep.found() and cc.has_header('numaif.h', dependencies: numa_dep) and cc.links(min_c_code, dependencies: numa_dep) + dpdk_conf.set10('RTE_HAS_LIBNUMA', true) + has_libnuma = true + ext_libnuma = true + endif endif endif diff --git a/lib/meson.build b/lib/meson.build index c8f42708681..f10ab6759a7 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -138,6 +138,11 @@ foreach l:libraries # use "deps" for internal DPDK dependencies, and "ext_deps" for # external package/library requirements ext_deps = [] + + if ext_libnuma + ext_deps += numa_dep + endif + deps = [] if dpdk_conf.has('RTE_LIB_EAL') # eal is standard dependency once built