When OVS is built with --with-dpdk, every binary gets linked with all DPDK libraries. Only ovs-vswitchd actually uses DPDK. This causes inflated binary sizes for static builds and unnecessary shared library dependencies for shared builds.
Fix this by: - Saving/restoring LIBS around the DPDK dependency detection in acinclude.m4 to prevent DPDK libraries from polluting global LIBS. - Moving DPDK source files (dpdk.c, netdev-dpdk.c, dpif-offload-dpdk.c, dpif-offload-dpdk-netdev.c) into a separate libopenvswitchdpdk.la static library. - Always compiling dpdk-stub.c into libopenvswitch (not conditionally), providing stub definitions for the general DPDK API (dpdk_init, etc.). - Adding dpdk-link-stubs.c with OVS_WEAK stubs for free_dpdk_buf and rte_get_tsc_hz in a separate translation unit, so the linker can resolve these without pulling in conflicting dpdk-stub.o definitions when linking ovs-vswitchd. - Introducing the OVS_WEAK macro in compiler.h, wrapping __attribute__((__weak__)) for portability with existing conventions. - Linking only ovs-vswitchd against libopenvswitchdpdk.la and DPDK_LIBS. This relies on archive linker semantics: when ovs-vswitchd links libopenvswitchdpdk.la before libopenvswitch.la, strong DPDK definitions are found first, and the stubs in dpdk-stub.o are never pulled in. The link-dependency stubs (free_dpdk_buf, rte_get_tsc_hz) are in their own object file so they can be individually pulled without conflicting. For other binaries, only libopenvswitch.la is linked, and the stubs resolve all DPDK symbols without requiring actual DPDK libraries. Result (static DPDK, stripped sizes): - ovs-vswitchd: ~25 MB (unchanged, has full DPDK) - ovs-ofctl, ovsdb-server, etc.: ~2-3 MB (down from ~14-16 MB) Reported-at: https://issues.redhat.com/browse/FDP-3277 Signed-off-by: Timothy Redaelli <[email protected]> --- acinclude.m4 | 4 +++ include/openvswitch/compiler.h | 2 ++ lib/automake.mk | 11 ++++--- lib/dpdk-link-stubs.c | 54 ++++++++++++++++++++++++++++++++++ vswitchd/automake.mk | 8 ++++- 5 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 lib/dpdk-link-stubs.c diff --git a/acinclude.m4 b/acinclude.m4 index e4e48cb53..417d513a7 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -425,6 +425,7 @@ AC_DEFUN([OVS_CHECK_DPDK], [ ovs_save_CFLAGS="$CFLAGS" ovs_save_LDFLAGS="$LDFLAGS" + ovs_save_LIBS="$LIBS" CFLAGS="$CFLAGS $DPDK_INCLUDE" AC_CHECK_HEADERS([rte_config.h], [], [ @@ -489,6 +490,7 @@ AC_DEFUN([OVS_CHECK_DPDK], [ CFLAGS="$ovs_save_CFLAGS" LDFLAGS="$ovs_save_LDFLAGS" + LIBS="$ovs_save_LIBS" # Stripping out possible instruction set specific configuration that DPDK # forces in pkg-config since this could override user-specified options. # It's enough to have -mssse3 to build with DPDK headers. @@ -517,9 +519,11 @@ AC_DEFUN([OVS_CHECK_DPDK], [ DPDK_vswitchd_LDFLAGS="-Wl,$DPDK_vswitchd_LDFLAGS" AC_SUBST([DPDK_vswitchd_LDFLAGS]) + DPDK_LIBS="$DPDK_LIB" AC_DEFINE([DPDK_NETDEV], [1], [System uses the DPDK module.]) fi + AC_SUBST([DPDK_LIBS]) AM_CONDITIONAL([DPDK_NETDEV], test "$DPDKLIB_FOUND" = true) ]) diff --git a/include/openvswitch/compiler.h b/include/openvswitch/compiler.h index 7dee9ec7a..2bc96cf7d 100644 --- a/include/openvswitch/compiler.h +++ b/include/openvswitch/compiler.h @@ -64,6 +64,7 @@ #define OVS_PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1))) #define OVS_SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(scanf, FMT, ARG1))) #define OVS_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#define OVS_WEAK __attribute__((__weak__)) #define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1) #define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0) #else @@ -71,6 +72,7 @@ #define OVS_PRINTF_FORMAT(FMT, ARG1) #define OVS_SCANF_FORMAT(FMT, ARG1) #define OVS_WARN_UNUSED_RESULT +#define OVS_WEAK #define OVS_LIKELY(CONDITION) (!!(CONDITION)) #define OVS_UNLIKELY(CONDITION) (!!(CONDITION)) #endif diff --git a/lib/automake.mk b/lib/automake.mk index c6e988906..cb9a1b2fe 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -503,17 +503,20 @@ lib_libopenvswitch_la_SOURCES += \ endif if DPDK_NETDEV -lib_libopenvswitch_la_SOURCES += \ +noinst_LTLIBRARIES += lib/libopenvswitchdpdk.la +lib_libopenvswitchdpdk_la_SOURCES = \ lib/dpdk.c \ lib/dpif-offload-dpdk.c \ lib/dpif-offload-dpdk-netdev.c \ lib/dpif-offload-dpdk-private.h \ lib/netdev-dpdk.c -else -lib_libopenvswitch_la_SOURCES += \ - lib/dpdk-stub.c +lib_libopenvswitchdpdk_la_LDFLAGS = -static endif +lib_libopenvswitch_la_SOURCES += \ + lib/dpdk-stub.c \ + lib/dpdk-link-stubs.c + if WIN32 lib_libopenvswitch_la_SOURCES += \ lib/dpif-netlink.c \ diff --git a/lib/dpdk-link-stubs.c b/lib/dpdk-link-stubs.c new file mode 100644 index 000000000..f87a4c3f9 --- /dev/null +++ b/lib/dpdk-link-stubs.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Weak stub definitions for DPDK symbols referenced by libopenvswitch objects. + * + * These stubs are compiled into libopenvswitch.a in a separate translation + * unit from dpdk-stub.c. This separation is critical: when linking + * ovs-vswitchd (which also links libopenvswitchdpdk.a with real DPDK + * definitions), the linker must be able to pull in these stubs without + * also pulling in the dpdk-stub.o definitions of dpdk_init, dpdk_status, + * etc., which would conflict with the real ones in dpdk.o. + * + * The stubs are declared OVS_WEAK so that if this object file is pulled + * into ovs-vswitchd (e.g. to resolve rte_get_tsc_hz), the weak + * free_dpdk_buf won't conflict with the strong definition in + * netdev-dpdk.o. */ + +#include <config.h> + +#ifdef DPDK_NETDEV + +#include <stdint.h> + +#include "dp-packet.h" +#include "util.h" + +OVS_WEAK void +free_dpdk_buf(struct dp_packet *buf OVS_UNUSED) +{ + /* Should never be called in binaries not linked with DPDK. + * DPBUF_DPDK packets cannot exist without DPDK initialization. */ + OVS_NOT_REACHED(); +} + +OVS_WEAK uint64_t +rte_get_tsc_hz(void) +{ + return 1; +} + +#endif /* DPDK_NETDEV */ diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk index 830c9a188..fdab16abe 100644 --- a/vswitchd/automake.mk +++ b/vswitchd/automake.mk @@ -9,10 +9,16 @@ vswitchd_ovs_vswitchd_SOURCES = \ vswitchd/ovs-vswitchd.c \ vswitchd/system-stats.c \ vswitchd/system-stats.h +if DPDK_NETDEV +DPDK_vswitchd_LDADD = lib/libopenvswitchdpdk.la +endif + vswitchd_ovs_vswitchd_LDADD = \ ofproto/libofproto.la \ lib/libsflow.la \ - lib/libopenvswitch.la + $(DPDK_vswitchd_LDADD) \ + lib/libopenvswitch.la \ + $(DPDK_LIBS) vswitchd_ovs_vswitchd_LDFLAGS = $(AM_LDFLAGS) $(DPDK_vswitchd_LDFLAGS) MAN_ROOTS += vswitchd/ovs-vswitchd.8.in -- 2.53.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
