diff --git a/net/batman-adv/Config.in b/net/batman-adv/Config.in new file mode 100644 index 00000000000000..9da3b8ab4361bb --- /dev/null +++ b/net/batman-adv/Config.in @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: +# +# Marek Lindner, Simon Wunderlich + +# +# B.A.T.M.A.N meshing protocol +# + +config BATMAN_ADV_BATMAN_V + bool "B.A.T.M.A.N. V protocol" + depends on PACKAGE_kmod-batman-adv + default y + help + This option enables the B.A.T.M.A.N. V protocol, the successor + of the currently used B.A.T.M.A.N. IV protocol. The main + changes include splitting of the OGM protocol into a neighbor + discovery protocol (Echo Location Protocol, ELP) and a new OGM + Protocol OGMv2 for flooding protocol information through the + network, as well as a throughput based metric. + B.A.T.M.A.N. V is currently considered experimental and not + compatible to B.A.T.M.A.N. IV networks. + +config BATMAN_ADV_BLA + bool "Bridge Loop Avoidance" + depends on PACKAGE_kmod-batman-adv + select PACKAGE_kmod-lib-crc16 + default y + help + This option enables BLA (Bridge Loop Avoidance), a mechanism + to avoid Ethernet frames looping when mesh nodes are connected + to both the same LAN and the same mesh. If you will never use + more than one mesh node in the same LAN, you can safely remove + this feature and save some space. + +config BATMAN_ADV_DAT + bool "Distributed ARP Table" + depends on PACKAGE_kmod-batman-adv + default y + help + This option enables DAT (Distributed ARP Table), a DHT based + mechanism that increases ARP reliability on sparse wireless + mesh networks. If you think that your network does not need + this option you can safely remove it and save some space. + +config BATMAN_ADV_MCAST + bool "Multicast optimisation" + depends on PACKAGE_kmod-batman-adv + default y + help + This option enables the multicast optimisation which aims to + reduce the air overhead while improving the reliability of + multicast messages. + +config BATMAN_ADV_DEBUG + bool "B.A.T.M.A.N. debugging" + depends on PACKAGE_kmod-batman-adv + help + This is an option for use by developers; most people should + say N here. This enables compilation of support for + outputting debugging information to the debugfs log or tracing + buffer. The output is controlled via the batadv netdev specific + log_level setting. + +config BATMAN_ADV_TRACING + bool "B.A.T.M.A.N. tracing support" + depends on PACKAGE_kmod-batman-adv + select KERNEL_FTRACE + select KERNEL_ENABLE_DEFAULT_TRACERS + help + This is an option for use by developers; most people should + say N here. Select this option to gather traces like the debug + messages using the generic tracing infrastructure of the kernel. + BATMAN_ADV_DEBUG must also be selected to get trace events for + batadv_dbg. diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile new file mode 100644 index 00000000000000..1e5178877a13c9 --- /dev/null +++ b/net/batman-adv/Makefile @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk + +PKG_NAME:=batman-adv +PKG_VERSION:=2026.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION) +PKG_HASH:=4e17fced2c80945e22609be87534481733ff1b5d17050de4e4f323c171418135 +PKG_EXTMOD_SUBDIRS:=net/batman-adv + +PKG_MAINTAINER:=Simon Wunderlich +PKG_LICENSE:=GPL-2.0-only MIT +PKG_LICENSE_FILES:=LICENSES/preferred/GPL-2.0 LICENSES/preferred/MIT + +PKG_BUILD_PARALLEL:=1 + +STAMP_CONFIGURED_DEPENDS:=$(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h + +PKG_CONFIG_DEPENDS += \ + CONFIG_BATMAN_ADV_BATMAN_V \ + CONFIG_BATMAN_ADV_BLA \ + CONFIG_BATMAN_ADV_DAT \ + CONFIG_BATMAN_ADV_MCAST \ + CONFIG_BATMAN_ADV_DEBUG \ + CONFIG_BATMAN_ADV_TRACING + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/batman-adv + SUBMENU:=Network Support + TITLE:=B.A.T.M.A.N. Adv + URL:=https://www.open-mesh.org/ + DEPENDS:=+BATMAN_ADV_BLA:kmod-lib-crc16 +LINUX_6_12:kmod-lib-crc32c +kmod-cfg80211 +batctl + FILES:=$(PKG_BUILD_DIR)/net/batman-adv/batman-adv.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoProbe,batman-adv) +endef + +define KernelPackage/batman-adv/description + B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is + a routing protocol for multi-hop ad-hoc mesh networks. The + networks may be wired or wireless. See + https://www.open-mesh.org/ for more information and user space + tools. This package builds version $(PKG_VERSION) of the kernel + module. +endef + +define KernelPackage/batman-adv/config + source "$(SOURCE)/Config.in" +endef + +PKG_MAKE_FLAGS:= \ + CONFIG_BATMAN_ADV=m \ + CONFIG_BATMAN_ADV_DEBUG=$(if $(CONFIG_BATMAN_ADV_DEBUG),y,n) \ + CONFIG_BATMAN_ADV_BLA=$(if $(CONFIG_BATMAN_ADV_BLA),y,n) \ + CONFIG_BATMAN_ADV_DAT=$(if $(CONFIG_BATMAN_ADV_DAT),y,n) \ + CONFIG_BATMAN_ADV_MCAST=$(if $(CONFIG_BATMAN_ADV_MCAST),y,n) \ + CONFIG_BATMAN_ADV_BATMAN_V=$(if $(CONFIG_BATMAN_ADV_BATMAN_V),y,n) \ + CONFIG_BATMAN_ADV_TRACING=$(if $(CONFIG_BATMAN_ADV_TRACING),y,n) \ + +NOSTDINC_FLAGS := \ + $(KERNEL_NOSTDINC_FLAGS) \ + -I$(PKG_BUILD_DIR)/include/ \ + -I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211-backport \ + -I$(STAGING_DIR)/usr/include/mac80211/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211 \ + -include backport/autoconf.h \ + -include backport/backport.h \ + -include $(PKG_BUILD_DIR)/compat-hacks.h \ + -DBATADV_SOURCE_VERSION=\\\"$(PKG_VERSION)-openwrt-$(PKG_RELEASE)\\\" + +NOSTDINC_FLAGS += \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(PKG_MAKE_FLAGS)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(PKG_MAKE_FLAGS)))) \ + +define Build/Compile + +$(KERNEL_MAKE) $(PKG_JOBS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/net/batman-adv" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +define KernelPackage/batman-adv/install + $(CP) ./files/. $(1)/ +endef + +$(eval $(call KernelPackage,batman-adv)) diff --git a/net/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif b/net/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif new file mode 100755 index 00000000000000..509374a92c8a29 --- /dev/null +++ b/net/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif @@ -0,0 +1,94 @@ +#!/bin/sh + +# This UCI-Defaults script will split the batadv proto network interfaces +# in batadv_hardif and batadv proto. The configuration options from +# /etc/config/batman-adv will be moved to the latter. + +. /lib/functions.sh + +proto_batadv_to_batadv_hardif() { + local section="$1" + local proto + local mesh + local routing_algo + + config_get proto "${section}" proto + config_get mesh "${section}" mesh + config_get routing_algo "${section}" routing_algo + + if [ -z "$mesh" -o "${proto}" != "batadv" ]; then + return + fi + + uci set network."${section}".proto="batadv_hardif" + uci rename network."${section}".mesh="master" + uci delete network."${section}".routing_algo + + # create new section or adjust existing one + uci set network."${mesh}"=interface + uci set network."${mesh}".proto=batadv + [ -n "${routing_algo}" ] && uci set network."${mesh}".routing_algo="${routing_algo}" +} + +mv_batadv_config_section() { + local section="$1" + local aggregated_ogms + local ap_isolation + local bonding + local bridge_loop_avoidance + local distributed_arp_table + local fragmentation + local gw_bandwidth + local gw_mode + local gw_sel_class + local hop_penalty + local isolation_mark + local log_level + local multicast_mode + local orig_interval + + config_get aggregated_ogms "${section}" aggregated_ogms + config_get ap_isolation "${section}" ap_isolation + config_get bonding "${section}" bonding + config_get bridge_loop_avoidance "${section}" bridge_loop_avoidance + config_get distributed_arp_table "${section}" distributed_arp_table + config_get fragmentation "${section}" fragmentation + config_get gw_bandwidth "${section}" gw_bandwidth + config_get gw_mode "${section}" gw_mode + config_get gw_sel_class "${section}" gw_sel_class + config_get hop_penalty "${section}" hop_penalty + config_get isolation_mark "${section}" isolation_mark + config_get log_level "${section}" log_level + config_get multicast_mode "${section}" multicast_mode + config_get orig_interval "${section}" orig_interval + + # update section in case it exists + [ -n "${aggregated_ogms}" ] && uci set network."${section}".aggregated_ogms="${aggregated_ogms}" + [ -n "${ap_isolation}" ] && uci set network."${section}".ap_isolation="${ap_isolation}" + [ -n "${bonding}" ] && uci set network."${section}".bonding="${bonding}" + [ -n "${bridge_loop_avoidance}" ] && uci set network."${section}".bridge_loop_avoidance="${bridge_loop_avoidance}" + [ -n "${distributed_arp_table}" ] && uci set network."${section}".distributed_arp_table="${distributed_arp_table}" + [ -n "${fragmentation}" ] && uci set network."${section}".fragmentation="${fragmentation}" + [ -n "${gw_bandwidth}" ] && uci set network."${section}".gw_bandwidth="${gw_bandwidth}" + [ -n "${gw_mode}" ] && uci set network."${section}".gw_mode="${gw_mode}" + [ -n "${gw_sel_class}" ] && uci set network."${section}".gw_sel_class="${gw_sel_class}" + [ -n "${hop_penalty}" ] && uci set network."${section}".hop_penalty="${hop_penalty}" + [ -n "${isolation_mark}" ] && uci set network."${section}".isolation_mark="${isolation_mark}" + [ -n "${log_level}" ] && uci set network."${section}".log_level="${log_level}" + [ -n "${multicast_mode}" ] && uci set network."${section}".multicast_mode="${multicast_mode}" + [ -n "${orig_interval}" ] && uci set network."${section}".orig_interval="${orig_interval}" +} + +if [ -f /etc/config/batman-adv ]; then + config_load network + config_foreach proto_batadv_to_batadv_hardif 'interface' + uci commit network + + config_load batman-adv + config_foreach mv_batadv_config_section 'mesh' + uci commit network + + rm -f /etc/config/batman-adv +fi + +exit 0 diff --git a/net/batman-adv/files/lib/netifd/proto/batadv.sh b/net/batman-adv/files/lib/netifd/proto/batadv.sh new file mode 100755 index 00000000000000..4ef490d3d7d838 --- /dev/null +++ b/net/batman-adv/files/lib/netifd/proto/batadv.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_batadv_init_config() { + no_device=1 + available=1 + + proto_config_add_boolean 'aggregated_ogms:bool' + proto_config_add_boolean 'ap_isolation:bool' + proto_config_add_boolean 'bonding:bool' + proto_config_add_boolean 'bridge_loop_avoidance:bool' + proto_config_add_boolean 'distributed_arp_table:bool' + proto_config_add_boolean 'fragmentation:bool' + proto_config_add_string 'gw_bandwidth' + proto_config_add_string 'gw_mode' + proto_config_add_int 'gw_sel_class' + proto_config_add_int 'hop_penalty' + proto_config_add_string 'isolation_mark' + proto_config_add_string 'log_level' + proto_config_add_int 'multicast_fanout' + proto_config_add_boolean 'multicast_mode:bool' + proto_config_add_int 'orig_interval' + proto_config_add_string 'routing_algo' +} + +proto_batadv_setup() { + local config="$1" + local iface="$config" + + local aggregated_ogms + local ap_isolation + local bonding + local bridge_loop_avoidance + local distributed_arp_table + local fragmentation + local gw_bandwidth + local gw_mode + local gw_sel_class + local hop_penalty + local isolation_mark + local log_level + local multicast_fanout + local multicast_mode + local orig_interval + local routing_algo + + json_get_vars aggregated_ogms + json_get_vars ap_isolation + json_get_vars bonding + json_get_vars bridge_loop_avoidance + json_get_vars distributed_arp_table + json_get_vars fragmentation + json_get_vars gw_bandwidth + json_get_vars gw_mode + json_get_vars gw_sel_class + json_get_vars hop_penalty + json_get_vars isolation_mark + json_get_vars log_level + json_get_vars multicast_fanout + json_get_vars multicast_mode + json_get_vars orig_interval + json_get_vars routing_algo + + set_default routing_algo 'BATMAN_IV' + + batctl routing_algo "$routing_algo" + batctl meshif "$iface" interface create + + [ -n "$aggregated_ogms" ] && batctl meshif "$iface" aggregation "$aggregated_ogms" + [ -n "$ap_isolation" ] && batctl meshif "$iface" ap_isolation "$ap_isolation" + [ -n "$bonding" ] && batctl meshif "$iface" bonding "$bonding" + [ -n "$bridge_loop_avoidance" ] && batctl meshif "$iface" bridge_loop_avoidance "$bridge_loop_avoidance" 2>&- + [ -n "$distributed_arp_table" ] && batctl meshif "$iface" distributed_arp_table "$distributed_arp_table" 2>&- + [ -n "$fragmentation" ] && batctl meshif "$iface" fragmentation "$fragmentation" + + case "$gw_mode" in + server) + if [ -n "$gw_bandwidth" ]; then + batctl meshif "$iface" gw_mode "server" "$gw_bandwidth" + else + batctl meshif "$iface" gw_mode "server" + fi + ;; + client) + if [ -n "$gw_sel_class" ]; then + batctl meshif "$iface" gw_mode "client" "$gw_sel_class" + else + batctl meshif "$iface" gw_mode "client" + fi + ;; + *) + batctl meshif "$iface" gw_mode "off" + ;; + esac + + [ -n "$hop_penalty" ] && batctl meshif "$iface" hop_penalty "$hop_penalty" + [ -n "$isolation_mark" ] && batctl meshif "$iface" isolation_mark "$isolation_mark" + [ -n "$multicast_fanout" ] && batctl meshif "$iface" multicast_fanout "$multicast_fanout" + [ -n "$multicast_mode" ] && batctl meshif "$iface" multicast_mode "$multicast_mode" 2>&- + [ -n "$log_level" ] && batctl meshif "$iface" loglevel "$log_level" 2>&- + [ -n "$orig_interval" ] && batctl meshif "$iface" orig_interval "$orig_interval" + + proto_init_update "$iface" 1 + proto_send_update "$config" +} + +proto_batadv_teardown() { + local config="$1" + local iface="$config" + + batctl meshif "$iface" interface destroy +} + +add_protocol batadv diff --git a/net/batman-adv/files/lib/netifd/proto/batadv_hardif.sh b/net/batman-adv/files/lib/netifd/proto/batadv_hardif.sh new file mode 100755 index 00000000000000..b2f87dd6c24eb6 --- /dev/null +++ b/net/batman-adv/files/lib/netifd/proto/batadv_hardif.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_batadv_hardif_init_config() { + proto_config_add_int 'elp_interval' + proto_config_add_int 'hop_penalty' + proto_config_add_string "master" + proto_config_add_string 'throughput_override' +} + +proto_batadv_hardif_setup() { + local config="$1" + local iface="$2" + + local elp_interval + local hop_penalty + local master + local throughput_override + + json_get_vars elp_interval + json_get_vars hop_penalty + json_get_vars master + json_get_vars throughput_override + + ( proto_add_host_dependency "$config" '' "$master" ) + + batctl meshif "$master" interface -M add "$iface" + + [ -n "$elp_interval" ] && batctl hardif "$iface" elp_interval "$elp_interval" + [ -n "$hop_penalty" ] && batctl hardif "$iface" hop_penalty "$hop_penalty" + [ -n "$throughput_override" ] && batctl hardif "$iface" throughput_override "$throughput_override" + + proto_init_update "$iface" 1 + proto_send_update "$config" +} + +proto_batadv_hardif_teardown() { + local config="$1" + local iface="$2" + + local master + + json_get_vars master + + batctl meshif "$master" interface -M del "$iface" || true +} + +add_protocol batadv_hardif diff --git a/net/batman-adv/files/lib/netifd/proto/batadv_vlan.sh b/net/batman-adv/files/lib/netifd/proto/batadv_vlan.sh new file mode 100755 index 00000000000000..4a8bce74398af0 --- /dev/null +++ b/net/batman-adv/files/lib/netifd/proto/batadv_vlan.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_batadv_vlan_init_config() { + proto_config_add_boolean 'ap_isolation:bool' +} + +proto_batadv_vlan_setup() { + local config="$1" + local iface="$2" + + # batadv_vlan options + local ap_isolation + + json_get_vars ap_isolation + + batctl vlan "$iface" ap_isolation "${ap_isolation:-0}" + proto_init_update "$iface" 1 + proto_send_update "$config" +} + +proto_batadv_vlan_teardown() { + local cfg="$1" +} + +add_protocol batadv_vlan diff --git a/net/batman-adv/patches/0001-fix-batadv_is_cfg80211_netdev.patch b/net/batman-adv/patches/0001-fix-batadv_is_cfg80211_netdev.patch new file mode 100644 index 00000000000000..12914d98fa7edc --- /dev/null +++ b/net/batman-adv/patches/0001-fix-batadv_is_cfg80211_netdev.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexandru Gagniuc +Date: Thu, 6 Apr 2023 18:05:50 -0500 +Subject: fix batadv_is_cfg80211_netdev + +Replace CONFIG_CFG80211 with CPTCFG_CFG80211, which is the correct +macro to use when building under backports. + +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -320,8 +320,7 @@ static bool batadv_is_cfg80211_netdev(st + { + if (!net_device) + return false; +- +-#if IS_ENABLED(CONFIG_CFG80211) ++#if IS_ENABLED(CPTCFG_CFG80211) + /* cfg80211 drivers have to set ieee80211_ptr */ + if (net_device->ieee80211_ptr) + return true; diff --git a/net/batman-adv/src/compat-hacks.h b/net/batman-adv/src/compat-hacks.h new file mode 100644 index 00000000000000..43cce807913775 --- /dev/null +++ b/net/batman-adv/src/compat-hacks.h @@ -0,0 +1,143 @@ +/* Please avoid adding hacks here - instead add it to mac80211/backports.git */ + +#undef CONFIG_MODULE_STRIPPED + +#include /* LINUX_VERSION_CODE */ +#include + +#if LINUX_VERSION_IS_LESS(6, 15, 0) +#include +#endif /* LINUX_VERSION_IS_LESS(6, 15, 0) */ + +#if LINUX_VERSION_IS_LESS(6, 16, 0) + +#define timer_container_of(var, callback_timer, timer_fieldname) \ + from_timer(var, callback_timer, timer_fieldname) + +#endif /* LINUX_VERSION_IS_LESS(6, 16, 0) */ + +#if LINUX_VERSION_IS_LESS(6, 16, 0) || !defined(CONFIG_NET_CRC32C) + +#include +#include + +static inline u32 batadv_skb_crc32c(struct sk_buff *skb, int offset, + int len, u32 crc) +{ + unsigned int to = offset + len; + unsigned int consumed = 0; + struct skb_seq_state st; + unsigned int l; + const u8 *data; + + if (len <= 0) + return crc; + + skb_prepare_seq_read(skb, offset, to, &st); + while ((l = skb_seq_read(consumed, &data, &st)) != 0) { + crc = crc32c(crc, data, l); + consumed += l; + } + + return crc; +} + +#define skb_crc32c batadv_skb_crc32c + +#endif /* LINUX_VERSION_IS_LESS(6, 16, 0) || !defined(CONFIG_NET_CRC32C) */ + +#include + +#if LINUX_VERSION_IS_LESS(7, 0, 0) + +#ifndef kzalloc_obj +#define kzalloc_obj(P, GFP) \ + kzalloc(sizeof(P), GFP) +#endif /* kzalloc_obj */ + +#ifndef kmalloc_obj +#define kmalloc_obj(P, GFP) \ + kmalloc(sizeof(P), GFP) +#endif /* kmalloc_obj */ + +#ifndef kmalloc_objs +#define kmalloc_objs(P, COUNT, GFP) \ + kmalloc_array((COUNT), sizeof(P), GFP) +#endif /* kmalloc_objs */ + +#endif /* < KERNEL_VERSION(7, 0, 0) */ + +/* */ + +#include +#include_next + +#include + +#ifdef DECLARE_EWMA +#undef DECLARE_EWMA +#endif /* DECLARE_EWMA */ + +/* + * Exponentially weighted moving average (EWMA) + * + * This implements a fixed-precision EWMA algorithm, with both the + * precision and fall-off coefficient determined at compile-time + * and built into the generated helper funtions. + * + * The first argument to the macro is the name that will be used + * for the struct and helper functions. + * + * The second argument, the precision, expresses how many bits are + * used for the fractional part of the fixed-precision values. + * + * The third argument, the weight reciprocal, determines how the + * new values will be weighed vs. the old state, new values will + * get weight 1/weight_rcp and old values 1-1/weight_rcp. Note + * that this parameter must be a power of two for efficiency. + */ + +#define DECLARE_EWMA(name, _precision, _weight_rcp) \ + struct ewma_##name { \ + unsigned long internal; \ + }; \ + static inline void ewma_##name##_init(struct ewma_##name *e) \ + { \ + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ + /* \ + * Even if you want to feed it just 0/1 you should have \ + * some bits for the non-fractional part... \ + */ \ + BUILD_BUG_ON((_precision) > 30); \ + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ + e->internal = 0; \ + } \ + static inline unsigned long \ + ewma_##name##_read(struct ewma_##name *e) \ + { \ + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ + BUILD_BUG_ON((_precision) > 30); \ + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ + return e->internal >> (_precision); \ + } \ + static inline void ewma_##name##_add(struct ewma_##name *e, \ + unsigned long val) \ + { \ + unsigned long internal = READ_ONCE(e->internal); \ + unsigned long weight_rcp = ilog2(_weight_rcp); \ + unsigned long precision = _precision; \ + \ + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ + BUILD_BUG_ON((_precision) > 30); \ + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ + \ + WRITE_ONCE(e->internal, internal ? \ + (((internal << weight_rcp) - internal) + \ + (val << precision)) >> weight_rcp : \ + (val << precision)); \ + } + +/* */